Skip to content

Commit ae538ba

Browse files
authored
Unrolled build for #145030
Rollup merge of #145030 - cjgillot:gvn-no-flatten-index, r=saethlin GVN: Do not flatten derefs with ProjectionElem::Index. r? `@saethlin` This should fix the bug you found with #131650
2 parents 67d45f4 + ebd60b9 commit ae538ba

File tree

4 files changed

+153
-2
lines changed

4 files changed

+153
-2
lines changed

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -756,7 +756,13 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
756756
&& let Some(v) = self.simplify_place_value(&mut pointee, location)
757757
{
758758
value = v;
759-
place_ref = pointee.project_deeper(&place.projection[index..], self.tcx).as_ref();
759+
// `pointee` holds a `Place`, so `ProjectionElem::Index` holds a `Local`.
760+
// That local is SSA, but we otherwise have no guarantee on that local's value at
761+
// the current location compared to its value where `pointee` was borrowed.
762+
if pointee.projection.iter().all(|elem| !matches!(elem, ProjectionElem::Index(_))) {
763+
place_ref =
764+
pointee.project_deeper(&place.projection[index..], self.tcx).as_ref();
765+
}
760766
}
761767
if let Some(local) = self.try_as_local(value, location) {
762768
// Both `local` and `Place { local: place.local, projection: projection[..index] }`
@@ -774,7 +780,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
774780
&& let Some(v) = self.simplify_place_value(&mut pointee, location)
775781
{
776782
value = v;
777-
place_ref = pointee.project_deeper(&[], self.tcx).as_ref();
783+
// `pointee` holds a `Place`, so `ProjectionElem::Index` holds a `Local`.
784+
// That local is SSA, but we otherwise have no guarantee on that local's value at
785+
// the current location compared to its value where `pointee` was borrowed.
786+
if pointee.projection.iter().all(|elem| !matches!(elem, ProjectionElem::Index(_))) {
787+
place_ref = pointee.project_deeper(&[], self.tcx).as_ref();
788+
}
778789
}
779790
if let Some(new_local) = self.try_as_local(value, location) {
780791
place_ref = PlaceRef { local: new_local, projection: &[] };
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
- // MIR for `dereference_indexing` before GVN
2+
+ // MIR for `dereference_indexing` after GVN
3+
4+
fn dereference_indexing(_1: [u8; 2], _2: usize) -> () {
5+
debug array => _1;
6+
debug index => _2;
7+
let mut _0: ();
8+
let _3: &u8;
9+
let _4: usize;
10+
let mut _5: usize;
11+
let _6: usize;
12+
let mut _7: bool;
13+
let _8: ();
14+
let mut _9: u8;
15+
scope 1 {
16+
debug a => _3;
17+
}
18+
scope 2 {
19+
debug i => _4;
20+
}
21+
22+
bb0: {
23+
StorageLive(_3);
24+
- StorageLive(_4);
25+
+ nop;
26+
StorageLive(_5);
27+
_5 = copy _2;
28+
- _4 = Add(move _5, const 1_usize);
29+
+ _4 = Add(copy _2, const 1_usize);
30+
StorageDead(_5);
31+
StorageLive(_6);
32+
_6 = copy _4;
33+
- _7 = Lt(copy _6, const 2_usize);
34+
- assert(move _7, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _6) -> [success: bb1, unwind unreachable];
35+
+ _7 = Lt(copy _4, const 2_usize);
36+
+ assert(move _7, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _4) -> [success: bb1, unwind unreachable];
37+
}
38+
39+
bb1: {
40+
- _3 = &_1[_6];
41+
- StorageDead(_4);
42+
+ _3 = &_1[_4];
43+
+ nop;
44+
StorageLive(_8);
45+
StorageLive(_9);
46+
_9 = copy (*_3);
47+
_8 = opaque::<u8>(move _9) -> [return: bb2, unwind unreachable];
48+
}
49+
50+
bb2: {
51+
StorageDead(_9);
52+
StorageDead(_8);
53+
_0 = const ();
54+
StorageDead(_6);
55+
StorageDead(_3);
56+
return;
57+
}
58+
}
59+
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
- // MIR for `dereference_indexing` before GVN
2+
+ // MIR for `dereference_indexing` after GVN
3+
4+
fn dereference_indexing(_1: [u8; 2], _2: usize) -> () {
5+
debug array => _1;
6+
debug index => _2;
7+
let mut _0: ();
8+
let _3: &u8;
9+
let _4: usize;
10+
let mut _5: usize;
11+
let _6: usize;
12+
let mut _7: bool;
13+
let _8: ();
14+
let mut _9: u8;
15+
scope 1 {
16+
debug a => _3;
17+
}
18+
scope 2 {
19+
debug i => _4;
20+
}
21+
22+
bb0: {
23+
StorageLive(_3);
24+
- StorageLive(_4);
25+
+ nop;
26+
StorageLive(_5);
27+
_5 = copy _2;
28+
- _4 = Add(move _5, const 1_usize);
29+
+ _4 = Add(copy _2, const 1_usize);
30+
StorageDead(_5);
31+
StorageLive(_6);
32+
_6 = copy _4;
33+
- _7 = Lt(copy _6, const 2_usize);
34+
- assert(move _7, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _6) -> [success: bb1, unwind continue];
35+
+ _7 = Lt(copy _4, const 2_usize);
36+
+ assert(move _7, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _4) -> [success: bb1, unwind continue];
37+
}
38+
39+
bb1: {
40+
- _3 = &_1[_6];
41+
- StorageDead(_4);
42+
+ _3 = &_1[_4];
43+
+ nop;
44+
StorageLive(_8);
45+
StorageLive(_9);
46+
_9 = copy (*_3);
47+
_8 = opaque::<u8>(move _9) -> [return: bb2, unwind continue];
48+
}
49+
50+
bb2: {
51+
StorageDead(_9);
52+
StorageDead(_8);
53+
_0 = const ();
54+
StorageDead(_6);
55+
StorageDead(_3);
56+
return;
57+
}
58+
}
59+

tests/mir-opt/gvn.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,26 @@ fn remove_casts_must_change_both_sides(mut_a: &*mut u8, mut_b: *mut u8) -> bool
10521052
}
10531053
}
10541054

