Skip to content

Commit 23c6b93

Browse files
committed
Don't re-assume in transmutes that don't change niches
1 parent a18bd8a commit 23c6b93

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

+7
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
386386
) -> Bx::Value {
387387
assert_eq!(from_scalar.size(self.cx), to_scalar.size(self.cx));
388388

389+
// While optimizations will remove no-op transmutes, they might still be
390+
// there in debug or things that aren't no-op in MIR because they change
391+
// the Rust type but not the underlying layout/niche.
392+
if from_scalar == to_scalar && from_backend_ty == to_backend_ty {
393+
return imm;
394+
}
395+
389396
use abi::Primitive::*;
390397
imm = bx.from_immediate(imm);
391398

tests/codegen/intrinsics/transmute.rs

+25
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use std::intrinsics::mir::*;
1111
use std::intrinsics::{transmute, transmute_unchecked};
1212
use std::mem::MaybeUninit;
13+
use std::num::NonZero;
1314

1415
// FIXME(LLVM18REMOVED): `trunc nuw` doesn't exist in LLVM 18, so once we no
1516
// 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 {
470471
// CHECK: ret i64 %[[VAL]]
471472
transmute(x)
472473
}
474+
475+
#[repr(transparent)]
476+
struct Level1(std::num::NonZero<u32>);
477+
#[repr(transparent)]
478+
struct Level2(Level1);
479+
#[repr(transparent)]
480+
struct Level3(Level2);
481+
482+
// CHECK-LABEL: @repeatedly_transparent_transmute
483+
// CHECK-SAME: (i32{{.+}}%[[ARG:[^)]+]])
484+
#[no_mangle]
485+
#[custom_mir(dialect = "runtime", phase = "optimized")]
486+
pub unsafe fn repeatedly_transparent_transmute(x: NonZero<u32>) -> Level3 {
487+
// CHECK: start
488+
// CHECK-NEXT: ret i32 %[[ARG]]
489+
mir! {
490+
{
491+
let A = CastTransmute::<NonZero<u32>, Level1>(x);
492+
let B = CastTransmute::<Level1, Level2>(A);
493+
RET = CastTransmute::<Level2, Level3>(B);
494+
Return()
495+
}
496+
}
497+
}

0 commit comments

Comments
 (0)