These optimizations may cross translation unit boundaries, so disable
them when must_remain_in_tu is set.
gcc/ChangeLog:
* cif-code.def (MUST_REMAIN_IN_TU): New.
* ipa-icf.cc (sem_function::equals_wpa): False with
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): Disable with
must_remain_in_tu.
* varpool.cc (varpool_node::ctor_useable_for_folding_p):
Likewise.
---
gcc/cif-code.def | 5 +++++
gcc/ipa-icf.cc | 6 ++++++
gcc/ipa-inline-transform.cc | 6 ++++++
gcc/ipa-inline.cc | 6 ++++++
gcc/varpool.cc | 4 ++++
5 files changed, 27 insertions(+)
diff --git a/gcc/cif-code.def b/gcc/cif-code.def
index 8735eafebc5..ea91a68b5d1 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 9d759d218b5..2ed9258e74a 100644
--- a/gcc/ipa-inline-transform.cc
+++ b/gcc/ipa-inline-transform.cc
@@ -495,6 +495,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, update_original, overall_size);
gcc_assert (curr->callee->inlined_to == to);
diff --git a/gcc/ipa-inline.cc b/gcc/ipa-inline.cc
index 0cf97a80687..04ceb2206f5 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/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.50.0