Fix PR 40049
authorMichael Meissner <meissner@linux.vnet.ibm.com>
Fri, 8 May 2009 22:38:49 +0000 (22:38 +0000)
committerMichael Meissner <meissner@gcc.gnu.org>
Fri, 8 May 2009 22:38:49 +0000 (22:38 +0000)
From-SVN: r147298

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/vect-shift-2.c [new file with mode: 0644]
gcc/tree-vect-stmts.c

index 026c8ef..83b14c3 100644 (file)
@@ -1,3 +1,11 @@
+2009-05-07  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+       PR tree-optimization/40049
+       * tree-vect-stmts.c (vectorizable_operation): If the machine has
+       only vector/vector shifts, convert the type of the constant to the
+       appropriate type to avoid building incorrect trees, which
+       eventually have problems with garbage collection.
+
 2009-05-08  Joseph Myers  <joseph@codesourcery.com>
 
        * fold-const.c (fold_binary): Do not fold multiplication by 1 or
index a03013e..3099e1b 100644 (file)
@@ -1,3 +1,8 @@
+2009-05-08  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+       PR tree-optimization/40049
+       * gcc.dg/vect/vect-shift-2.c: New test.
+
 2009-05-08  Joseph Myers  <joseph@codesourcery.com>
 
        * gcc.dg/torture/complex-sign-mul-minus-one.c,
