re PR tree-optimization/53922 (VRP: semantic conflict between range_includes_zero_p and value_inside_range)
2012-07-13 Richard Guenther <rguenther@suse.de> PR tree-optimization/53922 * tree-vrp.c (value_inside_range): Change prototype to take min/max instead of value-range. (range_includes_zero_p): Likewise. Return the result from value_inside_range. (extract_range_from_binary_expr_1): Adjust to handle dont-know return value from range_includes_zero_p. (extract_range_from_unary_expr_1): Likewise. (compare_range_with_value): Likewise. (vrp_meet_1): Likewise. * gcc.dg/torture/pr53922.c: New testcase. From-SVN: r189461
This commit is contained in:
parent
c3e7ee4191
commit
e8f808b30e
4 changed files with 66 additions and 52 deletions
|
@ -1,3 +1,16 @@
|
|||
2012-07-13 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/53922
|
||||
* tree-vrp.c (value_inside_range): Change prototype to take
|
||||
min/max instead of value-range.
|
||||
(range_includes_zero_p): Likewise. Return the result from
|
||||
value_inside_range.
|
||||
(extract_range_from_binary_expr_1): Adjust to handle dont-know
|
||||
return value from range_includes_zero_p.
|
||||
(extract_range_from_unary_expr_1): Likewise.
|
||||
(compare_range_with_value): Likewise.
|
||||
(vrp_meet_1): Likewise.
|
||||
|
||||
2012-07-13 Bill Schmidt <wschmidt@linux.ibm.com>
|
||||
|
||||
* doc/tm.texi: Regenerate.
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2012-07-13 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/53922
|
||||
* gcc.dg/torture/pr53922.c: New testcase.
|
||||
|
||||
2012-07-13 Hans-Peter Nilsson <hp@axis.com>
|
||||
|
||||
PR rtl-optimization/53908
|
||||
|
|
22
gcc/testsuite/gcc.dg/torture/pr53922.c
Normal file
22
gcc/testsuite/gcc.dg/torture/pr53922.c
Normal file
|
@ -0,0 +1,22 @@
|
|||
/* { dg-do run } */
|
||||
/* { dg-require-weak "" } */
|
||||
|
||||
int x(int a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
int y(int a) __attribute__ ((weak));
|
||||
int g = 0;
|
||||
int main()
|
||||
{
|
||||
int (*scan_func)(int);
|
||||
if (g)
|
||||
scan_func = x;
|
||||
else
|
||||
scan_func = y;
|
||||
|
||||
if (scan_func)
|
||||
g = scan_func(10);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1339,41 +1339,25 @@ compare_values (tree val1, tree val2)
|
|||
}
|
||||
|
||||
|
||||
/* Return 1 if VAL is inside value range VR (VR->MIN <= VAL <= VR->MAX),
|
||||
0 if VAL is not inside VR,
|
||||
/* Return 1 if VAL is inside value range MIN <= VAL <= MAX,
|
||||
0 if VAL is not inside [MIN, MAX],
|
||||
-2 if we cannot tell either way.
|
||||
|
||||
FIXME, the current semantics of this functions are a bit quirky
|
||||
when taken in the context of VRP. In here we do not care
|
||||
about VR's type. If VR is the anti-range ~[3, 5] the call
|
||||
value_inside_range (4, VR) will return 1.
|
||||
|
||||
This is counter-intuitive in a strict sense, but the callers
|
||||
currently expect this. They are calling the function
|
||||
merely to determine whether VR->MIN <= VAL <= VR->MAX. The
|
||||
callers are applying the VR_RANGE/VR_ANTI_RANGE semantics
|
||||
themselves.
|
||||
|
||||
This also applies to value_ranges_intersect_p and
|
||||
range_includes_zero_p. The semantics of VR_RANGE and
|
||||
VR_ANTI_RANGE should be encoded here, but that also means
|
||||
adapting the users of these functions to the new semantics.
|
||||
|
||||
Benchmark compile/20001226-1.c compilation time after changing this
|
||||
function. */
|
||||
|
||||
static inline int
|
||||
value_inside_range (tree val, value_range_t * vr)
|
||||
value_inside_range (tree val, tree min, tree max)
|
||||
{
|
||||
int cmp1, cmp2;
|
||||
|
||||
cmp1 = operand_less_p (val, vr->min);
|
||||
cmp1 = operand_less_p (val, min);
|
||||
if (cmp1 == -2)
|
||||
return -2;
|
||||
if (cmp1 == 1)
|
||||
return 0;
|
||||
|
||||
cmp2 = operand_less_p (vr->max, val);
|
||||
cmp2 = operand_less_p (max, val);
|
||||
if (cmp2 == -2)
|
||||
return -2;
|
||||
|
||||
|
@ -1402,23 +1386,14 @@ value_ranges_intersect_p (value_range_t *vr0, value_range_t *vr1)
|
|||
}
|
||||
|
||||
|
||||
/* Return true if VR includes the value zero, false otherwise. FIXME,
|
||||
currently this will return false for an anti-range like ~[-4, 3].
|
||||
This will be wrong when the semantics of value_inside_range are
|
||||
modified (currently the users of this function expect these
|
||||
semantics). */
|
||||
/* Return 1 if [MIN, MAX] includes the value zero, 0 if it does not
|
||||
include the value zero, -2 if we cannot tell. */
|
||||
|
||||
static inline bool
|
||||
range_includes_zero_p (value_range_t *vr)
|
||||
static inline int
|
||||
range_includes_zero_p (tree min, tree max)
|
||||
{
|
||||
tree zero;
|
||||
|
||||
gcc_assert (vr->type != VR_UNDEFINED
|
||||
&& vr->type != VR_VARYING
|
||||
&& !symbolic_range_p (vr));
|
||||
|
||||
zero = build_int_cst (TREE_TYPE (vr->min), 0);
|
||||
return (value_inside_range (zero, vr) == 1);
|
||||
tree zero = build_int_cst (TREE_TYPE (min), 0);
|
||||
return value_inside_range (zero, min, max);
|
||||
}
|
||||
|
||||
/* Return true if *VR is know to only contain nonnegative values. */
|
||||
|
@ -2641,7 +2616,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
|
|||
gives [min / 4, max / 4] range. */
|
||||
if (vr1.type == VR_RANGE
|
||||
&& !symbolic_range_p (&vr1)
|
||||
&& !range_includes_zero_p (&vr1))
|
||||
&& range_includes_zero_p (vr1.min, vr1.max) == 0)
|
||||
{
|
||||
vr0.type = type = VR_RANGE;
|
||||
vr0.min = vrp_val_min (expr_type);
|
||||
|
@ -2658,8 +2633,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
|
|||
not eliminate a division by zero. */
|
||||
if (cfun->can_throw_non_call_exceptions
|
||||
&& (vr1.type != VR_RANGE
|
||||
|| symbolic_range_p (&vr1)
|
||||
|| range_includes_zero_p (&vr1)))
|
||||
|| range_includes_zero_p (vr1.min, vr1.max) != 0))
|
||||
{
|
||||
set_value_range_to_varying (vr);
|
||||
return;
|
||||
|
@ -2670,8 +2644,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
|
|||
include 0. */
|
||||
if (vr0.type == VR_RANGE
|
||||
&& (vr1.type != VR_RANGE
|
||||
|| symbolic_range_p (&vr1)
|
||||
|| range_includes_zero_p (&vr1)))
|
||||
|| range_includes_zero_p (vr1.min, vr1.max) != 0))
|
||||
{
|
||||
tree zero = build_int_cst (TREE_TYPE (vr0.min), 0);
|
||||
int cmp;
|
||||
|
@ -2723,8 +2696,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
|
|||
else if (code == TRUNC_MOD_EXPR)
|
||||
{
|
||||
if (vr1.type != VR_RANGE
|
||||
|| symbolic_range_p (&vr1)
|
||||
|| range_includes_zero_p (&vr1)
|
||||
|| range_includes_zero_p (vr1.min, vr1.max) != 0
|
||||
|| vrp_val_is_min (vr1.min))
|
||||
{
|
||||
set_value_range_to_varying (vr);
|
||||
|
@ -3159,7 +3131,7 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
|
|||
~[-INF, min(MIN, MAX)]. */
|
||||
if (vr0.type == VR_ANTI_RANGE)
|
||||
{
|
||||
if (range_includes_zero_p (&vr0))
|
||||
if (range_includes_zero_p (vr0.min, vr0.max) == 1)
|
||||
{
|
||||
/* Take the lower of the two values. */
|
||||
if (cmp != 1)
|
||||
|
@ -3210,7 +3182,7 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
|
|||
|
||||
/* If the range contains zero then we know that the minimum value in the
|
||||
range will be zero. */
|
||||
else if (range_includes_zero_p (&vr0))
|
||||
else if (range_includes_zero_p (vr0.min, vr0.max) == 1)
|
||||
{
|
||||
if (cmp == 1)
|
||||
max = min;
|
||||
|
@ -3812,7 +3784,7 @@ compare_range_with_value (enum tree_code comp, value_range_t *vr, tree val,
|
|||
return NULL_TREE;
|
||||
|
||||
/* ~[VAL_1, VAL_2] OP VAL is known if VAL_1 <= VAL <= VAL_2. */
|
||||
if (value_inside_range (val, vr) == 1)
|
||||
if (value_inside_range (val, vr->min, vr->max) == 1)
|
||||
return (comp == NE_EXPR) ? boolean_true_node : boolean_false_node;
|
||||
|
||||
return NULL_TREE;
|
||||
|
@ -7548,12 +7520,14 @@ vrp_meet_1 (value_range_t *vr0, value_range_t *vr1)
|
|||
anti-range. FIXME, all this nonsense about distinguishing
|
||||
anti-ranges from ranges is necessary because of the odd
|
||||
semantics of range_includes_zero_p and friends. */
|
||||
if (!symbolic_range_p (&saved)
|
||||
&& ((saved.type == VR_RANGE && !range_includes_zero_p (&saved))
|
||||
|| (saved.type == VR_ANTI_RANGE && range_includes_zero_p (&saved)))
|
||||
&& !symbolic_range_p (vr1)
|
||||
&& ((vr1->type == VR_RANGE && !range_includes_zero_p (vr1))
|
||||
|| (vr1->type == VR_ANTI_RANGE && range_includes_zero_p (vr1))))
|
||||
if (((saved.type == VR_RANGE
|
||||
&& range_includes_zero_p (saved.min, saved.max) == 0)
|
||||
|| (saved.type == VR_ANTI_RANGE
|
||||
&& range_includes_zero_p (saved.min, saved.max) == 1))
|
||||
&& ((vr1->type == VR_RANGE
|
||||
&& range_includes_zero_p (vr1->min, vr1->max) == 0)
|
||||
|| (vr1->type == VR_ANTI_RANGE
|
||||
&& range_includes_zero_p (vr1->min, vr1->max) == 1)))
|
||||
{
|
||||
set_value_range_to_nonnull (vr0, TREE_TYPE (saved.min));
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue