https://gcc.gnu.org/g:592a97c94412fe046f9e3683dd52b758ef219313

commit r17-5631-g592a97c94412fe046f9e3683dd52b758ef219313
Author: Josef Melcr <[email protected]>
Date:   Wed Sep 16 13:41:40 2026 +0200

    cgraph, ipa: Internal callback edge redirection logic and call adjustments
    
    This patch adds logic for internal callback edge redirection and
    modification of their call statements.
    
    Internal callback edges need to be redirected in a different manner
    compared to their regular counterparts.  Because we have their call
    statements under complete control, we can implement call statement
    modifications beyond simple address replacement.  Functions for call
    modification need to be adjusted to accommodate for this.
    
    modify_call_stmt creates a summary describing what changes were done so
    far.  This summary contains indices of arguments which need to be remapped.
    
    modify_call also needed to have its indices remapped, as the summaries
    describing changes to be made follow the indexing of the assume
    function, not the call statement.
    
    Both functions now include a branch for the creation of an internal
    IFN_ASSUME call statement.
    
    gcc/ChangeLog:
    
            * cgraph.cc (cgraph_edge::redirect_call_stmt_to_callee): Add
            redirection logic for internal edges.
            * ipa-param-manipulation.cc (ipa_param_adjustments::modify_call):
            Adjust argument modifications for callback edges.
            (ipa_param_body_adjustments::modify_call_stmt): Likewise.
    
    Signed-off-by: Josef Melcr <[email protected]>

Diff:
---
 gcc/cgraph.cc                 | 21 ++++++++++++++++
 gcc/ipa-param-manipulation.cc | 58 ++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 73 insertions(+), 6 deletions(-)

diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc
index 0aa89d657bbb..3448bc377147 100644
--- a/gcc/cgraph.cc
+++ b/gcc/cgraph.cc
@@ -1903,6 +1903,27 @@ cgraph_edge::redirect_call_stmt_to_callee (cgraph_edge 
*e,
       callback_redirect_edge (e);
       return e->call_stmt;
     }
+  /* Callback calls to .ASSUME bodies might need to have their statement
+     rebuilt.  */
+  else if (e->callback && e->callee->assume_function)
+    {
+      ipa_param_adjustments *padjs
+       = callee_info ? callee_info->param_adjustments : NULL;
+
+      /* If there are no param adjustments, replace the address in the call
+        statement.  */
+      if (!padjs)
+       callback_redirect_edge (e);
+      else
+       {
+         new_stmt = padjs->modify_call (e, false, killed_ssas);
+         gcc_checking_assert (callback_ifn_assume_call_p (new_stmt));
+         e->caller->set_call_stmt_including_clones (e->call_stmt, new_stmt,
+                                                    false);
+       }
+      return e->call_stmt;
+    }
+  gcc_checking_assert (!e->callback);
 
   if (decl && ipa_saved_clone_sources)
     {
diff --git a/gcc/ipa-param-manipulation.cc b/gcc/ipa-param-manipulation.cc
index 0f384848ce55..fd70274e9b89 100644
--- a/gcc/ipa-param-manipulation.cc
+++ b/gcc/ipa-param-manipulation.cc
@@ -50,7 +50,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "sreal.h"
 #include "ipa-cp.h"
 #include "ipa-prop.h"
+#include "data-streamer.h"
 #include "attr-callback.h"
+#include "callback-info.h"
 
 /* Actual prefixes of different newly synthesized parameters.  Keep in sync
    with IPA_PARAM_PREFIX_* defines.  */
@@ -719,7 +721,17 @@ ipa_param_adjustments::modify_call (cgraph_edge *cs,
 
   unsigned len = vec_safe_length (m_adj_params);
   auto_vec<tree, 16> vargs (len);
-  unsigned old_nargs = gimple_call_num_args (stmt);
+  /* Argument remapping has to be used in this function, because it builds the
+     new call statement from the parameter descriptors, rather than the actual
+     arguments, as in ipa_param_adjustments::modify_call_stmt.  */
+  callback_info *ci = callback_info_sum->get (cs);
+
+  /* Callback edges should be here only if they are pointing towards .ASSUME
+     bodies, which always have a complete argument mapping.  */
+  if (ci)
+    gcc_assert (cs->callee->assume_function);
+
+  unsigned old_nargs = callback_call_num_args_summary (stmt, ci);
   unsigned orig_nargs = mod_info ? mod_info->index_map.length () : old_nargs;
   auto_vec<bool, 16> kept (old_nargs);
   kept.quick_grow_cleared (old_nargs);
@@ -728,6 +740,9 @@ ipa_param_adjustments::modify_call (cgraph_edge *cs,
   if (update_references)
     current_node->remove_stmt_references (stmt);
 
+  if (cs->callback && cs->callee->assume_function)
+    vargs.safe_push (build_fold_addr_expr (callee_decl));
+
   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
   gimple_stmt_iterator prev_gsi = gsi;
   gsi_prev (&prev_gsi);
@@ -747,7 +762,7 @@ ipa_param_adjustments::modify_call (cgraph_edge *cs,
              gcc_assert (index >= 0);
            }
 
-         tree arg = gimple_call_arg (stmt, index);
+         tree arg = callback_call_arg_summary (stmt, index, ci);
 
          vargs.quick_push (arg);
          kept[index] = true;
@@ -797,7 +812,7 @@ ipa_param_adjustments::modify_call (cgraph_edge *cs,
          index = mod_info->index_map[apm->base_index];
          gcc_assert (index >= 0);
        }
-      tree base = gimple_call_arg (stmt, index);
+      tree base = callback_call_arg_summary (stmt, index, ci);
 
       /* We create a new parameter out of the value of the old one, we can
         do the following kind of transformations:
@@ -919,6 +934,8 @@ ipa_param_adjustments::modify_call (cgraph_edge *cs,
          always_copy_start += mod_info->always_copy_delta;
          gcc_assert (always_copy_start >= 0);
        }
+
+      gcc_assert (!ci || always_copy_start >= (int) old_nargs);
       for (unsigned i = always_copy_start; i < old_nargs; i++)
        vargs.safe_push (gimple_call_arg (stmt, i));
     }
@@ -1005,7 +1022,11 @@ ipa_param_adjustments::modify_call (cgraph_edge *cs,
       print_gimple_stmt (dump_file, gsi_stmt (gsi), 0);
     }
 
-  gcall *new_stmt = gimple_build_call_vec (callee_decl, vargs);
+  gcall *new_stmt;
+  if (cs->callback && cs->callee->assume_function)
+    new_stmt = gimple_build_call_internal_vec (IFN_ASSUME, vargs);
+  else
+    new_stmt = gimple_build_call_vec (callee_decl, vargs);
 
   hash_set <tree> *ssas_to_remove = NULL;
   if (tree lhs = gimple_call_lhs (stmt))
@@ -2224,6 +2245,18 @@ ipa_param_body_adjustments::modify_call_stmt (gcall 
**stmt_p,
   bool recreate = false;
   gcc_assert (m_sorted_replacements_p);
 
+  callback_info *ci = NULL;
+  if (callback_ifn_assume_call_p (orig_stmt))
+    {
+      cgraph_edge *cbei = cgraph_node::get (m_fndecl)->get_edge (orig_stmt);
+      if (cbei)
+       {
+         gcc_checking_assert (cbei->callback);
+         ci = callback_info_sum->get (cbei);
+         gcc_assert (ci);
+       }
+    }
+
   for (unsigned i = 0; i < gimple_call_num_args (stmt); i++)
     {
       tree t = gimple_call_arg (stmt, i);
@@ -2349,7 +2382,16 @@ ipa_param_body_adjustments::modify_call_stmt (gcall 
**stmt_p,
              if (m_replacements[j].unit_offset < agg_arg_offset)
                continue;
              pass_through_split_map pt_map;
-             pt_map.base_index = i;
+             /* The base index wouldn't match for callback calls, as the
+                analysis is done on their remapped indices.  */
+             if (ci)
+               {
+                 int remapped_idx = ci->inverted_mapping[i];
+                 gcc_checking_assert (remapped_idx != -1);
+                 pt_map.base_index = remapped_idx;
+               }
+             else
+               pt_map.base_index = i;
              pt_map.unit_offset
                = m_replacements[j].unit_offset - agg_arg_offset;
              pt_map.new_index = new_arg_idx;
@@ -2379,7 +2421,11 @@ ipa_param_body_adjustments::modify_call_stmt (gcall 
**stmt_p,
        }
     }
 
-  gcall *new_stmt = gimple_build_call_vec (gimple_call_fn (stmt), vargs);
+  gcall *new_stmt;
+  if (callback_ifn_assume_call_p (orig_stmt))
+    new_stmt = gimple_build_call_internal_vec (IFN_ASSUME, vargs);
+  else
+    new_stmt = gimple_build_call_vec (gimple_call_fn (stmt), vargs);
   if (gimple_has_location (stmt))
     gimple_set_location (new_stmt, gimple_location (stmt));
   gimple_call_set_chain (new_stmt, gimple_call_chain (stmt));

Reply via email to