Commit c628d1c3 by Martin Jambor Committed by Martin Jambor

Limit AA walking in IPA summary generation

2019-01-20  Martin Jambor  <mjambor@suse.cz>

	PR ipa/87615
	* ipa-prop.h (struct ipa_func_body_info): Replaced field aa_walked
	with aa_walk_budget.
	* cgraph.h (ipa_polymorphic_call_context::get_dynamic_type): Add
	aa_walk_budget_p parameter.
	* ipa-fnsummary.c (unmodified_parm_1): New parameter fbi.  Limit AA
	walk.  Updated all callers.
	(unmodified_parm): New parameter fbi, pass it to unmodified_parm_1.
	(eliminated_by_inlining_prob): New parameter fbi, pass it on to
	unmodified_parm.
	(will_be_nonconstant_expr_predicate): New parameter fbi, removed
	parameter info.  Extract info from fbi.  Pass fbi to recursive calls
	and to unmodified_parm.
	(phi_result_unknown_predicate): New parameter fbi, removed parameter
	info, updated call to will_be_nonconstant_expr_predicate.
	(param_change_prob): New parameter fbi, limit AA walking.
	(analyze_function_body): Initialize aa_walk_budget in fbi.  Update
	calls to various above functions.
	* ipa-polymorphic-call.c (get_dynamic_type): Add aa_walk_budget_p
	parameter.  Use it to limit AA walking.
	* ipa-prop.c (detect_type_change_from_memory_writes): New parameter
	fbi, limit AA walk.
	(detect_type_change): New parameter fbi, pass it on to
	detect_type_change_from_memory_writes.
	(detect_type_change_ssa): Likewise.
	(aa_overwalked): Removed.
	(parm_preserved_before_stmt_p): Assume fbi is never NULL, stream line
	accordingly, adjust to the neew AA limiting scheme.
	(parm_ref_data_preserved_p): Likewise.
	(ipa_compute_jump_functions_for_edge): Adjust call to
	get_dynamic_type.
	(ipa_analyze_call_uses): Likewise.
	(ipa_analyze_virtual_call_uses): Pass fbi to detect_type_change_ssa.
	(ipa_analyze_node): Initialize aa_walk_budget.
	(ipcp_transform_function): Likewise.
	* tree-ssa-sccvn.c (eliminate_dom_walker::eliminate_stmt): Update call
	to get_dynamic_type.

