Re: [PATCH] [AutoFDO][IPA-CP] Handle zero-caller locals after AutoFDO early inlining
Jan Hubička <[email protected]> Tue, 4 Aug 2026 08:49:52 +0200
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <CAJf+ejeQyteMrW0Gezrbw-F=sVOdLXxnMHC=FSOmhx4AEHvRPg@mail.gmail.com> |
Hi, On Tue, Aug 4, 2026 at 2:38 AM Kugan Vivekanandarajah < [email protected]> wrote: > AutoFDO early inlining can inline all direct calls to a local > function while speculative call promotion keeps the function > address-taken. The function consequently remains in the call graph > with no direct callers, triggering the -ftoplevel-reorder checking > assertion in IPA-CP. > > Ordinary IPA devirtualization does not normally produce this state at > IPA-CP: it creates speculative edges before IPA-CP, but those edges are > inlined only by the later IPA inliner. IPA-CP therefore still sees a > direct caller. AutoFDO instead performs speculative inlining early, so > only its IPA_REF_ADDR may remain by the time IPA-CP runs. > > When AutoFDO inlining is enabled, recognize zero-caller functions that > cannot be removed after their direct calls disappear and initialize > their lattices as variable. Preserve the assertion for removable > locals and non-AutoFDO compilation. > > gcc/ChangeLog: > > * ipa-cp.cc (initialize_node_lattices): Handle zero-caller local > functions left after AutoFDO early inlining. > I think the problem here is earlier. If function is local, it can not be called indirectly and thus it makes no sense to add speculative call to it. I am not sure how the auto-FDO profile data got to a conclussion that the function can be called indirectly - I can see it can be triggered when source code changes between train run and compilation. Can you perhaps check what is happening and if something like this works? diff --git a/gcc/auto-profile.cc b/gcc/auto-profile.cc index 6aa5166c748..63ca8938146 100644 --- a/gcc/auto-profile.cc +++ b/gcc/auto-profile.cc @@ -3326,6 +3333,14 @@ afdo_indirect_call (gcall *stmt, const icall_target_map &map, afdo_string_table->get_symbol_name (max_iter->first)); return false; } + if (direct_call->local) + { + if (dump_file) + fprintf (dump_file, "AFDO Indirect call target %s " + "is local and thus can not be called indirectly\n", + afdo_string_table->get_symbol_name (max_iter->first)); + return false; + } callee = gimple_call_fn (stmt); > > Regression tested on aarch64-linux-gnu with no new regressions > > Signed-off-by: Kugan Vivekanandarajah <[email protected]> > --- > gcc/ipa-cp.cc | 13 ++++++++++++- > 1 file changed, 12 insertions(+), 1 deletion(-) > > diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc > index c1b1f6201fd3..d68952ec8711 100644 > --- a/gcc/ipa-cp.cc > +++ b/gcc/ipa-cp.cc > @@ -1443,7 +1443,18 @@ initialize_node_lattices (struct cgraph_node *node) > NULL, true); > else if (caller_count == 0) > { > - gcc_checking_assert (!opt_for_fn (node->decl, > flag_toplevel_reorder)); > + /* With -ftoplevel-reorder, a local body with no direct callers > + should already have been removed. AutoFDO early-inline of a > + speculative call expands via gimple_ic (&target), so after all > + direct call edges are inlined the local can remain > address-taken > + with unknown indirect uses; treat that as VARIABLE. Ordinary > + IPA devirtualization does not need this exception: it creates > + speculative edges before IPA-CP, but inlines them only later, > so > + IPA-CP still sees a direct caller. */ > + if (!(flag_auto_profile && flag_auto_profile_inlining > + && !node->can_remove_if_no_direct_calls_p (false))) > + gcc_checking_assert > + (!opt_for_fn (node->decl, flag_toplevel_reorder)); > variable = true; > } > } > -- > 2.34.1 > >