Hi! The following testcase ICEs on aarch64-linux, because combiner matches the (insn 25 24 26 2 (set (reg:DI 114) (rotatert:DI (reg:DI 115 [ d ]) (subreg:QI (neg:SI (and:SI (reg:SI 112) (const_int 65535 [0xffff]))) 0))) "pr84845.c":8 664 {*aarch64_reg_di3_neg_mask2} (expr_list:REG_DEAD (reg:SI 112) (expr_list:REG_DEAD (reg:DI 115 [ d ]) (nil)))) pattern, but what we split it into doesn't recog, because there are just patterns that use the same mode for the shift/rotate as for AND and use proper (match_operand 3 "const_int_operand" "n"))])))] "(~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0" and then there is another pattern for the mixed DImode shift/rotate and SImode mask, but that one uses for the mask instead (match_operand 3 "aarch64_shift_imm_di" "Usd"))])))] "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode)-1)) == 0)" which due to the predicate (and constraint) never matches.
The following patch fixes that bug (uses "const_int_operand" "n" like in similar patterns), also fixes another bug in the *aarch64_reg_<mode>3_neg_mask2 splitter, where if it isn't split before reload it would emit invalid negation (SImode negation from SImode input into DImode output). And the last change is that I find these patterns to be misnamed, the most important on these patterns is that they are shifts/rotates, but the names of the pattern don't indicate that at all; some other patterns around do indicate that with <optab>_ part, which the patch changes them to, and one pattern has that part in inconsistent spot to the others. Bootstrapped/regtested on aarch64-linux, ok for trunk? 2018-03-14 Jakub Jelinek <ja...@redhat.com> PR target/84845 * config/aarch64/aarch64.md (*aarch64_reg_<mode>3_neg_mask2): Rename to ... (*aarch64_<optab>_reg_<mode>3_neg_mask2): ... this. If pseudos can't be created, use lowpart_subreg of operands[0] rather than operands[0] itself. (*aarch64_reg_<mode>3_minus_mask): Rename to ... (*aarch64_ashl_reg_<mode>3_minus_mask): ... this. (*aarch64_<optab>_reg_di3_mask2): Use const_int_operand predicate and n constraint instead of aarch64_shift_imm_di and Usd. (*aarch64_reg_<optab>_minus<mode>3): Rename to ... (*aarch64_<optab>_reg_minus<mode>3): ... this. * gcc.c-torture/compile/pr84845.c: New test. --- gcc/config/aarch64/aarch64.md.jj 2018-03-13 00:38:26.000000000 +0100 +++ gcc/config/aarch64/aarch64.md 2018-03-13 18:33:47.657719021 +0100 @@ -4262,7 +4262,7 @@ (define_insn "*aarch64_<optab>_reg_<mode [(set_attr "type" "shift_reg")] ) -(define_insn_and_split "*aarch64_reg_<mode>3_neg_mask2" +(define_insn_and_split "*aarch64_<optab>_reg_<mode>3_neg_mask2" [(set (match_operand:GPI 0 "register_operand" "=&r") (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r") @@ -4275,7 +4275,7 @@ (define_insn_and_split "*aarch64_reg_<mo [(const_int 0)] { rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode) - : operands[0]); + : lowpart_subreg (SImode, operands[0], <MODE>mode)); emit_insn (gen_negsi2 (tmp, operands[2])); rtx and_op = gen_rtx_AND (SImode, tmp, operands[3]); @@ -4286,7 +4286,7 @@ (define_insn_and_split "*aarch64_reg_<mo } ) -(define_insn_and_split "*aarch64_reg_<mode>3_minus_mask" +(define_insn_and_split "*aarch64_ashl_reg_<mode>3_minus_mask" [(set (match_operand:GPI 0 "register_operand" "=&r") (ashift:GPI (match_operand:GPI 1 "register_operand" "r") @@ -4320,8 +4320,8 @@ (define_insn "*aarch64_<optab>_reg_di3_m (match_operand:DI 1 "register_operand" "r") (match_operator 4 "subreg_lowpart_operator" [(and:SI (match_operand:SI 2 "register_operand" "r") - (match_operand 3 "aarch64_shift_imm_di" "Usd"))])))] - "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode)-1)) == 0)" + (match_operand 3 "const_int_operand" "n"))])))] + "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode) - 1)) == 0)" { rtx xop[3]; xop[0] = operands[0]; @@ -4333,7 +4333,7 @@ (define_insn "*aarch64_<optab>_reg_di3_m [(set_attr "type" "shift_reg")] ) -(define_insn_and_split "*aarch64_reg_<optab>_minus<mode>3" +(define_insn_and_split "*aarch64_<optab>_reg_minus<mode>3" [(set (match_operand:GPI 0 "register_operand" "=&r") (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r") --- gcc/testsuite/gcc.c-torture/compile/pr84845.c.jj 2018-03-13 18:42:46.841004726 +0100 +++ gcc/testsuite/gcc.c-torture/compile/pr84845.c 2018-03-13 18:42:16.491988632 +0100 @@ -0,0 +1,12 @@ +/* PR target/84845 */ + +int a, b, c; +unsigned long d; + +void +foo (void) +{ + b = -1; + b <<= c >= 0; + d = d << (63 & (short)-b) | d >> (63 & -(short)-b); +} Jakub