On Wed Oct 14, 2026 at 4:09 PM CEST, Martin Jambor wrote:
> On Mon, Sep 21 2026, Josef Melcr wrote:
>> This patch adds a few shorthand functions to make further work with the
>> new callback edges a little easier. They are pretty self explanatory.
>> Some of them actaully contain some logic, but some of them exist just to
>> make some if statements a little shorter.
>>
>> gcc/ChangeLog:
>>
>> * callback-info.cc (callback_call_arg_summary): Add
>> implementation.
>> (callback_call_num_args_summary): Likewise.
>> (callback_ifn_assume_call_p): Likewise.
>> (callback_ifn_assume_call_with_edge_p): Likewise.
>> * callback-info.h (callback_call_arg_summary): New function,
>> remaps arguments for callback calls.
>> (callback_call_num_args_summary): New function, returns the
>> correct number of arguments for callback calls.
>> (callback_ifn_assume_call_p): New function, returns TRUE if the
>> passed call is a call to IFN_ASSUME.
>> (callback_ifn_assume_call_with_edge_p): New function, returns
>> TRUE if the passed call is a call to IFN_ASSUME with an attached
>> cgraph_edge.
>>
>> Signed-off-by: Josef Melcr <[email protected]>
>> ---
>> gcc/callback-info.cc | 54 ++++++++++++++++++++++++++++++++++++++++++++
>> gcc/callback-info.h | 16 +++++++++++++
>> 2 files changed, 70 insertions(+)
>>
>> diff --git a/gcc/callback-info.cc b/gcc/callback-info.cc
>> index ec2291f3338..95357b9c8ff 100644
>> --- a/gcc/callback-info.cc
>> +++ b/gcc/callback-info.cc
>> @@ -147,3 +147,57 @@ callback_info_sum_t::duplicate (cgraph_edge *,
>> cgraph_edge *,
>> dst_s->inverted_mapping = src_s->inverted_mapping.copy ();
>> dst_s->redirected = src_s->redirected;
>> }
>> +
>> +/* Return the argument at IDX if CI is null, otherwise use the mapping in
>> CI and
>
> Return the argument of STMT at IDX...
>
>> + return the remapped argument. Presumes that the remapped index is not
>> + ARG_MAPPING_UNKNOWN_IDX. */
>> +tree
>> +callback_call_arg_summary (gimple *stmt, int idx, callback_info *ci)
>
> Please make stmt const gcall * (if easily possible).
>
>> +{
>> + if (ci)
>> + idx = ci->arg_mapping[idx];
>> + gcc_checking_assert (idx != ARG_MAPPING_UNKNOWN_IDX);
>> + return gimple_call_arg (stmt, idx);
>> +}
>> +
>> +/* Return the number of arguments of STMT if CI is null,
>> + ci->arg_mapping.length() otherwise. */
>> +unsigned
>> +callback_call_num_args_summary (const gcall *stmt, callback_info *ci)
>> +{
>> + if (ci)
>> + return ci->arg_mapping.length ();
>> + return gimple_call_num_args (stmt);
>> +}
>> +
>> +/* Returns TRUE iff STMT is an internal call statement to IFN_ASSUME. */
>> +bool
>> +callback_ifn_assume_call_p (gimple *stmt)
>> +{
>> + return is_gimple_call (stmt) && gimple_call_internal_p (stmt)
>> + && (gimple_call_internal_fn (stmt) == IFN_ASSUME);
>> +}
>> +
>> +/* Returns TRUE iff STMT is an internal call statement to IFN_ASSUME with a
>> + callback edge to pointing to the outlined body. */
>
> Extraneous "to."
>
> But that is not all the function does, which I'm afraid requires some
> explanation.
The function is supposed to take a call statement and decide whether
it's an .ASSUME internal call with a callback edge attached to it.
There really are two ways to do that:
1) Take the caller node as a parameter and check caller_node->get_edge (stmt)
or, what this function does
2) Look at the callback's address inside the call statement, fetch its
node and check whether it has any callers.
Should I document this lookup or should I just switch to the first
approach to make it more understandable?
>
>> +bool
>> +callback_ifn_assume_call_with_edge_p (gimple *stmt)
>> +{
>> + /* Fast path for most cases. */
>> + if (!callback_ifn_assume_call_p (stmt))
>> + return false;
>> +
>> + tree decl = TREE_OPERAND (gimple_call_arg (stmt, 0), 0);
>> + cgraph_node *node = cgraph_node::get (decl);
>> + gcc_checking_assert (node->assume_function);
>> +
>> + if (!node->callers)
>> + return false;
>> +
>
> Does this check catch the case where we have not created a callback edge
> for whatever reason?
Yes.
>
>> + cgraph_edge *e;
>> + for (e = node->callers; e; e = e->next_caller)
>> + if (!e->callback)
>> + return false;
>
> ... if there is a non-callback caller, is that because an assume
> outlined function got ICFed together with a regular function or what is
> this guarding against?
Assume bodies and regular functions cannot be ICFed together (there is a
patch for that in this series), so this could, or rather should, be an assert.
Additionally, I noticed that I somehow missed a check whether any of the
edges actually correspond to the call statement, so I think that this
warrants a v2.
>
> Please explain in the function comment what are all the criteria the
> outlined function must meet for this function to return true.
The functions is supposed to return true if the body has a callback edge
pointing at it attached to the passed statement. There were no edges
pointing at the body up until now, so there is currently an invariant
that every caller of the assume is a callback caller. I am not sure if
that will change in the future, so I don't really know how to document
this. But I can certainly list off what the function checks in the comment.
>
> Otherwise the patch is otherwise OK once patches using these functions
> are approved.
>
> Thanks,
>
> Martin
Josef