On Mon, May 30, 2016 at 02:38:40PM +0200, Jan Hubicka wrote: > Hi, > this patch fixes profile updates in loop peeling pass. First it correctly > set wont_exit which can only be set when we know the number of iterations > tested by EXIT and this number is higher than maximal number of iterations > (an unlikely case which is usually removed by VRP pass or earlier cunroll). > > Second problem is that we determine number of peelings as number of estimated > iterations + 1. After peeling we currently underflow updating estimates > which makes them to be re-computed later to bogus values. > > Last change is way we netermine profile for the new loop header. We used to > drop the loop frequency 1/1000. This patch makes use of the info on remaining > entry edges to the loop. > > While working on this I noticed that try_peel_loop has tendency to iterate > and peel one loop many times. I will prepare followup for that. Also > testcases will come once I commit the change enabling loop peeling at -O3 > by using likely estimates. > > Bootstrapped/regtested x86_64-linux. > > * tree-ssa-loop-ivcanon.c (try_peel_loop): Correctly set wont_exit > for peeled copies; avoid underflow when updating estimates; correctly > scale loop profile. > > Index: tree-ssa-loop-ivcanon.c > =================================================================== > --- tree-ssa-loop-ivcanon.c (revision 236874) > +++ tree-ssa-loop-ivcanon.c (working copy)
> @@ -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)) shouldn't this compare loop->nb_iterations_upper_bound to npeel instead of 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)) nb_iterations_likely_upper_bound ? What am i missing? > + loop->nb_iterations_likely_upper_bound -= npeel; > + else > + { > + loop->any_estimate = true; > + loop->nb_iterations_estimate = 0; > + loop->nb_iterations_likely_upper_bound = 0; I don't immediately understand this else branch but didn't try hard. Can you please explain or maybe add a comment? thanks, > + } > + } > + 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.