tree-vrp.c (extract_range_from_assert): Refine the result range if the variable referenced by the ASSERT_EXPR has a...

* tree-vrp.c (extract_range_from_assert): Refine the result range
	if the variable referenced by the ASSERT_EXPR has a range and
	either the tentative result range or the previous range is a 
	VR_ANTI_RANGE.

	* gcc.dg/tree-ssa/vrp25.c: New test.

From-SVN: r109968
This commit is contained in:
Jeff Law 2006-01-19 09:30:59 -07:00 committed by Jeff Law
parent 2e6f91e35a
commit 307d19feb1
4 changed files with 153 additions and 0 deletions

View File

@ -1,3 +1,10 @@
2006-01-19 Jeff Law <law@redhat.com>
* tree-vrp.c (extract_range_from_assert): Refine the result range
if the variable referenced by the ASSERT_EXPR has a range and
either the tentative result range or the previous range is a
VR_ANTI_RANGE.
2006-01-19 Richard Sandiford <richard@codesourcery.com>
* c-decl.c (add_flexible_array_elts_to_size): Simplify vector accesses.

View File

@ -1,3 +1,7 @@
2006-01-18 Jeff Law <law@redhat.com>
* gcc.dg/tree-ssa/vrp25.c: New test.
2006-01-19 Richard Sandiford <richard@codesourcery.com>
* gcc.dg/pr25805.c: Fix misapplied patch.

View File

@ -0,0 +1,52 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-vrp-details" } */
extern void abort ();
int tree_code_length[100];
blah (int code1)
{
unsigned char D18670;
if (code1 != 53) goto L0; else goto L1;
L0:
abort ();
L1:
D18670 = tree_code_length[53];
if (D18670 <= 1) goto L2; else goto L3;
L2:
abort ();
L3:
if (D18670 == 2) goto L4; else goto L5;
L4:
abort ();
L5:
arf ();
if (code1 != 53) goto L6; else goto L7;
L6:
abort ();
L7:
if (D18670 <= 2) goto L8; else goto L9;
L8:
abort ();
L9:
return;
}
/* The second test of (code1 != 53) and the test (D18670 <= 2) are
both totally subsumed by earlier tests and thus should be folded
away using VRP. */
/* { dg-final { scan-tree-dump-times "Folding predicate" 2 "vrp" } } */
/* { dg-final { cleanup-tree-dump "vrp" } } */

View File

@ -1048,6 +1048,96 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
if (compare_values (var_vr->min, vr_p->min) == 0
&& compare_values (var_vr->max, vr_p->max) == 0)
set_value_range_to_varying (vr_p);
else
{
tree min, max, anti_min, anti_max, real_min, real_max;
/* We want to compute the logical AND of the two ranges;
there are three cases to consider.
1. The VR_ANTI_RANGE range is competely within the
VR_RANGE and the endpoints of the ranges are
different. In that case the resulting range
should be the VR_ANTI_RANGE.
2. The VR_ANTI_RANGE is completely disjoint from
the VR_RANGE. In this case the resulting range
should be the VR_RANGE.
3. There is some overlap between the VR_ANTI_RANGE
and the VR_RANGE.
3a. If the high limit of the VR_ANTI_RANGE resides
within the VR_RANGE, then the result is a new
VR_RANGE starting at the high limit of the
the VR_ANTI_RANGE + 1 and extending to the
high limit of the original VR_RANGE.
3b. If the low limit of the VR_ANTI_RANGE resides
within the VR_RANGE, then the result is a new
VR_RANGE starting at the low limit of the original
VR_RANGE and extending to the low limit of the
VR_ANTI_RANGE - 1. */
if (vr_p->type == VR_ANTI_RANGE)
{
anti_min = vr_p->min;
anti_max = vr_p->max;
real_min = var_vr->min;
real_max = var_vr->max;
}
else
{
anti_min = var_vr->min;
anti_max = var_vr->max;
real_min = vr_p->min;
real_max = vr_p->max;
}
/* Case 1, VR_ANTI_RANGE completely within VR_RANGE,
not including any endpoints. */
if (compare_values (anti_max, real_max) == -1
&& compare_values (anti_min, real_min) == 1)
{
set_value_range (vr_p, VR_ANTI_RANGE, anti_min,
anti_max, vr_p->equiv);
}
/* Case 2, VR_ANTI_RANGE completely disjoint from
VR_RANGE. */
else if (compare_values (anti_min, real_max) == 1
|| compare_values (anti_max, real_min) == -1)
{
set_value_range (vr_p, VR_RANGE, real_min,
real_max, vr_p->equiv);
}
/* Case 3a, the anti-range extends into the low
part of the real range. Thus creating a new
low for the real reange. */
else if ((compare_values (anti_max, real_min) == 1
|| compare_values (anti_max, real_min) == 0)
&& compare_values (anti_max, real_max) == -1)
{
min = fold_build2 (PLUS_EXPR, TREE_TYPE (var_vr->min),
anti_max,
build_int_cst (TREE_TYPE (var_vr->min), 1));
max = real_max;
set_value_range (vr_p, VR_RANGE, min, max, vr_p->equiv);
}
/* Case 3b, the anti-range extends into the high
part of the real range. Thus creating a new
higher for the real reange. */
else if (compare_values (anti_min, real_min) == 1
&& (compare_values (anti_min, real_max) == -1
|| compare_values (anti_min, real_max) == 0))
{
max = fold_build2 (MINUS_EXPR, TREE_TYPE (var_vr->min),
anti_min,
build_int_cst (TREE_TYPE (var_vr->min), 1));
min = real_min;
set_value_range (vr_p, VR_RANGE, min, max, vr_p->equiv);
}
}
}
/* Remove names from the equivalence set that have ranges