]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
lto: Add must_remain_in_tu flags to symtab_node
authorMichal Jires <mjires@suse.cz>
Thu, 18 Dec 2025 13:58:15 +0000 (14:58 +0100)
committerMichal Jires <mjires@suse.cz>
Sun, 11 Jan 2026 21:48:54 +0000 (22:48 +0100)
With toplevel assembly we are sometimes not allowed to globalize static
symbols. So such symbols cannot be in more than one partition.

must_remain_in_tu_* guarantee that such symbols or references to them do
not escape the original translation unit. Thus 1to1 partitioning is always
valid.

gcc/ChangeLog:

* cgraph.h: Add must_remain_in_tu_*.
* cgraphclones.cc (cgraph_node::create_clone): Propagate
must_remain_in_tu_body.
* cif-code.def (MUST_REMAIN_IN_TU): New.
* ipa-icf.cc (sem_function::equals_wpa): Check
must_remain_in_tu_*
(sem_variable::equals_wpa): Likewise.
* ipa-inline-transform.cc (inline_call): Propagate
must_remain_in_tu_body.
* ipa-inline.cc (can_inline_edge_p): Check
must_remain_in_tu_body.
* lto-cgraph.cc (lto_output_node): Output must_remain_in_tu_*
(lto_output_varpool_node): Likewise.
(input_overwrite_node): Input must_remain_in_tu_*.
(input_varpool_node): Likewise.
* tree.cc (decl_address_ip_invariant_p): Check
must_remain_in_tu_name.
* varpool.cc (varpool_node::ctor_useable_for_folding_p): Check
must_remain_in_tu_body.

gcc/lto/ChangeLog:

* lto-symtab.cc (lto_cgraph_replace_node): Propagate
must_remain_in_tu_*.
(lto_varpool_replace_node): Likewise.

gcc/cgraph.h
gcc/cgraphclones.cc
gcc/cif-code.def
gcc/ipa-icf.cc
gcc/ipa-inline-transform.cc
gcc/ipa-inline.cc
gcc/lto-cgraph.cc
gcc/lto/lto-symtab.cc
gcc/tree.cc
gcc/varpool.cc

index c36020d061687546dbb411f0addf42dc0a75effd..39209b539577ac5caf8e5199d39295ddf685d65c 100644 (file)
@@ -146,6 +146,7 @@ public:
       refuse_visibility_changes (false), externally_visible (false),
       no_reorder (false), force_output (false), forced_by_abi (false),
       ref_by_asm (false),
+      must_remain_in_tu_name (false), must_remain_in_tu_body (false),
       unique_name (false), implicit_section (false), body_removed (false),
       semantic_interposition (flag_semantic_interposition),
       used_from_other_partition (false), in_other_partition (false),
@@ -598,6 +599,12 @@ public:
      Static symbol may be renamed.  Global symbol should not be renamed.
      Unlike force_output, can be on declarations.  */
   unsigned ref_by_asm : 1;
+  /* Set when asm_name must remain in TU partition.
+     Used to guarantee not renaming of static ref_by_asm symbols.  */
+  unsigned must_remain_in_tu_name : 1;
+  /* Set when body (or any references) must remain in TU partition.
+     Used on symbols referring/calling must_remain_in_tu_name.  */
+  unsigned must_remain_in_tu_body : 1;
   /* True when the name is known to be unique and thus it does not need mangling.  */
   unsigned unique_name : 1;
   /* Specify whether the section was set by user or by
index 3ea23fd7668eae626f9fc3fba5fe6f7cdce3a6e3..180ef4e52c876dfe5c50363b4b34ae7b197599ea 100644 (file)
@@ -457,6 +457,7 @@ cgraph_node::create_clone (tree new_decl, profile_count prof_count,
   new_node->unit_id = unit_id;
   new_node->merged_comdat = merged_comdat;
   new_node->merged_extern_inline = merged_extern_inline;
+  new_node->must_remain_in_tu_body = must_remain_in_tu_body;
   clone_info *info = clone_info::get (this);
 
   if (param_adjustments)
index a8347bb8bfb04b1f39ca4183128a166e25c5a073..071fd936622c22630c4cd4072814b33bef639dde 100644 (file)
@@ -139,6 +139,11 @@ DEFCIFCODE(EXTERN_LIVE_ONLY_STATIC, CIF_FINAL_ERROR,
           N_("function has external linkage when the user requests only"
              " inlining static for live patching"))
 
+/* We can't inline because callee must remain in translation unit
+   and caller is in another.  */
+DEFCIFCODE(MUST_REMAIN_IN_TU, CIF_FINAL_ERROR,
+          N_("callee must remain in translation unit"))
+
 /* We proved that the call is unreachable.  */
 DEFCIFCODE(UNREACHABLE, CIF_FINAL_ERROR,
           N_("unreachable"))
