5

I'm toying with some algorithm in Rust (though the language doesn't really matter for my question). Consider the code:

#[no_mangle]
pub fn test(x: f32) -> f32 {
    let m = 0.;
    x + m
}

fn main() {
    test(2.);
}

It produces the following LLVM IR and corresponding x86_64 asm (optimizations enabled):

;; LLVM IR
define float @test(float %x) unnamed_addr #0 {
start:
    %0 = fadd float %x, 0.000000e+00
    ret float %0
}

;; x86_64
; test:
    xorps xmm1, xmm1
    addss xmm0, xmm1
    ret

If I change let m = 0.; to let m = -0.; the floating point addition is optimized away:

;; LLVM IR
define float @test(float returned %x) unnamed_addr #0 {
start:
    ret float %x
}

;; x86_64
; fn disappears entirely
phuclv
  • 37,963
  • 15
  • 156
  • 475
withkittens
  • 171
  • 1
  • 9
  • Consider `fn(-0.0)`. – user2357112 Jan 14 '18 at 23:43
  • 1
    so far as I can tell so far gcc allows two different compile time options, and for a simple C example of the question, with default settings similar results, change the setting and both positive and negative zero generate code other than a return. so it sounds like the rouding answer is the key, but the compiler does matter and the settings. Does rust provide compile time options for different rounding mode choices? – old_timer Jan 15 '18 at 00:02
  • didnt find a compile setting for clang that is supported, yet... – old_timer Jan 15 '18 at 00:06
  • 1
    @old_timer, from what I've read, LLVM have no means to change the rounding mode (and assume any other than default during its optimization pass), so have Rust. – withkittens Jan 15 '18 at 10:14
  • Does this answer your question? [Why does Clang optimize away x \* 1.0 but NOT x + 0.0?](https://stackoverflow.com/questions/33272994/why-does-clang-optimize-away-x-1-0-but-not-x-0-0) – Peter Cordes Jun 18 '22 at 10:14

1 Answers1

8

In the default round-to-nearest mode, that most high-level languages support exclusively, because they do not provide options to disable floating-point optimizations that become inapplicable in other modes—I assume that Rust falls in this category—, adding -0.0 happens to have no effect on any floating-point value (omitting small details about NaNs), whereas adding +0.0 has an effect on -0.0 (the result of -0.0 + (+0.0) is +0.0).

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281