https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97695
--- Comment #5 from Jan Hubicka <hubicka at ucw dot cz> --- 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); }