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
This commit is contained in:
parent
316a03a633
commit
70eff70551
4 changed files with 130 additions and 127 deletions
|
@ -1,3 +1,14 @@
|
|||
2018-08-21 Aldy Hernandez <aldyh@redhat.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2018-08-20 Michael Meissner <meissner@linux.ibm.com>
|
||||
|
||||
PR target/87033
|
||||
|
|
155
gcc/tree-vrp.c
155
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);
|
||||
|
|
|
@ -119,9 +119,10 @@ wide_int_range_set_zero_nonzero_bits (signop sign,
|
|||
accordingly. */
|
||||
|
||||
static void
|
||||
wide_int_range_min_max (wide_int &min, wide_int &max,
|
||||
wide_int &w0, wide_int &w1, wide_int &w2, wide_int &w3,
|
||||
signop sign)
|
||||
wide_int_range_order_set (wide_int &min, wide_int &max,
|
||||
wide_int &w0, wide_int &w1,
|
||||
wide_int &w2, wide_int &w3,
|
||||
signop sign)
|
||||
{
|
||||
/* Order pairs w0,w1 and w2,w3. */
|
||||
if (wi::gt_p (w0, w1, sign))
|
||||
|
@ -177,7 +178,7 @@ wide_int_range_cross_product (wide_int &res_lb, wide_int &res_ub,
|
|||
overflow_undefined))
|
||||
return false;
|
||||
|
||||
wide_int_range_min_max (res_lb, res_ub, cp1, cp2, cp3, cp4, sign);
|
||||
wide_int_range_order_set (res_lb, res_ub, cp1, cp2, cp3, cp4, sign);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -605,3 +606,60 @@ wide_int_range_trunc_mod (wide_int &wmin, wide_int &wmax,
|
|||
tmp = wi::zero (prec);
|
||||
wmax = wi::min (wmax, tmp, sign);
|
||||
}
|
||||
|
||||
/* Calculate ABS_EXPR on a range and store the result in [MIN, MAX]. */
|
||||
|
||||
bool
|
||||
wide_int_range_abs (wide_int &min, wide_int &max,
|
||||
signop sign, unsigned prec,
|
||||
const wide_int &vr0_min, const wide_int &vr0_max,
|
||||
bool overflow_undefined)
|
||||
{
|
||||
/* Pass through VR0 the easy cases. */
|
||||
if (sign == UNSIGNED || wi::ge_p (vr0_min, 0, sign))
|
||||
{
|
||||
min = vr0_min;
|
||||
max = vr0_max;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -TYPE_MIN_VALUE = TYPE_MIN_VALUE with flag_wrapv so we can't get a
|
||||
useful range. */
|
||||
wide_int min_value = wi::min_value (prec, sign);
|
||||
wide_int max_value = wi::max_value (prec, sign);
|
||||
if (!overflow_undefined && wi::eq_p (vr0_min, min_value))
|
||||
return false;
|
||||
|
||||
/* ABS_EXPR may flip the range around, if the original range
|
||||
included negative values. */
|
||||
if (wi::eq_p (vr0_min, min_value))
|
||||
min = max_value;
|
||||
else
|
||||
min = wi::abs (vr0_min);
|
||||
if (wi::eq_p (vr0_max, min_value))
|
||||
max = max_value;
|
||||
else
|
||||
max = wi::abs (vr0_max);
|
||||
|
||||
/* If the range contains zero then we know that the minimum value in the
|
||||
range will be zero. */
|
||||
if (wi::le_p (vr0_min, 0, sign) && wi::ge_p (vr0_max, 0, sign))
|
||||
{
|
||||
if (wi::gt_p (min, max, sign))
|
||||
max = min;
|
||||
min = wi::zero (prec);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the range was reversed, swap MIN and MAX. */
|
||||
if (wi::gt_p (min, max, sign))
|
||||
std::swap (min, max);
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
if (wi::gt_p (min, max, sign))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -94,6 +94,11 @@ extern void wide_int_range_trunc_mod (wide_int &wmin, wide_int &wmax,
|
|||
const wide_int &vr0_max,
|
||||
const wide_int &vr1_min,
|
||||
const wide_int &vr1_max);
|
||||
extern bool wide_int_range_abs (wide_int &min, wide_int &max,
|
||||
signop sign, unsigned prec,
|
||||
const wide_int &vr0_min,
|
||||
const wide_int &vr0_max,
|
||||
bool overflow_undefined);
|
||||
|
||||
/* Return TRUE if shifting by range [MIN, MAX] is undefined behavior. */
|
||||
|
||||
|
@ -112,4 +117,24 @@ wide_int_range_shift_undefined_p (signop sign, unsigned prec,
|
|||
return wi::lt_p (min, 0, sign) || wi::ge_p (max, prec, sign);
|
||||
}
|
||||
|
||||
/* Calculate MIN/MAX_EXPR of two ranges and store the result in [MIN, MAX]. */
|
||||
|
||||
inline bool
|
||||
wide_int_range_min_max (wide_int &min, wide_int &max,
|
||||
tree_code code,
|
||||
signop sign, unsigned prec,
|
||||
const wide_int &vr0_min, const wide_int &vr0_max,
|
||||
const wide_int &vr1_min, const wide_int &vr1_max)
|
||||
{
|
||||
wi::overflow_type overflow;
|
||||
wide_int_binop (min, code, vr0_min, vr1_min, sign, &overflow);
|
||||
wide_int_binop (max, code, vr0_max, vr1_max, sign, &overflow);
|
||||
/* If the new range covers the entire domain, that's really no range
|
||||
at all. */
|
||||
if (min == wi::min_value (prec, sign)
|
||||
&& max == wi::max_value (prec, sign))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* GCC_WIDE_INT_RANGE_H */
|
||||
|
|
Loading…
Add table
Reference in a new issue