diff options
Diffstat (limited to 'gcc')
-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); } |