/* Interprocedural passes scheduled to have their transform functions
applied next time we execute local pass on them. We maintain it
per-function in order to allow IPA passes to introduce new functions. */
- vec<ipa_opt_pass> GTY((skip)) ipa_transforms_to_apply;
+ vec<ipa_opt_pass, va_heap, vl_ptr> GTY((skip)) ipa_transforms_to_apply;
/* For inline clones this points to the function they will be
inlined into. */
= new fast_call_summary<edge_growth_cache_entry *, va_heap> (symtab);
node_context_cache
= new fast_function_summary<node_context_summary *, va_heap> (symtab);
+ edge_growth_cache->disable_duplication_hook ();
+ node_context_cache->disable_insertion_hook ();
+ node_context_cache->disable_duplication_hook ();
}
/* Free growth caches. */
e->callee->remove_from_same_comdat_group ();
e->callee->inlined_to = inlining_into;
+ if (e->callee->ipa_transforms_to_apply.length ())
+ {
+ e->callee->ipa_transforms_to_apply.release ();
+ e->callee->ipa_transforms_to_apply = vNULL;
+ }
/* Recursively clone all bodies. */
for (e = e->callee->callees; e; e = next)
tree prev_body_holder = node->decl;
if (!ipa_saved_clone_sources)
- ipa_saved_clone_sources = new function_summary <tree *> (symtab);
+ {
+ ipa_saved_clone_sources = new function_summary <tree *> (symtab);
+ ipa_saved_clone_sources->disable_insertion_hook ();
+ }
else
{
tree *p = ipa_saved_clone_sources->get (node);
if (!ipa_vr_hash_table)
ipa_vr_hash_table = hash_table<ipa_vr_ggc_hash_traits>::create_ggc (37);
if (ipcp_transformation_sum == NULL)
- ipcp_transformation_sum = ipcp_transformation_t::create_ggc (symtab);
+ {
+ ipcp_transformation_sum = ipcp_transformation_t::create_ggc (symtab);
+ ipcp_transformation_sum->disable_insertion_hook ();
+ }
}
/* Release the IPA CP transformation summary. */
{
public:
ipa_node_params_t (symbol_table *table, bool ggc):
- function_summary<ipa_node_params *> (table, ggc) { }
+ function_summary<ipa_node_params *> (table, ggc)
+ {
+ disable_insertion_hook ();
+ }
/* Hook that is called by summary when a node is duplicated. */
virtual void duplicate (cgraph_node *node,
}
if (ipa_ref_opt_sum_summaries == NULL)
- ipa_ref_opt_sum_summaries = new ipa_ref_opt_summary_t (symtab);
+ {
+ ipa_ref_opt_sum_summaries = new ipa_ref_opt_summary_t (symtab);
+ ipa_ref_opt_sum_summaries->disable_insertion_hook ();
+ }
/* Cleanup. */
FOR_EACH_DEFINED_FUNCTION (node)
gcc_checking_assert (ipa_ref_opt_sum_summaries == NULL);
ipa_ref_opt_sum_summaries = new ipa_ref_opt_summary_t (symtab);
+ ipa_ref_opt_sum_summaries->disable_insertion_hook ();
ipa_reference_vars_map = new reference_vars_map_t(257);
varpool_node_hooks
= symtab->add_varpool_removal_hook (varpool_removal_hook, NULL);
#include "tree-streamer.h"
#include "internal-fn.h"
+static void ipa_sra_summarize_function (cgraph_node *);
+
/* Bits used to track size of an aggregate in bytes interprocedurally. */
#define ISRA_ARG_SIZE_LIMIT_BITS 16
#define ISRA_ARG_SIZE_LIMIT (1 << ISRA_ARG_SIZE_LIMIT_BITS)
virtual void duplicate (cgraph_node *, cgraph_node *,
isra_func_summary *old_sum,
isra_func_summary *new_sum);
+ virtual void insert (cgraph_node *, isra_func_summary *);
};
/* Hook that is called by summary when a node is duplicated. */
static GTY(()) ipa_sra_function_summaries *func_sums;
+/* Hook that is called by summary when new node appears. */
+
+void
+ipa_sra_function_summaries::insert (cgraph_node *node, isra_func_summary *)
+{
+ if (opt_for_fn (node->decl, flag_ipa_sra))
+ {
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
+ ipa_sra_summarize_function (node);
+ pop_cfun ();
+ }
+ else
+ func_sums->remove (node);
+}
+
/* Class to manage call summaries. */
class ipa_sra_call_summaries: public call_summary <isra_call_summary *>
}
}
-/* Intraprocedural part of IPA-SRA analysis. Scan function body of NODE and
- create a summary structure describing IPA-SRA opportunities and constraints
- in it. */
-
-static void
-ipa_sra_summarize_function (cgraph_node *node)
-{
- if (dump_file)
- fprintf (dump_file, "Creating summary for %s/%i:\n", node->name (),
- node->order);
- if (!ipa_sra_preliminary_function_checks (node))
- return;
- gcc_obstack_init (&gensum_obstack);
- isra_func_summary *ifs = func_sums->get_create (node);
- ifs->m_candidate = true;
- tree ret = TREE_TYPE (TREE_TYPE (node->decl));
- ifs->m_returns_value = (TREE_CODE (ret) != VOID_TYPE);
-
- decl2desc = new hash_map<tree, gensum_param_desc *>;
- unsigned count = 0;
- for (tree parm = DECL_ARGUMENTS (node->decl); parm; parm = DECL_CHAIN (parm))
- count++;
-
- if (count > 0)
- {
- auto_vec<gensum_param_desc, 16> param_descriptions (count);
- param_descriptions.reserve_exact (count);
- param_descriptions.quick_grow_cleared (count);
-
- bool cfun_pushed = false;
- struct function *fun = DECL_STRUCT_FUNCTION (node->decl);
- if (create_parameter_descriptors (node, ¶m_descriptions))
- {
- push_cfun (fun);
- cfun_pushed = true;
- final_bbs = BITMAP_ALLOC (NULL);
- bb_dereferences = XCNEWVEC (HOST_WIDE_INT,
- by_ref_count
- * last_basic_block_for_fn (fun));
- aa_walking_limit = opt_for_fn (node->decl, param_ipa_max_aa_steps);
- scan_function (node, fun);
-
- if (dump_file)
- {
- dump_gensum_param_descriptors (dump_file, node->decl,
- ¶m_descriptions);
- fprintf (dump_file, "----------------------------------------\n");
- }
- }
- process_scan_results (node, fun, ifs, ¶m_descriptions);
-
- if (cfun_pushed)
- pop_cfun ();
- if (bb_dereferences)
- {
- free (bb_dereferences);
- bb_dereferences = NULL;
- BITMAP_FREE (final_bbs);
- final_bbs = NULL;
- }
- }
- isra_analyze_all_outgoing_calls (node);
-
- delete decl2desc;
- decl2desc = NULL;
- obstack_free (&gensum_obstack, NULL);
- if (dump_file)
- fprintf (dump_file, "\n\n");
- if (flag_checking)
- verify_splitting_accesses (node, false);
- return;
-}
-
/* Intraprocedural part of IPA-SRA analysis. Scan bodies of all functions in
this compilation unit and create summary structures describing IPA-SRA
opportunities and constraints in them. */
} // anon namespace
+/* Intraprocedural part of IPA-SRA analysis. Scan function body of NODE and
+ create a summary structure describing IPA-SRA opportunities and constraints
+ in it. */
+
+static void
+ipa_sra_summarize_function (cgraph_node *node)
+{
+ if (dump_file)
+ fprintf (dump_file, "Creating summary for %s/%i:\n", node->name (),
+ node->order);
+ if (!ipa_sra_preliminary_function_checks (node))
+ return;
+ gcc_obstack_init (&gensum_obstack);
+ isra_func_summary *ifs = func_sums->get_create (node);
+ ifs->m_candidate = true;
+ tree ret = TREE_TYPE (TREE_TYPE (node->decl));
+ ifs->m_returns_value = (TREE_CODE (ret) != VOID_TYPE);
+
+ decl2desc = new hash_map<tree, gensum_param_desc *>;
+ unsigned count = 0;
+ for (tree parm = DECL_ARGUMENTS (node->decl); parm; parm = DECL_CHAIN (parm))
+ count++;
+
+ if (count > 0)
+ {
+ auto_vec<gensum_param_desc, 16> param_descriptions (count);
+ param_descriptions.reserve_exact (count);
+ param_descriptions.quick_grow_cleared (count);
+
+ bool cfun_pushed = false;
+ struct function *fun = DECL_STRUCT_FUNCTION (node->decl);
+ if (create_parameter_descriptors (node, ¶m_descriptions))
+ {
+ push_cfun (fun);
+ cfun_pushed = true;
+ final_bbs = BITMAP_ALLOC (NULL);
+ bb_dereferences = XCNEWVEC (HOST_WIDE_INT,
+ by_ref_count
+ * last_basic_block_for_fn (fun));
+ aa_walking_limit = opt_for_fn (node->decl, param_ipa_max_aa_steps);
+ scan_function (node, fun);
+
+ if (dump_file)
+ {
+ dump_gensum_param_descriptors (dump_file, node->decl,
+ ¶m_descriptions);
+ fprintf (dump_file, "----------------------------------------\n");
+ }
+ }
+ process_scan_results (node, fun, ifs, ¶m_descriptions);
+
+ if (cfun_pushed)
+ pop_cfun ();
+ if (bb_dereferences)
+ {
+ free (bb_dereferences);
+ bb_dereferences = NULL;
+ BITMAP_FREE (final_bbs);
+ final_bbs = NULL;
+ }
+ }
+ isra_analyze_all_outgoing_calls (node);
+
+ delete decl2desc;
+ decl2desc = NULL;
+ obstack_free (&gensum_obstack, NULL);
+ if (dump_file)
+ fprintf (dump_file, "\n\n");
+ if (flag_checking)
+ verify_splitting_accesses (node, false);
+ return;
+}
+
ipa_opt_pass_d *
make_pass_ipa_sra (gcc::context *ctxt)
{
{
struct cgraph_node *node;
FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
- node->ipa_transforms_to_apply.safe_push ((ipa_opt_pass_d *)pass);
+ if (!node->inlined_to)
+ node->ipa_transforms_to_apply.safe_push ((ipa_opt_pass_d *)pass);
}
else if (dump_file)
do_per_function (execute_function_dump, pass);
function_summary_base (symbol_table *symtab CXX_MEM_STAT_INFO):
m_symtab (symtab),
m_insertion_enabled (true),
+ m_duplication_enabled (true),
m_allocator ("function summary" PASS_MEM_STAT)
{}
/* Basic implementation of insert operation. */
- virtual void insert (cgraph_node *, T *) {}
+ virtual void insert (cgraph_node *, T *)
+ {
+ /* In most cases, it makes no sense to create summaries without
+ initializing them. */
+ gcc_unreachable ();
+ }
/* Basic implementation of removal operation. */
virtual void remove (cgraph_node *, T *) {}
/* Basic implementation of duplication operation. */
- virtual void duplicate (cgraph_node *, cgraph_node *, T *, T *) {}
+ virtual void duplicate (cgraph_node *, cgraph_node *, T *, T *)
+ {
+ /* It makes no sense to not copy anything during duplication. */
+ gcc_unreachable ();
+ }
/* Enable insertion hook invocation. */
void enable_insertion_hook ()
m_insertion_enabled = false;
}
+ /* Enable duplication hook invocation. */
+ void enable_duplication_hook ()
+ {
+ m_duplication_enabled = true;
+ }
+
+ /* Enable duplication hook invocation. */
+ void disable_duplication_hook ()
+ {
+ m_duplication_enabled = false;
+ }
+
protected:
/* Allocates new data that are stored within map. */
T* allocate_new ()
/* Indicates if insertion hook is enabled. */
bool m_insertion_enabled;
+ /* Indicates if duplication hook is enabled. */
+ bool m_duplication_enabled;
private:
/* Return true when the summary uses GGC memory for allocation. */
cgraph_node *node2, void *data)
{
function_summary *summary = (function_summary <T *> *) (data);
- T *v = summary->get (node);
+ if (summary->m_duplication_enabled)
+ {
+ T *v = summary->get (node);
- if (v)
- summary->duplicate (node, node2, v, summary->get_create (node2));
+ if (v)
+ summary->duplicate (node, node2, v, summary->get_create (node2));
+ }
}
template <typename T>
void *data)
{
fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
- T *v = summary->get (node);
-
- if (v)
+ if (summary->m_duplication_enabled)
{
- T *duplicate = summary->get_create (node2);
- summary->duplicate (node, node2, v, duplicate);
+ T *v = summary->get (node);
+
+ if (v)
+ {
+ T *duplicate = summary->get_create (node2);
+ summary->duplicate (node, node2, v, duplicate);
+ }
}
}
call_summary_base (symbol_table *symtab CXX_MEM_STAT_INFO):
m_symtab (symtab),
m_initialize_when_cloning (false),
+ m_duplication_enabled (true),
m_allocator ("call summary" PASS_MEM_STAT)
{}
virtual void remove (cgraph_edge *, T *) {}
/* Basic implementation of duplication operation. */
- virtual void duplicate (cgraph_edge *, cgraph_edge *, T *, T *) {}
+ virtual void duplicate (cgraph_edge *, cgraph_edge *, T *, T *)
+ {
+ gcc_unreachable ();
+ }
+
+ /* Enable duplication hook invocation. */
+ void enable_duplication_hook ()
+ {
+ m_duplication_enabled = true;
+ }
+
+ /* Enable duplication hook invocation. */
+ void disable_duplication_hook ()
+ {
+ m_duplication_enabled = false;
+ }
protected:
/* Allocates new data that are stored within map. */
cgraph_2edge_hook_list *m_symtab_duplication_hook;
/* Initialize summary for an edge that is cloned. */
bool m_initialize_when_cloning;
+ /* Indicates if duplication hook is enabled. */
+ bool m_duplication_enabled;
private:
/* Return true when the summary uses GGC memory for allocation. */
cgraph_edge *edge2, void *data)
{
call_summary *summary = (call_summary <T *> *) (data);
- T *edge1_summary = NULL;
+ if (summary->m_duplication_enabled)
+ {
+ T *edge1_summary = NULL;
- if (summary->m_initialize_when_cloning)
- edge1_summary = summary->get_create (edge1);
- else
- edge1_summary = summary->get (edge1);
+ if (summary->m_initialize_when_cloning)
+ edge1_summary = summary->get_create (edge1);
+ else
+ edge1_summary = summary->get (edge1);
- if (edge1_summary)
- summary->duplicate (edge1, edge2, edge1_summary,
- summary->get_create (edge2));
+ if (edge1_summary)
+ summary->duplicate (edge1, edge2, edge1_summary,
+ summary->get_create (edge2));
+ }
}
template <typename T>
cgraph_edge *edge2, void *data)
{
fast_call_summary *summary = (fast_call_summary <T *, V> *) (data);
- T *edge1_summary = NULL;
-
- if (summary->m_initialize_when_cloning)
- edge1_summary = summary->get_create (edge1);
- else
- edge1_summary = summary->get (edge1);
-
- if (edge1_summary)
+ if (summary->m_duplication_enabled)
{
- T *duplicate = summary->get_create (edge2);
- summary->duplicate (edge1, edge2, edge1_summary, duplicate);
+ T *edge1_summary = NULL;
+
+ if (summary->m_initialize_when_cloning)
+ edge1_summary = summary->get_create (edge1);
+ else
+ edge1_summary = summary->get (edge1);
+
+ if (edge1_summary)
+ {
+ T *duplicate = summary->get_create (edge2);
+ summary->duplicate (edge1, edge2, edge1_summary, duplicate);
+ }
}
}
nested_function_info::get_create (cgraph_node *node)
{
if (!nested_function_sum)
- nested_function_sum = new function_summary <nested_function_info *>
- (symtab);
+ {
+ nested_function_sum = new function_summary <nested_function_info *>
+ (symtab);
+ nested_function_sum->disable_insertion_hook ();
+ }
return nested_function_sum->get_create (node);
}
void
maybe_record_nested_function (cgraph_node *node)
{
+ /* All nested functions gets lowered during the construction of symtab. */
+ if (symtab->state > CONSTRUCTION)
+ return;
if (DECL_CONTEXT (node->decl)
&& TREE_CODE (DECL_CONTEXT (node->decl)) == FUNCTION_DECL)
{