aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr45427.c29
-rw-r--r--gcc/tree-ssa-loop-niter.c69
4 files changed, 93 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 71dc958..fe16d48 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2010-08-30 Zdenek Dvorak <ook@ucw.cz>
+
+ PR tree-optimization/45427
+ * tree-ssa-loop-niter.c (number_of_iterations_ne_max): Rewritten.
+ Handle the case that the exit is never taken correctly.
+ (number_of_iterations_ne): Pass exit_must_be_taken to
+ number_of_iterations_ne_max.
+
2010-08-31 Catherine Moore <clm@codesourcery.com>
* config/mips/mips.h (BASE_DRIVER_SELF_SPECS):
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9bbb54b..fd8fecb 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2010-08-30 Zdenek Dvorak <ook@ucw.cz>
+
+ PR tree-optimization/45427
+ * gcc.dg/tree-ssa/pr45427.c: New test.
+
2010-08-30 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/45043
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr45427.c b/gcc/testsuite/gcc.dg/tree-ssa/pr45427.c
new file mode 100644
index 0000000..0952b5a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr45427.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-cunrolli-details" } */
+
+extern void abort (void);
+int __attribute__((noinline,noclone))
+foo (char *p)
+{
+ int h = 0;
+ do
+ {
+ if (*p == '\0')
+ break;
+ ++h;
+ if (p == 0)
+ abort ();
+ ++p;
+ }
+ while (1);
+ return h;
+}
+int main()
+{
+ if (foo("a") != 1)
+ abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "bounded by 0" 0 "cunrolli"} } */
+/* { dg-final { cleanup-tree-dump "cunrolli" } } */
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index d23592d..2118b97 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -536,22 +536,46 @@ inverse (tree x, tree mask)
}
/* Derives the upper bound BND on the number of executions of loop with exit
- condition S * i <> C, assuming that this exit is taken. If
- NO_OVERFLOW is true, then the control variable of the loop does not
- overflow. If NO_OVERFLOW is true or BNDS.below >= 0, then BNDS.up
- contains the upper bound on the value of C. */
+ condition S * i <> C. If NO_OVERFLOW is true, then the control variable of
+ the loop does not overflow. EXIT_MUST_BE_TAKEN is true if we are guaranteed
+ that the loop ends through this exit, i.e., the induction variable ever
+ reaches the value of C.
+
+ The value C is equal to final - base, where final and base are the final and
+ initial value of the actual induction variable in the analysed loop. BNDS
+ bounds the value of this difference when computed in signed type with
+ unbounded range, while the computation of C is performed in an unsigned
+ type with the range matching the range of the type of the induction variable.
+ In particular, BNDS.up contains an upper bound on C in the following cases:
+ -- if the iv must reach its final value without overflow, i.e., if
+ NO_OVERFLOW && EXIT_MUST_BE_TAKEN is true, or
+ -- if final >= base, which we know to hold when BNDS.below >= 0. */
static void
number_of_iterations_ne_max (mpz_t bnd, bool no_overflow, tree c, tree s,
- bounds *bnds)
+ bounds *bnds, bool exit_must_be_taken)
{
double_int max;
mpz_t d;
+ bool bnds_u_valid = ((no_overflow && exit_must_be_taken)
+ || mpz_sgn (bnds->below) >= 0);
- /* If the control variable does not overflow, the number of iterations is
- at most c / s. Otherwise it is at most the period of the control
- variable. */
- if (!no_overflow && !multiple_of_p (TREE_TYPE (c), c, s))
+ if (multiple_of_p (TREE_TYPE (c), c, s))
+ {
+ /* If C is an exact multiple of S, then its value will be reached before
+ the induction variable overflows (unless the loop is exited in some
+ other way before). Note that the actual induction variable in the
+ loop (which ranges from base to final instead of from 0 to C) may
+ overflow, in which case BNDS.up will not be giving a correct upper
+ bound on C; thus, BNDS_U_VALID had to be computed in advance. */
+ no_overflow = true;
+ exit_must_be_taken = true;
+ }
+
+ /* If the induction variable can overflow, the number of iterations is at
+ most the period of the control variable (or infinite, but in that case
+ the whole # of iterations analysis will fail). */
+ if (!no_overflow)
{
max = double_int_mask (TYPE_PRECISION (TREE_TYPE (c))
- tree_low_cst (num_ending_zeros (s), 1));
@@ -559,14 +583,22 @@ number_of_iterations_ne_max (mpz_t bnd, bool no_overflow, tree c, tree s,
return;
}
- /* Determine the upper bound on C. */
- if (no_overflow || mpz_sgn (bnds->below) >= 0)
- mpz_set (bnd, bnds->up);
- else if (TREE_CODE (c) == INTEGER_CST)
- mpz_set_double_int (bnd, tree_to_double_int (c), true);
- else
- mpz_set_double_int (bnd, double_int_mask (TYPE_PRECISION (TREE_TYPE (c))),
- true);
+ /* Now we know that the induction variable does not overflow, so the loop
+ iterates at most (range of type / S) times. */
+ mpz_set_double_int (bnd, double_int_mask (TYPE_PRECISION (TREE_TYPE (c))),
+ true);
+
+ /* If the induction variable is guaranteed to reach the value of C before
+ overflow, ... */
+ if (exit_must_be_taken)
+ {
+ /* ... then we can strenghten this to C / S, and possibly we can use
+ the upper bound on C given by BNDS. */
+ if (TREE_CODE (c) == INTEGER_CST)
+ mpz_set_double_int (bnd, tree_to_double_int (c), true);
+ else if (bnds_u_valid)
+ mpz_set (bnd, bnds->up);
+ }
mpz_init (d);
mpz_set_double_int (d, tree_to_double_int (s), true);
@@ -618,7 +650,8 @@ number_of_iterations_ne (tree type, affine_iv *iv, tree final,
}
mpz_init (max);
- number_of_iterations_ne_max (max, iv->no_overflow, c, s, bnds);
+ number_of_iterations_ne_max (max, iv->no_overflow, c, s, bnds,
+ exit_must_be_taken);
niter->max = mpz_get_double_int (niter_type, max, false);
mpz_clear (max);