Skip to content

Commit 7faeae0

Browse files
committed
Auto merge of #72135 - oli-obk:const_prop_deaggregates, r=wesleywiser
Propagate locals, even if they have unpropagatable assignments somewhere Second try for #71946 (comment) r? @wesleywiser cc @rust-lang/wg-mir-opt @RalfJung
2 parents e7f230d + 27c818b commit 7faeae0

File tree

5 files changed

+189
-1
lines changed

5 files changed

+189
-1
lines changed

src/librustc_mir/transform/const_prop.rs

+24-1
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,10 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
781781
// Projections are fine, because `&mut foo.x` will be caught by
782782
// `MutatingUseContext::Borrow` elsewhere.
783783
MutatingUse(MutatingUseContext::Projection)
784+
// These are just stores, where the storing is not propagatable, but there may be later
785+
// mutations of the same local via `Store`
786+
| MutatingUse(MutatingUseContext::Call)
787+
// Actual store that can possibly even propagate a value
784788
| MutatingUse(MutatingUseContext::Store) => {
785789
if !self.found_assignment.insert(local) {
786790
match &mut self.can_const_prop[local] {
@@ -805,7 +809,21 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
805809
| NonMutatingUse(NonMutatingUseContext::Inspect)
806810
| NonMutatingUse(NonMutatingUseContext::Projection)
807811
| NonUse(_) => {}
808-
_ => {
812+
813+
// These could be propagated with a smarter analysis or just some careful thinking about
814+
// whether they'd be fine right now.
815+
MutatingUse(MutatingUseContext::AsmOutput)
816+
| MutatingUse(MutatingUseContext::Yield)
817+
| MutatingUse(MutatingUseContext::Drop)
818+
| MutatingUse(MutatingUseContext::Retag)
819+
// These can't ever be propagated under any scheme, as we can't reason about indirect
820+
// mutation.
821+
| NonMutatingUse(NonMutatingUseContext::SharedBorrow)
822+
| NonMutatingUse(NonMutatingUseContext::ShallowBorrow)
823+
| NonMutatingUse(NonMutatingUseContext::UniqueBorrow)
824+
| NonMutatingUse(NonMutatingUseContext::AddressOf)
825+
| MutatingUse(MutatingUseContext::Borrow)
826+
| MutatingUse(MutatingUseContext::AddressOf) => {
809827
trace!("local {:?} can't be propagaged because it's used: {:?}", local, context);
810828
self.can_const_prop[local] = ConstPropMode::NoPropagation;
811829
}
@@ -881,6 +899,11 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
881899
// ```
882900
// FIXME: we overzealously erase the entire local, because that's easier to
883901
// implement.
902+
trace!(
903+
"propagation into {:?} failed.
904+
Nuking the entire site from orbit, it's the only way to be sure",
905+
place,
906+
);
884907
Self::remove_const(&mut self.ecx, place.local);
885908
}
886909
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// compile-flags: -O
2+
3+
// EMIT_MIR rustc.main.ConstProp.diff
4+
fn main() {
5+
let mut x: (i32, i32) = foo();
6+
x.1 = 99;
7+
x.0 = 42;
8+
let y = x.1;
9+
}
10+
11+
#[inline(never)]
12+
fn foo() -> (i32, i32) {
13+
unimplemented!()
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
- // MIR for `main` before ConstProp
2+
+ // MIR for `main` after ConstProp
3+
4+
fn main() -> () {
5+
let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:4:11: 4:11
6+
let mut _1: (i32, i32) as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:5:9: 5:14
7+
scope 1 {
8+
debug x => _1; // in scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:5:9: 5:14
9+
let _2: i32; // in scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:8:9: 8:10
10+
scope 2 {
11+
debug y => _2; // in scope 2 at $DIR/mutable_variable_aggregate_partial_read.rs:8:9: 8:10
12+
}
13+
}
14+
15+
bb0: {
16+
StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:5:9: 5:14
17+
_1 = const foo() -> bb1; // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:5:29: 5:34
18+
// ty::Const
19+
// + ty: fn() -> (i32, i32) {foo}
20+
// + val: Value(Scalar(<ZST>))
21+
// mir::Constant
22+
// + span: $DIR/mutable_variable_aggregate_partial_read.rs:5:29: 5:32
23+
// + literal: Const { ty: fn() -> (i32, i32) {foo}, val: Value(Scalar(<ZST>)) }
24+
}
25+
26+
bb1: {
27+
(_1.1: i32) = const 99i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:6:5: 6:13
28+
// ty::Const
29+
// + ty: i32
30+
// + val: Value(Scalar(0x00000063))
31+
// mir::Constant
32+
// + span: $DIR/mutable_variable_aggregate_partial_read.rs:6:11: 6:13
33+
// + literal: Const { ty: i32, val: Value(Scalar(0x00000063)) }
34+
(_1.0: i32) = const 42i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:7:5: 7:13
35+
// ty::Const
36+
// + ty: i32
37+
// + val: Value(Scalar(0x0000002a))
38+
// mir::Constant
39+
// + span: $DIR/mutable_variable_aggregate_partial_read.rs:7:11: 7:13
40+
// + literal: Const { ty: i32, val: Value(Scalar(0x0000002a)) }
41+
StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:8:9: 8:10
42+
- _2 = (_1.1: i32); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:8:13: 8:16
43+
+ _2 = const 99i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:8:13: 8:16
44+
+ // ty::Const
45+
+ // + ty: i32
46+
+ // + val: Value(Scalar(0x00000063))
47+
+ // mir::Constant
48+
+ // + span: $DIR/mutable_variable_aggregate_partial_read.rs:8:13: 8:16
49+
+ // + literal: Const { ty: i32, val: Value(Scalar(0x00000063)) }
50+
_0 = const (); // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:4:11: 9:2
51+
// ty::Const
52+
// + ty: ()
53+
// + val: Value(Scalar(<ZST>))
54+
// mir::Constant
55+
// + span: $DIR/mutable_variable_aggregate_partial_read.rs:4:11: 9:2
56+
// + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
57+
StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:9:1: 9:2
58+
StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:9:1: 9:2
59+
return; // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:9:2: 9:2
60+
}
61+
}
62+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// compile-flags: -O
2+
3+
// EMIT_MIR rustc.main.ConstProp.diff
4+
fn main() {
5+
let a = foo();
6+
let mut x: (i32, i32) = (1, 2);
7+
x.1 = a;
8+
let y = x.1;
9+
let z = x.0; // this could theoretically be allowed, but we can't handle it right now
10+
}
11+
12+
#[inline(never)]
13+
fn foo() -> i32 {
14+
unimplemented!()
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
- // MIR for `main` before ConstProp
2+
+ // MIR for `main` after ConstProp
3+
4+
fn main() -> () {
5+
let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_unprop_assign.rs:4:11: 4:11
6+
let _1: i32; // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:5:9: 5:10
7+
let mut _3: i32; // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:7:11: 7:12
8+
scope 1 {
9+
debug a => _1; // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:5:9: 5:10
10+
let mut _2: (i32, i32) as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:6:9: 6:14
11+
scope 2 {
12+
debug x => _2; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:6:9: 6:14
13+
let _4: i32; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:8:9: 8:10
14+
scope 3 {
15+
debug y => _4; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:8:9: 8:10
16+
let _5: i32; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:9:9: 9:10
17+
scope 4 {
18+
debug z => _5; // in scope 4 at $DIR/mutable_variable_unprop_assign.rs:9:9: 9:10
19+
}
20+
}
21+
}
22+
}
23+
24+
bb0: {
25+
StorageLive(_1); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:5:9: 5:10
26+
_1 = const foo() -> bb1; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:5:13: 5:18
27+
// ty::Const
28+
// + ty: fn() -> i32 {foo}
29+
// + val: Value(Scalar(<ZST>))
30+
// mir::Constant
31+
// + span: $DIR/mutable_variable_unprop_assign.rs:5:13: 5:16
32+
// + literal: Const { ty: fn() -> i32 {foo}, val: Value(Scalar(<ZST>)) }
33+
}
34+
35+
bb1: {
36+
StorageLive(_2); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:6:9: 6:14
37+
_2 = (const 1i32, const 2i32); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:6:29: 6:35
38+
// ty::Const
39+
// + ty: i32
40+
// + val: Value(Scalar(0x00000001))
41+
// mir::Constant
42+
- // + span: $DIR/mutable_variable_unprop_assign.rs:6:30: 6:31
43+
+ // + span: $DIR/mutable_variable_unprop_assign.rs:6:29: 6:35
44+
// + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) }
45+
// ty::Const
46+
// + ty: i32
47+
// + val: Value(Scalar(0x00000002))
48+
// mir::Constant
49+
- // + span: $DIR/mutable_variable_unprop_assign.rs:6:33: 6:34
50+
+ // + span: $DIR/mutable_variable_unprop_assign.rs:6:29: 6:35
51+
// + literal: Const { ty: i32, val: Value(Scalar(0x00000002)) }
52+
StorageLive(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:7:11: 7:12
53+
_3 = _1; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:7:11: 7:12
54+
(_2.1: i32) = move _3; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:7:5: 7:12
55+
StorageDead(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:7:11: 7:12
56+
StorageLive(_4); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:8:9: 8:10
57+
_4 = (_2.1: i32); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:8:13: 8:16
58+
StorageLive(_5); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:9:9: 9:10
59+
_5 = (_2.0: i32); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:9:13: 9:16
60+
_0 = const (); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:4:11: 10:2
61+
// ty::Const
62+
// + ty: ()
63+
// + val: Value(Scalar(<ZST>))
64+
// mir::Constant
65+
// + span: $DIR/mutable_variable_unprop_assign.rs:4:11: 10:2
66+
// + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
67+
StorageDead(_5); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:10:1: 10:2
68+
StorageDead(_4); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:10:1: 10:2
69+
StorageDead(_2); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:10:1: 10:2
70+
StorageDead(_1); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:10:1: 10:2
71+
return; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:10:2: 10:2
72+
}
73+
}
74+

0 commit comments

Comments
 (0)