> Hi Honza,
> 
> 
> This is an alternative patch  ICE with  speculative edges are not adjacent.
> 
> The root cause of this failure is the addition of speculative edges
> without verifying if they are already speculative in IPA-devirt pass. Since
> Profile-Guided Optimization (PGO) already disables
> flag_devirtualize_speculatively, the most stable fix for the current
> stage of GCC development is to adopt the same approach and disable
> the flags.
> 
> This issue is reproducible during an autoprofile bootstrap of GCC.
> The patch has been validated through bootstrap and regression testing
> on aarch64-gnu-linux.
> 
> Is this acceptable for trunk?
> 
> gcc/ChangeLog:
> 
> 2026-01-05  Kugan Vivekanandarajah  <[email protected]>
> 
>         * opts.cc (common_handle_option): Unset 
> flag_devirtualize_speculatively
>         and flag_speculatively_call_stored_functions for AutoFDO
>         like done in PGO.
Hello,
I finally got to reproduce the problem.

As discussed, in general the speculative devirtualization is intended to
turn itself off on calls already speculated, so it should not interfere
with auto-fdo (or normal PGO).  We only disable with with PGO since all
relevant calls should be handled by PGO given that it works with quite
complete information, so all the other specualizations should be either
wrong or in cold code.  We may want to enable it with -fprofile-use
-fprofile-partial-training

One problem is that simple call speculation does not turn itself off and
it seems to trigger quite few times during autoprofiledbootstrap.  
I fixed it by the attached patch.

Second problem is likely in the profile merging (but it does not
reproduce in the bootstrap for me).  Auto-fdo's devirtualization is
limited to devirtualization within single translation unit (which is
somehting we want to fix next stage1 - we know the symbol name and can
attach it to the histogram and hande at IPA time). Until that however it
may happen that call within the same comdat is auto-fdo devirtualized in
one unit but differently in another.  In this case profile merging code
should merge both profiles (i.e. one speculated by auto-fdo and other by
static heuristics). The logic seems ok except that it does not check the
consecutivity.

Bootstrapped/regtested x86_64-linux

gcc/ChangeLog:

        * ipa-devirt.cc (ipa_devirt): Improve statistics for multi-target
        devirtualization; do not simple-call devirtualize already devirtualized 
calls.

diff --git a/gcc/ipa-devirt.cc b/gcc/ipa-devirt.cc
index a7cb2697813..8577e9b30fb 100644
--- a/gcc/ipa-devirt.cc
+++ b/gcc/ipa-devirt.cc
@@ -3845,23 +3845,21 @@ ipa_devirt (void)
               with the speculation.  */
            if (e->speculative)
              {
-               bool found = false;
                for (cgraph_node * likely_target: likely_targets)
                  if (e->speculative_call_for_target (likely_target))
                    {
-                     found = true;
-                     break;
+                     fprintf (dump_file,
+                              "We agree with speculation on target %s\n\n",
+                              likely_target->dump_name ());
+                     stats.nok++;
+                   }
+                 else
+                   {
+                     fprintf (dump_file,
+                              "We disagree with speculation on target %s\n\n",
+                              likely_target->dump_name ());
+                     stats.nwrong++;
                    }
-               if (found)
-                 {
-                   fprintf (dump_file, "We agree with speculation\n\n");
-                   stats.nok++;
-                 }
-               else
-                 {
-                   fprintf (dump_file, "We disagree with speculation\n\n");
-                   stats.nwrong++;
-                 }
                continue;
              }
            bool first = true;
@@ -3908,6 +3906,16 @@ ipa_devirt (void)
        else if (cgraph_simple_indirect_info *sii
                 = dyn_cast <cgraph_simple_indirect_info *> (e->indirect_info))
          {
+           if (e->speculative)
+             {
+               if (dump_file)
+                 fprintf (dump_file, "Call is already speculated\n\n");
+               stats.nspeculated++;
+
+               /* When dumping see if we agree with speculation.  */
+               if (!dump_file)
+                 continue;
+             }
            if (!sii->fnptr_loaded_from_record
                || !opt_for_fn (n->decl,
                                flag_speculatively_call_stored_functions))
@@ -3930,6 +3938,20 @@ ipa_devirt (void)
                    if (alias)
                      likely_tgt_node = alias;
                  }
+               if (e->speculative)
+                 {
+                   if (e->speculative_call_for_target (likely_tgt_node))
+                     {
+                       fprintf (dump_file, "Simple call agree with 
speculation\n\n");
+                       stats.nok++;
+                     }
+                   else
+                     {
+                       fprintf (dump_file, "Simple call disagree with 
speculation\n\n");
+                       stats.nwrong++;
+                     }
+                   continue;
+                 }
 
                if (dump_enabled_p ())
                  dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, e->call_stmt,

Reply via email to