1055+
/// Verify that we do not references to non-existing locals when dereferencing projections.
1056+
fn dereference_indexing(array: [u8; 2], index: usize) {
1057+
// CHECK-LABEL: fn dereference_indexing(
1058+
// CHECK: debug a => [[a:_.*]];
1059+
// CHECK: debug i => [[i:_.*]];
1060+
1061+
let a = {
1062+
// CHECK: [[i]] = Add(copy _2, const 1_usize);
1063+
let i = index + 1;
1064+
// CHECK: [[a]] = &_1[[[i]]];
1065+
&array[i]
1066+
};
1067+
1068+
// CHECK-NOT: [{{.*}}]
1069+
// CHECK: [[tmp:_.*]] = copy (*[[a]]);
1070+
// CHECK: opaque::<u8>(move [[tmp]])
1071+
opaque(*a);
1072+
}
1073+
1074+
// CHECK-LABEL: fn main(
10551075
fn main() {
10561076
subexpression_elimination(2, 4, 5);
10571077
wrap_unwrap(5);
@@ -1079,6 +1099,7 @@ fn main() {
10791099
slice_const_length(&[1]);
10801100
meta_of_ref_to_slice(&42);
10811101
slice_from_raw_parts_as_ptr(&123, 456);
1102+
dereference_indexing([129, 14], 5);
10821103
}
10831104

10841105
#[inline(never)]
@@ -1138,3 +1159,4 @@ enum Never {}
11381159
// EMIT_MIR gvn.cast_pointer_then_transmute.GVN.diff
11391160
// EMIT_MIR gvn.transmute_then_cast_pointer.GVN.diff
11401161
// EMIT_MIR gvn.remove_casts_must_change_both_sides.GVN.diff
1162+
// EMIT_MIR gvn.dereference_indexing.GVN.diff

0 commit comments

Comments
 (0)