The following code is miscompiled by the current clang trunk (and 3.7.x) on x86_64-linux-gnu at -O2 and -O3 in both 32-bit and 64-bit modes. This is a regression from 3.6.x. $ clang-trunk -v clang version 3.9.0 (trunk 258416) Target: x86_64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/local/tools/bin Found candidate GCC installation: /usr/lib/gcc/i686-linux-gnu/4.9 Found candidate GCC installation: /usr/lib/gcc/i686-linux-gnu/4.9.3 Found candidate GCC installation: /usr/lib/gcc/i686-linux-gnu/5.2.1 Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.4 Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.4.7 Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.6 Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.6.4 Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.7 Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.7.3 Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.8 Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.8.4 Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9 Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9.3 Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/5.2.1 Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9 Candidate multilib: .;@m64 Candidate multilib: 32;@m32 Candidate multilib: x32;@mx32 Selected multilib: .;@m64 $ $ clang-trunk -Os small.c; ./a.out $ clang-3.6 -O2 small.c; ./a.out $ $ clang-trunk -O2 small.c $ ./a.out 0 $ clang-3.7 -O2 small.c $ ./a.out 0 $ ------------------------------------ int printf (const char *, ...); int a = 8, b, d, e, f; short c; void fn1 () { char g = c, h = c = c | 195; if (d) ; if ((!a && c > d) || c < d) for (g = 0; g < 20; g++) e ^= f; a = 2 & g; if (h >= c || g) printf ("%d\n", b); if (a) { fn1 (); for (;;) ; } } int main () { fn1 (); return 0; }
Bisection points to r231507: Author: Matthias Braun <matze@braunis.de> Date: Fri Mar 6 19:49:10 2015 +0000 DAGCombiner: Canonicalize select(and/or,x,y) depending on target. This is based on the following equivalences: select(C0 & C1, X, Y) <=> select(C0, select(C1, X, Y), Y) select(C0 | C1, X, Y) <=> select(C0, X, select(C1, X, Y)) Many target cannot perform and/or on the CPU flags and therefore the right side should be choosen to avoid materializign the i1 flags in an integer register. If the target can perform this operation efficiently we normalize to the left form. Matthias, can you please take a look?
The problem turned out to be unrelated to my commit. Fixed in r258729. +Ahmed who may be interested in a post-commit review (maybe there's a more elegant way to fix it).