diff options
author | Zdenek Dvorak <dvorakz@suse.cz> | 2006-06-19 20:32:20 +0200 |
---|---|---|
committer | Zdenek Dvorak <rakdver@gcc.gnu.org> | 2006-06-19 18:32:20 +0000 |
commit | 20fb52af9359cdf66e245f1779bbcd6f1a41de8b (patch) | |
tree | a31ea250ca70dd8f95b546f2b0488936821de9da | |
parent | dfa52cf9d1c5d14a6a8f905bcf84565ae7b0627c (diff) | |
download | gcc-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/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-niter.c | 43 |
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)); } |