rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
98.26k stars 12.71k forks source link

Missed optimization in if with constant branches #129144

Open tbillington opened 2 months ago

tbillington commented 2 months ago

I assume the following two functions behave identically, and therefore should result in the same codegen. https://godbolt.org/z/vj9ornqbG

#[no_mangle]
pub fn cast(x: bool) -> f32 {
    x as u8 as f32
}

#[no_mangle]
pub fn ifelse(x: bool) -> f32 {
    if x { 1. } else { 0. }
}

However, ifelse fails to be optimised to a cast.

cast:
        cvtsi2ss        xmm0, edi
        ret

.LCPI1_0:
        .long   0x3f800000
ifelse:
        test    edi, edi
        jne     .LBB1_1
        xorps   xmm0, xmm0
        ret
.LBB1_1:
        movss   xmm0, dword ptr [rip + .LCPI1_0]
        ret
ChayimFriedman2 commented 2 months ago

Are you sure it is faster? llvm-mca say it will be slower (506 vs 304 cycles).

ChayimFriedman2 commented 2 months ago

ifelse() is indeed slower, benchmarked with criterion. So if anything, the question should be the opposite.

ChayimFriedman2 commented 2 months ago

@rustbot label -C-bug +I-slow -needs-triage +A-LLVM +C-optimization

soooch commented 2 months ago

fwiw, filed an issue in llvm: https://github.com/llvm/llvm-project/issues/107034