https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63321
Oleg Endo <olegendo at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Last reconfirmed| |2014-12-02 CC| |segher at gcc dot gnu.org Ever confirmed|0 |1 --- Comment #1 from Oleg Endo <olegendo at gcc dot gnu.org> --- Combine recently received some updates which improve handling of multiple-set parallel insns. Applying the following: Index: gcc/config/sh/sh.md =================================================================== --- gcc/config/sh/sh.md (revision 218250) +++ gcc/config/sh/sh.md (working copy) @@ -5156,6 +5156,12 @@ DONE; } + if (operands[2] == const1_rtx) + { + emit_insn (gen_shlr (operands[0], operands[1])); + DONE; + } + /* If the lshrsi3_* insn is going to clobber the T_REG it must be expanded here. */ if (CONST_INT_P (operands[2]) will always expand the multiple-set shlr insn and combine will be able to utilize this. The test case void test2_1 (unsigned int x, unsigned int* y) { y[0] = x >> 1; y[1] = x & 1; } will compile to the desired sequence: shlr r4 movt r1 mov.l r4,@r5 rts mov.l r1,@(4,r5) However, in the context of e.g. pointer tagging use cases, the tag bits are usually used with conditional branches: void test2_2 (unsigned int x, unsigned int* y) { unsigned int xx = x >> 1; unsigned int p = x & 1; if (p != 0) foo (xx); } Combine can't handle this, because the shift and test insns end up in different basic blocks. Moreover, in order to utilize the shlr insn, the branch condition needs to be inverted. This could be done by emitting a movt-tst sequence and let the sh_treg_combine pass optimize it away by inverting the branch condition.