Skip to content

Commit 3a9056e

Browse files
committed
[mir-opt] GVN some more transmute cases
We already did `Transmute`-then-`PtrToPtr`; this adds the nearly-identical `PtrToPtr`-then-`Transmute`. It also adds `transmute(Foo(x))` → `transmute(x)`, when `Foo` is a single-field transparent type. That's useful for things like `NonNull { pointer: p }.as_ptr()`. Found these as I was looking at MCP807-related changes.
1 parent 96e51d9 commit 3a9056e

26 files changed

+886
-598
lines changed

compiler/rustc_mir_transform/src/gvn.rs

+42
Original file line numberDiff line numberDiff line change
@@ -1407,6 +1407,28 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
14071407
}
14081408
}
14091409

1410+
// Aggregate-then-Transmute can just transmute the original field value,
1411+
// so long as the type is transparent over only that one single field.
1412+
if let Transmute = kind
1413+
&& let Value::Aggregate(
1414+
AggregateTy::Def(aggregate_did, aggregate_args),
1415+
FIRST_VARIANT,
1416+
field_values,
1417+
) = self.get(value)
1418+
&& let [single_field_value] = **field_values
1419+
&& let adt = self.tcx.adt_def(aggregate_did)
1420+
&& adt.is_struct()
1421+
&& adt.repr().transparent()
1422+
{
1423+
let field_ty = adt.non_enum_variant().single_field().ty(self.tcx, aggregate_args);
1424+
from = field_ty;
1425+
value = single_field_value;
1426+
was_updated = true;
1427+
if field_ty == to {
1428+
return Some(single_field_value);
1429+
}
1430+
}
1431+
14101432
// PtrToPtr-then-Transmute can just transmute the original, so long as the
14111433
// PtrToPtr didn't change metadata (and thus the size of the pointer)
14121434
if let Transmute = kind
@@ -1426,6 +1448,26 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
14261448
}
14271449
}
14281450

1451+
// PtrToPtr-then-Transmute can just transmute the original, so long as the
1452+
// PtrToPtr didn't change metadata (and thus the size of the pointer)
1453+
if let PtrToPtr = kind
1454+
&& let Value::Cast {
1455+
kind: Transmute,
1456+
value: inner_value,
1457+
from: inner_from,
1458+
to: _inner_to,
1459+
} = *self.get(value)
1460+
&& self.pointers_have_same_metadata(from, to)
1461+
{
1462+
*kind = Transmute;
1463+
from = inner_from;
1464+
value = inner_value;
1465+
was_updated = true;
1466+
if inner_from == to {
1467+
return Some(inner_value);
1468+
}
1469+
}
1470+
14291471
if was_updated && let Some(op) = self.try_as_operand(value, location) {
14301472
*operand = op;
14311473
}

compiler/rustc_mir_transform/src/instsimplify.rs

-23
Original file line numberDiff line numberDiff line change
@@ -187,29 +187,6 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
187187
*kind = CastKind::IntToInt;
188188
return;
189189
}
190-
191-
// Transmuting a transparent struct/union to a field's type is a projection
192-
if let ty::Adt(adt_def, args) = operand_ty.kind()
193-
&& adt_def.repr().transparent()
194-
&& (adt_def.is_struct() || adt_def.is_union())
195-
&& let Some(place) = operand.place()
196-
{
197-
let variant = adt_def.non_enum_variant();
198-
for (i, field) in variant.fields.iter_enumerated() {
199-
let field_ty = field.ty(self.tcx, args);
200-
if field_ty == *cast_ty {
201-
let place = place
202-
.project_deeper(&[ProjectionElem::Field(i, *cast_ty)], self.tcx);
203-
let operand = if operand.is_move() {
204-
Operand::Move(place)
205-
} else {
206-
Operand::Copy(place)
207-
};
208-
*rvalue = Rvalue::Use(operand);
209-
return;
210-
}
211-
}
212-
}
213190
}
214191
}
215192
}

tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
StorageLive(_7);
5252
_7 = const 1_usize;
5353
_6 = const {0x1 as *mut [bool; 0]};
54-
StorageDead(_7);
5554
StorageLive(_11);
5655
StorageLive(_8);
5756
_8 = UbChecks();
@@ -79,6 +78,7 @@
7978
_11 = const {0x1 as *const [bool; 0]};
8079
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
8180
StorageDead(_11);
81+
StorageDead(_7);
8282
StorageDead(_6);
8383
_4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
8484
StorageDead(_5);

tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
StorageLive(_7);
5252
_7 = const 1_usize;
5353
_6 = const {0x1 as *mut [bool; 0]};
54-
StorageDead(_7);
5554
StorageLive(_11);
5655
StorageLive(_8);
5756
_8 = UbChecks();
@@ -83,6 +82,7 @@
8382
_11 = const {0x1 as *const [bool; 0]};
8483
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
8584
StorageDead(_11);
85+
StorageDead(_7);
8686
StorageDead(_6);
8787
_4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
8888
StorageDead(_5);

tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
StorageLive(_7);
5252
_7 = const 1_usize;
5353
_6 = const {0x1 as *mut [bool; 0]};
54-
StorageDead(_7);
5554
StorageLive(_11);
5655
StorageLive(_8);
5756
_8 = UbChecks();
@@ -79,6 +78,7 @@
7978
_11 = const {0x1 as *const [bool; 0]};
8079
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
8180
StorageDead(_11);
81+
StorageDead(_7);
8282
StorageDead(_6);
8383
_4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
8484
StorageDead(_5);

tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
StorageLive(_7);
5252
_7 = const 1_usize;
5353
_6 = const {0x1 as *mut [bool; 0]};
54-
StorageDead(_7);
5554
StorageLive(_11);
5655
StorageLive(_8);
5756
_8 = UbChecks();
@@ -83,6 +82,7 @@
8382
_11 = const {0x1 as *const [bool; 0]};
8483
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
8584
StorageDead(_11);
85+
StorageDead(_7);
8686
StorageDead(_6);
8787
_4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
8888
StorageDead(_5);

tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff

+3-3
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@
5353
- _6 = copy _7 as *mut [bool; 0] (Transmute);
5454
+ _7 = const 1_usize;
5555
+ _6 = const {0x1 as *mut [bool; 0]};
56-
StorageDead(_7);
5756
StorageLive(_11);
5857
StorageLive(_8);
5958
_8 = UbChecks();
@@ -67,7 +66,7 @@
6766

6867
bb2: {
6968
StorageLive(_10);
70-
- _10 = copy _6 as *mut () (PtrToPtr);
69+
- _10 = copy _7 as *mut () (Transmute);
7170
- _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable];
7271
+ _10 = const {0x1 as *mut ()};
7372
+ _9 = NonNull::<T>::new_unchecked::precondition_check(const {0x1 as *mut ()}) -> [return: bb3, unwind unreachable];
@@ -80,11 +79,12 @@
8079

8180
bb4: {
8281
StorageDead(_8);
83-
- _11 = copy _6 as *const [bool; 0] (PtrToPtr);
82+
- _11 = copy _7 as *const [bool; 0] (Transmute);
8483
- _5 = NonNull::<[bool; 0]> { pointer: copy _11 };
8584
+ _11 = const {0x1 as *const [bool; 0]};
8685
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
8786
StorageDead(_11);
87+
StorageDead(_7);
8888
StorageDead(_6);
8989
- _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
9090
+ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};

tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff

+3-3
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@
5353
- _6 = copy _7 as *mut [bool; 0] (Transmute);
5454
+ _7 = const 1_usize;
5555
+ _6 = const {0x1 as *mut [bool; 0]};
56-
StorageDead(_7);
5756
StorageLive(_11);
5857
StorageLive(_8);
5958
_8 = UbChecks();
@@ -71,7 +70,7 @@
7170

7271
bb3: {
7372
StorageLive(_10);
74-
- _10 = copy _6 as *mut () (PtrToPtr);
73+
- _10 = copy _7 as *mut () (Transmute);
7574
- _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable];
7675
+ _10 = const {0x1 as *mut ()};
7776
+ _9 = NonNull::<T>::new_unchecked::precondition_check(const {0x1 as *mut ()}) -> [return: bb4, unwind unreachable];
@@ -84,11 +83,12 @@
8483

8584
bb5: {
8685
StorageDead(_8);
87-
- _11 = copy _6 as *const [bool; 0] (PtrToPtr);
86+
- _11 = copy _7 as *const [bool; 0] (Transmute);
8887
- _5 = NonNull::<[bool; 0]> { pointer: copy _11 };
8988
+ _11 = const {0x1 as *const [bool; 0]};
9089
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
9190
StorageDead(_11);
91+
StorageDead(_7);
9292
StorageDead(_6);
9393
- _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
9494
+ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};

tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff

+3-3
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@
5353
- _6 = copy _7 as *mut [bool; 0] (Transmute);
5454
+ _7 = const 1_usize;
5555
+ _6 = const {0x1 as *mut [bool; 0]};
56-
StorageDead(_7);
5756
StorageLive(_11);
5857
StorageLive(_8);
5958
_8 = UbChecks();
@@ -67,7 +66,7 @@
6766

6867
bb2: {
6968
StorageLive(_10);
70-
- _10 = copy _6 as *mut () (PtrToPtr);
69+
- _10 = copy _7 as *mut () (Transmute);
7170
- _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable];
7271
+ _10 = const {0x1 as *mut ()};
7372
+ _9 = NonNull::<T>::new_unchecked::precondition_check(const {0x1 as *mut ()}) -> [return: bb3, unwind unreachable];
@@ -80,11 +79,12 @@
8079

