aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vrp.c
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/tree-vrp.c
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/tree-vrp.c')
-rw-r--r--gcc/tree-vrp.c35
1 files changed, 35 insertions, 0 deletions
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