GVN: Elide more intermediate transmutes
This commit is contained in:
parent
38c71295e8
commit
3a33ab0595
15 changed files with 328 additions and 175 deletions
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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]> }};
|
||||
|
|
|
|||
|
|
@ -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]> }};
|
||||
|
|
|
|||
|
|
@ -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]> }};
|
||||
|
|
|
|||
|
|
@ -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]> }};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue