Hi, On Wed, Sep 30 2020, Jan Hubicka wrote: >> This patch enhances the ability of IPA to reason under what conditions >> loops in a function have known iteration counts or strides because it >> replaces single predicates which currently hold conjunction of >> predicates for all loops with vectors capable of holding multiple >> predicates, each with a cumulative frequency of loops with the >> property. >> >> This second property is then used by IPA-CP to much more aggressively >> boost its heuristic score for cloning opportunities which make >> iteration counts or strides of frequent loops compile time constant. >> >> gcc/ChangeLog: >> >> 2020-09-03 Martin Jambor <mjam...@suse.cz> >> >> * ipa-fnsummary.h (ipa_freqcounting_predicate): New type. >> (ipa_fn_summary): Change the type of loop_iterations and loop_strides >> to vectors of ipa_freqcounting_predicate. >> (ipa_fn_summary::ipa_fn_summary): Construct the new vectors. >> (ipa_call_estimates): New fields loops_with_known_iterations and >> loops_with_known_strides. >> * ipa-cp.c (hint_time_bonus): Multiply param_ipa_cp_loop_hint_bonus >> with the expected frequencies of loops with known iteration count or >> stride. >> * ipa-fnsummary.c (add_freqcounting_predicate): New function. >> (ipa_fn_summary::~ipa_fn_summary): Release the new vectors instead of >> just two predicates. >> (remap_hint_predicate_after_duplication): Replace with function >> remap_freqcounting_preds_after_dup. >> (ipa_fn_summary_t::duplicate): Use it or duplicate new vectors. >> (ipa_dump_fn_summary): Dump the new vectors. >> (analyze_function_body): Compute the loop property vectors. >> (ipa_call_context::estimate_size_and_time): Calculate also >> loops_with_known_iterations and loops_with_known_strides. Adjusted >> dumping accordinly. >> (remap_hint_predicate): Replace with function >> remap_freqcounting_predicate. >> (ipa_merge_fn_summary_after_inlining): Use it. >> (inline_read_section): Stream loopcounting vectors instead of two >> simple predicates. >> (ipa_fn_summary_write): Likewise. >> * params.opt (ipa-max-loop-predicates): New parameter. >> * doc/invoke.texi (ipa-max-loop-predicates): Document new param. >> >> diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c >> index 6082f34d63f..bbbb94aa930 100644 >> --- a/gcc/ipa-fnsummary.c >> +++ b/gcc/ipa-fnsummary.c >> @@ -310,6 +310,36 @@ set_hint_predicate (predicate **p, predicate >> new_predicate) >> } >> } >> >> +/* Find if NEW_PREDICATE is already in V and if so, increment its freq. >> + Otherwise add a new item to the vector with this predicate and frerq >> equal >> + to add_freq, unless the number of predicates would exceed >> MAX_NUM_PREDICATES >> + in which case the function does nothing. */ >> + >> +static void >> +add_freqcounting_predicate (vec<ipa_freqcounting_predicate, va_gc> **v, >> + const predicate &new_predicate, sreal add_freq, >> + unsigned max_num_predicates) >> +{ >> + if (new_predicate == false || new_predicate == true) >> + return; >> + ipa_freqcounting_predicate *f; >> + for (int i = 0; vec_safe_iterate (*v, i, &f); i++) >> + if (new_predicate == f->predicate) >> + { >> + f->freq += add_freq; >> + return; >> + } >> + if (vec_safe_length (*v) >= max_num_predicates) >> + /* Too many different predicates to account for. */ >> + return; >> + >> + ipa_freqcounting_predicate fcp; >> + fcp.predicate = NULL; >> + set_hint_predicate (&fcp.predicate, new_predicate); >> + fcp.freq = add_freq; >> + vec_safe_push (*v, fcp); >> + return; >> +} >> >> /* Compute what conditions may or may not hold given information about >> parameters. RET_CLAUSE returns truths that may hold in a specialized >> copy, >> @@ -710,13 +740,17 @@ ipa_call_summary::~ipa_call_summary () >> >> ipa_fn_summary::~ipa_fn_summary () >> { >> - if (loop_iterations) >> - edge_predicate_pool.remove (loop_iterations); >> - if (loop_stride) >> - edge_predicate_pool.remove (loop_stride); >> + unsigned len = vec_safe_length (loop_iterations); >> + for (unsigned i = 0; i < len; i++) >> + edge_predicate_pool.remove ((*loop_iterations)[i].predicate); >> + len = vec_safe_length (loop_strides); >> + for (unsigned i = 0; i < len; i++) >> + edge_predicate_pool.remove ((*loop_strides)[i].predicate); > > For edges predicates are pointers since most of them have no interesting > predicate and thus NULL is more compact. I guess here it would make > snese to make predicates inline. Is there a problem with vectors not > liking non-pods? >> vec_free (conds); >> vec_free (size_time_table); >> vec_free (call_size_time_table); >> + vec_free (loop_iterations); >> + vec_free (loop_strides); > > However auto_vecs should work in the brave new C++ world.
Well, the summary lives in GC memory, so I don't think I can put auto_vecs there. I will add a note to look into putting a predicate directly instead as a pointer to ipa_freqcounting_predicate as a follow-up patch. > > The patch looks reasonable to me. Did you check how much memory it > consumes building bigger projects? Also I am bit worried about our > ability to use it reasonably in the heuristics since it is quite > complicated value... Thanks! Martin