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 ())
                        {

Reply via email to