From-SVN: r268107
parent 49686677
2019-01-20 Martin Jambor <mjambor@suse.cz>
PR ipa/87615
* ipa-prop.h (struct ipa_func_body_info): Replaced field aa_walked
with aa_walk_budget.
* cgraph.h (ipa_polymorphic_call_context::get_dynamic_type): Add
aa_walk_budget_p parameter.
* ipa-fnsummary.c (unmodified_parm_1): New parameter fbi. Limit AA
walk. Updated all callers.
(unmodified_parm): New parameter fbi, pass it to unmodified_parm_1.
(eliminated_by_inlining_prob): New parameter fbi, pass it on to
unmodified_parm.
(will_be_nonconstant_expr_predicate): New parameter fbi, removed
parameter info. Extract info from fbi. Pass fbi to recursive calls
and to unmodified_parm.
(phi_result_unknown_predicate): New parameter fbi, removed parameter
info, updated call to will_be_nonconstant_expr_predicate.
(param_change_prob): New parameter fbi, limit AA walking.
(analyze_function_body): Initialize aa_walk_budget in fbi. Update
calls to various above functions.
* ipa-polymorphic-call.c (get_dynamic_type): Add aa_walk_budget_p
parameter. Use it to limit AA walking.
* ipa-prop.c (detect_type_change_from_memory_writes): New parameter
fbi, limit AA walk.
(detect_type_change): New parameter fbi, pass it on to
detect_type_change_from_memory_writes.
(detect_type_change_ssa): Likewise.
(aa_overwalked): Removed.
(parm_preserved_before_stmt_p): Assume fbi is never NULL, stream line
accordingly, adjust to the neew AA limiting scheme.
(parm_ref_data_preserved_p): Likewise.
(ipa_compute_jump_functions_for_edge): Adjust call to
get_dynamic_type.
(ipa_analyze_call_uses): Likewise.
(ipa_analyze_virtual_call_uses): Pass fbi to detect_type_change_ssa.
(ipa_analyze_node): Initialize aa_walk_budget.
(ipcp_transform_function): Likewise.
* tree-ssa-sccvn.c (eliminate_dom_walker::eliminate_stmt): Update call
to get_dynamic_type.
2019-01-19 Jakub Jelinek <jakub@redhat.com>
* config/aarch64/aarch64.c (aarch64_stack_protect_guard): Move
......
......@@ -1557,7 +1557,7 @@ public:
/* Look for vtable stores or constructor calls to work out dynamic type
of memory location. */
bool get_dynamic_type (tree, tree, tree, gimple *);
bool get_dynamic_type (tree, tree, tree, gimple *, unsigned *);
/* Make context non-speculative. */
void clear_speculation ();
......
......@@ -1554,13 +1554,18 @@ check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data)
We do not include this analysis in the context analysis itself, because
it needs memory SSA to be fully built and the walk may be expensive.
So it is not suitable for use withing fold_stmt and similar uses. */
So it is not suitable for use withing fold_stmt and similar uses.
AA_WALK_BUDGET_P, if not NULL, is how statements we should allow
walk_aliased_vdefs to examine. The value should be decremented by the
number of stetements we examined or set to zero if exhausted. */
bool
ipa_polymorphic_call_context::get_dynamic_type (tree instance,
tree otr_object,
tree otr_type,
gimple *call)
gimple *call,
unsigned *aa_walk_budget_p)
{
struct type_change_info tci;
ao_ref ao;
......@@ -1723,8 +1728,13 @@ ipa_polymorphic_call_context::get_dynamic_type (tree instance,
tci.speculative = 0;
tci.seen_unanalyzed_store = false;
walk_aliased_vdefs (&ao, gimple_vuse (stmt), check_stmt_for_type_change,
&tci, NULL, &function_entry_reached);
unsigned aa_walk_budget = 0;
if (aa_walk_budget_p)
aa_walk_budget = *aa_walk_budget_p + 1;
int walked
= walk_aliased_vdefs (&ao, gimple_vuse (stmt), check_stmt_for_type_change,
&tci, NULL, &function_entry_reached, aa_walk_budget);
/* If we did not find any type changing statements, we may still drop
maybe_in_construction flag if the context already have outer type.
......@@ -1772,6 +1782,16 @@ ipa_polymorphic_call_context::get_dynamic_type (tree instance,
only if there was dyanmic type store that may affect given variable
(seen_unanalyzed_store) */
if (walked < 0)
{
if (dump_file)
fprintf (dump_file, " AA walk budget exhausted.\n");
*aa_walk_budget_p = 0;
return false;
}
else if (aa_walk_budget_p)
*aa_walk_budget_p -= walked;
if (!tci.type_maybe_changed
|| (outer_type
&& !dynamic
......
......@@ -746,13 +746,13 @@ param_type_may_change_p (tree function, tree arg, gimple *call)
that does the heavy work which is usually unnecesary. */
static bool
detect_type_change_from_memory_writes (tree arg, tree base, tree comp_type,
gcall *call, struct ipa_jump_func *jfunc,
detect_type_change_from_memory_writes (ipa_func_body_info *fbi, tree arg,
tree base, tree comp_type, gcall *call,
struct ipa_jump_func *jfunc,
HOST_WIDE_INT offset)
{
struct prop_type_change_info tci;
ao_ref ao;
bool entry_reached = false;
gcc_checking_assert (DECL_P (arg)
|| TREE_CODE (arg) == MEM_REF
......@@ -780,9 +780,11 @@ detect_type_change_from_memory_writes (tree arg, tree base, tree comp_type,
tci.object = get_base_address (arg);
tci.type_maybe_changed = false;
walk_aliased_vdefs (&ao, gimple_vuse (call), check_stmt_for_type_change,
&tci, NULL, &entry_reached);
if (!tci.type_maybe_changed)
int walked
= walk_aliased_vdefs (&ao, gimple_vuse (call), check_stmt_for_type_change,
&tci, NULL, NULL, fbi->aa_walk_budget + 1);
if (walked >= 0 && !tci.type_maybe_changed)
return false;
ipa_set_jf_unknown (jfunc);
......@@ -796,8 +798,9 @@ detect_type_change_from_memory_writes (tree arg, tree base, tree comp_type,
returned by get_ref_base_and_extent, as is the offset. */
static bool
detect_type_change (tree arg, tree base, tree comp_type, gcall *call,
struct ipa_jump_func *jfunc, HOST_WIDE_INT offset)
detect_type_change (ipa_func_body_info *fbi, tree arg, tree base,
tree comp_type, gcall *call, struct ipa_jump_func *jfunc,
HOST_WIDE_INT offset)
{
if (!flag_devirtualize)
return false;
......@@ -807,7 +810,7 @@ detect_type_change (tree arg, tree base, tree comp_type, gcall *call,
TREE_OPERAND (base, 0),
call))
return false;
return detect_type_change_from_memory_writes (arg, base, comp_type,
return detect_type_change_from_memory_writes (fbi, arg, base, comp_type,
call, jfunc, offset);
}
......@@ -816,7 +819,7 @@ detect_type_change (tree arg, tree base, tree comp_type, gcall *call,
be zero). */
static bool
detect_type_change_ssa (tree arg, tree comp_type,
detect_type_change_ssa (ipa_func_body_info *fbi, tree arg, tree comp_type,
gcall *call, struct ipa_jump_func *jfunc)
{
gcc_checking_assert (TREE_CODE (arg) == SSA_NAME);
......@@ -830,7 +833,7 @@ detect_type_change_ssa (tree arg, tree comp_type,
arg = build2 (MEM_REF, ptr_type_node, arg,
build_int_cst (ptr_type_node, 0));
return detect_type_change_from_memory_writes (arg, arg, comp_type,
return detect_type_change_from_memory_writes (fbi, arg, arg, comp_type,
call, jfunc, 0);
}
......@@ -846,16 +849,6 @@ mark_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
return true;
}
/* Return true if we have already walked so many statements in AA that we
should really just start giving up. */
static bool
aa_overwalked (struct ipa_func_body_info *fbi)
{
gcc_checking_assert (fbi);
return fbi->aa_walked > (unsigned) PARAM_VALUE (PARAM_IPA_MAX_AA_STEPS);
}
/* Find the nearest valid aa status for parameter specified by INDEX that
dominates BB. */
......@@ -922,28 +915,24 @@ parm_preserved_before_stmt_p (struct ipa_func_body_info *fbi, int index,
if (TREE_READONLY (base))
return true;
/* FIXME: FBI can be NULL if we are being called from outside
ipa_node_analysis or ipcp_transform_function, which currently happens
during inlining analysis. It would be great to extend fbi's lifetime and
always have it. Currently, we are just not afraid of too much walking in
that case. */
if (fbi)
{
if (aa_overwalked (fbi))
return false;
paa = parm_bb_aa_status_for_bb (fbi, gimple_bb (stmt), index);
if (paa->parm_modified)
return false;
}
else
paa = NULL;
gcc_checking_assert (fbi);
paa = parm_bb_aa_status_for_bb (fbi, gimple_bb (stmt), index);
if (paa->parm_modified)
return false;
gcc_checking_assert (gimple_vuse (stmt) != NULL_TREE);
ao_ref_init (&refd, parm_load);
int walked = walk_aliased_vdefs (&refd, gimple_vuse (stmt), mark_modified,
&modified, NULL);
if (fbi)
fbi->aa_walked += walked;
&modified, NULL, NULL,
fbi->aa_walk_budget + 1);
if (walked < 0)
{
modified = true;
if (fbi)
fbi->aa_walk_budget = 0;
}
else if (fbi)
fbi->aa_walk_budget -= walked;
if (paa && modified)
paa->parm_modified = true;
return !modified;
......@@ -988,29 +977,24 @@ parm_ref_data_preserved_p (struct ipa_func_body_info *fbi,
bool modified = false;
ao_ref refd;
/* FIXME: FBI can be NULL if we are being called from outside
ipa_node_analysis or ipcp_transform_function, which currently happens
during inlining analysis. It would be great to extend fbi's lifetime and
always have it. Currently, we are just not afraid of too much walking in
that case. */
if (fbi)
{
if (aa_overwalked (fbi))
return false;
paa = parm_bb_aa_status_for_bb (fbi, gimple_bb (stmt), index);
if (paa->ref_modified)
return false;
}
else
paa = NULL;
gcc_checking_assert (fbi);
paa = parm_bb_aa_status_for_bb (fbi, gimple_bb (stmt), index);
if (paa->ref_modified)
return false;
gcc_checking_assert (gimple_vuse (stmt));
ao_ref_init (&refd, ref);
int walked = walk_aliased_vdefs (&refd, gimple_vuse (stmt), mark_modified,
&modified, NULL);
if (fbi)
fbi->aa_walked += walked;
if (paa && modified)
&modified, NULL, NULL,
fbi->aa_walk_budget + 1);
if (walked < 0)
{
modified = true;
fbi->aa_walk_budget = 0;
}
else
fbi->aa_walk_budget -= walked;
if (modified)
paa->ref_modified = true;
return !modified;
}
......@@ -1030,8 +1014,7 @@ parm_ref_data_pass_through_p (struct ipa_func_body_info *fbi, int index,
function because it is not goin to use it. But do not cache the result
either. Also, no such calculations for non-pointers. */
if (!gimple_vuse (call)
|| !POINTER_TYPE_P (TREE_TYPE (parm))
|| aa_overwalked (fbi))
|| !POINTER_TYPE_P (TREE_TYPE (parm)))
return false;
struct ipa_param_aa_status *paa = parm_bb_aa_status_for_bb (fbi,
......@@ -1042,8 +1025,15 @@ parm_ref_data_pass_through_p (struct ipa_func_body_info *fbi, int index,
ao_ref_init_from_ptr_and_size (&refd, parm, NULL_TREE);
int walked = walk_aliased_vdefs (&refd, gimple_vuse (call), mark_modified,
&modified, NULL);
fbi->aa_walked += walked;
&modified, NULL, NULL,
fbi->aa_walk_budget + 1);
if (walked < 0)
{
fbi->aa_walk_budget = 0;
modified = true;
}
else
fbi->aa_walk_budget -= walked;
if (modified)
paa->pt_modified = true;
return !modified;
......@@ -1851,7 +1841,8 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
struct ipa_polymorphic_call_context context (cs->caller->decl,
arg, cs->call_stmt,
&instance);
context.get_dynamic_type (instance, arg, NULL, cs->call_stmt);
context.get_dynamic_type (instance, arg, NULL, cs->call_stmt,
&fbi->aa_walk_budget);
*ipa_get_ith_polymorhic_call_context (args, n) = context;
if (!context.useless_p ())
useful_context = true;
......@@ -2324,7 +2315,7 @@ ipa_analyze_virtual_call_uses (struct ipa_func_body_info *fbi,
anc_offset = 0;
index = ipa_get_param_decl_index (info, SSA_NAME_VAR (obj));
gcc_assert (index >= 0);
if (detect_type_change_ssa (obj, obj_type_ref_class (target),
if (detect_type_change_ssa (fbi, obj, obj_type_ref_class (target),
call, &jfunc))
return;
}
......@@ -2340,7 +2331,7 @@ ipa_analyze_virtual_call_uses (struct ipa_func_body_info *fbi,
index = ipa_get_param_decl_index (info,
SSA_NAME_VAR (TREE_OPERAND (expr, 0)));
gcc_assert (index >= 0);
if (detect_type_change (obj, expr, obj_type_ref_class (target),
if (detect_type_change (fbi, obj, expr, obj_type_ref_class (target),
call, &jfunc, anc_offset))
return;
}
......@@ -2388,7 +2379,8 @@ ipa_analyze_call_uses (struct ipa_func_body_info *fbi, gcall *call)
cs->indirect_info->vptr_changed
= !context.get_dynamic_type (instance,
OBJ_TYPE_REF_OBJECT (target),
obj_type_ref_class (target), call);
obj_type_ref_class (target), call,
&fbi->aa_walk_budget);
cs->indirect_info->context = context;
}
......@@ -2588,7 +2580,7 @@ ipa_analyze_node (struct cgraph_node *node)
fbi.bb_infos = vNULL;
fbi.bb_infos.safe_grow_cleared (last_basic_block_for_fn (cfun));
fbi.param_count = ipa_get_param_count (info);
fbi.aa_walked = 0;
fbi.aa_walk_budget = PARAM_VALUE (PARAM_IPA_MAX_AA_STEPS);
for (struct cgraph_edge *cs = node->callees; cs; cs = cs->next_callee)
{
......@@ -5157,7 +5149,7 @@ ipcp_transform_function (struct cgraph_node *node)
fbi.bb_infos = vNULL;
fbi.bb_infos.safe_grow_cleared (last_basic_block_for_fn (cfun));
fbi.param_count = param_count;
fbi.aa_walked = 0;
fbi.aa_walk_budget = PARAM_VALUE (PARAM_IPA_MAX_AA_STEPS);
vec_safe_grow_cleared (descriptors, param_count);
ipa_populate_param_decls (node, *descriptors);
......
......@@ -428,8 +428,9 @@ struct ipa_func_body_info
/* Number of parameters. */
int param_count;
/* Number of statements already walked by when analyzing this function. */
unsigned int aa_walked;
/* Number of statements we are still allowed to walked by when analyzing this
function. */
unsigned int aa_walk_budget;
};
/* ipa_node_params access functions. Please use these to access fields that
......
......@@ -5275,7 +5275,7 @@ eliminate_dom_walker::eliminate_stmt (basic_block b, gimple_stmt_iterator *gsi)
ipa_polymorphic_call_context context (current_function_decl,
fn, stmt, &instance);
context.get_dynamic_type (instance, OBJ_TYPE_REF_OBJECT (fn),
otr_type, stmt);
otr_type, stmt, NULL);
bool final;
vec <cgraph_node *> targets
= possible_polymorphic_call_targets (obj_type_ref_class (fn),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment