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: [email protected]
        ReportedBy: [email protected]
                CC: [email protected]


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@GOTPCREL(%rip), %rax
        movb    (%rax), %cl
        andb    $1, %cl
        movzbl  %cl, %eax
        cmpq    $0, %rax
        je      .LBB0_2
        movq    n@GOTPCREL(%rip), %rax
        movl    (%rax), %ecx
        imull   (%rax), %ecx
        imull   (%rax), %ecx
        imull   (%rax), %ecx
        movl    %ecx, %edi
        callq   _Z1fi@PLT
.LBB0_2:
        callq   _Z1gv@PLT
        popq    %rax
        ret

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

_Z1hv:
        pushq   %rax
        movq    b@GOTPCREL(%rip), %rax
        testb   $1, (%rax)
        je      .LBB0_2
        movq    n@GOTPCREL(%rip), %rax
        movl    (%rax), %eax
        movl    %eax, %edi
        imull   %edi, %edi
        imull   %eax, %edi
        imull   %eax, %edi
        callq   _Z1fi@PLT
.LBB0_2:
        popq    %rax
        jmp     _Z1gv@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.
_______________________________________________
LLVMbugs mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/llvmbugs

Reply via email to