Hi,
On Mon, Sep 21 2026, Josef Melcr wrote:
> The jump function logic for regular callback edges does not apply to
> internal callback edges, as it relies on the existence of a
> callback-carrying edge for the remapping. In order to make ipa-cp act
> on assume bodies, we need to remap the arguments before the analysis is
> done. This patch adds the remapping logic and also adds an early return
> to ipa_polymorphic_call_context::get_dynamic_type, which tries to get
> the called function from the call statement with gimple_call_fn.
> This of course doesn't work for internal calls.
>
> gcc/ChangeLog:
>
> * ipa-polymorphic-call.cc
> (ipa_polymorphic_call_context::get_dynamic_type): Exclude
> IFN_ASSUME internal calls.
> * ipa-prop.cc
> (ipa_compute_jump_functions_for_edge): Remap arguments for
> callback edges.
>
> Signed-off-by: Josef Melcr <[email protected]>
> ---
> gcc/ipa-polymorphic-call.cc | 7 +++++++
> gcc/ipa-prop.cc | 14 ++++++++++++--
> 2 files changed, 19 insertions(+), 2 deletions(-)
>
> diff --git a/gcc/ipa-polymorphic-call.cc b/gcc/ipa-polymorphic-call.cc
> index addb52561c7..12d9c9f878a 100644
> --- a/gcc/ipa-polymorphic-call.cc
> +++ b/gcc/ipa-polymorphic-call.cc
> @@ -41,6 +41,8 @@ along with GCC; see the file COPYING3. If not see
> #include "alloc-pool.h"
> #include "symbol-summary.h"
> #include "symtab-thunks.h"
> +#include "attr-callback.h"
> +#include "callback-info.h"
>
> /* Return true when TYPE contains an polymorphic type and thus is interesting
> for devirtualization machinery. */
> @@ -1584,6 +1586,11 @@ ipa_polymorphic_call_context::get_dynamic_type (tree
> instance,
> if (!instance)
> return false;
>
> + /* Bail to avoid segfaults for IFN_ASSUME internal calls. They are not
> + polymorphic anyway. */
> + if (callback_ifn_assume_call_p (call))
> + return false;
This will not return if call is an assume using an outlined function
that has also somehow has a call which is not callback (because of
ICF?). callback_ifn_assume_call_p seems to be written with some other
use in mind and perhaps needs to be split into two slightly different
predicates?
> +
> if (otr_type)
> otr_type = TYPE_MAIN_VARIANT (otr_type);
>
> diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc
> index 3f9f45b02c8..bc31e8e3399 100644
> --- a/gcc/ipa-prop.cc
> +++ b/gcc/ipa-prop.cc
> @@ -2492,7 +2492,8 @@ ipa_compute_jump_functions_for_edge (struct
> ipa_func_body_info *fbi,
> ipa_node_params *info = ipa_node_params_sum->get (cs->caller);
> ipa_edge_args *args = ipa_edge_args_sum->get_create (cs);
> gcall *call = cs->call_stmt;
> - int n, arg_num = gimple_call_num_args (call);
> + callback_info *ci = callback_info_sum->get (cs);
> + int n, arg_num = callback_call_num_args_summary (call, ci);
> bool useful_context = false;
>
> if (arg_num == 0 || args->jump_functions)
> @@ -2508,7 +2509,16 @@ ipa_compute_jump_functions_for_edge (struct
> ipa_func_body_info *fbi,
> for (n = 0; n < arg_num; n++)
> {
> struct ipa_jump_func *jfunc = ipa_get_ith_jump_func (args, n);
> - tree arg = gimple_call_arg (call, n);
> + tree arg;
> + if (cs->callback)
> + {
> + int remapped_idx = ci->arg_mapping[n];
> + if (remapped_idx == ARG_MAPPING_UNKNOWN_IDX)
> + continue;
> + arg = gimple_call_arg (call, remapped_idx);
> + }
> + else
> + arg = gimple_call_arg (call, n);
This feels a bit strange because before this patch series, the callback
edges were created in this function and their jump functions populated
differently by copying over what we calculated for the call to the
dispatcher.
I understand that callback edges for assumes have to be created
elsewhere, can we add an assert to the if block above so that readers of
the code know this is why it is that we handle things differently?
Thanks,
Martin
> tree param_type = ipa_get_callee_param_type (cs, n);
> if (flag_devirtualize && POINTER_TYPE_P (TREE_TYPE (arg)))
> {
> --
> 2.55.0