aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vrp.c
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@redhat.com>2018-08-21 06:27:14 +0000
committerAldy Hernandez <aldyh@gcc.gnu.org>2018-08-21 06:27:14 +0000
commit70eff705513d3d3cd387a7b54af5e0818727a8f0 (patch)
treefc819ab84ec6dd98e2d5b3f7999a9b4c3e138c16 /gcc/tree-vrp.c
parent316a03a633443f0201a980f30f67aac4aaf43e28 (diff)
downloadgcc-70eff705513d3d3cd387a7b54af5e0818727a8f0.zip
gcc-70eff705513d3d3cd387a7b54af5e0818727a8f0.tar.gz
gcc-70eff705513d3d3cd387a7b54af5e0818727a8f0.tar.bz2
wide-int-range.cc (wide_int_range_abs): New.
* wide-int-range.cc (wide_int_range_abs): New. (wide_int_range_order_set): Rename from wide_int_range_min_max. * wide-int-range.h (wide_int_range_abs): New. (wide_int_range_min_max): New. * tree-vrp.c (extract_range_from_unary_expr): Rewrite ABS_EXPR case to call wide_int_range_abs. Rewrite MIN/MAX_EXPR to call wide_int_range_min_max. (extract_range_from_abs_expr): Delete. From-SVN: r263685
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r--gcc/tree-vrp.c155
1 files changed, 32 insertions, 123 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 2ddb0c2..24e089b 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -1594,50 +1594,19 @@ extract_range_from_binary_expr_1 (value_range *vr,
else if (code == MIN_EXPR
|| code == MAX_EXPR)
{
- if (vr0.type == VR_RANGE
- && !symbolic_range_p (&vr0))
- {
- type = VR_RANGE;
- if (vr1.type == VR_RANGE
- && !symbolic_range_p (&vr1))
- {
- /* For operations that make the resulting range directly
- proportional to the original ranges, apply the operation to
- the same end of each range. */
- min = int_const_binop (code, vr0.min, vr1.min);
- max = int_const_binop (code, vr0.max, vr1.max);
- }
- else if (code == MIN_EXPR)
- {
- min = vrp_val_min (expr_type);
- max = vr0.max;
- }
- else if (code == MAX_EXPR)
- {
- min = vr0.min;
- max = vrp_val_max (expr_type);
- }
- }
- else if (vr1.type == VR_RANGE
- && !symbolic_range_p (&vr1))
- {
- type = VR_RANGE;
- if (code == MIN_EXPR)
- {
- min = vrp_val_min (expr_type);
- max = vr1.max;
- }
- else if (code == MAX_EXPR)
- {
- min = vr1.min;
- max = vrp_val_max (expr_type);
- }
- }
+ wide_int wmin, wmax;
+ wide_int vr0_min, vr0_max;
+ wide_int vr1_min, vr1_max;
+ extract_range_into_wide_ints (&vr0, sign, prec, &vr0_min, &vr0_max);
+ extract_range_into_wide_ints (&vr1, sign, prec, &vr1_min, &vr1_max);
+ if (wide_int_range_min_max (wmin, wmax, code, sign, prec,
+ vr0_min, vr0_max, vr1_min, vr1_max))
+ set_value_range (vr, VR_RANGE,
+ wide_int_to_tree (expr_type, wmin),
+ wide_int_to_tree (expr_type, wmax), NULL);
else
- {
- set_value_range_to_varying (vr);
- return;
- }
+ set_value_range_to_varying (vr);
+ return;
}
else if (code == MULT_EXPR)
{
@@ -1924,85 +1893,6 @@ extract_range_from_binary_expr_1 (value_range *vr,
set_value_range (vr, type, min, max, NULL);
}
-/* Calculates the absolute value of a range and puts the result in VR.
- VR0 is the input range. TYPE is the type of the resulting
- range. */
-
-static void
-extract_range_from_abs_expr (value_range &vr, tree type, value_range &vr0)
-{
- /* Pass through vr0 in the easy cases. */
- if (TYPE_UNSIGNED (type)
- || value_range_nonnegative_p (&vr0))
- {
- copy_value_range (&vr, &vr0);
- return;
- }
-
- /* For the remaining varying or symbolic ranges we can't do anything
- useful. */
- if (vr0.type == VR_VARYING
- || symbolic_range_p (&vr0))
- {
- set_value_range_to_varying (&vr);
- return;
- }
-
- /* -TYPE_MIN_VALUE = TYPE_MIN_VALUE with flag_wrapv so we can't get a
- useful range. */
- if (!TYPE_OVERFLOW_UNDEFINED (type)
- && ((vr0.type == VR_RANGE
- && vrp_val_is_min (vr0.min))
- || (vr0.type == VR_ANTI_RANGE
- && !vrp_val_is_min (vr0.min))))
- {
- set_value_range_to_varying (&vr);
- return;
- }
-
- /* ABS_EXPR may flip the range around, if the original range
- included negative values. */
- tree min, max;
- if (!vrp_val_is_min (vr0.min))
- min = fold_unary_to_constant (ABS_EXPR, type, vr0.min);
- else
- min = TYPE_MAX_VALUE (type);
-
- if (!vrp_val_is_min (vr0.max))
- max = fold_unary_to_constant (ABS_EXPR, type, vr0.max);
- else
- max = TYPE_MAX_VALUE (type);
-
- int cmp = compare_values (min, max);
- gcc_assert (vr0.type != VR_ANTI_RANGE);
-
- /* If the range contains zero then we know that the minimum value in the
- range will be zero. */
- if (range_includes_zero_p (vr0.min, vr0.max) == 1)
- {
- if (cmp == 1)
- max = min;
- min = build_int_cst (type, 0);
- }
- else
- {
- /* If the range was reversed, swap MIN and MAX. */
- if (cmp == 1)
- std::swap (min, max);
- }
-
- cmp = compare_values (min, max);
- if (cmp == -2 || cmp == 1)
- {
- /* If the new range has its limits swapped around (MIN > MAX),
- then the operation caused one of them to wrap around, mark
- the new range VARYING. */
- set_value_range_to_varying (&vr);
- }
- else
- set_value_range (&vr, vr0.type, min, max, NULL);
-}
-
/* Extract range information from a unary operation CODE based on
the range of its operand *VR0 with type OP0_TYPE with resulting type TYPE.
The resulting range is stored in *VR. */
@@ -2012,6 +1902,8 @@ extract_range_from_unary_expr (value_range *vr,
enum tree_code code, tree type,
value_range *vr0_, tree op0_type)
{
+ signop sign = TYPE_SIGN (type);
+ unsigned int prec = TYPE_PRECISION (type);
value_range vr0 = *vr0_, vrtem0 = VR_INITIALIZER, vrtem1 = VR_INITIALIZER;
/* VRP only operates on integral and pointer types. */
@@ -2133,7 +2025,24 @@ extract_range_from_unary_expr (value_range *vr,
return;
}
else if (code == ABS_EXPR)
- return extract_range_from_abs_expr (*vr, type, vr0);
+ {
+ if (vr0.type != VR_RANGE || symbolic_range_p (&vr0))
+ {
+ set_value_range_to_varying (vr);
+ return;
+ }
+ wide_int wmin, wmax;
+ wide_int vr0_min, vr0_max;
+ extract_range_into_wide_ints (&vr0, sign, prec, &vr0_min, &vr0_max);
+ if (wide_int_range_abs (wmin, wmax, sign, prec, vr0_min, vr0_max,
+ TYPE_OVERFLOW_UNDEFINED (type)))
+ set_value_range (vr, VR_RANGE,
+ wide_int_to_tree (type, wmin),
+ wide_int_to_tree (type, wmax), NULL);
+ else
+ set_value_range_to_varying (vr);
+ return;
+ }
/* For unhandled operations fall back to varying. */
set_value_range_to_varying (vr);