summaryrefslogtreecommitdiff
path: root/gcc/loop-unroll.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2012-10-08 18:09:41 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2012-10-08 18:09:41 +0000
commita9ef98778deaf3b83ca1349ad09e7b15ce908158 (patch)
treeeb195a552c62fbc24735e6506d9aa729f6806b75 /gcc/loop-unroll.c
parent514d377a3dcb7aeb49113b23d70fc87f6304a30e (diff)
downloadgcc-a9ef98778deaf3b83ca1349ad09e7b15ce908158.tar.gz
* loop-unswitch.c (unswitch_single_loop): Use
estimated_loop_iterations_int to prevent unswitching when loop is known to not roll. * tree-ssa-loop-niter.c (estimated_loop_iterations): Do not segfault when SCEV is not initialized. (max_loop_iterations): Likewise. * tree-ssa-loop-unswitch.c (tree_ssa_unswitch_loops): Use estimated_loop_iterations_int to prevent unswithcing when loop is known to not roll. * tree-scalar-evolution.c (scev_initialized_p): New function. * tree-scalar-evolution.h (scev_initialized_p): Likewise. * loop-unroll.c (decide_peel_once_rolling): Use max_loop_iterations_int. (unroll_loop_constant_iterations): Update nb_iterations_upper_bound and nb_iterations_estimate. (decide_unroll_runtime_iterations): Use estimated_loop_iterations or max_loop_iterations; (unroll_loop_runtime_iterations): fix profile updating. (decide_peel_simple): Use estimated_loop_iterations and max_loop_iterations. (decide_unroll_stupid): Use estimated_loop_iterations ad max_loop_iterations. * loop-doloop.c (doloop_modify): Use max_loop_iterations_int. (doloop_optimize): Likewise. * loop-iv.c (iv_number_of_iterations): Use record_niter_bound. (find_simple_exit): Likewise. * cfgloop.h (struct niter_desc): Remove niter_max. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@192219 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/loop-unroll.c')
-rw-r--r--gcc/loop-unroll.c83
1 files changed, 65 insertions, 18 deletions
diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c
index a09192597dd..b9ac22b8255 100644
--- a/gcc/loop-unroll.c
+++ b/gcc/loop-unroll.c
@@ -341,7 +341,8 @@ decide_peel_once_rolling (struct loop *loop, int flags ATTRIBUTE_UNUSED)
|| desc->assumptions
|| desc->infinite
|| !desc->const_iter
- || desc->niter != 0)
+ || (desc->niter != 0
+ && max_loop_iterations_int (loop) != 0))
{
if (dump_file)
fprintf (dump_file,
@@ -695,7 +696,13 @@ unroll_loop_constant_iterations (struct loop *loop)
desc->noloop_assumptions = NULL_RTX;
desc->niter -= exit_mod;
- desc->niter_max -= exit_mod;
+ loop->nb_iterations_upper_bound -= double_int::from_uhwi (exit_mod);
+ if (loop->any_estimate
+ && double_int::from_uhwi (exit_mod).ule
+ (loop->nb_iterations_estimate))
+ loop->nb_iterations_estimate -= double_int::from_uhwi (exit_mod);
+ else
+ loop->any_estimate = false;
}
SET_BIT (wont_exit, 1);
@@ -733,7 +740,12 @@ unroll_loop_constant_iterations (struct loop *loop)
apply_opt_in_copies (opt_info, exit_mod + 1, false, false);
desc->niter -= exit_mod + 1;
- desc->niter_max -= exit_mod + 1;
+ if (loop->any_estimate
+ && double_int::from_uhwi (exit_mod + 1).ule
+ (loop->nb_iterations_estimate))
+ loop->nb_iterations_estimate -= double_int::from_uhwi (exit_mod + 1);
+ else
+ loop->any_estimate = false;
desc->noloop_assumptions = NULL_RTX;
SET_BIT (wont_exit, 0);
@@ -782,7 +794,15 @@ unroll_loop_constant_iterations (struct loop *loop)
}
desc->niter /= max_unroll + 1;
- desc->niter_max /= max_unroll + 1;
+ loop->nb_iterations_upper_bound
+ = loop->nb_iterations_upper_bound.udiv (double_int::from_uhwi (exit_mod
+ + 1),
+ FLOOR_DIV_EXPR);
+ if (loop->any_estimate)
+ loop->nb_iterations_estimate
+ = loop->nb_iterations_estimate.udiv (double_int::from_uhwi (exit_mod
+ + 1),
+ FLOOR_DIV_EXPR);
desc->niter_expr = GEN_INT (desc->niter);
/* Remove the edges. */
@@ -803,6 +823,7 @@ decide_unroll_runtime_iterations (struct loop *loop, int flags)
{
unsigned nunroll, nunroll_by_av, i;
struct niter_desc *desc;
+ double_int iterations;
if (!(flags & UAP_UNROLL))
{
@@ -856,9 +877,10 @@ decide_unroll_runtime_iterations (struct loop *loop, int flags)
}
/* If we have profile feedback, check whether the loop rolls. */
- if ((loop->header->count
- && expected_loop_iterations (loop) < 2 * nunroll)
- || desc->niter_max < 2 * nunroll)
+ if ((estimated_loop_iterations (loop, &iterations)
+ || max_loop_iterations (loop, &iterations))
+ && iterations.fits_shwi ()
+ && iterations.to_shwi () <= 2 * nunroll)
{
if (dump_file)
fprintf (dump_file, ";; Not unrolling loop, doesn't roll\n");
@@ -1092,6 +1114,7 @@ unroll_loop_runtime_iterations (struct loop *loop)
single_pred_edge (swtch)->probability = REG_BR_PROB_BASE - p;
e = make_edge (swtch, preheader,
single_succ_edge (swtch)->flags & EDGE_IRREDUCIBLE_LOOP);
+ e->count = RDIV (preheader->count * REG_BR_PROB_BASE, p);
e->probability = p;
}
@@ -1111,6 +1134,7 @@ unroll_loop_runtime_iterations (struct loop *loop)
single_succ_edge (swtch)->probability = REG_BR_PROB_BASE - p;
e = make_edge (swtch, preheader,
single_succ_edge (swtch)->flags & EDGE_IRREDUCIBLE_LOOP);
+ e->count = RDIV (preheader->count * REG_BR_PROB_BASE, p);
e->probability = p;
}
@@ -1172,13 +1196,26 @@ unroll_loop_runtime_iterations (struct loop *loop)
desc->niter_expr =
simplify_gen_binary (UDIV, desc->mode, old_niter,
GEN_INT (max_unroll + 1));
- desc->niter_max /= max_unroll + 1;
+ loop->nb_iterations_upper_bound
+ = loop->nb_iterations_upper_bound.udiv (double_int::from_uhwi (max_unroll
+ + 1),
+ FLOOR_DIV_EXPR);
+ if (loop->any_estimate)
+ loop->nb_iterations_estimate
+ = loop->nb_iterations_estimate.udiv (double_int::from_uhwi (max_unroll
+ + 1),
+ FLOOR_DIV_EXPR);
if (exit_at_end)
{
desc->niter_expr =
simplify_gen_binary (MINUS, desc->mode, desc->niter_expr, const1_rtx);
desc->noloop_assumptions = NULL_RTX;
- desc->niter_max--;
+ --loop->nb_iterations_upper_bound;
+ if (loop->any_estimate
+ && loop->nb_iterations_estimate != double_int_zero)
+ --loop->nb_iterations_estimate;
+ else
+ loop->any_estimate = false;
}
if (dump_file)
@@ -1196,6 +1233,7 @@ decide_peel_simple (struct loop *loop, int flags)
{
unsigned npeel;
struct niter_desc *desc;
+ double_int iterations;
if (!(flags & UAP_PEEL))
{
@@ -1239,23 +1277,30 @@ decide_peel_simple (struct loop *loop, int flags)
return;
}
- if (loop->header->count)
+ /* If we have realistic estimate on number of iterations, use it. */
+ if (estimated_loop_iterations (loop, &iterations))
{
- unsigned niter = expected_loop_iterations (loop);
- if (niter + 1 > npeel)
+ if (!iterations.fits_shwi ()
+ || iterations.to_shwi () + 1 > npeel)
{
if (dump_file)
{
fprintf (dump_file, ";; Not peeling loop, rolls too much (");
fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) (niter + 1));
+ (HOST_WIDEST_INT) (iterations.to_shwi () + 1));
fprintf (dump_file, " iterations > %d [maximum peelings])\n",
npeel);
}
return;
}
- npeel = niter + 1;
- }
+ npeel = iterations.to_shwi () + 1;
+ }
+ /* If we have small enough bound on iterations, we can still peel (completely
+ unroll). */
+ else if (max_loop_iterations (loop, &iterations)
+ && iterations.fits_shwi ()
+ && iterations.to_shwi () + 1 <= npeel)
+ npeel = iterations.to_shwi () + 1;
else
{
/* For now we have no good heuristics to decide whether loop peeling
@@ -1349,6 +1394,7 @@ decide_unroll_stupid (struct loop *loop, int flags)
{
unsigned nunroll, nunroll_by_av, i;
struct niter_desc *desc;
+ double_int iterations;
if (!(flags & UAP_UNROLL_ALL))
{
@@ -1401,9 +1447,10 @@ decide_unroll_stupid (struct loop *loop, int flags)
}
/* If we have profile feedback, check whether the loop rolls. */
- if ((loop->header->count
- && expected_loop_iterations (loop) < 2 * nunroll)
- || desc->niter_max < 2 * nunroll)
+ if ((estimated_loop_iterations (loop, &iterations)
+ || max_loop_iterations (loop, &iterations))
+ && iterations.fits_shwi ()
+ && iterations.to_shwi () <= 2 * nunroll)
{
if (dump_file)
fprintf (dump_file, ";; Not unrolling loop, doesn't roll\n");