]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-vect-stmts.c (vectorizable_shift): If op1 is vect_external_def in a loop and...
authorJakub Jelinek <jakub@redhat.com>
Mon, 31 Oct 2011 16:52:19 +0000 (17:52 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 31 Oct 2011 16:52:19 +0000 (17:52 +0100)
* tree-vect-stmts.c (vectorizable_shift): If op1 is vect_external_def
in a loop and has different type from op0, cast it to op0's type
before the loop first.  For slp give up.  Don't crash if op1_vectype
is NULL.

* gcc.dg/vshift-3.c: New test.
* gcc.dg/vshift-4.c: New test.
* gcc.dg/vshift-5.c: New test.

From-SVN: r180704

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vshift-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vshift-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vshift-5.c [new file with mode: 0644]
gcc/tree-vect-stmts.c

index 53f8878288d5d09ef2589f590484bfeccfef1580..ada5acbd16e51591632131f1df9f7a324a106446 100644 (file)
@@ -1,3 +1,10 @@
+2011-10-31  Jakub Jelinek  <jakub@redhat.com>
+
+       * tree-vect-stmts.c (vectorizable_shift): If op1 is vect_external_def
+       in a loop and has different type from op0, cast it to op0's type
+       before the loop first.  For slp give up.  Don't crash if op1_vectype
+       is NULL.
+
 2011-10-31  Paul Brook  <paul@codesourcery.com>
 
        * cgraphunit.c: Don't mark clones as static constructors.
index c3a1f0fba4349341cfcb1becc87d7e0bf3204fcd..f58934b472a769fc7cd2e1d329c023b101073111 100644 (file)
@@ -1,3 +1,9 @@
+2011-10-31  Jakub Jelinek  <jakub@redhat.com>
+
+       * gcc.dg/vshift-3.c: New test.
+       * gcc.dg/vshift-4.c: New test.
+       * gcc.dg/vshift-5.c: New test.
+
 2011-10-31  Janne Blomqvist  <jb@gcc.gnu.org>
 
        * gfortran.dg/inquire_5.f90: Update testcase to match the standard
diff --git a/gcc/testsuite/gcc.dg/vshift-3.c b/gcc/testsuite/gcc.dg/vshift-3.c
new file mode 100644 (file)
index 0000000..e62c76b
--- /dev/null
@@ -0,0 +1,136 @@
+/* { dg-do run } */
+/* { dg-options "-O3" } */
+
+#include <stdlib.h>
+
+#define N 64
+
+#ifndef TYPE1
+#define TYPE1 int
+#define TYPE2 long long
+#endif
+
+signed TYPE1 a[N], b, g[N];
+unsigned TYPE1 c[N], h[N];
+signed TYPE2 d[N], e, j[N];
+unsigned TYPE2 f[N], k[N];
+
+#ifndef S
+#define S(x) x
+#endif
+
+__attribute__((noinline)) void
+f1 (void)
+{
+  int i;
+  for (i = 0; i < N; i++)
+    g[i] = a[i] << S (b);
+}
+
+__attribute__((noinline)) void
+f2 (void)
+{
+  int i;
+  for (i = 0; i < N; i++)
+    g[i] = a[i] >> S (b);
+}
+
+__attribute__((noinline)) void
+f3 (void)
+{
+  int i;
+  for (i = 0; i < N; i++)
+    h[i] = c[i] >> S (b);
+}
+
+__attribute__((noinline)) void
+f4 (void)
+{
+  int i;
+  for (i = 0; i < N; i++)
+    j[i] = d[i] << S (e);
+}
+
+__attribute__((noinline)) void
+f5 (void)
+{
+  int i;
+  for (i = 0; i < N; i++)
+    j[i] = d[i] >> S (e);
+}
+
+__attribute__((noinline)) void
+f6 (void)
+{
+  int i;
+  for (i = 0; i < N; i++)
+    k[i] = f[i] >> S (e);
+}
+
+__attribute__((noinline)) void
+f7 (void)
+{
+  int i;
+  for (i = 0; i < N; i++)
+    j[i] = d[i] << S (b);
+}
+
+__attribute__((noinline)) void
+f8 (void)
+{
+  int i;
+  for (i = 0; i < N; i++)
+    j[i] = d[i] >> S (b);
+}
+
+__attribute__((noinline)) void
+f9 (void)
+{
+  int i;
+  for (i = 0; i < N; i++)
+    k[i] = f[i] >> S (b);
+}
+
+int
+main ()
+{
+  int i;
+  b = 7;
+  e = 12;
+  for (i = 0; i < N; i++)
+    {
+      asm ("");
+      c[i] = (random () << 1) | (random () & 1);
+      a[i] = c[i];
+      d[i] = (random () << 1) | (random () & 1);
+      d[i] |= (unsigned long long) c[i] << 32;
+      f[i] = d[i];
+    }
+  f1 ();
+  f3 ();
+  f4 ();
+  f6 ();
+  for (i = 0; i < N; i++)
+    if (g[i] != (signed TYPE1) (a[i] << S (b))
+       || h[i] != (unsigned TYPE1) (c[i] >> S (b))
+       || j[i] != (signed TYPE2) (d[i] << S (e))
+       || k[i] != (unsigned TYPE2) (f[i] >> S (e)))
+      abort ();
+  f2 ();
+  f5 ();
+  f9 ();
+  for (i = 0; i < N; i++)
+    if (g[i] != (signed TYPE1) (a[i] >> S (b))
+       || j[i] != (signed TYPE2) (d[i] >> S (e))
+       || k[i] != (unsigned TYPE2) (f[i] >> S (b)))
+      abort ();
+  f7 ();
+  for (i = 0; i < N; i++)
+    if (j[i] != (signed TYPE2) (d[i] << S (b)))
+      abort ();
+  f8 ();
+  for (i = 0; i < N; i++)
+    if (j[i] != (signed TYPE2) (d[i] >> S (b)))
+      abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vshift-4.c b/gcc/testsuite/gcc.dg/vshift-4.c
new file mode 100644 (file)
index 0000000..c43fbcc
--- /dev/null
@@ -0,0 +1,6 @@
+/* { dg-do run } */
+/* { dg-options "-O3" } */
+
+#define S(x) 3
+
+#include "vshift-3.c"
diff --git a/gcc/testsuite/gcc.dg/vshift-5.c b/gcc/testsuite/gcc.dg/vshift-5.c
new file mode 100644 (file)
index 0000000..daa5f1c
--- /dev/null
@@ -0,0 +1,81 @@
+/* { dg-do run } */
+/* { dg-options "-O3" } */
+
+extern void abort (void);
+long long a[16];
+
+__attribute__((noinline, noclone)) void
+f1 (void)
+{
+  long long a0, a1, a2, a3;
+  a0 = a[0];
+  a1 = a[1];
+  a2 = a[2];
+  a3 = a[3];
+  a0 = a0 << 2;
+  a1 = a1 << 3;
+  a2 = a2 << 4;
+  a3 = a3 << 5;
+  a[0] = a0;
+  a[1] = a1;
+  a[2] = a2;
+  a[3] = a3;
+}
+
+__attribute__((noinline, noclone)) void
+f2 (void)
+{
+  long long a0, a1, a2, a3;
+  a0 = a[0];
+  a1 = a[1];
+  a2 = a[2];
+  a3 = a[3];
+  a0 = a0 << 2;
+  a1 = a1 << 2;
+  a2 = a2 << 2;
+  a3 = a3 << 2;
+  a[0] = a0;
+  a[1] = a1;
+  a[2] = a2;
+  a[3] = a3;
+}
+
+__attribute__((noinline, noclone)) void
+f3 (int x)
+{
+  long long a0, a1, a2, a3;
+  a0 = a[0];
+  a1 = a[1];
+  a2 = a[2];
+  a3 = a[3];
+  a0 = a0 << x;
+  a1 = a1 << x;
+  a2 = a2 << x;
+  a3 = a3 << x;
+  a[0] = a0;
+  a[1] = a1;
+  a[2] = a2;
+  a[3] = a3;
+}
+
+int
+main ()
+{
+  a[0] = 4LL;
+  a[1] = 3LL;
+  a[2] = 2LL;
+  a[3] = 1LL;
+  f1 ();
+  if (a[0] != (4LL << 2) || a[1] != (3LL << 3)
+      || a[2] != (2LL << 4) || a[3] != (1LL << 5))
+    abort ();
+  f2 ();
+  if (a[0] != (4LL << 4) || a[1] != (3LL << 5)
+      || a[2] != (2LL << 6) || a[3] != (1LL << 7))
+    abort ();
+  f3 (3);
+  if (a[0] != (4LL << 7) || a[1] != (3LL << 8)
+      || a[2] != (2LL << 9) || a[3] != (1LL << 10))
+    abort ();
+  return 0;
+}
index 08abd23c0a113f7541eecb8c4ebc915a42503761..c6df30e9310c1efd4d30e7468b23d73b5e81f6ce 100644 (file)
@@ -2453,7 +2453,10 @@ vectorizable_shift (gimple stmt, gimple_stmt_iterator *gsi,
       optab = optab_for_tree_code (code, vectype, optab_vector);
       if (vect_print_dump_info (REPORT_DETAILS))
         fprintf (vect_dump, "vector/vector shift/rotate found.");
-      if (TYPE_MODE (op1_vectype) != TYPE_MODE (vectype))
+      if (!op1_vectype)
+       op1_vectype = get_same_sized_vectype (TREE_TYPE (op1), vectype_out);
+      if (op1_vectype == NULL_TREE
+         || TYPE_MODE (op1_vectype) != TYPE_MODE (vectype))
        {
          if (vect_print_dump_info (REPORT_DETAILS))
            fprintf (vect_dump, "unusable type for last operand in"
@@ -2487,9 +2490,28 @@ vectorizable_shift (gimple stmt, gimple_stmt_iterator *gsi,
               /* Unlike the other binary operators, shifts/rotates have
                  the rhs being int, instead of the same type as the lhs,
                  so make sure the scalar is the right type if we are
-                 dealing with vectors of short/char.  */
+                dealing with vectors of long long/long/short/char.  */
               if (dt[1] == vect_constant_def)
                 op1 = fold_convert (TREE_TYPE (vectype), op1);
+             else if (!useless_type_conversion_p (TREE_TYPE (vectype),
+                                                  TREE_TYPE (op1)))
+               {
+                 if (slp_node
+                     && TYPE_MODE (TREE_TYPE (vectype))
+                        != TYPE_MODE (TREE_TYPE (op1)))
+                   {
+                     if (vect_print_dump_info (REPORT_DETAILS))
+                     fprintf (vect_dump, "unusable type for last operand in"
+                                         " vector/vector shift/rotate.");
+                       return false;
+                   }
+                 if (vec_stmt && !slp_node)
+                   {
+                     op1 = fold_convert (TREE_TYPE (vectype), op1);
+                     op1 = vect_init_vector (stmt, op1,
+                                             TREE_TYPE (vectype), NULL);
+                   }
+               }
             }
         }
     }