Hi, this patch fixes issue with speculation and x264. With profile feedback we first introduce speculative calls to mc_chroma which is called indirectly. Then we propagate constants acorss these calls (which is useful transform) but then speculation_useful_p decides that these speculations are not useful and we end up calling unspecialized version.
This patch updates speculation_useful_p to consider edges redirected earlier to clones as useful, since we can expect that ipa-cp knows what it is doing (originally it only looked for inlined calls). I also noticed that we want to keep edges even if they are not hot. Finally I noticed a typo in computing target in code which intends to keep devirtualized calls to functions where we propagated pureness/constness. Newly we also track ipa-modref summaries as they also may be useful. Bootstrapped/regtested x86_64-linux, comitted. gcc/ChangeLog: PR ipa/119147 * ipa-inline.cc: Include ipa-modref-tree.h and ipa-modref.h. (speculation_useful_p): If target is a clone, speculation is usef; fix mixup of caller and callee; speculate also calls not considered hot; consider modref summary also possibly useful for optimization. * ipa-profile.cc (ipa_profile): Keep non-hot speculations. diff --git a/gcc/ipa-inline.cc b/gcc/ipa-inline.cc index 163129540ac..9e6e85d714b 100644 --- a/gcc/ipa-inline.cc +++ b/gcc/ipa-inline.cc @@ -121,6 +121,8 @@ along with GCC; see the file COPYING3. If not see #include "attribs.h" #include "asan.h" #include "ipa-strub.h" +#include "ipa-modref-tree.h" +#include "ipa-modref.h" /* Inliner uses greedy algorithm to inline calls in a priority order. Badness is used as the key in a Fibonacci heap which roughly corresponds @@ -1941,23 +1943,30 @@ heap_edge_removal_hook (struct cgraph_edge *e, void *data) bool speculation_useful_p (struct cgraph_edge *e, bool anticipate_inlining) { - /* If we have already decided to inline the edge, it seems useful. */ - if (!e->inline_failed) + /* If we have already decided to inline the edge, it seems useful. + Also if ipa-cp or other pass worked hard enough to produce a clone, + we already decided this is a good idea. */ + if (!e->inline_failed + || e->callee->clone_of) return true; enum availability avail; struct cgraph_node *target = e->callee->ultimate_alias_target (&avail, - e->caller); + e->callee); gcc_assert (e->speculative && !e->indirect_unknown_callee); - if (!e->maybe_hot_p ()) + /* Even if calll statement is not hot, we can still have useful speculation + in cases where a lot of time is spent is callee. + Do not check maybe_hot_p. */ + if (!e->count.nonzero_p ()) return false; /* See if IP optimizations found something potentially useful about the - function. For now we look only for CONST/PURE flags. Almost everything - else we propagate is useless. */ - if (avail >= AVAIL_AVAILABLE) + function. Do this only if the call seems hot since this is about + optimizing the code surrounding call site rahter than improving + callee. */ + if (avail >= AVAIL_AVAILABLE && e->maybe_hot_p ()) { int ecf_flags = flags_from_decl_or_type (target->decl); if (ecf_flags & ECF_CONST) @@ -1972,12 +1981,18 @@ speculation_useful_p (struct cgraph_edge *e, bool anticipate_inlining) ->ecf_flags & ECF_PURE)) return true; } + else if (get_modref_function_summary (target)) + return true; } /* If we did not managed to inline the function nor redirect to an ipa-cp clone (that are seen by having local flag set), it is probably pointless to inline it unless hardware is missing - indirect call predictor. */ - if (!anticipate_inlining && !target->local) + indirect call predictor. + + At this point we know we will not dispatch into faster version of + callee, so if call itself is not hot, we definitely can give up + speculating. */ + if (!anticipate_inlining && (!target->local || !e->maybe_hot_p ())) return false; /* For overwritable targets there is not much to do. */ if (!can_inline_edge_p (e, false) diff --git a/gcc/ipa-profile.cc b/gcc/ipa-profile.cc index 51616def254..08638667f65 100644 --- a/gcc/ipa-profile.cc +++ b/gcc/ipa-profile.cc @@ -882,13 +882,6 @@ ipa_profile (void) "Not speculating: " "probability is too low.\n"); } - else if (!e->maybe_hot_p ()) - { - nuseless++; - if (dump_file) - fprintf (dump_file, - "Not speculating: call is cold.\n"); - } else if (n2->get_availability () <= AVAIL_INTERPOSABLE && n2->can_be_discarded_p ()) {