Hi!

Unlike x86, where the last operand of vector by scalar shift is DImode for
V[248]DImode shifts, on aarch64 they seem to be SImode.
vect_recog_rotate_pattern when the rotate amount is not constant casts the
amount to the element type of the vector, so for V[248]DImode vectors to
DImode, but then we ICE during expand_shift_1 because such argument doesn't
satisfy the predicate and can't be widened to it.

The following patch fixes it by special casing vector by scalar shifts
when adding patterns for rotates, in that case we punt if the operand isn't
INTEGER_CST or external_def, and the patch just keeps using the type of the
amount operand the rotate had for the shifts too.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2019-12-10  Jakub Jelinek  <ja...@redhat.com>

        PR target/92723
        * tree-vect-patterns.c (vect_recog_rotate_pattern): If vector x vector
        shifts aren't supported and rotate amount is SSA_NAME, use its type
        rather than first operand's type for the shift amounts.

        * gcc.dg/vect/pr92723.c: New test.

--- gcc/tree-vect-patterns.c.jj 2019-12-09 11:12:29.983288823 +0100
+++ gcc/tree-vect-patterns.c    2019-12-10 16:30:59.922177911 +0100
@@ -2242,6 +2242,7 @@ vect_recog_rotate_pattern (stmt_vec_info
   optab optab1, optab2;
   edge ext_def = NULL;
   bool bswap16_p = false;
+  bool scalar_shift_p = false;
 
   if (is_gimple_assign (last_stmt))
     {
@@ -2420,6 +2421,7 @@ vect_recog_rotate_pattern (stmt_vec_info
          || !optab2
          || optab_handler (optab2, TYPE_MODE (vectype)) == CODE_FOR_nothing)
        return NULL;
+      scalar_shift_p = true;
     }
 
   *type_out = vectype;
@@ -2439,7 +2441,8 @@ vect_recog_rotate_pattern (stmt_vec_info
   def = NULL_TREE;
   scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
   if (TREE_CODE (oprnd1) == INTEGER_CST
-      || TYPE_MODE (TREE_TYPE (oprnd1)) == mode)
+      || TYPE_MODE (TREE_TYPE (oprnd1)) == mode
+      || scalar_shift_p)
     def = oprnd1;
   else if (def_stmt && gimple_assign_cast_p (def_stmt))
     {
--- gcc/testsuite/gcc.dg/vect/pr92723.c.jj      2019-12-10 16:37:09.924375698 
+0100
+++ gcc/testsuite/gcc.dg/vect/pr92723.c 2019-12-10 16:37:21.823189103 +0100
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+
+void
+foo (unsigned long long *x, unsigned long long *y, int z)
+{
+  int i;
+  for (i = 0; i < 1024; i++)
+    x[i] = (y[i] >> z) | (y[i] << (-z & (__SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 
1)));
+}

        Jakub

Reply via email to