Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit fd92746

Browse files
committedNov 22, 2024·
[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 2d0ea79 commit fd92746

14 files changed

+433
-17
lines changed
 

‎compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,6 +1405,29 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
14051405
}
14061406
}
14071407

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

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

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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 3 additions & 3 deletions
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

Lines changed: 3 additions & 3 deletions
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

Lines changed: 3 additions & 3 deletions
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

Lines changed: 3 additions & 3 deletions
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]> }};
Lines changed: 81 additions & 0 deletions
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+
Lines changed: 81 additions & 0 deletions
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 continue];
42+
+ _4 = opaque::<u16>(copy _1) -> [return: bb1, unwind continue];
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 continue];
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+

‎tests/mir-opt/gvn.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#![allow(unused)]
1313

1414
use std::intrinsics::mir::*;
15-
use std::marker::Freeze;
15+
use std::marker::{Freeze, PhantomData};
1616
use std::mem::transmute;
1717

1818
struct S<T>(T);
@@ -913,6 +913,20 @@ fn cast_pointer_eq(p1: *mut u8, p2: *mut u32, p3: *mut u32, p4: *mut [u32]) {
913913
// CHECK: _0 = const ();
914914
}
915915

916+
unsafe fn aggregate_struct_then_transmute(id: u16) {
917+
// CHECK: opaque::<u16>(copy _1)
918+
let a = MyId(id);
919+
opaque(std::intrinsics::transmute::<_, u16>(a));
920+
921+
// GVN can't do this yet because it doesn't know which field is the ZST,
922+
// but future changes might enable it.
923+
// CHECK: [[AGG:_.+]] = TypedId::<String>(copy _1, const PhantomData::<String>);
924+
// CHECK: [[INT:_.+]] = copy [[AGG]] as u16 (Transmute);
925+
// CHECK: opaque::<u16>(move [[INT]])
926+
let b = TypedId::<String>(id, PhantomData);
927+
opaque(std::intrinsics::transmute::<_, u16>(b));
928+
}
929+
916930
// Transmuting can skip a pointer cast so long as it wasn't a fat-to-thin cast.
917931
unsafe fn cast_pointer_then_transmute(thin: *mut u32, fat: *mut [u8]) {
918932
// CHECK-LABEL: fn cast_pointer_then_transmute
@@ -926,6 +940,23 @@ unsafe fn cast_pointer_then_transmute(thin: *mut u32, fat: *mut [u8]) {
926940
let fat_addr: usize = std::intrinsics::transmute(fat as *const ());
927941
}
928942

943+
unsafe fn transmute_then_cast_pointer(addr: usize) {
944+
// CHECK-LABEL: fn transmute_then_cast_pointer
945+
946+
// This is roughly what `NonNull::dangling` does
947+
// CHECK: [[CPTR:_.+]] = copy _1 as *const u8 (Transmute);
948+
// CHECK: takes_const_ptr::<u8>(move [[CPTR]])
949+
let p: *mut u8 = std::intrinsics::transmute(addr);
950+
takes_const_ptr(p);
951+
952+
// This cast is fat-to-thin, so can't be merged with the transmute
953+
// CHECK: [[FAT:_.+]] = move {{.+}} as *const [i32] (Transmute);
954+
// CHECK: [[THIN:_.+]] = copy [[FAT]] as *const i32 (PtrToPtr);
955+
// CHECK: takes_const_ptr::<i32>(move [[THIN]])
956+
let q = std::intrinsics::transmute::<&mut [i32], *const [i32]>(&mut [1, 2, 3]);
957+
takes_const_ptr(q as *const i32);
958+
}
959+
929960
#[custom_mir(dialect = "analysis")]
930961
fn remove_casts_must_change_both_sides(mut_a: &*mut u8, mut_b: *mut u8) -> bool {
931962
// CHECK-LABEL: fn remove_casts_must_change_both_sides(
@@ -982,6 +1013,16 @@ fn identity<T>(x: T) -> T {
9821013
x
9831014
}
9841015

1016+
#[inline(never)]
1017+
fn takes_const_ptr<T>(_: *const T) {}
1018+
1019+
#[repr(transparent)]
1020+
#[rustc_layout_scalar_valid_range_end(55555)]
1021+
struct MyId(u16);
1022+
1023+
#[repr(transparent)]
1024+
struct TypedId<T>(u16, PhantomData<T>);
1025+
9851026
// EMIT_MIR gvn.subexpression_elimination.GVN.diff
9861027
// EMIT_MIR gvn.wrap_unwrap.GVN.diff
9871028
// EMIT_MIR gvn.repeated_index.GVN.diff
@@ -1013,5 +1054,7 @@ fn identity<T>(x: T) -> T {
10131054
// EMIT_MIR gvn.array_len.GVN.diff
10141055
// EMIT_MIR gvn.generic_cast_metadata.GVN.diff
10151056
// EMIT_MIR gvn.cast_pointer_eq.GVN.diff
1057+
// EMIT_MIR gvn.aggregate_struct_then_transmute.GVN.diff
10161058
// EMIT_MIR gvn.cast_pointer_then_transmute.GVN.diff
1059+
// EMIT_MIR gvn.transmute_then_cast_pointer.GVN.diff
10171060
// EMIT_MIR gvn.remove_casts_must_change_both_sides.GVN.diff
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
- // MIR for `transmute_then_cast_pointer` before GVN
2+
+ // MIR for `transmute_then_cast_pointer` after GVN
3+
4+
fn transmute_then_cast_pointer(_1: usize) -> () {
5+
debug addr => _1;
6+
let mut _0: ();
7+
let _2: *mut u8;
8+
let mut _3: usize;
9+
let _4: ();
10+
let mut _5: *const u8;
11+
let mut _6: *mut u8;
12+
let mut _8: &mut [i32];
13+
let mut _9: &mut [i32; 3];
14+
let mut _10: &mut [i32; 3];
15+
let mut _11: [i32; 3];
16+
let _12: ();
17+
let mut _13: *const i32;
18+
let mut _14: *const [i32];
19+
scope 1 {
20+
debug p => _2;
21+
let _7: *const [i32];
22+
scope 2 {
23+
debug q => _7;
24+
}
25+
}
26+
27+
bb0: {
28+
- StorageLive(_2);
29+
+ nop;
30+
StorageLive(_3);
31+
_3 = copy _1;
32+
- _2 = move _3 as *mut u8 (Transmute);
33+
+ _2 = copy _1 as *mut u8 (Transmute);
34+
StorageDead(_3);
35+
StorageLive(_4);
36+
StorageLive(_5);
37+
StorageLive(_6);
38+
_6 = copy _2;
39+
- _5 = move _6 as *const u8 (PtrToPtr);
40+
+ _5 = copy _1 as *const u8 (Transmute);
41+
StorageDead(_6);
42+
_4 = takes_const_ptr::<u8>(move _5) -> [return: bb1, unwind unreachable];
43+
}
44+
45+
bb1: {
46+
StorageDead(_5);
47+
StorageDead(_4);
48+
- StorageLive(_7);
49+
+ nop;
50+
StorageLive(_8);
51+
StorageLive(_9);
52+
StorageLive(_10);
53+
StorageLive(_11);
54+
_11 = [const 1_i32, const 2_i32, const 3_i32];
55+
_10 = &mut _11;
56+
_9 = &mut (*_10);
57+
_8 = move _9 as &mut [i32] (PointerCoercion(Unsize, Implicit));
58+
StorageDead(_9);
59+
_7 = move _8 as *const [i32] (Transmute);
60+
StorageDead(_8);
61+
StorageDead(_11);
62+
StorageDead(_10);
63+
StorageLive(_12);
64+
StorageLive(_13);
65+
StorageLive(_14);
66+
_14 = copy _7;
67+
- _13 = move _14 as *const i32 (PtrToPtr);
68+
+ _13 = copy _7 as *const i32 (PtrToPtr);
69+
StorageDead(_14);
70+
_12 = takes_const_ptr::<i32>(move _13) -> [return: bb2, unwind unreachable];
71+
}
72+
73+
bb2: {
74+
StorageDead(_13);
75+
StorageDead(_12);
76+
_0 = const ();
77+
- StorageDead(_7);
78+
- StorageDead(_2);
79+
+ nop;
80+
+ nop;
81+
return;
82+
}
83+
}
84+
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
- // MIR for `transmute_then_cast_pointer` before GVN
2+
+ // MIR for `transmute_then_cast_pointer` after GVN
3+
4+
fn transmute_then_cast_pointer(_1: usize) -> () {
5+
debug addr => _1;
6+
let mut _0: ();
7+
let _2: *mut u8;
8+
let mut _3: usize;
9+
let _4: ();
10+
let mut _5: *const u8;
11+
let mut _6: *mut u8;
12+
let mut _8: &mut [i32];
13+
let mut _9: &mut [i32; 3];
14+
let mut _10: &mut [i32; 3];
15+
let mut _11: [i32; 3];
16+
let _12: ();
17+
let mut _13: *const i32;
18+
let mut _14: *const [i32];
19+
scope 1 {
20+
debug p => _2;
21+
let _7: *const [i32];
22+
scope 2 {
23+
debug q => _7;
24+
}
25+
}
26+
27+
bb0: {
28+
- StorageLive(_2);
29+
+ nop;
30+
StorageLive(_3);
31+
_3 = copy _1;
32+
- _2 = move _3 as *mut u8 (Transmute);
33+
+ _2 = copy _1 as *mut u8 (Transmute);
34+
StorageDead(_3);
35+
StorageLive(_4);
36+
StorageLive(_5);
37+
StorageLive(_6);
38+
_6 = copy _2;
39+
- _5 = move _6 as *const u8 (PtrToPtr);
40+
+ _5 = copy _1 as *const u8 (Transmute);
41+
StorageDead(_6);
42+
_4 = takes_const_ptr::<u8>(move _5) -> [return: bb1, unwind continue];
43+
}
44+
45+
bb1: {
46+
StorageDead(_5);
47+
StorageDead(_4);
48+
- StorageLive(_7);
49+
+ nop;
50+
StorageLive(_8);
51+
StorageLive(_9);
52+
StorageLive(_10);
53+
StorageLive(_11);
54+
_11 = [const 1_i32, const 2_i32, const 3_i32];
55+
_10 = &mut _11;
56+
_9 = &mut (*_10);
57+
_8 = move _9 as &mut [i32] (PointerCoercion(Unsize, Implicit));
58+
StorageDead(_9);
59+
_7 = move _8 as *const [i32] (Transmute);
60+
StorageDead(_8);
61+
StorageDead(_11);
62+
StorageDead(_10);
63+
StorageLive(_12);
64+
StorageLive(_13);
65+
StorageLive(_14);
66+
_14 = copy _7;
67+
- _13 = move _14 as *const i32 (PtrToPtr);
68+
+ _13 = copy _7 as *const i32 (PtrToPtr);
69+
StorageDead(_14);
70+
_12 = takes_const_ptr::<i32>(move _13) -> [return: bb2, unwind continue];
71+
}
72+
73+
bb2: {
74+
StorageDead(_13);
75+
StorageDead(_12);
76+
_0 = const ();
77+
- StorageDead(_7);
78+
- StorageDead(_2);
79+
+ nop;
80+
+ nop;
81+
return;
82+
}
83+
}
84+

0 commit comments

Comments
 (0)
Please sign in to comment.