Issue 144816
Summary clang generates incorrect code with -O2
Labels clang
Assignees
Reporter Evenedric
    The code below delivers different results from clang, depending on the level of optimization. Correct behavior is:
```
> g++ mytest.cc -Wall && ./a.out
n=1 r=0.000000
```

Incorrect behavior is:
```
> g++ -O2 mytest.cc -Wall && ./a.out
n=2 r=7.000000
```

(I'm looking at the value of `n`, it should be returned as 1). Behavior is the same when running with UBSAN and ASAN (and no violations observed). I don't _think_ the code is a victim of undefined behavior.

Other information:
```
> g++ -v
Apple clang version 17.0.0 (clang-1700.0.13.3)
Target: arm64-apple-darwin24.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
```

Note that following combination of things are necessary to reproduce the bad behavior, so this is a minimal example:
  * Use `std::min()`
  * Use `atan()`
  * Don't initialize `r` in `main()`
  * `printf()` the value of `r`.

The code is below.

```cpp
#include <math.h>
#include <stdio.h>
#include <algorithm>

int Foo(double *r) {
  double a = std::min(2.0, atan(1) + 10);     // == 2
  if (a > 3) { // Should be false
    *r = 5 + a;
    return 2;
  }
  return 1;
}

int main() {
  double r;
  int n = Foo(&r);
  printf("n=%d r=%f \n", n, r);
  return 0;
}
```

Examination of the disassembled `-O2` code shows the optimizer inlined `Foo()` and chose the incorrect path:
```
_main:
0000053c  sub sp, sp, #0x20                            ; Adjust stack frame
00000540  stp x29, x30, [sp, #0x10]                    ; Save x29, x30
00000544  fmov d0, #1.00000000                         ; d0 = 1.0
00000548  bl 0x10000058c ; symbol stub for: _atan      ; d0 = atan(1.0)
0000054c  fmov d1, #10.00000000                        ; d1 = 10.0
00000550  fadd d0, d0, d1                              ; d0 = atan(1.0) + 10.0
00000554  fmov d1, #2.00000000                         ; d1 = 2.0
00000558  fminnm d0, d0, d1                            ; d0 = min(atan(1.0) + 10.0, 2.0)
0000055c  fmov d1, #5.00000000 ; d1 = 5.0
00000560  fadd d0, d0, d1                              ; d0 = min(atan(1.0) + 10.0, 2.0) + 5.0
00000564  mov w8, #0x2 ; w8 = 2
00000568  str x8, [sp] ; store the printf argument '2'
0000056c  str d0, [sp, #0x8] ; store the printf argument d0
00000570  adrp x0, 0 ; 0x100000000
00000574  add x0, x0, #0x5a4                           ; x0 = literal pool for: "n=%d r=%f \n"
00000578  bl 0x100000598 ; symbol stub for: _printf    ; Call printf
0000057c  mov w0, #0x0
00000580  ldp x29, x30, [sp, #0x10]
00000584  add sp, sp, #0x20
00000588  ret
```


_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to