https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109866
--- Comment #1 from Uroš Bizjak <ubizjak at gmail dot com> --- (In reply to Andrew Pinski from comment #0) > Take: > ``` > int g(void); int h(void); int t(void); > int f(int a, int b) > { > int c = a - b; > if(c == 0) > return g(); > if (c > 0) > return h(); > return t(); > } > ``` > This is reduced from bzip2 in spec 2006, though I am not so sure any more. > On x86_64 GCC produces: > ``` > subl %esi, %edi > testl %edi, %edi > je .L5 > jle .L3 > jmp h() > .L3: > jmp t() > .L5: > jmp g() > ``` > But GCC should produce (likes clang/LLVM does): > ``` > cmpl %esi, %edi > je .L5 > jle .L3 > jmp h() > .L3: > jmp t() > .L5: > jmp g() > ``` > > Note a similar thing happens with aarch64 target too. These two assemblies are not equal as demonstrated by the following test: --cut here-- #include <stdio.h> _Bool __attribute__((noinline)) foo (int a, int b) { _Bool r; int tmp; asm ("subl %3, %0; testl %0, %0" : "=r"(tmp), "=@cc" "le"(r) : "0"(a), "r"(b)); return r; } _Bool __attribute__((noinline)) bar (int a, int b) { _Bool r; asm ("cmpl %2, %1" : "=@cc" "le"(r) : "r"(a), "r"(b)); return r; } int main () { int a, b; _Bool ra, rb; a = 0x80000000, b = 0x40000000; ra = foo (a, b); rb = bar (a, b); printf ("%i %i\n", ra, rb); return 0; } --cut here-- $ ./a.out 0 1 The difference is in handling of overflow flag.