Unable to induce constant float folding via `assert_eq!(x, 0.0)`
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
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
ret
and 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 (573a01569 2025-06-12)
@rustbot label +A-codegen +T-compiler
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by compiling the one and two functions from the issue in optimized mode and compare their x86_64 assembly using the linked Godbolt reproduction. Trace the compiler codegen path for assert_unchecked(y == 0.0) and floating-point constant propagation; done means the asserted case receives the intended optimized codegen or the limitation is documented with a focused regression test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100