https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69569
Bug ID: 69569 Summary: unnecessary branches on an if followed by a switch Product: gcc Version: 6.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: rtl-optimization Assignee: unassigned at gcc dot gnu.org Reporter: msebor at gcc dot gnu.org Target Milestone: --- While investigating the target-specific bug 37262 we noticed a target-independent optimization opportunity for code like the following where GCC emits an unnecessary branch for code like that below: int foo (); int baz (int i) { if (i < 3) switch (i) { case 0: case 1: break; case 2: return foo (); } return 77; } For instance, in the powerpc64le code, when the first branch is taken it's immediately followed by another branch. The second branch could be eliminated. baz: .LCF1: 0: addis 2,12,.TOC.-.LCF1@ha addi 2,2,.TOC.-.LCF1@l cmpwi 7,3,2 ble 7,.L17 .L12: li 3,77 blr .L17: bne 7,.L12 mflr 0 std 0,16(1) stdu 1,-96(1) bl foo nop addi 1,1,96 ld 0,16(1) mtlr 0 blr Annotating the if conditional using __builtin_expect(i < 3, E) and comparing the results shows that GCC assumes the if branch not to be taken. When annotated to indicate the branch is likely to be taken (E=1), the problem becomes more obvious. Of the two consecutive branch instructions the first is clearly unnecessary. bar_1: .LCF2: 0: addis 2,12,.TOC.-.LCF2@ha addi 2,2,.TOC.-.LCF2@l cmpwi 7,3,2 bgt 7,.L29 <<< unnecessary branch beq 7,.L34 .L29: li 3,77 blr .L34: mflr 0 std 0,16(1) stdu 1,-96(1) bl foo nop addi 1,1,96 ld 0,16(1) mtlr 0 blr The x86_64 code is comparable: cmpl $2, %edi jg .L14 <<< unnecessary branch je .L19 .L14: movl $77, %eax ret .L19: xorl %eax, %eax jmp foo For comparison, Clang emits the following for x86_64: bar_1: # @bar_1 cmpl $2, %edi jne .LBB2_1 xorl %eax, %eax jmp foo # TAILCALL .LBB2_1: # %return movl $77, %eax retq