On Wed Oct 14, 2026 at 5:34 PM CEST, Martin Jambor wrote:
> Hi,
>
> On Mon, Sep 21 2026, Josef Melcr wrote:
>> Internal callback edges cause some trouble during ipa-fnsummary summary
>> generation.
>>
>> First one is that fnsummary only looks at regular (i.e. not internal) calls
>> and tries to fetch their callgraph edges. Because internal callback
>> edges will be created as a part of ipa-prop, the edge might not always
>> exist. We can anticipate this situation and guard it with an assert to
>> make sure it only happens for internal IFN_ASSUME calls.
>>
>> The second one is the summary itself. The existing callback edge logic
>> assumes the existence of a callback-carrying edge, which the internal
>> callback edges lack. In order to have the correct size and time (both
>> being 0) filled, we need to special case this situation as well.
>>
>> gcc/ChangeLog:
>>
>> * ipa-fnsummary.cc (analyze_function_body): Adjust summary
>> generation for internal callback edges.
>>
>> Signed-off-by: Josef Melcr <[email protected]>
>> ---
>> gcc/ipa-fnsummary.cc | 22 +++++++++++++++++++++-
>> 1 file changed, 21 insertions(+), 1 deletion(-)
>>
>> diff --git a/gcc/ipa-fnsummary.cc b/gcc/ipa-fnsummary.cc
>> index b8571c5b718..423b1c4fdf8 100644
>> --- a/gcc/ipa-fnsummary.cc
>> +++ b/gcc/ipa-fnsummary.cc
>> @@ -90,6 +90,8 @@ along with GCC; see the file COPYING3. If not see
>> #include "symtab-clones.h"
>> #include "gimple-range.h"
>> #include "tree-dfa.h"
>> +#include "attr-callback.h"
>> +#include "callback-info.h"
>>
>> /* Summaries. */
>> fast_function_summary <ipa_fn_summary *, va_gc> *ipa_fn_summaries;
>> @@ -3058,9 +3060,18 @@ analyze_function_body (struct cgraph_node *node, bool
>> early)
>> }
>>
>> if (is_gimple_call (stmt)
>> - && !gimple_call_internal_p (stmt))
>> + && (!gimple_call_internal_p (stmt)
>> + || gimple_call_internal_fn (stmt) == IFN_ASSUME))
>> {
>> struct cgraph_edge *edge = node->get_edge (stmt);
>> + if (!edge)
>> + {
>> + /* The edge for .ASSUME outlined bodies is created when
>> + generating ipa-sra summaries. Ignore the call statement
>> + for now. */
>
> I have issues understanding the comment, why only the statements with an
> edge? Perhaps this is only about those that have not been processed by
> IPA-SRA analysis (yet)?
This comment is outdated unfortunately, the edges are now created as a
part of ipa-prop, not ipa-sra. But to answer your question, this if
statement is in a loop which creates and fills out an ipa_call_summary
when it encounters a gimple call, so the edge being absent is an issue,
as you cannot create a summary for a nullptr.
>
>> + gcc_checking_assert (callback_ifn_assume_call_p (stmt));
>> + continue;
>
> While probably harmless, at least until someone adds something below it,
> this continue statement makes me nervous, it skips much more than the if
> block.
>
> Can we perhaps change the condition to:
>
> cgraph_edge *edge;
> if (is_gimple_call (stmt)
> && (!gimple_call_internal_p (stmt)
> || gimple_call_internal_fn (stmt) == IFN_ASSUME))
> && (edge = node->get_edge (stmt)))
>
> instead?
Sure :)
>
>> + }
>> ipa_call_summary *es = ipa_call_summaries->get_create (edge);
>>
>> /* Special case: results of BUILT_IN_CONSTANT_P will be always
>> @@ -3147,6 +3158,15 @@ analyze_function_body (struct cgraph_node *node, bool
>> early)
>> es2->call_stmt_time = 0;
>> }
>> }
>> + /* Internal calls are not in the callgraph, so edges pointing to
>> + .ASSUME bodies are not covered by the above branch, as the
>> + dispatching edge doesn't exist. */
>> + else if (edge->callback)
>> + {
>> + gcc_checking_assert (edge->callee->assume_function);
>> + es->call_stmt_size = 0;
>> + es->call_stmt_time = 0;
>> + }
>> }
>
> I guess OK with the above changes.
>
> Thanks,
>
> Martin
Thanks,
Josef