Make default duplicate and insert methods of summaries abort; fix fallout

the default duplicate and insert methods of sumaries produce empty
summary that is not useful for anything and makes it easy to introduce
bugs.

This patch makes the default hooks to abort and summaries that do not
need dupicaito/insertion disable the corresponding hooks. I also
implemented missing insertion hook for ipa-sra which forced me to move
analysis out of anonymous namespace.

2020-10-23  Jan Hubicka  <hubicka@ucw.cz>

	* cgraph.h (struct cgraph_node): Make ipa_transforms_to_apply vl_ptr.
	* ipa-inline-analysis.c (initialize_growth_caches): Disable insertion
	and duplication hooks.
	* ipa-inline-transform.c (clone_inlined_nodes): Clear
	ipa_transforms_to_apply.
	(save_inline_function_body): Disable insertion hoook for
	ipa_saved_clone_sources.
	* ipa-prop.c (ipcp_transformation_initialize): Disable insertion hook.
	* ipa-prop.h (ipa_node_params_t): Disable insertion hook.
	* ipa-reference.c (propagate): Disable insertion hoook.
	* ipa-sra.c (ipa_sra_summarize_function): Move out of anonymous
	namespace.
	(ipa_sra_function_summaries::insert): New virtual function.
	* passes.c (execute_one_pass): Do not add transforms to inline clones.
	* symbol-summary.h (function_summary_base): Make insert and duplicate
	hooks fail instead of silently producing empty summaries; add way to
	disable duplication hooks
	(call_summary_base): Likewise.
	* tree-nested.c (nested_function_info::get_create): Disable insertion
	hooks
	(maybe_record_nested_function): Likewise.
This commit is contained in:
Jan Hubicka 2020-10-26 11:24:33 +01:00
parent dc7824734e
commit 40e67ab8e5
10 changed files with 210 additions and 110 deletions

View File

@ -1402,7 +1402,7 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node
/* 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. */

View File

@ -127,6 +127,9 @@ initialize_growth_caches ()
= 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. */

View File

@ -231,6 +231,11 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
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)
@ -606,7 +611,10 @@ save_inline_function_body (struct cgraph_node *node)
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);

View File

@ -4211,7 +4211,10 @@ ipcp_transformation_initialize (void)
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. */

View File

@ -941,7 +941,10 @@ class GTY((user)) ipa_node_params_t: public function_summary <ipa_node_params *>
{
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,

View File

@ -894,7 +894,10 @@ propagate (void)
}
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)
@ -1130,6 +1133,7 @@ ipa_reference_read_optimization_summary (void)
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);

View File

@ -85,6 +85,8 @@ along with GCC; see the file COPYING3. If not see
#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)
@ -373,6 +375,7 @@ public:
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. */
@ -426,6 +429,21 @@ ipa_sra_function_summaries::duplicate (cgraph_node *, cgraph_node *,
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 *>
@ -2478,79 +2496,6 @@ verify_splitting_accesses (cgraph_node *node, bool certain_must_exist)
}
}
/* 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, &param_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,
&param_descriptions);
fprintf (dump_file, "----------------------------------------\n");
}
}
process_scan_results (node, fun, ifs, &param_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. */
@ -4102,6 +4047,79 @@ public:
} // 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, &param_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,
&param_descriptions);
fprintf (dump_file, "----------------------------------------\n");
}
}
process_scan_results (node, fun, ifs, &param_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)
{

View File

@ -2566,7 +2566,8 @@ execute_one_pass (opt_pass *pass)
{
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);

View File

@ -31,17 +31,27 @@ public:
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 ()
@ -55,6 +65,18 @@ public:
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 ()
@ -88,6 +110,8 @@ protected:
/* 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. */
@ -269,10 +293,13 @@ function_summary<T *>::symtab_duplication (cgraph_node *node,
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>
@ -468,12 +495,15 @@ fast_function_summary<T *, V>::symtab_duplication (cgraph_node *node,
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);
}
}
}
@ -536,6 +566,7 @@ public:
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)
{}
@ -543,7 +574,22 @@ public:
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. */
@ -576,6 +622,8 @@ protected:
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. */
@ -726,16 +774,19 @@ call_summary<T *>::symtab_duplication (cgraph_edge *edge1,
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>
@ -892,17 +943,20 @@ fast_call_summary<T *, V>::symtab_duplication (cgraph_edge *edge1,
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);
}
}
}

View File

@ -65,8 +65,11 @@ nested_function_info *
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);
}
@ -124,6 +127,9 @@ nested_function_info::release ()
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)
{