diff options
author | Jakub Jelinek <jakub@redhat.com> | 2013-04-26 15:13:36 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2013-04-26 15:13:36 +0200 |
commit | 41e106896a657b1a5276559f243c9cfe39c67f83 (patch) | |
tree | 3870fb7da07120a1e6c6232584678ef485acf3c9 | |
parent | d7ed20db763473e20d1186e5e138ae00e5afc764 (diff) | |
download | gcc-41e106896a657b1a5276559f243c9cfe39c67f83.zip gcc-41e106896a657b1a5276559f243c9cfe39c67f83.tar.gz gcc-41e106896a657b1a5276559f243c9cfe39c67f83.tar.bz2 |
re PR tree-optimization/57051 (Optimization regression in 4.8.0 from 4.7.2)
PR tree-optimization/57051
* fold-const.c (const_binop): Handle VEC_LSHIFT_EXPR
and VEC_RSHIFT_EXPR if shift count is a multiple of element
bitsize.
From-SVN: r198339
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/fold-const.c | 39 |
2 files changed, 39 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index dd49037..bd5c8f1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2013-04-26 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/57051 + * fold-const.c (const_binop): Handle VEC_LSHIFT_EXPR + and VEC_RSHIFT_EXPR if shift count is a multiple of element + bitsize. + 2013-04-26 Richard Biener <rguenther@suse.de> * omp-low.c (finalize_task_copyfn): Do not drop PROP_loops. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 59dbc03..f93ce8a 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -1380,17 +1380,42 @@ const_binop (enum tree_code code, tree arg1, tree arg2) int count = TYPE_VECTOR_SUBPARTS (type), i; tree *elts = XALLOCAVEC (tree, count); - for (i = 0; i < count; i++) + if (code == VEC_LSHIFT_EXPR + || code == VEC_RSHIFT_EXPR) { - tree elem1 = VECTOR_CST_ELT (arg1, i); - - elts[i] = const_binop (code, elem1, arg2); + if (!host_integerp (arg2, 1)) + return NULL_TREE; - /* It is possible that const_binop cannot handle the given - code and return NULL_TREE */ - if (elts[i] == NULL_TREE) + unsigned HOST_WIDE_INT shiftc = tree_low_cst (arg2, 1); + unsigned HOST_WIDE_INT outerc = tree_low_cst (TYPE_SIZE (type), 1); + unsigned HOST_WIDE_INT innerc + = tree_low_cst (TYPE_SIZE (TREE_TYPE (type)), 1); + if (shiftc >= outerc || (shiftc % innerc) != 0) return NULL_TREE; + int offset = shiftc / innerc; + if (code == VEC_LSHIFT_EXPR) + offset = -offset; + tree zero = build_zero_cst (TREE_TYPE (type)); + for (i = 0; i < count; i++) + { + if (i + offset < 0 || i + offset >= count) + elts[i] = zero; + else + elts[i] = VECTOR_CST_ELT (arg1, i + offset); + } } + else + for (i = 0; i < count; i++) + { + tree elem1 = VECTOR_CST_ELT (arg1, i); + + elts[i] = const_binop (code, elem1, arg2); + + /* It is possible that const_binop cannot handle the given + code and return NULL_TREE */ + if (elts[i] == NULL_TREE) + return NULL_TREE; + } return build_vector (type, elts); } |