- Notifications
You must be signed in to change notification settings - Fork 13.9k
Description
I have a performance-sensitive pipeline that accepts data of a shape where some of the floating point elements are known (to me) to currently always be zero, but I don't want to remove the operations from the code lest that change in the future. I was hoping to be able to assert_eq!() my way into getting the compiler to perform constant folding on the mathematical operation but found that it does not work as expected.
A test case that reproduces the issue:
#[no_mangle] pub extern "C" fn one(x: f32, y: f32, z: f32) -> f32 { unsafe { std::hint::assert_unchecked(y == 0.0); } x*9.0 + y*8.0 + z } #[no_mangle] pub extern "C" fn two(x: f32, y: f32, z: f32) -> f32 { let y = 0.0; x*9.0 + y*8.0 + z }giving the following x86_64 (optimized) assembly:
.LCPI0_0: .long 0x41100000 .LCPI0_1: .long 0x41000000 one: vmulss xmm0, xmm0, dword ptr [rip + .LCPI0_0] vmulss xmm1, xmm1, dword ptr [rip + .LCPI0_1] vaddss xmm0, xmm0, xmm1 vaddss xmm0, xmm2, xmm0 ret .LCPI1_0: .long 0x41100000 two: vmulss xmm0, xmm0, dword ptr [rip + .LCPI1_0] vxorps xmm1, xmm1, xmm1 vaddss xmm0, xmm0, xmm1 vaddss xmm0, xmm0, xmm2 retand a link to the godbolt disassembly
I am using assert_unchecked() rather than assert_eq!() just to simplify the assembly output for diagnostic purposes, but the intent is to test whether or not the compiler can elide the mul with a "constant" zero. The codegen from one() does not benefit from the assert_unchecked(y == 0.0) call, and performs the same codegen with or without it, while the code in two() demonstrates that, in the general case, rust is able to fold away the multiplication with a constant, but that for $reasons, it currently isn't able to do so after asserting the value.
The obvious workaround would be to use something like the following:
assert_eq!(y, 0.0); let y = 0.0;Tested with 1.90.0 stable and rustc 1.89.0-nightly (573a015 2025-06-12)
@rustbot label +A-codegen +T-compiler