From 307d19feb13bd6ba0886ef8bda1f17bf5ab5362c Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Thu, 19 Jan 2006 09:30:59 -0700 Subject: [PATCH] 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 --- gcc/ChangeLog | 7 +++ gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gcc.dg/tree-ssa/vrp25.c | 52 ++++++++++++++++ gcc/tree-vrp.c | 90 +++++++++++++++++++++++++++ 4 files changed, 153 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vrp25.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 71eb7007f464..8da8006782b8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2006-01-19 Jeff Law + + * 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 * c-decl.c (add_flexible_array_elts_to_size): Simplify vector accesses. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4266cb0aa4a4..ab86c53c0285 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2006-01-18 Jeff Law + + * gcc.dg/tree-ssa/vrp25.c: New test. + 2006-01-19 Richard Sandiford * gcc.dg/pr25805.c: Fix misapplied patch. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp25.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp25.c new file mode 100644 index 000000000000..52f9ea2fea54 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp25.c @@ -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" } } */ + diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index a5028b4d8f59..c4a921c50a9a 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -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