diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index f1d885bf1bce8..e947fcb883c9a 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -299,7 +299,8 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { .generic_activity("codegen prelude") .run(|| crate::abi::codegen_fn_prelude(fx, start_block)); - let reachable_blocks = traversal::mono_reachable_as_bitset(fx.mir, fx.tcx, fx.instance); + let (reachable_blocks, _reachable_locals) = + traversal::mono_reachable_as_bitset(fx.mir, fx.tcx, fx.instance); for (bb, bb_data) in fx.mir.basic_blocks.iter_enumerated() { let block = fx.get_block(bb); diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index de94d87bcea7a..6836e1557c3f3 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -192,6 +192,9 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( }) .collect(); + let (reachable_blocks, reachable_locals) = + traversal::mono_reachable_as_bitset(mir, cx.tcx(), instance); + let mut fx = FunctionCx { instance, mir, @@ -218,7 +221,8 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut start_bx); - let memory_locals = analyze::non_ssa_locals(&fx); + let mut memory_locals = analyze::non_ssa_locals(&fx); + memory_locals.intersect(&reachable_locals); // Allocate variable and temp allocas let local_values = { @@ -277,8 +281,6 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // So drop the builder of `start_llbb` to avoid having two at the same time. drop(start_bx); - let reachable_blocks = traversal::mono_reachable_as_bitset(mir, cx.tcx(), instance); - // Codegen the body of each block using reverse postorder for (bb, _) in traversal::reverse_postorder(mir) { if reachable_blocks.contains(bb) { diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index 245e9096bad47..7c71bb771cfaf 100644 --- a/compiler/rustc_middle/src/mir/traversal.rs +++ b/compiler/rustc_middle/src/mir/traversal.rs @@ -303,10 +303,10 @@ pub fn mono_reachable_as_bitset<'a, 'tcx>( body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, -) -> BitSet { +) -> (BitSet, BitSet) { let mut iter = mono_reachable(body, tcx, instance); while let Some(_) = iter.next() {} - iter.visited + (iter.visited, iter.locals) } pub struct MonoReachable<'a, 'tcx> { @@ -318,6 +318,23 @@ pub struct MonoReachable<'a, 'tcx> { // store ours in a BitSet and thus save allocations because BitSet has a small size // optimization. worklist: BitSet, + locals: BitSet, +} + +struct UsedLocals<'a> { + locals: &'a mut BitSet, +} + +use crate::mir::visit::Visitor; +impl<'a, 'tcx> Visitor<'tcx> for UsedLocals<'a> { + fn visit_local( + &mut self, + local: Local, + _ctx: crate::mir::visit::PlaceContext, + _location: Location, + ) { + self.locals.insert(local); + } } impl<'a, 'tcx> MonoReachable<'a, 'tcx> { @@ -334,6 +351,7 @@ impl<'a, 'tcx> MonoReachable<'a, 'tcx> { instance, visited: BitSet::new_empty(body.basic_blocks.len()), worklist, + locals: BitSet::new_empty(body.local_decls.len()), } } @@ -357,6 +375,7 @@ impl<'a, 'tcx> Iterator for MonoReachable<'a, 'tcx> { } let data = &self.body[idx]; + UsedLocals { locals: &mut self.locals }.visit_basic_block_data(idx, data); if let Some((bits, targets)) = Body::try_const_mono_switchint(self.tcx, self.instance, data)