* cgraph.h (struct cgraph_node): Add ipcp_clone flag.
(cgraph_node::create_virtual_clone): Copy it.
* ipa-cp.c (ipcp_versionable_function_p): Watch for missing
summaries.
(ignore_edge_p): If caller has ipa-cp disabled, skip the edge, too.
(ipcp_verify_propagated_values): Do not verify nodes where ipcp
is disabled.
(propagate_constants_across_call): If callee is not analyzed, give up.
(propagate_constants_topo): Lower to bottom latties of all callees of
functions with ipa-cp disabled.
(ipcp_propagate_stage): Skip functions with ipa-cp disabled.
(cgraph_edge_brings_value_p): Check for availability first.
(create_specialized_node): Set ipcp_clone.
(ipcp_store_bits_results): Check that info is present.
* ipa-fnsummary.c (evaluate_properties_for_edge): Do not analyze
thunks.
(ipa_call_context::duplicate_from, ipa_call_context::equal_to): Be
conservative when callee summary is missing.
(remap_edge_summaries): Lookup call summary only when needed.
* ipa-icf.c (sem_function::param_used_p): Be ready for missing summary.
* ipa-prpo.c (ipa_alloc_node_params, ipa_initialize_node_params):
Use get_create.
(ipa_analyze_node): Use get_create.
(propagate_controlled_uses): Do not propagate when function is not
analyzed.
(ipa_propagate_indirect_call_infos): Remove summary of inline clone.
(ipa_read_node_info): Use get_create.
* ipa-prop.h (IPA_NODE_REF): Use get.
(IPA_NODE_REF_GET_CREATE): New.
From-SVN: r278016
+2019-11-09 Jan Hubicka <hubicka@ucw.cz>
+
+ * cgraph.h (struct cgraph_node): Add ipcp_clone flag.
+ (cgraph_node::create_virtual_clone): Copy it.
+ * ipa-cp.c (ipcp_versionable_function_p): Watch for missing
+ summaries.
+ (ignore_edge_p): If caller has ipa-cp disabled, skip the edge, too.
+ (ipcp_verify_propagated_values): Do not verify nodes where ipcp
+ is disabled.
+ (propagate_constants_across_call): If callee is not analyzed, give up.
+ (propagate_constants_topo): Lower to bottom latties of all callees of
+ functions with ipa-cp disabled.
+ (ipcp_propagate_stage): Skip functions with ipa-cp disabled.
+ (cgraph_edge_brings_value_p): Check for availability first.
+ (create_specialized_node): Set ipcp_clone.
+ (ipcp_store_bits_results): Check that info is present.
+ * ipa-fnsummary.c (evaluate_properties_for_edge): Do not analyze
+ thunks.
+ (ipa_call_context::duplicate_from, ipa_call_context::equal_to): Be
+ conservative when callee summary is missing.
+ (remap_edge_summaries): Lookup call summary only when needed.
+ * ipa-icf.c (sem_function::param_used_p): Be ready for missing summary.
+ * ipa-prpo.c (ipa_alloc_node_params, ipa_initialize_node_params):
+ Use get_create.
+ (ipa_analyze_node): Use get_create.
+ (propagate_controlled_uses): Do not propagate when function is not
+ analyzed.
+ (ipa_propagate_indirect_call_infos): Remove summary of inline clone.
+ (ipa_read_node_info): Use get_create.
+ * ipa-prop.h (IPA_NODE_REF): Use get.
+ (IPA_NODE_REF_GET_CREATE): New.
+
2019-11-09 Jan Hubicka <hubicka@ucw.cz>
* ipa-fnsummary.c (evaluate_properties_for_edge): Call IPA_NODE_REF
unsigned redefined_extern_inline : 1;
/* True if the function may enter serial irrevocable mode. */
unsigned tm_may_enter_irr : 1;
+ /* True if this was a clone created by ipa-cp. */
+ unsigned ipcp_clone : 1;
private:
/* Unique id of the node. */
??? We cannot use COMDAT linkage because there is no
ABI support for this. */
set_new_clone_decl_and_node_flags (new_node);
+ new_node->ipcp_clone = ipcp_clone;
new_node->clone.tree_map = tree_map;
if (!implicit_section)
new_node->set_section (get_section ());
static bool
ipcp_versionable_function_p (struct cgraph_node *node)
{
- return IPA_NODE_REF (node)->versionable;
+ return IPA_NODE_REF (node) && IPA_NODE_REF (node)->versionable;
}
/* Structure holding accumulated information about callers of a node. */
= e->callee->function_or_virtual_thunk_symbol (&avail, e->caller);
return (avail <= AVAIL_INTERPOSABLE
+ || !opt_for_fn (e->caller->decl, flag_ipa_cp)
|| !opt_for_fn (ultimate_target->decl, flag_ipa_cp));
}
FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
{
class ipa_node_params *info = IPA_NODE_REF (node);
+ if (!opt_for_fn (node->decl, flag_ipa_cp))
+ continue;
int i, count = ipa_get_param_count (info);
for (i = 0; i < count; i++)
return false;
gcc_checking_assert (callee->has_gimple_body_p ());
callee_info = IPA_NODE_REF (callee);
+ if (!callee_info)
+ return false;
args = IPA_EDGE_REF (cs);
parms_count = ipa_get_param_count (callee_info);
until all lattices stabilize. */
FOR_EACH_VEC_ELT (cycle_nodes, j, v)
if (v->has_gimple_body_p ())
- push_node_to_stack (topo, v);
+ {
+ if (opt_for_fn (v->decl, flag_ipa_cp))
+ push_node_to_stack (topo, v);
+ /* When V is not optimized, we can not push it to stac, but
+ still we need to set all its callees lattices to bottom. */
+ else
+ {
+ for (cgraph_edge *cs = v->callees; cs; cs = cs->next_callee)
+ propagate_constants_across_call (cs);
+ }
+ }
v = pop_node_from_stack (topo);
while (v)
the local effects of the discovered constants and all valid values to
their topological sort. */
FOR_EACH_VEC_ELT (cycle_nodes, j, v)
- if (v->has_gimple_body_p ())
+ if (v->has_gimple_body_p ()
+ && opt_for_fn (v->decl, flag_ipa_cp))
{
struct cgraph_edge *cs;
FOR_EACH_DEFINED_FUNCTION (node)
{
- class ipa_node_params *info = IPA_NODE_REF (node);
-
- determine_versionability (node, info);
- if (node->has_gimple_body_p ())
+ if (node->has_gimple_body_p () && opt_for_fn (node->decl, flag_ipa_cp))
{
+ class ipa_node_params *info = IPA_NODE_REF (node);
+ determine_versionability (node, info);
info->lattices = XCNEWVEC (class ipcp_param_lattices,
ipa_get_param_count (info));
initialize_node_lattices (node);
enum availability availability;
cgraph_node *real_dest = cs->callee->function_symbol (&availability);
- if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
- || availability <= AVAIL_INTERPOSABLE
+ if (availability <= AVAIL_INTERPOSABLE
+ || !same_node_or_its_all_contexts_clone_p (real_dest, dest)
|| caller_info->node_dead)
return false;
ipcp_value<ipa_polymorphic_call_context> *)
{
class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
- cgraph_node *real_dest = cs->callee->function_symbol ();
+ enum availability avail;
+ cgraph_node *real_dest = cs->callee->function_symbol (&avail);
- if (!same_node_or_its_all_contexts_clone_p (real_dest, dest)
+ if (avail <= AVAIL_INTERPOSABLE
+ || !same_node_or_its_all_contexts_clone_p (real_dest, dest)
|| caller_info->node_dead)
return false;
if (!src->val)
update_profiling_info (node, new_node);
new_info = IPA_NODE_REF (new_node);
new_info->ipcp_orig_node = node;
+ new_node->ipcp_clone = true;
new_info->known_csts = known_csts;
new_info->known_contexts = known_contexts;
bool dumped_sth = false;
bool found_useful_result = false;
- if (!opt_for_fn (node->decl, flag_ipa_bit_cp))
+ if (!opt_for_fn (node->decl, flag_ipa_bit_cp) || !info)
{
if (dump_file)
fprintf (dump_file, "Not considering %s for ipa bitwise propagation "
if (count && known_contexts_ptr)
known_contexts_ptr->safe_grow_cleared (count);
- for (i = 0; i < count; i++)
- {
- struct ipa_jump_func *jf = ipa_get_ith_jump_func (args, i);
- tree cst = ipa_value_from_jfunc (caller_parms_info, jf,
- ipa_get_type (callee_pi, i));
-
- if (!cst && e->call_stmt
- && i < (int)gimple_call_num_args (e->call_stmt))
- {
- cst = gimple_call_arg (e->call_stmt, i);
- if (!is_gimple_min_invariant (cst))
- cst = NULL;
- }
- if (cst)
- {
- gcc_checking_assert (TREE_CODE (cst) != TREE_BINFO);
- if (known_vals.exists ())
- known_vals[i] = cst;
- }
- else if (inline_p && !es->param[i].change_prob)
- known_vals[i] = error_mark_node;
-
- if (known_contexts_ptr)
- (*known_contexts_ptr)[i]
- = ipa_context_from_jfunc (caller_parms_info, e, i, jf);
- /* TODO: When IPA-CP starts propagating and merging aggregate jump
- functions, use its knowledge of the caller too, just like the
- scalar case above. */
- known_aggs[i] = &jf->agg;
- }
+ if (callee_pi)
+ for (i = 0; i < count; i++)
+ {
+ struct ipa_jump_func *jf = ipa_get_ith_jump_func (args, i);
+ tree cst = ipa_value_from_jfunc (caller_parms_info, jf,
+ ipa_get_type (callee_pi, i));
+
+ if (!cst && e->call_stmt
+ && i < (int)gimple_call_num_args (e->call_stmt))
+ {
+ cst = gimple_call_arg (e->call_stmt, i);
+ if (!is_gimple_min_invariant (cst))
+ cst = NULL;
+ }
+ if (cst)
+ {
+ gcc_checking_assert (TREE_CODE (cst) != TREE_BINFO);
+ if (known_vals.exists ())
+ known_vals[i] = cst;
+ }
+ else if (inline_p && !es->param[i].change_prob)
+ known_vals[i] = error_mark_node;
+
+ if (known_contexts_ptr)
+ (*known_contexts_ptr)[i]
+ = ipa_context_from_jfunc (caller_parms_info, e, i, jf);
+ /* TODO: When IPA-CP starts propagating and merging aggregate jump
+ functions, use its knowledge of the caller too, just like the
+ scalar case above. */
+ known_aggs[i] = &jf->agg;
+ }
+ else
+ gcc_assert (callee->thunk.thunk_p);
}
else if (e->call_stmt && !e->call_stmt_cannot_inline_p
&& ((clause_ptr && info->conds) || known_vals_ptr))
m_possible_truths = ctx.m_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);
+ unsigned int nargs = params_summary
+ ? ipa_get_param_count (params_summary) : 0;
m_inline_param_summary = vNULL;
/* Copy the info only if there is at least one useful entry. */
return false;
class ipa_node_params *params_summary = IPA_NODE_REF (m_node);
- unsigned int nargs = ipa_get_param_count (params_summary);
+ unsigned int nargs = params_summary
+ ? ipa_get_param_count (params_summary) : 0;
if (m_inline_param_summary.exists () || ctx.m_inline_param_summary.exists ())
{
}
/* Update change_prob of EDGE after INLINED_EDGE has been inlined.
- When functoin A is inlined in B and A calls C with parameter that
+ When function A is inlined in B and A calls C with parameter that
changes with probability PROB1 and C is known to be passthroug
of argument if B that change with probability PROB2, the probability
of change is now PROB1*PROB2. */
struct cgraph_edge *e, *next;
for (e = node->callees; e; e = next)
{
- class ipa_call_summary *es = ipa_call_summaries->get (e);
predicate p;
next = e->next_callee;
if (e->inline_failed)
{
+ class ipa_call_summary *es = ipa_call_summaries->get (e);
remap_edge_change_prob (inlined_edge, e);
if (es->predicate)
class ipa_node_params *parms_info = IPA_NODE_REF (get_node ());
- if (vec_safe_length (parms_info->descriptors) <= i)
+ if (!parms_info || vec_safe_length (parms_info->descriptors) <= i)
return true;
return ipa_is_param_used (IPA_NODE_REF (get_node ()), i);
static bool
ipa_alloc_node_params (struct cgraph_node *node, int param_count)
{
- class ipa_node_params *info = IPA_NODE_REF (node);
+ class ipa_node_params *info = IPA_NODE_REF_GET_CREATE (node);
if (!info->descriptors && param_count)
{
void
ipa_initialize_node_params (struct cgraph_node *node)
{
- class ipa_node_params *info = IPA_NODE_REF (node);
+ class ipa_node_params *info = IPA_NODE_REF_GET_CREATE (node);
if (!info->descriptors
&& ipa_alloc_node_params (node, count_formal_params (node->decl)))
ipa_check_create_node_params ();
ipa_check_create_edge_args ();
- info = IPA_NODE_REF (node);
+ info = IPA_NODE_REF_GET_CREATE (node);
if (info->analysis_done)
return;
class ipa_node_params *old_root_info = IPA_NODE_REF (cs->callee);
int count, i;
+ if (!old_root_info)
+ return;
+
count = MIN (ipa_get_cs_argument_count (args),
ipa_get_param_count (old_root_info));
for (i = 0; i < count; i++)
clone = cs->caller;
while (clone->inlined_to
- && clone != rdesc->cs->caller
- && IPA_NODE_REF (clone)->ipcp_orig_node)
+ && clone->ipcp_clone
+ && clone != rdesc->cs->caller)
{
struct ipa_ref *ref;
ref = clone->find_reference (n, NULL, 0);
propagate_controlled_uses (cs);
changed = propagate_info_to_inlined_callees (cs, cs->callee, new_edges);
+ ipa_node_params_sum->remove (cs->callee);
return changed;
}
struct cgraph_edge *e;
struct bitpack_d bp;
bool prevails = node->prevailing_p ();
- class ipa_node_params *info = prevails ? IPA_NODE_REF (node) : NULL;
+ class ipa_node_params *info = prevails
+ ? IPA_NODE_REF_GET_CREATE (node) : NULL;
int param_count = streamer_read_uhwi (ib);
if (prevails)
/* Return the associated parameter/argument info corresponding to the given
node/edge. */
-#define IPA_NODE_REF(NODE) (ipa_node_params_sum->get_create (NODE))
+#define IPA_NODE_REF(NODE) (ipa_node_params_sum->get (NODE))
+#define IPA_NODE_REF_GET_CREATE(NODE) (ipa_node_params_sum->get_create (NODE))
#define IPA_EDGE_REF(EDGE) (ipa_edge_args_sum->get (EDGE))
#define IPA_EDGE_REF_GET_CREATE(EDGE) (ipa_edge_args_sum->get_create (EDGE))
/* This macro checks validity of index returned by