diff options
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/loop_optimization3.adb | 15 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/loop_optimization3_pkg.adb | 8 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/loop_optimization3_pkg.ads | 5 | ||||
-rw-r--r-- | gcc/tree-flow.h | 1 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-ivopts.c | 41 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-niter.c | 2 |
8 files changed, 71 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 917031f..42f0b32 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2008-07-03 Eric Botcazou <ebotcazou@adacore.com> + + * tree-flow.h (loop_only_exit_p): Declare. + * tree-ssa-loop-niter.c (loop_only_exit_p): Make public. + * tree-ssa-loop-ivopts.c (may_eliminate_iv): Reinstate direct check on + the number of iterations if it is constant. Otherwise, if this is the + only possible exit of the loop, use the conservative estimate on the + number of iterations of the entire loop if available. + 2008-07-03 Richard Sandiford <rdsandiford@googlemail.com> * Makefile.in (libgcc.mvars): Add LIBGCC_SYNC and LIBGCC_SYNC_CFLAGS. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4f4e3b9..51e89e5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2008-07-03 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/loop_optimization3.adb: New test. + * gnat.dg/loop_optimization3_pkg.ad[sb]: New helper. + 2008-07-03 Uros Bizjak <ubizjak@gmail.com> PR target/36710 diff --git a/gcc/testsuite/gnat.dg/loop_optimization3.adb b/gcc/testsuite/gnat.dg/loop_optimization3.adb new file mode 100644 index 0000000..e69f535 --- /dev/null +++ b/gcc/testsuite/gnat.dg/loop_optimization3.adb @@ -0,0 +1,15 @@ +-- { dg-do run } +-- { dg-options "-O" } + +with Loop_Optimization3_Pkg; use Loop_Optimization3_Pkg; + +procedure Loop_Optimization3 is + + type Arr is array (Integer range -3 .. 3) of Integer; + C : constant Arr := (1, others => F(2)); + +begin + if C /= (1, 2, 2, 2, 2, 2, 2) then + raise Program_Error; + end if; +end; diff --git a/gcc/testsuite/gnat.dg/loop_optimization3_pkg.adb b/gcc/testsuite/gnat.dg/loop_optimization3_pkg.adb new file mode 100644 index 0000000..7a64815 --- /dev/null +++ b/gcc/testsuite/gnat.dg/loop_optimization3_pkg.adb @@ -0,0 +1,8 @@ +package body Loop_Optimization3_Pkg is + + function F (n : Integer) return Integer is + begin + return n; + end; + +end Loop_Optimization3_Pkg; diff --git a/gcc/testsuite/gnat.dg/loop_optimization3_pkg.ads b/gcc/testsuite/gnat.dg/loop_optimization3_pkg.ads new file mode 100644 index 0000000..90f4fc3 --- /dev/null +++ b/gcc/testsuite/gnat.dg/loop_optimization3_pkg.ads @@ -0,0 +1,5 @@ +package Loop_Optimization3_Pkg is + + function F (n : Integer) return Integer; + +end Loop_Optimization3_Pkg; diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index 9610547..5479c33 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -1039,6 +1039,7 @@ void tree_ssa_iv_optimize (void); unsigned tree_predictive_commoning (void); bool parallelize_loops (void); +bool loop_only_exit_p (const struct loop *, const_edge); bool number_of_iterations_exit (struct loop *, edge, struct tree_niter_desc *niter, bool); tree find_loop_niter (struct loop *, edge *); diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index 41c3794..ce5c05c 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -3745,13 +3745,12 @@ may_eliminate_iv (struct ivopts_data *data, tree nit, period; struct loop *loop = data->current_loop; aff_tree bnd; - double_int period_value, max_niter; if (TREE_CODE (cand->iv->step) != INTEGER_CST) return false; - /* For now works only for exits that dominate the loop latch. TODO -- extend - for other conditions inside loop body. */ + /* For now works only for exits that dominate the loop latch. + TODO: extend to other conditions inside loop body. */ ex_bb = bb_for_stmt (use->stmt); if (use->stmt != last_stmt (ex_bb) || TREE_CODE (use->stmt) != COND_EXPR) @@ -3769,19 +3768,33 @@ may_eliminate_iv (struct ivopts_data *data, if (!nit) return false; - /* Determine whether we may use the variable to test whether niter iterations - elapsed. This is the case iff the period of the induction variable is - greater than the number of iterations. */ + /* Determine whether we can use the variable to test the exit condition. + This is the case iff the period of the induction variable is greater + than the number of iterations for which the exit condition is true. */ period = iv_period (cand->iv); - if (!period) - return false; - /* Compare the period with the estimate on the number of iterations of the - loop. */ - if (!estimated_loop_iterations (loop, true, &max_niter)) - return false; - period_value = tree_to_double_int (period); - if (double_int_ucmp (period_value, max_niter) <= 0) + /* If the number of iterations is constant, compare against it directly. */ + if (TREE_CODE (nit) == INTEGER_CST) + { + if (!tree_int_cst_lt (nit, period)) + return false; + } + + /* If not, and if this is the only possible exit of the loop, see whether + we can get a conservative estimate on the number of iterations of the + entire loop and compare against that instead. */ + else if (loop_only_exit_p (loop, exit)) + { + double_int period_value, max_niter; + if (!estimated_loop_iterations (loop, true, &max_niter)) + return false; + period_value = tree_to_double_int (period); + if (double_int_ucmp (max_niter, period_value) >= 0) + return false; + } + + /* Otherwise, punt. */ + else return false; cand_value_at (loop, cand, use->stmt, nit, &bnd); diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index 74153fd..80b45c2 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -1672,7 +1672,7 @@ simplify_using_outer_evolutions (struct loop *loop, tree expr) /* Returns true if EXIT is the only possible exit from LOOP. */ -static bool +bool loop_only_exit_p (const struct loop *loop, const_edge exit) { basic_block *body; |