Skip to content

Commit 26d5903

Browse files
committed
Auto merge of #153085 - oli-obk:transmute_project, r=<try>
GVN: transmute adts to their fields if a field projection is immediately transmuted anyway
2 parents 70d86e3 + 9bf1aaa commit 26d5903

12 files changed

Lines changed: 155 additions & 14 deletions

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1495,6 +1495,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
14951495
}
14961496
}
14971497

1498+
#[instrument(level = "trace", skip(self), ret)]
14981499
fn simplify_cast(
14991500
&mut self,
15001501
initial_kind: &mut CastKind,
@@ -1550,6 +1551,42 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
15501551
}
15511552
}
15521553

1554+
// Field-Access-then-Transmute can just transmute the original value,
1555+
// so long as the bytes of a value from only from a single field.
1556+
if let Transmute = kind
1557+
&& let Value::Projection(field_value, ProjectionElem::Field(field_idx, ())) =
1558+
self.get(value)
1559+
{
1560+
if let Value::Projection(
1561+
downcast_value,
1562+
ProjectionElem::Downcast(_, _variant_idx),
1563+
) = self.get(field_value)
1564+
{
1565+
let downcast_ty = self.ty(downcast_value);
1566+
if let Ok(downcast_layout) = self.ecx.layout_of(downcast_ty)
1567+
&& let Ok(projected_layout) = self.ecx.layout_of(from)
1568+
&& downcast_layout.size == projected_layout.size
1569+
{
1570+
from = downcast_ty;
1571+
value = downcast_value;
1572+
was_updated_this_iteration = true;
1573+
if projected_layout.ty == to {
1574+
return Some(value);
1575+
}
1576+
}
1577+
} else if let Some((f_idx, field_ty)) =
1578+
self.value_is_all_in_one_field(self.ty(field_value), FIRST_VARIANT)
1579+
{
1580+
assert_eq!(field_idx, f_idx, "{from} -> {field_ty}");
1581+
from = self.ty(field_value);
1582+
value = field_value;
1583+
was_updated_this_iteration = true;
1584+
if field_ty == to {
1585+
return Some(value);
1586+
}
1587+
}
1588+
}
1589+
15531590
// Aggregate-then-Transmute can just transmute the original field value,
15541591
// so long as the bytes of a value from only from a single field.
15551592
if let Transmute = kind
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
- // MIR for `option_field` before GVN
2+
+ // MIR for `option_field` after GVN
3+
4+
fn option_field(_1: Option<NonNull<()>>) -> *const () {
5+
debug x => _1;
6+
let mut _0: *const ();
7+
let mut _2: isize;
8+
let mut _4: std::ptr::NonNull<()>;
9+
scope 1 {
10+
debug x => _3;
11+
let _3: std::ptr::NonNull<()>;
12+
}
13+
14+
bb0: {
15+
_2 = discriminant(_1);
16+
switchInt(move _2) -> [1: bb1, otherwise: bb2];
17+
}
18+
19+
bb1: {
20+
- StorageLive(_3);
21+
+ nop;
22+
_3 = copy ((_1 as Some).0: std::ptr::NonNull<()>);
23+
StorageLive(_4);
24+
_4 = copy _3;
25+
- _0 = move _4 as *const () (Transmute);
26+
+ _0 = copy _1 as *const () (Transmute);
27+
StorageDead(_4);
28+
- StorageDead(_3);
29+
+ nop;
30+
goto -> bb3;
31+
}
32+
33+
bb2: {
34+
_0 = const 0_usize as *const () (PointerWithExposedProvenance);
35+
goto -> bb3;
36+
}
37+
38+
bb3: {
39+
return;
40+
}
41+
}
42+
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
- // MIR for `option_field` before GVN
2+
+ // MIR for `option_field` after GVN
3+
4+
fn option_field(_1: Option<NonNull<()>>) -> *const () {
5+
debug x => _1;
6+
let mut _0: *const ();
7+
let mut _2: isize;
8+
let mut _4: std::ptr::NonNull<()>;
9+
scope 1 {
10+
debug x => _3;
11+
let _3: std::ptr::NonNull<()>;
12+
}
13+
14+
bb0: {
15+
_2 = discriminant(_1);
16+
switchInt(move _2) -> [1: bb1, otherwise: bb2];
17+
}
18+
19+
bb1: {
20+
- StorageLive(_3);
21+
+ nop;
22+
_3 = copy ((_1 as Some).0: std::ptr::NonNull<()>);
23+
StorageLive(_4);
24+
_4 = copy _3;
25+
- _0 = move _4 as *const () (Transmute);
26+
+ _0 = copy _1 as *const () (Transmute);
27+
StorageDead(_4);
28+
- StorageDead(_3);
29+
+ nop;
30+
goto -> bb3;
31+
}
32+
33+
bb2: {
34+
_0 = const 0_usize as *const () (PointerWithExposedProvenance);
35+
goto -> bb3;
36+
}
37+
38+
bb3: {
39+
return;
40+
}
41+
}
42+

