Skip to content

Commit

Permalink
Auto merge of rust-lang#101785 - jyn514:query-struct-fn-ptrs, r=cjgillot
Browse files Browse the repository at this point in the history
Use function pointers instead of macro-unrolled loops in rustc_query_impl

By making these standalone functions, we
a) allow making them extensible in the future with a new `QueryStruct`
b) greatly decrease the amount of code in each individual function, avoiding exponential blowup in llvm

Helps with rust-lang#96524. Based on rust-lang#101173; only the last commit is relevant.

r? `@cjgillot`
  • Loading branch information
bors committed Sep 26, 2022
2 parents ff40f2e + 7a83690 commit 3288d3a
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 56 deletions.
2 changes: 2 additions & 0 deletions compiler/rustc_query_impl/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Support for serializing the dep-graph and reloading it.

#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
// this shouldn't be necessary, but the check for `&mut _` is too naive and denies returning a function pointer that takes a mut ref
#![feature(const_mut_refs)]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(once_cell)]
Expand Down
124 changes: 86 additions & 38 deletions compiler/rustc_query_impl/src/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
//! manage the caches, and so forth.

use crate::keys::Key;
use crate::on_disk_cache::CacheDecoder;
use crate::on_disk_cache::{CacheDecoder, CacheEncoder, EncodedDepNodeIndex};
use crate::profiling_support::QueryKeyStringCache;
use crate::{on_disk_cache, Queries};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::{AtomicU64, Lock};
Expand Down Expand Up @@ -173,34 +174,14 @@ impl<'tcx> QueryCtxt<'tcx> {

pub(super) fn encode_query_results(
self,
encoder: &mut on_disk_cache::CacheEncoder<'_, 'tcx>,
query_result_index: &mut on_disk_cache::EncodedDepNodeIndex,
encoder: &mut CacheEncoder<'_, 'tcx>,
query_result_index: &mut EncodedDepNodeIndex,
) {
macro_rules! expand_if_cached {
([] $encode:expr) => {};
([(cache) $($rest:tt)*] $encode:expr) => {
$encode
};
([$other:tt $($modifiers:tt)*] $encode:expr) => {
expand_if_cached!([$($modifiers)*] $encode)
};
}

macro_rules! encode_queries {
(
$($(#[$attr:meta])*
[$($modifiers:tt)*] fn $query:ident($($K:tt)*) -> $V:ty,)*) => {
$(
expand_if_cached!([$($modifiers)*] on_disk_cache::encode_query_results::<_, super::queries::$query<'_>>(
self,
encoder,
query_result_index
));
)*
for query in &self.queries.query_structs {
if let Some(encode) = query.encode_query_results {
encode(self, encoder, query_result_index);
}
}

rustc_query_append!(encode_queries!);
}

pub fn try_print_query_stack(
Expand All @@ -213,6 +194,14 @@ impl<'tcx> QueryCtxt<'tcx> {
}
}

#[derive(Clone, Copy)]
pub(crate) struct QueryStruct<'tcx> {
pub try_collect_active_jobs: fn(QueryCtxt<'tcx>, &mut QueryMap) -> Option<()>,
pub alloc_self_profile_query_strings: fn(TyCtxt<'tcx>, &mut QueryKeyStringCache),
pub encode_query_results:
Option<fn(QueryCtxt<'tcx>, &mut CacheEncoder<'_, 'tcx>, &mut EncodedDepNodeIndex)>,
}

macro_rules! handle_cycle_error {
([]) => {{
rustc_query_system::HandleCycleError::Error
Expand Down Expand Up @@ -438,6 +427,18 @@ where
}
}

macro_rules! expand_if_cached {
([], $tokens:expr) => {{
None
}};
([(cache) $($rest:tt)*], $tokens:expr) => {{
Some($tokens)
}};
([$other:tt $($modifiers:tt)*], $tokens:expr) => {
expand_if_cached!([$($modifiers)*], $tokens)
};
}

// NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros
// invoked by `rustc_query_append`.
macro_rules! define_queries {
Expand Down Expand Up @@ -571,6 +572,59 @@ macro_rules! define_queries {
})*
}

mod query_structs {
use rustc_middle::ty::TyCtxt;
use $crate::plumbing::{QueryStruct, QueryCtxt};
use $crate::profiling_support::QueryKeyStringCache;
use rustc_query_system::query::{QueryDescription, QueryMap};

pub(super) const fn dummy_query_struct<'tcx>() -> QueryStruct<'tcx> {
fn noop_try_collect_active_jobs(_: QueryCtxt<'_>, _: &mut QueryMap) -> Option<()> {
None
}
fn noop_alloc_self_profile_query_strings(_: TyCtxt<'_>, _: &mut QueryKeyStringCache) {}

QueryStruct {
try_collect_active_jobs: noop_try_collect_active_jobs,
alloc_self_profile_query_strings: noop_alloc_self_profile_query_strings,
encode_query_results: None,
}
}

pub(super) use dummy_query_struct as Null;
pub(super) use dummy_query_struct as Red;
pub(super) use dummy_query_struct as TraitSelect;
pub(super) use dummy_query_struct as CompileCodegenUnit;
pub(super) use dummy_query_struct as CompileMonoItem;

$(
pub(super) const fn $name<'tcx>() -> QueryStruct<'tcx> { QueryStruct {
try_collect_active_jobs: |tcx, qmap| {
let make_query = |tcx, key| {
let kind = rustc_middle::dep_graph::DepKind::$name;
let name = stringify!($name);
$crate::plumbing::create_query_frame(tcx, super::queries::$name::describe, key, kind, name)
};
tcx.queries.$name.try_collect_active_jobs(
tcx,
make_query,
qmap,
)
},
alloc_self_profile_query_strings: |tcx, string_cache| {
$crate::profiling_support::alloc_self_profile_query_strings_for_query_cache(
tcx,
stringify!($name),
&tcx.query_caches.$name,
string_cache,
)
},
encode_query_results: expand_if_cached!([$($modifiers)*], |tcx, encoder, query_result_index|
$crate::on_disk_cache::encode_query_results::<_, super::queries::$name<'_>>(tcx, encoder, query_result_index)
),
}})*
}

pub fn query_callbacks<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindStruct<'tcx>] {
arena.alloc_from_iter(make_dep_kind_array!(query_callbacks))
}
Expand All @@ -585,9 +639,11 @@ impl<'tcx> Queries<'tcx> {
extern_providers: ExternProviders,
on_disk_cache: Option<OnDiskCache<'tcx>>,
) -> Self {
use crate::query_structs;
Queries {
local_providers: Box::new(local_providers),
extern_providers: Box::new(extern_providers),
query_structs: make_dep_kind_array!(query_structs).to_vec(),
on_disk_cache,
jobs: AtomicU64::new(1),
..Queries::default()
Expand All @@ -602,6 +658,7 @@ macro_rules! define_queries_struct {
pub struct Queries<'tcx> {
local_providers: Box<Providers>,
extern_providers: Box<ExternProviders>,
query_structs: Vec<$crate::plumbing::QueryStruct<'tcx>>,

pub on_disk_cache: Option<OnDiskCache<'tcx>>,

Expand All @@ -618,18 +675,9 @@ macro_rules! define_queries_struct {
let tcx = QueryCtxt { tcx, queries: self };
let mut jobs = QueryMap::default();

$(
let make_query = |tcx, key| {
let kind = dep_graph::DepKind::$name;
let name = stringify!($name);
$crate::plumbing::create_query_frame(tcx, queries::$name::describe, key, kind, name)
};
self.$name.try_collect_active_jobs(
tcx,
make_query,
&mut jobs,
)?;
)*
for query in &self.query_structs {
(query.try_collect_active_jobs)(tcx, &mut jobs);
}

Some(jobs)
}
Expand Down
25 changes: 7 additions & 18 deletions compiler/rustc_query_impl/src/profiling_support.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::QueryCtxt;
use measureme::{StringComponent, StringId};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::profiling::SelfProfiler;
Expand All @@ -8,7 +9,7 @@ use rustc_query_system::query::QueryCache;
use std::fmt::Debug;
use std::io::Write;

struct QueryKeyStringCache {
pub(crate) struct QueryKeyStringCache {
def_id_cache: FxHashMap<DefId, StringId>,
}

Expand Down Expand Up @@ -226,7 +227,7 @@ where
/// Allocate the self-profiling query strings for a single query cache. This
/// method is called from `alloc_self_profile_query_strings` which knows all
/// the queries via macro magic.
fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
pub(crate) fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
tcx: TyCtxt<'tcx>,
query_name: &'static str,
query_cache: &C,
Expand Down Expand Up @@ -298,27 +299,15 @@ fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
/// If we are recording only summary data, the ids will point to
/// just the query names. If we are recording query keys too, we
/// allocate the corresponding strings here.
pub fn alloc_self_profile_query_strings(tcx: TyCtxt<'_>) {
pub fn alloc_self_profile_query_strings<'tcx>(tcx: TyCtxt<'tcx>) {
if !tcx.prof.enabled() {
return;
}

let mut string_cache = QueryKeyStringCache::new();
let queries = QueryCtxt::from_tcx(tcx);

macro_rules! alloc_once {
(
$($(#[$attr:meta])*
[$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
$(
alloc_self_profile_query_strings_for_query_cache(
tcx,
stringify!($name),
&tcx.query_caches.$name,
&mut string_cache,
);
)+
}
for query in &queries.queries.query_structs {
(query.alloc_self_profile_query_strings)(tcx, &mut string_cache);
}

rustc_query_append! { alloc_once! }
}

0 comments on commit 3288d3a

Please sign in to comment.