X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=gcc%2Fipa-reference.c;h=78737aa9e3f3b8ace8e78f09814fc2982bb7e2fe;hb=ac71c66c0f8f737601d34ee7eb813cdfacf83455;hp=56ace1200fafc507ae5b2f4531cc10f96bd67265;hpb=6698dfce642230013b3ee58123ad1b403baa6780;p=thirdparty%2Fgcc.git diff --git a/gcc/ipa-reference.c b/gcc/ipa-reference.c index 56ace1200faf..78737aa9e3f3 100644 --- a/gcc/ipa-reference.c +++ b/gcc/ipa-reference.c @@ -1,5 +1,5 @@ /* Callgraph based analysis of static variables. - Copyright (C) 2004-2014 Free Software Foundation, Inc. + Copyright (C) 2004-2019 Free Software Foundation, Inc. Contributed by Kenneth Zadeck This file is part of GCC. @@ -39,30 +39,17 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" -#include "tm.h" +#include "backend.h" #include "tree.h" -#include "calls.h" -#include "basic-block.h" -#include "tree-ssa-alias.h" -#include "internal-fn.h" -#include "gimple-expr.h" -#include "is-a.h" #include "gimple.h" -#include "tree-inline.h" #include "tree-pass.h" +#include "cgraph.h" +#include "data-streamer.h" +#include "calls.h" #include "splay-tree.h" #include "ipa-utils.h" #include "ipa-reference.h" -#include "flags.h" -#include "diagnostic.h" -#include "data-streamer.h" -#include "lto-streamer.h" - -static void remove_node_data (struct cgraph_node *node, - void *data ATTRIBUTE_UNUSED); -static void duplicate_node_data (struct cgraph_node *src, - struct cgraph_node *dst, - void *data ATTRIBUTE_UNUSED); +#include "symbol-summary.h" /* The static variables defined within the compilation unit that are loaded or stored directly by function that owns this structure. */ @@ -92,9 +79,10 @@ struct ipa_reference_optimization_summary_d bitmap statics_not_written; }; -typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t; -typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t; -typedef struct ipa_reference_optimization_summary_d *ipa_reference_optimization_summary_t; +typedef ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t; +typedef ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t; +typedef ipa_reference_optimization_summary_d * + ipa_reference_optimization_summary_t; struct ipa_reference_vars_info_d { @@ -112,6 +100,9 @@ static splay_tree reference_vars_to_consider; static we are considering. This is added to the local info when asm code is found that clobbers all memory. */ static bitmap all_module_statics; +/* Set of all statics that should be ignored because they are touched by + -fno-ipa-reference code. */ +static bitmap ignore_module_statics; /* Obstack holding bitmaps of local analysis (live from analysis to propagation) */ @@ -119,146 +110,158 @@ static bitmap_obstack local_info_obstack; /* Obstack holding global analysis live forever. */ static bitmap_obstack optimization_summary_obstack; -/* Holders of ipa cgraph hooks: */ -static struct cgraph_2node_hook_list *node_duplication_hook_holder; -static struct cgraph_node_hook_list *node_removal_hook_holder; +class ipa_ref_var_info_summary_t: public fast_function_summary + +{ +public: + ipa_ref_var_info_summary_t (symbol_table *symtab): + fast_function_summary (symtab) {} +}; + +static ipa_ref_var_info_summary_t *ipa_ref_var_info_summaries = NULL; -/* Vector where the reference var infos are actually stored. - Indexed by UID of call graph nodes. */ -static vec ipa_reference_vars_vector; +class ipa_ref_opt_summary_t: public fast_function_summary + +{ +public: + ipa_ref_opt_summary_t (symbol_table *symtab): + fast_function_summary (symtab) {} + + virtual void remove (cgraph_node *src_node, + ipa_reference_optimization_summary_d *data); + virtual void duplicate (cgraph_node *src_node, cgraph_node *dst_node, + ipa_reference_optimization_summary_d *src_data, + ipa_reference_optimization_summary_d *dst_data); +}; -static vec ipa_reference_opt_sum_vector; +static ipa_ref_opt_summary_t *ipa_ref_opt_sum_summaries = NULL; /* Return the ipa_reference_vars structure starting from the cgraph NODE. */ static inline ipa_reference_vars_info_t get_reference_vars_info (struct cgraph_node *node) { - if (!ipa_reference_vars_vector.exists () - || ipa_reference_vars_vector.length () <= (unsigned int) node->uid) + if (ipa_ref_var_info_summaries == NULL) return NULL; - return ipa_reference_vars_vector[node->uid]; + + ipa_reference_vars_info_t v = ipa_ref_var_info_summaries->get (node); + return v == NULL ? NULL : v; } /* Return the ipa_reference_vars structure starting from the cgraph NODE. */ static inline ipa_reference_optimization_summary_t get_reference_optimization_summary (struct cgraph_node *node) { - if (!ipa_reference_opt_sum_vector.exists () - || (ipa_reference_opt_sum_vector.length () <= (unsigned int) node->uid)) + if (ipa_ref_opt_sum_summaries == NULL) return NULL; - return ipa_reference_opt_sum_vector[node->uid]; -} -/* Return the ipa_reference_vars structure starting from the cgraph NODE. */ -static inline void -set_reference_vars_info (struct cgraph_node *node, - ipa_reference_vars_info_t info) -{ - if (!ipa_reference_vars_vector.exists () - || ipa_reference_vars_vector.length () <= (unsigned int) node->uid) - ipa_reference_vars_vector.safe_grow_cleared (node->uid + 1); - ipa_reference_vars_vector[node->uid] = info; -} + ipa_reference_optimization_summary_t v + = ipa_ref_opt_sum_summaries->get (node); -/* Return the ipa_reference_vars structure starting from the cgraph NODE. */ -static inline void -set_reference_optimization_summary (struct cgraph_node *node, - ipa_reference_optimization_summary_t info) -{ - if (!ipa_reference_opt_sum_vector.exists () - || (ipa_reference_opt_sum_vector.length () <= (unsigned int) node->uid)) - ipa_reference_opt_sum_vector.safe_grow_cleared (node->uid + 1); - ipa_reference_opt_sum_vector[node->uid] = info; + return v == NULL ? NULL : v; } -/* Return a bitmap indexed by DECL_UID for the static variables that - are *not* read during the execution of the function FN. Returns +/* Return a bitmap indexed by ipa_reference_var_uid for the static variables + that are *not* read during the execution of the function FN. Returns NULL if no data is available. */ bitmap ipa_reference_get_not_read_global (struct cgraph_node *fn) { + if (!opt_for_fn (current_function_decl, flag_ipa_reference)) + return NULL; + + enum availability avail; + struct cgraph_node *fn2 = fn->function_symbol (&avail); ipa_reference_optimization_summary_t info = - get_reference_optimization_summary (cgraph_function_node (fn, NULL)); - if (info) + get_reference_optimization_summary (fn2); + + if (info + && (avail >= AVAIL_AVAILABLE + || (avail == AVAIL_INTERPOSABLE + && flags_from_decl_or_type (fn->decl) & ECF_LEAF)) + && opt_for_fn (fn2->decl, flag_ipa_reference)) return info->statics_not_read; - else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF) + else if (avail == AVAIL_NOT_AVAILABLE + && flags_from_decl_or_type (fn->decl) & ECF_LEAF) return all_module_statics; else return NULL; } -/* Return a bitmap indexed by DECL_UID for the static variables that - are *not* written during the execution of the function FN. Note +/* Return a bitmap indexed by ipa_reference_var_uid for the static variables + that are *not* written during the execution of the function FN. Note that variables written may or may not be read during the function call. Returns NULL if no data is available. */ bitmap ipa_reference_get_not_written_global (struct cgraph_node *fn) { + if (!opt_for_fn (current_function_decl, flag_ipa_reference)) + return NULL; + + enum availability avail; + struct cgraph_node *fn2 = fn->function_symbol (&avail); ipa_reference_optimization_summary_t info = - get_reference_optimization_summary (fn); - if (info) + get_reference_optimization_summary (fn2); + + if (info + && (avail >= AVAIL_AVAILABLE + || (avail == AVAIL_INTERPOSABLE + && flags_from_decl_or_type (fn->decl) & ECF_LEAF)) + && opt_for_fn (fn2->decl, flag_ipa_reference)) return info->statics_not_written; - else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF) + else if (avail == AVAIL_NOT_AVAILABLE + && flags_from_decl_or_type (fn->decl) & ECF_LEAF) return all_module_statics; else return NULL; } - -/* Add VAR to all_module_statics and the two - reference_vars_to_consider* sets. */ - -static inline void -add_static_var (tree var) -{ - int uid = DECL_UID (var); - gcc_assert (TREE_CODE (var) == VAR_DECL); - if (dump_file) - splay_tree_insert (reference_vars_to_consider, - uid, (splay_tree_value)var); - bitmap_set_bit (all_module_statics, uid); -} - -/* Return true if the variable T is the right kind of static variable to - perform compilation unit scope escape analysis. */ - -static inline bool -is_proper_for_analysis (tree t) +/* Hepler for is_proper_for_analysis. */ +static bool +is_improper (symtab_node *n, void *v ATTRIBUTE_UNUSED) { + tree t = n->decl; /* If the variable has the "used" attribute, treat it as if it had a been touched by the devil. */ if (DECL_PRESERVE_P (t)) - return false; + return true; /* Do not want to do anything with volatile except mark any function that uses one to be not const or pure. */ if (TREE_THIS_VOLATILE (t)) - return false; + return true; /* We do not need to analyze readonly vars, we already know they do not alias. */ if (TREE_READONLY (t)) - return false; + return true; - /* We can not track variables with address taken. */ + /* We cannot track variables with address taken. */ if (TREE_ADDRESSABLE (t)) - return false; + return true; - /* TODO: We could track public variables that are not addressable, but currently - frontends don't give us those. */ + /* TODO: We could track public variables that are not addressable, but + currently frontends don't give us those. */ if (TREE_PUBLIC (t)) - return false; + return true; - /* TODO: Check aliases. */ + return false; +} - /* This is a variable we care about. Check if we have seen it - before, and if not add it the set of variables we care about. */ - if (all_module_statics - && !bitmap_bit_p (all_module_statics, DECL_UID (t))) - add_static_var (t); +/* Return true if the variable T is the right kind of static variable to + perform compilation unit scope escape analysis. */ + +static inline bool +is_proper_for_analysis (tree t) +{ + if (bitmap_bit_p (ignore_module_statics, ipa_reference_var_uid (t))) + return false; + + if (symtab_node::get (t) + ->call_for_symbol_and_aliases (is_improper, NULL, true)) + return false; return true; } @@ -355,14 +358,15 @@ propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x e = e->next_callee) { enum availability avail; - struct cgraph_node *y = cgraph_function_node (e->callee, &avail); + struct cgraph_node *y = e->callee->function_symbol (&avail); if (!y) continue; /* Only look into nodes we can propagate something. */ int flags = flags_from_decl_or_type (y->decl); - if (avail > AVAIL_OVERWRITABLE - || (avail == AVAIL_OVERWRITABLE && (flags & ECF_LEAF))) + if (opt_for_fn (y->decl, flag_ipa_reference) + && (avail > AVAIL_INTERPOSABLE + || (avail == AVAIL_INTERPOSABLE && (flags & ECF_LEAF)))) { if (get_reference_vars_info (y)) { @@ -387,7 +391,7 @@ propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x seems so to local analysis. If we cannot return from the function, we can safely ignore the call. */ if ((flags & ECF_PURE) - || cgraph_edge_cannot_lead_to_return (e)) + || e->cannot_lead_to_return_p ()) continue; union_static_var_sets (x_global->statics_written, @@ -399,17 +403,17 @@ propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x } } +static bool ipa_init_p = false; + /* The init routine for analyzing global static variable usage. See comments at top for description. */ static void ipa_init (void) { - static bool init_p = false; - - if (init_p) + if (ipa_init_p) return; - init_p = true; + ipa_init_p = true; if (dump_file) reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0); @@ -417,11 +421,16 @@ ipa_init (void) bitmap_obstack_initialize (&local_info_obstack); bitmap_obstack_initialize (&optimization_summary_obstack); all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack); + ignore_module_statics = BITMAP_ALLOC (&optimization_summary_obstack); + + if (ipa_ref_var_info_summaries == NULL) + ipa_ref_var_info_summaries = new ipa_ref_var_info_summary_t (symtab); - node_removal_hook_holder = - cgraph_add_node_removal_hook (&remove_node_data, NULL); - node_duplication_hook_holder = - cgraph_add_node_duplication_hook (&duplicate_node_data, NULL); + if (ipa_ref_opt_sum_summaries != NULL) + { + delete ipa_ref_opt_sum_summaries; + ipa_ref_opt_sum_summaries = NULL; + } } @@ -431,10 +440,7 @@ static ipa_reference_local_vars_info_t init_function_info (struct cgraph_node *fn) { ipa_reference_vars_info_t info - = XCNEW (struct ipa_reference_vars_info_d); - - /* Add the info to the tree's annotation. */ - set_reference_vars_info (fn, info); + = ipa_ref_var_info_summaries->get_create (fn); info->local.statics_read = BITMAP_ALLOC (&local_info_obstack); info->local.statics_written = BITMAP_ALLOC (&local_info_obstack); @@ -454,6 +460,8 @@ analyze_function (struct cgraph_node *fn) int i; tree var; + if (!opt_for_fn (fn->decl, flag_ipa_reference)) + return; local = init_function_info (fn); for (i = 0; fn->iterate_reference (i, ref); i++) { @@ -462,15 +470,25 @@ analyze_function (struct cgraph_node *fn) var = ref->referred->decl; if (!is_proper_for_analysis (var)) continue; + /* This is a variable we care about. Check if we have seen it + before, and if not add it the set of variables we care about. */ + if (all_module_statics + && bitmap_set_bit (all_module_statics, ipa_reference_var_uid (var))) + { + if (dump_file) + splay_tree_insert (reference_vars_to_consider, + ipa_reference_var_uid (var), + (splay_tree_value)var); + } switch (ref->use) { case IPA_REF_LOAD: - bitmap_set_bit (local->statics_read, DECL_UID (var)); + bitmap_set_bit (local->statics_read, ipa_reference_var_uid (var)); break; case IPA_REF_STORE: if (ref->cannot_lead_to_return ()) break; - bitmap_set_bit (local->statics_written, DECL_UID (var)); + bitmap_set_bit (local->statics_written, ipa_reference_var_uid (var)); break; case IPA_REF_ADDR: break; @@ -479,25 +497,19 @@ analyze_function (struct cgraph_node *fn) } } - if (cgraph_node_cannot_return (fn)) + if (fn->cannot_return_p ()) bitmap_clear (local->statics_written); } /* Called when new clone is inserted to callgraph late. */ -static void -duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst, - void *data ATTRIBUTE_UNUSED) +void +ipa_ref_opt_summary_t::duplicate (cgraph_node *, cgraph_node *, + ipa_reference_optimization_summary_d *ginfo, + ipa_reference_optimization_summary_d + *dst_ginfo) { - ipa_reference_optimization_summary_t ginfo; - ipa_reference_optimization_summary_t dst_ginfo; - - ginfo = get_reference_optimization_summary (src); - if (!ginfo) - return; - dst_ginfo = XCNEW (struct ipa_reference_optimization_summary_d); - set_reference_optimization_summary (dst, dst_ginfo); dst_ginfo->statics_not_read = copy_static_var_set (ginfo->statics_not_read); dst_ginfo->statics_not_written = @@ -506,23 +518,17 @@ duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst, /* Called when node is removed. */ -static void -remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) +void +ipa_ref_opt_summary_t::remove (cgraph_node *, + ipa_reference_optimization_summary_d *ginfo) { - ipa_reference_optimization_summary_t ginfo; - ginfo = get_reference_optimization_summary (node); - if (ginfo) - { - if (ginfo->statics_not_read - && ginfo->statics_not_read != all_module_statics) - BITMAP_FREE (ginfo->statics_not_read); - - if (ginfo->statics_not_written - && ginfo->statics_not_written != all_module_statics) - BITMAP_FREE (ginfo->statics_not_written); - free (ginfo); - set_reference_optimization_summary (node, NULL); - } + if (ginfo->statics_not_read + && ginfo->statics_not_read != all_module_statics) + BITMAP_FREE (ginfo->statics_not_read); + + if (ginfo->statics_not_written + && ginfo->statics_not_written != all_module_statics) + BITMAP_FREE (ginfo->statics_not_written); } /* Analyze each function in the cgraph to see which global or statics @@ -538,6 +544,22 @@ generate_summary (void) ipa_init (); /* Process all of the functions next. */ + FOR_EACH_DEFINED_FUNCTION (node) + if (!node->alias && !opt_for_fn (node->decl, flag_ipa_reference)) + { + struct ipa_ref *ref = NULL; + int i; + tree var; + for (i = 0; node->iterate_reference (i, ref); i++) + { + if (!is_a (ref->referred)) + continue; + var = ref->referred->decl; + if (!is_proper_for_analysis (var)) + continue; + bitmap_set_bit (ignore_module_statics, ipa_reference_var_uid (var)); + } + } FOR_EACH_DEFINED_FUNCTION (node) analyze_function (node); @@ -550,7 +572,8 @@ generate_summary (void) if (dump_file) FOR_EACH_DEFINED_FUNCTION (node) - if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) + if (node->get_availability () >= AVAIL_INTERPOSABLE + && opt_for_fn (node->decl, flag_ipa_reference)) { ipa_reference_local_vars_info_t l; unsigned int index; @@ -558,8 +581,7 @@ generate_summary (void) l = &get_reference_vars_info (node)->local; fprintf (dump_file, - "\nFunction name:%s/%i:", - node->asm_name (), node->order); + "\nFunction name:%s:", node->dump_name ()); fprintf (dump_file, "\n locals read: "); if (l->statics_read) EXECUTE_IF_SET_IN_BITMAP (l->statics_read, @@ -587,17 +609,15 @@ read_write_all_from_decl (struct cgraph_node *node, tree decl = node->decl; int flags = flags_from_decl_or_type (decl); if ((flags & ECF_LEAF) - && cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE) + && node->get_availability () < AVAIL_INTERPOSABLE) ; else if (flags & ECF_CONST) ; - else if ((flags & ECF_PURE) - || cgraph_node_cannot_return (node)) + else if ((flags & ECF_PURE) || node->cannot_return_p ()) { read_all = true; if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, " %s/%i -> read all\n", - node->asm_name (), node->order); + fprintf (dump_file, " %s -> read all\n", node->dump_name ()); } else { @@ -606,8 +626,8 @@ read_write_all_from_decl (struct cgraph_node *node, read_all = true; write_all = true; if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, " %s/%i -> read all, write all\n", - node->asm_name (), node->order); + fprintf (dump_file, " %s -> read all, write all\n", + node->dump_name ()); } } @@ -620,8 +640,9 @@ get_read_write_all_from_node (struct cgraph_node *node, { struct cgraph_edge *e, *ie; - /* When function is overwritable, we can not assume anything. */ - if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE) + /* When function is overwritable, we cannot assume anything. */ + if (node->get_availability () <= AVAIL_INTERPOSABLE + || (node->analyzed && !opt_for_fn (node->decl, flag_ipa_reference))) read_write_all_from_decl (node, read_all, write_all); for (e = node->callees; @@ -629,9 +650,11 @@ get_read_write_all_from_node (struct cgraph_node *node, e = e->next_callee) { enum availability avail; - struct cgraph_node *callee = cgraph_function_node (e->callee, &avail); + struct cgraph_node *callee = e->callee->function_symbol (&avail); gcc_checking_assert (callee); - if (avail <= AVAIL_OVERWRITABLE) + if (avail <= AVAIL_INTERPOSABLE + || (callee->analyzed && !opt_for_fn (callee->decl, + flag_ipa_reference))) read_write_all_from_decl (callee, read_all, write_all); } @@ -643,7 +666,7 @@ get_read_write_all_from_node (struct cgraph_node *node, read_all = true; if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, " indirect call -> read all\n"); - if (!cgraph_edge_cannot_lead_to_return (ie) + if (!ie->cannot_lead_to_return_p () && !(ie->indirect_info->ecf_flags & ECF_PURE)) { if (dump_file && (dump_flags & TDF_DETAILS)) @@ -653,6 +676,25 @@ get_read_write_all_from_node (struct cgraph_node *node, } } +/* Skip edges from and to nodes without ipa_reference enabled. + Ignore not available symbols. This leave + them out of strongly connected components and makes them easy to skip in the + propagation loop bellow. */ + +static bool +ignore_edge_p (cgraph_edge *e) +{ + enum availability avail; + cgraph_node *ultimate_target + = e->callee->function_or_virtual_thunk_symbol (&avail, e->caller); + + return (avail < AVAIL_INTERPOSABLE + || (avail == AVAIL_INTERPOSABLE + && !(flags_from_decl_or_type (e->callee->decl) & ECF_LEAF)) + || !opt_for_fn (e->caller->decl, flag_ipa_reference) + || !opt_for_fn (ultimate_target->decl, flag_ipa_reference)); +} + /* Produce the global information by preforming a transitive closure on the local information that was produced by ipa_analyze_function. */ @@ -661,21 +703,22 @@ propagate (void) { struct cgraph_node *node; struct cgraph_node **order = - XCNEWVEC (struct cgraph_node *, cgraph_n_nodes); + XCNEWVEC (struct cgraph_node *, symtab->cgraph_count); int order_pos; int i; + bool remove_p; if (dump_file) - dump_cgraph (dump_file); + cgraph_node::dump_cgraph (dump_file); - ipa_discover_readonly_nonaddressable_vars (); + remove_p = ipa_discover_variable_flags (); generate_summary (); /* Propagate the local information through the call graph to produce the global information. All the nodes within a cycle will have the same info so we collapse cycles first. Then we can do the propagation in one pass from the leaves to the roots. */ - order_pos = ipa_reduced_postorder (order, true, true, NULL); + order_pos = ipa_reduced_postorder (order, true, ignore_edge_p); if (dump_file) ipa_print_order (dump_file, "reduced", order, order_pos); @@ -690,7 +733,7 @@ propagate (void) bool write_all = false; node = order[i]; - if (node->alias) + if (node->alias || !opt_for_fn (node->decl, flag_ipa_reference)) continue; node_info = get_reference_vars_info (node); @@ -699,17 +742,15 @@ propagate (void) node_g = &node_info->global; if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "Starting cycle with %s/%i\n", - node->asm_name (), node->order); + fprintf (dump_file, "Starting cycle with %s\n", node->dump_name ()); - vec cycle_nodes = ipa_get_nodes_in_cycle (node); + vec cycle_nodes = ipa_get_nodes_in_cycle (node); /* If any node in a cycle is read_all or write_all, they all are. */ FOR_EACH_VEC_ELT (cycle_nodes, x, w) { if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, " Visiting %s/%i\n", - w->asm_name (), w->order); + fprintf (dump_file, " Visiting %s\n", w->dump_asm_name ()); get_read_write_all_from_node (w, read_all, write_all); if (read_all && write_all) break; @@ -742,7 +783,7 @@ propagate (void) read_all = union_static_var_sets (node_g->statics_read, w_l->statics_read); if (!(flags & ECF_PURE) - && !cgraph_node_cannot_return (w)) + && !w->cannot_return_p ()) write_all = union_static_var_sets (node_g->statics_written, w_l->statics_written); } @@ -768,24 +809,21 @@ propagate (void) struct cgraph_node *w; node = order[i]; - if (node->alias) + if (node->alias || !opt_for_fn (node->decl, flag_ipa_reference)) continue; - fprintf (dump_file, - "\nFunction name:%s/%i:", - node->asm_name (), node->order); + fprintf (dump_file, "\nFunction name:%s:", node->dump_asm_name ()); ipa_reference_vars_info_t node_info = get_reference_vars_info (node); ipa_reference_global_vars_info_t node_g = &node_info->global; - vec cycle_nodes = ipa_get_nodes_in_cycle (node); + vec cycle_nodes = ipa_get_nodes_in_cycle (node); FOR_EACH_VEC_ELT (cycle_nodes, x, w) { ipa_reference_vars_info_t w_ri = get_reference_vars_info (w); ipa_reference_local_vars_info_t w_l = &w_ri->local; if (w != node) - fprintf (dump_file, "\n next cycle: %s/%i ", - w->asm_name (), w->order); + fprintf (dump_file, "\n next cycle: %s ", w->dump_asm_name ()); fprintf (dump_file, "\n locals read: "); dump_static_vars_set_to_file (dump_file, w_l->statics_read); fprintf (dump_file, "\n locals written: "); @@ -801,22 +839,24 @@ propagate (void) } } + if (ipa_ref_opt_sum_summaries == NULL) + ipa_ref_opt_sum_summaries = new ipa_ref_opt_summary_t (symtab); + /* Cleanup. */ FOR_EACH_DEFINED_FUNCTION (node) { ipa_reference_vars_info_t node_info; ipa_reference_global_vars_info_t node_g; - ipa_reference_optimization_summary_t opt; node_info = get_reference_vars_info (node); - if (!node->alias - && (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE + if (!node->alias && opt_for_fn (node->decl, flag_ipa_reference) + && (node->get_availability () > AVAIL_INTERPOSABLE || (flags_from_decl_or_type (node->decl) & ECF_LEAF))) { node_g = &node_info->global; - opt = XCNEW (struct ipa_reference_optimization_summary_d); - set_reference_optimization_summary (node, opt); + ipa_reference_optimization_summary_d *opt + = ipa_ref_opt_sum_summaries->get_create (node); /* Create the complimentary sets. */ @@ -844,18 +884,24 @@ propagate (void) node_g->statics_written); } } - free (node_info); } ipa_free_postorder_info (); free (order); bitmap_obstack_release (&local_info_obstack); - ipa_reference_vars_vector.release (); + + if (ipa_ref_var_info_summaries == NULL) + { + delete ipa_ref_var_info_summaries; + ipa_ref_var_info_summaries = NULL; + } + + ipa_ref_var_info_summaries = NULL; if (dump_file) splay_tree_delete (reference_vars_to_consider); reference_vars_to_consider = NULL; - return 0; + return remove_p ? TODO_remove_functions : 0; } /* Return true if we need to write summary of NODE. */ @@ -871,8 +917,9 @@ write_node_summary_p (struct cgraph_node *node, if (!node->definition || node->global.inlined_to) return false; info = get_reference_optimization_summary (node); - if (!info || (bitmap_empty_p (info->statics_not_read) - && bitmap_empty_p (info->statics_not_written))) + if (!info + || (bitmap_empty_p (info->statics_not_read) + && bitmap_empty_p (info->statics_not_written))) return false; /* See if we want to encode it. @@ -922,7 +969,8 @@ stream_out_bitmap (struct lto_simple_output_block *ob, return; EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi) { - tree decl = (tree)splay_tree_lookup (reference_vars_to_consider, index)->value; + tree decl = (tree)splay_tree_lookup (reference_vars_to_consider, + index)->value; lto_output_var_decl_index (ob->decl_state, ob->main_stream, decl); } } @@ -937,7 +985,7 @@ ipa_reference_write_optimization_summary (void) unsigned int count = 0; int ltrans_statics_bitcount = 0; lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder; - bitmap ltrans_statics = BITMAP_ALLOC (NULL); + auto_bitmap ltrans_statics; int i; reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0); @@ -948,13 +996,15 @@ ipa_reference_write_optimization_summary (void) symtab_node *snode = lto_symtab_encoder_deref (encoder, i); varpool_node *vnode = dyn_cast (snode); if (vnode - && bitmap_bit_p (all_module_statics, DECL_UID (vnode->decl)) + && bitmap_bit_p (all_module_statics, + ipa_reference_var_uid (vnode->decl)) && referenced_from_this_partition_p (vnode, encoder)) { tree decl = vnode->decl; - bitmap_set_bit (ltrans_statics, DECL_UID (decl)); + bitmap_set_bit (ltrans_statics, ipa_reference_var_uid (decl)); splay_tree_insert (reference_vars_to_consider, - DECL_UID (decl), (splay_tree_value)decl); + ipa_reference_var_uid (decl), + (splay_tree_value)decl); ltrans_statics_bitcount ++; } } @@ -995,7 +1045,6 @@ ipa_reference_write_optimization_summary (void) ltrans_statics_bitcount); } } - BITMAP_FREE (ltrans_statics); lto_destroy_simple_output_block (ob); splay_tree_delete (reference_vars_to_consider); } @@ -1011,17 +1060,16 @@ ipa_reference_read_optimization_summary (void) unsigned int j = 0; bitmap_obstack_initialize (&optimization_summary_obstack); - node_removal_hook_holder = - cgraph_add_node_removal_hook (&remove_node_data, NULL); - node_duplication_hook_holder = - cgraph_add_node_duplication_hook (&duplicate_node_data, NULL); + if (ipa_ref_opt_sum_summaries == NULL) + ipa_ref_opt_sum_summaries = new ipa_ref_opt_summary_t (symtab); + all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack); while ((file_data = file_data_vec[j++])) { const char *data; size_t len; - struct lto_input_block *ib + class lto_input_block *ib = lto_create_simple_input_block (file_data, LTO_section_ipa_reference, &data, &len); @@ -1040,7 +1088,8 @@ ipa_reference_read_optimization_summary (void) unsigned int var_index = streamer_read_uhwi (ib); tree v_decl = lto_file_decl_data_get_var_decl (file_data, var_index); - bitmap_set_bit (all_module_statics, DECL_UID (v_decl)); + bitmap_set_bit (all_module_statics, + ipa_reference_var_uid (v_decl)); if (dump_file) fprintf (dump_file, " %s", fndecl_name (v_decl)); } @@ -1049,21 +1098,25 @@ ipa_reference_read_optimization_summary (void) { unsigned int j, index; struct cgraph_node *node; - ipa_reference_optimization_summary_t info; int v_count; lto_symtab_encoder_t encoder; index = streamer_read_uhwi (ib); encoder = file_data->symtab_node_encoder; - node = cgraph (lto_symtab_encoder_deref (encoder, index)); - info = XCNEW (struct ipa_reference_optimization_summary_d); - set_reference_optimization_summary (node, info); - info->statics_not_read = BITMAP_ALLOC (&optimization_summary_obstack); - info->statics_not_written = BITMAP_ALLOC (&optimization_summary_obstack); + node = dyn_cast (lto_symtab_encoder_deref + (encoder, index)); + + ipa_reference_optimization_summary_d *info + = ipa_ref_opt_sum_summaries->get_create (node); + + info->statics_not_read = BITMAP_ALLOC + (&optimization_summary_obstack); + info->statics_not_written = BITMAP_ALLOC + (&optimization_summary_obstack); if (dump_file) fprintf (dump_file, - "\nFunction name:%s/%i:\n static not read:", - node->asm_name (), node->order); + "\nFunction name:%s:\n static not read:", + node->dump_asm_name ()); /* Set the statics not read. */ v_count = streamer_read_hwi (ib); @@ -1079,7 +1132,8 @@ ipa_reference_read_optimization_summary (void) unsigned int var_index = streamer_read_uhwi (ib); tree v_decl = lto_file_decl_data_get_var_decl (file_data, var_index); - bitmap_set_bit (info->statics_not_read, DECL_UID (v_decl)); + bitmap_set_bit (info->statics_not_read, + ipa_reference_var_uid (v_decl)); if (dump_file) fprintf (dump_file, " %s", fndecl_name (v_decl)); } @@ -1101,7 +1155,8 @@ ipa_reference_read_optimization_summary (void) unsigned int var_index = streamer_read_uhwi (ib); tree v_decl = lto_file_decl_data_get_var_decl (file_data, var_index); - bitmap_set_bit (info->statics_not_written, DECL_UID (v_decl)); + bitmap_set_bit (info->statics_not_written, + ipa_reference_var_uid (v_decl)); if (dump_file) fprintf (dump_file, " %s", fndecl_name (v_decl)); } @@ -1114,10 +1169,11 @@ ipa_reference_read_optimization_summary (void) ib, data, len); } else - /* Fatal error here. We do not want to support compiling ltrans units with - different version of compiler or different flags than the WPA unit, so - this should never happen. */ - fatal_error ("ipa reference summary is missing in ltrans unit"); + /* Fatal error here. We do not want to support compiling ltrans units + with different version of compiler or different flags than + the WPA unit, so this should never happen. */ + fatal_error (input_location, + "ipa reference summary is missing in ltrans unit"); } } @@ -1157,7 +1213,7 @@ public: /* opt_pass methods: */ virtual bool gate (function *) { - return (flag_ipa_reference + return ((in_lto_p || flag_ipa_reference) /* Don't bother doing anything if the program has errors. */ && !seen_error ()); } @@ -1173,3 +1229,22 @@ make_pass_ipa_reference (gcc::context *ctxt) { return new pass_ipa_reference (ctxt); } + +/* Reset all state within ipa-reference.c so that we can rerun the compiler + within the same process. For use by toplev::finalize. */ + +void +ipa_reference_c_finalize (void) +{ + if (ipa_ref_opt_sum_summaries != NULL) + { + delete ipa_ref_opt_sum_summaries; + ipa_ref_opt_sum_summaries = NULL; + } + + if (ipa_init_p) + { + bitmap_obstack_release (&optimization_summary_obstack); + ipa_init_p = false; + } +}