Skip to content

Commit c5a0b2c

Browse files
Auto merge of #147844 - dianqk:gvn-deref-ssa, r=<try>
GVN: Bail out if the address cannot be dereferenced.
2 parents c8a31b7 + 5b2be88 commit c5a0b2c

12 files changed

+145
-33
lines changed

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,12 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
795795
// The base is a pointer's deref, so we introduce the implicit deref.
796796
AddressBase::Deref(reborrow) => {
797797
let place_ty = PlaceTy::from_ty(self.ty(reborrow));
798-
self.project(place_ty, reborrow, ProjectionElem::Deref)?
798+
self.project(place_ty, reborrow, ProjectionElem::Deref).unwrap_or_else(|| {
799+
// Insert a deref instead if `reborrow` cannot be dereferenced.
800+
let projection_ty =
801+
place_ty.projection_ty::<VnIndex>(self.tcx, ProjectionElem::Deref);
802+
return (projection_ty, self.insert_deref(projection_ty.ty, reborrow));
803+
})
799804
}
800805
};
801806
for &proj in projection {
@@ -817,9 +822,9 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
817822
if let Some(Mutability::Not) = place_ty.ty.ref_mutability()
818823
&& projection_ty.ty.is_freeze(self.tcx, self.typing_env())
819824
{
820-
if let Value::Address { base, projection, .. } = self.get(value)
821-
&& let Some(value) = self.dereference_address(base, projection)
822-
{
825+
if let Value::Address { base, projection, .. } = self.get(value) {
826+
// Bail out if the address cannot be dereferenced.
827+
let value = self.dereference_address(base, projection)?;
823828
return Some((projection_ty, value));
824829
}
825830

tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@
108108
_18 = &(*_1);
109109
StorageLive(_19);
110110
StorageLive(_20);
111-
_20 = copy (*_18);
111+
- _20 = copy (*_18);
112+
+ _20 = copy (*_1);
112113
_19 = opaque::<u32>(move _20) -> [return: bb7, unwind unreachable];
113114
}
114115

@@ -117,7 +118,8 @@
117118
StorageDead(_19);
118119
StorageLive(_21);
119120
StorageLive(_22);
120-
_22 = copy (*_18);
121+
- _22 = copy (*_18);
122+
+ _22 = copy (*_1);
121123
_21 = opaque::<u32>(move _22) -> [return: bb8, unwind unreachable];
122124
}
123125

tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@
108108
_18 = &(*_1);
109109
StorageLive(_19);
110110
StorageLive(_20);
111-
_20 = copy (*_18);
111+
- _20 = copy (*_18);
112+
+ _20 = copy (*_1);
112113
_19 = opaque::<u32>(move _20) -> [return: bb7, unwind continue];
113114
}
114115

@@ -117,7 +118,8 @@
117118
StorageDead(_19);
118119
StorageLive(_21);
119120
StorageLive(_22);
120-
_22 = copy (*_18);
121+
- _22 = copy (*_18);
122+
+ _22 = copy (*_1);
121123
_21 = opaque::<u32>(move _22) -> [return: bb8, unwind continue];
122124
}
123125

tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@
88
let mut _3: fn(u8) -> u8;
99
let _5: ();
1010
let mut _6: fn(u8) -> u8;
11-
let mut _9: {closure@$DIR/gvn.rs:617:19: 617:21};
11+
let mut _9: {closure@$DIR/gvn.rs:616:19: 616:21};
1212
let _10: ();
1313
let mut _11: fn();
14-
let mut _13: {closure@$DIR/gvn.rs:617:19: 617:21};
14+
let mut _13: {closure@$DIR/gvn.rs:616:19: 616:21};
1515
let _14: ();
1616
let mut _15: fn();
1717
scope 1 {
1818
debug f => _1;
1919
let _4: fn(u8) -> u8;
2020
scope 2 {
2121
debug g => _4;
22-
let _7: {closure@$DIR/gvn.rs:617:19: 617:21};
22+
let _7: {closure@$DIR/gvn.rs:616:19: 616:21};
2323
scope 3 {
2424
debug closure => _7;
2525
let _8: fn();
@@ -62,16 +62,16 @@
6262
StorageDead(_6);
6363
StorageDead(_5);
6464
- StorageLive(_7);
65-
- _7 = {closure@$DIR/gvn.rs:617:19: 617:21};
65+
- _7 = {closure@$DIR/gvn.rs:616:19: 616:21};
6666
- StorageLive(_8);
6767
+ nop;
68-
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21};
68+
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:616:19: 616:21};
6969
+ nop;
7070
StorageLive(_9);
7171
- _9 = copy _7;
7272
- _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
73-
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21};
74-
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
73+
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:616:19: 616:21};
74+
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:616:19: 616:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
7575
StorageDead(_9);
7676
StorageLive(_10);
7777
StorageLive(_11);
@@ -88,8 +88,8 @@
8888
StorageLive(_13);
8989
- _13 = copy _7;
9090
- _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
91-
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21};
92-
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
91+
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:616:19: 616:21};
92+
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:616:19: 616:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
9393
StorageDead(_13);
9494
StorageLive(_14);
9595
StorageLive(_15);

tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@
88
let mut _3: fn(u8) -> u8;
99
let _5: ();
1010
let mut _6: fn(u8) -> u8;
11-
let mut _9: {closure@$DIR/gvn.rs:617:19: 617:21};
11+
let mut _9: {closure@$DIR/gvn.rs:616:19: 616:21};
1212
let _10: ();
1313
let mut _11: fn();
14-
let mut _13: {closure@$DIR/gvn.rs:617:19: 617:21};
14+
let mut _13: {closure@$DIR/gvn.rs:616:19: 616:21};
1515
let _14: ();
1616
let mut _15: fn();
1717
scope 1 {
1818
debug f => _1;
1919
let _4: fn(u8) -> u8;
2020
scope 2 {
2121
debug g => _4;
22-
let _7: {closure@$DIR/gvn.rs:617:19: 617:21};
22+
let _7: {closure@$DIR/gvn.rs:616:19: 616:21};
2323
scope 3 {
2424
debug closure => _7;
2525
let _8: fn();
@@ -62,16 +62,16 @@
6262
StorageDead(_6);
6363
StorageDead(_5);
6464
- StorageLive(_7);
65-
- _7 = {closure@$DIR/gvn.rs:617:19: 617:21};
65+
- _7 = {closure@$DIR/gvn.rs:616:19: 616:21};
6666
- StorageLive(_8);
6767
+ nop;
68-
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21};
68+
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:616:19: 616:21};
6969
+ nop;
7070
StorageLive(_9);
7171
- _9 = copy _7;
7272
- _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
73-
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21};
74-
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
73+
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:616:19: 616:21};
74+
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:616:19: 616:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
7575
StorageDead(_9);
7676
StorageLive(_10);
7777
StorageLive(_11);
@@ -88,8 +88,8 @@
8888
StorageLive(_13);
8989
- _13 = copy _7;
9090
- _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
91-
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21};
92-
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
91+
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:616:19: 616:21};
92+
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:616:19: 616:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
9393
StorageDead(_13);
9494
StorageLive(_14);
9595
StorageLive(_15);

