Created attachment 23127 [details] 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
A recent 4.6 snapshot shows the same issue .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 xorl %eax, %eax testl %edx, %edx jne .L10 .L7: addq $8, %rsp .cfi_remember_state .cfi_def_cfa_offset 8 ret .L10: .cfi_restore_state subl $1, %edx je .L7 .p2align 4,,5 call unlikelyCall() movl $1, %eax jmp .L7 .cfi_endproc .LFE5: .size test_expect2(EnumStruct const&), .-test_expect2(EnumStruct const&) .ident "GCC: (Debian 20110116-1) 4.6.0 20110116 (experimental) [trunk revision 168860]" .section .note.GNU-stack,"",@progbits
Confirmed, the C testcase works though.
This is fixed now. I don't know what fixed it.