aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2012-05-15 13:18:32 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2012-05-15 13:18:32 +0000
commit8c1f1d428facaaa17c3ce21cfef418948e3c52fa (patch)
tree83af2b9b3ebecd6808484f834799b5c45641c689 /gcc
parent1ce499ae1a08089cbafa46e9577de7096298f10a (diff)
downloadgcc-8c1f1d428facaaa17c3ce21cfef418948e3c52fa.zip
gcc-8c1f1d428facaaa17c3ce21cfef418948e3c52fa.tar.gz
gcc-8c1f1d428facaaa17c3ce21cfef418948e3c52fa.tar.bz2
re PR tree-optimization/53355 (Autovectorization of a simple loop could be improved.)
2012-05-15 Richard Guenther <rguenther@suse.de> PR tree-optimization/53355 * tree-vrp.c (extract_range_from_binary_expr_1): Handle LSHIFT_EXPRs by constants. * gcc.dg/tree-ssa/vrp67.c: New testcase. From-SVN: r187535
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp67.c38
-rw-r--r--gcc/tree-vrp.c35
4 files changed, 84 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 180e62c..c1e2297 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2012-05-15 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/53355
+ * tree-vrp.c (extract_range_from_binary_expr_1): Handle LSHIFT_EXPRs
+ by constants.
+
2012-05-15 Tristan Gingold <gingold@adacore.com>
* tree-ssa-strlen.c (get_string_length): Convert lhs if needed.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9980ad7..8e82b01 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2012-05-15 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/53355
+ * gcc.dg/tree-ssa/vrp67.c: New testcase.
+
2012-05-15 Bernhard Reutner-Fischer <aldot@gcc.gnu.org>
* gfortran.dg/*.f90: Remove now redundant manual
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp67.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp67.c
new file mode 100644
index 0000000..f02d837
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp67.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp1" } */
+
+unsigned foo (unsigned i)
+{
+ if (i == 2)
+ {
+ i = i << 2;
+ if (i != 8)
+ link_error ();
+ }
+ return i;
+}
+unsigned bar (unsigned i)
+{
+ if (i == 1 << (sizeof (unsigned) * 8 - 1))
+ {
+ i = i << 1;
+ if (i != 0)
+ link_error ();
+ }
+ return i;
+}
+unsigned baz (unsigned i)
+{
+ i = i & 15;
+ if (i == 0)
+ return 0;
+ i = 1000 - i;
+ i >>= 1;
+ i <<= 1;
+ if (i == 0)
+ link_error ();
+ return i;
+}
+
+/* { dg-final { scan-tree-dump-times "Folding predicate" 3 "vrp1" } } */
+/* { dg-final { cleanup-tree-dump "vrp1" } } */
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 72c647f..4dc942c 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -2403,6 +2403,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
&& code != ROUND_DIV_EXPR
&& code != TRUNC_MOD_EXPR
&& code != RSHIFT_EXPR
+ && code != LSHIFT_EXPR
&& code != MIN_EXPR
&& code != MAX_EXPR
&& code != BIT_AND_EXPR
@@ -2596,6 +2597,40 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
extract_range_from_multiplicative_op_1 (vr, code, &vr0, &vr1);
return;
}
+ else if (code == LSHIFT_EXPR)
+ {
+ /* If we have a LSHIFT_EXPR with any shift values outside [0..prec-1],
+ then drop to VR_VARYING. Outside of this range we get undefined
+ behavior from the shift operation. We cannot even trust
+ SHIFT_COUNT_TRUNCATED at this stage, because that applies to rtl
+ shifts, and the operation at the tree level may be widened. */
+ if (vr1.type != VR_RANGE
+ || !value_range_nonnegative_p (&vr1)
+ || TREE_CODE (vr1.max) != INTEGER_CST
+ || compare_tree_int (vr1.max, TYPE_PRECISION (expr_type) - 1) == 1)
+ {
+ set_value_range_to_varying (vr);
+ return;
+ }
+
+ /* We can map shifts by constants to MULT_EXPR handling. */
+ if (range_int_cst_singleton_p (&vr1))
+ {
+ value_range_t vr1p = { VR_RANGE, NULL_TREE, NULL_TREE, NULL };
+ vr1p.min
+ = double_int_to_tree (expr_type,
+ double_int_lshift (double_int_one,
+ TREE_INT_CST_LOW (vr1.min),
+ TYPE_PRECISION (expr_type),
+ false));
+ vr1p.max = vr1p.min;
+ extract_range_from_multiplicative_op_1 (vr, MULT_EXPR, &vr0, &vr1p);
+ return;
+ }
+
+ set_value_range_to_varying (vr);
+ return;
+ }
else if (code == TRUNC_DIV_EXPR
|| code == FLOOR_DIV_EXPR
|| code == CEIL_DIV_EXPR