Closed
Description
#[inline]
pub fn imm8(x: u32) -> u32 {
let mut out = 0u32;
out |= (x >> 0) & 0xff;
out
}
#[inline(never)]
pub fn inner(fields: u32) -> i64 {
imm8(fields).rotate_right(((fields >> 8) & 0xf) << 1) as i32 as i64
}
fn main() {
let val = inner(0xe32cf20f);
println!("{val:#x}");
}
This code normally prints 0xfffffffff0000000
but when compiled with O -C debug-assertions=on -Zmir-opt-level=2
it produces 0x0
instead. This was noticed because MIR optimization is enabled by default on the current nightly.
This is the LLVM IR for the inner
function with -C no-prepopulate-passes
. Notice how the inputs to llvm.fshr.i32
(used by rotate_right
) are 0
, which is incorrect.
define i64 @_ZN4test5inner17hd60ec7d5b1d44c39E(i32 %fields) unnamed_addr #0 {
start:
%0 = alloca i32, align 4
%_13.0 = lshr i32 %fields, 0
br label %bb3
bb3: ; preds = %start
%_10.0 = lshr i32 %fields, 8
br label %bb1
bb1: ; preds = %bb3
%_7 = and i32 %_10.0, 15
%_11.0 = shl i32 %_7, 1
br label %bb2
bb2: ; preds = %bb1
call void @llvm.lifetime.start.p0(i64 4, ptr %0)
%1 = call i32 @llvm.fshr.i32(i32 0, i32 0, i32 %_11.0)
store i32 %1, ptr %0, align 4
%_3 = load i32, ptr %0, align 4
call void @llvm.lifetime.end.p0(i64 4, ptr %0)
br label %bb4
bb4: ; preds = %bb2
%2 = sext i32 %_3 to i64
ret i64 %2
}