GVN: Elide more intermediate transmutes

This commit is contained in:
Scott McMurray 2026-01-24 15:05:36 -08:00
parent 38c71295e8
commit 3a33ab0595
15 changed files with 328 additions and 175 deletions

View file

@ -1591,10 +1591,12 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
(Transmute, PtrToPtr) if self.pointers_have_same_metadata(from, to) => {
Some(Transmute)
}
// If would be legal to always do this, but we don't want to hide information
// It would be legal to always do this, but we don't want to hide information
// from the backend that it'd otherwise be able to use for optimizations.
(Transmute, Transmute)
if !self.type_may_have_niche_of_interest_to_backend(from) =>
if !self.transmute_may_have_niche_of_interest_to_backend(
inner_from, from, to,
) =>
{
Some(Transmute)
}
@ -1642,24 +1644,65 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
}
}
/// Returns `false` if we know for sure that this type has no interesting niche,
/// and thus we can skip transmuting through it without worrying.
/// Returns `false` if we're confident that the middle type doesn't have an
/// interesting niche so we can skip that step when transmuting.
///
/// The backend will emit `assume`s when transmuting between types with niches,
/// so we want to preserve `i32 -> char -> u32` so that that data is around,
/// but it's fine to skip whole-range-is-value steps like `A -> u32 -> B`.
fn type_may_have_niche_of_interest_to_backend(&self, ty: Ty<'tcx>) -> bool {
let Ok(layout) = self.ecx.layout_of(ty) else {
fn transmute_may_have_niche_of_interest_to_backend(
&self,
from_ty: Ty<'tcx>,
middle_ty: Ty<'tcx>,
to_ty: Ty<'tcx>,
) -> bool {
let Ok(middle_layout) = self.ecx.layout_of(middle_ty) else {
// If it's too generic or something, then assume it might be interesting later.
return true;
};
if layout.uninhabited {
if middle_layout.uninhabited {
return true;
}
match layout.backend_repr {
BackendRepr::Scalar(a) => !a.is_always_valid(&self.ecx),
match middle_layout.backend_repr {
BackendRepr::Scalar(mid) => {
if mid.is_always_valid(&self.ecx) {
// With no niche it's never interesting, so don't bother
// looking at the layout of the other two types.
false
} else if let Ok(from_layout) = self.ecx.layout_of(from_ty)
&& !from_layout.uninhabited
&& from_layout.size == middle_layout.size
&& let BackendRepr::Scalar(from_a) = from_layout.backend_repr
&& let mid_range = mid.valid_range(&self.ecx)
&& let from_range = from_a.valid_range(&self.ecx)
&& mid_range.contains_range(from_range, middle_layout.size)
{
// The `from_range` is a (non-strict) subset of `mid_range`
// such as if we're doing `bool` -> `ascii::Char` -> `_`,
// where `from_range: 0..=1` and `mid_range: 0..=127`,
// and thus the middle doesn't tell us anything we don't
// already know from the initial type.
false
} else if let Ok(to_layout) = self.ecx.layout_of(to_ty)
&& !to_layout.uninhabited
&& to_layout.size == middle_layout.size
&& let BackendRepr::Scalar(to_a) = to_layout.backend_repr
&& let mid_range = mid.valid_range(&self.ecx)
&& let to_range = to_a.valid_range(&self.ecx)
&& mid_range.contains_range(to_range, middle_layout.size)
{
// The `to_range` is a (non-strict) subset of `mid_range`
// such as if we're doing `_` -> `ascii::Char` -> `bool`,
// where `mid_range: 0..=127` and `to_range: 0..=1`,
// and thus the middle doesn't tell us anything we don't
// already know from the final type.
false
} else {
true
}
}
BackendRepr::ScalarPair(a, b) => {
!a.is_always_valid(&self.ecx) || !b.is_always_valid(&self.ecx)
}

View file

@ -16,12 +16,11 @@
scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) {
let mut _5: std::ptr::NonNull<[bool; 0]>;
scope 5 (inlined NonNull::<[bool; 0]>::dangling) {
let mut _6: std::num::NonZero<usize>;
scope 6 {
scope 8 (inlined std::ptr::Alignment::as_nonzero) {
}
scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) {
let _7: *const [bool; 0];
let _6: *const [bool; 0];
scope 10 {
}
scope 11 (inlined NonZero::<usize>::get) {
@ -45,11 +44,8 @@
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
_6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
StorageLive(_7);
_7 = const {0x1 as *const [bool; 0]};
_6 = const {0x1 as *const [bool; 0]};
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
StorageDead(_7);
StorageDead(_6);
_4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
StorageDead(_5);

View file

@ -16,12 +16,11 @@
scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) {
let mut _5: std::ptr::NonNull<[bool; 0]>;
scope 5 (inlined NonNull::<[bool; 0]>::dangling) {
let mut _6: std::num::NonZero<usize>;
scope 6 {
scope 8 (inlined std::ptr::Alignment::as_nonzero) {
}
scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) {
let _7: *const [bool; 0];
let _6: *const [bool; 0];
scope 10 {
}
scope 11 (inlined NonZero::<usize>::get) {
@ -45,11 +44,8 @@
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
_6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
StorageLive(_7);
_7 = const {0x1 as *const [bool; 0]};
_6 = const {0x1 as *const [bool; 0]};
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
StorageDead(_7);
StorageDead(_6);
_4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
StorageDead(_5);

View file

@ -16,12 +16,11 @@
scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) {
let mut _5: std::ptr::NonNull<[bool; 0]>;
scope 5 (inlined NonNull::<[bool; 0]>::dangling) {
let mut _6: std::num::NonZero<usize>;
scope 6 {
scope 8 (inlined std::ptr::Alignment::as_nonzero) {
}
scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) {
let _7: *const [bool; 0];
let _6: *const [bool; 0];
scope 10 {
}
scope 11 (inlined NonZero::<usize>::get) {
@ -45,11 +44,8 @@
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
_6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
StorageLive(_7);
_7 = const {0x1 as *const [bool; 0]};
_6 = const {0x1 as *const [bool; 0]};
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
StorageDead(_7);
StorageDead(_6);
_4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
StorageDead(_5);

View file

@ -16,12 +16,11 @@
scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) {
let mut _5: std::ptr::NonNull<[bool; 0]>;
scope 5 (inlined NonNull::<[bool; 0]>::dangling) {
let mut _6: std::num::NonZero<usize>;
scope 6 {
scope 8 (inlined std::ptr::Alignment::as_nonzero) {
}
scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) {
let _7: *const [bool; 0];
let _6: *const [bool; 0];
scope 10 {
}
scope 11 (inlined NonZero::<usize>::get) {
@ -45,11 +44,8 @@
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
_6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
StorageLive(_7);
_7 = const {0x1 as *const [bool; 0]};
_6 = const {0x1 as *const [bool; 0]};
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
StorageDead(_7);
StorageDead(_6);
_4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
StorageDead(_5);

View file

@ -16,12 +16,11 @@
scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) {
let mut _5: std::ptr::NonNull<[bool; 0]>;
scope 5 (inlined NonNull::<[bool; 0]>::dangling) {
let mut _6: std::num::NonZero<usize>;
scope 6 {
scope 8 (inlined std::ptr::Alignment::as_nonzero) {
}
scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) {
let _7: *const [bool; 0];
let _6: *const [bool; 0];
scope 10 {
}
scope 11 (inlined NonZero::<usize>::get) {
@ -45,14 +44,10 @@
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as std::num::NonZero<usize> (Transmute);
+ _6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
StorageLive(_7);
- _7 = copy _6 as *const [bool; 0] (Transmute);
- _5 = NonNull::<[bool; 0]> { pointer: copy _7 };
+ _7 = const {0x1 as *const [bool; 0]};
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute);
- _5 = NonNull::<[bool; 0]> { pointer: copy _6 };
+ _6 = const {0x1 as *const [bool; 0]};
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
StorageDead(_7);
StorageDead(_6);
- _4 = std::ptr::Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
+ _4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};

View file

@ -16,12 +16,11 @@
scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) {
let mut _5: std::ptr::NonNull<[bool; 0]>;
scope 5 (inlined NonNull::<[bool; 0]>::dangling) {
let mut _6: std::num::NonZero<usize>;
scope 6 {
scope 8 (inlined std::ptr::Alignment::as_nonzero) {
}
scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) {
let _7: *const [bool; 0];
let _6: *const [bool; 0];
scope 10 {
}
scope 11 (inlined NonZero::<usize>::get) {
@ -45,14 +44,10 @@
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as std::num::NonZero<usize> (Transmute);
+ _6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
StorageLive(_7);
- _7 = copy _6 as *const [bool; 0] (Transmute);
- _5 = NonNull::<[bool; 0]> { pointer: copy _7 };
+ _7 = const {0x1 as *const [bool; 0]};
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute);
- _5 = NonNull::<[bool; 0]> { pointer: copy _6 };
+ _6 = const {0x1 as *const [bool; 0]};
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
StorageDead(_7);
StorageDead(_6);
- _4 = std::ptr::Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
+ _4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};

View file

@ -16,12 +16,11 @@
scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) {
let mut _5: std::ptr::NonNull<[bool; 0]>;
scope 5 (inlined NonNull::<[bool; 0]>::dangling) {
let mut _6: std::num::NonZero<usize>;
scope 6 {
scope 8 (inlined std::ptr::Alignment::as_nonzero) {
}
scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) {
let _7: *const [bool; 0];
let _6: *const [bool; 0];
scope 10 {
}
scope 11 (inlined NonZero::<usize>::get) {
@ -45,14 +44,10 @@
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as std::num::NonZero<usize> (Transmute);
+ _6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
StorageLive(_7);
- _7 = copy _6 as *const [bool; 0] (Transmute);
- _5 = NonNull::<[bool; 0]> { pointer: copy _7 };
+ _7 = const {0x1 as *const [bool; 0]};
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute);
- _5 = NonNull::<[bool; 0]> { pointer: copy _6 };
+ _6 = const {0x1 as *const [bool; 0]};
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
StorageDead(_7);
StorageDead(_6);
- _4 = std::ptr::Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
+ _4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};

View file

@ -16,12 +16,11 @@
scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) {
let mut _5: std::ptr::NonNull<[bool; 0]>;
scope 5 (inlined NonNull::<[bool; 0]>::dangling) {
let mut _6: std::num::NonZero<usize>;
scope 6 {
scope 8 (inlined std::ptr::Alignment::as_nonzero) {
}
scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) {
let _7: *const [bool; 0];
let _6: *const [bool; 0];
scope 10 {
}
scope 11 (inlined NonZero::<usize>::get) {
@ -45,14 +44,10 @@
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as std::num::NonZero<usize> (Transmute);
+ _6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
StorageLive(_7);
- _7 = copy _6 as *const [bool; 0] (Transmute);
- _5 = NonNull::<[bool; 0]> { pointer: copy _7 };
+ _7 = const {0x1 as *const [bool; 0]};
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute);
- _5 = NonNull::<[bool; 0]> { pointer: copy _6 };
+ _6 = const {0x1 as *const [bool; 0]};
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
StorageDead(_7);
StorageDead(_6);
- _4 = std::ptr::Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
+ _4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};

View file

@ -8,10 +8,10 @@
let mut _3: fn(u8) -> u8;
let _5: ();
let mut _6: fn(u8) -> u8;
let mut _9: {closure@$DIR/gvn.rs:617:19: 617:21};
let mut _9: {closure@$DIR/gvn.rs:618:19: 618:21};
let _10: ();
let mut _11: fn();
let mut _13: {closure@$DIR/gvn.rs:617:19: 617:21};
let mut _13: {closure@$DIR/gvn.rs:618:19: 618:21};
let _14: ();
let mut _15: fn();
scope 1 {
@ -19,7 +19,7 @@
let _4: fn(u8) -> u8;
scope 2 {
debug g => _4;
let _7: {closure@$DIR/gvn.rs:617:19: 617:21};
let _7: {closure@$DIR/gvn.rs:618:19: 618:21};
scope 3 {
debug closure => _7;
let _8: fn();
@ -62,16 +62,16 @@
StorageDead(_6);
StorageDead(_5);
- StorageLive(_7);
- _7 = {closure@$DIR/gvn.rs:617:19: 617:21};
- _7 = {closure@$DIR/gvn.rs:618:19: 618:21};
- StorageLive(_8);
+ nop;
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21};
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21};
+ nop;
StorageLive(_9);
- _9 = copy _7;
- _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21};
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21};
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
StorageDead(_9);
StorageLive(_10);
StorageLive(_11);
@ -88,8 +88,8 @@
StorageLive(_13);
- _13 = copy _7;
- _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21};
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21};
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
StorageDead(_13);
StorageLive(_14);
StorageLive(_15);

View file

@ -8,10 +8,10 @@
let mut _3: fn(u8) -> u8;
let _5: ();
let mut _6: fn(u8) -> u8;
let mut _9: {closure@$DIR/gvn.rs:617:19: 617:21};
let mut _9: {closure@$DIR/gvn.rs:618:19: 618:21};
let _10: ();
let mut _11: fn();
let mut _13: {closure@$DIR/gvn.rs:617:19: 617:21};
let mut _13: {closure@$DIR/gvn.rs:618:19: 618:21};
let _14: ();
let mut _15: fn();
scope 1 {
@ -19,7 +19,7 @@
let _4: fn(u8) -> u8;
scope 2 {
debug g => _4;
let _7: {closure@$DIR/gvn.rs:617:19: 617:21};
let _7: {closure@$DIR/gvn.rs:618:19: 618:21};
scope 3 {
debug closure => _7;
let _8: fn();
@ -62,16 +62,16 @@
StorageDead(_6);
StorageDead(_5);
- StorageLive(_7);
- _7 = {closure@$DIR/gvn.rs:617:19: 617:21};
- _7 = {closure@$DIR/gvn.rs:618:19: 618:21};
- StorageLive(_8);
+ nop;
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21};
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21};
+ nop;
StorageLive(_9);
- _9 = copy _7;
- _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21};
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21};
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
StorageDead(_9);
StorageLive(_10);
StorageLive(_11);
@ -88,8 +88,8 @@
StorageLive(_13);
- _13 = copy _7;
- _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21};
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21};
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
StorageDead(_13);
StorageLive(_14);
StorageLive(_15);

View file

@ -9,6 +9,7 @@
#![feature(freeze)]
#![allow(ambiguous_wide_pointer_comparisons)]
#![allow(unconditional_panic)]
#![allow(unnecessary_transmutes)]
#![allow(unused)]
use std::intrinsics::mir::*;
@ -985,7 +986,14 @@ unsafe fn aggregate_struct_then_transmute(id: u16, thin: *const u8) {
opaque(std::intrinsics::transmute::<_, *const u8>(j));
}
unsafe fn transmute_then_transmute_again(a: u32, c: char) {
#[repr(u8)]
enum ZeroOneTwo {
Zero,
One,
Two,
}
unsafe fn transmute_then_transmute_again(a: u32, c: char, b: bool, d: u8) {
// CHECK: [[TEMP1:_[0-9]+]] = copy _1 as char (Transmute);
// CHECK: [[TEMP2:_[0-9]+]] = copy [[TEMP1]] as i32 (Transmute);
// CHECK: opaque::<i32>(move [[TEMP2]])
@ -996,6 +1004,16 @@ unsafe fn transmute_then_transmute_again(a: u32, c: char) {
// CHECK: opaque::<i32>(move [[TEMP]])
let x = std::intrinsics::transmute::<char, u32>(c);
opaque(std::intrinsics::transmute::<u32, i32>(x));
// CHECK: [[TEMP:_[0-9]+]] = copy _3 as u8 (Transmute);
// CHECK: opaque::<u8>(move [[TEMP]])
let x = std::intrinsics::transmute::<bool, ZeroOneTwo>(b);
opaque(std::intrinsics::transmute::<ZeroOneTwo, u8>(x));
// CHECK: [[TEMP:_[0-9]+]] = copy _4 as bool (Transmute);
// CHECK: opaque::<bool>(move [[TEMP]])
let x = std::intrinsics::transmute::<u8, ZeroOneTwo>(d);
opaque(std::intrinsics::transmute::<ZeroOneTwo, bool>(x));
}
// Transmuting can skip a pointer cast so long as it wasn't a fat-to-thin cast.

View file

@ -1,71 +1,135 @@
- // MIR for `transmute_then_transmute_again` before GVN
+ // MIR for `transmute_then_transmute_again` after GVN
fn transmute_then_transmute_again(_1: u32, _2: char) -> () {
fn transmute_then_transmute_again(_1: u32, _2: char, _3: bool, _4: u8) -> () {
debug a => _1;
debug c => _2;
debug b => _3;
debug d => _4;
let mut _0: ();
let _3: char;
let mut _4: u32;
let _5: ();
let mut _6: i32;
let mut _7: char;
let _5: char;
let mut _6: u32;
let _7: ();
let mut _8: i32;
let mut _9: char;
let _10: ();
let mut _11: i32;
let mut _12: u32;
let mut _11: char;
let _12: ();
let mut _13: i32;
let mut _14: u32;
let mut _16: bool;
let _17: ();
let mut _18: u8;
let mut _19: ZeroOneTwo;
let mut _21: u8;
let _22: ();
let mut _23: bool;
let mut _24: ZeroOneTwo;
scope 1 {
debug x => _3;
let _8: u32;
debug x => _5;
let _10: u32;
scope 2 {
debug x => _8;
debug x => _10;
let _15: ZeroOneTwo;
scope 3 {
debug x => _15;
let _20: ZeroOneTwo;
scope 4 {
debug x => _20;
}
}
}
}
bb0: {
- StorageLive(_3);
- StorageLive(_5);
+ nop;
StorageLive(_4);
_4 = copy _1;
- _3 = move _4 as char (Transmute);
+ _3 = copy _1 as char (Transmute);
StorageDead(_4);
StorageLive(_5);
StorageLive(_6);
_6 = copy _1;
- _5 = move _6 as char (Transmute);
+ _5 = copy _1 as char (Transmute);
StorageDead(_6);
StorageLive(_7);
_7 = copy _3;
- _6 = move _7 as i32 (Transmute);
+ _6 = copy _3 as i32 (Transmute);
StorageDead(_7);
_5 = opaque::<i32>(move _6) -> [return: bb1, unwind unreachable];
StorageLive(_8);
StorageLive(_9);
_9 = copy _5;
- _8 = move _9 as i32 (Transmute);
+ _8 = copy _5 as i32 (Transmute);
StorageDead(_9);
_7 = opaque::<i32>(move _8) -> [return: bb1, unwind unreachable];
}
bb1: {
StorageDead(_6);
StorageDead(_5);
- StorageLive(_8);
StorageDead(_8);
StorageDead(_7);
- StorageLive(_10);
+ nop;
StorageLive(_9);
_9 = copy _2;
- _8 = move _9 as u32 (Transmute);
+ _8 = copy _2 as u32 (Transmute);
StorageDead(_9);
StorageLive(_10);
StorageLive(_11);
_11 = copy _2;
- _10 = move _11 as u32 (Transmute);
+ _10 = copy _2 as u32 (Transmute);
StorageDead(_11);
StorageLive(_12);
_12 = copy _8;
- _11 = move _12 as i32 (Transmute);
+ _11 = copy _2 as i32 (Transmute);
StorageDead(_12);
_10 = opaque::<i32>(move _11) -> [return: bb2, unwind unreachable];
StorageLive(_13);
StorageLive(_14);
_14 = copy _10;
- _13 = move _14 as i32 (Transmute);
+ _13 = copy _2 as i32 (Transmute);
StorageDead(_14);
_12 = opaque::<i32>(move _13) -> [return: bb2, unwind unreachable];
}
bb2: {
StorageDead(_11);
StorageDead(_10);
StorageDead(_13);
StorageDead(_12);
- StorageLive(_15);
+ nop;
StorageLive(_16);
_16 = copy _3;
- _15 = move _16 as ZeroOneTwo (Transmute);
+ _15 = copy _3 as ZeroOneTwo (Transmute);
StorageDead(_16);
StorageLive(_17);
StorageLive(_18);
StorageLive(_19);
- _19 = move _15;
- _18 = move _19 as u8 (Transmute);
+ _19 = copy _15;
+ _18 = copy _3 as u8 (Transmute);
StorageDead(_19);
_17 = opaque::<u8>(move _18) -> [return: bb3, unwind unreachable];
}
bb3: {
StorageDead(_18);
StorageDead(_17);
- StorageLive(_20);
+ nop;
StorageLive(_21);
_21 = copy _4;
- _20 = move _21 as ZeroOneTwo (Transmute);
+ _20 = copy _4 as ZeroOneTwo (Transmute);
StorageDead(_21);
StorageLive(_22);
StorageLive(_23);
StorageLive(_24);
- _24 = move _20;
- _23 = move _24 as bool (Transmute);
+ _24 = copy _20;
+ _23 = copy _4 as bool (Transmute);
StorageDead(_24);
_22 = opaque::<bool>(move _23) -> [return: bb4, unwind unreachable];
}
bb4: {
StorageDead(_23);
StorageDead(_22);
_0 = const ();
- StorageDead(_8);
- StorageDead(_3);
- StorageDead(_20);
- StorageDead(_15);
- StorageDead(_10);
- StorageDead(_5);
+ nop;
+ nop;
+ nop;
+ nop;
return;

View file

@ -1,71 +1,135 @@
- // MIR for `transmute_then_transmute_again` before GVN
+ // MIR for `transmute_then_transmute_again` after GVN
fn transmute_then_transmute_again(_1: u32, _2: char) -> () {
fn transmute_then_transmute_again(_1: u32, _2: char, _3: bool, _4: u8) -> () {
debug a => _1;
debug c => _2;
debug b => _3;
debug d => _4;
let mut _0: ();
let _3: char;
let mut _4: u32;
let _5: ();
let mut _6: i32;
let mut _7: char;
let _5: char;
let mut _6: u32;
let _7: ();
let mut _8: i32;
let mut _9: char;
let _10: ();
let mut _11: i32;
let mut _12: u32;
let mut _11: char;
let _12: ();
let mut _13: i32;
let mut _14: u32;
let mut _16: bool;
let _17: ();
let mut _18: u8;
let mut _19: ZeroOneTwo;
let mut _21: u8;
let _22: ();
let mut _23: bool;
let mut _24: ZeroOneTwo;
scope 1 {
debug x => _3;
let _8: u32;
debug x => _5;
let _10: u32;
scope 2 {
debug x => _8;
debug x => _10;
let _15: ZeroOneTwo;
scope 3 {
debug x => _15;
let _20: ZeroOneTwo;
scope 4 {
debug x => _20;
}
}
}
}
bb0: {
- StorageLive(_3);
- StorageLive(_5);
+ nop;
StorageLive(_4);
_4 = copy _1;
- _3 = move _4 as char (Transmute);
+ _3 = copy _1 as char (Transmute);
StorageDead(_4);
StorageLive(_5);
StorageLive(_6);
_6 = copy _1;
- _5 = move _6 as char (Transmute);
+ _5 = copy _1 as char (Transmute);
StorageDead(_6);
StorageLive(_7);
_7 = copy _3;
- _6 = move _7 as i32 (Transmute);
+ _6 = copy _3 as i32 (Transmute);
StorageDead(_7);
_5 = opaque::<i32>(move _6) -> [return: bb1, unwind continue];
StorageLive(_8);
StorageLive(_9);
_9 = copy _5;
- _8 = move _9 as i32 (Transmute);
+ _8 = copy _5 as i32 (Transmute);
StorageDead(_9);
_7 = opaque::<i32>(move _8) -> [return: bb1, unwind continue];
}
bb1: {
StorageDead(_6);
StorageDead(_5);
- StorageLive(_8);
StorageDead(_8);
StorageDead(_7);
- StorageLive(_10);
+ nop;
StorageLive(_9);
_9 = copy _2;
- _8 = move _9 as u32 (Transmute);
+ _8 = copy _2 as u32 (Transmute);
StorageDead(_9);
StorageLive(_10);
StorageLive(_11);
_11 = copy _2;
- _10 = move _11 as u32 (Transmute);
+ _10 = copy _2 as u32 (Transmute);
StorageDead(_11);
StorageLive(_12);
_12 = copy _8;
- _11 = move _12 as i32 (Transmute);
+ _11 = copy _2 as i32 (Transmute);
StorageDead(_12);
_10 = opaque::<i32>(move _11) -> [return: bb2, unwind continue];
StorageLive(_13);
StorageLive(_14);
_14 = copy _10;
- _13 = move _14 as i32 (Transmute);
+ _13 = copy _2 as i32 (Transmute);
StorageDead(_14);
_12 = opaque::<i32>(move _13) -> [return: bb2, unwind continue];
}
bb2: {
StorageDead(_11);
StorageDead(_10);
StorageDead(_13);
StorageDead(_12);
- StorageLive(_15);
+ nop;
StorageLive(_16);
_16 = copy _3;
- _15 = move _16 as ZeroOneTwo (Transmute);
+ _15 = copy _3 as ZeroOneTwo (Transmute);
StorageDead(_16);
StorageLive(_17);
StorageLive(_18);
StorageLive(_19);
- _19 = move _15;
- _18 = move _19 as u8 (Transmute);
+ _19 = copy _15;
+ _18 = copy _3 as u8 (Transmute);
StorageDead(_19);
_17 = opaque::<u8>(move _18) -> [return: bb3, unwind continue];
}
bb3: {
StorageDead(_18);
StorageDead(_17);
- StorageLive(_20);
+ nop;
StorageLive(_21);
_21 = copy _4;
- _20 = move _21 as ZeroOneTwo (Transmute);
+ _20 = copy _4 as ZeroOneTwo (Transmute);
StorageDead(_21);
StorageLive(_22);
StorageLive(_23);
StorageLive(_24);
- _24 = move _20;
- _23 = move _24 as bool (Transmute);
+ _24 = copy _20;
+ _23 = copy _4 as bool (Transmute);
StorageDead(_24);
_22 = opaque::<bool>(move _23) -> [return: bb4, unwind continue];
}
bb4: {
StorageDead(_23);
StorageDead(_22);
_0 = const ();
- StorageDead(_8);
- StorageDead(_3);
- StorageDead(_20);
- StorageDead(_15);
- StorageDead(_10);
- StorageDead(_5);
+ nop;
+ nop;
+ nop;
+ nop;
return;

View file

@ -7,7 +7,7 @@
let mut _2: *mut u8;
scope 1 (inlined dangling_mut::<u8>) {
scope 2 (inlined NonNull::<u8>::dangling) {
let mut _3: std::num::NonZero<usize>;
let _3: std::ptr::Alignment;
scope 3 {
scope 5 (inlined std::ptr::Alignment::as_nonzero) {
}
@ -40,9 +40,9 @@
StorageLive(_1);
StorageLive(_2);
StorageLive(_3);
- _3 = const std::ptr::Alignment::of::<u8>::{constant#0} as std::num::NonZero<usize> (Transmute);
- _3 = const std::ptr::Alignment::of::<u8>::{constant#0};
- _2 = copy _3 as *mut u8 (Transmute);
+ _3 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
+ _3 = const std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0);
+ _2 = const {0x1 as *mut u8};
StorageDead(_3);
StorageLive(_4);