https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64345
Bug ID: 64345 Summary: [SH] Improve single bit extraction Product: gcc Version: 5.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: olegendo at gcc dot gnu.org Target: sh*-*-* Single bit extractions can be done through the T bit. Some examples: unsigned int test0 (unsigned int x) { return ((x >> 4) ^ 1) & 1; } unsigned int test1 (unsigned int x) { return ((x >> 4) & 1) ^ 1; } unsigned int test2 (unsigned int x) { return ~(x >> 4) & 1; } now: mov r4,r0 shlr2 r0 shlr2 r0 xor #1,r0 and #1,r0 non-sh2a: mov r4,r0 tst #(1<<4),r0 movt r0 sh2a: bld #4,r4 movrt r0 unsigned int test3 (unsigned int x) { return ((~x >> 4) & 1); } now: not r4,r4 mov r4,r0 shlr2 r0 shlr2 r0 rts and #1,r0 non-sh2a: mov r4,r0 tst #(1<<4),r0 movt r0 sh2a: bld #4,r4 movrt r0 unsigned int test4 (unsigned int x) { return (x >> 4) & 1; } now: mov r4,r0 shlr2 r0 shlr2 r0 and #1,r0 non-sh2: not r4,r0 tst #(1<<4),r0 movt r0 sh2a (1): mov r4,r0 tst #(1<<4),r0 movrt r0 sh2a (2) bld #4,r4 movt r0 This can be realized by implementing zero_extract combine patterns such as: set (reg:SI 170 [ D.1727 ]) (zero_extract:SI (xor:SI (reg:SI 4 r4 [ x ]) (const_int 16 [0x10])) (const_int 1 [0x1]) (const_int 4 [0x4]))) Using the recently added support for multi-set patterns in combine, the T bit contents can be described exactly, instead of simply T bit clobbers. If the bit position is 0...7 the SH2A bld insn can be used. For higher bit positions it might be better to load a constant and use the tst rm,rn insn. Alternatively the reg can be shifted right via shlr8 and shlr16 before the tst insn. However, in this case it's probably better to use a shld + and #1,r0 sequence, if dynamic shifts are available. Although that forces the result value into r0, which might need to be moved into another reg. With the tst insn, r0 is used only as a temporary scratch register.