diff options
-rw-r--r-- | gcc/ChangeLog | 94 | ||||
-rw-r--r-- | gcc/Makefile.in | 2 | ||||
-rw-r--r-- | gcc/cgraph.c | 32 | ||||
-rw-r--r-- | gcc/cgraph.h | 72 | ||||
-rw-r--r-- | gcc/cgraphbuild.c | 59 | ||||
-rw-r--r-- | gcc/cgraphclones.c | 11 | ||||
-rw-r--r-- | gcc/cgraphunit.c | 17 | ||||
-rw-r--r-- | gcc/ipa-comdats.c | 6 | ||||
-rw-r--r-- | gcc/ipa-cp.c | 9 | ||||
-rw-r--r-- | gcc/ipa-devirt.c | 3 | ||||
-rw-r--r-- | gcc/ipa-inline-transform.c | 4 | ||||
-rw-r--r-- | gcc/ipa-inline.c | 16 | ||||
-rw-r--r-- | gcc/ipa-prop.c | 24 | ||||
-rw-r--r-- | gcc/ipa-pure-const.c | 8 | ||||
-rw-r--r-- | gcc/ipa-ref.c | 284 | ||||
-rw-r--r-- | gcc/ipa-ref.h | 64 | ||||
-rw-r--r-- | gcc/ipa-reference.c | 12 | ||||
-rw-r--r-- | gcc/ipa-split.c | 2 | ||||
-rw-r--r-- | gcc/ipa-utils.c | 6 | ||||
-rw-r--r-- | gcc/ipa-visibility.c | 15 | ||||
-rw-r--r-- | gcc/ipa.c | 33 | ||||
-rw-r--r-- | gcc/lto-cgraph.c | 48 | ||||
-rw-r--r-- | gcc/lto-streamer-in.c | 6 | ||||
-rw-r--r-- | gcc/lto-streamer-out.c | 3 | ||||
-rw-r--r-- | gcc/lto-streamer.h | 2 | ||||
-rw-r--r-- | gcc/lto/lto-partition.c | 28 | ||||
-rw-r--r-- | gcc/lto/lto-symtab.c | 4 | ||||
-rw-r--r-- | gcc/symtab.c | 293 | ||||
-rw-r--r-- | gcc/trans-mem.c | 8 | ||||
-rw-r--r-- | gcc/tree-emutls.c | 2 | ||||
-rw-r--r-- | gcc/tree-inline.c | 6 | ||||
-rw-r--r-- | gcc/varpool.c | 17 |
32 files changed, 684 insertions, 506 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fd7bec24758..e35a8fe4f89 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,97 @@ +2014-06-25 Martin Liska <mliska@suse.cz> + + IPA REF refactoring + * Makefile.in: Removed header file (ipa-ref-inline.h). + * cgraph.c (cgraph_turn_edge_to_speculative): New IPA REF function + called. + (cgraph_speculative_call_info): Likewise. + (cgraph_for_node_thunks_and_aliases): Likewise. + (cgraph_for_node_and_aliases): Likewise. + (verify_cgraph_node): Likewise. + * cgraph.h: Batch of IPA REF functions become member functions of + symtab_node: add_reference, maybe_add_reference, clone_references, + clone_referring, clone_reference, find_reference, + remove_stmt_references, remove_all_references, + remove_all_referring, dump_references, dump_referring, + has_alias_p, iterate_reference, iterate_referring. + * cgraphbuild.c (record_reference): New IPA REF function used. + (record_type_list): Likewise. + (record_eh_tables): Likewise. + (mark_address): Likewise. + (mark_load): Likewise. + (mark_store): Likewise. + (pass_build_cgraph_edges): Likewise. + (rebuild_cgraph_edge): Likewise. + (cgraph_rebuild_references): Likewise. + (pass_remove_cgraph_callee_edges): Likewise. + * cgraphclones.c (cgraph_clone_node): Likewise. + (cgraph_create_virtual_clone): Likewise. + (cgraph_materialize_clone): Likewise. + (cgraph_materialize_all_clones): Likewise. + * cgraphunit.c (cgraph_reset_node): Likewise. + (cgraph_reset_node): Likewise. + (analyze_function): Likewise. + (assemble_thunks_and_aliases): Likewise. + (expand_function): Likewise. + * ipa-comdats.c (propagate_comdat_group): Likewise. + (enqueue_references): Likewise. + * ipa-cp.c (ipcp_discover_new_direct_edges): Likewise. + (create_specialized_node): Likewise. + * ipa-devirt.c (referenced_from_vtable_p): Likewise. + * ipa-inline-transform.c (can_remove_node_now_p_1): Likewise. + * ipa-inline.c (reset_edge_caches): Likewise. + (update_caller_keys): Likewise. + (execute): Likewise. + * ipa-prop.c (remove_described_reference): Likewise. + (propagate_controlled_uses): Likewise. + (ipa_edge_duplication_hook): Likewise. + (ipa_modify_call_arguments): Likewise. + * ipa-pure-const.c (propagate_pure_const): Likewise. + * ipa-ref-inline.h: Header file removed, functions moved + to symtab_node class. + * ipa-ref.c (remove_reference): New class member function. + (cannot_lead_to_return): New class member function. + (referring_ref_list): Likewise. + (referred_ref_list): Likewise. + Rest of functions moved to symtab_node class. + * ipa-ref.h: New member functions remove_reference, + cannot_lead_to_return, referring_ref_list, referred_ref_list added + to ipa_ref class. + ipa_ref_list class has new member functions: first_reference, + first_referring, clear, nreferences. + * ipa-reference.c (analyze_function): New IPA REF function used. + (write_node_summary_p): Likewise. + (ipa_reference_write_optimization_summary): Likewise. + * ipa-split.c (split_function): Likewise. + * ipa-utils.c (ipa_reverse_postorder): Likewise. + * ipa-visibility.c (cgraph_non_local_node_p_1): Likewise. + (function_and_variable_visibility): Likewise. + * ipa.c (has_addr_references_p): Likewise. + (process_references): Argument type changed. + (symtab_remove_unreachable_nodes): New IPA REF function used. + (process_references): Likewise. + (set_writeonly_bit): Likewise. + * lto-cgraph.c: Implementation of new symtab_node member functions + that uses new IPA REF functions. + * lto-streamer-in.c (fixup_call_stmt_edges_1): New IPA REF function used. + * lto-streamer-out.c (output_symbol_p): Likewise. + * lto-streamer.h (referenced_from_this_partition_p): Argument type + changed. + * lto/lto-partition.c (add_references_to_partition): New IPA REF function + used. + (add_symbol_to_partition_1): Likewise. + (lto_balanced_map): Likewise. + * lto/lto-symtab.c (lto_cgraph_replace_node): Likewise. + * symtab.c: Implementation of new IPA REF API. + * trans-mem.c (ipa_tm_create_version_alias): New IPA REF function used. + (ipa_tm_create_version): Likewise. + (ipa_tm_execute): Likewise. + * tree-emutls.c (gen_emutls_addr): Likewise. + * tree-inline.c (copy_bb): Likewise. + (delete_unreachable_blocks_update_callgraph): Likewise. + * varpool.c (varpool_remove_unreferenced_decls): Likewise. + (varpool_for_node_and_aliases): Likewise. + 2014-06-25 Trevor Saunders <tsaunders@mozilla.com> * config/i386/winnt.c (i386_find_on_wrapper_list): Fix typo. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 5587b75d62a..c9502736a83 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -905,7 +905,7 @@ CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) double-int.h \ IPA_UTILS_H = ipa-utils.h $(TREE_H) $(CGRAPH_H) IPA_REFERENCE_H = ipa-reference.h $(BITMAP_H) $(TREE_H) CGRAPH_H = cgraph.h $(VEC_H) $(TREE_H) $(BASIC_BLOCK_H) $(FUNCTION_H) \ - cif-code.def ipa-ref.h ipa-ref-inline.h $(LINKER_PLUGIN_API_H) is-a.h + cif-code.def ipa-ref.h $(LINKER_PLUGIN_API_H) is-a.h DF_H = df.h $(BITMAP_H) $(REGSET_H) sbitmap.h $(BASIC_BLOCK_H) \ alloc-pool.h $(TIMEVAR_H) RESOURCE_H = resource.h hard-reg-set.h $(DF_H) diff --git a/gcc/cgraph.c b/gcc/cgraph.c index afd41b71798..7360f773421 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -1101,7 +1101,7 @@ cgraph_turn_edge_to_speculative (struct cgraph_edge *e, int direct_frequency) { struct cgraph_node *n = e->caller; - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; struct cgraph_edge *e2; if (dump_file) @@ -1123,8 +1123,7 @@ cgraph_turn_edge_to_speculative (struct cgraph_edge *e, e->count -= e2->count; e->frequency -= e2->frequency; cgraph_call_edge_duplication_hooks (e, e2); - ref = ipa_record_reference (n, n2, - IPA_REF_ADDR, e->call_stmt); + ref = n->add_reference (n2, IPA_REF_ADDR, e->call_stmt); ref->lto_stmt_uid = e->lto_stmt_uid; ref->speculative = e->speculative; cgraph_mark_address_taken_node (n2); @@ -1177,8 +1176,7 @@ cgraph_speculative_call_info (struct cgraph_edge *e, indirect = e2; reference = NULL; - for (i = 0; ipa_ref_list_reference_iterate (&e->caller->ref_list, - i, ref); i++) + for (i = 0; e->caller->iterate_reference (i, ref); i++) if (ref->speculative && ((ref->stmt && ref->stmt == e->call_stmt) || (!ref->stmt && ref->lto_stmt_uid == e->lto_stmt_uid))) @@ -1257,7 +1255,7 @@ cgraph_resolve_speculation (struct cgraph_edge *edge, tree callee_decl) edge->frequency = CGRAPH_FREQ_MAX; edge->speculative = false; e2->speculative = false; - ipa_remove_reference (ref); + ref->remove_reference (); if (e2->indirect_unknown_callee || e2->inline_failed) cgraph_remove_edge (e2); else @@ -2197,7 +2195,7 @@ cgraph_for_node_thunks_and_aliases (struct cgraph_node *node, { struct cgraph_edge *e; int i; - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; if (callback (node, data)) return true; @@ -2208,10 +2206,10 @@ cgraph_for_node_thunks_and_aliases (struct cgraph_node *node, if (cgraph_for_node_thunks_and_aliases (e->caller, callback, data, include_overwritable)) return true; - for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) + for (i = 0; node->iterate_referring (i, ref); i++) if (ref->use == IPA_REF_ALIAS) { - struct cgraph_node *alias = ipa_ref_referring_node (ref); + struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring); if (include_overwritable || cgraph_function_body_availability (alias) > AVAIL_OVERWRITABLE) if (cgraph_for_node_thunks_and_aliases (alias, callback, data, @@ -2232,14 +2230,14 @@ cgraph_for_node_and_aliases (struct cgraph_node *node, bool include_overwritable) { int i; - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; if (callback (node, data)) return true; - for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) + for (i = 0; node->iterate_referring (i, ref); i++) if (ref->use == IPA_REF_ALIAS) { - struct cgraph_node *alias = ipa_ref_referring_node (ref); + struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring); if (include_overwritable || cgraph_function_body_availability (alias) > AVAIL_OVERWRITABLE) if (cgraph_for_node_and_aliases (alias, callback, data, @@ -2843,15 +2841,14 @@ verify_cgraph_node (struct cgraph_node *node) { bool ref_found = false; int i; - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; if (node->callees) { error ("Alias has call edges"); error_found = true; } - for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, - i, ref); i++) + for (i = 0; node->iterate_reference (i, ref); i++) if (ref->use != IPA_REF_ALIAS) { error ("Alias has non-alias reference"); @@ -2897,7 +2894,7 @@ verify_cgraph_node (struct cgraph_node *node) { pointer_set_t *stmts = pointer_set_create (); int i; - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; /* Reach the trees by walking over the CFG, and note the enclosing basic-blocks in the call edges. */ @@ -2955,8 +2952,7 @@ verify_cgraph_node (struct cgraph_node *node) } } for (i = 0; - ipa_ref_list_reference_iterate (&node->ref_list, i, ref); - i++) + node->iterate_reference (i, ref); i++) if (ref->stmt && !pointer_set_contains (stmts, ref->stmt)) { error ("reference to dead statement"); diff --git a/gcc/cgraph.h b/gcc/cgraph.h index ce6b9e64de8..0761e266a14 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -189,6 +189,71 @@ public: return x_section->name; } + /* Return ipa reference from this symtab_node to + REFERED_NODE or REFERED_VARPOOL_NODE. USE_TYPE specify type + of the use and STMT the statement (if it exists). */ + struct ipa_ref *add_reference (symtab_node *referred_node, + enum ipa_ref_use use_type); + + /* Return ipa reference from this symtab_node to + REFERED_NODE or REFERED_VARPOOL_NODE. USE_TYPE specify type + of the use and STMT the statement (if it exists). */ + struct ipa_ref *add_reference (symtab_node *referred_node, + enum ipa_ref_use use_type, gimple stmt); + + /* If VAL is a reference to a function or a variable, add a reference from + this symtab_node to the corresponding symbol table node. USE_TYPE specify + type of the use and STMT the statement (if it exists). Return the new + reference or NULL if none was created. */ + struct ipa_ref *maybe_add_reference (tree val, enum ipa_ref_use use_type, + gimple stmt); + + /* Clone all references from symtab NODE to this symtab_node. */ + void clone_references (symtab_node *node); + + /* Remove all stmt references in non-speculative references. + Those are not maintained during inlining & clonning. + The exception are speculative references that are updated along + with callgraph edges associated with them. */ + void clone_referring (symtab_node *node); + + /* Clone reference REF to this symtab_node and set its stmt to STMT. */ + struct ipa_ref *clone_reference (struct ipa_ref *ref, gimple stmt); + + /* Find the structure describing a reference to REFERRED_NODE + and associated with statement STMT. */ + struct ipa_ref *find_reference (symtab_node *, gimple, unsigned int); + + /* Remove all references that are associated with statement STMT. */ + void remove_stmt_references (gimple stmt); + + /* Remove all stmt references in non-speculative references. + Those are not maintained during inlining & clonning. + The exception are speculative references that are updated along + with callgraph edges associated with them. */ + void clear_stmts_in_references (void); + + /* Remove all references in ref list. */ + void remove_all_references (void); + + /* Remove all referring items in ref list. */ + void remove_all_referring (void); + + /* Dump references in ref list to FILE. */ + void dump_references (FILE *file); + + /* Dump referring in list to FILE. */ + void dump_referring (FILE *); + + /* Return true if list contains an alias. */ + bool has_aliases_p (void); + + /* Iterates I-th reference in the list, REF is also set. */ + struct ipa_ref *iterate_reference (unsigned i, struct ipa_ref *&ref); + + /* Iterates I-th referring item in the list, REF is also set. */ + struct ipa_ref *iterate_referring (unsigned i, struct ipa_ref *&ref); + /* Vectors of referring and referenced entities. */ struct ipa_ref_list ref_list; @@ -1537,16 +1602,13 @@ varpool_all_refs_explicit_p (varpool_node *vnode) /* Constant pool accessor function. */ htab_t constant_pool_htab (void); -/* FIXME: inappropriate dependency of cgraph on IPA. */ -#include "ipa-ref-inline.h" - /* Return node that alias N is aliasing. */ static inline symtab_node * symtab_alias_target (symtab_node *n) { - struct ipa_ref *ref; - ipa_ref_list_reference_iterate (&n->ref_list, 0, ref); + struct ipa_ref *ref = NULL; + n->iterate_reference (0, ref); gcc_checking_assert (ref->use == IPA_REF_ALIAS); return ref->referred; } diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c index 6bdc8ca0eda..bfc4495ca19 100644 --- a/gcc/cgraphbuild.c +++ b/gcc/cgraphbuild.c @@ -82,17 +82,13 @@ record_reference (tree *tp, int *walk_subtrees, void *data) 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, - node, - IPA_REF_ADDR, NULL); + ctx->varpool_node->add_reference (node, IPA_REF_ADDR); } if (TREE_CODE (decl) == VAR_DECL) { varpool_node *vnode = varpool_node_for_decl (decl); - ipa_record_reference (ctx->varpool_node, - vnode, - IPA_REF_ADDR, NULL); + ctx->varpool_node->add_reference (vnode, IPA_REF_ADDR); } *walk_subtrees = 0; break; @@ -129,9 +125,7 @@ record_type_list (struct cgraph_node *node, tree list) if (TREE_CODE (type) == VAR_DECL) { varpool_node *vnode = varpool_node_for_decl (type); - ipa_record_reference (node, - vnode, - IPA_REF_ADDR, NULL); + node->add_reference (vnode, IPA_REF_ADDR); } } } @@ -150,7 +144,7 @@ record_eh_tables (struct cgraph_node *node, struct function *fun) tree per_decl = DECL_FUNCTION_PERSONALITY (node->decl); struct cgraph_node *per_node = cgraph_get_create_node (per_decl); - ipa_record_reference (node, per_node, IPA_REF_ADDR, NULL); + node->add_reference (per_node, IPA_REF_ADDR); cgraph_mark_address_taken_node (per_node); } @@ -231,18 +225,14 @@ mark_address (gimple stmt, tree addr, tree, void *data) { struct cgraph_node *node = cgraph_get_create_node (addr); cgraph_mark_address_taken_node (node); - ipa_record_reference ((symtab_node *)data, - node, - IPA_REF_ADDR, stmt); + ((symtab_node *)data)->add_reference (node, IPA_REF_ADDR, stmt); } else if (addr && TREE_CODE (addr) == VAR_DECL && (TREE_STATIC (addr) || DECL_EXTERNAL (addr))) { varpool_node *vnode = varpool_node_for_decl (addr); - ipa_record_reference ((symtab_node *)data, - vnode, - IPA_REF_ADDR, stmt); + ((symtab_node *)data)->add_reference (vnode, IPA_REF_ADDR, stmt); } return false; @@ -260,18 +250,14 @@ mark_load (gimple stmt, tree t, tree, void *data) directly manipulated in the code. Pretend that it's an address. */ struct cgraph_node *node = cgraph_get_create_node (t); cgraph_mark_address_taken_node (node); - ipa_record_reference ((symtab_node *)data, - node, - IPA_REF_ADDR, stmt); + ((symtab_node *)data)->add_reference (node, IPA_REF_ADDR, stmt); } else if (t && TREE_CODE (t) == VAR_DECL && (TREE_STATIC (t) || DECL_EXTERNAL (t))) { varpool_node *vnode = varpool_node_for_decl (t); - ipa_record_reference ((symtab_node *)data, - vnode, - IPA_REF_LOAD, stmt); + ((symtab_node *)data)->add_reference (vnode, IPA_REF_LOAD, stmt); } return false; } @@ -287,9 +273,7 @@ mark_store (gimple stmt, tree t, tree, void *data) { varpool_node *vnode = varpool_node_for_decl (t); - ipa_record_reference ((symtab_node *)data, - vnode, - IPA_REF_STORE, stmt); + ((symtab_node *)data)->add_reference (vnode, IPA_REF_STORE, stmt); } return false; } @@ -375,22 +359,19 @@ pass_build_cgraph_edges::execute (function *fun) && gimple_omp_parallel_child_fn (stmt)) { tree fn = gimple_omp_parallel_child_fn (stmt); - ipa_record_reference (node, - cgraph_get_create_node (fn), - IPA_REF_ADDR, stmt); + node->add_reference (cgraph_get_create_node (fn), + IPA_REF_ADDR, stmt); } if (gimple_code (stmt) == GIMPLE_OMP_TASK) { tree fn = gimple_omp_task_child_fn (stmt); if (fn) - ipa_record_reference (node, - cgraph_get_create_node (fn), - IPA_REF_ADDR, stmt); + node->add_reference (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_node (fn), - IPA_REF_ADDR, stmt); + node->add_reference (cgraph_get_create_node (fn), + IPA_REF_ADDR, stmt); } } for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) @@ -446,7 +427,7 @@ rebuild_cgraph_edges (void) gimple_stmt_iterator gsi; cgraph_node_remove_callees (node); - ipa_remove_all_references (&node->ref_list); + node->remove_all_references (); node->count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count; @@ -492,13 +473,13 @@ cgraph_rebuild_references (void) basic_block bb; struct cgraph_node *node = cgraph_get_node (current_function_decl); gimple_stmt_iterator gsi; - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; int i; /* Keep speculative references for further cgraph edge expansion. */ - for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref);) + for (i = 0; node->iterate_reference (i, ref);) if (!ref->speculative) - ipa_remove_reference (ref); + ref->remove_reference (); else i++; @@ -588,7 +569,7 @@ pass_remove_cgraph_callee_edges::execute (function *) { struct cgraph_node *node = cgraph_get_node (current_function_decl); cgraph_node_remove_callees (node); - ipa_remove_all_references (&node->ref_list); + node->remove_all_references (); return 0; } diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c index 6f83d746058..d57cd9f3a41 100644 --- a/gcc/cgraphclones.c +++ b/gcc/cgraphclones.c @@ -459,7 +459,7 @@ cgraph_clone_node (struct cgraph_node *n, tree decl, gcov_type count, int freq, for (e = n->indirect_calls; e; e = e->next_callee) cgraph_clone_edge (e, new_node, e->call_stmt, e->lto_stmt_uid, count_scale, freq, update_original); - ipa_clone_references (new_node, &n->ref_list); + new_node->clone_references (n); new_node->next_sibling_clone = n->clones; if (n->clones) @@ -568,8 +568,7 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node, || in_lto_p) new_node->unique_name = true; FOR_EACH_VEC_SAFE_ELT (tree_map, i, map) - ipa_maybe_record_reference (new_node, map->new_tree, - IPA_REF_ADDR, NULL); + new_node->maybe_add_reference (map->new_tree, IPA_REF_ADDR, NULL); if (!args_to_skip) new_node->clone.combined_args_to_skip = old_node->clone.combined_args_to_skip; else if (old_node->clone.combined_args_to_skip) @@ -1035,7 +1034,7 @@ cgraph_materialize_clone (struct cgraph_node *node) { cgraph_release_function_body (node->clone_of); cgraph_node_remove_callees (node->clone_of); - ipa_remove_all_references (&node->clone_of->ref_list); + node->clone_of->remove_all_references (); } node->clone_of = NULL; bitmap_obstack_release (NULL); @@ -1120,10 +1119,10 @@ cgraph_materialize_all_clones (void) if (!node->analyzed && node->callees) { cgraph_node_remove_callees (node); - ipa_remove_all_references (&node->ref_list); + node->remove_all_references (); } else - ipa_clear_stmts_in_references (node); + node->clear_stmts_in_references (); if (cgraph_dump_file) fprintf (cgraph_dump_file, "Materialization Call site updates done.\n"); #ifdef ENABLE_CHECKING diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 1b7ab330a3e..76b2fda1d1e 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -393,7 +393,7 @@ cgraph_reset_node (struct cgraph_node *node) node->cpp_implicit_alias = false; cgraph_node_remove_callees (node); - ipa_remove_all_references (&node->ref_list); + node->remove_all_references (); } /* Return true when there are references to NODE. */ @@ -401,10 +401,10 @@ cgraph_reset_node (struct cgraph_node *node) static bool referred_to_p (symtab_node *node) { - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; /* See if there are any references at all. */ - if (ipa_ref_list_referring_iterate (&node->ref_list, 0, ref)) + if (node->iterate_referring (0, ref)) return true; /* For functions check also calls. */ cgraph_node *cn = dyn_cast <cgraph_node *> (node); @@ -1069,7 +1069,7 @@ analyze_functions (void) next = next->same_comdat_group) enqueue_node (next); } - for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++) + for (i = 0; node->iterate_reference (i, ref); i++) if (ref->referred->definition) enqueue_node (ref->referred); cgraph_process_new_functions (); @@ -1712,7 +1712,7 @@ assemble_thunks_and_aliases (struct cgraph_node *node) { struct cgraph_edge *e; int i; - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; for (e = node->callers; e;) if (e->caller->thunk.thunk_p) @@ -1725,11 +1725,10 @@ assemble_thunks_and_aliases (struct cgraph_node *node) } else e = e->next_caller; - for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, - i, ref); i++) + for (i = 0; node->iterate_referring (i, ref); i++) if (ref->use == IPA_REF_ALIAS) { - struct cgraph_node *alias = ipa_ref_referring_node (ref); + struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring); bool saved_written = TREE_ASM_WRITTEN (node->decl); /* Force assemble_alias to really output the alias this time instead @@ -1852,7 +1851,7 @@ expand_function (struct cgraph_node *node) /* Eliminate all call edges. This is important so the GIMPLE_CALL no longer points to the dead function body. */ cgraph_node_remove_callees (node); - ipa_remove_all_references (&node->ref_list); + node->remove_all_references (); } /* Node comparer that is responsible for the order that corresponds diff --git a/gcc/ipa-comdats.c b/gcc/ipa-comdats.c index b1bc35e9392..f9e1ad80059 100644 --- a/gcc/ipa-comdats.c +++ b/gcc/ipa-comdats.c @@ -72,7 +72,7 @@ propagate_comdat_group (struct symtab_node *symbol, /* Walk all references to SYMBOL, recursively dive into aliases. */ for (i = 0; - ipa_ref_list_referring_iterate (&symbol->ref_list, i, ref) + symbol->iterate_referring (i, ref) && newgroup != error_mark_node; i++) { struct symtab_node *symbol2 = ref->referring; @@ -161,9 +161,9 @@ enqueue_references (symtab_node **first, symtab_node *symbol) { int i; - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; - for (i = 0; ipa_ref_list_reference_iterate (&symbol->ref_list, i, ref); i++) + for (i = 0; symbol->iterate_reference (i, ref); i++) { symtab_node *node = symtab_alias_ultimate_target (ref->referred, NULL); if (!node->aux && node->definition) diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 33ff9b63f6c..04e88b576fd 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -2387,14 +2387,12 @@ ipcp_discover_new_direct_edges (struct cgraph_node *node, fprintf (dump_file, " controlled uses count of param " "%i bumped down to %i\n", param_index, c); if (c == 0 - && (to_del = ipa_find_reference (node, - cs->callee, - NULL, 0))) + && (to_del = node->find_reference (cs->callee, NULL, 0))) { if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, " and even removing its " "cloning-created reference\n"); - ipa_remove_reference (to_del); + to_del->remove_reference (); } } } @@ -2803,8 +2801,7 @@ create_specialized_node (struct cgraph_node *node, args_to_skip, "constprop"); ipa_set_node_agg_value_chain (new_node, aggvals); for (av = aggvals; av; av = av->next) - ipa_maybe_record_reference (new_node, av->value, - IPA_REF_ADDR, NULL); + new_node->maybe_add_reference (av->value, IPA_REF_ADDR, NULL); if (dump_file && (dump_flags & TDF_DETAILS)) { diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c index 604b809dbcd..21f4f11218f 100644 --- a/gcc/ipa-devirt.c +++ b/gcc/ipa-devirt.c @@ -686,8 +686,7 @@ referenced_from_vtable_p (struct cgraph_node *node) if (cgraph_state <= CGRAPH_STATE_CONSTRUCTION) return true; - for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, - i, ref); i++) + for (i = 0; node->iterate_referring (i, ref); i++) if ((ref->use == IPA_REF_ALIAS && referenced_from_vtable_p (cgraph (ref->referring))) diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c index 4cfd87b1015..03442fc07d7 100644 --- a/gcc/ipa-inline-transform.c +++ b/gcc/ipa-inline-transform.c @@ -86,7 +86,7 @@ can_remove_node_now_p_1 (struct cgraph_node *node) can remove its offline copy, but we would need to keep unanalyzed node in the callgraph so references can point to it. */ return (!node->address_taken - && !ipa_ref_has_aliases_p (&node->ref_list) + && !node->has_aliases_p () && !node->used_as_abstract_origin && cgraph_can_remove_if_no_direct_calls_p (node) /* Inlining might enable more devirtualizing, so we want to remove @@ -451,7 +451,7 @@ inline_transform (struct cgraph_node *node) next = e->next_callee; cgraph_redirect_edge_call_stmt_to_callee (e); } - ipa_remove_all_references (&node->ref_list); + node->remove_all_references (); timevar_push (TV_INTEGRATION); if (node->callees && optimize) diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index 82bbd7f14dd..81030f3a01a 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -1120,7 +1120,7 @@ reset_edge_caches (struct cgraph_node *node) struct cgraph_edge *e = node->callees; struct cgraph_node *where = node; int i; - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; if (where->global.inlined_to) where = where->global.inlined_to; @@ -1131,10 +1131,9 @@ reset_edge_caches (struct cgraph_node *node) for (edge = where->callers; edge; edge = edge->next_caller) if (edge->inline_failed) reset_edge_growth_cache (edge); - for (i = 0; ipa_ref_list_referring_iterate (&where->ref_list, - i, ref); i++) + for (i = 0; where->iterate_referring (i, ref); i++) if (ref->use == IPA_REF_ALIAS) - reset_edge_caches (ipa_ref_referring_node (ref)); + reset_edge_caches (dyn_cast <cgraph_node *> (ref->referring)); if (!e) return; @@ -1174,7 +1173,7 @@ update_caller_keys (fibheap_t heap, struct cgraph_node *node, { struct cgraph_edge *edge; int i; - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; if ((!node->alias && !inline_summary (node)->inlinable) || node->global.inlined_to) @@ -1182,11 +1181,10 @@ update_caller_keys (fibheap_t heap, struct cgraph_node *node, if (!bitmap_set_bit (updated_nodes, node->uid)) return; - for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, - i, ref); i++) + for (i = 0; node->iterate_referring (i, ref); i++) if (ref->use == IPA_REF_ALIAS) { - struct cgraph_node *alias = ipa_ref_referring_node (ref); + struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring); update_caller_keys (heap, alias, updated_nodes, check_inlinablity_for); } @@ -2430,7 +2428,7 @@ pass_early_inline::execute (function *fun) #ifdef ENABLE_CHECKING verify_cgraph_node (node); #endif - ipa_remove_all_references (&node->ref_list); + node->remove_all_references (); /* Even when not optimizing or not inlining inline always-inline functions. */ diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index d9dca52d47f..5f5bf891a5d 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -2806,12 +2806,12 @@ remove_described_reference (symtab_node *symbol, struct ipa_cst_ref_desc *rdesc) origin = rdesc->cs; if (!origin) return false; - to_del = ipa_find_reference (origin->caller, symbol, - origin->call_stmt, origin->lto_stmt_uid); + to_del = origin->caller->find_reference (symbol, origin->call_stmt, + origin->lto_stmt_uid); if (!to_del) return false; - ipa_remove_reference (to_del); + to_del->remove_reference (); if (dump_file) fprintf (dump_file, "ipa-prop: Removed a reference from %s/%i to %s.\n", xstrdup (origin->caller->name ()), @@ -3209,8 +3209,7 @@ propagate_controlled_uses (struct cgraph_edge *cs) if (t && TREE_CODE (t) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL && (n = cgraph_get_node (TREE_OPERAND (t, 0))) - && (ref = ipa_find_reference (new_root, - n, NULL, 0))) + && (ref = new_root->find_reference (n, NULL, 0))) { if (dump_file) fprintf (dump_file, "ipa-prop: Removing cloning-created " @@ -3218,7 +3217,7 @@ propagate_controlled_uses (struct cgraph_edge *cs) xstrdup (new_root->name ()), new_root->order, xstrdup (n->name ()), n->order); - ipa_remove_reference (ref); + ref->remove_reference (); } } } @@ -3249,8 +3248,7 @@ propagate_controlled_uses (struct cgraph_edge *cs) && IPA_NODE_REF (clone)->ipcp_orig_node) { struct ipa_ref *ref; - ref = ipa_find_reference (clone, - n, NULL, 0); + ref = clone->find_reference (n, NULL, 0); if (ref) { if (dump_file) @@ -3261,7 +3259,7 @@ propagate_controlled_uses (struct cgraph_edge *cs) clone->order, xstrdup (n->name ()), n->order); - ipa_remove_reference (ref); + ref->remove_reference (); } clone = clone->callers->caller; } @@ -3455,10 +3453,10 @@ ipa_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst, struct ipa_ref *ref; symtab_node *n = cgraph_node_for_jfunc (src_jf); gcc_checking_assert (n); - ref = ipa_find_reference (src->caller, n, - src->call_stmt, src->lto_stmt_uid); + ref = src->caller->find_reference (n, src->call_stmt, + src->lto_stmt_uid); gcc_checking_assert (ref); - ipa_clone_ref (ref, dst->caller, ref->stmt); + dst->caller->clone_reference (ref, ref->stmt); gcc_checking_assert (ipa_refdesc_pool); struct ipa_cst_ref_desc *dst_rdesc @@ -3899,7 +3897,7 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt, len = adjustments.length (); vargs.create (len); callee_decl = !cs ? gimple_call_fndecl (stmt) : cs->callee->decl; - ipa_remove_stmt_references (current_node, stmt); + current_node->remove_stmt_references (stmt); gsi = gsi_for_stmt (stmt); prev_gsi = gsi; diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c index b9a3d3e0418..a074a1186c5 100644 --- a/gcc/ipa-pure-const.c +++ b/gcc/ipa-pure-const.c @@ -1138,7 +1138,7 @@ propagate_pure_const (void) struct cgraph_edge *e; struct cgraph_edge *ie; int i; - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; funct_state w_l = get_function_state (w); if (dump_file && (dump_flags & TDF_DETAILS)) @@ -1263,7 +1263,7 @@ propagate_pure_const (void) break; /* And finally all loads and stores. */ - for (i = 0; ipa_ref_list_reference_iterate (&w->ref_list, i, ref); i++) + for (i = 0; w->iterate_reference (i, ref); i++) { enum pure_const_state_e ref_state = IPA_CONST; bool ref_looping = false; @@ -1271,14 +1271,14 @@ propagate_pure_const (void) { case IPA_REF_LOAD: /* readonly reads are safe. */ - if (TREE_READONLY (ipa_ref_varpool_node (ref)->decl)) + if (TREE_READONLY (ref->referred->decl)) break; if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, " nonreadonly global var read\n"); ref_state = IPA_PURE; break; case IPA_REF_STORE: - if (ipa_ref_cannot_lead_to_return (ref)) + if (ref->cannot_lead_to_return ()) break; ref_state = IPA_NEITHER; if (dump_file && (dump_flags & TDF_DETAILS)) diff --git a/gcc/ipa-ref.c b/gcc/ipa-ref.c index df84c9cc1af..1be173a1b44 100644 --- a/gcc/ipa-ref.c +++ b/gcc/ipa-ref.c @@ -27,294 +27,60 @@ along with GCC; see the file COPYING3. If not see #include "cgraph.h" #include "ipa-utils.h" -static const char *ipa_ref_use_name[] = {"read","write","addr","alias"}; - -/* Return ipa reference from REFERING_NODE or REFERING_VARPOOL_NODE - to REFERED_NODE or REFERED_VARPOOL_NODE. USE_TYPE specify type - of the use and STMT the statement (if it exists). */ - -struct ipa_ref * -ipa_record_reference (symtab_node *referring_node, - symtab_node *referred_node, - enum ipa_ref_use use_type, gimple stmt) -{ - struct ipa_ref *ref, *ref2; - struct ipa_ref_list *list, *list2; - ipa_ref_t *old_references; - - gcc_checking_assert (!stmt || is_a <cgraph_node *> (referring_node)); - gcc_checking_assert (use_type != IPA_REF_ALIAS || !stmt); - - list = &referring_node->ref_list; - old_references = vec_safe_address (list->references); - vec_safe_grow (list->references, vec_safe_length (list->references) + 1); - ref = &list->references->last (); - - list2 = &referred_node->ref_list; - list2->referring.safe_push (ref); - ref->referred_index = list2->referring.length () - 1; - ref->referring = referring_node; - ref->referred = referred_node; - ref->stmt = stmt; - ref->lto_stmt_uid = 0; - ref->use = use_type; - ref->speculative = 0; - - /* If vector was moved in memory, update pointers. */ - if (old_references != list->references->address ()) - { - int i; - for (i = 0; ipa_ref_list_reference_iterate (list, i, ref2); i++) - ipa_ref_referred_ref_list (ref2)->referring[ref2->referred_index] = ref2; - } - return ref; -} - -/* If VAL is a reference to a function or a variable, add a reference from - REFERRING_NODE to the corresponding symbol table node. USE_TYPE specify - type of the use and STMT the statement (if it exists). Return the new - reference or NULL if none was created. */ - -struct ipa_ref * -ipa_maybe_record_reference (symtab_node *referring_node, tree val, - enum ipa_ref_use use_type, gimple stmt) -{ - STRIP_NOPS (val); - if (TREE_CODE (val) != ADDR_EXPR) - return NULL; - val = get_base_var (val); - if (val && (TREE_CODE (val) == FUNCTION_DECL - || TREE_CODE (val) == VAR_DECL)) - { - symtab_node *referred = symtab_get_node (val); - gcc_checking_assert (referred); - return ipa_record_reference (referring_node, referred, - use_type, stmt); - } - return NULL; -} - -/* Remove reference REF. */ +/* Remove reference. */ void -ipa_remove_reference (struct ipa_ref *ref) +ipa_ref::remove_reference () { - struct ipa_ref_list *list = ipa_ref_referred_ref_list (ref); - struct ipa_ref_list *list2 = ipa_ref_referring_ref_list (ref); + struct ipa_ref_list *list = referred_ref_list (); + struct ipa_ref_list *list2 = referring_ref_list (); vec<ipa_ref_t, va_gc> *old_references = list2->references; struct ipa_ref *last; - gcc_assert (list->referring[ref->referred_index] == ref); + gcc_assert (list->referring[referred_index] == this); last = list->referring.last (); - if (ref != last) + if (this != last) { - list->referring[ref->referred_index] = list->referring.last (); - list->referring[ref->referred_index]->referred_index - = ref->referred_index; + list->referring[referred_index] = list->referring.last (); + list->referring[referred_index]->referred_index + = referred_index; } list->referring.pop (); last = &list2->references->last (); + + struct ipa_ref *ref = this; + if (ref != last) { *ref = *last; - ipa_ref_referred_ref_list (ref)->referring[ref->referred_index] = ref; + referred_ref_list ()->referring[referred_index] = ref; } list2->references->pop (); gcc_assert (list2->references == old_references); } -/* Remove all references in ref list LIST. */ - -void -ipa_remove_all_references (struct ipa_ref_list *list) -{ - while (vec_safe_length (list->references)) - ipa_remove_reference (&list->references->last ()); - vec_free (list->references); -} - -/* Remove all references in ref list LIST. */ - -void -ipa_remove_all_referring (struct ipa_ref_list *list) -{ - while (list->referring.length ()) - ipa_remove_reference (list->referring.last ()); - list->referring.release (); -} - -/* Dump references in LIST to FILE. */ - -void -ipa_dump_references (FILE * file, struct ipa_ref_list *list) -{ - struct ipa_ref *ref; - int i; - for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++) - { - fprintf (file, "%s/%i (%s)", - ref->referred->asm_name (), - ref->referred->order, - ipa_ref_use_name [ref->use]); - if (ref->speculative) - fprintf (file, " (speculative)"); - } - fprintf (file, "\n"); -} - -/* Dump referring in LIST to FILE. */ - -void -ipa_dump_referring (FILE * file, struct ipa_ref_list *list) -{ - struct ipa_ref *ref; - int i; - for (i = 0; ipa_ref_list_referring_iterate (list, i, ref); i++) - { - fprintf (file, "%s/%i (%s)", - ref->referring->asm_name (), - ref->referring->order, - ipa_ref_use_name [ref->use]); - if (ref->speculative) - fprintf (file, " (speculative)"); - } - fprintf (file, "\n"); -} - -/* Clone reference REF to DEST_NODE and set its stmt to STMT. */ - -struct ipa_ref * -ipa_clone_ref (struct ipa_ref *ref, - symtab_node *dest_node, - gimple stmt) -{ - bool speculative = ref->speculative; - unsigned int stmt_uid = ref->lto_stmt_uid; - struct ipa_ref *ref2; - - ref2 = ipa_record_reference (dest_node, - ref->referred, - ref->use, stmt); - ref2->speculative = speculative; - ref2->lto_stmt_uid = stmt_uid; - return ref2; -} - -/* Clone all references from SRC to DEST_NODE or DEST_VARPOOL_NODE. */ +/* Return true when execution of reference can lead to return from + function. */ -void -ipa_clone_references (symtab_node *dest_node, - struct ipa_ref_list *src) -{ - struct ipa_ref *ref, *ref2; - int i; - for (i = 0; ipa_ref_list_reference_iterate (src, i, ref); i++) - { - bool speculative = ref->speculative; - unsigned int stmt_uid = ref->lto_stmt_uid; - - ref2 = ipa_record_reference (dest_node, - ref->referred, - ref->use, ref->stmt); - ref2->speculative = speculative; - ref2->lto_stmt_uid = stmt_uid; - } -} - -/* Clone all referring from SRC to DEST_NODE or DEST_VARPOOL_NODE. */ - -void -ipa_clone_referring (symtab_node *dest_node, - struct ipa_ref_list *src) -{ - struct ipa_ref *ref, *ref2; - int i; - for (i = 0; ipa_ref_list_referring_iterate (src, i, ref); i++) - { - bool speculative = ref->speculative; - unsigned int stmt_uid = ref->lto_stmt_uid; - - ref2 = ipa_record_reference (ref->referring, - dest_node, - ref->use, ref->stmt); - ref2->speculative = speculative; - ref2->lto_stmt_uid = stmt_uid; - } -} - -/* Return true when execution of REF can lead to return from - function. */ bool -ipa_ref_cannot_lead_to_return (struct ipa_ref *ref) +ipa_ref::cannot_lead_to_return () { - return cgraph_node_cannot_return (ipa_ref_referring_node (ref)); -} - -/* Return true if list contains an alias. */ -bool -ipa_ref_has_aliases_p (struct ipa_ref_list *ref_list) -{ - struct ipa_ref *ref; - int i; - - for (i = 0; ipa_ref_list_referring_iterate (ref_list, i, ref); i++) - if (ref->use == IPA_REF_ALIAS) - return true; - return false; + return cgraph_node_cannot_return (dyn_cast <cgraph_node *> (referring)); } -/* Find the structure describing a reference in REFERRING_NODE to REFERRED_NODE - and associated with statement STMT. */ +/* Return reference list this reference is in. */ -struct ipa_ref * -ipa_find_reference (symtab_node *referring_node, symtab_node *referred_node, - gimple stmt, unsigned int lto_stmt_uid) +struct ipa_ref_list * +ipa_ref::referring_ref_list (void) { - struct ipa_ref *r = NULL; - int i; - - for (i = 0; ipa_ref_list_reference_iterate (&referring_node->ref_list, i, r); i++) - if (r->referred == referred_node - && !r->speculative - && ((stmt && r->stmt == stmt) - || (lto_stmt_uid && r->lto_stmt_uid == lto_stmt_uid) - || (!stmt && !lto_stmt_uid && !r->stmt && !r->lto_stmt_uid))) - return r; - return NULL; + return &referring->ref_list; } -/* Remove all references from REFERRING_NODE that are associated with statement - STMT. */ +/* Return reference list this reference is in. */ -void -ipa_remove_stmt_references (symtab_node *referring_node, gimple stmt) +struct ipa_ref_list * +ipa_ref::referred_ref_list (void) { - struct ipa_ref *r = NULL; - int i = 0; - - while (ipa_ref_list_reference_iterate (&referring_node->ref_list, i, r)) - if (r->stmt == stmt) - ipa_remove_reference (r); - else - i++; -} - -/* Remove all stmt references in non-speculative references. - Those are not maintained during inlining & clonning. - The exception are speculative references that are updated along - with callgraph edges associated with them. */ - -void -ipa_clear_stmts_in_references (symtab_node *referring_node) -{ - struct ipa_ref *r = NULL; - int i; - - for (i = 0; ipa_ref_list_reference_iterate (&referring_node->ref_list, i, r); i++) - if (!r->speculative) - { - r->stmt = NULL; - r->lto_stmt_uid = 0; - } + return &referred->ref_list; } diff --git a/gcc/ipa-ref.h b/gcc/ipa-ref.h index 4ce5f8d2f5a..d2de006b3ca 100644 --- a/gcc/ipa-ref.h +++ b/gcc/ipa-ref.h @@ -35,6 +35,20 @@ enum GTY(()) ipa_ref_use /* Record of reference in callgraph or varpool. */ struct GTY(()) ipa_ref { +public: + /* Remove reference. */ + void remove_reference (); + + /* Return true when execution of reference can lead to return from + function. */ + bool cannot_lead_to_return (); + + /* Return reference list this reference is in. */ + struct ipa_ref_list * referring_ref_list (void); + + /* Return reference list this reference is in. */ + struct ipa_ref_list * referred_ref_list (void); + symtab_node *referring; symtab_node *referred; gimple stmt; @@ -51,29 +65,39 @@ typedef struct ipa_ref *ipa_ref_ptr; /* List of references. This is stored in both callgraph and varpool nodes. */ struct GTY(()) ipa_ref_list { +public: + /* Return first reference in list or NULL if empty. */ + struct ipa_ref *first_reference (void) + { + if (!vec_safe_length (references)) + return NULL; + return &(*references)[0]; + } + + /* Return first referring ref in list or NULL if empty. */ + struct ipa_ref *first_referring (void) + { + if (!referring.length ()) + return NULL; + return referring[0]; + } + + /* Clear reference list. */ + void clear (void) + { + referring.create (0); + references = NULL; + } + + /* Return number of references. */ + unsigned int nreferences (void) + { + return vec_safe_length (references); + } + /* Store actual references in references vector. */ vec<ipa_ref_t, va_gc> *references; /* Referring is vector of pointers to references. It must not live in GGC space or GGC will try to mark middle of references vectors. */ vec<ipa_ref_ptr> GTY((skip)) referring; }; - -struct ipa_ref * ipa_record_reference (symtab_node *, - symtab_node *, - enum ipa_ref_use, gimple); -struct ipa_ref * ipa_maybe_record_reference (symtab_node *, tree, - enum ipa_ref_use, gimple); - -void ipa_remove_reference (struct ipa_ref *); -void ipa_remove_all_references (struct ipa_ref_list *); -void ipa_remove_all_referring (struct ipa_ref_list *); -void ipa_dump_references (FILE *, struct ipa_ref_list *); -void ipa_dump_referring (FILE *, struct ipa_ref_list *); -void ipa_clone_references (symtab_node *, struct ipa_ref_list *); -void ipa_clone_referring (symtab_node *, struct ipa_ref_list *); -struct ipa_ref * ipa_clone_ref (struct ipa_ref *, symtab_node *, gimple); -bool ipa_ref_cannot_lead_to_return (struct ipa_ref *); -bool ipa_ref_has_aliases_p (struct ipa_ref_list *); -struct ipa_ref * ipa_find_reference (symtab_node *, symtab_node *, gimple, unsigned int); -void ipa_remove_stmt_references (symtab_node *, gimple); -void ipa_clear_stmts_in_references (symtab_node *); diff --git a/gcc/ipa-reference.c b/gcc/ipa-reference.c index e815454162b..064fde22aa9 100644 --- a/gcc/ipa-reference.c +++ b/gcc/ipa-reference.c @@ -450,16 +450,16 @@ static void analyze_function (struct cgraph_node *fn) { ipa_reference_local_vars_info_t local; - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; int i; tree var; local = init_function_info (fn); - for (i = 0; ipa_ref_list_reference_iterate (&fn->ref_list, i, ref); i++) + for (i = 0; fn->iterate_reference (i, ref); i++) { if (!is_a <varpool_node *> (ref->referred)) continue; - var = ipa_ref_varpool_node (ref)->decl; + var = ref->referred->decl; if (!is_proper_for_analysis (var)) continue; switch (ref->use) @@ -468,7 +468,7 @@ analyze_function (struct cgraph_node *fn) bitmap_set_bit (local->statics_read, DECL_UID (var)); break; case IPA_REF_STORE: - if (ipa_ref_cannot_lead_to_return (ref)) + if (ref->cannot_lead_to_return ()) break; bitmap_set_bit (local->statics_written, DECL_UID (var)); break; @@ -882,7 +882,7 @@ write_node_summary_p (struct cgraph_node *node, In future we might also want to include summaries of functions references by initializers of constant variables references in current unit. */ if (!reachable_from_this_partition_p (node, encoder) - && !referenced_from_this_partition_p (&node->ref_list, encoder)) + && !referenced_from_this_partition_p (node, encoder)) return false; /* See if the info has non-empty intersections with vars we want to encode. */ @@ -949,7 +949,7 @@ ipa_reference_write_optimization_summary (void) varpool_node *vnode = dyn_cast <varpool_node *> (snode); if (vnode && bitmap_bit_p (all_module_statics, DECL_UID (vnode->decl)) - && referenced_from_this_partition_p (&vnode->ref_list, encoder)) + && referenced_from_this_partition_p (vnode, encoder)) { tree decl = vnode->decl; bitmap_set_bit (ltrans_statics, DECL_UID (decl)); diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c index bfcd43e496e..3ca57b6afe7 100644 --- a/gcc/ipa-split.c +++ b/gcc/ipa-split.c @@ -1251,7 +1251,7 @@ split_function (struct split_point *split_point) a warning for the non-inlinable part. */ DECL_NO_INLINE_WARNING_P (node->decl) = 1; cgraph_node_remove_callees (cur_node); - ipa_remove_all_references (&cur_node->ref_list); + cur_node->remove_all_references (); if (!split_part_return_p) TREE_THIS_VOLATILE (node->decl) = 1; if (dump_file) diff --git a/gcc/ipa-utils.c b/gcc/ipa-utils.c index 8e7c7cb5ebe..c191210ccb7 100644 --- a/gcc/ipa-utils.c +++ b/gcc/ipa-utils.c @@ -289,7 +289,7 @@ ipa_reverse_postorder (struct cgraph_node **order) int order_pos = 0; struct cgraph_edge *edge; int pass; - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; struct postorder_stack *stack = XCNEWVEC (struct postorder_stack, cgraph_n_nodes); @@ -332,13 +332,13 @@ ipa_reverse_postorder (struct cgraph_node **order) (cgraph_function_node (edge->callee, NULL)->decl)) node2 = NULL; } - for (;ipa_ref_list_referring_iterate (&stack[stack_size].node->ref_list, + for (; stack[stack_size].node->iterate_referring ( stack[stack_size].ref, ref) && !node2; stack[stack_size].ref++) { if (ref->use == IPA_REF_ALIAS) - node2 = ipa_ref_referring_node (ref); + node2 = dyn_cast <cgraph_node *> (ref->referring); } if (!node2) break; diff --git a/gcc/ipa-visibility.c b/gcc/ipa-visibility.c index 9e4d8c38f4b..a4848c24783 100644 --- a/gcc/ipa-visibility.c +++ b/gcc/ipa-visibility.c @@ -91,7 +91,7 @@ cgraph_non_local_node_p_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED { /* FIXME: Aliases can be local, but i386 gets thunks wrong then. */ return !(cgraph_only_called_directly_or_aliased_p (node) - && !ipa_ref_has_aliases_p (&node->ref_list) + && !node->has_aliases_p () && node->definition && !DECL_EXTERNAL (node->decl) && !node->externally_visible @@ -120,15 +120,15 @@ bool address_taken_from_non_vtable_p (symtab_node *node) { int i; - struct ipa_ref *ref; - for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, - i, ref); i++) + struct ipa_ref *ref = NULL; + + for (i = 0; node->iterate_referring (i, ref); i++) if (ref->use == IPA_REF_ADDR) { varpool_node *node; if (is_a <cgraph_node *> (ref->referring)) return true; - node = ipa_ref_referring_varpool_node (ref); + node = dyn_cast <varpool_node *> (ref->referring); if (!DECL_VIRTUAL_P (node->decl)) return true; } @@ -682,8 +682,7 @@ function_and_variable_visibility (bool whole_program) bool found = false; /* See if there is something to update. */ - for (i = 0; ipa_ref_list_referring_iterate (&vnode->ref_list, - i, ref); i++) + for (i = 0; vnode->iterate_referring (i, ref); i++) if (ref->use == IPA_REF_ADDR && can_replace_by_local_alias_in_vtable (ref->referred)) { @@ -696,7 +695,7 @@ function_and_variable_visibility (bool whole_program) walk_tree (&DECL_INITIAL (vnode->decl), update_vtable_references, NULL, visited_nodes); pointer_set_destroy (visited_nodes); - ipa_remove_all_references (&vnode->ref_list); + vnode->remove_all_references (); record_references_in_initializer (vnode->decl, false); } } diff --git a/gcc/ipa.c b/gcc/ipa.c index 04f2c79ae33..fce2e36174f 100644 --- a/gcc/ipa.c +++ b/gcc/ipa.c @@ -51,10 +51,9 @@ has_addr_references_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) { int i; - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; - for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, - i, ref); i++) + for (i = 0; node->iterate_referring (i, ref); i++) if (ref->use == IPA_REF_ADDR) return true; return false; @@ -101,14 +100,14 @@ enqueue_node (symtab_node *node, symtab_node **first, /* Process references. */ static void -process_references (struct ipa_ref_list *list, +process_references (symtab_node *snode, symtab_node **first, bool before_inlining_p, struct pointer_set_t *reachable) { int i; - struct ipa_ref *ref; - for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++) + struct ipa_ref *ref = NULL; + for (i = 0; snode->iterate_reference (i, ref); i++) { symtab_node *node = ref->referred; @@ -358,8 +357,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) enqueue_node (next, &first, reachable); } /* Mark references as reachable. */ - process_references (&node->ref_list, &first, - before_inlining_p, reachable); + process_references (node, &first, before_inlining_p, reachable); } if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node)) @@ -446,8 +444,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) && !vnode->alias && in_boundary_p) { - struct ipa_ref *ref; - for (int i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++) + struct ipa_ref *ref = NULL; + for (int i = 0; node->iterate_reference (i, ref); i++) enqueue_node (ref->referred, &first, reachable); } } @@ -493,7 +491,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) node->local.local = false; cgraph_node_remove_callees (node); symtab_remove_from_same_comdat_group (node); - ipa_remove_all_references (&node->ref_list); + node->remove_all_references (); changed = true; } } @@ -555,7 +553,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) varpool_remove_initializer (vnode); else DECL_INITIAL (vnode->decl) = init; - ipa_remove_all_references (&vnode->ref_list); + vnode->remove_all_references (); } else vnode->aux = NULL; @@ -618,8 +616,7 @@ process_references (varpool_node *vnode, || TREE_THIS_VOLATILE (vnode->decl)) *explicit_refs = false; - for (i = 0; ipa_ref_list_referring_iterate (&vnode->ref_list, - i, ref) + for (i = 0; vnode->iterate_referring (i, ref) && *explicit_refs && (!*written || !*address_taken || !*read); i++) switch (ref->use) { @@ -658,7 +655,7 @@ set_writeonly_bit (varpool_node *vnode, void *data ATTRIBUTE_UNUSED) { DECL_INITIAL (vnode->decl) = NULL; if (!vnode->alias) - ipa_remove_all_references (&vnode->ref_list); + vnode->remove_all_references (); } return false; } @@ -1153,7 +1150,7 @@ propagate_single_user (varpool_node *vnode, cgraph_node *function, /* Check all users and see if they correspond to a single function. */ for (i = 0; - ipa_ref_list_referring_iterate (&vnode->ref_list, i, ref) + vnode->iterate_referring (i, ref) && function != BOTTOM; i++) { struct cgraph_node *cnode = dyn_cast <cgraph_node *> (ref->referring); @@ -1221,7 +1218,7 @@ ipa_single_use (void) /* Enqueue all aliases for re-processing. */ for (i = 0; - ipa_ref_list_referring_iterate (&var->ref_list, i, ref); i++) + var->iterate_referring (i, ref); i++) if (ref->use == IPA_REF_ALIAS && !ref->referring->aux) { @@ -1230,7 +1227,7 @@ ipa_single_use (void) } /* Enqueue all users for re-processing. */ for (i = 0; - ipa_ref_list_reference_iterate (&var->ref_list, i, ref); i++) + var->iterate_reference (i, ref); i++) if (!ref->referred->aux && ref->referred->definition && is_a <varpool_node *> (ref->referred)) diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index ffc62473d1c..af480bcaea2 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -315,14 +315,15 @@ lto_output_edge (struct lto_simple_output_block *ob, struct cgraph_edge *edge, } } -/* Return if LIST contain references from other partitions. */ +/* Return if NODE contain references from other partitions. */ bool -referenced_from_other_partition_p (struct ipa_ref_list *list, lto_symtab_encoder_t encoder) +referenced_from_other_partition_p (symtab_node *node, lto_symtab_encoder_t encoder) { int i; - struct ipa_ref *ref; - for (i = 0; ipa_ref_list_referring_iterate (list, i, ref); i++) + struct ipa_ref *ref = NULL; + + for (i = 0; node->iterate_referring (i, ref); i++) { if (ref->referring->in_other_partition || !lto_symtab_encoder_in_partition_p (encoder, ref->referring)) @@ -348,15 +349,16 @@ reachable_from_other_partition_p (struct cgraph_node *node, lto_symtab_encoder_t return false; } -/* Return if LIST contain references from other partitions. */ +/* Return if NODE contain references from other partitions. */ bool -referenced_from_this_partition_p (struct ipa_ref_list *list, +referenced_from_this_partition_p (symtab_node *node, lto_symtab_encoder_t encoder) { int i; - struct ipa_ref *ref; - for (i = 0; ipa_ref_list_referring_iterate (list, i, ref); i++) + struct ipa_ref *ref = NULL; + + for (i = 0; node->iterate_referring (i, ref); i++) if (lto_symtab_encoder_in_partition_p (encoder, ref->referring)) return true; return false; @@ -523,8 +525,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, bp_pack_value (&bp, tag == LTO_symtab_analyzed_node && symtab_get_symbol_partitioning_class (node) == SYMBOL_PARTITION && (reachable_from_other_partition_p (node, encoder) - || referenced_from_other_partition_p (&node->ref_list, - encoder)), 1); + || referenced_from_other_partition_p (node, encoder)), 1); bp_pack_value (&bp, node->lowered, 1); bp_pack_value (&bp, in_other_partition, 1); /* Real aliases in a boundary become non-aliases. However we still stream @@ -607,8 +608,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node, else { bp_pack_value (&bp, node->definition - && referenced_from_other_partition_p (&node->ref_list, - encoder), 1); + && referenced_from_other_partition_p (node, encoder), 1); bp_pack_value (&bp, node->analyzed && boundary_p && !DECL_EXTERNAL (node->decl), 1); /* in_other_partition. */ @@ -760,14 +760,13 @@ output_refs (lto_symtab_encoder_t encoder) { symtab_node *node = lsei_node (lsei); - count = ipa_ref_list_nreferences (&node->ref_list); + count = node->ref_list.nreferences (); if (count) { streamer_write_gcov_count_stream (ob->main_stream, count); streamer_write_uhwi_stream (ob->main_stream, lto_symtab_encoder_lookup (encoder, node)); - for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, - i, ref); i++) + for (i = 0; node->iterate_reference (i, ref); i++) lto_output_ref (ob, ref, encoder); } } @@ -791,17 +790,16 @@ add_node_to (lto_symtab_encoder_t encoder, struct cgraph_node *node, lto_symtab_encoder_encode (encoder, node); } -/* Add all references in LIST to encoders. */ +/* Add all references in NODE to encoders. */ static void -add_references (lto_symtab_encoder_t encoder, - struct ipa_ref_list *list) +add_references (lto_symtab_encoder_t encoder, symtab_node *node) { int i; - struct ipa_ref *ref; - for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++) + struct ipa_ref *ref = NULL; + for (i = 0; node->iterate_reference (i, ref); i++) if (is_a <cgraph_node *> (ref->referred)) - add_node_to (encoder, ipa_ref_node (ref), false); + add_node_to (encoder, dyn_cast <cgraph_node *> (ref->referred), false); else lto_symtab_encoder_encode (encoder, ref->referred); } @@ -834,7 +832,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder) struct cgraph_node *node = lsei_cgraph_node (lsei); add_node_to (encoder, node, true); lto_set_symtab_encoder_in_partition (encoder, node); - add_references (encoder, &node->ref_list); + add_references (encoder, node); /* For proper debug info, we need to ship the origins, too. */ if (DECL_ABSTRACT_ORIGIN (node->decl)) { @@ -850,7 +848,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder) lto_set_symtab_encoder_in_partition (encoder, vnode); lto_set_symtab_encoder_encode_initializer (encoder, vnode); - add_references (encoder, &vnode->ref_list); + add_references (encoder, vnode); /* For proper debug info, we need to ship the origins, too. */ if (DECL_ABSTRACT_ORIGIN (vnode->decl)) { @@ -872,7 +870,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder) && ctor_for_folding (vnode->decl) != error_mark_node) { lto_set_symtab_encoder_encode_initializer (encoder, vnode); - add_references (encoder, &vnode->ref_list); + add_references (encoder, vnode); } } } @@ -1317,7 +1315,7 @@ input_ref (struct lto_input_block *ib, use = (enum ipa_ref_use) bp_unpack_value (&bp, 2); speculative = (enum ipa_ref_use) bp_unpack_value (&bp, 1); node = nodes[streamer_read_hwi (ib)]; - ref = ipa_record_reference (referring_node, node, use, NULL); + ref = referring_node->add_reference (node, use); ref->speculative = speculative; if (is_a <cgraph_node *> (referring_node)) ref->lto_stmt_uid = streamer_read_hwi (ib); diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c index 671532715a5..5d7989353fe 100644 --- a/gcc/lto-streamer-in.c +++ b/gcc/lto-streamer-in.c @@ -785,7 +785,7 @@ fixup_call_stmt_edges_1 (struct cgraph_node *node, gimple *stmts, struct function *fn) { struct cgraph_edge *cedge; - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; unsigned int i; for (cedge = node->callees; cedge; cedge = cedge->next_callee) @@ -804,9 +804,7 @@ fixup_call_stmt_edges_1 (struct cgraph_node *node, gimple *stmts, if (!cedge->call_stmt) fatal_error ("Cgraph edge statement index not found"); } - for (i = 0; - ipa_ref_list_reference_iterate (&node->ref_list, i, ref); - i++) + for (i = 0; node->iterate_reference (i, ref); i++) if (ref->lto_stmt_uid) { if (gimple_stmt_max_uid (fn) < ref->lto_stmt_uid) diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index cb47b0023c9..30645627d02 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -2362,8 +2362,7 @@ output_symbol_p (symtab_node *node) { int i; struct ipa_ref *ref; - for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, - i, ref); i++) + for (i = 0; node->iterate_referring (i, ref); i++) { if (ref->use == IPA_REF_ALIAS) continue; diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h index 566a0e0b359..cfa965c4d1e 100644 --- a/gcc/lto-streamer.h +++ b/gcc/lto-streamer.h @@ -888,7 +888,7 @@ bool referenced_from_other_partition_p (struct ipa_ref_list *, lto_symtab_encoder_t); bool reachable_from_other_partition_p (struct cgraph_node *, lto_symtab_encoder_t); -bool referenced_from_this_partition_p (struct ipa_ref_list *, +bool referenced_from_this_partition_p (struct symtab_node *, lto_symtab_encoder_t); bool reachable_from_this_partition_p (struct cgraph_node *, lto_symtab_encoder_t); diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c index 5a8c843b775..4d19ef6de61 100644 --- a/gcc/lto/lto-partition.c +++ b/gcc/lto/lto-partition.c @@ -86,10 +86,10 @@ static void add_references_to_partition (ltrans_partition part, symtab_node *node) { int i; - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; /* Add all duplicated references to the partition. */ - for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++) + for (i = 0; node->iterate_reference (i, ref); i++) if (symtab_get_symbol_partitioning_class (ref->referred) == SYMBOL_DUPLICATE) add_symbol_to_partition (part, ref->referred); /* References to a readonly variable may be constant foled into its value. @@ -114,7 +114,7 @@ add_symbol_to_partition_1 (ltrans_partition part, symtab_node *node) { enum symbol_partitioning_class c = symtab_get_symbol_partitioning_class (node); int i; - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; symtab_node *node1; /* If NODE is already there, we have nothing to do. */ @@ -168,7 +168,7 @@ add_symbol_to_partition_1 (ltrans_partition part, symtab_node *node) add_references_to_partition (part, node); /* Add all aliases associated with the symbol. */ - for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) + for (i = 0; node->iterate_referring (i, ref); i++) if (ref->use == IPA_REF_ALIAS && !node->weakref) add_symbol_to_partition_1 (part, ref->referring); @@ -516,9 +516,9 @@ lto_balanced_map (int n_lto_partitions) it and thus we need to subtract it from COST. */ while (last_visited_node < lto_symtab_encoder_size (partition->encoder)) { - struct ipa_ref_list *refs; + symtab_node *refs_node; int j; - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; symtab_node *snode = lto_symtab_encoder_deref (partition->encoder, last_visited_node); @@ -526,7 +526,7 @@ lto_balanced_map (int n_lto_partitions) { struct cgraph_edge *edge; - refs = &node->ref_list; + refs_node = node; last_visited_node++; @@ -570,18 +570,18 @@ lto_balanced_map (int n_lto_partitions) } else { - refs = &snode->ref_list; + refs_node = snode; last_visited_node++; } /* Compute boundary cost of IPA REF edges and at the same time look into variables referenced from current partition and try to add them. */ - for (j = 0; ipa_ref_list_reference_iterate (refs, j, ref); j++) + for (j = 0; refs_node->iterate_reference (j, ref); j++) if (is_a <varpool_node *> (ref->referred)) { int index; - vnode = ipa_ref_varpool_node (ref); + vnode = dyn_cast <varpool_node *> (ref->referred); if (!vnode->definition) continue; if (!symbol_partitioned_p (vnode) && flag_toplevel_reorder @@ -599,7 +599,7 @@ lto_balanced_map (int n_lto_partitions) { int index; - node = ipa_ref_node (ref); + node = dyn_cast <cgraph_node *> (ref->referred); if (!node->definition) continue; index = lto_symtab_encoder_lookup (partition->encoder, @@ -610,12 +610,12 @@ lto_balanced_map (int n_lto_partitions) else cost++; } - for (j = 0; ipa_ref_list_referring_iterate (refs, j, ref); j++) + for (j = 0; refs_node->iterate_referring (j, ref); j++) if (is_a <varpool_node *> (ref->referring)) { int index; - vnode = ipa_ref_referring_varpool_node (ref); + vnode = dyn_cast <varpool_node *> (ref->referring); gcc_assert (vnode->definition); /* It is better to couple variables with their users, because it allows them to be removed. Coupling with objects they refer to only helps to reduce @@ -636,7 +636,7 @@ lto_balanced_map (int n_lto_partitions) { int index; - node = ipa_ref_referring_node (ref); + node = dyn_cast <cgraph_node *> (ref->referring); gcc_assert (node->definition); index = lto_symtab_encoder_lookup (partition->encoder, node); diff --git a/gcc/lto/lto-symtab.c b/gcc/lto/lto-symtab.c index c02f987aaea..82ee827f63c 100644 --- a/gcc/lto/lto-symtab.c +++ b/gcc/lto/lto-symtab.c @@ -84,7 +84,7 @@ lto_cgraph_replace_node (struct cgraph_node *node, e->call_stmt_cannot_inline_p = 1; } /* Redirect incomming references. */ - ipa_clone_referring (prevailing_node, &node->ref_list); + prevailing_node->clone_referring (node); ipa_merge_profiles (prevailing_node, node); lto_free_function_in_decl_state_for_node (node); @@ -106,7 +106,7 @@ lto_varpool_replace_node (varpool_node *vnode, gcc_assert (!vnode->definition || prevailing_node->definition); gcc_assert (!vnode->analyzed || prevailing_node->analyzed); - ipa_clone_referring (prevailing_node, &vnode->ref_list); + prevailing_node->clone_referring (vnode); if (vnode->force_output) prevailing_node->force_output = true; if (vnode->forced_by_abi) diff --git a/gcc/symtab.c b/gcc/symtab.c index 6e521154fa8..89591ee3ac7 100644 --- a/gcc/symtab.c +++ b/gcc/symtab.c @@ -42,6 +42,9 @@ along with GCC; see the file COPYING3. If not see #include "timevar.h" #include "lto-streamer.h" #include "output.h" +#include "ipa-utils.h" + +static const char *ipa_ref_use_name[] = {"read","write","addr","alias"}; const char * const ld_plugin_symbol_resolution_names[]= { @@ -284,7 +287,7 @@ symtab_register_node (symtab_node *node) if (!node->decl->decl_with_vis.symtab_node) node->decl->decl_with_vis.symtab_node = node; - ipa_empty_ref_list (&node->ref_list); + node->ref_list.clear (); node->order = symtab_order++; @@ -319,8 +322,8 @@ symtab_remove_from_same_comdat_group (symtab_node *node) void symtab_unregister_node (symtab_node *node) { - ipa_remove_all_references (&node->ref_list); - ipa_remove_all_referring (&node->ref_list); + node->remove_all_references (); + node->remove_all_referring (); /* Remove reference to section. */ node->set_section_for_node (NULL); @@ -522,6 +525,277 @@ symtab_node::name () const return lang_hooks.decl_printable_name (decl, 2); } +/* Return ipa reference from this symtab_node to + REFERED_NODE or REFERED_VARPOOL_NODE. USE_TYPE specify type + of the use. */ + +struct ipa_ref * +symtab_node::add_reference (symtab_node *referred_node, + enum ipa_ref_use use_type) +{ + return add_reference (referred_node, use_type, NULL); +} + + +/* Return ipa reference from this symtab_node to + REFERED_NODE or REFERED_VARPOOL_NODE. USE_TYPE specify type + of the use and STMT the statement (if it exists). */ + +struct ipa_ref * +symtab_node::add_reference (symtab_node *referred_node, + enum ipa_ref_use use_type, gimple stmt) +{ + struct ipa_ref *ref = NULL, *ref2 = NULL; + struct ipa_ref_list *list, *list2; + ipa_ref_t *old_references; + + gcc_checking_assert (!stmt || is_a <cgraph_node *> (this)); + gcc_checking_assert (use_type != IPA_REF_ALIAS || !stmt); + + list = &ref_list; + old_references = vec_safe_address (list->references); + vec_safe_grow (list->references, vec_safe_length (list->references) + 1); + ref = &list->references->last (); + + list2 = &referred_node->ref_list; + list2->referring.safe_push (ref); + ref->referred_index = list2->referring.length () - 1; + ref->referring = this; + ref->referred = referred_node; + ref->stmt = stmt; + ref->lto_stmt_uid = 0; + ref->use = use_type; + ref->speculative = 0; + + /* If vector was moved in memory, update pointers. */ + if (old_references != list->references->address ()) + { + int i; + for (i = 0; iterate_reference(i, ref2); i++) + ref2->referred_ref_list ()->referring[ref2->referred_index] = ref2; + } + return ref; +} + +/* If VAL is a reference to a function or a variable, add a reference from + this symtab_node to the corresponding symbol table node. USE_TYPE specify + type of the use and STMT the statement (if it exists). Return the new + reference or NULL if none was created. */ + +struct ipa_ref * +symtab_node::maybe_add_reference (tree val, enum ipa_ref_use use_type, + gimple stmt) +{ + STRIP_NOPS (val); + if (TREE_CODE (val) != ADDR_EXPR) + return NULL; + val = get_base_var (val); + if (val && (TREE_CODE (val) == FUNCTION_DECL + || TREE_CODE (val) == VAR_DECL)) + { + symtab_node *referred = symtab_get_node (val); + gcc_checking_assert (referred); + return add_reference (referred, use_type, stmt); + } + return NULL; +} + +/* Clone all references from symtab NODE to this symtab_node. */ + +void +symtab_node::clone_references (struct symtab_node *node) +{ + struct ipa_ref *ref = NULL, *ref2 = NULL; + int i; + for (i = 0; node->iterate_reference (i, ref); i++) + { + bool speculative = ref->speculative; + unsigned int stmt_uid = ref->lto_stmt_uid; + + ref2 = add_reference (ref->referred, ref->use, ref->stmt); + ref2->speculative = speculative; + ref2->lto_stmt_uid = stmt_uid; + } +} + +/* Clone all referring from symtab NODE to this symtab_node. */ + +void +symtab_node::clone_referring (struct symtab_node *node) +{ + struct ipa_ref *ref = NULL, *ref2 = NULL; + int i; + for (i = 0; node->iterate_referring(i, ref); i++) + { + bool speculative = ref->speculative; + unsigned int stmt_uid = ref->lto_stmt_uid; + + ref2 = ref->referring->add_reference (this, ref->use, ref->stmt); + ref2->speculative = speculative; + ref2->lto_stmt_uid = stmt_uid; + } +} + +/* Clone reference REF to this symtab_node and set its stmt to STMT. */ + +struct ipa_ref * +symtab_node::clone_reference (struct ipa_ref *ref, gimple stmt) +{ + bool speculative = ref->speculative; + unsigned int stmt_uid = ref->lto_stmt_uid; + struct ipa_ref *ref2; + + ref2 = add_reference (ref->referred, ref->use, stmt); + ref2->speculative = speculative; + ref2->lto_stmt_uid = stmt_uid; + return ref2; +} + +/* Find the structure describing a reference to REFERRED_NODE + and associated with statement STMT. */ + +struct ipa_ref * +symtab_node::find_reference (symtab_node *referred_node, + gimple stmt, unsigned int lto_stmt_uid) +{ + struct ipa_ref *r = NULL; + int i; + + for (i = 0; iterate_reference (i, r); i++) + if (r->referred == referred_node + && !r->speculative + && ((stmt && r->stmt == stmt) + || (lto_stmt_uid && r->lto_stmt_uid == lto_stmt_uid) + || (!stmt && !lto_stmt_uid && !r->stmt && !r->lto_stmt_uid))) + return r; + return NULL; +} + +/* Remove all references that are associated with statement STMT. */ + +void +symtab_node::remove_stmt_references (gimple stmt) +{ + struct ipa_ref *r = NULL; + int i = 0; + + while (iterate_reference (i, r)) + if (r->stmt == stmt) + r->remove_reference (); + else + i++; +} + +/* Remove all stmt references in non-speculative references. + Those are not maintained during inlining & clonning. + The exception are speculative references that are updated along + with callgraph edges associated with them. */ + +void +symtab_node::clear_stmts_in_references (void) +{ + struct ipa_ref *r = NULL; + int i; + + for (i = 0; iterate_reference (i, r); i++) + if (!r->speculative) + { + r->stmt = NULL; + r->lto_stmt_uid = 0; + } +} + +/* Remove all references in ref list. */ + +void +symtab_node::remove_all_references (void) +{ + while (vec_safe_length (ref_list.references)) + ref_list.references->last ().remove_reference (); + vec_free (ref_list.references); +} + +/* Remove all referring items in ref list. */ + +void +symtab_node::remove_all_referring (void) +{ + while (ref_list.referring.length ()) + ref_list.referring.last ()->remove_reference (); + ref_list.referring.release (); +} + +/* Dump references in ref list to FILE. */ + +void +symtab_node::dump_references (FILE *file) +{ + struct ipa_ref *ref = NULL; + int i; + for (i = 0; iterate_reference (i, ref); i++) + { + fprintf (file, "%s/%i (%s)", + ref->referred->asm_name (), + ref->referred->order, + ipa_ref_use_name [ref->use]); + if (ref->speculative) + fprintf (file, " (speculative)"); + } + fprintf (file, "\n"); +} + +/* Dump referring in list to FILE. */ + +void +symtab_node::dump_referring (FILE *file) +{ + struct ipa_ref *ref = NULL; + int i; + for (i = 0; iterate_referring(i, ref); i++) + { + fprintf (file, "%s/%i (%s)", + ref->referring->asm_name (), + ref->referring->order, + ipa_ref_use_name [ref->use]); + if (ref->speculative) + fprintf (file, " (speculative)"); + } + fprintf (file, "\n"); +} + +/* Return true if list contains an alias. */ +bool +symtab_node::has_aliases_p (void) +{ + struct ipa_ref *ref = NULL; + int i; + + for (i = 0; iterate_referring (i, ref); i++) + if (ref->use == IPA_REF_ALIAS) + return true; + return false; +} + +/* Iterates I-th reference in the list, REF is also set. */ + +struct ipa_ref * +symtab_node::iterate_reference (unsigned i, struct ipa_ref *&ref) +{ + vec_safe_iterate (ref_list.references, i, &ref); + + return ref; +} + +/* Iterates I-th referring item in the list, REF is also set. */ + +struct ipa_ref * +symtab_node::iterate_referring (unsigned i, struct ipa_ref *&ref) +{ + ref_list.referring.iterate (i, &ref); + + return ref; +} + static const char * const symtab_type_names[] = {"symbol", "function", "variable"}; /* Dump base fields of symtab nodes. Not to be used directly. */ @@ -634,9 +908,9 @@ dump_symtab_base (FILE *f, symtab_node *node) } fprintf (f, " References: "); - ipa_dump_references (f, &node->ref_list); + node->dump_references (f); fprintf (f, " Referring: "); - ipa_dump_referring (f, &node->ref_list); + node->dump_referring (f); if (node->lto_file_data) fprintf (f, " Read from file: %s\n", node->lto_file_data->file_name); @@ -819,10 +1093,9 @@ verify_symtab_base (symtab_node *node) while (n != node); if (symtab_comdat_local_p (node)) { - struct ipa_ref_list *refs = &node->ref_list; - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; - for (int i = 0; ipa_ref_list_referring_iterate (refs, i, ref); ++i) + for (int i = 0; node->iterate_referring (i, ref); ++i) { if (!symtab_in_same_comdat_p (ref->referring, node)) { @@ -1355,7 +1628,7 @@ symtab_resolve_alias (symtab_node *node, symtab_node *target) node->definition = true; node->alias = true; node->analyzed = true; - ipa_record_reference (node, target, IPA_REF_ALIAS, NULL); + node->add_reference (target, IPA_REF_ALIAS, NULL); /* Add alias into the comdat group of its target unless it is already there. */ if (node->same_comdat_group) @@ -1406,7 +1679,7 @@ symtab_for_node_and_aliases (symtab_node *node, if (callback (node, data)) return true; - for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) + for (i = 0; node->iterate_referring (i, ref); i++) if (ref->use == IPA_REF_ALIAS) { symtab_node *alias = ref->referring; diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c index c4baa437e98..af8bc09e187 100644 --- a/gcc/trans-mem.c +++ b/gcc/trans-mem.c @@ -4860,7 +4860,7 @@ ipa_tm_create_version_alias (struct cgraph_node *node, void *data) record_tm_clone_pair (old_decl, new_decl); if (info->old_node->force_output - || ipa_ref_list_first_referring (&info->old_node->ref_list)) + || info->old_node->ref_list.first_referring ()) ipa_tm_mark_force_output_node (new_node); if (info->old_node->forced_by_abi) ipa_tm_mark_forced_by_abi_node (new_node); @@ -4919,7 +4919,7 @@ ipa_tm_create_version (struct cgraph_node *old_node) cgraph_call_function_insertion_hooks (new_node); if (old_node->force_output - || ipa_ref_list_first_referring (&old_node->ref_list)) + || old_node->ref_list.first_referring ()) ipa_tm_mark_force_output_node (new_node); if (old_node->forced_by_abi) ipa_tm_mark_forced_by_abi_node (new_node); @@ -5439,7 +5439,7 @@ ipa_tm_execute (void) { struct cgraph_node *caller; struct cgraph_edge *e; - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; unsigned j; if (i > 256 && i == irr_worklist.length () / 8) @@ -5466,7 +5466,7 @@ ipa_tm_execute (void) } /* Propagate back to referring aliases as well. */ - for (j = 0; ipa_ref_list_referring_iterate (&node->ref_list, j, ref); j++) + for (j = 0; node->iterate_referring (j, ref); j++) { caller = cgraph (ref->referring); if (ref->use == IPA_REF_ALIAS diff --git a/gcc/tree-emutls.c b/gcc/tree-emutls.c index fe1e85d9014..3a486305c1b 100644 --- a/gcc/tree-emutls.c +++ b/gcc/tree-emutls.c @@ -453,7 +453,7 @@ gen_emutls_addr (tree decl, struct lower_emutls_data *d) /* We may be adding a new reference to a new variable to the function. This means we have to play with the ipa-reference web. */ - ipa_record_reference (d->cfun_node, cvar, IPA_REF_ADDR, x); + d->cfun_node->add_reference (cvar, IPA_REF_ADDR, x); /* Record this ssa_name for possible use later in the basic block. */ access_vars[index] = addr; diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 6b4d3f30ebc..f07c1a85d74 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -1791,7 +1791,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, (old_edge->frequency + indirect->frequency)), CGRAPH_FREQ_MAX); } - ipa_clone_ref (ref, id->dst_node, stmt); + id->dst_node->clone_reference (ref, stmt); } else { @@ -5169,7 +5169,7 @@ delete_unreachable_blocks_update_callgraph (copy_body_data *id) struct cgraph_edge *e; struct cgraph_node *node; - ipa_remove_stmt_references (id->dst_node, gsi_stmt (bsi)); + id->dst_node->remove_stmt_references (gsi_stmt (bsi)); if (gimple_code (gsi_stmt (bsi)) == GIMPLE_CALL &&(e = cgraph_edge (id->dst_node, gsi_stmt (bsi))) != NULL) @@ -5183,7 +5183,7 @@ delete_unreachable_blocks_update_callgraph (copy_body_data *id) && id->dst_node->clones) for (node = id->dst_node->clones; node != id->dst_node;) { - ipa_remove_stmt_references (node, gsi_stmt (bsi)); + node->remove_stmt_references (gsi_stmt (bsi)); if (gimple_code (gsi_stmt (bsi)) == GIMPLE_CALL && (e = cgraph_edge (node, gsi_stmt (bsi))) != NULL) { diff --git a/gcc/varpool.c b/gcc/varpool.c index 580144e0899..04ac8704188 100644 --- a/gcc/varpool.c +++ b/gcc/varpool.c @@ -425,11 +425,12 @@ static void assemble_aliases (varpool_node *node) { int i; - struct ipa_ref *ref; - for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) + struct ipa_ref *ref = NULL; + + for (i = 0; node->iterate_referring (i, ref); i++) if (ref->use == IPA_REF_ALIAS) { - varpool_node *alias = ipa_ref_referring_varpool_node (ref); + varpool_node *alias = dyn_cast <varpool_node *> (ref->referring); do_assemble_alias (alias->decl, DECL_ASSEMBLER_NAME (node->decl)); assemble_aliases (alias); @@ -506,7 +507,7 @@ varpool_remove_unreferenced_decls (void) varpool_node *next, *node; varpool_node *first = (varpool_node *)(void *)1; int i; - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; struct pointer_set_t *referenced = pointer_set_create (); if (seen_error ()) @@ -544,7 +545,7 @@ varpool_remove_unreferenced_decls (void) enqueue_node (vnext, &first); } } - for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++) + for (i = 0; node->iterate_reference (i, ref); i++) { varpool_node *vnode = dyn_cast <varpool_node *> (ref->referred); if (vnode @@ -694,14 +695,14 @@ varpool_for_node_and_aliases (varpool_node *node, bool include_overwritable) { int i; - struct ipa_ref *ref; + struct ipa_ref *ref = NULL; if (callback (node, data)) return true; - for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) + for (i = 0; node->iterate_referring (i, ref); i++) if (ref->use == IPA_REF_ALIAS) { - varpool_node *alias = ipa_ref_referring_varpool_node (ref); + varpool_node *alias = dyn_cast <varpool_node *> (ref->referring); if (include_overwritable || cgraph_variable_initializer_availability (alias) > AVAIL_OVERWRITABLE) if (varpool_for_node_and_aliases (alias, callback, data, |