index 099ab75457dcd7c14b50e5239925efd3a0474e3b..40e9614c73649f98437e542307d5a036afbdc6b6 100644 (file)
@@ -534,6 +534,10 @@ sem_function::equals_wpa (sem_item *item,
 
   m_compared_func = static_cast<sem_function *> (item);
 
+  if (cnode->must_remain_in_tu_name || cnode2->must_remain_in_tu_name
+      || cnode->must_remain_in_tu_body || cnode2->must_remain_in_tu_body)
+    return return_false_with_msg ("must remain in TU");
+
   if (cnode->thunk != cnode2->thunk)
     return return_false_with_msg ("thunk mismatch");
   if (cnode->former_thunk_p () != cnode2->former_thunk_p ())
@@ -1651,6 +1655,10 @@ sem_variable::equals_wpa (sem_item *item,
 {
   gcc_assert (item->type == VAR);
 
+  if (node->must_remain_in_tu_name || item->node->must_remain_in_tu_name
+      || node->must_remain_in_tu_body || item->node->must_remain_in_tu_body)
+    return return_false_with_msg ("must remain in TU");
+
   if (node->num_references () != item->node->num_references ())
     return return_false_with_msg ("different number of references");
 
index 895b6e785ac3fdf7a0d3559ea1d447aec367d2ad..c4df9d91425b1c4967d3d24896112430b4786526 100644 (file)
@@ -558,6 +558,12 @@ inline_call (struct cgraph_edge *e, bool update_original,
        }
     }
 
+  if (callee->must_remain_in_tu_body)
+    {
+      gcc_assert (callee->lto_file_data == to->lto_file_data);
+      to->must_remain_in_tu_body = true;
+    }
+
   clone_inlined_nodes (e, true, keep_offline_copy,
                       update_original, overall_size);
 
index 8b0e9b194fa558a55db21916954f9ca33961c1cf..24d8974d5ca4c85116856c1542299402d1c0b9fd 100644 (file)
@@ -452,6 +452,12 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
       e->inline_failed = CIF_UNSPECIFIED;
       inlinable = false;
     }
+  if (inlinable && callee->must_remain_in_tu_body
+      && caller->lto_file_data != callee->lto_file_data)
+    {
+      e->inline_failed = CIF_MUST_REMAIN_IN_TU;
+      inlinable = false;
+    }
   if (!inlinable && report)
     report_inline_failed_reason (e);
   return inlinable;
index 71fbf80c54b239a9410c6477c884741ab8df4b6f..635ed1af76b372e6172c39607677f56c1e2e6509 100644 (file)
@@ -534,6 +534,8 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
   bp_pack_value (&bp, node->force_output, 1);
   bp_pack_value (&bp, node->forced_by_abi, 1);
   bp_pack_value (&bp, node->ref_by_asm, 1);
+  bp_pack_value (&bp, node->must_remain_in_tu_name, 1);
+  bp_pack_value (&bp, node->must_remain_in_tu_body, 1);
   bp_pack_value (&bp, node->unique_name, 1);
   bp_pack_value (&bp, node->body_removed, 1);
   bp_pack_value (&bp, node->semantic_interposition, 1);
@@ -622,6 +624,8 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node,
   bp_pack_value (&bp, node->force_output, 1);
   bp_pack_value (&bp, node->forced_by_abi, 1);
   bp_pack_value (&bp, node->ref_by_asm, 1);
+  bp_pack_value (&bp, node->must_remain_in_tu_name, 1);
+  bp_pack_value (&bp, node->must_remain_in_tu_body, 1);
   bp_pack_value (&bp, node->unique_name, 1);
   bp_pack_value (&bp,
                 node->body_removed
@@ -1255,6 +1259,8 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
   node->force_output = bp_unpack_value (bp, 1);
   node->forced_by_abi = bp_unpack_value (bp, 1);
   node->ref_by_asm = bp_unpack_value (bp, 1);
+  node->must_remain_in_tu_name = bp_unpack_value (bp, 1);
+  node->must_remain_in_tu_body = bp_unpack_value (bp, 1);
   node->unique_name = bp_unpack_value (bp, 1);
   node->body_removed = bp_unpack_value (bp, 1);
   node->semantic_interposition = bp_unpack_value (bp, 1);
@@ -1462,6 +1468,8 @@ input_varpool_node (struct lto_file_decl_data *file_data,
   node->force_output = bp_unpack_value (&bp, 1);
   node->forced_by_abi = bp_unpack_value (&bp, 1);
   node->ref_by_asm = bp_unpack_value (&bp, 1);
+  node->must_remain_in_tu_name = bp_unpack_value (&bp, 1);
+  node->must_remain_in_tu_body = bp_unpack_value (&bp, 1);
   node->unique_name = bp_unpack_value (&bp, 1);
   node->body_removed = bp_unpack_value (&bp, 1);
   node->semantic_interposition = bp_unpack_value (&bp, 1);
index 6bbc30c2ebcaedd788be4b91535f03b86ad4c8cb..b8759a7fef5511cf6760cb42a5ae2e331eb14f36 100644 (file)
@@ -62,6 +62,8 @@ lto_cgraph_replace_node (struct cgraph_node *node,
   if (node->forced_by_abi)
     prevailing_node->forced_by_abi = true;
   prevailing_node->ref_by_asm |= node->ref_by_asm;
+  prevailing_node->must_remain_in_tu_name |= node->must_remain_in_tu_name;
+  prevailing_node->must_remain_in_tu_body |= node->must_remain_in_tu_body;
 
   if (node->address_taken)
     {
@@ -124,6 +126,8 @@ lto_varpool_replace_node (varpool_node *vnode,
   if (vnode->forced_by_abi)
     prevailing_node->forced_by_abi = true;
   prevailing_node->ref_by_asm |= vnode->ref_by_asm;
+  prevailing_node->must_remain_in_tu_name |= vnode->must_remain_in_tu_name;
+  prevailing_node->must_remain_in_tu_body |= vnode->must_remain_in_tu_body;
 
   /* Be sure we can garbage collect the initializer.  */
   if (DECL_INITIAL (vnode->decl)
index 610a3fc82ab8bc3aa53ce63adfe3ad5eeb8674bb..faa0aa9f1af837b29db2c0fedfb68532beb10dc5 100644 (file)
@@ -4000,14 +4000,26 @@ decl_address_ip_invariant_p (const_tree op)
   /* The conditions below are slightly less strict than the one in
      staticp.  */
 
+  symtab_node* node;
   switch (TREE_CODE (op))
     {
     case LABEL_DECL:
-    case FUNCTION_DECL:
     case STRING_CST:
       return true;
 
+    case FUNCTION_DECL:
+      /* Disable const propagation of symbols defined in assembly.  */
+      node = symtab_node::get (op);
+      return !node || !node->must_remain_in_tu_name;
+
     case VAR_DECL:
+      if (TREE_STATIC (op) || DECL_EXTERNAL (op))
+         {
+           /* Disable const propagation of symbols defined in assembly.  */
+           node = symtab_node::get (op);
+           if (node && node->must_remain_in_tu_name)
+             return false;
+         }
       if (((TREE_STATIC (op) || DECL_EXTERNAL (op))
            && !DECL_DLLIMPORT_P (op))
           || DECL_THREAD_LOCAL_P (op))
index b1ec157733ab263db7191209f810b1f16a45fe3d..1025535ec5aa7bdeca15e61dbe3f371f42843135 100644 (file)
@@ -339,6 +339,10 @@ varpool_node::ctor_useable_for_folding_p (void)
       && !real_node->lto_file_data)
     return false;
 
+  /* Folding may cross TU boundaries.  */
+  if (must_remain_in_tu_body)
+    return false;
+
   /* Vtables are defined by their types and must match no matter of interposition
      rules.  */
   if (DECL_VIRTUAL_P (decl))