diff --git a/gcc/testsuite/gcc.dg/vect/vect-shift-2.c b/gcc/testsuite/gcc.dg/vect/vect-shift-2.c
new file mode 100644 (file)
index 0000000..ea41c99
--- /dev/null
@@ -0,0 +1,189 @@
+/* { dg-require-effective-target vect_shift } */
+/* { dg-require-effective-target vect_int } */
+/* Check the standard integer types for left and right shifts to see if the
+   compiler replaced a scalar instruction with a vector instruction whether the
+   correct value is generated.  */
+
+#ifdef TRACE
+#include <stdio.h>
+#endif
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#ifndef ALIGN
+#define ALIGN __attribute__((__aligned__(32)))
+#endif
+
+#ifndef NOINLINE
+#define NOINLINE __attribute__((__noinline__))
+#endif
+
+#ifdef TRACE
+#define TRACE_FUNC(PREFIX, NAME) printf (#PREFIX #NAME "\n")
+#define TRACE_DONE()  printf ("done!\n")
+#define TRACE_ABORT(I,E,G)                                             \
+do {                                                                   \
+  printf ("Element %d, expected 0x%lx, got 0x%lx\n",                   \
+         I, (long)(E), (long)(G));                                     \
+  abort ();                                                            \
+} while (0)
+
+#else
+#define TRACE_FUNC(PREFIX, A)
+#define TRACE_DONE()
+#define TRACE_ABORT(I,E,G) abort ()
+#endif
+
+#define NAME(A,B) A ## B
+
+#define VECT_TESTS(PREFIX, TYPE, N)                                    \
+ /* Restrict the optimizer from optimizing the setup loops.  */                \
+volatile TYPE NAME (PREFIX, zero) = 0;                                 \
+                                                                       \
+TYPE NAME (PREFIX, a)[N] ALIGN;                                                \
+TYPE NAME (PREFIX, b)[N] ALIGN;                                                \
+TYPE NAME (PREFIX, c)[N] ALIGN;                                                \
+TYPE NAME (PREFIX, d)[N] ALIGN;                                                \
+                                                                       \
+static void NOINLINE                                                   \
+NAME (PREFIX, lshift_2) (void)                                         \
+{                                                                      \
+  int i;                                                               \
+                                                                       \
+  TRACE_FUNC (PREFIX, lshift_2);                                       \
+  for (i = 0; i < N; i++)                                              \
+    NAME (PREFIX, a)[i] = NAME (PREFIX, b)[i] << 2;                    \
+}                                                                      \
+                                                                       \
+static void NOINLINE                                                   \
+NAME (PREFIX, lshift_var) (int shift)                                  \
+{                                                                      \
+  int i;                                                               \
+                                                                       \
+  TRACE_FUNC (PREFIX, lshift_var);                                     \
+  for (i = 0; i < N; i++)                                              \
+    NAME (PREFIX, a)[i] = NAME (PREFIX, b)[i] << shift;                        \
+}                                                                      \
+                                                                       \
+static void NOINLINE                                                   \
+NAME (PREFIX, lshift_vect) (void)                                      \
+{                                                                      \
+  int i;                                                               \
+                                                                       \
+  TRACE_FUNC (PREFIX, lshift_vect);                                    \
+  for (i = 0; i < N; i++)                                              \
+    NAME (PREFIX, a)[i] = NAME (PREFIX, b)[i] << NAME (PREFIX, c)[i];  \
+}                                                                      \
+                                                                       \
+static void NOINLINE                                                   \
+NAME (PREFIX, rshift_2) (void)                                         \
+{                                                                      \
+  int i;                                                               \
+                                                                       \
+  TRACE_FUNC (PREFIX, rshift_2);                                       \
+  for (i = 0; i < N; i++)                                              \
+    NAME (PREFIX, a)[i] = NAME (PREFIX, b)[i] >> 2;                    \
+}                                                                      \
+                                                                       \
+static void NOINLINE                                                   \
+NAME (PREFIX, rshift_var) (int shift)                                  \
+{                                                                      \
+  int i;                                                               \
+                                                                       \
+  TRACE_FUNC (PREFIX, rshift_var);                                     \
+  for (i = 0; i < N; i++)                                              \
+    NAME (PREFIX, a)[i] = NAME (PREFIX, b)[i] >> shift;                        \
+}                                                                      \
+                                                                       \
+static void NOINLINE                                                   \
+NAME (PREFIX, rshift_vect) (void)                                      \
+{                                                                      \
+  int i;                                                               \
+                                                                       \
+  TRACE_FUNC (PREFIX, rshift_vect);                                    \
+  for (i = 0; i < N; i++)                                              \
+    NAME (PREFIX, a)[i] = NAME (PREFIX, b)[i] >> NAME (PREFIX, c)[i];  \
+}                                                                      \
+                                                                       \
+static void NOINLINE                                                   \
+NAME (PREFIX, check) (void)                                            \
+{                                                                      \
+  int i;                                                               \
+                                                                       \
+  TRACE_FUNC (PREFIX, check);                                          \
+  for (i = 0; i < N; i++)                                              \
+    if (NAME (PREFIX, a)[i] != NAME (PREFIX, d)[i])                    \
+      TRACE_ABORT (i, NAME (PREFIX, d)[i], NAME (PREFIX, a)[i]);       \
+}                                                                      \
+                                                                       \
+static void NOINLINE                                                   \
+NAME (PREFIX, tests) (void)                                            \
+{                                                                      \
+  int i;                                                               \
+                                                                       \
+  TRACE_FUNC (PREFIX, tests);                                          \
+  for (i = 0; i < N; i++)                                              \
+    {                                                                  \
+      NAME (PREFIX, b)[i] = (i + NAME (PREFIX, zero));                 \
+      NAME (PREFIX, c)[i] = 2;                                         \
+      NAME (PREFIX, d)[i] = (i + NAME (PREFIX, zero)) << 2;            \
+    }                                                                  \
+                                                                       \
+  NAME (PREFIX, lshift_2) ();                                          \
+  NAME (PREFIX, check) ();                                             \
+                                                                       \
+  NAME (PREFIX, lshift_var) (2);                                       \
+  NAME (PREFIX, check) ();                                             \
+                                                                       \
+  NAME (PREFIX, lshift_vect) ();                                       \
+  NAME (PREFIX, check) ();                                             \
+                                                                       \
+  for (i = 0; i < N; i++)                                              \
+    {                                                                  \
+      NAME (PREFIX, b)[i] = ((i + NAME (PREFIX, zero)) << 4)           \
+       | (((TYPE)0x80) << ((sizeof (TYPE) * 8) - 8));                  \
+      NAME (PREFIX, c)[i] = 2;                                         \
+      NAME (PREFIX, d)[i] = (TYPE)((NAME (PREFIX, b)[i]                        \
+                                   + NAME (PREFIX, zero)) >> 2);       \
+    }                                                                  \
+                                                                       \
+  NAME (PREFIX, rshift_2) ();                                          \
+  NAME (PREFIX, check) ();                                             \
+                                                                       \
+  NAME (PREFIX, rshift_var) (2);                                       \
+  NAME (PREFIX, check) ();                                             \
+                                                                       \
+  NAME (PREFIX, rshift_vect) ();                                       \
+  NAME (PREFIX, check) ();                                             \
+}
+
+VECT_TESTS(uc_, unsigned char,  16)
+VECT_TESTS(us_, unsigned short, 32)
+VECT_TESTS(ui_, unsigned int,   32)
+VECT_TESTS(ul_, unsigned long,  32)
+
+VECT_TESTS(sc_, signed char,    16)
+VECT_TESTS(ss_, short,          32)
+VECT_TESTS(si_, int,            32)
+VECT_TESTS(sl_, long,           32)
+
+int main ()
+{
+  int i;
+
+  check_vect ();
+
+  uc_tests ();
+  us_tests ();
+  ui_tests ();
+  ul_tests ();
+
+  sc_tests ();
+  ss_tests ();
+  si_tests ();
+  sl_tests ();
+
+  TRACE_DONE ();
+  return 0;
+}
index 0ab9883..06d51e2 100644 (file)
@@ -1974,11 +1974,20 @@ vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi,
          else
            {
              optab = optab_for_tree_code (code, vectype, optab_vector);
-             if (vect_print_dump_info (REPORT_DETAILS)
-                 && optab
+             if (optab
                  && (optab_handler (optab, TYPE_MODE (vectype))->insn_code
                      != CODE_FOR_nothing))
-               fprintf (vect_dump, "vector/vector shift/rotate found.");
+               {
+                 if (vect_print_dump_info (REPORT_DETAILS))
+                   fprintf (vect_dump, "vector/vector shift/rotate found.");
+
+                 /* 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.  */
+                 if (dt[1] == vect_constant_def)
+                   op1 = fold_convert (TREE_TYPE (vectype), op1);
+               }
            }
        }