aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZdenek Dvorak <dvorakz@suse.cz>2006-06-19 20:32:20 +0200
committerZdenek Dvorak <rakdver@gcc.gnu.org>2006-06-19 18:32:20 +0000
commit20fb52af9359cdf66e245f1779bbcd6f1a41de8b (patch)
treea31ea250ca70dd8f95b546f2b0488936821de9da
parentdfa52cf9d1c5d14a6a8f905bcf84565ae7b0627c (diff)
downloadgcc-20fb52af9359cdf66e245f1779bbcd6f1a41de8b.zip
gcc-20fb52af9359cdf66e245f1779bbcd6f1a41de8b.tar.gz
gcc-20fb52af9359cdf66e245f1779bbcd6f1a41de8b.tar.bz2
tree-ssa-loop-niter.c (implies_ge_p): New function.
* tree-ssa-loop-niter.c (implies_ge_p): New function. (derive_constant_upper_bound): Handle OP0 - CST in unsigned types correctly. From-SVN: r114782
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/tree-ssa-loop-niter.c43
2 files changed, 47 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d0303b8..3cca1ab 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2006-06-19 Zdenek Dvorak <dvorakz@suse.cz>
+
+ * tree-ssa-loop-niter.c (implies_ge_p): New function.
+ (derive_constant_upper_bound): Handle OP0 - CST in unsigned types
+ correctly.
+
2006-06-19 Denis Chertykov <denisc@overta.ru>
* config/avr/libgcc.S : Correct my wrong previous commit.
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index e160656..a896d03 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -1491,6 +1491,24 @@ implies_nonnegative_p (tree cond, tree val)
return nonzero_p (compare);
}
+/* Returns true if we can prove that COND ==> A >= B. */
+
+static bool
+implies_ge_p (tree cond, tree a, tree b)
+{
+ tree compare = fold_build2 (GE_EXPR, boolean_type_node, a, b);
+
+ if (nonzero_p (compare))
+ return true;
+
+ if (nonzero_p (cond))
+ return false;
+
+ compare = tree_simplify_using_condition_1 (cond, compare);
+
+ return nonzero_p (compare);
+}
+
/* Returns a constant upper bound on the value of expression VAL. VAL
is considered to be unsigned. If its type is signed, its value must
be nonnegative.
@@ -1554,8 +1572,11 @@ derive_constant_upper_bound (tree val, tree additional)
|| !implies_nonnegative_p (additional, op0))
return max;
- /* Canonicalize to OP0 - CST. */
+ /* Canonicalize to OP0 - CST. Consider CST to be signed, in order to
+ choose the most logical way how to treat this constant regardless
+ of the signedness of the type. */
cst = tree_to_double_int (op1);
+ cst = double_int_sext (cst, TYPE_PRECISION (type));
if (TREE_CODE (val) == PLUS_EXPR)
cst = double_int_neg (cst);
@@ -1568,7 +1589,7 @@ derive_constant_upper_bound (tree val, tree additional)
if (double_int_negative_p (cst))
return max;;
- /* Case OP0 + CST. We need to check that
+ /* OP0 + CST. We need to check that
BND <= MAX (type) - CST. */
mmax = double_int_add (max, double_int_neg (cst));
@@ -1579,9 +1600,27 @@ derive_constant_upper_bound (tree val, tree additional)
}
else
{
+ /* OP0 - CST, where CST >= 0.
+
+ If TYPE is signed, we have already verified that OP0 >= 0, and we
+ know that the result is nonnegative. This implies that
+ VAL <= BND - CST.
+
+ If TYPE is unsigned, we must additionally know that OP0 >= CST,
+ otherwise the operation underflows.
+ */
+
+ /* This should only happen if the type is unsigned; however, for
+ programs that use overflowing signed arithmetics even with
+ -fno-wrapv, this condition may also be true for signed values. */
if (double_int_ucmp (bnd, cst) < 0)
return max;
+ if (TYPE_UNSIGNED (type)
+ && !implies_ge_p (additional,
+ op0, double_int_to_tree (type, cst)))
+ return max;
+
bnd = double_int_add (bnd, double_int_neg (cst));
}