Skip to content

Commit cd2b201

Browse files
committed
Auto merge of #151622 - scottmcm:elide-more-transmutes, r=<try>
GVN: Elide more intermediate transmutes
2 parents 75963ce + 433703d commit cd2b201

File tree

27 files changed

+399
-249
lines changed

27 files changed

+399
-249
lines changed

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,10 +1591,12 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
15911591
(Transmute, PtrToPtr) if self.pointers_have_same_metadata(from, to) => {
15921592
Some(Transmute)
15931593
}
1594-
// If would be legal to always do this, but we don't want to hide information
1594+
// It would be legal to always do this, but we don't want to hide information
15951595
// from the backend that it'd otherwise be able to use for optimizations.
15961596
(Transmute, Transmute)
1597-
if !self.type_may_have_niche_of_interest_to_backend(from) =>
1597+
if !self.transmute_may_have_niche_of_interest_to_backend(
1598+
inner_from, from, to,
1599+
) =>
15981600
{
15991601
Some(Transmute)
16001602
}
@@ -1642,24 +1644,55 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
16421644
}
16431645
}
16441646

1645-
/// Returns `false` if we know for sure that this type has no interesting niche,
1646-
/// and thus we can skip transmuting through it without worrying.
1647+
/// Returns `false` if we're confident that the middle type doesn't have an
1648+
/// interesting niche so we can skip that step when transmuting.
16471649
///
16481650
/// The backend will emit `assume`s when transmuting between types with niches,
16491651
/// so we want to preserve `i32 -> char -> u32` so that that data is around,
16501652
/// but it's fine to skip whole-range-is-value steps like `A -> u32 -> B`.
1651-
fn type_may_have_niche_of_interest_to_backend(&self, ty: Ty<'tcx>) -> bool {
1652-
let Ok(layout) = self.ecx.layout_of(ty) else {
1653+
fn transmute_may_have_niche_of_interest_to_backend(
1654+
&self,
1655+
from_ty: Ty<'tcx>,
1656+
middle_ty: Ty<'tcx>,
1657+
to_ty: Ty<'tcx>,
1658+
) -> bool {
1659+
let Ok(middle_layout) = self.ecx.layout_of(middle_ty) else {
16531660
// If it's too generic or something, then assume it might be interesting later.
16541661
return true;
16551662
};
16561663

1657-
if layout.uninhabited {
1664+
if middle_layout.uninhabited {
16581665
return true;
16591666
}
16601667

1661-
match layout.backend_repr {
1662-
BackendRepr::Scalar(a) => !a.is_always_valid(&self.ecx),
1668+
match middle_layout.backend_repr {
1669+
BackendRepr::Scalar(a) => {
1670+
if a.is_always_valid(&self.ecx) {
1671+
// With no niche it's never interesting, so don't bother
1672+
// looking at the layout of the other two types.
1673+
false
1674+
} else if let Ok(from_layout) = self.ecx.layout_of(from_ty)
1675+
&& !from_layout.uninhabited
1676+
&& from_layout.size == middle_layout.size
1677+
&& let BackendRepr::Scalar(from_a) = from_layout.backend_repr
1678+
&& let a_range = a.valid_range(&self.ecx)
1679+
&& let from_range = from_a.valid_range(&self.ecx)
1680+
&& a_range.contains_range(from_range, middle_layout.size)
1681+
{
1682+
false
1683+
} else if let Ok(to_layout) = self.ecx.layout_of(to_ty)
1684+
&& !to_layout.uninhabited
1685+
&& to_layout.size == middle_layout.size
1686+
&& let BackendRepr::Scalar(to_a) = to_layout.backend_repr
1687+
&& let a_range = a.valid_range(&self.ecx)
1688+
&& let to_range = to_a.valid_range(&self.ecx)
1689+
&& a_range.contains_range(to_range, middle_layout.size)
1690+
{
1691+
false
1692+
} else {
1693+
true
1694+
}
1695+
}
16631696
BackendRepr::ScalarPair(a, b) => {
16641697
!a.is_always_valid(&self.ecx) || !b.is_always_valid(&self.ecx)
16651698
}

library/core/src/ptr/alignment.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@ use crate::{cmp, fmt, hash, mem, num};
1212
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
1313
#[derive(Copy, Clone, PartialEq, Eq)]
1414
#[repr(transparent)]
15-
pub struct Alignment(AlignmentEnum);
15+
pub struct Alignment {
16+
// This field is never used directly (nor is the enum),
17+
// as it's just there to convey the validity invariant.
18+
// (Hopefully it'll eventually be a pattern type instead.)
19+
_inner_repr_trick: AlignmentEnum,
20+
}
1621

1722
// Alignment is `repr(usize)`, but via extra steps.
1823
const _: () = assert!(size_of::<Alignment>() == size_of::<usize>());
@@ -36,7 +41,7 @@ impl Alignment {
3641
/// assert_eq!(Alignment::MIN.as_usize(), 1);
3742
/// ```
3843
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
39-
pub const MIN: Self = Self(AlignmentEnum::_Align1Shl0);
44+
pub const MIN: Self = Self::new(1).unwrap();
4045

4146
/// Returns the alignment for a type.
4247
///
@@ -92,7 +97,10 @@ impl Alignment {
9297
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
9398
#[inline]
9499
pub const fn as_usize(self) -> usize {
95-
self.0 as usize
100+
// Going through `as_nonzero` helps this be more clearly the inverse of
101+
// `new_unchecked`, letting MIR optimizations fold it away.
102+
103+
self.as_nonzero().get()
96104
}
97105

98106
/// Returns the alignment as a <code>[NonZero]<[usize]></code>.

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@
1616
scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) {
1717
let mut _5: std::ptr::NonNull<[bool; 0]>;
1818
scope 5 (inlined NonNull::<[bool; 0]>::dangling) {
19-
let mut _6: std::num::NonZero<usize>;
2019
scope 6 {
2120
scope 8 (inlined std::ptr::Alignment::as_nonzero) {
2221
}
2322
scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) {
24-
let _7: *const [bool; 0];
23+
let _6: *const [bool; 0];
2524
scope 10 {
2625
}
2726
scope 11 (inlined NonZero::<usize>::get) {
@@ -45,11 +44,8 @@
4544
StorageLive(_4);
4645
StorageLive(_5);
4746
StorageLive(_6);
48-
_6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
49-
StorageLive(_7);
50-
_7 = const {0x1 as *const [bool; 0]};
47+
_6 = const {0x1 as *const [bool; 0]};
5148
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
52-
StorageDead(_7);
5349
StorageDead(_6);
5450
_4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
5551
StorageDead(_5);

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@
1616
scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) {
1717
let mut _5: std::ptr::NonNull<[bool; 0]>;
1818
scope 5 (inlined NonNull::<[bool; 0]>::dangling) {
19-
let mut _6: std::num::NonZero<usize>;
2019
scope 6 {
2120
scope 8 (inlined std::ptr::Alignment::as_nonzero) {
2221
}
2322
scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) {
24-
let _7: *const [bool; 0];
23+
let _6: *const [bool; 0];
2524
scope 10 {
2625
}
2726
scope 11 (inlined NonZero::<usize>::get) {
@@ -45,11 +44,8 @@
4544
StorageLive(_4);
4645
StorageLive(_5);
4746
StorageLive(_6);
48-
_6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
49-
StorageLive(_7);
50-
_7 = const {0x1 as *const [bool; 0]};
47+
_6 = const {0x1 as *const [bool; 0]};
5148
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
52-
StorageDead(_7);
5349
StorageDead(_6);
5450
_4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
5551
StorageDead(_5);

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@
1616
scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) {
1717
let mut _5: std::ptr::NonNull<[bool; 0]>;
1818
scope 5 (inlined NonNull::<[bool; 0]>::dangling) {
19-
let mut _6: std::num::NonZero<usize>;
2019
scope 6 {
2120
scope 8 (inlined std::ptr::Alignment::as_nonzero) {
2221
}
2322
scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) {
24-
let _7: *const [bool; 0];
23+
let _6: *const [bool; 0];
2524
scope 10 {
2625
}
2726
scope 11 (inlined NonZero::<usize>::get) {
@@ -45,11 +44,8 @@
4544
StorageLive(_4);
4645
StorageLive(_5);
4746
StorageLive(_6);
48-
_6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
49-
StorageLive(_7);
50-
_7 = const {0x1 as *const [bool; 0]};
47+
_6 = const {0x1 as *const [bool; 0]};
5148
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
52-
StorageDead(_7);
5349
StorageDead(_6);
5450
_4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
5551
StorageDead(_5);

tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@
1616
scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) {
1717
let mut _5: std::ptr::NonNull<[bool; 0]>;
1818
scope 5 (inlined NonNull::<[bool; 0]>::dangling) {
19-
let mut _6: std::num::NonZero<usize>;
2019
scope 6 {
2120
scope 8 (inlined std::ptr::Alignment::as_nonzero) {
2221
}
2322
scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) {
24-
let _7: *const [bool; 0];
23+
let _6: *const [bool; 0];
2524
scope 10 {
2625
}
2726
scope 11 (inlined NonZero::<usize>::get) {
@@ -45,11 +44,8 @@
4544
StorageLive(_4);
4645
StorageLive(_5);
4746
StorageLive(_6);
48-
_6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
49-
StorageLive(_7);
50-
_7 = const {0x1 as *const [bool; 0]};
47+
_6 = const {0x1 as *const [bool; 0]};
5148
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
52-
StorageDead(_7);
5349
StorageDead(_6);
5450
_4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
5551
StorageDead(_5);

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

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@
1616
scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) {
1717
let mut _5: std::ptr::NonNull<[bool; 0]>;
1818
scope 5 (inlined NonNull::<[bool; 0]>::dangling) {
19-
let mut _6: std::num::NonZero<usize>;
2019
scope 6 {
2120
scope 8 (inlined std::ptr::Alignment::as_nonzero) {
2221
}
2322
scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) {
24-
let _7: *const [bool; 0];
23+
let _6: *const [bool; 0];
2524
scope 10 {
2625
}
2726
scope 11 (inlined NonZero::<usize>::get) {
@@ -45,14 +44,10 @@
4544
StorageLive(_4);
4645
StorageLive(_5);
4746
StorageLive(_6);
48-
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as std::num::NonZero<usize> (Transmute);
49-
+ _6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
50-
StorageLive(_7);
51-
- _7 = copy _6 as *const [bool; 0] (Transmute);
52-
- _5 = NonNull::<[bool; 0]> { pointer: copy _7 };
53-
+ _7 = const {0x1 as *const [bool; 0]};
47+
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute);
48+
- _5 = NonNull::<[bool; 0]> { pointer: copy _6 };
49+
+ _6 = const {0x1 as *const [bool; 0]};
5450
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
55-
StorageDead(_7);
5651
StorageDead(_6);
5752
- _4 = std::ptr::Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
5853
+ _4 = const std::ptr::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: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@
1616
scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) {
1717
let mut _5: std::ptr::NonNull<[bool; 0]>;
1818
scope 5 (inlined NonNull::<[bool; 0]>::dangling) {
19-
let mut _6: std::num::NonZero<usize>;
2019
scope 6 {
2120
scope 8 (inlined std::ptr::Alignment::as_nonzero) {
2221
}
2322
scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) {
24-
let _7: *const [bool; 0];
23+
let _6: *const [bool; 0];
2524
scope 10 {
2625
}
2726
scope 11 (inlined NonZero::<usize>::get) {
@@ -45,14 +44,10 @@
4544
StorageLive(_4);
4645
StorageLive(_5);
4746
StorageLive(_6);
48-
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as std::num::NonZero<usize> (Transmute);
49-
+ _6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
50-
StorageLive(_7);
51-
- _7 = copy _6 as *const [bool; 0] (Transmute);
52-
- _5 = NonNull::<[bool; 0]> { pointer: copy _7 };
53-
+ _7 = const {0x1 as *const [bool; 0]};
47+
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute);
48+
- _5 = NonNull::<[bool; 0]> { pointer: copy _6 };
49+
+ _6 = const {0x1 as *const [bool; 0]};
5450
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
55-
StorageDead(_7);
5651
StorageDead(_6);
5752
- _4 = std::ptr::Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
5853
+ _4 = const std::ptr::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: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@
1616
scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) {
1717
let mut _5: std::ptr::NonNull<[bool; 0]>;
1818
scope 5 (inlined NonNull::<[bool; 0]>::dangling) {
19-
let mut _6: std::num::NonZero<usize>;
2019
scope 6 {
2120
scope 8 (inlined std::ptr::Alignment::as_nonzero) {
2221
}
2322
scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) {
24-
let _7: *const [bool; 0];
23+
let _6: *const [bool; 0];
2524
scope 10 {
2625
}
2726
scope 11 (inlined NonZero::<usize>::get) {
@@ -45,14 +44,10 @@
4544
StorageLive(_4);
4645
StorageLive(_5);
4746
StorageLive(_6);
48-
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as std::num::NonZero<usize> (Transmute);
49-
+ _6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
50-
StorageLive(_7);
51-
- _7 = copy _6 as *const [bool; 0] (Transmute);
52-
- _5 = NonNull::<[bool; 0]> { pointer: copy _7 };
53-
+ _7 = const {0x1 as *const [bool; 0]};
47+
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute);
48+
- _5 = NonNull::<[bool; 0]> { pointer: copy _6 };
49+
+ _6 = const {0x1 as *const [bool; 0]};
5450
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
55-
StorageDead(_7);
5651
StorageDead(_6);
5752
- _4 = std::ptr::Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
5853
+ _4 = const std::ptr::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: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@
1616
scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) {
1717
let mut _5: std::ptr::NonNull<[bool; 0]>;
1818
scope 5 (inlined NonNull::<[bool; 0]>::dangling) {
19-
let mut _6: std::num::NonZero<usize>;
2019
scope 6 {
2120
scope 8 (inlined std::ptr::Alignment::as_nonzero) {
2221
}
2322
scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) {
24-
let _7: *const [bool; 0];
23+
let _6: *const [bool; 0];
2524
scope 10 {
2625
}
2726
scope 11 (inlined NonZero::<usize>::get) {
@@ -45,14 +44,10 @@
4544
StorageLive(_4);
4645
StorageLive(_5);
4746
StorageLive(_6);
48-
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as std::num::NonZero<usize> (Transmute);
49-
+ _6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
50-
StorageLive(_7);
51-
- _7 = copy _6 as *const [bool; 0] (Transmute);
52-
- _5 = NonNull::<[bool; 0]> { pointer: copy _7 };
53-
+ _7 = const {0x1 as *const [bool; 0]};
47+
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute);
48+
- _5 = NonNull::<[bool; 0]> { pointer: copy _6 };
49+
+ _6 = const {0x1 as *const [bool; 0]};
5450
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
55-
StorageDead(_7);
5651
StorageDead(_6);
5752
- _4 = std::ptr::Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
5853
+ _4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};

0 commit comments

Comments
 (0)