From df15f022efef80de1004867aa352a425b276be77 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 12 Sep 2026 17:38:34 +1000 Subject: [PATCH] Disconnect `rustc_codegen_ssa` from `rustc_mir_transform` The direct dependency from `rustc_codegen_ssa` to `rustc_mir_transform` allowed codegen to reuse some MIR-transform code for identifying unnecessary landing pads. However, we can achieve the same result by calling through a hook on `TyCtxt`, eliminating the crate dependency. --- Cargo.lock | 1 - compiler/rustc_codegen_ssa/Cargo.toml | 1 - compiler/rustc_codegen_ssa/src/mir/mod.rs | 9 +--- compiler/rustc_middle/src/hooks.rs | 20 +++++++- compiler/rustc_mir_transform/src/lib.rs | 4 +- .../src/remove_noop_landing_pads.rs | 49 ++++++++++--------- 6 files changed, 49 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 030aaba3d42b8..6c55c01ebed9c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3855,7 +3855,6 @@ dependencies = [ "rustc_macros", "rustc_metadata", "rustc_middle", - "rustc_mir_transform", "rustc_serialize", "rustc_session", "rustc_span", diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 55305815b05f0..188bd29cc6042 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -29,7 +29,6 @@ rustc_lint_defs = { path = "../rustc_lint_defs" } rustc_macros = { path = "../rustc_macros" } rustc_metadata = { path = "../rustc_metadata" } rustc_middle = { path = "../rustc_middle" } -rustc_mir_transform = { path = "../rustc_mir_transform" } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 6e87a295e9d2b..1b08ab1d0bfab 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -217,14 +217,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty()); debug!("fn_abi: {:?}", fn_abi); - let nop_landing_pads = rustc_mir_transform::remove_noop_landing_pads::find_noop_landing_pads( - mir, - Some(rustc_mir_transform::remove_noop_landing_pads::ExtraInfo { - tcx, - instance, - typing_env: cx.typing_env(), - }), - ); + let nop_landing_pads = tcx.find_noop_landing_pads_for_instance(mir, instance, cx.typing_env()); if tcx.features().ergonomic_clones() { let monomorphized_mir = instance.instantiate_mir_and_normalize_erasing_regions( diff --git a/compiler/rustc_middle/src/hooks.rs b/compiler/rustc_middle/src/hooks.rs index df95bd6149e47..9eb45ac9d5412 100644 --- a/compiler/rustc_middle/src/hooks.rs +++ b/compiler/rustc_middle/src/hooks.rs @@ -4,16 +4,24 @@ //! compilation, whereas hooks are just plain function pointers without any of the query magic. use rustc_hir::def_id::{DefId, DefPathHash}; +use rustc_index::bit_set::DenseBitSet; use rustc_session::StableCrateId; use rustc_span::def_id::{CrateNum, LocalDefId}; use rustc_span::{ExpnHash, ExpnId}; use crate::mir; use crate::query::on_disk_cache::CacheEncoder; -use crate::ty::{Ty, TyCtxt}; +use crate::ty::{self, Ty, TyCtxt}; macro_rules! declare_hooks { - ($($(#[$attr:meta])*hook $name:ident($($arg:ident: $K:ty),*) -> $V:ty;)*) => { + ( + $( + $(#[$attr:meta])* + hook $name:ident( + $( $arg:ident: $K:ty ),* $(,)? + ) -> $V:ty; + )* + ) => { impl<'tcx> TyCtxt<'tcx> { $( @@ -107,6 +115,14 @@ declare_hooks! { /// Serializes all eligible query return values into the on-disk cache. hook encode_query_values(encoder: &mut CacheEncoder<'tcx>) -> (); + + /// Identifies landing pads that don't do anything, allowing some post-monomorphization + /// simplifications during codegen. + hook find_noop_landing_pads_for_instance( + body: &mir::Body<'tcx>, + instance: ty::Instance<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + ) -> DenseBitSet; } #[cold] diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index d9d9e334c2acc..68a9cfa53f984 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -169,7 +169,7 @@ declare_passes! { mod prettify : ReorderBasicBlocks, ReorderLocals; mod promote_consts : PromoteTemps; mod ref_prop : ReferencePropagation; - pub mod remove_noop_landing_pads : RemoveNoopLandingPads; + mod remove_noop_landing_pads : RemoveNoopLandingPads; mod remove_place_mention : RemovePlaceMention; mod remove_storage_markers : RemoveStorageMarkers; mod remove_uninit_drops : RemoveUninitDrops; @@ -215,6 +215,8 @@ pub fn provide(providers: &mut Providers) { ffi_unwind_calls::provide(&mut providers.queries); shim::provide(&mut providers.queries); cross_crate_inline::provide(&mut providers.queries); + providers.hooks.find_noop_landing_pads_for_instance = + remove_noop_landing_pads::find_noop_landing_pads_for_instance; providers.queries = query::Providers { mir_keys, mir_built, diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index c25404ed7ab99..c340d82d0a80b 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -18,8 +18,8 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads { PassPolicy::optional(ctx.panic_strategy().unwinds()) } - #[instrument(level = "debug", skip(self, _tcx, body))] - fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + #[instrument(level = "debug", skip(self, tcx, body))] + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let def_id = body.source.def_id(); debug!(?def_id); @@ -33,7 +33,7 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads { return; } - let nop_landing_pads = find_noop_landing_pads(body, None); + let nop_landing_pads = find_noop_landing_pads(tcx, body, None); if nop_landing_pads.is_empty() { debug!("no nop landing pads in MIR"); @@ -74,10 +74,12 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads { impl RemoveNoopLandingPads { fn is_nop_landing_pad<'tcx>( &self, + tcx: TyCtxt<'tcx>, bbdata: &BasicBlockData<'tcx>, body: &Body<'tcx>, nop_landing_pads: &DenseBitSet, - extra: Option<&ExtraInfo<'tcx>>, + // Extra post-monomorphization info that allows more cases to be identified. + extra: Option<(Instance<'tcx>, ty::TypingEnv<'tcx>)>, ) -> bool { for stmt in &bbdata.statements { match &stmt.kind { @@ -120,15 +122,15 @@ impl RemoveNoopLandingPads { terminator.successors().all(|succ| nop_landing_pads.contains(succ)) } TerminatorKind::Drop { place, .. } => { - if let Some(extra) = extra { - let ty = place.ty(body, extra.tcx).ty; - debug!("monomorphize: instance={:?}", extra.instance); - let ty = extra.instance.instantiate_mir_and_normalize_erasing_regions( - extra.tcx, - extra.typing_env, - ty::EarlyBinder::bind(extra.tcx, ty), + if let Some((instance, typing_env)) = extra { + let ty = place.ty(body, tcx).ty; + debug!("monomorphize: instance={instance:?}"); + let ty = instance.instantiate_mir_and_normalize_erasing_regions( + tcx, + typing_env, + ty::EarlyBinder::bind(tcx, ty), ); - let drop_fn = Instance::resolve_drop_glue(extra.tcx, ty); + let drop_fn = Instance::resolve_drop_glue(tcx, ty); if let ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_, None)) = drop_fn.def { // no need to drop anything, if all of our successors are also no-op then we // can be skipped. @@ -151,18 +153,20 @@ impl RemoveNoopLandingPads { } } -/// This provides extra information that allows further analysis. -/// -/// Used by rustc_codegen_ssa. -pub struct ExtraInfo<'tcx> { - pub tcx: TyCtxt<'tcx>, - pub instance: Instance<'tcx>, - pub typing_env: ty::TypingEnv<'tcx>, +/// Hook impl for [`TyCtxt::find_noop_landing_pads_for_instance`]. +pub(crate) fn find_noop_landing_pads_for_instance<'tcx>( + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, + instance: Instance<'tcx>, + typing_env: ty::TypingEnv<'tcx>, +) -> DenseBitSet { + find_noop_landing_pads(tcx, body, Some((instance, typing_env))) } -pub fn find_noop_landing_pads<'tcx>( +fn find_noop_landing_pads<'tcx>( + tcx: TyCtxt<'tcx>, body: &Body<'tcx>, - extra: Option>, + extra: Option<(Instance<'tcx>, ty::TypingEnv<'tcx>)>, ) -> DenseBitSet { let mut nop_landing_pads = DenseBitSet::new_empty(body.basic_blocks.len()); @@ -171,10 +175,11 @@ pub fn find_noop_landing_pads<'tcx>( let postorder: Vec<_> = traversal::postorder(body).map(|(bb, _)| bb).collect(); for bb in postorder { let is_nop_landing_pad = RemoveNoopLandingPads.is_nop_landing_pad( + tcx, &body.basic_blocks[bb], body, &nop_landing_pads, - extra.as_ref(), + extra, ); if is_nop_landing_pad { nop_landing_pads.insert(bb);