From eb897cfcf5b0777f1e1d25e0b3c64d233dd56ec0 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Mon, 30 May 2016 15:25:02 +0200 Subject: [PATCH] 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 --- gcc/ChangeLog | 6 ++++ gcc/tree-ssa-loop-ivcanon.c | 68 +++++++++++++++++++++++++++++++------ 2 files changed, 63 insertions(+), 11 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4c3a0314490..82d3683c73d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2016-05-30 Jan Hubicka + + * tree-ssa-loop-ivcanon.c (try_peel_loop): Correctly set wont_exit + for peeled copies; avoid underflow when updating estimates; correctly + scale loop profile. + 2016-05-30 Kugan Vivekanandarajah * tree-ssa-reassoc.ci (swap_ops_for_binary_stmt): Fix typo from commit diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c index 4673d022753..4cfdb27bb67 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. -- 2.30.2