diff options
author | Michael Meissner <meissner@linux.vnet.ibm.com> | 2009-05-08 22:38:49 +0000 |
---|---|---|
committer | Michael Meissner <meissner@gcc.gnu.org> | 2009-05-08 22:38:49 +0000 |
commit | ad6c0864efa692fd8123a9d680e5c405a8a5dbb2 (patch) | |
tree | 0af10d3c32a433a02b46a4025e3c6673a396c80e /gcc | |
parent | c94f9067af215b26b634b6c9678297aa92d74fc7 (diff) | |
download | gcc-ad6c0864efa692fd8123a9d680e5c405a8a5dbb2.zip gcc-ad6c0864efa692fd8123a9d680e5c405a8a5dbb2.tar.gz gcc-ad6c0864efa692fd8123a9d680e5c405a8a5dbb2.tar.bz2 |
Fix PR 40049
From-SVN: r147298
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-shift-2.c | 189 | ||||
-rw-r--r-- | gcc/tree-vect-stmts.c | 15 |
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); + } } } |