Commit 40a777e8 by Jan Hubicka Committed by Jan Hubicka

Improve effectivity of ipa_polymorphi_context cache.

        * ipa-fnsummary.c (set_cond_stmt_execution_predicate,
	set_switch_stmt_execution_predicate, compute_bb_predicates,
	will_be_nonconstant_expr_predicate,
	phi_result_unknown_predicate,
	analyze_function_body): Pass arround params summary.
	(ipa_call_context::duplicate_from): New comment;
	only duplicate useful values.
	(ipa_call_context::equal_to): Only compare useful values.
	(remap_edge_summaries): Pass params_summary.
	(remap_hint_predicate): Likewise.
	(ipa_merge_fn_summary_after_inlining): Likewise.
	(inline_read_section): Initialize params summary used flags.
	* ipa-predicate.c (predicate::remap_after_inlining): Pass
	around param_summary.
	(add_condition): Initialized used params summary flags.
	* ipa-predicate.h (inline_param_summary::equals_to): Make const.
	(inline_param_summary::useless_p): New predicate.
	(remap_after_inlining, add_condition): Update prototype
	* ipa-prop.c (ipa_populate_param_decls): Watch overflow in
	move_cost.
	(ipa_note_param_call): Add parameter POLYMORPHIC; update params
	summaries.
	(ipa_analyze_indirect_call_uses): Update use of ipa_note_param_call.
	(ipa_analyze_virtual_call_uses): Likewise.
	(update_indirect_edges_after_inlining): Update param summaries.
	(ipa_print_node_params): Print used flags.
	(ipa_read_indirect_edge_info): Update param summareis.
	* ipa-prop.h (ipa_param_descriptor): Add
	used_by_ipa_predicates, used_by_indirect_call
	and used_by_polymorphic_call.
	(ipa_set_param_used_by_ipa_predicates,
	ipa_set_param_used_by_indirect_call,
	ipa_set_param_used_by_polymorphic_call,
	ipa_is_param_used_by_ipa_predicates,
	ipa_is_param_used_by_indirect_call,
	ipa_is_param_used_by_polymorphic_call): New inline functions.

From-SVN: r277759
parent 4bcd578a
2019-11-02 Jan Hubicka <hubicka@ucw.cz> 2019-11-02 Jan Hubicka <hubicka@ucw.cz>
* ipa-fnsummary.c (set_cond_stmt_execution_predicate,
set_switch_stmt_execution_predicate, compute_bb_predicates,
will_be_nonconstant_expr_predicate,
phi_result_unknown_predicate,
analyze_function_body): Pass arround params summary.
(ipa_call_context::duplicate_from): New comment;
only duplicate useful values.
(ipa_call_context::equal_to): Only compare useful values.
(remap_edge_summaries): Pass params_summary.
(remap_hint_predicate): Likewise.
(ipa_merge_fn_summary_after_inlining): Likewise.
(inline_read_section): Initialize params summary used flags.
* ipa-predicate.c (predicate::remap_after_inlining): Pass
around param_summary.
(add_condition): Initialized used params summary flags.
* ipa-predicate.h (inline_param_summary::equals_to): Make const.
(inline_param_summary::useless_p): New predicate.
(remap_after_inlining, add_condition): Update prototype
* ipa-prop.c (ipa_populate_param_decls): Watch overflow in
move_cost.
(ipa_note_param_call): Add parameter POLYMORPHIC; update params
summaries.
(ipa_analyze_indirect_call_uses): Update use of ipa_note_param_call.
(ipa_analyze_virtual_call_uses): Likewise.
(update_indirect_edges_after_inlining): Update param summaries.
(ipa_print_node_params): Print used flags.
(ipa_read_indirect_edge_info): Update param summareis.
* ipa-prop.h (ipa_param_descriptor): Add
used_by_ipa_predicates, used_by_indirect_call
and used_by_polymorphic_call.
(ipa_set_param_used_by_ipa_predicates,
ipa_set_param_used_by_indirect_call,
ipa_set_param_used_by_polymorphic_call,
ipa_is_param_used_by_ipa_predicates,
ipa_is_param_used_by_indirect_call,
ipa_is_param_used_by_polymorphic_call): New inline functions.
2019-11-02 Jan Hubicka <hubicka@ucw.cz>
* ipa-fnsummary.c (ipa_call_context::duplicate_from): New * ipa-fnsummary.c (ipa_call_context::duplicate_from): New
member function. member function.
(ipa_call_context::release): Add ALL parameter. (ipa_call_context::release): Add ALL parameter.
...@@ -1312,6 +1312,7 @@ fail: ...@@ -1312,6 +1312,7 @@ fail:
static void static void
set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi, set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi,
class ipa_fn_summary *summary, class ipa_fn_summary *summary,
class ipa_node_params *params_summary,
basic_block bb) basic_block bb)
{ {
gimple *last; gimple *last;
...@@ -1354,7 +1355,8 @@ set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi, ...@@ -1354,7 +1355,8 @@ set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi,
&& !dominated_by_p (CDI_POST_DOMINATORS, bb, e->dest)) && !dominated_by_p (CDI_POST_DOMINATORS, bb, e->dest))
{ {
predicate p predicate p
= add_condition (summary, index, param_type, &aggpos, = add_condition (summary, params_summary, index,
param_type, &aggpos,
this_code, gimple_cond_rhs (last), param_ops); this_code, gimple_cond_rhs (last), param_ops);
e->aux = edge_predicate_pool.allocate (); e->aux = edge_predicate_pool.allocate ();
*(predicate *) e->aux = p; *(predicate *) e->aux = p;
...@@ -1387,7 +1389,8 @@ set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi, ...@@ -1387,7 +1389,8 @@ set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi,
return; return;
FOR_EACH_EDGE (e, ei, bb->succs) if (e->flags & EDGE_FALSE_VALUE) FOR_EACH_EDGE (e, ei, bb->succs) if (e->flags & EDGE_FALSE_VALUE)
{ {
predicate p = add_condition (summary, index, param_type, &aggpos, predicate p = add_condition (summary, params_summary, index,
param_type, &aggpos,
predicate::is_not_constant, NULL_TREE); predicate::is_not_constant, NULL_TREE);
e->aux = edge_predicate_pool.allocate (); e->aux = edge_predicate_pool.allocate ();
*(predicate *) e->aux = p; *(predicate *) e->aux = p;
...@@ -1401,6 +1404,7 @@ set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi, ...@@ -1401,6 +1404,7 @@ set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi,
static void static void
set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi, set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi,
class ipa_fn_summary *summary, class ipa_fn_summary *summary,
class ipa_node_params *params_summary,
basic_block bb) basic_block bb)
{ {
gimple *lastg; gimple *lastg;
...@@ -1470,15 +1474,15 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi, ...@@ -1470,15 +1474,15 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi,
if (dominated_by_p (CDI_POST_DOMINATORS, bb, e->dest)) if (dominated_by_p (CDI_POST_DOMINATORS, bb, e->dest))
p = true; p = true;
else if (min == max) else if (min == max)
p = add_condition (summary, index, param_type, &aggpos, EQ_EXPR, p = add_condition (summary, params_summary, index, param_type,
min, param_ops); &aggpos, EQ_EXPR, min, param_ops);
else else
{ {
predicate p1, p2; predicate p1, p2;
p1 = add_condition (summary, index, param_type, &aggpos, GE_EXPR, p1 = add_condition (summary, params_summary, index, param_type,
min, param_ops); &aggpos, GE_EXPR, min, param_ops);
p2 = add_condition (summary, index, param_type, &aggpos, LE_EXPR, p2 = add_condition (summary, params_summary,index, param_type,
max, param_ops); &aggpos, LE_EXPR, max, param_ops);
p = p1 & p2; p = p1 & p2;
} }
*(class predicate *) e->aux *(class predicate *) e->aux
...@@ -1559,7 +1563,8 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi, ...@@ -1559,7 +1563,8 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi,
tree max = ranges[i].second; tree max = ranges[i].second;
if (min == max) if (min == max)
p_seg &= add_condition (summary, index, param_type, &aggpos, NE_EXPR, p_seg &= add_condition (summary, params_summary, index,
param_type, &aggpos, NE_EXPR,
min, param_ops); min, param_ops);
else else
{ {
...@@ -1567,7 +1572,8 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi, ...@@ -1567,7 +1572,8 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi,
of switch index. */ of switch index. */
if (wi::lt_p (vr_wmin, wi::to_wide (min), TYPE_SIGN (type))) if (wi::lt_p (vr_wmin, wi::to_wide (min), TYPE_SIGN (type)))
{ {
p_seg &= add_condition (summary, index, param_type, &aggpos, p_seg &= add_condition (summary, params_summary, index,
param_type, &aggpos,
LT_EXPR, min, param_ops); LT_EXPR, min, param_ops);
p_all = p_all.or_with (summary->conds, p_seg); p_all = p_all.or_with (summary->conds, p_seg);
} }
...@@ -1580,7 +1586,8 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi, ...@@ -1580,7 +1586,8 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi,
break; break;
} }
p_seg = add_condition (summary, index, param_type, &aggpos, GT_EXPR, p_seg = add_condition (summary, params_summary, index,
param_type, &aggpos, GT_EXPR,
max, param_ops); max, param_ops);
} }
} }
...@@ -1599,7 +1606,8 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi, ...@@ -1599,7 +1606,8 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi,
static void static void
compute_bb_predicates (struct ipa_func_body_info *fbi, compute_bb_predicates (struct ipa_func_body_info *fbi,
struct cgraph_node *node, struct cgraph_node *node,
class ipa_fn_summary *summary) class ipa_fn_summary *summary,
class ipa_node_params *params_summary)
{ {
struct function *my_function = DECL_STRUCT_FUNCTION (node->decl); struct function *my_function = DECL_STRUCT_FUNCTION (node->decl);
bool done = false; bool done = false;
...@@ -1607,8 +1615,8 @@ compute_bb_predicates (struct ipa_func_body_info *fbi, ...@@ -1607,8 +1615,8 @@ compute_bb_predicates (struct ipa_func_body_info *fbi,
FOR_EACH_BB_FN (bb, my_function) FOR_EACH_BB_FN (bb, my_function)
{ {
set_cond_stmt_execution_predicate (fbi, summary, bb); set_cond_stmt_execution_predicate (fbi, summary, params_summary, bb);
set_switch_stmt_execution_predicate (fbi, summary, bb); set_switch_stmt_execution_predicate (fbi, summary, params_summary, bb);
} }
/* Entry block is always executable. */ /* Entry block is always executable. */
...@@ -1701,6 +1709,7 @@ compute_bb_predicates (struct ipa_func_body_info *fbi, ...@@ -1701,6 +1709,7 @@ compute_bb_predicates (struct ipa_func_body_info *fbi,
static predicate static predicate
will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi, will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi,
class ipa_fn_summary *summary, class ipa_fn_summary *summary,
class ipa_node_params *params_summary,
tree expr, tree expr,
vec<predicate> nonconstant_names) vec<predicate> nonconstant_names)
{ {
...@@ -1712,7 +1721,7 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi, ...@@ -1712,7 +1721,7 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi,
parm = unmodified_parm (fbi, NULL, expr, NULL); parm = unmodified_parm (fbi, NULL, expr, NULL);
if (parm && (index = ipa_get_param_decl_index (fbi->info, parm)) >= 0) if (parm && (index = ipa_get_param_decl_index (fbi->info, parm)) >= 0)
return add_condition (summary, index, TREE_TYPE (parm), NULL, return add_condition (summary, params_summary, index, TREE_TYPE (parm), NULL,
predicate::changed, NULL_TREE); predicate::changed, NULL_TREE);
if (is_gimple_min_invariant (expr)) if (is_gimple_min_invariant (expr))
return false; return false;
...@@ -1722,6 +1731,7 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi, ...@@ -1722,6 +1731,7 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi,
{ {
predicate p1 predicate p1
= will_be_nonconstant_expr_predicate (fbi, summary, = will_be_nonconstant_expr_predicate (fbi, summary,
params_summary,
TREE_OPERAND (expr, 0), TREE_OPERAND (expr, 0),
nonconstant_names); nonconstant_names);
if (p1 == true) if (p1 == true)
...@@ -1729,6 +1739,7 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi, ...@@ -1729,6 +1739,7 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi,
predicate p2 predicate p2
= will_be_nonconstant_expr_predicate (fbi, summary, = will_be_nonconstant_expr_predicate (fbi, summary,
params_summary,
TREE_OPERAND (expr, 1), TREE_OPERAND (expr, 1),
nonconstant_names); nonconstant_names);
return p1.or_with (summary->conds, p2); return p1.or_with (summary->conds, p2);
...@@ -1737,6 +1748,7 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi, ...@@ -1737,6 +1748,7 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi,
{ {
predicate p1 predicate p1
= will_be_nonconstant_expr_predicate (fbi, summary, = will_be_nonconstant_expr_predicate (fbi, summary,
params_summary,
TREE_OPERAND (expr, 0), TREE_OPERAND (expr, 0),
nonconstant_names); nonconstant_names);
if (p1 == true) if (p1 == true)
...@@ -1744,12 +1756,14 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi, ...@@ -1744,12 +1756,14 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi,
predicate p2 predicate p2
= will_be_nonconstant_expr_predicate (fbi, summary, = will_be_nonconstant_expr_predicate (fbi, summary,
params_summary,
TREE_OPERAND (expr, 1), TREE_OPERAND (expr, 1),
nonconstant_names); nonconstant_names);
if (p2 == true) if (p2 == true)
return p2; return p2;
p1 = p1.or_with (summary->conds, p2); p1 = p1.or_with (summary->conds, p2);
p2 = will_be_nonconstant_expr_predicate (fbi, summary, p2 = will_be_nonconstant_expr_predicate (fbi, summary,
params_summary,
TREE_OPERAND (expr, 2), TREE_OPERAND (expr, 2),
nonconstant_names); nonconstant_names);
return p2.or_with (summary->conds, p1); return p2.or_with (summary->conds, p1);
...@@ -1771,6 +1785,7 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi, ...@@ -1771,6 +1785,7 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi,
static predicate static predicate
will_be_nonconstant_predicate (struct ipa_func_body_info *fbi, will_be_nonconstant_predicate (struct ipa_func_body_info *fbi,
class ipa_fn_summary *summary, class ipa_fn_summary *summary,
class ipa_node_params *params_summary,
gimple *stmt, gimple *stmt,
vec<predicate> nonconstant_names) vec<predicate> nonconstant_names)
{ {
...@@ -1828,7 +1843,8 @@ will_be_nonconstant_predicate (struct ipa_func_body_info *fbi, ...@@ -1828,7 +1843,8 @@ will_be_nonconstant_predicate (struct ipa_func_body_info *fbi,
if (is_load) if (is_load)
op_non_const = op_non_const =
add_condition (summary, base_index, param_type, &aggpos, add_condition (summary, params_summary,
base_index, param_type, &aggpos,
predicate::changed, NULL_TREE); predicate::changed, NULL_TREE);
else else
op_non_const = false; op_non_const = false;
...@@ -1840,7 +1856,8 @@ will_be_nonconstant_predicate (struct ipa_func_body_info *fbi, ...@@ -1840,7 +1856,8 @@ will_be_nonconstant_predicate (struct ipa_func_body_info *fbi,
if (parm && (index = ipa_get_param_decl_index (fbi->info, parm)) >= 0) if (parm && (index = ipa_get_param_decl_index (fbi->info, parm)) >= 0)
{ {
if (index != base_index) if (index != base_index)
p = add_condition (summary, index, TREE_TYPE (parm), NULL, p = add_condition (summary, params_summary, index,
TREE_TYPE (parm), NULL,
predicate::changed, NULL_TREE); predicate::changed, NULL_TREE);
else else
continue; continue;
...@@ -2027,7 +2044,9 @@ param_change_prob (ipa_func_body_info *fbi, gimple *stmt, int i) ...@@ -2027,7 +2044,9 @@ param_change_prob (ipa_func_body_info *fbi, gimple *stmt, int i)
static bool static bool
phi_result_unknown_predicate (ipa_func_body_info *fbi, phi_result_unknown_predicate (ipa_func_body_info *fbi,
ipa_fn_summary *summary, basic_block bb, ipa_fn_summary *summary,
class ipa_node_params *params_summary,
basic_block bb,
predicate *p, predicate *p,
vec<predicate> nonconstant_names) vec<predicate> nonconstant_names)
{ {
...@@ -2071,7 +2090,7 @@ phi_result_unknown_predicate (ipa_func_body_info *fbi, ...@@ -2071,7 +2090,7 @@ phi_result_unknown_predicate (ipa_func_body_info *fbi,
|| !is_gimple_ip_invariant (gimple_cond_rhs (stmt))) || !is_gimple_ip_invariant (gimple_cond_rhs (stmt)))
return false; return false;
*p = will_be_nonconstant_expr_predicate (fbi, summary, *p = will_be_nonconstant_expr_predicate (fbi, summary, params_summary,
gimple_cond_lhs (stmt), gimple_cond_lhs (stmt),
nonconstant_names); nonconstant_names);
if (*p == true) if (*p == true)
...@@ -2264,6 +2283,7 @@ analyze_function_body (struct cgraph_node *node, bool early) ...@@ -2264,6 +2283,7 @@ analyze_function_body (struct cgraph_node *node, bool early)
struct function *my_function = DECL_STRUCT_FUNCTION (node->decl); struct function *my_function = DECL_STRUCT_FUNCTION (node->decl);
sreal freq; sreal freq;
class ipa_fn_summary *info = ipa_fn_summaries->get_create (node); class ipa_fn_summary *info = ipa_fn_summaries->get_create (node);
class ipa_node_params *params_summary = early ? NULL : IPA_NODE_REF (node);
predicate bb_predicate; predicate bb_predicate;
struct ipa_func_body_info fbi; struct ipa_func_body_info fbi;
vec<predicate> nonconstant_names = vNULL; vec<predicate> nonconstant_names = vNULL;
...@@ -2329,7 +2349,7 @@ analyze_function_body (struct cgraph_node *node, bool early) ...@@ -2329,7 +2349,7 @@ analyze_function_body (struct cgraph_node *node, bool early)
bb_predicate); bb_predicate);
if (fbi.info) if (fbi.info)
compute_bb_predicates (&fbi, node, info); compute_bb_predicates (&fbi, node, info, params_summary);
order = XNEWVEC (int, n_basic_blocks_for_fn (cfun)); order = XNEWVEC (int, n_basic_blocks_for_fn (cfun));
nblocks = pre_and_rev_post_order_compute (NULL, order, false); nblocks = pre_and_rev_post_order_compute (NULL, order, false);
for (n = 0; n < nblocks; n++) for (n = 0; n < nblocks; n++)
...@@ -2371,7 +2391,9 @@ analyze_function_body (struct cgraph_node *node, bool early) ...@@ -2371,7 +2391,9 @@ analyze_function_body (struct cgraph_node *node, bool early)
gsi_next (&bsi)) gsi_next (&bsi))
{ {
if (first_phi if (first_phi
&& !phi_result_unknown_predicate (&fbi, info, bb, && !phi_result_unknown_predicate (&fbi, info,
params_summary,
bb,
&phi_predicate, &phi_predicate,
nonconstant_names)) nonconstant_names))
break; break;
...@@ -2469,7 +2491,7 @@ analyze_function_body (struct cgraph_node *node, bool early) ...@@ -2469,7 +2491,7 @@ analyze_function_body (struct cgraph_node *node, bool early)
just maximum of the possible paths. */ just maximum of the possible paths. */
if (fbi.info) if (fbi.info)
will_be_nonconstant will_be_nonconstant
= will_be_nonconstant_predicate (&fbi, info, = will_be_nonconstant_predicate (&fbi, info, params_summary,
stmt, nonconstant_names); stmt, nonconstant_names);
else else
will_be_nonconstant = true; will_be_nonconstant = true;
...@@ -2536,7 +2558,8 @@ analyze_function_body (struct cgraph_node *node, bool early) ...@@ -2536,7 +2558,8 @@ analyze_function_body (struct cgraph_node *node, bool early)
predicate p = bb_predicate; predicate p = bb_predicate;
if (fbi.info) if (fbi.info)
p = p & will_be_nonconstant_expr_predicate p = p & will_be_nonconstant_expr_predicate
(&fbi, info, TREE_OPERAND (op, 1), (&fbi, info, params_summary,
TREE_OPERAND (op, 1),
nonconstant_names); nonconstant_names);
if (p != false) if (p != false)
{ {
...@@ -2581,6 +2604,7 @@ analyze_function_body (struct cgraph_node *node, bool early) ...@@ -2581,6 +2604,7 @@ analyze_function_body (struct cgraph_node *node, bool early)
{ {
predicate will_be_nonconstant predicate will_be_nonconstant
= will_be_nonconstant_expr_predicate (&fbi, info, = will_be_nonconstant_expr_predicate (&fbi, info,
params_summary,
niter_desc.niter, niter_desc.niter,
nonconstant_names); nonconstant_names);
if (will_be_nonconstant != true) if (will_be_nonconstant != true)
...@@ -2625,7 +2649,9 @@ analyze_function_body (struct cgraph_node *node, bool early) ...@@ -2625,7 +2649,9 @@ analyze_function_body (struct cgraph_node *node, bool early)
continue; continue;
predicate will_be_nonconstant predicate will_be_nonconstant
= will_be_nonconstant_expr_predicate (&fbi, info, iv.step, = will_be_nonconstant_expr_predicate (&fbi, info,
params_summary,
iv.step,
nonconstant_names); nonconstant_names);
if (will_be_nonconstant != true) if (will_be_nonconstant != true)
will_be_nonconstant = bb_predicate & will_be_nonconstant; will_be_nonconstant = bb_predicate & will_be_nonconstant;
...@@ -2964,29 +2990,73 @@ ipa_call_context::ipa_call_context (cgraph_node *node, ...@@ -2964,29 +2990,73 @@ ipa_call_context::ipa_call_context (cgraph_node *node,
{ {
} }
/* Set THIS to be a duplicate of CTX. Copy all relevant info. */
void void
ipa_call_context::duplicate_from (const ipa_call_context &ctx) ipa_call_context::duplicate_from (const ipa_call_context &ctx)
{ {
m_node = ctx.m_node; m_node = ctx.m_node;
m_possible_truths = ctx.m_possible_truths; m_possible_truths = ctx.m_possible_truths;
m_nonspec_possible_truths = ctx.m_nonspec_possible_truths; m_nonspec_possible_truths = ctx.m_nonspec_possible_truths;
class ipa_node_params *params_summary = IPA_NODE_REF (m_node);
unsigned int nargs = ipa_get_param_count (params_summary);
if (ctx.m_inline_param_summary.exists ())
m_inline_param_summary = ctx.m_inline_param_summary.copy ();
else
m_inline_param_summary = vNULL; m_inline_param_summary = vNULL;
/* Copy the info only if there is at least one useful entry. */
if (ctx.m_inline_param_summary.exists ())
{
unsigned int n = MIN (ctx.m_inline_param_summary.length (), nargs);
for (unsigned int i = 0; i < n; i++)
if (ipa_is_param_used_by_ipa_predicates (params_summary, i)
&& !ctx.m_inline_param_summary[i].useless_p ())
{
m_inline_param_summary
= ctx.m_inline_param_summary.copy ();
break;
}
}
m_known_vals = vNULL;
if (ctx.m_known_vals.exists ()) if (ctx.m_known_vals.exists ())
{
unsigned int n = MIN (ctx.m_known_vals.length (), nargs);
for (unsigned int i = 0; i < n; i++)
if (ipa_is_param_used_by_indirect_call (params_summary, i)
&& ctx.m_known_vals[i])
{
m_known_vals = ctx.m_known_vals.copy (); m_known_vals = ctx.m_known_vals.copy ();
else break;
m_known_vals = vNULL; }
}
m_known_contexts = vNULL;
if (ctx.m_known_contexts.exists ()) if (ctx.m_known_contexts.exists ())
{
unsigned int n = MIN (ctx.m_known_contexts.length (), nargs);
for (unsigned int i = 0; i < n; i++)
if (ipa_is_param_used_by_polymorphic_call (params_summary, i)
&& !ctx.m_known_contexts[i].useless_p ())
{
m_known_contexts = ctx.m_known_contexts.copy (); m_known_contexts = ctx.m_known_contexts.copy ();
else break;
m_known_contexts = vNULL; }
}
m_known_aggs = vNULL;
if (ctx.m_known_aggs.exists ()) if (ctx.m_known_aggs.exists ())
{
unsigned int n = MIN (ctx.m_known_aggs.length (), nargs);
for (unsigned int i = 0; i < n; i++)
if (ipa_is_param_used_by_indirect_call (params_summary, i)
&& ctx.m_known_aggs[i])
{
m_known_aggs = ctx.m_known_aggs.copy (); m_known_aggs = ctx.m_known_aggs.copy ();
else break;
m_known_aggs = vNULL; }
}
} }
/* Release memory used by known_vals/contexts/aggs vectors. /* Release memory used by known_vals/contexts/aggs vectors.
...@@ -3016,50 +3086,108 @@ ipa_call_context::equal_to (const ipa_call_context &ctx) ...@@ -3016,50 +3086,108 @@ ipa_call_context::equal_to (const ipa_call_context &ctx)
|| m_possible_truths != ctx.m_possible_truths || m_possible_truths != ctx.m_possible_truths
|| m_nonspec_possible_truths != ctx.m_nonspec_possible_truths) || m_nonspec_possible_truths != ctx.m_nonspec_possible_truths)
return false; return false;
if (m_inline_param_summary.exists () != ctx.m_inline_param_summary.exists ()
|| m_known_vals.exists () != ctx.m_known_vals.exists() class ipa_node_params *params_summary = IPA_NODE_REF (m_node);
|| m_known_contexts.exists () != ctx.m_known_contexts.exists () unsigned int nargs = ipa_get_param_count (params_summary);
|| m_known_aggs.exists () != ctx.m_known_aggs.exists ())
if (m_inline_param_summary.exists () || ctx.m_inline_param_summary.exists ())
{
for (unsigned int i = 0; i < nargs; i++)
{
if (!ipa_is_param_used_by_ipa_predicates (params_summary, i))
continue;
if (i >= m_inline_param_summary.length ()
|| m_inline_param_summary[i].useless_p ())
{
if (i < ctx.m_inline_param_summary.length ()
&& !ctx.m_inline_param_summary[i].useless_p ())
return false; return false;
if (m_inline_param_summary.exists ()) continue;
}
if (i >= ctx.m_inline_param_summary.length ()
|| ctx.m_inline_param_summary[i].useless_p ())
{ {
if (m_inline_param_summary.length () != ctx.m_inline_param_summary.length ()) if (i < m_inline_param_summary.length ()
&& !m_inline_param_summary[i].useless_p ())
return false; return false;
for (unsigned int i = 0; i < m_inline_param_summary.length (); i++) continue;
if (!m_inline_param_summary[i].equal_to (ctx.m_inline_param_summary[i])) }
if (!m_inline_param_summary[i].equal_to
(ctx.m_inline_param_summary[i]))
return false; return false;
} }
if (m_known_vals.exists ()) }
if (m_known_vals.exists () || ctx.m_known_vals.exists ())
{
for (unsigned int i = 0; i < nargs; i++)
{
if (!ipa_is_param_used_by_indirect_call (params_summary, i))
continue;
if (i >= m_known_vals.length () || !m_known_vals[i])
{ {
if (m_known_vals.length () != ctx.m_known_vals.length ()) if (i < ctx.m_known_vals.length () && ctx.m_known_vals[i])
return false; return false;
for (unsigned int i = 0; i < m_known_vals.length (); i++) continue;
}
if (i >= ctx.m_known_vals.length () || !ctx.m_known_vals[i])
{ {
tree t1 = m_known_vals[i]; if (i < m_known_vals.length () && m_known_vals[i])
tree t2 = ctx.m_known_vals[i]; return false;
continue;
if (t1 != t2 }
&& (!t1 || !t2 || !operand_equal_p (m_known_vals[i], if (m_known_vals[i] != ctx.m_known_vals[i])
ctx.m_known_vals[i], 0)))
return false; return false;
} }
} }
if (m_known_contexts.exists ()) if (m_known_contexts.exists () || ctx.m_known_contexts.exists ())
{
for (unsigned int i = 0; i < nargs; i++)
{
if (!ipa_is_param_used_by_polymorphic_call (params_summary, i))
continue;
if (i >= m_known_contexts.length ()
|| m_known_contexts[i].useless_p ())
{ {
if (m_known_contexts.length () != ctx.m_known_contexts.length ()) if (i < ctx.m_known_contexts.length ()
&& !ctx.m_known_contexts[i].useless_p ())
return false; return false;
for (unsigned int i = 0; i < m_known_contexts.length (); i++) continue;
if (!m_known_contexts[i].equal_to (ctx.m_known_contexts[i])) }
if (i >= ctx.m_known_contexts.length ()
|| ctx.m_known_contexts[i].useless_p ())
{
if (i < m_known_contexts.length ()
&& !m_known_contexts[i].useless_p ())
return false; return false;
continue;
}
if (!m_known_contexts[i].equal_to
(ctx.m_known_contexts[i]))
return false;
}
} }
if (m_known_aggs.exists ()) if (m_known_aggs.exists () || ctx.m_known_aggs.exists ())
{ {
if (m_known_aggs.length () != ctx.m_known_aggs.length ()) for (unsigned int i = 0; i < nargs; i++)
{
if (!ipa_is_param_used_by_indirect_call (params_summary, i))
continue;
if (i >= m_known_aggs.length () || !m_known_aggs[i])
{
if (i < ctx.m_known_aggs.length () && ctx.m_known_aggs[i])
return false;
continue;
}
if (i >= ctx.m_known_aggs.length () || !ctx.m_known_aggs[i])
{
if (i < m_known_aggs.length () && m_known_aggs[i])
return false; return false;
for (unsigned int i = 0; i < m_known_aggs.length (); i++) continue;
if (!m_known_aggs[i]->equal_to (*ctx.m_known_aggs[i])) }
if (m_known_aggs[i] != ctx.m_known_aggs[i])
return false; return false;
} }
}
return true; return true;
} }
...@@ -3319,6 +3447,7 @@ static void ...@@ -3319,6 +3447,7 @@ static void
remap_edge_summaries (struct cgraph_edge *inlined_edge, remap_edge_summaries (struct cgraph_edge *inlined_edge,
struct cgraph_node *node, struct cgraph_node *node,
class ipa_fn_summary *info, class ipa_fn_summary *info,
class ipa_node_params *params_summary,
class ipa_fn_summary *callee_info, class ipa_fn_summary *callee_info,
vec<int> operand_map, vec<int> operand_map,
vec<int> offset_map, vec<int> offset_map,
...@@ -3339,7 +3468,8 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge, ...@@ -3339,7 +3468,8 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge,
if (es->predicate) if (es->predicate)
{ {
p = es->predicate->remap_after_inlining p = es->predicate->remap_after_inlining
(info, callee_info, operand_map, (info, params_summary,
callee_info, operand_map,
offset_map, possible_truths, offset_map, possible_truths,
*toplev_predicate); *toplev_predicate);
edge_set_predicate (e, &p); edge_set_predicate (e, &p);
...@@ -3348,7 +3478,8 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge, ...@@ -3348,7 +3478,8 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge,
edge_set_predicate (e, toplev_predicate); edge_set_predicate (e, toplev_predicate);
} }
else else
remap_edge_summaries (inlined_edge, e->callee, info, callee_info, remap_edge_summaries (inlined_edge, e->callee, info,
params_summary, callee_info,
operand_map, offset_map, possible_truths, operand_map, offset_map, possible_truths,
toplev_predicate); toplev_predicate);
} }
...@@ -3362,7 +3493,8 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge, ...@@ -3362,7 +3493,8 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge,
if (es->predicate) if (es->predicate)
{ {
p = es->predicate->remap_after_inlining p = es->predicate->remap_after_inlining
(info, callee_info, operand_map, offset_map, (info, params_summary,
callee_info, operand_map, offset_map,
possible_truths, *toplev_predicate); possible_truths, *toplev_predicate);
edge_set_predicate (e, &p); edge_set_predicate (e, &p);
} }
...@@ -3375,6 +3507,7 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge, ...@@ -3375,6 +3507,7 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge,
static void static void
remap_hint_predicate (class ipa_fn_summary *info, remap_hint_predicate (class ipa_fn_summary *info,
class ipa_node_params *params_summary,
class ipa_fn_summary *callee_info, class ipa_fn_summary *callee_info,
predicate **hint, predicate **hint,
vec<int> operand_map, vec<int> operand_map,
...@@ -3387,7 +3520,7 @@ remap_hint_predicate (class ipa_fn_summary *info, ...@@ -3387,7 +3520,7 @@ remap_hint_predicate (class ipa_fn_summary *info,
if (!*hint) if (!*hint)
return; return;
p = (*hint)->remap_after_inlining p = (*hint)->remap_after_inlining
(info, callee_info, (info, params_summary, callee_info,
operand_map, offset_map, operand_map, offset_map,
possible_truths, *toplev_predicate); possible_truths, *toplev_predicate);
if (p != false && p != true) if (p != false && p != true)
...@@ -3415,6 +3548,8 @@ ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge) ...@@ -3415,6 +3548,8 @@ ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge)
int i; int i;
predicate toplev_predicate; predicate toplev_predicate;
class ipa_call_summary *es = ipa_call_summaries->get (edge); class ipa_call_summary *es = ipa_call_summaries->get (edge);
class ipa_node_params *params_summary = (ipa_node_params_sum
? IPA_NODE_REF (to) : NULL);
if (es->predicate) if (es->predicate)
toplev_predicate = *es->predicate; toplev_predicate = *es->predicate;
...@@ -3461,19 +3596,21 @@ ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge) ...@@ -3461,19 +3596,21 @@ ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge)
} }
} }
operand_map[i] = map; operand_map[i] = map;
gcc_assert (map < ipa_get_param_count (IPA_NODE_REF (to))); gcc_assert (map < ipa_get_param_count (params_summary));
} }
} }
for (i = 0; vec_safe_iterate (callee_info->size_time_table, i, &e); i++) for (i = 0; vec_safe_iterate (callee_info->size_time_table, i, &e); i++)
{ {
predicate p; predicate p;
p = e->exec_predicate.remap_after_inlining p = e->exec_predicate.remap_after_inlining
(info, callee_info, operand_map, (info, params_summary,
callee_info, operand_map,
offset_map, clause, offset_map, clause,
toplev_predicate); toplev_predicate);
predicate nonconstp; predicate nonconstp;
nonconstp = e->nonconst_predicate.remap_after_inlining nonconstp = e->nonconst_predicate.remap_after_inlining
(info, callee_info, operand_map, (info, params_summary,
callee_info, operand_map,
offset_map, clause, offset_map, clause,
toplev_predicate); toplev_predicate);
if (p != false && nonconstp != false) if (p != false && nonconstp != false)
...@@ -3491,12 +3628,13 @@ ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge) ...@@ -3491,12 +3628,13 @@ ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge)
info->account_size_time (e->size, add_time, p, nonconstp); info->account_size_time (e->size, add_time, p, nonconstp);
} }
} }
remap_edge_summaries (edge, edge->callee, info, callee_info, operand_map, remap_edge_summaries (edge, edge->callee, info, params_summary,
callee_info, operand_map,
offset_map, clause, &toplev_predicate); offset_map, clause, &toplev_predicate);
remap_hint_predicate (info, callee_info, remap_hint_predicate (info, params_summary, callee_info,
&callee_info->loop_iterations, &callee_info->loop_iterations,
operand_map, offset_map, clause, &toplev_predicate); operand_map, offset_map, clause, &toplev_predicate);
remap_hint_predicate (info, callee_info, remap_hint_predicate (info, params_summary, callee_info,
&callee_info->loop_stride, &callee_info->loop_stride,
operand_map, offset_map, clause, &toplev_predicate); operand_map, offset_map, clause, &toplev_predicate);
...@@ -3687,6 +3825,7 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data, ...@@ -3687,6 +3825,7 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data,
unsigned int index; unsigned int index;
struct cgraph_node *node; struct cgraph_node *node;
class ipa_fn_summary *info; class ipa_fn_summary *info;
class ipa_node_params *params_summary;
class ipa_size_summary *size_info; class ipa_size_summary *size_info;
lto_symtab_encoder_t encoder; lto_symtab_encoder_t encoder;
struct bitpack_d bp; struct bitpack_d bp;
...@@ -3698,6 +3837,7 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data, ...@@ -3698,6 +3837,7 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data,
node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref (encoder, node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref (encoder,
index)); index));
info = node->prevailing_p () ? ipa_fn_summaries->get_create (node) : NULL; info = node->prevailing_p () ? ipa_fn_summaries->get_create (node) : NULL;
params_summary = node->prevailing_p () ? IPA_NODE_REF (node) : NULL;
size_info = node->prevailing_p () size_info = node->prevailing_p ()
? ipa_size_summaries->get_create (node) : NULL; ? ipa_size_summaries->get_create (node) : NULL;
...@@ -3746,6 +3886,9 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data, ...@@ -3746,6 +3886,9 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data,
c.param_ops = NULL; c.param_ops = NULL;
if (info) if (info)
vec_safe_reserve_exact (c.param_ops, count3); vec_safe_reserve_exact (c.param_ops, count3);
if (params_summary)
ipa_set_param_used_by_ipa_predicates
(params_summary, c.operand_num, true);
for (k = 0; k < count3; k++) for (k = 0; k < count3; k++)
{ {
struct expr_eval_op op; struct expr_eval_op op;
......
...@@ -505,6 +505,7 @@ predicate::remap_after_duplication (clause_t possible_truths) ...@@ -505,6 +505,7 @@ predicate::remap_after_duplication (clause_t possible_truths)
predicate predicate
predicate::remap_after_inlining (class ipa_fn_summary *info, predicate::remap_after_inlining (class ipa_fn_summary *info,
class ipa_node_params *params_summary,
class ipa_fn_summary *callee_info, class ipa_fn_summary *callee_info,
vec<int> operand_map, vec<int> operand_map,
vec<int> offset_map, vec<int> offset_map,
...@@ -566,7 +567,7 @@ predicate::remap_after_inlining (class ipa_fn_summary *info, ...@@ -566,7 +567,7 @@ predicate::remap_after_inlining (class ipa_fn_summary *info,
ap.offset = c->offset + offset_delta; ap.offset = c->offset + offset_delta;
ap.agg_contents = c->agg_contents; ap.agg_contents = c->agg_contents;
ap.by_ref = c->by_ref; ap.by_ref = c->by_ref;
cond_predicate = add_condition (info, cond_predicate = add_condition (info, params_summary,
operand_map[c->operand_num], operand_map[c->operand_num],
c->type, &ap, c->code, c->type, &ap, c->code,
c->val, c->param_ops); c->val, c->param_ops);
...@@ -629,7 +630,9 @@ predicate::stream_out (struct output_block *ob) ...@@ -629,7 +630,9 @@ predicate::stream_out (struct output_block *ob)
aggregate. */ aggregate. */
predicate predicate
add_condition (class ipa_fn_summary *summary, int operand_num, add_condition (class ipa_fn_summary *summary,
class ipa_node_params *params_summary,
int operand_num,
tree type, struct agg_position_info *aggpos, tree type, struct agg_position_info *aggpos,
enum tree_code code, tree val, expr_eval_ops param_ops) enum tree_code code, tree val, expr_eval_ops param_ops)
{ {
...@@ -640,6 +643,9 @@ add_condition (class ipa_fn_summary *summary, int operand_num, ...@@ -640,6 +643,9 @@ add_condition (class ipa_fn_summary *summary, int operand_num,
bool agg_contents, by_ref; bool agg_contents, by_ref;
expr_eval_op *op; expr_eval_op *op;
if (params_summary)
ipa_set_param_used_by_ipa_predicates (params_summary, operand_num, true);
if (aggpos) if (aggpos)
{ {
offset = aggpos->offset; offset = aggpos->offset;
......
...@@ -77,10 +77,14 @@ struct inline_param_summary ...@@ -77,10 +77,14 @@ struct inline_param_summary
Value 0 is reserved for compile time invariants. */ Value 0 is reserved for compile time invariants. */
int change_prob; int change_prob;
bool equal_to (const inline_param_summary &other) bool equal_to (const inline_param_summary &other) const
{ {
return change_prob == other.change_prob; return change_prob == other.change_prob;
} }
bool useless_p (void) const
{
return change_prob == REG_BR_PROB_BASE;
}
}; };
typedef vec<condition, va_gc> *conditions; typedef vec<condition, va_gc> *conditions;
...@@ -233,6 +237,7 @@ public: ...@@ -233,6 +237,7 @@ public:
/* Return predicate equal to THIS after inlining. */ /* Return predicate equal to THIS after inlining. */
predicate remap_after_inlining (class ipa_fn_summary *, predicate remap_after_inlining (class ipa_fn_summary *,
class ipa_node_params *params_summary,
class ipa_fn_summary *, class ipa_fn_summary *,
vec<int>, vec<int>, clause_t, const predicate &); vec<int>, vec<int>, clause_t, const predicate &);
...@@ -254,7 +259,9 @@ private: ...@@ -254,7 +259,9 @@ private:
}; };
void dump_condition (FILE *f, conditions conditions, int cond); void dump_condition (FILE *f, conditions conditions, int cond);
predicate add_condition (class ipa_fn_summary *summary, int operand_num, predicate add_condition (class ipa_fn_summary *summary,
class ipa_node_params *params_summary,
int operand_num,
tree type, struct agg_position_info *aggpos, tree type, struct agg_position_info *aggpos,
enum tree_code code, tree val, enum tree_code code, tree val,
expr_eval_ops param_ops = NULL); expr_eval_ops param_ops = NULL);
...@@ -227,8 +227,10 @@ ipa_populate_param_decls (struct cgraph_node *node, ...@@ -227,8 +227,10 @@ ipa_populate_param_decls (struct cgraph_node *node,
for (parm = fnargs; parm; parm = DECL_CHAIN (parm)) for (parm = fnargs; parm; parm = DECL_CHAIN (parm))
{ {
descriptors[param_num].decl_or_type = parm; descriptors[param_num].decl_or_type = parm;
descriptors[param_num].move_cost = estimate_move_cost (TREE_TYPE (parm), unsigned int cost = estimate_move_cost (TREE_TYPE (parm), true);
true); descriptors[param_num].move_cost = cost;
/* Watch overflow, move_cost is a bitfield. */
gcc_checking_assert (cost == descriptors[param_num].move_cost);
param_num++; param_num++;
} }
} }
...@@ -2116,11 +2118,12 @@ ipa_is_ssa_with_stmt_def (tree t) ...@@ -2116,11 +2118,12 @@ ipa_is_ssa_with_stmt_def (tree t)
/* Find the indirect call graph edge corresponding to STMT and mark it as a /* Find the indirect call graph edge corresponding to STMT and mark it as a
call to a parameter number PARAM_INDEX. NODE is the caller. Return the call to a parameter number PARAM_INDEX. NODE is the caller. Return the
indirect call graph edge. */ indirect call graph edge.
If POLYMORPHIC is true record is as a destination of polymorphic call. */
static struct cgraph_edge * static struct cgraph_edge *
ipa_note_param_call (struct cgraph_node *node, int param_index, ipa_note_param_call (struct cgraph_node *node, int param_index,
gcall *stmt) gcall *stmt, bool polymorphic)
{ {
struct cgraph_edge *cs; struct cgraph_edge *cs;
...@@ -2129,6 +2132,11 @@ ipa_note_param_call (struct cgraph_node *node, int param_index, ...@@ -2129,6 +2132,11 @@ ipa_note_param_call (struct cgraph_node *node, int param_index,
cs->indirect_info->agg_contents = 0; cs->indirect_info->agg_contents = 0;
cs->indirect_info->member_ptr = 0; cs->indirect_info->member_ptr = 0;
cs->indirect_info->guaranteed_unmodified = 0; cs->indirect_info->guaranteed_unmodified = 0;
ipa_set_param_used_by_indirect_call (IPA_NODE_REF (node),
param_index, true);
if (cs->indirect_info->polymorphic || polymorphic)
ipa_set_param_used_by_polymorphic_call
(IPA_NODE_REF (node), param_index, true);
return cs; return cs;
} }
...@@ -2204,7 +2212,7 @@ ipa_analyze_indirect_call_uses (struct ipa_func_body_info *fbi, gcall *call, ...@@ -2204,7 +2212,7 @@ ipa_analyze_indirect_call_uses (struct ipa_func_body_info *fbi, gcall *call,
tree var = SSA_NAME_VAR (target); tree var = SSA_NAME_VAR (target);
int index = ipa_get_param_decl_index (info, var); int index = ipa_get_param_decl_index (info, var);
if (index >= 0) if (index >= 0)
ipa_note_param_call (fbi->node, index, call); ipa_note_param_call (fbi->node, index, call, false);
return; return;
} }
...@@ -2216,7 +2224,8 @@ ipa_analyze_indirect_call_uses (struct ipa_func_body_info *fbi, gcall *call, ...@@ -2216,7 +2224,8 @@ ipa_analyze_indirect_call_uses (struct ipa_func_body_info *fbi, gcall *call,
gimple_assign_rhs1 (def), &index, &offset, gimple_assign_rhs1 (def), &index, &offset,
NULL, &by_ref, &guaranteed_unmodified)) NULL, &by_ref, &guaranteed_unmodified))
{ {
struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index, call); struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index,
call, false);
cs->indirect_info->offset = offset; cs->indirect_info->offset = offset;
cs->indirect_info->agg_contents = 1; cs->indirect_info->agg_contents = 1;
cs->indirect_info->by_ref = by_ref; cs->indirect_info->by_ref = by_ref;
...@@ -2317,7 +2326,8 @@ ipa_analyze_indirect_call_uses (struct ipa_func_body_info *fbi, gcall *call, ...@@ -2317,7 +2326,8 @@ ipa_analyze_indirect_call_uses (struct ipa_func_body_info *fbi, gcall *call,
if (index >= 0 if (index >= 0
&& parm_preserved_before_stmt_p (fbi, index, call, rec)) && parm_preserved_before_stmt_p (fbi, index, call, rec))
{ {
struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index, call); struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index,
call, false);
cs->indirect_info->offset = offset; cs->indirect_info->offset = offset;
cs->indirect_info->agg_contents = 1; cs->indirect_info->agg_contents = 1;
cs->indirect_info->member_ptr = 1; cs->indirect_info->member_ptr = 1;
...@@ -2377,7 +2387,8 @@ ipa_analyze_virtual_call_uses (struct ipa_func_body_info *fbi, ...@@ -2377,7 +2387,8 @@ ipa_analyze_virtual_call_uses (struct ipa_func_body_info *fbi,
return; return;
} }
struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index, call); struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index,
call, true);
class cgraph_indirect_call_info *ii = cs->indirect_info; class cgraph_indirect_call_info *ii = cs->indirect_info;
ii->offset = anc_offset; ii->offset = anc_offset;
ii->otr_token = tree_to_uhwi (OBJ_TYPE_REF_TOKEN (target)); ii->otr_token = tree_to_uhwi (OBJ_TYPE_REF_TOKEN (target));
...@@ -3510,6 +3521,11 @@ update_indirect_edges_after_inlining (struct cgraph_edge *cs, ...@@ -3510,6 +3521,11 @@ update_indirect_edges_after_inlining (struct cgraph_edge *cs,
if (ici->polymorphic if (ici->polymorphic
&& !ipa_get_jf_pass_through_type_preserved (jfunc)) && !ipa_get_jf_pass_through_type_preserved (jfunc))
ici->vptr_changed = true; ici->vptr_changed = true;
ipa_set_param_used_by_indirect_call (new_root_info,
ici->param_index, true);
if (ici->polymorphic)
ipa_set_param_used_by_polymorphic_call (new_root_info,
ici->param_index, true);
} }
} }
else if (jfunc->type == IPA_JF_ANCESTOR) else if (jfunc->type == IPA_JF_ANCESTOR)
...@@ -4055,6 +4071,12 @@ ipa_print_node_params (FILE *f, struct cgraph_node *node) ...@@ -4055,6 +4071,12 @@ ipa_print_node_params (FILE *f, struct cgraph_node *node)
ipa_dump_param (f, info, i); ipa_dump_param (f, info, i);
if (ipa_is_param_used (info, i)) if (ipa_is_param_used (info, i))
fprintf (f, " used"); fprintf (f, " used");
if (ipa_is_param_used_by_ipa_predicates (info, i))
fprintf (f, " used_by_ipa_predicates");
if (ipa_is_param_used_by_indirect_call (info, i))
fprintf (f, " used_by_indirect_call");
if (ipa_is_param_used_by_polymorphic_call (info, i))
fprintf (f, " used_by_polymorphic_call");
c = ipa_get_controlled_uses (info, i); c = ipa_get_controlled_uses (info, i);
if (c == IPA_UNDESCRIBED_USE) if (c == IPA_UNDESCRIBED_USE)
fprintf (f, " undescribed_use"); fprintf (f, " undescribed_use");
...@@ -4331,7 +4353,8 @@ ipa_write_indirect_edge_info (struct output_block *ob, ...@@ -4331,7 +4353,8 @@ ipa_write_indirect_edge_info (struct output_block *ob,
static void static void
ipa_read_indirect_edge_info (class lto_input_block *ib, ipa_read_indirect_edge_info (class lto_input_block *ib,
class data_in *data_in, class data_in *data_in,
struct cgraph_edge *cs) struct cgraph_edge *cs,
class ipa_node_params *info)
{ {
class cgraph_indirect_call_info *ii = cs->indirect_info; class cgraph_indirect_call_info *ii = cs->indirect_info;
struct bitpack_d bp; struct bitpack_d bp;
...@@ -4354,6 +4377,14 @@ ipa_read_indirect_edge_info (class lto_input_block *ib, ...@@ -4354,6 +4377,14 @@ ipa_read_indirect_edge_info (class lto_input_block *ib,
ii->otr_type = stream_read_tree (ib, data_in); ii->otr_type = stream_read_tree (ib, data_in);
ii->context.stream_in (ib, data_in); ii->context.stream_in (ib, data_in);
} }
if (info && ii->param_index >= 0)
{
if (ii->polymorphic)
ipa_set_param_used_by_polymorphic_call (info,
ii->param_index , true);
ipa_set_param_used_by_indirect_call (info,
ii->param_index, true);
}
} }
/* Stream out NODE info to OB. */ /* Stream out NODE info to OB. */
...@@ -4523,7 +4554,7 @@ ipa_read_node_info (class lto_input_block *ib, struct cgraph_node *node, ...@@ -4523,7 +4554,7 @@ ipa_read_node_info (class lto_input_block *ib, struct cgraph_node *node,
for (e = node->indirect_calls; e; e = e->next_callee) for (e = node->indirect_calls; e; e = e->next_callee)
{ {
ipa_read_edge_info (ib, data_in, e, prevails); ipa_read_edge_info (ib, data_in, e, prevails);
ipa_read_indirect_edge_info (ib, data_in, e); ipa_read_indirect_edge_info (ib, data_in, e, info);
} }
} }
......
...@@ -333,9 +333,12 @@ struct GTY(()) ipa_param_descriptor ...@@ -333,9 +333,12 @@ struct GTY(()) ipa_param_descriptor
says how many there are. If any use could not be described by means of says how many there are. If any use could not be described by means of
ipa-prop structures, this is IPA_UNDESCRIBED_USE. */ ipa-prop structures, this is IPA_UNDESCRIBED_USE. */
int controlled_uses; int controlled_uses;
unsigned int move_cost : 31; unsigned int move_cost : 28;
/* The parameter is used. */ /* The parameter is used. */
unsigned used : 1; unsigned used : 1;
unsigned used_by_ipa_predicates : 1;
unsigned used_by_indirect_call : 1;
unsigned used_by_polymorphic_call : 1;
}; };
/* ipa_node_params stores information related to formal parameters of functions /* ipa_node_params stores information related to formal parameters of functions
...@@ -519,6 +522,36 @@ ipa_set_param_used (class ipa_node_params *info, int i, bool val) ...@@ -519,6 +522,36 @@ ipa_set_param_used (class ipa_node_params *info, int i, bool val)
(*info->descriptors)[i].used = val; (*info->descriptors)[i].used = val;
} }
/* Set the used_by_ipa_predicates flag corresponding to the Ith formal
parameter of the function associated with INFO to VAL. */
static inline void
ipa_set_param_used_by_ipa_predicates (class ipa_node_params *info, int i, bool val)
{
gcc_checking_assert (info->descriptors);
(*info->descriptors)[i].used_by_ipa_predicates = val;
}
/* Set the used_by_indirect_call flag corresponding to the Ith formal
parameter of the function associated with INFO to VAL. */
static inline void
ipa_set_param_used_by_indirect_call (class ipa_node_params *info, int i, bool val)
{
gcc_checking_assert (info->descriptors);
(*info->descriptors)[i].used_by_indirect_call = val;
}
/* Set the .used_by_polymorphic_call flag corresponding to the Ith formal
parameter of the function associated with INFO to VAL. */
static inline void
ipa_set_param_used_by_polymorphic_call (class ipa_node_params *info, int i, bool val)
{
gcc_checking_assert (info->descriptors);
(*info->descriptors)[i].used_by_polymorphic_call = val;
}
/* Return how many uses described by ipa-prop a parameter has or /* Return how many uses described by ipa-prop a parameter has or
IPA_UNDESCRIBED_USE if there is a use that is not described by these IPA_UNDESCRIBED_USE if there is a use that is not described by these
structures. */ structures. */
...@@ -550,6 +583,36 @@ ipa_is_param_used (class ipa_node_params *info, int i) ...@@ -550,6 +583,36 @@ ipa_is_param_used (class ipa_node_params *info, int i)
return (*info->descriptors)[i].used; return (*info->descriptors)[i].used;
} }
/* Return the used_by_ipa_predicates flag corresponding to the Ith formal
parameter of the function associated with INFO. */
static inline bool
ipa_is_param_used_by_ipa_predicates (class ipa_node_params *info, int i)
{
gcc_checking_assert (info->descriptors);
return (*info->descriptors)[i].used_by_ipa_predicates;
}
/* Return the used_by_indirect_call flag corresponding to the Ith formal
parameter of the function associated with INFO. */
static inline bool
ipa_is_param_used_by_indirect_call (class ipa_node_params *info, int i)
{
gcc_checking_assert (info->descriptors);
return (*info->descriptors)[i].used_by_indirect_call;
}
/* Return the used_by_polymorphic_call flag corresponding to the Ith formal
parameter of the function associated with INFO. */
static inline bool
ipa_is_param_used_by_polymorphic_call (class ipa_node_params *info, int i)
{
gcc_checking_assert (info->descriptors);
return (*info->descriptors)[i].used_by_polymorphic_call;
}
/* Information about replacements done in aggregates for a given node (each /* Information about replacements done in aggregates for a given node (each
node has its linked list). */ node has its linked list). */
struct GTY(()) ipa_agg_replacement_value struct GTY(()) ipa_agg_replacement_value
......
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