From 06f9b387e517d6f54b6c9b35d4f972bc1542855c Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 12 Apr 2013 10:18:59 +0200 Subject: [PATCH] re PR tree-optimization/56918 (incorrect auto-vectorization of array initialization) PR tree-optimization/56918 PR tree-optimization/56920 * fold-const.c (int_const_binop_1): Use op1.mul_with_sign (op2, ...) instead of op1 - op2. Pass 2 * TYPE_PRECISION (type) as second argument to rshift method. For 2 * HOST_BITS_PER_WIDE_INT precision use wide_mul_with_sign method. * gcc.dg/vect/pr56918.c: New test. * gcc.dg/vect/pr56920.c: New test. From-SVN: r197846 --- gcc/ChangeLog | 9 +++++++++ gcc/fold-const.c | 20 ++++++++++++++----- gcc/testsuite/ChangeLog | 7 +++++++ gcc/testsuite/gcc.dg/vect/pr56918.c | 31 +++++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/vect/pr56920.c | 21 +++++++++++++++++++ 5 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/vect/pr56918.c create mode 100644 gcc/testsuite/gcc.dg/vect/pr56920.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index afcdb109efd..aa332721946 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2013-04-12 Jakub Jelinek + + PR tree-optimization/56918 + PR tree-optimization/56920 + * fold-const.c (int_const_binop_1): Use op1.mul_with_sign (op2, ...) + instead of op1 - op2. Pass 2 * TYPE_PRECISION (type) as second + argument to rshift method. For 2 * HOST_BITS_PER_WIDE_INT precision + use wide_mul_with_sign method. + 2013-04-12 Richard Biener * gimple.c (is_gimple_constant): Vector CONSTRUCTORs should diff --git a/gcc/fold-const.c b/gcc/fold-const.c index e8187cbf477..59dbc034c4f 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -984,12 +984,22 @@ int_const_binop_1 (enum tree_code code, const_tree arg1, const_tree arg2, break; case MULT_HIGHPART_EXPR: - /* ??? Need quad precision, or an additional shift operand - to the multiply primitive, to handle very large highparts. */ if (TYPE_PRECISION (type) > HOST_BITS_PER_WIDE_INT) - return NULL_TREE; - tmp = op1 - op2; - res = tmp.rshift (TYPE_PRECISION (type), TYPE_PRECISION (type), !uns); + { + bool dummy_overflow; + if (TYPE_PRECISION (type) != 2 * HOST_BITS_PER_WIDE_INT) + return NULL_TREE; + op1.wide_mul_with_sign (op2, uns, &res, &dummy_overflow); + } + else + { + bool dummy_overflow; + /* MULT_HIGHPART_EXPR can't ever oveflow, as the multiplication + is performed in twice the precision of arguments. */ + tmp = op1.mul_with_sign (op2, false, &dummy_overflow); + res = tmp.rshift (TYPE_PRECISION (type), + 2 * TYPE_PRECISION (type), !uns); + } break; case TRUNC_DIV_EXPR: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bbf27e6bb23..2c8c87872aa 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2013-04-12 Jakub Jelinek + + PR tree-optimization/56918 + PR tree-optimization/56920 + * gcc.dg/vect/pr56918.c: New test. + * gcc.dg/vect/pr56920.c: New test. + 2013-04-12 Tobias Burnus PR fortran/56845 diff --git a/gcc/testsuite/gcc.dg/vect/pr56918.c b/gcc/testsuite/gcc.dg/vect/pr56918.c new file mode 100644 index 00000000000..581faa0e226 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr56918.c @@ -0,0 +1,31 @@ +/* PR tree-optimization/56918 */ +/* { dg-additional-options "-O3" } */ + +#include "tree-vect.h" + +extern void abort (void); +double data[8]; + +__attribute__((noinline, noclone)) void +foo () +{ + int i; + for (i = 0; i < 8; ++i) + data[i] = ((i + 2) % 3) + 1; +} + +int +main () +{ + int i; + check_vect (); + foo (); + if (data[0] != 3 || data[7] != 1) + abort (); + for (i = 1; i < 4; ++i) + if (data[i] != i || data[i + 3] != i) + abort (); + return 0; +} + +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr56920.c b/gcc/testsuite/gcc.dg/vect/pr56920.c new file mode 100644 index 00000000000..c6c7cca0f41 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr56920.c @@ -0,0 +1,21 @@ +/* PR tree-optimization/56920 */ +/* { dg-additional-options "-O3" } */ + +#include "tree-vect.h" + +extern void abort (void); + +int +main () +{ + unsigned int a[15], i; + check_vect (); + for (i = 0; i < 15; ++i) + a[i] = (i * 2) % 15; + for (i = 0; i < 15; ++i) + if (a[i] != (i * 2) % 15) + abort (); + return 0; +} + +/* { dg-final { cleanup-tree-dump "vect" } } */ -- 2.30.2