Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor the query system to reduce the amount of macro-expanded functions #96524

Closed
5 of 6 tasks
cjgillot opened this issue Apr 28, 2022 · 10 comments
Closed
5 of 6 tasks
Labels
A-incr-comp Area: Incremental compilation A-query-system Area: The rustc query system (https://rustc-dev-guide.rust-lang.org/query.html) E-medium Call for participation: Medium difficulty. Experience needed to fix: Intermediate. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@cjgillot
Copy link
Contributor

cjgillot commented Apr 28, 2022

The current implementation of the query system relies on a lot of macro-expanded functions.
This issue tracks perspectives to reduce this use of macros.

The objective of this issue is to have the macros expand to a self-contained description of the query, instead of breadcrumbs in several files.

The interface code in rustc_middle::ty::query can be made responsible for calling it, it already does.

  • Simplify QueryDescription trait

TRY_LOAD_FROM_DISK, cache_on_disk and describe are only used for
the QueryVtable and make_query::$name. They can be made inherent
associated constant and functions on the queries::$name types.

This would allow to replace the function pointer for handle_cycle_error by a simple enum.

The call to opt_remap_env_constness! is unnecessary. The DepKind can be passed as a parameter. describe can be passed as a function pointer. key can be made an impl Key + HashStable.

We should consider moving part of the code into QueryState::try_collect_active_jobs which is the only user of these functions.

DepKindStruct is defined in rustc_middle::dep_graph::dep_node. It depends on TyCtxt and DepKind, but that can be replaced by a generic parameter CTX: DepContext and CTX::DepKind.

rustc_query_system would access it through a new DepContext::dep_kind_info providing fingerprint_style, is_eval_always, try_force_from_dep_node and try_load_from_on_disk_cacke, and replacing TyCtxt::query_kind.

If specialization allows it, we should aim to make most of the code in rustc_middle::dep_graph::dep_node generic over CTX: DepContext, and move it to rustc_query_system.

Having macro-unrolled loops prevents extension of the infrastructure to non-statically known instances. This struct is to be used in a similar way to DepKindStruct, but with types private to rustc_query_impl.

struct QueryStruct {
    try_collect_active_jobs: fn(QueryCtxt<'_>, &mut QueryMap) -> Option<()>,
    alloc_self_profile_query_strings: fn(QueryCtxt<'tcx>, &mut QueryKeyStringCache),
    encode_query_results: Option<fn(QueryCtxt<'_>, &mut CacheEncoder<...>, &mut EncodedDepNodeIndex)>
}

This will be used to:

  • replace the macro expansion in try_collect_active_jobs by a loop over function pointers;
  • replace the macro expansion in alloc_self_profile_query_strings by a loop over function pointers;
  • replace the macro expansion in encode_query_results by a loop over function pointers.

The array itself should be created using make_dep_kind_array! which handles the indices.
Possible variant: put the try_collect_active_jobs and alloc_self_profile_query_strings function pointers in DepKindStruct instead.

Please contact me on Zulip for further information.

@cjgillot cjgillot added E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. A-incr-comp Area: Incremental compilation E-medium Call for participation: Medium difficulty. Experience needed to fix: Intermediate. labels Apr 28, 2022
@kckeiks
Copy link
Contributor

kckeiks commented Apr 28, 2022

@rustbot claim

@kckeiks
Copy link
Contributor

kckeiks commented Jul 20, 2022

Update: I started working on this a while back but I got pulled away by other things. I will have more bandwidth in the next couple of weeks and hopefully have a PR.

TaKO8Ki added a commit to TaKO8Ki/rust that referenced this issue Aug 16, 2022
…tem, r=cjgillot

Remove opt_remap_env_constness from rustc_query_impl

1st task off rust-lang#96524.

r? `@cjgillot`
@jyn514
Copy link
Member

jyn514 commented Aug 24, 2022

@kckeiks what parts of this issue are you currently working on? don't want to step on your toes, but I think there's enough work here we can split it up between us and have plenty of work for both :)

@kckeiks
Copy link
Contributor

kckeiks commented Aug 24, 2022

@jyn514 I had started working on "Simplify QueryDescription trait" and looking into "Refactor make_query::$name functions to a generic version instead of a macro". I was planning on continuing working on these tasks in the next 1-2 weeks when I would have more bandwidth. Please let me know what you plan to pick up.

@jyn514
Copy link
Member

jyn514 commented Aug 24, 2022

Cool :) I've already done the make_query bits I think: #100943
I'll let you know if I start working on anything else, I'll avoid QueryDescription for now.

@jyn514
Copy link
Member

jyn514 commented Aug 29, 2022

I had an idea for how to change the 3 nested macros (rustc_queries -> rustc_query_append -> define_callbacks) but after spending a long time writing it up, I no longer think it's a good idea. Posting it below anyway because maybe it will give others ideas lol

I've realized one of the reasons rustc_queries! is so complicated is because it's a proc macro with multiple outputs; which isn't natively supported by the language, so we hack it by defining multiple macros, one for each output. I wonder if it would be simpler to define a single trait + trait impls instead, which the rest of rustc_query_impl::plumbing can use rather than the macro outputs.

The tradeoff is that we'll have fewer layers of macros, at the cost of moving more code into the proc-macro, which makes it harder to refactor. define_callbacks is the main one that would add complexity to rustc_queries; see below.

Here are the uses of the macros I see today:

  • rustc_query_description! { $name } in impl<'tcx> QueryDescription<QueryCtxt<'tcx>> for queries::$name<'tcx> { (inside define_queries). If the QueryDescription impl is generated by the proc-macro this will no longer be necessary at all.
  • rustc_cached_queries!(encode_queries!) in encode_query_results. I think we can avoid this by having an static ALL_QUERIES: &[&dyn QueryDescription] = [ ... ]; array generated by the macro; we'd loop over the array rather than having the macro generate static calls. That may have a runtime impact due to the new function pointer, but we might make it up in icache. Not sure how hot encode_query_results is.
  • rustc_dep_node_append!(define_dep_nodes![]) in compiler/rustc_middle/src/dep_graph/dep_node.rs. This one seems harder - label_strs is easy to avoid by adding a const NAME: &'static str; item to QueryDescription, but adding custom Null/Red/TraitSelect variants to the enum DepKind seems harder. Maybe those can be defined by the proc-macro, rather than added after the fact?
  • rustc_query_append! { define_queries! } in compiler/rustc_query_impl/src/lib.rs. IMO this already does 99% of what I'd want the proc-macro to do; not many changes needed here
  • rustc_query_append! { alloc_once! } in alloc_self_profile_query_strings. this is not perf sensitive and only uses the macro name; the ALL_QUERIES list would work here too.
  • rustc_query_append! { define_callbacks! } in compiler/rustc_middle/src/ty/query.rs. This would have to be directly defined by the proc-macro, I think; not sure how much is simplified there :/ This is quite a large macro too (200+ lines) so it's adding a great deal of complexity to the proc-macro.

@jyn514
Copy link
Member

jyn514 commented Sep 2, 2022

The tradeoff is that we'll have fewer layers of macros, at the cost of moving more code into the proc-macro, which makes it harder to refactor. define_callbacks is the main one that would add complexity to rustc_queries; see below.

oh heh, this is what @eddyb suggested 4 years ago #56462 (comment)

bors added a commit to rust-lang-ci/rust that referenced this issue Sep 2, 2022
Simplify the `define_query` macro

This moves a bunch of control flow out of the macro into generic functions, leaving the macro just to call the function with a new generic parameter for each query.

It may be possible to improve compile-times / icache by instantiating the generic functions only with the query key, not the query type itself, but I'm going to leave that for a follow-up PR.

Helps with rust-lang#96524.

r? `@cjgillot`
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this issue Sep 7, 2022
…r=cjgillot

Make `HandleCycleError` an enum instead of a macro-generated closure

Helps with rust-lang#96524. Based on rust-lang#100943 to avoid merge conflicts, so it looks larger than it is (only the last commit is relevant).

cc https://rust-lang.zulipchat.com/#narrow/stream/241847-t-compiler.2Fwg-incr-comp/topic/Moving.20.60Value.60.20to.20rustc_query_system.20.2396524

r? `@cjgillot`
bors added a commit to rust-lang-ci/rust that referenced this issue Sep 8, 2022
…cjgillot

Make `HandleCycleError` an enum instead of a macro-generated closure

Helps with rust-lang#96524. Based on rust-lang#100943 to avoid merge conflicts, so it looks larger than it is (only the last commit is relevant).

cc https://rust-lang.zulipchat.com/#narrow/stream/241847-t-compiler.2Fwg-incr-comp/topic/Moving.20.60Value.60.20to.20rustc_query_system.20.2396524

r? `@cjgillot`
@jyn514
Copy link
Member

jyn514 commented Sep 12, 2022

Possible variant: put the try_collect_active_jobs and alloc_self_profile_query_strings function pointers in DepKindStruct instead.

I think this won't be possible after #101710, because DepKindStruct will be defined in rustc_query_system which doesn't have access to QueryCtxt. I guess it could use type parameters though.

@jyn514 jyn514 added the A-query-system Area: The rustc query system (https://rustc-dev-guide.rust-lang.org/query.html) label Sep 14, 2022
bors added a commit to rust-lang-ci/rust that referenced this issue Sep 26, 2022
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`
bors added a commit to rust-lang-ci/rust that referenced this issue Oct 15, 2022
Get rid of `rustc_query_description!`

**I am not entirely sure whether this is an improvement and would like to get your feedback on it.**

Helps with rust-lang#96524.

Queries can provide an arbitrary expression for their description and their caching behavior. Before, these expressions where stored in a `rustc_query_description` macro emitted by the `rustc_queries` macro, and then used in `rustc_query_impl` to fill out the methods for the `QueryDescription` trait.

Instead, we now emit two new modules from `rustc_queries` containing the functions with the expressions. `rustc_query_impl` calls these functions now instead of invoking the macro.

Since we are now defining some of the functions in `rustc_middle::query`, we now need all the imports for the key types mthere as well.

r? `@cjgillot`
@Noratrieb
Copy link
Member

Releasing assignment due to inactivity, feel free to claim it again. @rustbot release-assignment

@kckeiks
Copy link
Contributor

kckeiks commented Jan 19, 2023

Yeah sorry, I got busy with work :(. If no one picks it up in the summer, I should have some time to try to tackle it then.

@Noratrieb Noratrieb added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Apr 5, 2023
@cjgillot cjgillot closed this as completed Apr 8, 2023
RalfJung pushed a commit to RalfJung/rust-analyzer that referenced this issue Apr 20, 2024
Make `HandleCycleError` an enum instead of a macro-generated closure

Helps with rust-lang/rust#96524. Based on rust-lang/rust#100943 to avoid merge conflicts, so it looks larger than it is (only the last commit is relevant).

cc https://rust-lang.zulipchat.com/#narrow/stream/241847-t-compiler.2Fwg-incr-comp/topic/Moving.20.60Value.60.20to.20rustc_query_system.20.2396524

r? `@cjgillot`
RalfJung pushed a commit to RalfJung/rust-analyzer that referenced this issue Apr 27, 2024
Make `HandleCycleError` an enum instead of a macro-generated closure

Helps with rust-lang/rust#96524. Based on rust-lang/rust#100943 to avoid merge conflicts, so it looks larger than it is (only the last commit is relevant).

cc https://rust-lang.zulipchat.com/#narrow/stream/241847-t-compiler.2Fwg-incr-comp/topic/Moving.20.60Value.60.20to.20rustc_query_system.20.2396524

r? `@cjgillot`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-incr-comp Area: Incremental compilation A-query-system Area: The rustc query system (https://rustc-dev-guide.rust-lang.org/query.html) E-medium Call for participation: Medium difficulty. Experience needed to fix: Intermediate. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants