https://gcc.gnu.org/g:c94fe046c0ba8177ef023f56577e8cc00795afec

commit r17-5618-gc94fe046c0ba8177ef023f56577e8cc00795afec
Author: Josef Melcr <[email protected]>
Date:   Thu Sep 10 15:56:13 2026 +0200

    cgraph: Add assume_function field to cgraph_node
    
    This patch adds a new field to cgraph_node called assume_function.  It
    serves the same purpose as the field of the same name in struct
    function.  Struct function is not always available (e.g. LTO), so this field
    preserves the information.  The patch also fixes ICF so that it doesn't 
merge
    functions with different values of this field.
    
    gcc/ChangeLog:
    
            * cgraph.cc (cgraph_node::dump): Print the new flag.
            * cgraph.h (struct cgraph_node): Add assume_function field.
            (cgraph_node::finalize_function): Change return type to 
cgraph_node*.
            (cgraph_node::add_new_function): Likewise.
            * cgraphclones.cc (cgraph_node::create_clone): Copy over the
            assume_function flag.
            * cgraphunit.cc (cgraph_node::finalize_function): Change return
            type to cgraph_node*, return the node.
            (cgraph_node::add_new_function): Likewise.
            * gimple-low.cc (lower_assumption): Set assume_function to TRUE
            for assume bodies.
            * lto-cgraph.cc (lto_output_node): Stream out assume_function.
            (input_overwrite_node): Read assume_function.
            * ipa-icf.cc (sem_function::get_hash): Hash
            cgraph_node::assume_function.
            (sem_function::equals_wpa): Check for assume_function equality.
            (sem_function::equals_private): Likewise.
    
    Signed-off-by: Josef Melcr <[email protected]>

Diff:
---
 gcc/cgraph.cc       |  2 ++
 gcc/cgraph.h        | 17 +++++++++++------
 gcc/cgraphclones.cc |  1 +
 gcc/cgraphunit.cc   | 15 ++++++++++-----
 gcc/gimple-low.cc   |  3 ++-
 gcc/ipa-icf.cc      | 11 ++++++++++-
 gcc/lto-cgraph.cc   |  2 ++
 7 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc
index 8e3491897248..c1bf53f6c36a 100644
--- a/gcc/cgraph.cc
+++ b/gcc/cgraph.cc
@@ -2583,6 +2583,8 @@ cgraph_node::dump (FILE *f)
     fprintf (f, " calls_comdat_local");
   if (icf_merged)
     fprintf (f, " icf_merged");
+  if (assume_function)
+    fprintf (f, " assume_function");
   if (merged_comdat)
     fprintf (f, " merged_comdat");
   if (merged_extern_inline)
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index d9f3d4815b0d..9799605ed24a 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -939,8 +939,8 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public 
symtab_node
       only_called_at_startup (false), only_called_at_exit (false),
       tm_clone (false), dispatcher_function (false),
       dispatcher_resolver_function (false), is_target_clone (false),
-      calls_comdat_local (false),
-      icf_merged (false), nonfreeing_fn (false), merged_comdat (false),
+      calls_comdat_local (false), icf_merged (false), assume_function (false),
+      nonfreeing_fn (false), merged_comdat (false),
       merged_extern_inline (false), parallelized_function (false),
       split_part (false), indirect_call_target (false), local (false),
       versionable (false), can_change_signature (false),
@@ -1400,8 +1400,10 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : 
public symtab_node
      API breaking optimizations are performed on it).
 
      Main work done by this function is to enqueue the function for later
-     processing to avoid need the passes to be re-entrant.  */
-  static void add_new_function (tree fndecl, bool lowered);
+     processing to avoid need the passes to be re-entrant.
+
+     Returns the created node.  */
+  static cgraph_node *add_new_function (tree fndecl, bool lowered);
 
   /* Return callgraph node for given symbol and check it is a function. */
   static inline cgraph_node *get (const_tree decl)
@@ -1413,8 +1415,9 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : 
public symtab_node
   /* DECL has been parsed.  Take it, queue it, compile it at the whim of the
      logic in effect.  If NO_COLLECT is true, then our caller cannot stand to
      have the garbage collector run at the moment.  We would need to either
-     create a new GC context, or just not compile right now.  */
-  static void finalize_function (tree, bool);
+     create a new GC context, or just not compile right now.  Returns the
+     created node.  */
+  static cgraph_node *finalize_function (tree, bool);
 
   /* Return cgraph node assigned to DECL.  Create new one when needed.  */
   static cgraph_node * create (tree decl);
@@ -1536,6 +1539,8 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : 
public symtab_node
   unsigned calls_comdat_local : 1;
   /* True if node has been created by merge operation in IPA-ICF.  */
   unsigned icf_merged: 1;
+  /* True if node has been created by lowering an [[assume(...)]] statement.  
*/
+  unsigned assume_function : 1;
   /* True if call to node can't result in a call to free, munmap or
      other operation that could make previously non-trapping memory
      accesses trapping.  */
diff --git a/gcc/cgraphclones.cc b/gcc/cgraphclones.cc
index b5f2ce5ff2f3..c5aead0c3b8c 100644
--- a/gcc/cgraphclones.cc
+++ b/gcc/cgraphclones.cc
@@ -452,6 +452,7 @@ cgraph_node::create_clone (tree new_decl, profile_count 
prof_count,
   new_node->tp_first_run = tp_first_run;
   new_node->tm_clone = tm_clone;
   new_node->icf_merged = icf_merged;
+  new_node->assume_function = assume_function;
   new_node->thunk = thunk;
   new_node->unit_id = unit_id;
   new_node->merged_comdat = merged_comdat;
diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc
index 7a7278ace5ac..b77f082757bf 100644
--- a/gcc/cgraphunit.cc
+++ b/gcc/cgraphunit.cc
@@ -445,9 +445,10 @@ symtab_node::referred_to_p (bool include_self)
 /* DECL has been parsed.  Take it, queue it, compile it at the whim of the
    logic in effect.  If NO_COLLECT is true, then our caller cannot stand to 
have
    the garbage collector run at the moment.  We would need to either create
-   a new GC context, or just not compile right now.  */
+   a new GC context, or just not compile right now.  Returns the created
+   node.  */
 
-void
+cgraph_node *
 cgraph_node::finalize_function (tree decl, bool no_collect)
 {
   cgraph_node *node = cgraph_node::get_create (decl);
@@ -511,6 +512,7 @@ cgraph_node::finalize_function (tree decl, bool no_collect)
   if (symtab->state == CONSTRUCTION
       && (node->needed_p () || node->referred_to_p ()))
     enqueue_node (node);
+  return node;
 }
 
 /* Add the function FNDECL to the call graph.
@@ -523,9 +525,11 @@ cgraph_node::finalize_function (tree decl, bool no_collect)
    API breaking optimizations are performed on it).
 
    Main work done by this function is to enqueue the function for later
-   processing to avoid need the passes to be re-entrant.  */
+   processing to avoid need the passes to be re-entrant.
 
-void
+   Returns the created node.  */
+
+cgraph_node *
 cgraph_node::add_new_function (tree fndecl, bool lowered)
 {
   gcc::pass_manager *passes = g->get_passes ();
@@ -550,7 +554,7 @@ cgraph_node::add_new_function (tree fndecl, bool lowered)
   switch (symtab->state)
     {
       case PARSING:
-       cgraph_node::finalize_function (fndecl, false);
+       node = cgraph_node::finalize_function (fndecl, false);
        break;
       case CONSTRUCTION:
        /* Just enqueue function to be processed at nearest occurrence.  */
@@ -620,6 +624,7 @@ cgraph_node::add_new_function (tree fndecl, bool lowered)
       && (function_needs_eh_personality (DECL_STRUCT_FUNCTION (fndecl))
          == eh_personality_lang))
     DECL_FUNCTION_PERSONALITY (fndecl) = lang_hooks.eh_personality ();
+  return node;
 }
 
 /* Analyze the function scheduled to be output.  */
diff --git a/gcc/gimple-low.cc b/gcc/gimple-low.cc
index ed7524298544..a24d8e49bb22 100644
--- a/gcc/gimple-low.cc
+++ b/gcc/gimple-low.cc
@@ -676,7 +676,8 @@ lower_assumption (gimple_stmt_iterator *gsi, struct 
lower_data *data)
   /* The body function no longer has var. args, unset stdarg.  */
   DECL_STRUCT_FUNCTION (lad.id.dst_fn)->stdarg = 0;
 
-  cgraph_node::add_new_function (lad.id.dst_fn, false);
+  cgraph_node *dst_node = cgraph_node::add_new_function (lad.id.dst_fn, false);
+  dst_node->assume_function = 1;
 
   for (unsigned i = 0; i < sz; ++i)
     {
diff --git a/gcc/ipa-icf.cc b/gcc/ipa-icf.cc
index 7b524bdf16b1..7aa2554f8a74 100644
--- a/gcc/ipa-icf.cc
+++ b/gcc/ipa-icf.cc
@@ -295,6 +295,7 @@ sem_function::get_hash (void)
       hstate.add_flag (DECL_CXX_CONSTRUCTOR_P (decl));
       hstate.add_flag (DECL_CXX_DESTRUCTOR_P (decl));
       hstate.add_flag (DECL_STATIC_CHAIN (decl));
+      hstate.add_flag (as_a<cgraph_node *> (node)->assume_function);
 
       set_hash (hstate.end ());
     }
@@ -538,6 +539,8 @@ sem_function::equals_wpa (sem_item *item,
       || cnode->must_remain_in_tu_body || cnode2->must_remain_in_tu_body)
     return return_false_with_msg ("must remain in TU");
 
+  if (cnode->assume_function != cnode2->assume_function)
+    return return_false_with_msg ("assume_function mismatch");
   if (cnode->thunk != cnode2->thunk)
     return return_false_with_msg ("thunk mismatch");
   if (cnode->former_thunk_p () != cnode2->former_thunk_p ())
@@ -889,7 +892,13 @@ sem_function::equals_private (sem_item *item)
  if (DECL_STATIC_CHAIN (decl) != DECL_STATIC_CHAIN (m_compared_func->decl))
     return return_false_with_msg ("static chain mismatch");
 
-  if (!dyn_cast <cgraph_node *> (node)->has_gimple_body_p ())
+  cgraph_node *cnode = as_a<cgraph_node *> (node);
+  cgraph_node *cnode2 = as_a<cgraph_node *> (m_compared_func->node);
+
+  if (cnode->assume_function != cnode2->assume_function)
+    return return_false_with_msg ("assume_function mismatch");
+
+  if (!cnode->has_gimple_body_p ())
     return true;
 
   /* Fill-up label dictionary.  */
diff --git a/gcc/lto-cgraph.cc b/gcc/lto-cgraph.cc
index bffe35f2353d..b3644e47becb 100644
--- a/gcc/lto-cgraph.cc
+++ b/gcc/lto-cgraph.cc
@@ -561,6 +561,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct 
cgraph_node *node,
   bp_pack_value (&bp, node->tm_clone, 1);
   bp_pack_value (&bp, node->calls_comdat_local, 1);
   bp_pack_value (&bp, node->icf_merged, 1);
+  bp_pack_value (&bp, node->assume_function, 1);
   bp_pack_value (&bp, node->nonfreeing_fn, 1);
   bp_pack_value (&bp, node->merged_comdat, 1);
   bp_pack_value (&bp, node->merged_extern_inline, 1);
@@ -1299,6 +1300,7 @@ input_overwrite_node (struct lto_file_decl_data 
*file_data,
   node->tm_clone = bp_unpack_value (bp, 1);
   node->calls_comdat_local = bp_unpack_value (bp, 1);
   node->icf_merged = bp_unpack_value (bp, 1);
+  node->assume_function = bp_unpack_value (bp, 1);
   node->nonfreeing_fn = bp_unpack_value (bp, 1);
   node->merged_comdat = bp_unpack_value (bp, 1);
   node->merged_extern_inline = bp_unpack_value (bp, 1);

Reply via email to