>
> 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.
OK
> --- a/gcc/ipa-icf.cc
> +++ b/gcc/ipa-icf.cc
> @@ -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");
> +
This is probably overly conservative. We can still prove equivalence
but prevent cross-module merging in sem_function::merge.
For that we probably also need to handle toplevel asm statements
specially, since literaly same staements in different units are not the
same.
> diff --git a/gcc/tree.cc b/gcc/tree.cc
> index 8dcb59dc875..2cfe8932c22 100644
> --- a/gcc/tree.cc
> +++ b/gcc/tree.cc
> @@ -4000,14 +4000,24 @@ 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:
> + node = symtab_node::get (op);
> + return !node || !node->must_remain_in_tu_name;
> +
> case VAR_DECL:
> + if (TREE_STATIC (op) || DECL_EXTERNAL (op))
> + {
> + node = symtab_node::get (op);
> + if (node && node->must_remain_in_tu_name)
> + return false;
> + }
Please add a comment here.
Honza