> 
> 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

Reply via email to