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.

Reply via email to