while(__builtin_expect(len != 0, 1)) below produces a slower
loop than without the __builtin_expect().   It adds a jmp
which makes an extra testl instruction needed in the loop.

__builtin_expect(..., 1) and __builtin_expect(..., 0)
produce the same code in this case, maybe that is relevant.

-fprofile-arcs/-fbranch-probabilities are OK, they produce
the same code as without __builtin_expect().

bash$ cat sum.c
#ifdef E
#define EXPECT(c) __builtin_expect(c, E)
#else
#define EXPECT(c) (c)
#endif

unsigned __attribute__((fastcall, noinline))
Sum(const unsigned *data, unsigned len)
{
  unsigned s = 0;
  for (; EXPECT(len != 0); len--)
    s += *data++;
  return s;
}

#ifdef TEST
unsigned data[65536];
int main(void)
{
  unsigned i;
  for (i = 0; i < 1000; i++)
    Sum(data, sizeof (data) / sizeof (*data));
  return 0;
}
#endif /* TEST */

bash$ : without __builtin_expect:
bash$ gcc -S -O -fomit-frame-pointer sum.c -o- | sed -ne '/Sum:/,/ret/p'
Sum:
        movl    $0, %eax
        testl   %edx, %edx
        je      .L4
        movl    $0, %eax
.L5:
        addl    (%ecx), %eax
        addl    $4, %ecx
        decl    %edx
        jne     .L5
.L4:
        ret

bash$ : with __builtin_expect:
bash$ gcc -DE=1 -S -O -fomit-frame-pointer sum.c -o- | sed -ne '/Sum:/,/ret/p'
Sum:
        movl    $0, %eax
        jmp     .L2
.L3:
        addl    -4(%ecx), %eax
        decl    %edx
.L2:
        addl    $4, %ecx
        testl   %edx, %edx
        jne     .L3
        ret

bash$ : time without __builtin_expect:
bash$ gcc -DTEST -O -fomit-frame-pointer sum.c && time ./a.out
real    0m0.172s
user    0m0.168s
sys     0m0.001s

bash$ : time with __builtin_expect:
bash$ gcc -DE=1 -DTEST -O -fomit-frame-pointer sum.c && time ./a.out
real    0m0.254s
user    0m0.252s
sys     0m0.001s


-- 
           Summary: while(__builtin_expect()) pessimizes loop
           Product: gcc
           Version: 4.1.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: other
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: h dot b dot furuseth at usit dot uio dot no
 GCC build triplet: i686-pc-linux-gnu
  GCC host triplet: i686-pc-linux-gnu
GCC target triplet: i686-pc-linux-gnu


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30055

Reply via email to