Hi all,

In this [8 Regression] PR we ICE because we can't recognise the insn:
(insn 59 58 43 7 (set (reg:DI 124)
        (rotatert:DI (reg:DI 125 [ c ])
            (subreg:QI (and:SI (reg:SI 128)
                    (const_int 65535 [0xffff])) 0)))

This was created by the *aarch64_reg_<mode>3_neg_mask2 splitter.
The point of these splitters and patterns is to eliminate redundant
masking of the shift (or rotate in this case) amount when shifting
by a variable amount.  For example in AND x3, x3, 0xffff ; ROR x1, x2, x3
we can eliminate the AND because the ROR instruction implicitly "MOD"s
the shift amount in X3 by 64. So this pattern is supposed to match the 
following:

(define_insn "*aarch64_<optab>_reg_di3_mask2"
  [(set (match_operand:DI 0 "register_operand" "=r")
    (SHIFT:DI
      (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"))])))]

The rotation amount mask is supposed to be operand 3 but the predicate for it 
here
is aarch64_shift_imm_di which only allows values in [0, 63], whereas we want to 
allow
any value that doesn't touch the bottom GET_MODE_BITSIZE (DImode) bits, which 
is what
the pattern predicate tests. So the predicate on operands 3 is too strict.

This patch just makes it const_int_operand since the pattern predicates has the 
correct
validation for its values. This is in line with what the 
*aarch64_reg_<mode>3_neg_mask2
and *aarch64_reg_<mode>3_minus_mask splitters accept (and they are the ones 
that generate
this insn pattern).

Bootstrapped and tested on aarch64-none-linux-gnu.

Ok for trunk?
Thanks,
Kyrill

2018-02-02  Kyrylo Tkachov  <kyrylo.tkac...@arm.com>

    PR target/84164
    * config/aarch64/aarch64.md (*aarch64_<optab>_reg_di3_mask2):
    Use const_int_operand predicate for operand 3.

2018-02-02  Kyrylo Tkachov  <kyrylo.tkac...@arm.com>

    PR target/84164
    * gcc.c-torture/compile/pr84164.c: New test.
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 04b2d203fa168bebcf6f93a13e3bd67a5998935a..eef0d1a780dd1c886e1bebb9992c552fb9d5b57c 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -4358,8 +4358,8 @@ (define_insn "*aarch64_<optab>_reg_di3_mask2"
 	  (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];
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr84164.c b/gcc/testsuite/gcc.c-torture/compile/pr84164.c
new file mode 100644
index 0000000000000000000000000000000000000000..d663fe5d6649e495f3e956e6a3bc938236a4bf91
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr84164.c
@@ -0,0 +1,17 @@
+/* PR target/84164.  */
+
+int b, d;
+unsigned long c;
+
+static inline __attribute__ ((always_inline)) void
+bar (int e)
+{
+  e += __builtin_sub_overflow_p (b, d, c);
+  c = c << ((short) ~e & 3) | c >> (-((short) ~e & 3) & 63);
+}
+
+int
+foo (void)
+{
+  bar (~1);
+}

Reply via email to