Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions compiler/rustc_mir_transform/src/gvn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1494,6 +1494,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
}
}

#[instrument(level = "trace", skip(self), ret)]
fn simplify_cast(
&mut self,
initial_kind: &mut CastKind,
Expand Down Expand Up @@ -1549,6 +1550,42 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
}
}

// Field-Access-then-Transmute can just transmute the original value,
// so long as the bytes of a value from only from a single field.
if let Transmute = kind
&& let Value::Projection(field_value, ProjectionElem::Field(field_idx, ())) =
self.get(value)
{
if let Value::Projection(
downcast_value,
ProjectionElem::Downcast(_, _variant_idx),
) = self.get(field_value)
{
let downcast_ty = self.ty(downcast_value);
if let Ok(downcast_layout) = self.ecx.layout_of(downcast_ty)
&& let Ok(projected_layout) = self.ecx.layout_of(from)
&& downcast_layout.size == projected_layout.size
{
from = downcast_ty;
value = downcast_value;
was_updated_this_iteration = true;
if projected_layout.ty == to {
return Some(value);
}
}
} else if let Some((f_idx, field_ty)) =
self.value_is_all_in_one_field(self.ty(field_value), FIRST_VARIANT)
{
assert_eq!(field_idx, f_idx, "{from} -> {field_ty}");
from = self.ty(field_value);
value = field_value;
was_updated_this_iteration = true;
if field_ty == to {
return Some(value);
}
}
}

// Aggregate-then-Transmute can just transmute the original field value,
// so long as the bytes of a value from only from a single field.
if let Transmute = kind
Expand Down
42 changes: 42 additions & 0 deletions tests/mir-opt/const_prop/transmute.option_field.GVN.32bit.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
- // MIR for `option_field` before GVN
+ // MIR for `option_field` after GVN

fn option_field(_1: Option<NonNull<()>>) -> *const () {
debug x => _1;
let mut _0: *const ();
let mut _2: isize;
let mut _4: std::ptr::NonNull<()>;
scope 1 {
debug x => _3;
let _3: std::ptr::NonNull<()>;
}

bb0: {
_2 = discriminant(_1);
switchInt(move _2) -> [1: bb1, otherwise: bb2];
}

bb1: {
- StorageLive(_3);
+ nop;
_3 = copy ((_1 as Some).0: std::ptr::NonNull<()>);
StorageLive(_4);
_4 = copy _3;
- _0 = move _4 as *const () (Transmute);
+ _0 = copy _1 as *const () (Transmute);
StorageDead(_4);
- StorageDead(_3);
+ nop;
goto -> bb3;
}

bb2: {
_0 = const 0_usize as *const () (PointerWithExposedProvenance);
goto -> bb3;
}

bb3: {
return;
}
}

42 changes: 42 additions & 0 deletions tests/mir-opt/const_prop/transmute.option_field.GVN.64bit.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
- // MIR for `option_field` before GVN
+ // MIR for `option_field` after GVN

fn option_field(_1: Option<NonNull<()>>) -> *const () {
debug x => _1;
let mut _0: *const ();
let mut _2: isize;
let mut _4: std::ptr::NonNull<()>;
scope 1 {
debug x => _3;
let _3: std::ptr::NonNull<()>;
}

bb0: {
_2 = discriminant(_1);
switchInt(move _2) -> [1: bb1, otherwise: bb2];
}

bb1: {
- StorageLive(_3);
+ nop;
_3 = copy ((_1 as Some).0: std::ptr::NonNull<()>);
StorageLive(_4);
_4 = copy _3;
- _0 = move _4 as *const () (Transmute);
+ _0 = copy _1 as *const () (Transmute);
StorageDead(_4);
- StorageDead(_3);
+ nop;
goto -> bb3;
}

bb2: {
_0 = const 0_usize as *const () (PointerWithExposedProvenance);
goto -> bb3;
}

bb3: {
return;
}
}

8 changes: 8 additions & 0 deletions tests/mir-opt/const_prop/transmute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,12 @@ pub unsafe fn unreachable_box() -> ! {
match *x {}
}

