I see you have patch, too :)
However we do not want to copy clone info to every inline clone (since
the body is materialized just once).  The problem is that in case the
offline copy is removed we move clone info to first inline clone and
reshape the tree.  This is quite old code to save little memory for the
extra symbol that I may get rid of becuase it also trigger quadratic
time issues with tree-inline, but for now we should copy the info
correctly.  Code is not very well structured for this since it first
calls removal hooks and only then looks for replacement so patch is bit
ugly.  I will clean it up incrementally.

gcc/ChangeLog:

2020-11-03  Jan Hubicka  <hubi...@ucw.cz>

        * cgraph.c (cgraph_edge::redirect_call_stmt_to_callee): Fix ICE with
        in dumping code.
        (cgraph_node::remove): Save clone info before releasing it and pass it
        to unregister.
        * cgraph.h (symtab_node::unregister): Add clone_info parameter.
        (cgraph_clone::unregister): Likewise.
        * cgraphclones.c (cgraph_node::find_replacement): Copy clone info
        * symtab-clones.cc (clone_infos_t::duplicate): Remove.
        (clone_info::get_create): Simplify.
        * symtab.c (symtab_node::unregister): Pass around clone info.
        * varpool.c (varpool_node::remove): Update.

diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 36bdb009bf8..19dfe2be23b 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -1503,14 +1503,13 @@ cgraph_edge::redirect_call_stmt_to_callee (cgraph_edge 
*e)
 
   if (symtab->dump_file)
     {
-
       fprintf (symtab->dump_file, "updating call of %s -> %s: ",
               e->caller->dump_name (), e->callee->dump_name ());
       print_gimple_stmt (symtab->dump_file, e->call_stmt, 0, dump_flags);
       if (callee_info && callee_info->param_adjustments)
        callee_info->param_adjustments->dump (symtab->dump_file);
       unsigned performed_len
-       = vec_safe_length (caller_info->performed_splits);
+       = caller_info ? vec_safe_length (caller_info->performed_splits) : 0;
       if (performed_len > 0)
        fprintf (symtab->dump_file, "Performed splits records:\n");
       for (unsigned i = 0; i < performed_len; i++)
@@ -1861,12 +1860,19 @@ cgraph_node::release_body (bool keep_arguments)
 void
 cgraph_node::remove (void)
 {
+  bool clone_info_set = false;
+  clone_info *info, saved_info;
   if (symtab->ipa_clones_dump_file && symtab->cloned_nodes.contains (this))
     fprintf (symtab->ipa_clones_dump_file,
             "Callgraph removal;%s;%d;%s;%d;%d\n", asm_name (), order,
             DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl),
             DECL_SOURCE_COLUMN (decl));
 
+  if ((info = clone_info::get (this)) != NULL)
+    {
+      saved_info = *info;
+      clone_info_set = true;
+    }
   symtab->call_cgraph_removal_hooks (this);
   remove_callers ();
   remove_callees ();
@@ -1878,7 +1884,7 @@ cgraph_node::remove (void)
   force_output = false;
   forced_by_abi = false;
 
-  unregister ();
+  unregister (clone_info_set ? &saved_info : NULL);
   if (prev_sibling_clone)
     prev_sibling_clone->next_sibling_clone = next_sibling_clone;
   else if (clone_of)
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index cd22676ff9e..c87180f1e96 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -631,7 +631,7 @@ protected:
 
   /* Remove node from symbol table.  This function is not used directly, but 
via
      cgraph/varpool node removal routines.  */
-  void unregister (void);
+  void unregister (struct clone_info *);
 
   /* Return the initialization and finalization priority information for
      DECL.  If there is no previous priority information, a freshly
@@ -949,7 +949,7 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public 
symtab_node
 
   /* cgraph node being removed from symbol table; see if its entry can be
    replaced by other inline clone.  */
-  cgraph_node *find_replacement (void);
+  cgraph_node *find_replacement (struct clone_info *);
 
   /* Create a new cgraph node which is the new version of
      callgraph node.  REDIRECT_CALLERS holds the callers
diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c
index 36ca6477139..a49e58ce279 100644
--- a/gcc/cgraphclones.c
+++ b/gcc/cgraphclones.c
@@ -650,7 +650,7 @@ cgraph_node::create_virtual_clone (vec<cgraph_edge *> 
redirect_callers,
 /* callgraph node being removed from symbol table; see if its entry can be
    replaced by other inline clone.  */
 cgraph_node *
-cgraph_node::find_replacement (void)
+cgraph_node::find_replacement (clone_info *info)
 {
   cgraph_node *next_inline_clone, *replacement;
 
@@ -690,7 +690,6 @@ cgraph_node::find_replacement (void)
       clones = NULL;
 
       /* Copy clone info.  */
-      clone_info *info = clone_info::get (this);
       if (info)
        *clone_info::get_create (next_inline_clone) = *info;
 
diff --git a/gcc/symtab-clones.cc b/gcc/symtab-clones.cc
index 76b86c6496f..ad154f6522d 100644
--- a/gcc/symtab-clones.cc
+++ b/gcc/symtab-clones.cc
@@ -42,22 +42,8 @@ class GTY((user)) clone_infos_t: public function_summary 
<clone_info *>
 public:
   clone_infos_t (symbol_table *table, bool ggc):
     function_summary<clone_info *> (table, ggc) { }
-
-  /* Hook that is called by summary when a node is duplicated.  */
-  virtual void duplicate (cgraph_node *node,
-                         cgraph_node *node2,
-                         clone_info *data,
-                         clone_info *data2);
 };
 
-/* Duplication hook.  */
-void
-clone_infos_t::duplicate (cgraph_node *, cgraph_node *,
-                         clone_info *src, clone_info *dst)
-{
-  *dst = *src;
-}
-
 }  /* anon namespace  */
 
 /* Return thunk_info possibly creating new one.  */
@@ -67,8 +53,8 @@ clone_info::get_create (cgraph_node *node)
   if (!symtab->m_clones)
     {
       symtab->m_clones
-        = new (ggc_alloc_no_dtor <clone_infos_t> ())
-            clone_infos_t (symtab, true);
+        = new (ggc_alloc_no_dtor <function_summary <clone_info *>> ())
+            function_summary <clone_info *> (symtab, true);
       symtab->m_clones->disable_insertion_hook ();
       symtab->m_clones->disable_duplication_hook ();
     }
diff --git a/gcc/symtab.c b/gcc/symtab.c
index 9db88fa8531..86f5184fdf4 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -411,7 +411,7 @@ symtab_node::remove_from_same_comdat_group (void)
    cgraph/varpool node removal routines.  */
 
 void
-symtab_node::unregister (void)
+symtab_node::unregister (clone_info *info)
 {
   remove_all_references ();
   remove_all_referring ();
@@ -430,7 +430,7 @@ symtab_node::unregister (void)
     {
       symtab_node *replacement_node = NULL;
       if (cgraph_node *cnode = dyn_cast <cgraph_node *> (this))
-       replacement_node = cnode->find_replacement ();
+       replacement_node = cnode->find_replacement (info);
       decl->decl_with_vis.symtab_node = replacement_node;
     }
   if (!is_a <varpool_node *> (this) || !DECL_HARD_REGISTER (decl))
diff --git a/gcc/varpool.c b/gcc/varpool.c
index 31ea2132331..dc04d10cd42 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -186,7 +186,7 @@ varpool_node::remove (void)
           && !ctor_useable_for_folding_p ())
     remove_initializer ();
 
-  unregister ();
+  unregister (NULL);
   ggc_free (this);
 }
 

Reply via email to