We should convert foo into bar (if profitable). void baz (); unsigned int foo (unsigned int a, unsigned int b) { if (a <= 7 && b <= 7) baz (); } unsigned int bar (unsigned int a, unsigned int b) { if ((a | b) <= 7) baz (); } The last SSA form looks like: ;; Function foo (foo) foo (a, b) { _Bool T.2; _Bool T.1; _Bool T.0; <bb 0>: T.0_2 = a_1 <= 7; T.1_4 = b_3 <= 7; T.2_5 = T.0_2 && T.1_4; if (T.2_5) goto <L0>; else goto <L1>; <L0>:; baz () [tail call]; <L1>:; return; } ;; Function bar (bar) bar (a, b) { unsigned int T.3; <bb 0>: T.3_3 = a_1 | b_2; if (T.3_3 <= 7) goto <L0>; else goto <L1>; <L0>:; baz () [tail call]; <L1>:; return; } On i686-pc-linux-gnu, I get: foo: cmpl $7, 4(%esp) setbe %dl cmpl $7, 8(%esp) setbe %al testb %al, %dl jne .L5 rep ; ret .p2align 4,,7 .L5: jmp baz .size foo, .-foo .p2align 4,,15 .globl bar .type bar, @function bar: movl 8(%esp), %eax orl 4(%esp), %eax cmpl $7, %eax jbe .L9 rep ; ret .p2align 4,,7 .L9: jmp baz
Confirmed but note I think this should happen late in compiling.
On PPC the former is much worse than the later: _foo: subfic r3,r3,7 li r3,0 adde r3,r3,r3 // <-- r3 == r3 <=7 on some processors this is serializing subfic r4,r4,7 li r4,0 adde r4,r4,r4 // <--r4 == r4 <=7 on some processors this is serializing and. r0,r3,r4 // r0 = r4 & r3, cr0 = (rs3 & r4) == 0 beqlr- cr0 // return if cr0(equal) is true b L_baz$stub .align 2 .globl _bar _bar: or r4,r3,r4 cmplwi cr7,r4,7 bgtlr- cr7 b L_baz$stub
I am going to implement this in my tree combiner branch. It should not be hard. Then what could be done is combineif could use the combiner to see if things reduce and use that result.
Fixed since GCC 8