http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58017
Bug ID: 58017 Summary: [SH] Use shift and test for unsigned compare Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: enhancement Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: olegendo at gcc dot gnu.org Target: sh*-*-* On SH unsigned int comparisons against some constants can be converted to shift and test sequences to potentially save one register. For example: int test_00 (unsigned int a, int b, int c) { if (a == 0 || a == 1) return 50; return 0; } compiled with -O2: mov #1,r1 cmp/hi r1,r4 // T = r4 > r1 (unsigned) bf/s .L7 mov #0,r0 rts nop .L7: rts mov #50,r0 can also be written as: shlr r4 // r4 >>= 1 tst r4,r4 // T = r4 == 0 bt .L7 mov #0,r0 rts nop .L7: rts mov #50,r0 In this case it doesn't save much, but if register pressure is high and the compared value is not used anywhere else, this can avoid using one register for the comparison constant. This is probably only going to be beneficial for right shift patterns that can be done in 1 or 2 insns and if the inverted comparison result can be handled by a following conditional branch. If the comparison constant does not fit into an imm8 it will be loaded from the constant pool: mov.l .L7,r1 cmp/hi r1,r4 bf .L3 mov #50,r0 rts nop .L3: rts mov #0,r0 .L8: .align 2 .L7: .long 65535 In this case it might always be beneficial to replace the comparison with shlr16 r4 tst r4,r4 especially if the compared reg is dead after the comparison.