mirror of
https://forge.sourceware.org/marek/gcc.git
synced 2026-02-21 19:35:36 -05:00
lto: Add must_remain_in_tu flags to symtab_node
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.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
14
gcc/tree.cc
14
gcc/tree.cc
@@ -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))
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user