[LLVMbugs] [Bug 11096] New: __builtin_expect-based machine basic block reordering not working in simple cases

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Sun Oct 9 15:42:34 PDT 2011


http://llvm.org/bugs/show_bug.cgi?id=11096

           Summary: __builtin_expect-based machine basic block reordering
                    not working in simple cases
           Product: libraries
           Version: trunk
          Platform: PC
        OS/Version: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: Transformation Utilities
        AssignedTo: unassignedbugs at nondot.org
        ReportedBy: richard-llvm at metafoo.co.uk
                CC: llvmbugs at cs.uiuc.edu


Consider the following code:

void f(int n);
void g();
extern bool b;
extern int n;
void h() {
  if (__builtin_expect(b,E))
    f(n * n * n * n);
  g();
}

With g++ -DE=0 -O3 (on x86_64), we get this:

_Z1hv:
        subq    $8, %rsp
        cmpb    $0, b(%rip)
        jne     .L4
.L2:
        addq    $8, %rsp
        jmp     _Z1gv
.L4:
        movl    n(%rip), %edi
        imull   %edi, %edi
        imull   %edi, %edi
        call    _Z1fi
        jmp     .L2

With g++ -DE=1 -O3, we get this:

_Z1hv:
        subq    $8, %rsp
        cmpb    $0, b(%rip)
        je      .L2
        movl    n(%rip), %edi
        imull   %edi, %edi
        imull   %edi, %edi
        call    _Z1fi
.L2:
        addq    $8, %rsp
        jmp     _Z1gv

However, LLVM doesn't do anywhere near as well. clang++ -DE=0 -O3 produces
this:

_Z1hv:
        pushq   %rax
        movq    b at GOTPCREL(%rip), %rax
        movb    (%rax), %cl
        andb    $1, %cl
        movzbl  %cl, %eax
        cmpq    $0, %rax
        je      .LBB0_2
        movq    n at GOTPCREL(%rip), %rax
        movl    (%rax), %ecx
        imull   (%rax), %ecx
        imull   (%rax), %ecx
        imull   (%rax), %ecx
        movl    %ecx, %edi
        callq   _Z1fi at PLT
.LBB0_2:
        callq   _Z1gv at PLT
        popq    %rax
        ret

clang++ -DE=1 -O3 produces this:

_Z1hv:
        pushq   %rax
        movq    b at GOTPCREL(%rip), %rax
        testb   $1, (%rax)
        je      .LBB0_2
        movq    n at GOTPCREL(%rip), %rax
        movl    (%rax), %eax
        movl    %eax, %edi
        imull   %edi, %edi
        imull   %eax, %edi
        imull   %eax, %edi
        callq   _Z1fi at PLT
.LBB0_2:
        popq    %rax
        jmp     _Z1gv at PLT

There are lots of things which llvm has done badly here, but in particular the
__builtin_expect(b, 0) has not caused the unexpected code to be moved to the
end of the function (though it has made the test of 'b' bizarrely inefficient,
so it's not being entirely ignored).

The problem seems to be in llvm rather than in clang: the __builtin_expect is
converted to an llvm.expect.i64 (which is converted to !prof metadata).

-- 
Configure bugmail: http://llvm.org/bugs/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.



More information about the llvm-bugs mailing list