8180
bb4: {
8281
StorageDead(_8);
83-
- _11 = copy _6 as *const [bool; 0] (PtrToPtr);
82+
- _11 = copy _7 as *const [bool; 0] (Transmute);
8483
- _5 = NonNull::<[bool; 0]> { pointer: copy _11 };
8584
+ _11 = const {0x1 as *const [bool; 0]};
8685
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
8786
StorageDead(_11);
87+
StorageDead(_7);
8888
StorageDead(_6);
8989
- _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
9090
+ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};

tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff

+3-3
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@
5353
- _6 = copy _7 as *mut [bool; 0] (Transmute);
5454
+ _7 = const 1_usize;
5555
+ _6 = const {0x1 as *mut [bool; 0]};
56-
StorageDead(_7);
5756
StorageLive(_11);
5857
StorageLive(_8);
5958
_8 = UbChecks();
@@ -71,7 +70,7 @@
7170

7271
bb3: {
7372
StorageLive(_10);
74-
- _10 = copy _6 as *mut () (PtrToPtr);
73+
- _10 = copy _7 as *mut () (Transmute);
7574
- _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable];
7675
+ _10 = const {0x1 as *mut ()};
7776
+ _9 = NonNull::<T>::new_unchecked::precondition_check(const {0x1 as *mut ()}) -> [return: bb4, unwind unreachable];
@@ -84,11 +83,12 @@
8483

8584
bb5: {
8685
StorageDead(_8);
87-
- _11 = copy _6 as *const [bool; 0] (PtrToPtr);
86+
- _11 = copy _7 as *const [bool; 0] (Transmute);
8887
- _5 = NonNull::<[bool; 0]> { pointer: copy _11 };
8988
+ _11 = const {0x1 as *const [bool; 0]};
9089
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
9190
StorageDead(_11);
91+
StorageDead(_7);
9292
StorageDead(_6);
9393
- _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
9494
+ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
- // MIR for `aggregate_struct_then_transmute` before GVN
2+
+ // MIR for `aggregate_struct_then_transmute` after GVN
3+
4+
fn aggregate_struct_then_transmute(_1: u16) -> () {
5+
debug id => _1;
6+
let mut _0: ();
7+
let _2: MyId;
8+
let mut _3: u16;
9+
let _4: ();
10+
let mut _5: u16;
11+
let mut _6: MyId;
12+
let mut _8: u16;
13+
let mut _9: std::marker::PhantomData<std::string::String>;
14+
let _10: ();
15+
let mut _11: u16;
16+
let mut _12: TypedId<std::string::String>;
17+
scope 1 {
18+
debug a => _2;
19+
let _7: TypedId<std::string::String>;
20+
scope 2 {
21+
debug b => _7;
22+
}
23+
}
24+
25+
bb0: {
26+
- StorageLive(_2);
27+
+ nop;
28+
StorageLive(_3);
29+
_3 = copy _1;
30+
- _2 = MyId(move _3);
31+
+ _2 = MyId(copy _1);
32+
StorageDead(_3);
33+
StorageLive(_4);
34+
StorageLive(_5);
35+
StorageLive(_6);
36+
- _6 = move _2;
37+
- _5 = move _6 as u16 (Transmute);
38+
+ _6 = copy _2;
39+
+ _5 = copy _1;
40+
StorageDead(_6);
41+
- _4 = opaque::<u16>(move _5) -> [return: bb1, unwind unreachable];
42+
+ _4 = opaque::<u16>(copy _1) -> [return: bb1, unwind unreachable];
43+
}
44+
45+
bb1: {
46+
StorageDead(_5);
47+
StorageDead(_4);
48+
- StorageLive(_7);
49+
+ nop;
50+
StorageLive(_8);
51+
_8 = copy _1;
52+
StorageLive(_9);
53+
- _9 = PhantomData::<String>;
54+
- _7 = TypedId::<String>(move _8, move _9);
55+
+ _9 = const PhantomData::<String>;
56+
+ _7 = TypedId::<String>(copy _1, const PhantomData::<String>);
57+
StorageDead(_9);
58+
StorageDead(_8);
59+
StorageLive(_10);
60+
StorageLive(_11);
61+
StorageLive(_12);
62+
- _12 = move _7;
63+
- _11 = move _12 as u16 (Transmute);
64+
+ _12 = copy _7;
65+
+ _11 = copy _7 as u16 (Transmute);
66+
StorageDead(_12);
67+
_10 = opaque::<u16>(move _11) -> [return: bb2, unwind unreachable];
68+
}
69+
70+
bb2: {
71+
StorageDead(_11);
72+
StorageDead(_10);
73+
_0 = const ();
74+
- StorageDead(_7);
75+
- StorageDead(_2);
76+
+ nop;
77+
+ nop;
78+
return;
79+
}
80+
}
81+

0 commit comments

Comments
 (0)