From 49577f8f4555c6e1f140958b2f6caf714266aa8f Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sat, 26 Sep 2026 14:24:16 -0400 Subject: [PATCH] GVN transmutes of Immediate::Uninit to Immediate::Uninit --- compiler/rustc_mir_transform/src/gvn.rs | 3 ++ tests/mir-opt/const_prop/maybe_uninit.rs | 7 ++++ ...maybe_uninit.u8_array_assume_init.GVN.diff | 36 +++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 tests/mir-opt/const_prop/maybe_uninit.u8_array_assume_init.GVN.diff diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 81a41be1c62da..b5fa022a527e5 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -725,6 +725,9 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { } CastKind::Transmute | CastKind::Subtype => { let value = self.eval_to_const(value)?; + if value.is_immediate_uninit() { + return Some(ImmTy::uninit(ty).into()); + } // `offset` for immediates generally only supports projections that match the // type of the immediate. However, as a HACK, we exploit that it can also do // limited transmutes: it only works between types with the same layout, and diff --git a/tests/mir-opt/const_prop/maybe_uninit.rs b/tests/mir-opt/const_prop/maybe_uninit.rs index 649fea6252216..89c395a7be5bb 100644 --- a/tests/mir-opt/const_prop/maybe_uninit.rs +++ b/tests/mir-opt/const_prop/maybe_uninit.rs @@ -8,3 +8,10 @@ pub fn u8_array() -> [MaybeUninit; 8] { // CHECK: _0 = const ; [MaybeUninit::uninit(); 8] } + +// EMIT_MIR maybe_uninit.u8_array_assume_init.GVN.diff +pub fn u8_array_assume_init() -> [MaybeUninit; 8] { + // CHECK: fn u8_array_assume_init( + // CHECK: _0 = const ; + unsafe { MaybeUninit::uninit().assume_init() } +} diff --git a/tests/mir-opt/const_prop/maybe_uninit.u8_array_assume_init.GVN.diff b/tests/mir-opt/const_prop/maybe_uninit.u8_array_assume_init.GVN.diff new file mode 100644 index 0000000000000..e0c4af329fadc --- /dev/null +++ b/tests/mir-opt/const_prop/maybe_uninit.u8_array_assume_init.GVN.diff @@ -0,0 +1,36 @@ +- // MIR for `u8_array_assume_init` before GVN ++ // MIR for `u8_array_assume_init` after GVN + + fn u8_array_assume_init() -> [MaybeUninit; 8] { + let mut _0: [std::mem::MaybeUninit; 8]; + let mut _1: std::mem::MaybeUninit<[std::mem::MaybeUninit; 8]>; + scope 1 (inlined MaybeUninit::<[MaybeUninit; 8]>::uninit) { + } + scope 2 (inlined #[track_caller] MaybeUninit::<[MaybeUninit; 8]>::assume_init) { + scope 3 (inlined transmute_neo::; 8]>, [MaybeUninit; 8]>) { + } + } + + bb0: { + StorageLive(_1); +- _1 = MaybeUninit::<[MaybeUninit; 8]> { uninit: const () }; ++ _1 = const ; + goto -> bb1; + } + + bb1: { +- _0 = copy _1 as [std::mem::MaybeUninit; 8] (Transmute); ++ _0 = const ; + StorageDead(_1); + return; + } ++ } ++ ++ ALLOC0 (size: 8, align: 1) { ++ __ __ __ __ __ __ __ __ │ ░░░░░░░░ ++ } ++ ++ ALLOC1 (size: 8, align: 1) { ++ __ __ __ __ __ __ __ __ │ ░░░░░░░░ + } +