aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr24670.c23
-rw-r--r--gcc/tree-vrp.c88
4 files changed, 120 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c752e61..dbe9c08 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2005-11-06 Diego Novillo <dnovillo@redhat.com>
+
+ PR 24670
+ * tree-vrp.c (fix_equivalence_set): New.
+ (extract_range_from_assert): Call it.
+
2005-11-05 Ian Lance Taylor <ian@airs.com>
PR target/22432
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9fc72af..79c7ac7 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2005-11-06 Diego Novillo <dnovillo@redhat.com>
+
+ PR 24670
+ * gcc.dg/tree-ssa/pr24670.c: New test.
+
2005-11-05 Ian Lance Taylor <ian@airs.com>
PR target/22432
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr24670.c b/gcc/testsuite/gcc.dg/tree-ssa/pr24670.c
new file mode 100644
index 0000000..a5ff800
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr24670.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+__inline__ void
+shift128Right (int count, long long int *z1Ptr)
+{
+ long long int z1;
+ if (count == 0);
+ else if (count < 64);
+ else
+ z1 = (count < 64) ? count : 0;
+ *z1Ptr = z1;
+}
+
+float128_rem ()
+{
+ signed int expDiff;
+ long long int aSig1;
+ long long int sigMean1;
+ if (-64 < expDiff)
+ shift128Right (-expDiff, &aSig1);
+ add128 (&sigMean1);
+}
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 7269fb5..929908b 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -632,6 +632,81 @@ range_includes_zero_p (value_range_t *vr)
}
+/* When extracting ranges from X_i = ASSERT_EXPR <Y_j, pred>, we will
+ initially consider X_i and Y_j equivalent, so the equivalence set
+ of Y_j is added to the equivalence set of X_i. However, it is
+ possible to have a chain of ASSERT_EXPRs whose predicates are
+ actually incompatible. This is usually the result of nesting of
+ contradictory if-then-else statements. For instance, in PR 24670:
+
+ count_4 has range [-INF, 63]
+
+ if (count_4 != 0)
+ {
+ count_19 = ASSERT_EXPR <count_4, count_4 != 0>
+ if (count_19 > 63)
+ {
+ count_18 = ASSERT_EXPR <count_19, count_19 > 63>
+ if (count_18 <= 63)
+ ...
+ }
+ }
+
+ Notice that 'if (count_19 > 63)' is trivially false and will be
+ folded out at the end. However, during propagation, the flowgraph
+ is not cleaned up and so, VRP will evaluate predicates more
+ predicates than necessary, so it must support these
+ inconsistencies. The problem here is that because of the chaining
+ of ASSERT_EXPRs, the equivalency set for count_18 includes count_4.
+ Since count_4 has an incompatible range, we ICE when evaluating the
+ ranges in the equivalency set. So, we need to remove count_4 from
+ it. */
+
+static void
+fix_equivalence_set (value_range_t *vr_p)
+{
+ bitmap_iterator bi;
+ unsigned i;
+ bitmap e = vr_p->equiv;
+ bitmap to_remove = BITMAP_ALLOC (NULL);
+
+ /* Only detect inconsistencies on numeric ranges. */
+ if (vr_p->type == VR_VARYING
+ || vr_p->type == VR_UNDEFINED
+ || symbolic_range_p (vr_p))
+ return;
+
+ EXECUTE_IF_SET_IN_BITMAP (e, 0, i, bi)
+ {
+ value_range_t *equiv_vr = vr_value[i];
+
+ if (equiv_vr->type == VR_VARYING
+ || equiv_vr->type == VR_UNDEFINED
+ || symbolic_range_p (equiv_vr))
+ continue;
+
+ if (equiv_vr->type == VR_RANGE
+ && vr_p->type == VR_RANGE
+ && !value_ranges_intersect_p (vr_p, equiv_vr))
+ bitmap_set_bit (to_remove, i);
+ else if ((equiv_vr->type == VR_RANGE && vr_p->type == VR_ANTI_RANGE)
+ || (equiv_vr->type == VR_ANTI_RANGE && vr_p->type == VR_RANGE))
+ {
+ /* A range and an anti-range have an empty intersection if
+ their end points are the same. FIXME,
+ value_ranges_intersect_p should handle this
+ automatically. */
+ if (compare_values (equiv_vr->min, vr_p->min) == 0
+ && compare_values (equiv_vr->max, vr_p->max) == 0)
+ bitmap_set_bit (to_remove, i);
+ }
+ }
+
+ bitmap_and_compl_into (vr_p->equiv, to_remove);
+ BITMAP_FREE (to_remove);
+}
+
+
/* Extract value range information from an ASSERT_EXPR EXPR and store
it in *VR_P. */
@@ -747,7 +822,11 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
}
}
- /* The new range has the same set of equivalences of VAR's range. */
+ /* Initially, the new range has the same set of equivalences of
+ VAR's range. This will be revised before returning the final
+ value. Since assertions may be chained via mutually exclusive
+ predicates, we will need to trim the set of equivalences before
+ we are done. */
gcc_assert (vr_p->equiv == NULL);
vr_p->equiv = BITMAP_ALLOC (NULL);
add_equivalence (vr_p->equiv, var);
@@ -924,7 +1003,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
|| var_vr->type == VR_UNDEFINED
|| symbolic_range_p (vr_p)
|| symbolic_range_p (var_vr))
- return;
+ goto done;
if (var_vr->type == VR_RANGE && vr_p->type == VR_RANGE)
{
@@ -968,6 +1047,11 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
&& compare_values (var_vr->max, vr_p->max) == 0)
set_value_range_to_varying (vr_p);
}
+
+ /* Remove names from the equivalence set that have ranges
+ incompatible with VR_P. */
+done:
+ fix_equivalence_set (vr_p);
}