aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/fold-const.c39
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);
}