tests/mir-opt/const_prop/transmute.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,12 @@ pub unsafe fn unreachable_box() -> ! {
8484
match *x {}
8585
}
8686

87+
// EMIT_MIR transmute.option_field.GVN.diff
88+
pub unsafe fn option_field(x: Option<std::ptr::NonNull<()>>) -> *const () {
89+
// CHECK-LABEL: fn option_field(
90+
// CHECK: _3 = copy ((_1 as Some).0: std::ptr::NonNull<()>)
91+
// CHECK: _0 = copy _1 as *const () (Transmute)
92+
if let Some(x) = x { unsafe { transmute(x) } } else { 0 as *const () }
93+
}
94+
8795
enum Never {}

tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
- _1 = const 1_usize as std::boxed::Box<Never> (Transmute);
1515
- _2 = copy ((_1.0: std::ptr::Unique<Never>).0: std::ptr::NonNull<Never>) as *const Never (Transmute);
1616
+ _1 = const Box::<Never>(std::ptr::Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global);
17-
+ _2 = const std::ptr::NonNull::<Never> {{ pointer: {0x1 as *const Never} }} as *const Never (Transmute);
17+
+ _2 = const std::boxed::Box::<Never>(std::ptr::Unique::<Never> {{ pointer: std::ptr::NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: std::marker::PhantomData::<Never> }}, std::alloc::Global) as *const Never (Transmute);
1818
unreachable;
1919
}
2020
}

tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
- _1 = const 1_usize as std::boxed::Box<Never> (Transmute);
1515
- _2 = copy ((_1.0: std::ptr::Unique<Never>).0: std::ptr::NonNull<Never>) as *const Never (Transmute);
1616
+ _1 = const Box::<Never>(std::ptr::Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global);
17-
+ _2 = const std::ptr::NonNull::<Never> {{ pointer: {0x1 as *const Never} }} as *const Never (Transmute);
17+
+ _2 = const std::boxed::Box::<Never>(std::ptr::Unique::<Never> {{ pointer: std::ptr::NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: std::marker::PhantomData::<Never> }}, std::alloc::Global) as *const Never (Transmute);
1818
unreachable;
1919
}
2020
}

tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@
7474
- StorageLive(_5);
7575
+ nop;
7676
_10 = copy (*_1);
77-
_11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
77+
- _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
78+
+ _11 = copy _10 as *const () (Transmute);
7879
_5 = &raw const (*_11);
7980
- StorageLive(_6);
8081
+ nop;

tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@
5454
- StorageLive(_5);
5555
+ nop;
5656
_10 = copy (*_1);
57-
_11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
57+
- _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
58+
+ _11 = copy _10 as *const () (Transmute);
5859
_5 = &raw const (*_11);
5960
- StorageLive(_6);
6061
+ nop;

tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@
7474
- StorageLive(_5);
7575
+ nop;
7676
_10 = copy (*_1);
77-
_11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
77+
- _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
78+
+ _11 = copy _10 as *const () (Transmute);
7879
_5 = &raw const (*_11);
7980
- StorageLive(_6);
8081
+ nop;

tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@
5454
- StorageLive(_5);
5555
+ nop;
5656
_10 = copy (*_1);
57-
_11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
57+
- _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
58+
+ _11 = copy _10 as *const () (Transmute);
5859
_5 = &raw const (*_11);
5960
- StorageLive(_6);
6061
+ nop;

0 commit comments

Comments
 (0)