aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMichael Meissner <meissner@linux.vnet.ibm.com>2009-05-08 22:38:49 +0000
committerMichael Meissner <meissner@gcc.gnu.org>2009-05-08 22:38:49 +0000
commitad6c0864efa692fd8123a9d680e5c405a8a5dbb2 (patch)
tree0af10d3c32a433a02b46a4025e3c6673a396c80e /gcc
parentc94f9067af215b26b634b6c9678297aa92d74fc7 (diff)
downloadgcc-ad6c0864efa692fd8123a9d680e5c405a8a5dbb2.zip
gcc-ad6c0864efa692fd8123a9d680e5c405a8a5dbb2.tar.gz
gcc-ad6c0864efa692fd8123a9d680e5c405a8a5dbb2.tar.bz2
Fix PR 40049
From-SVN: r147298
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-shift-2.c189
-rw-r--r--gcc/tree-vect-stmts.c15
4 files changed, 214 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 026c8ef..83b14c3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a03013e..3099e1b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..ea41c99
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-shift-2.c
@@ -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;
+}
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 0ab9883..06d51e2 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -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);
+ }
}
}