https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65265
Bug ID: 65265 Summary: [SH] Use rotcl to logically and/or comparison results 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*-*-* The following code: int test (int a, int b, int c, int d) { return (a == b) & (b == 0) & (c != 0); } currently compiles to: tst r5,r5 movt r1 tst r6,r6 mov #-1,r0 negc r0,r0 cmp/eq r5,r4 and r0,r1 movt r0 rts and r1,r0 which is slightly better as: tst r5,r5 movt r0 tst r6,r6 rotcl r0 cmp/eq r4,r5 rotcl r0 cmp/eq #5,r0 rts movt r0 Logical ANDs/ORs of comparison results can be done by first collecting all comparison results in one register and then testing/comparing that register. Negated T bit stores (negc above) can be handled by adjusting the final comparison/bit test constant, or by negating all bits using a not reg,reg insn. It seems this is worth doing for 3 or more comparisons. Since regs are 32 bits, up to 32 comparison results can be collected that way, although it's probably better to insert conditional branches in between to short circuit the thing. Combine already tries out things like: Failed to match this instruction: (set (reg:SI 179) (and:SI (ne:SI (reg:SI 6 r6 [ c ]) (const_int 0 [0])) (eq:SI (reg:SI 5 r5 [ b ]) (const_int 0 [0])))) Which can be handled rather easily using treg_set_expr: [(set (match_operand:SI 0 "arith_reg_dest") (and:SI (match_operand 1 "treg_set_expr") (match_operand 2 "treg_set_expr")))] .. which will make combine try out longer and/ior chains like (and:SI (and:SI (match_operand 1 "treg_set_expr") (match_operand 2 "treg_set_expr") (match_operand 3 "treg_set_expr")) and so on. This can be captured using a special predicate and then smashed in split1 into the respective insn sequence.