Hi, as discussed with Honza on many occasions, all users of cgraph_get_create_node really want cgraph_get_create_real_symbol_node, i.e. they are not interested in inline nodes and should get a standalone node instead. So this patch changes cgraph_get_create_node to do what cgraph_get_create_real_symbol_node currently does and removes the latter altogether.
I had to change a call to cgraph_get_create_node to cgraph_get_node in lto-streamer-in.c so that it does not make the node it operates on a clone of another one because this made ipa_pta_execute abort on assert after calling cgraph_get_body (visionary points to Richi for putting the assert there). The patch successfully passed bootstrap and testing ("all" languages + Ada) and LTO-bootstrap (C and C++ only) on x86_64-linux. OK for trunk? Thanks, Martin 2013-11-12 Martin Jambor <mjam...@suse.cz> * cgraph.c (cgraph_get_create_node): Do what cgraph_get_create_real_symbol_node used to do. (cgraph_get_create_real_symbol_node): Removed. Changed all users to call cgraph_get_create_node. * cgraph.h (cgraph_get_create_real_symbol_node): Removed. * lto-streamer-in.c (input_function): Call cgraph_get_node instead of cgraph_get_create_node. Assert we get a node. Index: src/gcc/cgraph.c =================================================================== --- src.orig/gcc/cgraph.c +++ src/gcc/cgraph.c @@ -540,19 +540,34 @@ cgraph_create_node (tree decl) return node; } -/* Try to find a call graph node for declaration DECL and if it does not exist, - create it. */ +/* Try to find a call graph node for declaration DECL and if it does not exist + or if it corresponds to an inline clone, create a new one. */ struct cgraph_node * cgraph_get_create_node (tree decl) { - struct cgraph_node *node; + struct cgraph_node *first_clone = cgraph_get_node (decl); - node = cgraph_get_node (decl); - if (node) - return node; + if (first_clone && !first_clone->global.inlined_to) + return first_clone; - return cgraph_create_node (decl); + struct cgraph_node *node = cgraph_create_node (decl); + if (first_clone) + { + first_clone->clone_of = node; + node->clones = first_clone; + symtab_prevail_in_asm_name_hash (node); + symtab_insert_node_to_hashtable (node); + if (dump_file) + fprintf (dump_file, "Introduced new external node " + "(%s/%i) and turned into root of the clone tree.\n", + xstrdup (cgraph_node_name (node)), node->order); + } + else if (dump_file) + fprintf (dump_file, "Introduced new external node " + "(%s/%i).\n", xstrdup (cgraph_node_name (node)), + node->order); + return node; } /* Mark ALIAS as an alias to DECL. DECL_NODE is cgraph node representing @@ -2889,51 +2904,6 @@ verify_cgraph (void) verify_cgraph_node (node); } -/* Create external decl node for DECL. - The difference i nbetween cgraph_get_create_node and - cgraph_get_create_real_symbol_node is that cgraph_get_create_node - may return inline clone, while cgraph_get_create_real_symbol_node - will create a new node in this case. - FIXME: This function should be removed once clones are put out of decl - hash. */ - -struct cgraph_node * -cgraph_get_create_real_symbol_node (tree decl) -{ - struct cgraph_node *first_clone = cgraph_get_node (decl); - struct cgraph_node *node; - /* create symbol table node. even if inline clone exists, we can not take - it as a target of non-inlined call. */ - node = cgraph_get_node (decl); - if (node && !node->global.inlined_to) - return node; - - node = cgraph_create_node (decl); - - /* ok, we previously inlined the function, then removed the offline copy and - now we want it back for external call. this can happen when devirtualizing - while inlining function called once that happens after extern inlined and - virtuals are already removed. in this case introduce the external node - and make it available for call. */ - if (first_clone) - { - first_clone->clone_of = node; - node->clones = first_clone; - symtab_prevail_in_asm_name_hash (node); - symtab_insert_node_to_hashtable (node); - if (dump_file) - fprintf (dump_file, "Introduced new external node " - "(%s/%i) and turned into root of the clone tree.\n", - xstrdup (cgraph_node_name (node)), node->order); - } - else if (dump_file) - fprintf (dump_file, "Introduced new external node " - "(%s/%i).\n", xstrdup (cgraph_node_name (node)), - node->order); - return node; -} - - /* Given NODE, walk the alias chain to return the function NODE is alias of. Walk through thunk, too. When AVAILABILITY is non-NULL, get minimal availability in the chain. */ Index: src/gcc/cgraph.h =================================================================== --- src.orig/gcc/cgraph.h +++ src/gcc/cgraph.h @@ -633,7 +633,6 @@ struct cgraph_indirect_call_info *cgraph struct cgraph_node * cgraph_create_node (tree); struct cgraph_node * cgraph_create_empty_node (void); struct cgraph_node * cgraph_get_create_node (tree); -struct cgraph_node * cgraph_get_create_real_symbol_node (tree); struct cgraph_node * cgraph_same_body_alias (struct cgraph_node *, tree, tree); struct cgraph_node * cgraph_add_thunk (struct cgraph_node *, tree, tree, bool, HOST_WIDE_INT, HOST_WIDE_INT, tree, tree); Index: src/gcc/cgraphbuild.c =================================================================== --- src.orig/gcc/cgraphbuild.c +++ src/gcc/cgraphbuild.c @@ -71,7 +71,7 @@ record_reference (tree *tp, int *walk_su decl = get_base_var (*tp); if (TREE_CODE (decl) == FUNCTION_DECL) { - struct cgraph_node *node = cgraph_get_create_real_symbol_node (decl); + struct cgraph_node *node = cgraph_get_create_node (decl); if (!ctx->only_vars) cgraph_mark_address_taken_node (node); ipa_record_reference (ctx->varpool_node, @@ -139,9 +139,9 @@ record_eh_tables (struct cgraph_node *no if (DECL_FUNCTION_PERSONALITY (node->decl)) { - struct cgraph_node *per_node; + tree per_decl = DECL_FUNCTION_PERSONALITY (node->decl); + struct cgraph_node *per_node = cgraph_get_create_node (per_decl); - per_node = cgraph_get_create_real_symbol_node (DECL_FUNCTION_PERSONALITY (node->decl)); ipa_record_reference (node, per_node, IPA_REF_ADDR, NULL); cgraph_mark_address_taken_node (per_node); } @@ -221,7 +221,7 @@ mark_address (gimple stmt, tree addr, vo addr = get_base_address (addr); if (TREE_CODE (addr) == FUNCTION_DECL) { - struct cgraph_node *node = cgraph_get_create_real_symbol_node (addr); + struct cgraph_node *node = cgraph_get_create_node (addr); cgraph_mark_address_taken_node (node); ipa_record_reference ((symtab_node *)data, node, @@ -250,7 +250,7 @@ mark_load (gimple stmt, tree t, void *da { /* ??? This can happen on platforms with descriptors when these are directly manipulated in the code. Pretend that it's an address. */ - struct cgraph_node *node = cgraph_get_create_real_symbol_node (t); + struct cgraph_node *node = cgraph_get_create_node (t); cgraph_mark_address_taken_node (node); ipa_record_reference ((symtab_node *)data, node, @@ -338,7 +338,7 @@ build_cgraph_edges (void) { tree fn = gimple_omp_parallel_child_fn (stmt); ipa_record_reference (node, - cgraph_get_create_real_symbol_node (fn), + cgraph_get_create_node (fn), IPA_REF_ADDR, stmt); } if (gimple_code (stmt) == GIMPLE_OMP_TASK) @@ -346,12 +346,12 @@ build_cgraph_edges (void) tree fn = gimple_omp_task_child_fn (stmt); if (fn) ipa_record_reference (node, - cgraph_get_create_real_symbol_node (fn), + cgraph_get_create_node (fn), IPA_REF_ADDR, stmt); fn = gimple_omp_task_copy_fn (stmt); if (fn) ipa_record_reference (node, - cgraph_get_create_real_symbol_node (fn), + cgraph_get_create_node (fn), IPA_REF_ADDR, stmt); } } Index: src/gcc/gimple-fold.c =================================================================== --- src.orig/gcc/gimple-fold.c +++ src/gcc/gimple-fold.c @@ -196,7 +196,7 @@ canonicalize_constructor_val (tree cval, /* Make sure we create a cgraph node for functions we'll reference. They can be non-existent if the reference comes from an entry of an external vtable for example. */ - cgraph_get_create_real_symbol_node (base); + cgraph_get_create_node (base); } /* Fixup types in global initializers. */ if (TREE_TYPE (TREE_TYPE (cval)) != TREE_TYPE (TREE_OPERAND (cval, 0))) Index: src/gcc/ipa-prop.c =================================================================== --- src.orig/gcc/ipa-prop.c +++ src/gcc/ipa-prop.c @@ -2454,7 +2454,7 @@ ipa_make_edge_direct_to_target (struct c ie->callee->order); return NULL; } - callee = cgraph_get_create_real_symbol_node (target); + callee = cgraph_get_create_node (target); } ipa_check_create_node_params (); Index: src/gcc/ipa.c =================================================================== --- src.orig/gcc/ipa.c +++ src/gcc/ipa.c @@ -355,7 +355,7 @@ symtab_remove_unreachable_nodes (bool be if (DECL_ABSTRACT_ORIGIN (node->decl)) { struct cgraph_node *origin_node - = cgraph_get_create_real_symbol_node (DECL_ABSTRACT_ORIGIN (node->decl)); + = cgraph_get_create_node (DECL_ABSTRACT_ORIGIN (node->decl)); origin_node->used_as_abstract_origin = true; enqueue_node (origin_node, &first, reachable); } Index: src/gcc/lto-streamer-in.c =================================================================== --- src.orig/gcc/lto-streamer-in.c +++ src/gcc/lto-streamer-in.c @@ -915,7 +915,8 @@ input_function (tree fn_decl, struct dat gimple_register_cfg_hooks (); - node = cgraph_get_create_node (fn_decl); + node = cgraph_get_node (fn_decl); + gcc_checking_assert (node); input_struct_function_base (fn, data_in, ib); input_cfg (ib_cfg, fn, node->count_materialization_scale);