-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Description
Bugzilla Link | 11096 |
Resolution | FIXED |
Resolved on | Apr 18, 2012 19:03 |
Version | trunk |
OS | Linux |
CC | @asl,@atrick |
Extended Description
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).