http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47466
Summary: c++ __builtin_expect() regression
Product: gcc
Version: 4.5.2
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: middle-end
AssignedTo: [email protected]
ReportedBy: [email protected]
Created attachment 23127
--> http://gcc.gnu.org/bugzilla/attachment.cgi?id=23127
test case
This is a followup from http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42233
While the example given there now works, a slightly different example leads to
the same problem: the "unlikely" path is favored by the compiler (the likely
case will branch).
$ cat foo.cpp
struct EnumStruct {
enum Enum { ONE, TWO, THREE };
char e;
EnumStruct(Enum _e) : e(_e) {}
operator Enum() const { return (Enum)e; }
};
extern void unlikelyCall();
#define unlikely(x) __builtin_expect(!!(x), 0)
int test_expect(const EnumStruct& s) {
if (unlikely(s != EnumStruct::ONE && s != EnumStruct::TWO)) {
unlikelyCall();
return 1;
}
return 0;
}
int test_expect2(const EnumStruct& s) {
if (unlikely(s != EnumStruct::ONE) &&
unlikely(s != EnumStruct::TWO)) {
unlikelyCall();
return 1;
}
return 0;
}
$ g++45 -O3 -S -o foo.S foo.cpp
$ cat foo.S | c++filt
.file "foo.cpp"
.text
.p2align 4,,15
.globl test_expect(EnumStruct const&)
.type test_expect(EnumStruct const&), @function
test_expect(EnumStruct const&):
.LFB4:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movsbl (%rdi), %edx
xorl %eax, %eax
testl %edx, %edx
je .L2
cmpl $1, %edx
je .L2
call unlikelyCall()
movl $1, %eax
.L2:
addq $8, %rsp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE4:
.size test_expect(EnumStruct const&), .-test_expect(EnumStruct const&)
.p2align 4,,15
.globl test_expect2(EnumStruct const&)
.type test_expect2(EnumStruct const&), @function
test_expect2(EnumStruct const&):
.LFB5:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movsbl (%rdi), %edx
testl %edx, %edx
jne .L10
xorl %eax, %eax
.L7:
addq $8, %rsp
.cfi_remember_state
.cfi_def_cfa_offset 8
ret
.L10:
.cfi_restore_state
xorl %eax, %eax
subl $1, %edx
je .L7
call unlikelyCall()
movl $1, %eax
jmp .L7
.cfi_endproc
.LFE5:
.size test_expect2(EnumStruct const&), .-test_expect2(EnumStruct const&)
.ident "GCC: (GNU) .5.2 20100819 (prerelease)"
Same symptom as bug 42233. The unlikely path is favored and breaking the
"unlilkely(foo && bar)" into "unlikely(foo) && unlikely(bar)" works around the
problem.
I verified that this example leads to the likely path being favored with gcc
4.1.2 from CentOS, 4.2.1 from FreeBSD. gcc 4.3 seems to have the same problem