diff options
| author | Scott McMurray <scottmcm@users.noreply.github.com> | 2025-02-23 23:18:04 -0800 |
|---|---|---|
| committer | Scott McMurray <scottmcm@users.noreply.github.com> | 2025-02-23 23:18:04 -0800 |
| commit | 23c6b93de8fdee21f50bfd20b8e9a30f24234fbe (patch) | |
| tree | 4fe49307f385949cd89381fd0589899de9305872 | |
| parent | a18bd8acfc32dbfbbe150cd52eecf24e67fb69b6 (diff) | |
| download | rust-23c6b93de8fdee21f50bfd20b8e9a30f24234fbe.tar.gz rust-23c6b93de8fdee21f50bfd20b8e9a30f24234fbe.zip | |
Don't re-`assume` in `transmute`s that don't change niches
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 7 | ||||
| -rw-r--r-- | tests/codegen/intrinsics/transmute.rs | 25 |
2 files changed, 32 insertions, 0 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index daa4fa90ed7..de3cd27c943 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -386,6 +386,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ) -> Bx::Value { assert_eq!(from_scalar.size(self.cx), to_scalar.size(self.cx)); + // While optimizations will remove no-op transmutes, they might still be + // there in debug or things that aren't no-op in MIR because they change + // the Rust type but not the underlying layout/niche. + if from_scalar == to_scalar && from_backend_ty == to_backend_ty { + return imm; + } + use abi::Primitive::*; imm = bx.from_immediate(imm); diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs index ff297b27065..4849b88c09c 100644 --- a/tests/codegen/intrinsics/transmute.rs +++ b/tests/codegen/intrinsics/transmute.rs @@ -10,6 +10,7 @@ use std::intrinsics::mir::*; use std::intrinsics::{transmute, transmute_unchecked}; use std::mem::MaybeUninit; +use std::num::NonZero; // FIXME(LLVM18REMOVED): `trunc nuw` doesn't exist in LLVM 18, so once we no // longer support it the optional flag checks can be changed to required. @@ -470,3 +471,27 @@ pub unsafe fn check_from_overalign(x: HighAlignScalar) -> u64 { // CHECK: ret i64 %[[VAL]] transmute(x) } + +#[repr(transparent)] +struct Level1(std::num::NonZero<u32>); +#[repr(transparent)] +struct Level2(Level1); +#[repr(transparent)] +struct Level3(Level2); + +// CHECK-LABEL: @repeatedly_transparent_transmute +// CHECK-SAME: (i32{{.+}}%[[ARG:[^)]+]]) +#[no_mangle] +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub unsafe fn repeatedly_transparent_transmute(x: NonZero<u32>) -> Level3 { + // CHECK: start + // CHECK-NEXT: ret i32 %[[ARG]] + mir! { + { + let A = CastTransmute::<NonZero<u32>, Level1>(x); + let B = CastTransmute::<Level1, Level2>(A); + RET = CastTransmute::<Level2, Level3>(B); + Return() + } + } +} |
