Commit df0d8136 by Jan Hubicka Committed by Jan Hubicka

* ipa-polymorphic-call.c

	(ipa_polymorphic_call_context::speculation_consistent_p): Constify.
	(ipa_polymorphic_call_context::meet_speculation_with): New function.
	(ipa_polymorphic_call_context::combine_with): Handle types in construction
	better.
	(ipa_polymorphic_call_context::equal_to): Do not bother about useless
	speculation.
	(ipa_polymorphic_call_context::meet_with): New function.
	* cgraph.h (class ipa_polymorphic_call_context): Add
	meet_width, meet_speculation_with; constify speculation_consistent_p.
	* ipa-cp.c (ipa_context_from_jfunc): Handle speculation; combine with incomming
	context.
	(propagate_context_accross_jump_function): Likewise; be more cureful.
	about set_contains_variable.
	(ipa_get_indirect_edge_target_1): Fix handling of dynamic type changes.
	(find_more_scalar_values_for_callers_subset): Fix.
	(find_more_contexts_for_caller_subset): Perform meet operation.

From-SVN: r217634
parent 70486010
2014-11-16 Jan Hubicka <hubicka@ucw.cz> 2014-11-16 Jan Hubicka <hubicka@ucw.cz>
* ipa-polymorphic-call.c
(ipa_polymorphic_call_context::speculation_consistent_p): Constify.
(ipa_polymorphic_call_context::meet_speculation_with): New function.
(ipa_polymorphic_call_context::combine_with): Handle types in construction
better.
(ipa_polymorphic_call_context::equal_to): Do not bother about useless
speculation.
(ipa_polymorphic_call_context::meet_with): New function.
* cgraph.h (class ipa_polymorphic_call_context): Add
meet_width, meet_speculation_with; constify speculation_consistent_p.
* ipa-cp.c (ipa_context_from_jfunc): Handle speculation; combine with incomming
context.
(propagate_context_accross_jump_function): Likewise; be more cureful.
about set_contains_variable.
(ipa_get_indirect_edge_target_1): Fix handling of dynamic type changes.
(find_more_scalar_values_for_callers_subset): Fix.
(find_more_contexts_for_caller_subset): Perform meet operation.
2014-11-16 Jan Hubicka <hubicka@ucw.cz>
* passes.c (execute_one_pass): Do not apply all transforms prior * passes.c (execute_one_pass): Do not apply all transforms prior
every simple IPA pass. every simple IPA pass.
* cgraphunit.c: Do not include fibheap.h * cgraphunit.c: Do not include fibheap.h
...@@ -1389,6 +1389,7 @@ public: ...@@ -1389,6 +1389,7 @@ public:
If actual type the context is being used in is known, OTR_TYPE should be If actual type the context is being used in is known, OTR_TYPE should be
set accordingly. This improves quality of combined result. */ set accordingly. This improves quality of combined result. */
bool combine_with (ipa_polymorphic_call_context, tree otr_type = NULL); bool combine_with (ipa_polymorphic_call_context, tree otr_type = NULL);
bool meet_with (ipa_polymorphic_call_context, tree otr_type = NULL);
/* Return TRUE if context is fully useless. */ /* Return TRUE if context is fully useless. */
bool useless_p () const; bool useless_p () const;
...@@ -1406,9 +1407,10 @@ public: ...@@ -1406,9 +1407,10 @@ public:
private: private:
bool combine_speculation_with (tree, HOST_WIDE_INT, bool, tree); bool combine_speculation_with (tree, HOST_WIDE_INT, bool, tree);
bool meet_speculation_with (tree, HOST_WIDE_INT, bool, tree);
void set_by_decl (tree, HOST_WIDE_INT); void set_by_decl (tree, HOST_WIDE_INT);
bool set_by_invariant (tree, tree, HOST_WIDE_INT); bool set_by_invariant (tree, tree, HOST_WIDE_INT);
bool speculation_consistent_p (tree, HOST_WIDE_INT, bool, tree); bool speculation_consistent_p (tree, HOST_WIDE_INT, bool, tree) const;
void make_speculative (tree otr_type = NULL); void make_speculative (tree otr_type = NULL);
}; };
......
...@@ -946,17 +946,17 @@ ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx, ...@@ -946,17 +946,17 @@ ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx,
{ {
ipa_polymorphic_call_context srcctx; ipa_polymorphic_call_context srcctx;
int srcidx; int srcidx;
bool type_preserved = true;
if (jfunc->type == IPA_JF_PASS_THROUGH) if (jfunc->type == IPA_JF_PASS_THROUGH)
{ {
if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
|| !ipa_get_jf_pass_through_type_preserved (jfunc))
return ctx; return ctx;
type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
srcidx = ipa_get_jf_pass_through_formal_id (jfunc); srcidx = ipa_get_jf_pass_through_formal_id (jfunc);
} }
else else
{ {
if (!ipa_get_jf_ancestor_type_preserved (jfunc)) type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
return ctx;
srcidx = ipa_get_jf_ancestor_formal_id (jfunc); srcidx = ipa_get_jf_ancestor_formal_id (jfunc);
} }
if (info->ipcp_orig_node) if (info->ipcp_orig_node)
...@@ -981,7 +981,10 @@ ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx, ...@@ -981,7 +981,10 @@ ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx,
return ctx; return ctx;
if (jfunc->type == IPA_JF_ANCESTOR) if (jfunc->type == IPA_JF_ANCESTOR)
srcctx.offset_by (ipa_get_jf_ancestor_offset (jfunc)); srcctx.offset_by (ipa_get_jf_ancestor_offset (jfunc));
ctx.combine_with (srcctx); if (!type_preserved)
srcctx.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
srcctx.combine_with (ctx);
return srcctx;
} }
return ctx; return ctx;
...@@ -1298,15 +1301,13 @@ propagate_context_accross_jump_function (cgraph_edge *cs, ...@@ -1298,15 +1301,13 @@ propagate_context_accross_jump_function (cgraph_edge *cs,
return false; return false;
bool ret = false; bool ret = false;
bool added_sth = false; bool added_sth = false;
bool type_preserved = true;
ipa_polymorphic_call_context edge_ctx, *edge_ctx_ptr ipa_polymorphic_call_context edge_ctx, *edge_ctx_ptr
= ipa_get_ith_polymorhic_call_context (args, idx); = ipa_get_ith_polymorhic_call_context (args, idx);
if (edge_ctx_ptr) if (edge_ctx_ptr)
{ edge_ctx = *edge_ctx_ptr;
edge_ctx = *edge_ctx_ptr;
edge_ctx.clear_speculation ();
}
if (jfunc->type == IPA_JF_PASS_THROUGH if (jfunc->type == IPA_JF_PASS_THROUGH
|| jfunc->type == IPA_JF_ANCESTOR) || jfunc->type == IPA_JF_ANCESTOR)
...@@ -1320,15 +1321,14 @@ propagate_context_accross_jump_function (cgraph_edge *cs, ...@@ -1320,15 +1321,14 @@ propagate_context_accross_jump_function (cgraph_edge *cs,
not set instead of punting. */ not set instead of punting. */
if (jfunc->type == IPA_JF_PASS_THROUGH) if (jfunc->type == IPA_JF_PASS_THROUGH)
{ {
if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
|| !ipa_get_jf_pass_through_type_preserved (jfunc))
goto prop_fail; goto prop_fail;
type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc);
src_idx = ipa_get_jf_pass_through_formal_id (jfunc); src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
} }
else else
{ {
if (!ipa_get_jf_ancestor_type_preserved (jfunc)) type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc);
goto prop_fail;
src_idx = ipa_get_jf_ancestor_formal_id (jfunc); src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
} }
...@@ -1338,21 +1338,24 @@ propagate_context_accross_jump_function (cgraph_edge *cs, ...@@ -1338,21 +1338,24 @@ propagate_context_accross_jump_function (cgraph_edge *cs,
&& (src_lat->contains_variable && (src_lat->contains_variable
|| (src_lat->values_count > 1))) || (src_lat->values_count > 1)))
goto prop_fail; goto prop_fail;
if (src_lat->contains_variable)
ret |= dest_lat->set_contains_variable ();
ipcp_value<ipa_polymorphic_call_context> *src_val; ipcp_value<ipa_polymorphic_call_context> *src_val;
for (src_val = src_lat->values; src_val; src_val = src_val->next) for (src_val = src_lat->values; src_val; src_val = src_val->next)
{ {
ipa_polymorphic_call_context cur = src_val->value; ipa_polymorphic_call_context cur = src_val->value;
if (!type_preserved)
cur.possible_dynamic_type_change (cs->in_polymorphic_cdtor);
if (jfunc->type == IPA_JF_ANCESTOR) if (jfunc->type == IPA_JF_ANCESTOR)
cur.offset_by (ipa_get_jf_ancestor_offset (jfunc)); cur.offset_by (ipa_get_jf_ancestor_offset (jfunc));
/* TODO: Perhaps attempt to look up some used OTR type? */ /* TODO: In cases we know how the context is going to be used,
cur.clear_speculation (); we can improve the result by passing proper OTR_TYPE. */
if (!edge_ctx.useless_p ()) cur.combine_with (edge_ctx);
cur.combine_with (edge_ctx);
if (!cur.useless_p ()) if (!cur.useless_p ())
{ {
if (src_lat->contains_variable
&& !edge_ctx.equal_to (cur))
ret |= dest_lat->set_contains_variable ();
ret |= dest_lat->add_value (cur, cs, src_val, src_idx); ret |= dest_lat->add_value (cur, cs, src_val, src_idx);
added_sth = true; added_sth = true;
} }
...@@ -1848,6 +1851,10 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, ...@@ -1848,6 +1851,10 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
if (known_contexts.length () > (unsigned int) param_index) if (known_contexts.length () > (unsigned int) param_index)
{ {
context = known_contexts[param_index]; context = known_contexts[param_index];
context.offset_by (anc_offset);
if (ie->indirect_info->vptr_changed)
context.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
ie->indirect_info->otr_type);
if (t) if (t)
{ {
ipa_polymorphic_call_context ctx2 = ipa_polymorphic_call_context ipa_polymorphic_call_context ctx2 = ipa_polymorphic_call_context
...@@ -3160,6 +3167,7 @@ find_more_scalar_values_for_callers_subset (struct cgraph_node *node, ...@@ -3160,6 +3167,7 @@ find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
struct cgraph_edge *cs; struct cgraph_edge *cs;
tree newval = NULL_TREE; tree newval = NULL_TREE;
int j; int j;
bool first = true;
if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i]) if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i])
continue; continue;
...@@ -3178,13 +3186,15 @@ find_more_scalar_values_for_callers_subset (struct cgraph_node *node, ...@@ -3178,13 +3186,15 @@ find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func); t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func);
if (!t if (!t
|| (newval || (newval
&& !values_equal_for_ipcp_p (t, newval))) && !values_equal_for_ipcp_p (t, newval))
|| (!first && !newval))
{ {
newval = NULL_TREE; newval = NULL_TREE;
break; break;
} }
else else
newval = t; newval = t;
first = false;
} }
if (newval) if (newval)
...@@ -3226,7 +3236,7 @@ find_more_contexts_for_caller_subset (cgraph_node *node, ...@@ -3226,7 +3236,7 @@ find_more_contexts_for_caller_subset (cgraph_node *node,
continue; continue;
ipa_polymorphic_call_context newval; ipa_polymorphic_call_context newval;
bool found = false; bool first = true;
int j; int j;
FOR_EACH_VEC_ELT (callers, j, cs) FOR_EACH_VEC_ELT (callers, j, cs)
...@@ -3238,21 +3248,18 @@ find_more_contexts_for_caller_subset (cgraph_node *node, ...@@ -3238,21 +3248,18 @@ find_more_contexts_for_caller_subset (cgraph_node *node,
ipa_polymorphic_call_context ctx; ipa_polymorphic_call_context ctx;
ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i, ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i,
jfunc); jfunc);
ctx.clear_speculation (); if (first)
if (ctx.useless_p ()
|| (found && !values_equal_for_ipcp_p (newval, ctx)))
{
found = false;
break;
}
else if (!found)
{ {
found = true;
newval = ctx; newval = ctx;
first = false;
} }
else
newval.meet_with (ctx);
if (newval.useless_p ())
break;
} }
if (found) if (!newval.useless_p ())
{ {
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
......
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