aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-loop-ivcanon.c
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@ucw.cz>2016-05-30 15:25:02 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2016-05-30 13:25:02 +0000
commiteb897cfcf5b0777f1e1d25e0b3c64d233dd56ec0 (patch)
treed72e73c8aa02c293d7c033c633958574e92570c2 /gcc/tree-ssa-loop-ivcanon.c
parent5750980942ac1ed0ddb4b42c8089c522509eeca5 (diff)
downloadgcc-eb897cfcf5b0777f1e1d25e0b3c64d233dd56ec0.zip
gcc-eb897cfcf5b0777f1e1d25e0b3c64d233dd56ec0.tar.gz
gcc-eb897cfcf5b0777f1e1d25e0b3c64d233dd56ec0.tar.bz2
tree-ssa-loop-ivcanon.c (try_peel_loop): Correctly set wont_exit for peeled copies...
* tree-ssa-loop-ivcanon.c (try_peel_loop): Correctly set wont_exit for peeled copies; avoid underflow when updating estimates; correctly scale loop profile. From-SVN: r236878
Diffstat (limited to 'gcc/tree-ssa-loop-ivcanon.c')
-rw-r--r--gcc/tree-ssa-loop-ivcanon.c68
1 files changed, 57 insertions, 11 deletions
diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c
index 4673d02..4cfdb27 100644
--- a/gcc/tree-ssa-loop-ivcanon.c
+++ b/gcc/tree-ssa-loop-ivcanon.c
@@ -970,7 +970,9 @@ try_peel_loop (struct loop *loop,
if (!flag_peel_loops || PARAM_VALUE (PARAM_MAX_PEEL_TIMES) <= 0)
return false;
- /* Peel only innermost loops. */
+ /* Peel only innermost loops.
+ While the code is perfectly capable of peeling non-innermost loops,
+ the heuristics would probably need some improvements. */
if (loop->inner)
{
if (dump_file)
@@ -1029,13 +1031,23 @@ try_peel_loop (struct loop *loop,
/* Duplicate possibly eliminating the exits. */
initialize_original_copy_tables ();
wont_exit = sbitmap_alloc (npeel + 1);
- bitmap_ones (wont_exit);
- bitmap_clear_bit (wont_exit, 0);
+ if (exit && niter
+ && TREE_CODE (niter) == INTEGER_CST
+ && wi::leu_p (npeel, wi::to_widest (niter)))
+ {
+ bitmap_ones (wont_exit);
+ if (wi::eq_p (wi::to_widest (niter), npeel))
+ bitmap_clear_bit (wont_exit, 0);
+ }
+ else
+ {
+ exit = NULL;
+ bitmap_clear (wont_exit);
+ }
if (!gimple_duplicate_loop_to_header_edge (loop, loop_preheader_edge (loop),
npeel, wont_exit,
exit, &to_remove,
- DLTHE_FLAG_UPDATE_FREQ
- | DLTHE_FLAG_COMPLETTE_PEEL))
+ DLTHE_FLAG_UPDATE_FREQ))
{
free_original_copy_tables ();
free (wont_exit);
@@ -1053,14 +1065,48 @@ try_peel_loop (struct loop *loop,
fprintf (dump_file, "Peeled loop %d, %i times.\n",
loop->num, (int) npeel);
}
+ if (loop->any_estimate)
+ {
+ if (wi::ltu_p (npeel, loop->nb_iterations_estimate))
+ loop->nb_iterations_estimate -= npeel;
+ else
+ loop->nb_iterations_estimate = 0;
+ }
if (loop->any_upper_bound)
- loop->nb_iterations_upper_bound -= npeel;
+ {
+ if (wi::ltu_p (npeel, loop->nb_iterations_estimate))
+ loop->nb_iterations_upper_bound -= npeel;
+ else
+ loop->nb_iterations_upper_bound = 0;
+ }
if (loop->any_likely_upper_bound)
- loop->nb_iterations_likely_upper_bound -= npeel;
- loop->nb_iterations_estimate = 0;
- /* Make sure to mark loop cold so we do not try to peel it more. */
- scale_loop_profile (loop, 1, 0);
- loop->header->count = 0;
+ {
+ if (wi::ltu_p (npeel, loop->nb_iterations_estimate))
+ loop->nb_iterations_likely_upper_bound -= npeel;
+ else
+ {
+ loop->any_estimate = true;
+ loop->nb_iterations_estimate = 0;
+ loop->nb_iterations_likely_upper_bound = 0;
+ }
+ }
+ gcov_type entry_count = 0;
+ int entry_freq = 0;
+
+ edge_iterator ei;
+ FOR_EACH_EDGE (e, ei, loop->header->preds)
+ if (e->src != loop->latch)
+ {
+ entry_count += e->src->count;
+ entry_freq += e->src->frequency;
+ gcc_assert (!flow_bb_inside_loop_p (loop, e->src));
+ }
+ int scale = 1;
+ if (loop->header->count)
+ scale = RDIV (entry_count * REG_BR_PROB_BASE, loop->header->count);
+ else if (loop->header->frequency)
+ scale = RDIV (entry_freq * REG_BR_PROB_BASE, loop->header->frequency);
+ scale_loop_profile (loop, scale, 0);
return true;
}
/* Adds a canonical induction variable to LOOP if suitable.