Hello,
When doing PGO or autofdo we should first read the FDO info and
create speculative edges based on it.

Later speculation is made by ipa-devirt and ipa-prop. If profile feedback
is available (i.e. edge->speculative is true) we do not want to add another
speculation. First we do not know how to redistribute probabilities and
profile info should be more accurate.

ipa-devirt already has check
            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;
              }
 ...
            /* This is reached only when dumping; check if we agree or
disagree
               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;
                    }
                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;
              }

Similarly ipa-prop avoids double-speculation
 /* If the edge is already speculated.  */
  if (speculative && ie->speculative)
    {
      if (dump_file)
        {
          cgraph_edge *e2 = ie->speculative_call_for_target (callee);
          if (!e2)
            {
              if (dump_file)
                fprintf (dump_file, "ipa-prop: Discovered call to a "
                         "speculative target (%s -> %s) but the call is "
                         "already speculated to different target.  "
                         "Giving up.\n",
                         ie->caller->dump_name (), callee->dump_name ());
            }
          else
            {
              if (dump_file)
                fprintf (dump_file,
                         "ipa-prop: Discovered call to a speculative target
"
                         "(%s -> %s) this agree with previous
speculation.\n",
                         ie->caller->dump_name (), callee->dump_name ());
            }
        }
      return NULL;
    }

So I wonder how the additional speculation is created at the first place?
Is it via ipa_merge_profiles?

Honza

On Fri, Jan 9, 2026 at 7:51 AM Kugan Vivekanandarajah <
[email protected]> wrote:

>
>
> > On 9 Jan 2026, at 5:48 pm, Kugan Vivekanandarajah <
> [email protected]> wrote:
> >
> > The issue is shows up in  AutoFDO with:
> >
> >    • Multiple speculative calls within a single function.
> >    • Complex interactions between the AutoFDO early-inliner,
> devirtualization, and indirect call transformation.
> >    • The ICE triggers when these calls are processed across different
> IPA passes that inadvertently disrupt the cgraph_edge linked-list adjacency.
> >
> > See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123496
> >
> > I have two patches that ensures the call-graph and call_site_hash
> invariants are maintained during edge creation/redirection.
> >
> > First patch measure that we don't create the same  speculative edges are
> not adding from different optimisations
> > Send patch measure that the order is maintained.
> >
> > Bootstrapped and regression tested with now new regressions on
> aarch64-linux-gnu with no new regressions.
> >
> > Is this OK?
> >
>
> When creating speculative edges, ensure they remain adjacent in the callees
> list to satisfy verification requirements. The create_edge() function
> always
> inserts new edges at the head of the list, which can break adjacency when
> multiple speculative edges exist for the same call statement.
>
> gcc/ChangeLog:
>
>         * cgraph.cc (cgraph_edge::make_speculative): Find the last existing
>         speculative edge for the same call_stmt and insert the new edge
>         adjacent to it, maintaining the verification invariant.
>
>
> Thanks,
> Kugan
>

Reply via email to