tests/mir-opt/gvn.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -499,11 +499,10 @@ fn dereferences(t: &mut u32, u: &impl Copy, s: &S<u32>) {
499499
unsafe { opaque(*z) };
500500
unsafe { opaque(*z) };
501501

502-
// Do not reuse dereferences of `&Freeze`.
503502
// CHECK: [[ref:_.*]] = &(*_1);
504-
// CHECK: [[st7:_.*]] = copy (*[[ref]]);
503+
// CHECK: [[st7:_.*]] = copy (*_1);
505504
// CHECK: opaque::<u32>(move [[st7]])
506-
// CHECK: [[st8:_.*]] = copy (*[[ref]]);
505+
// CHECK: [[st8:_.*]] = copy (*_1);
507506
// CHECK: opaque::<u32>(move [[st8]])
508507
let z = &*t;
509508
opaque(*z);
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
- // MIR for `deref_nonssa` before GVN
2+
+ // MIR for `deref_nonssa` after GVN
3+
4+
fn deref_nonssa() -> Single {
5+
let mut _0: Single;
6+
let mut _1: Single;
7+
let mut _4: Single;
8+
let mut _5: u8;
9+
scope 1 {
10+
debug a => _1;
11+
let _2: &Single;
12+
scope 2 {
13+
debug b => _2;
14+
let _3: u8;
15+
scope 3 {
16+
debug c => _3;
17+
}
18+
}
19+
}
20+
21+
bb0: {
22+
StorageLive(_1);
23+
- _1 = Single(const 0_u8);
24+
+ _1 = const Single(0_u8);
25+
StorageLive(_2);
26+
_2 = &_1;
27+
- StorageLive(_3);
28+
+ nop;
29+
_3 = copy ((*_2).0: u8);
30+
StorageLive(_4);
31+
- _4 = Single(const 1_u8);
32+
- _1 = move _4;
33+
+ _4 = const Single(1_u8);
34+
+ _1 = const Single(1_u8);
35+
StorageDead(_4);
36+
StorageLive(_5);
37+
_5 = copy _3;
38+
- _0 = Single(move _5);
39+
+ _0 = Single(copy _3);
40+
StorageDead(_5);
41+
- StorageDead(_3);
42+
+ nop;
43+
StorageDead(_2);
44+
StorageDead(_1);
45+
return;
46+
}
47+
}
48+

tests/mir-opt/gvn_copy_aggregate.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,3 +259,19 @@ fn remove_storage_dead_from_index(f: fn() -> usize, v: [SameType; 5]) -> SameTyp
259259
}
260260
}
261261
}
262+
263+
pub struct Single(u8);
264+
265+
// EMIT_MIR gvn_copy_aggregate.deref_nonssa.GVN.diff
266+
fn deref_nonssa() -> Single {
267+
// CHECK-LABEL: fn deref_nonssa(
268+
// CHECK: debug c => [[C:_.*]];
269+
// CHECK-NOT: _0 = copy (*_{{.*}});
270+
// CHECK: _0 = Single(copy [[C]]);
271+
let mut a = Single(0);
272+
let b = &a;
273+
let c = (*b).0;
274+
a = Single(1);
275+
// GVN shouldn't replace `Single(c)` with `*b`.
276+
Single(c)
277+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
- // MIR for `copy_overlapping` before GVN
2+
+ // MIR for `copy_overlapping` after GVN
3+
4+
fn copy_overlapping() -> () {
5+
let mut _0: ();
6+
let mut _1: Adt;
7+
let mut _2: u32;
8+
let mut _3: &Adt;
9+
10+
bb0: {
11+
((_1 as variant#1).0: u32) = const 0_u32;
12+
_3 = &_1;
13+
_2 = copy (((*_3) as variant#1).0: u32);
14+
_1 = Adt::Some(copy _2);
15+
return;
16+
}
17+
}
18+

tests/mir-opt/gvn_overlapping.overlapping.GVN.diff

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
bb0: {
1111
_2 = &raw mut _1;
1212
_4 = &(*_2);
13-
_3 = copy (((*_4) as variant#1).0: u32);
13+
- _3 = copy (((*_4) as variant#1).0: u32);
14+
+ _3 = copy (((*_2) as variant#1).0: u32);
1415
(*_2) = Adt::Some(copy _3);
1516
return;
1617
}

0 commit comments

Comments
 (0)