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 guarantees 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.
        * 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.
        * ipa-inline.cc (can_inline_edge_p): Check must_remain_in_tu.
        * 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.
        * varpool.cc (varpool_node::ctor_useable_for_folding_p): Check
        must_remain_in_tu.

gcc/lto/ChangeLog:

        * lto-symtab.cc (lto_cgraph_replace_node): Propagate
        must_remain_in_tu.
        (lto_varpool_replace_node): Likewise.
---
 gcc/cgraph.h                | 5 ++++-
 gcc/cgraphclones.cc         | 1 +
 gcc/cif-code.def            | 5 +++++
 gcc/ipa-icf.cc              | 6 ++++++
 gcc/ipa-inline-transform.cc | 6 ++++++
 gcc/ipa-inline.cc           | 6 ++++++
 gcc/lto-cgraph.cc           | 4 ++++
 gcc/lto/lto-symtab.cc       | 2 ++
 gcc/varpool.cc              | 4 ++++
 9 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 036a89da9cb..26f7b3c3f4f 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -140,7 +140,7 @@ public:
       symver (false), analyzed (false), writeonly (false),
       refuse_visibility_changes (false), externally_visible (false),
       no_reorder (false), force_output (false), forced_by_abi (false),
-      ref_by_asm (false),
+      ref_by_asm (false), must_remain_in_tu (false),
       unique_name (false), implicit_section (false), body_removed (false),
       semantic_interposition (flag_semantic_interposition),
       used_from_other_partition (false), in_other_partition (false),
@@ -593,6 +593,9 @@ 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 must remain in TU partition.
+     Used to guarantee not renaming of static ref_by_asm symbols.  */
+  unsigned must_remain_in_tu : 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
diff --git a/gcc/cgraphclones.cc b/gcc/cgraphclones.cc
index 49f0e58fa1e..872d3f93f5f 100644
--- a/gcc/cgraphclones.cc
+++ b/gcc/cgraphclones.cc
@@ -440,6 +440,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 = must_remain_in_tu;
   clone_info *info = clone_info::get (this);
 
   if (param_adjustments)
diff --git a/gcc/cif-code.def b/gcc/cif-code.def
index a54116f48bc..b66573db20e 100644
--- a/gcc/cif-code.def
+++ b/gcc/cif-code.def
@@ -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"))
diff --git a/gcc/ipa-icf.cc b/gcc/ipa-icf.cc
index c7596f9ff1c..d420b173af4 100644
--- a/gcc/ipa-icf.cc
+++ b/gcc/ipa-icf.cc
@@ -534,6 +534,9 @@ sem_function::equals_wpa (sem_item *item,
 
   m_compared_func = static_cast<sem_function *> (item);
 
+  if (cnode->must_remain_in_tu || cnode2->must_remain_in_tu)
+    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 +1654,9 @@ sem_variable::equals_wpa (sem_item *item,
 {
   gcc_assert (item->type == VAR);
 
+  if (node->must_remain_in_tu || item->node->must_remain_in_tu)
+    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");
 
diff --git a/gcc/ipa-inline-transform.cc b/gcc/ipa-inline-transform.cc
index 9dc66213895..fa5623a2421 100644
--- a/gcc/ipa-inline-transform.cc
+++ b/gcc/ipa-inline-transform.cc
@@ -558,6 +558,12 @@ inline_call (struct cgraph_edge *e, bool update_original,
        }
     }
 
+  if (e->callee->must_remain_in_tu)
+    {
+      gcc_assert (e->callee->lto_file_data == e->caller->lto_file_data);
+      e->caller->must_remain_in_tu = true;
+    }
+
   clone_inlined_nodes (e, true, keep_offline_copy,
                       update_original, overall_size);
 
diff --git a/gcc/ipa-inline.cc b/gcc/ipa-inline.cc
index 1f2287da896..87a5b33676a 100644
--- a/gcc/ipa-inline.cc
+++ b/gcc/ipa-inline.cc
@@ -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
+      && 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;
diff --git a/gcc/lto-cgraph.cc b/gcc/lto-cgraph.cc
index 1a99ff48152..c836984bb24 100644
--- a/gcc/lto-cgraph.cc
+++ b/gcc/lto-cgraph.cc
@@ -532,6 +532,7 @@ 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, 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);
@@ -620,6 +621,7 @@ 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, 1);
   bp_pack_value (&bp, node->unique_name, 1);
   bp_pack_value (&bp,
                 node->body_removed
@@ -1253,6 +1255,7 @@ 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 = 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);
@@ -1460,6 +1463,7 @@ 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 = 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);
diff --git a/gcc/lto/lto-symtab.cc b/gcc/lto/lto-symtab.cc
index 2a84fce24ff..14812756cc2 100644
--- a/gcc/lto/lto-symtab.cc
+++ b/gcc/lto/lto-symtab.cc
@@ -62,6 +62,7 @@ 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 |= node->must_remain_in_tu;
 
   if (node->address_taken)
     {
@@ -124,6 +125,7 @@ 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 |= vnode->must_remain_in_tu;
 
   /* Be sure we can garbage collect the initializer.  */
   if (DECL_INITIAL (vnode->decl)
diff --git a/gcc/varpool.cc b/gcc/varpool.cc
index 8dc5f986294..4bc6e6840d1 100644
--- a/gcc/varpool.cc
+++ b/gcc/varpool.cc
@@ -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)
+    return false;
+
   /* Vtables are defined by their types and must match no matter of 
interposition
      rules.  */
   if (DECL_VIRTUAL_P (decl))
-- 
2.51.1

Reply via email to