-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Don't alloca for unused locals #129283
Don't alloca for unused locals #129283
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -218,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); | ||
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 = { | ||
|
@@ -277,17 +278,20 @@ 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); | ||
let mut unreached_blocks = BitSet::new_filled(mir.basic_blocks.len()); | ||
// Codegen the body of each reachable block using our reverse postorder list. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, neat. I like being able to re-use the same order here. |
||
for bb in traversal_order { | ||
fx.codegen_block(bb); | ||
unreached_blocks.remove(bb); | ||
} | ||
|
||
// Codegen the body of each block using reverse postorder | ||
for (bb, _) in traversal::reverse_postorder(mir) { | ||
if reachable_blocks.contains(bb) { | ||
fx.codegen_block(bb); | ||
} else { | ||
// We want to skip this block, because it's not reachable. But we still create | ||
// the block so terminators in other blocks can reference it. | ||
fx.codegen_block_as_unreachable(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. | ||
Comment on lines
+288
to
+291
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, not this PR, but I wonder if we can avoid re-doing that by making the SwitchInt lowering use the list of blocks we are going to reach, and then instead of looking at the actual input to the switch we could just look at whether there are multiple possible targets or not. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could do that, but I think MonoReachable is a dead-end approach, at least in terms of getting PRs through review: #129287 (comment). If we start storing it in FunctionCx, I think we'll then be forced to tack on yet another hack to get further codegen improvements for the cases that MonoReachable doesn't handle, or structurally cannot fix. For example, the SwitchInt lowering leaves behind a lot of goto chains (you know, a thing we have a MIR optimization for). I'd much prefer to work on either doing post-mono MIR optimizations. The other alternative is a new post-mono IR. |
||
// 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); | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
//@ compile-flags: -Cno-prepopulate-passes -Copt-level=0 -Cpanic=abort | ||
// Check that there's an alloca for the reference and the vector, but nothing else. | ||
// We use panic=abort because unwinding panics give hint::black_box a cleanup block, which has | ||
// another alloca. | ||
|
||
#![crate_type = "lib"] | ||
|
||
#[inline(never)] | ||
fn test<const SIZE: usize>() { | ||
// CHECK-LABEL: no_alloca_inside_if_false::test | ||
// CHECK: start: | ||
// CHECK-NEXT: alloca [{{12|24}} x i8] | ||
// CHECK-NOT: alloca | ||
if const { SIZE < 4096 } { | ||
let arr = [0u8; SIZE]; | ||
std::hint::black_box(&arr); | ||
} else { | ||
let vec = vec![0u8; SIZE]; | ||
std::hint::black_box(&vec); | ||
} | ||
} | ||
|
||
// CHECK-LABEL: @main | ||
#[no_mangle] | ||
pub fn main() { | ||
test::<8192>(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which traversal order is this? Or do we want to leave it unspecified?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The traversal order requirements are spelled out in a comment in this function:
So we can't traverse in just any order and indeed we don't. What do you think I should call this argument instead?