// EMIT_MIR transmute.option_field.GVN.diff
pub unsafe fn option_field(x: Option<std::ptr::NonNull<()>>) -> *const () {
// CHECK-LABEL: fn option_field(
// CHECK: _3 = copy ((_1 as Some).0: std::ptr::NonNull<()>)
// CHECK: _0 = copy _1 as *const () (Transmute)
if let Some(x) = x { unsafe { transmute(x) } } else { 0 as *const () }
}

enum Never {}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
- _1 = const 1_usize as std::boxed::Box<Never> (Transmute);
- _2 = copy ((_1.0: std::ptr::Unique<Never>).0: std::ptr::NonNull<Never>) as *const Never (Transmute);
+ _1 = const Box::<Never>(std::ptr::Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global);
+ _2 = const std::ptr::NonNull::<Never> {{ pointer: {0x1 as *const Never} }} as *const Never (Transmute);
+ _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);
unreachable;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
- _1 = const 1_usize as std::boxed::Box<Never> (Transmute);
- _2 = copy ((_1.0: std::ptr::Unique<Never>).0: std::ptr::NonNull<Never>) as *const Never (Transmute);
+ _1 = const Box::<Never>(std::ptr::Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global);
+ _2 = const std::ptr::NonNull::<Never> {{ pointer: {0x1 as *const Never} }} as *const Never (Transmute);
+ _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);
unreachable;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@
- StorageLive(_5);
+ nop;
_10 = copy (*_1);
_11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
- _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
+ _11 = copy _10 as *const () (Transmute);
_5 = &raw const (*_11);
- StorageLive(_6);
+ nop;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@
- StorageLive(_5);
+ nop;
_10 = copy (*_1);
_11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
- _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
+ _11 = copy _10 as *const () (Transmute);
_5 = &raw const (*_11);
- StorageLive(_6);
+ nop;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@
- StorageLive(_5);
+ nop;
_10 = copy (*_1);
_11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
- _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
+ _11 = copy _10 as *const () (Transmute);
_5 = &raw const (*_11);
- StorageLive(_6);
+ nop;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@
- StorageLive(_5);
+ nop;
_10 = copy (*_1);
_11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
- _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
+ _11 = copy _10 as *const () (Transmute);
_5 = &raw const (*_11);
- StorageLive(_6);
+ nop;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@
StorageLive(_3);
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
- StorageLive(_6);
+ nop;
StorageLive(_7);
- _7 = copy _1;
- _6 = std::alloc::Global::alloc_impl_runtime(move _7, const false) -> [return: bb4, unwind unreachable];
Expand All @@ -93,11 +94,14 @@
}

bb6: {
_5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>);
- _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>);
+ _5 = copy ((_6 as Ok).0: std::ptr::NonNull<[u8]>);
StorageDead(_14);
StorageDead(_10);
StorageDead(_6);
_4 = copy _5 as *mut [u8] (Transmute);
- StorageDead(_6);
- _4 = copy _5 as *mut [u8] (Transmute);
+ nop;
+ _4 = copy _6 as *mut [u8] (Transmute);
StorageDead(_5);
_3 = copy _4 as *mut u8 (PtrToPtr);
StorageDead(_4);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@
StorageLive(_3);
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
- StorageLive(_6);
+ nop;
StorageLive(_7);
- _7 = copy _1;
- _6 = std::alloc::Global::alloc_impl_runtime(move _7, const false) -> [return: bb4, unwind unreachable];
Expand All @@ -93,11 +94,14 @@
}

bb6: {
_5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>);
- _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>);
+ _5 = copy ((_6 as Ok).0: std::ptr::NonNull<[u8]>);
StorageDead(_14);
StorageDead(_10);
StorageDead(_6);
_4 = copy _5 as *mut [u8] (Transmute);
- StorageDead(_6);
- _4 = copy _5 as *mut [u8] (Transmute);
+ nop;
+ _4 = copy _6 as *mut [u8] (Transmute);
StorageDead(_5);
_3 = copy _4 as *mut u8 (PtrToPtr);
StorageDead(_4);
Expand Down
Loading