Skip to content

Commit 3288d3a

Browse files
committed
Auto merge of #101785 - jyn514:query-struct-fn-ptrs, r=cjgillot
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 #96524. Based on #101173; only the last commit is relevant. r? `@cjgillot`
2 parents ff40f2e + 7a83690 commit 3288d3a

File tree

3 files changed

+95
-56
lines changed

3 files changed

+95
-56
lines changed

compiler/rustc_query_impl/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! Support for serializing the dep-graph and reloading it.
22
33
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
4+
// this shouldn't be necessary, but the check for `&mut _` is too naive and denies returning a function pointer that takes a mut ref
5+
#![feature(const_mut_refs)]
46
#![feature(min_specialization)]
57
#![feature(never_type)]
68
#![feature(once_cell)]

compiler/rustc_query_impl/src/plumbing.rs

+86-38
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
//! manage the caches, and so forth.
44
55
use crate::keys::Key;
6-
use crate::on_disk_cache::CacheDecoder;
6+
use crate::on_disk_cache::{CacheDecoder, CacheEncoder, EncodedDepNodeIndex};
7+
use crate::profiling_support::QueryKeyStringCache;
78
use crate::{on_disk_cache, Queries};
89
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
910
use rustc_data_structures::sync::{AtomicU64, Lock};
@@ -173,34 +174,14 @@ impl<'tcx> QueryCtxt<'tcx> {
173174

174175
pub(super) fn encode_query_results(
175176
self,
176-
encoder: &mut on_disk_cache::CacheEncoder<'_, 'tcx>,
177-
query_result_index: &mut on_disk_cache::EncodedDepNodeIndex,
177+
encoder: &mut CacheEncoder<'_, 'tcx>,
178+
query_result_index: &mut EncodedDepNodeIndex,
178179
) {
179-
macro_rules! expand_if_cached {
180-
([] $encode:expr) => {};
181-
([(cache) $($rest:tt)*] $encode:expr) => {
182-
$encode
183-
};
184-
([$other:tt $($modifiers:tt)*] $encode:expr) => {
185-
expand_if_cached!([$($modifiers)*] $encode)
186-
};
187-
}
188-
189-
macro_rules! encode_queries {
190-
(
191-
$($(#[$attr:meta])*
192-
[$($modifiers:tt)*] fn $query:ident($($K:tt)*) -> $V:ty,)*) => {
193-
$(
194-
expand_if_cached!([$($modifiers)*] on_disk_cache::encode_query_results::<_, super::queries::$query<'_>>(
195-
self,
196-
encoder,
197-
query_result_index
198-
));
199-
)*
180+
for query in &self.queries.query_structs {
181+
if let Some(encode) = query.encode_query_results {
182+
encode(self, encoder, query_result_index);
200183
}
201184
}
202-
203-
rustc_query_append!(encode_queries!);
204185
}
205186

206187
pub fn try_print_query_stack(
@@ -213,6 +194,14 @@ impl<'tcx> QueryCtxt<'tcx> {
213194
}
214195
}
215196

197+
#[derive(Clone, Copy)]
198+
pub(crate) struct QueryStruct<'tcx> {
199+
pub try_collect_active_jobs: fn(QueryCtxt<'tcx>, &mut QueryMap) -> Option<()>,
200+
pub alloc_self_profile_query_strings: fn(TyCtxt<'tcx>, &mut QueryKeyStringCache),
201+
pub encode_query_results:
202+
Option<fn(QueryCtxt<'tcx>, &mut CacheEncoder<'_, 'tcx>, &mut EncodedDepNodeIndex)>,
203+
}
204+
216205
macro_rules! handle_cycle_error {
217206
([]) => {{
218207
rustc_query_system::HandleCycleError::Error
@@ -438,6 +427,18 @@ where
438427
}
439428
}
440429

430+
macro_rules! expand_if_cached {
431+
([], $tokens:expr) => {{
432+
None
433+
}};
434+
([(cache) $($rest:tt)*], $tokens:expr) => {{
435+
Some($tokens)
436+
}};
437+
([$other:tt $($modifiers:tt)*], $tokens:expr) => {
438+
expand_if_cached!([$($modifiers)*], $tokens)
439+
};
440+
}
441+
441442
// NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros
442443
// invoked by `rustc_query_append`.
443444
macro_rules! define_queries {
@@ -571,6 +572,59 @@ macro_rules! define_queries {
571572
})*
572573
}
573574

575+
mod query_structs {
576+
use rustc_middle::ty::TyCtxt;
577+
use $crate::plumbing::{QueryStruct, QueryCtxt};
578+
use $crate::profiling_support::QueryKeyStringCache;
579+
use rustc_query_system::query::{QueryDescription, QueryMap};
580+
581+
pub(super) const fn dummy_query_struct<'tcx>() -> QueryStruct<'tcx> {
582+
fn noop_try_collect_active_jobs(_: QueryCtxt<'_>, _: &mut QueryMap) -> Option<()> {
583+
None
584+
}
585+
fn noop_alloc_self_profile_query_strings(_: TyCtxt<'_>, _: &mut QueryKeyStringCache) {}
586+
587+
QueryStruct {
588+
try_collect_active_jobs: noop_try_collect_active_jobs,
589+
alloc_self_profile_query_strings: noop_alloc_self_profile_query_strings,
590+
encode_query_results: None,
591+
}
592+
}
593+
594+
pub(super) use dummy_query_struct as Null;
595+
pub(super) use dummy_query_struct as Red;
596+
pub(super) use dummy_query_struct as TraitSelect;
597+
pub(super) use dummy_query_struct as CompileCodegenUnit;
598+
pub(super) use dummy_query_struct as CompileMonoItem;
599+
600+
$(
601+
pub(super) const fn $name<'tcx>() -> QueryStruct<'tcx> { QueryStruct {
602+
try_collect_active_jobs: |tcx, qmap| {
603+
let make_query = |tcx, key| {
604+
let kind = rustc_middle::dep_graph::DepKind::$name;
605+
let name = stringify!($name);
606+
$crate::plumbing::create_query_frame(tcx, super::queries::$name::describe, key, kind, name)
607+
};
608+
tcx.queries.$name.try_collect_active_jobs(
609+
tcx,
610+
make_query,
611+
qmap,
612+
)
613+
},
614+
alloc_self_profile_query_strings: |tcx, string_cache| {
615+
$crate::profiling_support::alloc_self_profile_query_strings_for_query_cache(
616+
tcx,
617+
stringify!($name),
618+
&tcx.query_caches.$name,
619+
string_cache,
620+
)
621+
},
622+
encode_query_results: expand_if_cached!([$($modifiers)*], |tcx, encoder, query_result_index|
623+
$crate::on_disk_cache::encode_query_results::<_, super::queries::$name<'_>>(tcx, encoder, query_result_index)
624+
),
625+
}})*
626+
}
627+
574628
pub fn query_callbacks<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindStruct<'tcx>] {
575629
arena.alloc_from_iter(make_dep_kind_array!(query_callbacks))
576630
}
@@ -585,9 +639,11 @@ impl<'tcx> Queries<'tcx> {
585639
extern_providers: ExternProviders,
586640
on_disk_cache: Option<OnDiskCache<'tcx>>,
587641
) -> Self {
642+
use crate::query_structs;
588643
Queries {
589644
local_providers: Box::new(local_providers),
590645
extern_providers: Box::new(extern_providers),
646+
query_structs: make_dep_kind_array!(query_structs).to_vec(),
591647
on_disk_cache,
592648
jobs: AtomicU64::new(1),
593649
..Queries::default()
@@ -602,6 +658,7 @@ macro_rules! define_queries_struct {
602658
pub struct Queries<'tcx> {
603659
local_providers: Box<Providers>,
604660
extern_providers: Box<ExternProviders>,
661+
query_structs: Vec<$crate::plumbing::QueryStruct<'tcx>>,
605662

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

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

621-
$(
622-
let make_query = |tcx, key| {
623-
let kind = dep_graph::DepKind::$name;
624-
let name = stringify!($name);
625-
$crate::plumbing::create_query_frame(tcx, queries::$name::describe, key, kind, name)
626-
};
627-
self.$name.try_collect_active_jobs(
628-
tcx,
629-
make_query,
630-
&mut jobs,
631-
)?;
632-
)*
678+
for query in &self.query_structs {
679+
(query.try_collect_active_jobs)(tcx, &mut jobs);
680+
}
633681

634682
Some(jobs)
635683
}

compiler/rustc_query_impl/src/profiling_support.rs

+7-18
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::QueryCtxt;
12
use measureme::{StringComponent, StringId};
23
use rustc_data_structures::fx::FxHashMap;
34
use rustc_data_structures::profiling::SelfProfiler;
@@ -8,7 +9,7 @@ use rustc_query_system::query::QueryCache;
89
use std::fmt::Debug;
910
use std::io::Write;
1011

11-
struct QueryKeyStringCache {
12+
pub(crate) struct QueryKeyStringCache {
1213
def_id_cache: FxHashMap<DefId, StringId>,
1314
}
1415

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

306307
let mut string_cache = QueryKeyStringCache::new();
308+
let queries = QueryCtxt::from_tcx(tcx);
307309

308-
macro_rules! alloc_once {
309-
(
310-
$($(#[$attr:meta])*
311-
[$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
312-
$(
313-
alloc_self_profile_query_strings_for_query_cache(
314-
tcx,
315-
stringify!($name),
316-
&tcx.query_caches.$name,
317-
&mut string_cache,
318-
);
319-
)+
320-
}
310+
for query in &queries.queries.query_structs {
311+
(query.alloc_self_profile_query_strings)(tcx, &mut string_cache);
321312
}
322-
323-
rustc_query_append! { alloc_once! }
324313
}

0 commit comments

Comments
 (0)