1
Fork 0

Compute reachable locals as part of non_ssa_locals

This commit is contained in:
Ben Kimock 2024-08-24 21:03:38 -04:00
parent 0ea5dc506f
commit 523f8f8398
6 changed files with 79 additions and 112 deletions

View file

@ -16,26 +16,16 @@ use crate::traits::*;
pub(crate) fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
fx: &FunctionCx<'a, 'tcx, Bx>,
traversal_order: &[mir::BasicBlock],
reachable_locals: &BitSet<mir::Local>,
) -> BitSet<mir::Local> {
let mir = fx.mir;
let dominators = mir.basic_blocks.dominators();
let locals = mir
.local_decls
.iter_enumerated()
.map(|(local, decl)| {
if !reachable_locals.contains(local) {
return LocalKind::Unused;
}
.iter()
.map(|decl| {
let ty = fx.monomorphize(decl.ty);
let layout = fx.cx.spanned_layout_of(ty, decl.source_info.span);
if layout.is_zst() {
LocalKind::ZST
} else if fx.cx.is_backend_immediate(layout) || fx.cx.is_backend_scalar_pair(layout) {
LocalKind::Unused
} else {
LocalKind::Memory
}
if layout.is_zst() { LocalKind::ZST } else { LocalKind::Unused }
})
.collect();
@ -83,11 +73,22 @@ struct LocalAnalyzer<'a, 'b, 'tcx, Bx: BuilderMethods<'b, 'tcx>> {
impl<'a, 'b, 'tcx, Bx: BuilderMethods<'b, 'tcx>> LocalAnalyzer<'a, 'b, 'tcx, Bx> {
fn define(&mut self, local: mir::Local, location: DefLocation) {
let fx = self.fx;
let kind = &mut self.locals[local];
let decl = &fx.mir.local_decls[local];
match *kind {
LocalKind::ZST => {}
LocalKind::Memory => {}
LocalKind::Unused => *kind = LocalKind::SSA(location),
LocalKind::Unused => {
let ty = fx.monomorphize(decl.ty);
let layout = fx.cx.spanned_layout_of(ty, decl.source_info.span);
*kind =
if fx.cx.is_backend_immediate(layout) || fx.cx.is_backend_scalar_pair(layout) {
LocalKind::SSA(location)
} else {
LocalKind::Memory
};
}
LocalKind::SSA(_) => *kind = LocalKind::Memory,
}
}

View file

@ -192,9 +192,6 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
})
.collect();
let (traversal_order, reachable_locals) =
traversal::mono_reachable_reverse_postorder(mir, cx.tcx(), instance);
let mut fx = FunctionCx {
instance,
mir,
@ -221,7 +218,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, &traversal_order, &reachable_locals);
let traversal_order = traversal::mono_reachable_reverse_postorder(mir, cx.tcx(), instance);
let memory_locals = analyze::non_ssa_locals(&fx, &traversal_order);
// Allocate variable and temp allocas
let local_values = {
@ -286,6 +284,12 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
fx.codegen_block(bb);
unreached_blocks.remove(bb);
}
// FIXME: These empty unreachable blocks are *mostly* a waste. They are occasionally
// targets for a SwitchInt terminator, but the reimplementation of the mono-reachable
// simplification in SwitchInt lowering sometimes misses cases that
// mono_reachable_reverse_postorder manages to figure out.
// The solution is to do something like post-mono GVN. But for now we have this hack.
for bb in unreached_blocks.iter() {
fx.codegen_block_as_unreachable(bb);
}