Skip to content

Commit 0d080cf

Browse files
authored
Unrolled build for #155680
Rollup merge of #155680 - Amanieu:call-arg-move-index, r=cjgillot Handle index projections in call destinations in DSE Since call destinations are evaluated after call arguments, we can't turn copy arguments into moves if the same local is later used as an index projection in the call destination. DSE call arg optimization: #113758 r? @cjgillot cc @RalfJung
2 parents 0a4ee3f + b15544d commit 0d080cf

4 files changed

Lines changed: 63 additions & 1 deletion

File tree

compiler/rustc_mir_transform/src/dead_store_elimination.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,21 @@ fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
4747
let mut patch = Vec::new();
4848

4949
for (bb, bb_data) in traversal::preorder(body) {
50-
if let TerminatorKind::Call { ref args, .. } = bb_data.terminator().kind {
50+
if let TerminatorKind::Call { ref args, ref destination, .. } = bb_data.terminator().kind {
5151
let loc = Location { block: bb, statement_index: bb_data.statements.len() };
5252

5353
// Position ourselves between the evaluation of `args` and the write to `destination`.
5454
live.seek_to_block_end(bb);
5555
let mut state = live.get().clone();
5656

57+
// Don't turn into a move if the local is used as an index
58+
// projection for the destination place.
59+
LivenessTransferFunction(&mut state).visit_place(
60+
destination,
61+
visit::PlaceContext::MutatingUse(visit::MutatingUseContext::Call),
62+
loc,
63+
);
64+
5765
for (index, arg) in args.iter().map(|a| &a.node).enumerate().rev() {
5866
if let Operand::Copy(place) = *arg
5967
&& !place.is_indirect()
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
- // MIR for `move_index` before DeadStoreElimination-final
2+
+ // MIR for `move_index` after DeadStoreElimination-final
3+
4+
fn move_index(_1: [usize; 10], _2: usize) -> () {
5+
let mut _0: ();
6+
7+
bb0: {
8+
_1[_2] = passthrough_usize(copy _2) -> [return: bb1, unwind unreachable];
9+
}
10+
11+
bb1: {
12+
return;
13+
}
14+
}
15+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
- // MIR for `move_index` before DeadStoreElimination-final
2+
+ // MIR for `move_index` after DeadStoreElimination-final
3+
4+
fn move_index(_1: [usize; 10], _2: usize) -> () {
5+
let mut _0: ();
6+
7+
bb0: {
8+
_1[_2] = passthrough_usize(copy _2) -> [return: bb1, unwind continue];
9+
}
10+
11+
bb1: {
12+
return;
13+
}
14+
}
15+

tests/mir-opt/dead-store-elimination/call_arg_copy.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,31 @@ fn move_packed(packed: Packed) {
4040
}
4141
}
4242

43+
#[inline(never)]
44+
fn passthrough_usize(a: usize) -> usize {
45+
a
46+
}
47+
48+
// EMIT_MIR call_arg_copy.move_index.DeadStoreElimination-final.diff
49+
#[custom_mir(dialect = "analysis")]
50+
fn move_index(a: [usize; 10], b: usize) {
51+
// CHECK-LABEL: fn move_index(
52+
// CHECK: = passthrough_usize(copy _2)
53+
mir! {
54+
{
55+
// The index is used again after the operand is evaluated to
56+
// evaluate the destionation place, so the argument cannot be turned
57+
// into a move.
58+
Call(a[b] = passthrough_usize(b), ReturnTo(ret), UnwindContinue())
59+
}
60+
ret = {
61+
Return()
62+
}
63+
}
64+
}
65+
4366
fn main() {
4467
move_simple(1);
4568
move_packed(Packed { x: 0, y: 1 });
69+
move_index([0; _], 1);
4670
}

0 commit comments

Comments
 (0)