ipa-prop.h (ipa_get_jf_pass_through_type_preserved): use agg_preserved flag instead.
2014-11-14 Martin Jambor <mjambor@suse.cz> * ipa-prop.h (ipa_get_jf_pass_through_type_preserved): use agg_preserved flag instead. (ipa_get_jf_ancestor_type_preserved): Likewise. (ipa_node_params): Rename known_vals to known_csts, update all users. New field known_contexts. (ipa_get_indirect_edge_target): Update prototype. (ipcp_poly_ctx_values_pool): Declare. (ipa_context_from_jfunc): Likewise. * ipa-inline.h (estimate_ipcp_clone_size_and_time): Updated prototype. * cgraph.h (ipa_polymorphic_call_context): New method equal_to. New parameter newline of method dump. * ipa-cp.c (ctxlat): New field. (ipcp_values_pool): Renamed to ipcp_cst_values_pool, updated all users. (ipcp_poly_ctx_values_pool):New variable. (ipa_get_poly_ctx_lat): New function. (print_ipcp_constant_value): New overloaded function for contexts. (print_all_lattices): Also print contexts. (ipa_topo_info): New field contexts; (set_all_contains_variable): Also set the flag in the context lattice. (initialize_node_lattices): Likewise for flag bottom. (ipa_get_jf_ancestor_result): Removed BINFO handling. (ipa_value_from_jfunc): Likewise. (ipa_context_from_jfunc): New function. (values_equal_for_ipcp_p): New overloaded function for contexts. (allocate_and_init_ipcp_value): Construct the value. (allocate_and_init_ipcp_value): New overloaded function for contexts. (propagate_scalar_accross_jump_function): Removed handling of KNOWN_TYPE jump functions. (propagate_context_accross_jump_function): New function. (propagate_constants_accross_call): Also propagate contexts. (ipa_get_indirect_edge_target_1): Work on contexts rather than BINFOs. (ipa_get_indirect_edge_target): Likewise. (devirtualization_time_bonus): Likewise. (gather_context_independent_values): Create and populate known_contexts vector rather than known_binfos. (perform_estimation_of_a_value): Work on contexts rather than BINFOs. (estimate_local_effects): Likewise. (add_all_node_vals_to_toposort): Also add contexts to teir topological sort. (ipcp_propagate_stage): Also propagate effects of contexts. (ipcp_discover_new_direct_edges): Receive and pass known_contexts to ipa_get_indirect_edge_target_1. (cgraph_edge_brings_value_p): New overloaded function for contexts. (create_specialized_node): Work on contexts rather than BINFOs. (find_more_contexts_for_caller_subset): New function. (known_contexts_useful_p): New function. (copy_useful_known_contexts): Likewise. (modify_known_vectors_with_val): Likewise. (ipcp_val_in_agg_replacements_p): Renamed to ipcp_val_agg_replacement_ok_p, return true for all offset indicating non-aggregate. (ipcp_val_agg_replacement_ok_p): New overloaded function for contexts. (decide_about_value): Work on contexts rather than BINFOs. (decide_whether_version_node): Likewise. (ipcp_driver): Initialize the new alloc pool. * ipa-prop.c (ipa_print_node_jump_functions_for_edge): Prettify printing of edge contexts. (ipa_set_ancestor_jf): Replace assert with conditional setting of type_preserved to false. (update_jump_functions_after_inlining): Use access function instead of reading agg_preserved directly. Store combined context in the ancestor case. (try_make_edge_direct_virtual_call): Work on contexts rather than BINFOs. (update_indirect_edges_after_inlining): Get context from ipa_context_from_jfunc. (ipa_free_node_params_substructures): Free also known_contexts. (ipa_free_all_structures_after_ipa_cp): Free the new alloc pool. (ipa_free_all_structures_after_iinln): Likewise. * ipa-inline-analysis.c (evaluate_properties_for_edge): Work on contexts rather than BINFOs. (estimate_edge_devirt_benefit): Likewise. (estimate_edge_size_and_time): Likewise. (estimate_calls_size_and_time): Likewise. (estimate_node_size_and_time): Likewise. (estimate_ipcp_clone_size_and_time): Likewise. (do_estimate_edge_time): Likewise. (do_estimate_edge_size): Likewise. (do_estimate_edge_hints): Likewise. * ipa-polymorphic-call.c (ipa_polymorphic_call_context::dump): New parameter newline, ouput newline only when it is set. (ipa_polymorphic_call_context::equal_to): New method. testsuite/ * g++.dg/ipa/devirt-11.C: Dont't run ipa-cp, remove times constraint from the dump scan. * g++.dg/ipa/devirt-21.C: Xfail. * g++.dg/ipa/devirt-24.C: Likewise. * g++.dg/ipa/devirt-10.C: Removed times constraint from the dump scan. * g++.dg/ipa/devirt-41.C: Updated the dump scan. * g++.dg/ipa/devirt-44.C: Likewise. * g++.dg/ipa/devirt-43.C: Xfail. From-SVN: r217587
This commit is contained in:
parent
c0cb505599
commit
44210a9672
|
@ -1,3 +1,88 @@
|
|||
2014-11-14 Martin Jambor <mjambor@suse.cz>
|
||||
|
||||
* ipa-prop.h (ipa_get_jf_pass_through_type_preserved): use
|
||||
agg_preserved flag instead.
|
||||
(ipa_get_jf_ancestor_type_preserved): Likewise.
|
||||
(ipa_node_params): Rename known_vals to known_csts, update all users.
|
||||
New field known_contexts.
|
||||
(ipa_get_indirect_edge_target): Update prototype.
|
||||
(ipcp_poly_ctx_values_pool): Declare.
|
||||
(ipa_context_from_jfunc): Likewise.
|
||||
* ipa-inline.h (estimate_ipcp_clone_size_and_time): Updated prototype.
|
||||
* cgraph.h (ipa_polymorphic_call_context): New method equal_to. New
|
||||
parameter newline of method dump.
|
||||
* ipa-cp.c (ctxlat): New field.
|
||||
(ipcp_values_pool): Renamed to ipcp_cst_values_pool, updated all users.
|
||||
(ipcp_poly_ctx_values_pool):New variable.
|
||||
(ipa_get_poly_ctx_lat): New function.
|
||||
(print_ipcp_constant_value): New overloaded function for contexts.
|
||||
(print_all_lattices): Also print contexts.
|
||||
(ipa_topo_info): New field contexts;
|
||||
(set_all_contains_variable): Also set the flag in the context lattice.
|
||||
(initialize_node_lattices): Likewise for flag bottom.
|
||||
(ipa_get_jf_ancestor_result): Removed BINFO handling.
|
||||
(ipa_value_from_jfunc): Likewise.
|
||||
(ipa_context_from_jfunc): New function.
|
||||
(values_equal_for_ipcp_p): New overloaded function for contexts.
|
||||
(allocate_and_init_ipcp_value): Construct the value.
|
||||
(allocate_and_init_ipcp_value): New overloaded function for contexts.
|
||||
(propagate_scalar_accross_jump_function): Removed handling of
|
||||
KNOWN_TYPE jump functions.
|
||||
(propagate_context_accross_jump_function): New function.
|
||||
(propagate_constants_accross_call): Also propagate contexts.
|
||||
(ipa_get_indirect_edge_target_1): Work on contexts rather than BINFOs.
|
||||
(ipa_get_indirect_edge_target): Likewise.
|
||||
(devirtualization_time_bonus): Likewise.
|
||||
(gather_context_independent_values): Create and populate known_contexts
|
||||
vector rather than known_binfos.
|
||||
(perform_estimation_of_a_value): Work on contexts rather than BINFOs.
|
||||
(estimate_local_effects): Likewise.
|
||||
(add_all_node_vals_to_toposort): Also add contexts to teir topological
|
||||
sort.
|
||||
(ipcp_propagate_stage): Also propagate effects of contexts.
|
||||
(ipcp_discover_new_direct_edges): Receive and pass known_contexts to
|
||||
ipa_get_indirect_edge_target_1.
|
||||
(cgraph_edge_brings_value_p): New overloaded function for contexts.
|
||||
(create_specialized_node): Work on contexts rather than BINFOs.
|
||||
(find_more_contexts_for_caller_subset): New function.
|
||||
(known_contexts_useful_p): New function.
|
||||
(copy_useful_known_contexts): Likewise.
|
||||
(modify_known_vectors_with_val): Likewise.
|
||||
(ipcp_val_in_agg_replacements_p): Renamed to
|
||||
ipcp_val_agg_replacement_ok_p, return true for all offset indicating
|
||||
non-aggregate.
|
||||
(ipcp_val_agg_replacement_ok_p): New overloaded function for contexts.
|
||||
(decide_about_value): Work on contexts rather than BINFOs.
|
||||
(decide_whether_version_node): Likewise.
|
||||
(ipcp_driver): Initialize the new alloc pool.
|
||||
* ipa-prop.c (ipa_print_node_jump_functions_for_edge): Prettify
|
||||
printing of edge contexts.
|
||||
(ipa_set_ancestor_jf): Replace assert with conditional setting of
|
||||
type_preserved to false.
|
||||
(update_jump_functions_after_inlining): Use access function instead of
|
||||
reading agg_preserved directly. Store combined context in the ancestor
|
||||
case.
|
||||
(try_make_edge_direct_virtual_call): Work on contexts rather than
|
||||
BINFOs.
|
||||
(update_indirect_edges_after_inlining): Get context from
|
||||
ipa_context_from_jfunc.
|
||||
(ipa_free_node_params_substructures): Free also known_contexts.
|
||||
(ipa_free_all_structures_after_ipa_cp): Free the new alloc pool.
|
||||
(ipa_free_all_structures_after_iinln): Likewise.
|
||||
* ipa-inline-analysis.c (evaluate_properties_for_edge): Work on
|
||||
contexts rather than BINFOs.
|
||||
(estimate_edge_devirt_benefit): Likewise.
|
||||
(estimate_edge_size_and_time): Likewise.
|
||||
(estimate_calls_size_and_time): Likewise.
|
||||
(estimate_node_size_and_time): Likewise.
|
||||
(estimate_ipcp_clone_size_and_time): Likewise.
|
||||
(do_estimate_edge_time): Likewise.
|
||||
(do_estimate_edge_size): Likewise.
|
||||
(do_estimate_edge_hints): Likewise.
|
||||
* ipa-polymorphic-call.c (ipa_polymorphic_call_context::dump): New
|
||||
parameter newline, ouput newline only when it is set.
|
||||
(ipa_polymorphic_call_context::equal_to): New method.
|
||||
|
||||
2014-11-14 Martin Jambor <mjambor@suse.cz>
|
||||
|
||||
* ipa-cp.c (ipcp_value_source): Converted to a template class. All
|
||||
|
|
|
@ -1387,9 +1387,12 @@ public:
|
|||
|
||||
/* Return TRUE if context is fully useless. */
|
||||
bool useless_p () const;
|
||||
/* Return TRUE if this context conveys the same information as X. */
|
||||
bool equal_to (const ipa_polymorphic_call_context &x) const;
|
||||
|
||||
/* Dump human readable context to F. */
|
||||
void dump (FILE *f) const;
|
||||
/* Dump human readable context to F. If NEWLINE is true, it will be
|
||||
terminated by a newline. */
|
||||
void dump (FILE *f, bool newline = true) const;
|
||||
void DEBUG_FUNCTION debug () const;
|
||||
|
||||
/* LTO streaming. */
|
||||
|
|
825
gcc/ipa-cp.c
825
gcc/ipa-cp.c
File diff suppressed because it is too large
Load Diff
|
@ -895,7 +895,8 @@ static void
|
|||
evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p,
|
||||
clause_t *clause_ptr,
|
||||
vec<tree> *known_vals_ptr,
|
||||
vec<tree> *known_binfos_ptr,
|
||||
vec<ipa_polymorphic_call_context>
|
||||
*known_contexts_ptr,
|
||||
vec<ipa_agg_jump_function_p> *known_aggs_ptr)
|
||||
{
|
||||
struct cgraph_node *callee = e->callee->ultimate_alias_target ();
|
||||
|
@ -907,12 +908,12 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p,
|
|||
*clause_ptr = inline_p ? 0 : 1 << predicate_not_inlined_condition;
|
||||
if (known_vals_ptr)
|
||||
known_vals_ptr->create (0);
|
||||
if (known_binfos_ptr)
|
||||
known_binfos_ptr->create (0);
|
||||
if (known_contexts_ptr)
|
||||
known_contexts_ptr->create (0);
|
||||
|
||||
if (ipa_node_params_vector.exists ()
|
||||
&& !e->call_stmt_cannot_inline_p
|
||||
&& ((clause_ptr && info->conds) || known_vals_ptr || known_binfos_ptr))
|
||||
&& ((clause_ptr && info->conds) || known_vals_ptr || known_contexts_ptr))
|
||||
{
|
||||
struct ipa_node_params *parms_info;
|
||||
struct ipa_edge_args *args = IPA_EDGE_REF (e);
|
||||
|
@ -928,8 +929,8 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p,
|
|||
known_vals.safe_grow_cleared (count);
|
||||
if (count && (info->conds || known_aggs_ptr))
|
||||
known_aggs.safe_grow_cleared (count);
|
||||
if (count && known_binfos_ptr)
|
||||
known_binfos_ptr->safe_grow_cleared (count);
|
||||
if (count && known_contexts_ptr)
|
||||
known_contexts_ptr->safe_grow_cleared (count);
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
|
@ -937,14 +938,16 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p,
|
|||
tree cst = ipa_value_from_jfunc (parms_info, jf);
|
||||
if (cst)
|
||||
{
|
||||
if (known_vals.exists () && TREE_CODE (cst) != TREE_BINFO)
|
||||
gcc_checking_assert (TREE_CODE (cst) != TREE_BINFO);
|
||||
if (known_vals.exists ())
|
||||
known_vals[i] = cst;
|
||||
else if (known_binfos_ptr != NULL
|
||||
&& TREE_CODE (cst) == TREE_BINFO)
|
||||
(*known_binfos_ptr)[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 (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. */
|
||||
|
@ -2969,14 +2972,14 @@ make_pass_inline_parameters (gcc::context *ctxt)
|
|||
}
|
||||
|
||||
|
||||
/* Estimate benefit devirtualizing indirect edge IE, provided KNOWN_VALS and
|
||||
KNOWN_BINFOS. */
|
||||
/* Estimate benefit devirtualizing indirect edge IE, provided KNOWN_VALS,
|
||||
KNOWN_CONTEXTS and KNOWN_AGGS. */
|
||||
|
||||
static bool
|
||||
estimate_edge_devirt_benefit (struct cgraph_edge *ie,
|
||||
int *size, int *time,
|
||||
vec<tree> known_vals,
|
||||
vec<tree> known_binfos,
|
||||
vec<ipa_polymorphic_call_context> known_contexts,
|
||||
vec<ipa_agg_jump_function_p> known_aggs)
|
||||
{
|
||||
tree target;
|
||||
|
@ -2984,12 +2987,12 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie,
|
|||
struct inline_summary *isummary;
|
||||
enum availability avail;
|
||||
|
||||
if (!known_vals.exists () && !known_binfos.exists ())
|
||||
if (!known_vals.exists () && !known_contexts.exists ())
|
||||
return false;
|
||||
if (!flag_indirect_inlining)
|
||||
return false;
|
||||
|
||||
target = ipa_get_indirect_edge_target (ie, known_vals, known_binfos,
|
||||
target = ipa_get_indirect_edge_target (ie, known_vals, known_contexts,
|
||||
known_aggs);
|
||||
if (!target)
|
||||
return false;
|
||||
|
@ -3013,7 +3016,7 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie,
|
|||
/* Increase SIZE, MIN_SIZE (if non-NULL) and TIME for size and time needed to
|
||||
handle edge E with probability PROB.
|
||||
Set HINTS if edge may be devirtualized.
|
||||
KNOWN_VALS, KNOWN_AGGS and KNOWN_BINFOS describe context of the call
|
||||
KNOWN_VALS, KNOWN_AGGS and KNOWN_CONTEXTS describe context of the call
|
||||
site. */
|
||||
|
||||
static inline void
|
||||
|
@ -3021,7 +3024,7 @@ estimate_edge_size_and_time (struct cgraph_edge *e, int *size, int *min_size,
|
|||
int *time,
|
||||
int prob,
|
||||
vec<tree> known_vals,
|
||||
vec<tree> known_binfos,
|
||||
vec<ipa_polymorphic_call_context> known_contexts,
|
||||
vec<ipa_agg_jump_function_p> known_aggs,
|
||||
inline_hints *hints)
|
||||
{
|
||||
|
@ -3031,7 +3034,7 @@ estimate_edge_size_and_time (struct cgraph_edge *e, int *size, int *min_size,
|
|||
int cur_size;
|
||||
if (!e->callee
|
||||
&& estimate_edge_devirt_benefit (e, &call_size, &call_time,
|
||||
known_vals, known_binfos, known_aggs)
|
||||
known_vals, known_contexts, known_aggs)
|
||||
&& hints && e->maybe_hot_p ())
|
||||
*hints |= INLINE_HINT_indirect_call;
|
||||
cur_size = call_size * INLINE_SIZE_SCALE;
|
||||
|
@ -3047,9 +3050,8 @@ estimate_edge_size_and_time (struct cgraph_edge *e, int *size, int *min_size,
|
|||
|
||||
|
||||
/* Increase SIZE, MIN_SIZE and TIME for size and time needed to handle all
|
||||
calls in NODE.
|
||||
POSSIBLE_TRUTHS, KNOWN_VALS, KNOWN_AGGS and KNOWN_BINFOS describe context of
|
||||
the call site. */
|
||||
calls in NODE. POSSIBLE_TRUTHS, KNOWN_VALS, KNOWN_AGGS and KNOWN_CONTEXTS
|
||||
describe context of the call site. */
|
||||
|
||||
static void
|
||||
estimate_calls_size_and_time (struct cgraph_node *node, int *size,
|
||||
|
@ -3057,7 +3059,7 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size,
|
|||
inline_hints *hints,
|
||||
clause_t possible_truths,
|
||||
vec<tree> known_vals,
|
||||
vec<tree> known_binfos,
|
||||
vec<ipa_polymorphic_call_context> known_contexts,
|
||||
vec<ipa_agg_jump_function_p> known_aggs)
|
||||
{
|
||||
struct cgraph_edge *e;
|
||||
|
@ -3074,14 +3076,14 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size,
|
|||
estimate_edge_size_and_time (e, size,
|
||||
es->predicate ? NULL : min_size,
|
||||
time, REG_BR_PROB_BASE,
|
||||
known_vals, known_binfos,
|
||||
known_vals, known_contexts,
|
||||
known_aggs, hints);
|
||||
}
|
||||
else
|
||||
estimate_calls_size_and_time (e->callee, size, min_size, time,
|
||||
hints,
|
||||
possible_truths,
|
||||
known_vals, known_binfos,
|
||||
known_vals, known_contexts,
|
||||
known_aggs);
|
||||
}
|
||||
}
|
||||
|
@ -3093,14 +3095,14 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size,
|
|||
estimate_edge_size_and_time (e, size,
|
||||
es->predicate ? NULL : min_size,
|
||||
time, REG_BR_PROB_BASE,
|
||||
known_vals, known_binfos, known_aggs,
|
||||
known_vals, known_contexts, known_aggs,
|
||||
hints);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Estimate size and time needed to execute NODE assuming
|
||||
POSSIBLE_TRUTHS clause, and KNOWN_VALS, KNOWN_AGGS and KNOWN_BINFOS
|
||||
POSSIBLE_TRUTHS clause, and KNOWN_VALS, KNOWN_AGGS and KNOWN_CONTEXTS
|
||||
information about NODE's arguments. If non-NULL use also probability
|
||||
information present in INLINE_PARAM_SUMMARY vector.
|
||||
Additionally detemine hints determined by the context. Finally compute
|
||||
|
@ -3112,7 +3114,7 @@ static void
|
|||
estimate_node_size_and_time (struct cgraph_node *node,
|
||||
clause_t possible_truths,
|
||||
vec<tree> known_vals,
|
||||
vec<tree> known_binfos,
|
||||
vec<ipa_polymorphic_call_context> known_contexts,
|
||||
vec<ipa_agg_jump_function_p> known_aggs,
|
||||
int *ret_size, int *ret_min_size, int *ret_time,
|
||||
inline_hints *ret_hints,
|
||||
|
@ -3189,7 +3191,7 @@ estimate_node_size_and_time (struct cgraph_node *node,
|
|||
hints |= INLINE_HINT_declared_inline;
|
||||
|
||||
estimate_calls_size_and_time (node, &size, &min_size, &time, &hints, possible_truths,
|
||||
known_vals, known_binfos, known_aggs);
|
||||
known_vals, known_contexts, known_aggs);
|
||||
gcc_checking_assert (size >= 0);
|
||||
gcc_checking_assert (time >= 0);
|
||||
time = RDIV (time, INLINE_TIME_SCALE);
|
||||
|
@ -3212,13 +3214,14 @@ estimate_node_size_and_time (struct cgraph_node *node,
|
|||
|
||||
/* Estimate size and time needed to execute callee of EDGE assuming that
|
||||
parameters known to be constant at caller of EDGE are propagated.
|
||||
KNOWN_VALS and KNOWN_BINFOS are vectors of assumed known constant values
|
||||
KNOWN_VALS and KNOWN_CONTEXTS are vectors of assumed known constant values
|
||||
and types for parameters. */
|
||||
|
||||
void
|
||||
estimate_ipcp_clone_size_and_time (struct cgraph_node *node,
|
||||
vec<tree> known_vals,
|
||||
vec<tree> known_binfos,
|
||||
vec<ipa_polymorphic_call_context>
|
||||
known_contexts,
|
||||
vec<ipa_agg_jump_function_p> known_aggs,
|
||||
int *ret_size, int *ret_time,
|
||||
inline_hints *hints)
|
||||
|
@ -3227,7 +3230,7 @@ estimate_ipcp_clone_size_and_time (struct cgraph_node *node,
|
|||
|
||||
clause = evaluate_conditions_for_known_args (node, false, known_vals,
|
||||
known_aggs);
|
||||
estimate_node_size_and_time (node, clause, known_vals, known_binfos,
|
||||
estimate_node_size_and_time (node, clause, known_vals, known_contexts,
|
||||
known_aggs, ret_size, NULL, ret_time, hints, vNULL);
|
||||
}
|
||||
|
||||
|
@ -3672,7 +3675,7 @@ do_estimate_edge_time (struct cgraph_edge *edge)
|
|||
struct cgraph_node *callee;
|
||||
clause_t clause;
|
||||
vec<tree> known_vals;
|
||||
vec<tree> known_binfos;
|
||||
vec<ipa_polymorphic_call_context> known_contexts;
|
||||
vec<ipa_agg_jump_function_p> known_aggs;
|
||||
struct inline_edge_summary *es = inline_edge_summary (edge);
|
||||
int min_size;
|
||||
|
@ -3681,9 +3684,9 @@ do_estimate_edge_time (struct cgraph_edge *edge)
|
|||
|
||||
gcc_checking_assert (edge->inline_failed);
|
||||
evaluate_properties_for_edge (edge, true,
|
||||
&clause, &known_vals, &known_binfos,
|
||||
&clause, &known_vals, &known_contexts,
|
||||
&known_aggs);
|
||||
estimate_node_size_and_time (callee, clause, known_vals, known_binfos,
|
||||
estimate_node_size_and_time (callee, clause, known_vals, known_contexts,
|
||||
known_aggs, &size, &min_size, &time, &hints, es->param);
|
||||
|
||||
/* When we have profile feedback, we can quite safely identify hot
|
||||
|
@ -3697,7 +3700,7 @@ do_estimate_edge_time (struct cgraph_edge *edge)
|
|||
hints |= INLINE_HINT_known_hot;
|
||||
|
||||
known_vals.release ();
|
||||
known_binfos.release ();
|
||||
known_contexts.release ();
|
||||
known_aggs.release ();
|
||||
gcc_checking_assert (size >= 0);
|
||||
gcc_checking_assert (time >= 0);
|
||||
|
@ -3728,7 +3731,7 @@ do_estimate_edge_size (struct cgraph_edge *edge)
|
|||
struct cgraph_node *callee;
|
||||
clause_t clause;
|
||||
vec<tree> known_vals;
|
||||
vec<tree> known_binfos;
|
||||
vec<ipa_polymorphic_call_context> known_contexts;
|
||||
vec<ipa_agg_jump_function_p> known_aggs;
|
||||
|
||||
/* When we do caching, use do_estimate_edge_time to populate the entry. */
|
||||
|
@ -3746,12 +3749,12 @@ do_estimate_edge_size (struct cgraph_edge *edge)
|
|||
/* Early inliner runs without caching, go ahead and do the dirty work. */
|
||||
gcc_checking_assert (edge->inline_failed);
|
||||
evaluate_properties_for_edge (edge, true,
|
||||
&clause, &known_vals, &known_binfos,
|
||||
&clause, &known_vals, &known_contexts,
|
||||
&known_aggs);
|
||||
estimate_node_size_and_time (callee, clause, known_vals, known_binfos,
|
||||
estimate_node_size_and_time (callee, clause, known_vals, known_contexts,
|
||||
known_aggs, &size, NULL, NULL, NULL, vNULL);
|
||||
known_vals.release ();
|
||||
known_binfos.release ();
|
||||
known_contexts.release ();
|
||||
known_aggs.release ();
|
||||
return size;
|
||||
}
|
||||
|
@ -3767,7 +3770,7 @@ do_estimate_edge_hints (struct cgraph_edge *edge)
|
|||
struct cgraph_node *callee;
|
||||
clause_t clause;
|
||||
vec<tree> known_vals;
|
||||
vec<tree> known_binfos;
|
||||
vec<ipa_polymorphic_call_context> known_contexts;
|
||||
vec<ipa_agg_jump_function_p> known_aggs;
|
||||
|
||||
/* When we do caching, use do_estimate_edge_time to populate the entry. */
|
||||
|
@ -3785,12 +3788,12 @@ do_estimate_edge_hints (struct cgraph_edge *edge)
|
|||
/* Early inliner runs without caching, go ahead and do the dirty work. */
|
||||
gcc_checking_assert (edge->inline_failed);
|
||||
evaluate_properties_for_edge (edge, true,
|
||||
&clause, &known_vals, &known_binfos,
|
||||
&clause, &known_vals, &known_contexts,
|
||||
&known_aggs);
|
||||
estimate_node_size_and_time (callee, clause, known_vals, known_binfos,
|
||||
estimate_node_size_and_time (callee, clause, known_vals, known_contexts,
|
||||
known_aggs, NULL, NULL, NULL, &hints, vNULL);
|
||||
known_vals.release ();
|
||||
known_binfos.release ();
|
||||
known_contexts.release ();
|
||||
known_aggs.release ();
|
||||
hints |= simple_edge_hints (edge);
|
||||
return hints;
|
||||
|
|
|
@ -223,7 +223,8 @@ void initialize_inline_failed (struct cgraph_edge *);
|
|||
int estimate_time_after_inlining (struct cgraph_node *, struct cgraph_edge *);
|
||||
int estimate_size_after_inlining (struct cgraph_node *, struct cgraph_edge *);
|
||||
void estimate_ipcp_clone_size_and_time (struct cgraph_node *,
|
||||
vec<tree>, vec<tree>,
|
||||
vec<tree>,
|
||||
vec<ipa_polymorphic_call_context>,
|
||||
vec<ipa_agg_jump_function_p>,
|
||||
int *, int *, inline_hints *);
|
||||
int do_estimate_growth (struct cgraph_node *);
|
||||
|
|
|
@ -599,10 +599,11 @@ decl_maybe_in_construction_p (tree base, tree outer_type,
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Dump human readable context to F. */
|
||||
/* Dump human readable context to F. If NEWLINE is true, it will be terminated
|
||||
by a newline. */
|
||||
|
||||
void
|
||||
ipa_polymorphic_call_context::dump (FILE *f) const
|
||||
ipa_polymorphic_call_context::dump (FILE *f, bool newline) const
|
||||
{
|
||||
fprintf (f, " ");
|
||||
if (invalid)
|
||||
|
@ -634,7 +635,8 @@ ipa_polymorphic_call_context::dump (FILE *f) const
|
|||
speculative_offset);
|
||||
}
|
||||
}
|
||||
fprintf(f, "\n");
|
||||
if (newline)
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
/* Print context to stderr. */
|
||||
|
@ -2130,3 +2132,47 @@ ipa_polymorphic_call_context::possible_dynamic_type_change (bool in_poly_cdtor,
|
|||
else if (in_poly_cdtor)
|
||||
maybe_in_construction = true;
|
||||
}
|
||||
|
||||
/* Return TRUE if this context conveys the same information as OTHER. */
|
||||
|
||||
bool
|
||||
ipa_polymorphic_call_context::equal_to
|
||||
(const ipa_polymorphic_call_context &x) const
|
||||
{
|
||||
if (useless_p ())
|
||||
return x.useless_p ();
|
||||
if (invalid)
|
||||
return x.invalid;
|
||||
if (x.useless_p () || x.invalid)
|
||||
return false;
|
||||
|
||||
if (outer_type)
|
||||
{
|
||||
if (!x.outer_type
|
||||
|| !types_odr_comparable (outer_type, x.outer_type)
|
||||
|| !types_same_for_odr (outer_type, x.outer_type)
|
||||
|| offset != x.offset
|
||||
|| maybe_in_construction != x.maybe_in_construction
|
||||
|| maybe_derived_type != x.maybe_derived_type
|
||||
|| dynamic != x.dynamic)
|
||||
return false;
|
||||
}
|
||||
else if (x.outer_type)
|
||||
return false;
|
||||
|
||||
if (speculative_outer_type)
|
||||
{
|
||||
if (!x.speculative_outer_type
|
||||
|| !types_odr_comparable (speculative_outer_type,
|
||||
x.speculative_outer_type)
|
||||
|| !types_same_for_odr (speculative_outer_type,
|
||||
x.speculative_outer_type)
|
||||
|| speculative_offset != x.speculative_offset
|
||||
|| speculative_maybe_derived_type != x.speculative_maybe_derived_type)
|
||||
return false;
|
||||
}
|
||||
else if (x.speculative_outer_type)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
157
gcc/ipa-prop.c
157
gcc/ipa-prop.c
|
@ -380,8 +380,14 @@ ipa_print_node_jump_functions_for_edge (FILE *f, struct cgraph_edge *cs)
|
|||
fprintf (f, "\n");
|
||||
}
|
||||
}
|
||||
if (IPA_EDGE_REF (cs)->polymorphic_call_contexts)
|
||||
ipa_get_ith_polymorhic_call_context (IPA_EDGE_REF (cs), i)->dump (f);
|
||||
|
||||
struct ipa_polymorphic_call_context *ctx
|
||||
= ipa_get_ith_polymorhic_call_context (IPA_EDGE_REF (cs), i);
|
||||
if (ctx && !ctx->useless_p ())
|
||||
{
|
||||
fprintf (f, " Context: ");
|
||||
ctx->dump (dump_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -559,7 +565,8 @@ ipa_set_ancestor_jf (struct ipa_jump_func *jfunc, HOST_WIDE_INT offset,
|
|||
type = NULL_TREE;
|
||||
if (type)
|
||||
type = TYPE_MAIN_VARIANT (type);
|
||||
gcc_assert (!type_preserved || contains_polymorphic_type_p (type));
|
||||
if (!type || !contains_polymorphic_type_p (type))
|
||||
type_preserved = false;
|
||||
jfunc->type = IPA_JF_ANCESTOR;
|
||||
jfunc->value.ancestor.formal_id = formal_id;
|
||||
jfunc->value.ancestor.offset = offset;
|
||||
|
@ -2622,9 +2629,12 @@ combine_known_type_and_ancestor_jfs (struct ipa_jump_func *src,
|
|||
+ ipa_get_jf_ancestor_offset (dst);
|
||||
combined_type = ipa_get_jf_ancestor_type (dst);
|
||||
|
||||
ipa_set_jf_known_type (dst, combined_offset,
|
||||
ipa_get_jf_known_type_base_type (src),
|
||||
combined_type);
|
||||
if (combined_type)
|
||||
ipa_set_jf_known_type (dst, combined_offset,
|
||||
ipa_get_jf_known_type_base_type (src),
|
||||
combined_type);
|
||||
else
|
||||
dst->type = IPA_JF_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Update the jump functions associated with call graph edge E when the call
|
||||
|
@ -2669,7 +2679,7 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs,
|
|||
struct ipa_polymorphic_call_context ctx = *src_ctx;
|
||||
|
||||
/* TODO: Make type preserved safe WRT contexts. */
|
||||
if (!dst->value.ancestor.agg_preserved)
|
||||
if (!ipa_get_jf_ancestor_type_preserved (dst))
|
||||
ctx.possible_dynamic_type_change (e->in_polymorphic_cdtor);
|
||||
ctx.offset_by (dst->value.ancestor.offset);
|
||||
if (!ctx.useless_p ())
|
||||
|
@ -2678,6 +2688,7 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs,
|
|||
count);
|
||||
dst_ctx = ipa_get_ith_polymorhic_call_context (args, i);
|
||||
}
|
||||
dst_ctx->combine_with (ctx);
|
||||
}
|
||||
|
||||
if (src->agg.items
|
||||
|
@ -2739,7 +2750,7 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs,
|
|||
struct ipa_polymorphic_call_context ctx = *src_ctx;
|
||||
|
||||
/* TODO: Make type preserved safe WRT contexts. */
|
||||
if (!dst->value.ancestor.agg_preserved)
|
||||
if (!ipa_get_jf_pass_through_type_preserved (dst))
|
||||
ctx.possible_dynamic_type_change (e->in_polymorphic_cdtor);
|
||||
if (!ctx.useless_p ())
|
||||
{
|
||||
|
@ -3152,41 +3163,24 @@ ipa_impossible_devirt_target (struct cgraph_edge *ie, tree target)
|
|||
/* Try to find a destination for indirect edge IE that corresponds to a virtual
|
||||
call based on a formal parameter which is described by jump function JFUNC
|
||||
and if it can be determined, make it direct and return the direct edge.
|
||||
Otherwise, return NULL. NEW_ROOT_INFO is the node info that JFUNC lattices
|
||||
are relative to. */
|
||||
Otherwise, return NULL. CTX describes the polymorphic context that the
|
||||
parameter the call is based on brings along with it. */
|
||||
|
||||
static struct cgraph_edge *
|
||||
try_make_edge_direct_virtual_call (struct cgraph_edge *ie,
|
||||
struct ipa_jump_func *jfunc,
|
||||
struct ipa_node_params *new_root_info,
|
||||
struct ipa_polymorphic_call_context *ctx_ptr)
|
||||
struct ipa_polymorphic_call_context ctx)
|
||||
{
|
||||
tree binfo, target = NULL;
|
||||
tree target = NULL;
|
||||
bool speculative = false;
|
||||
bool updated = false;
|
||||
|
||||
if (!flag_devirtualize)
|
||||
return NULL;
|
||||
|
||||
/* If this is call of a function parameter, restrict its type
|
||||
based on knowlede of the context. */
|
||||
if (ctx_ptr && !ie->indirect_info->by_ref)
|
||||
{
|
||||
struct ipa_polymorphic_call_context ctx = *ctx_ptr;
|
||||
|
||||
ctx.offset_by (ie->indirect_info->offset);
|
||||
|
||||
if (ie->indirect_info->vptr_changed)
|
||||
ctx.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
|
||||
ie->indirect_info->otr_type);
|
||||
|
||||
updated = ie->indirect_info->context.combine_with
|
||||
(ctx, ie->indirect_info->otr_type);
|
||||
}
|
||||
gcc_assert (!ie->indirect_info->by_ref);
|
||||
|
||||
/* Try to do lookup via known virtual table pointer value. */
|
||||
if (!ie->indirect_info->by_ref
|
||||
&& (!ie->indirect_info->vptr_changed || flag_devirtualize_speculatively))
|
||||
if (!ie->indirect_info->vptr_changed || flag_devirtualize_speculatively)
|
||||
{
|
||||
tree vtable;
|
||||
unsigned HOST_WIDE_INT offset;
|
||||
|
@ -3217,67 +3211,44 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie,
|
|||
}
|
||||
}
|
||||
|
||||
binfo = ipa_value_from_jfunc (new_root_info, jfunc);
|
||||
ipa_polymorphic_call_context ie_context (ie);
|
||||
vec <cgraph_node *>targets;
|
||||
bool final;
|
||||
|
||||
if (binfo && TREE_CODE (binfo) != TREE_BINFO)
|
||||
ctx.offset_by (ie->indirect_info->offset);
|
||||
if (ie->indirect_info->vptr_changed)
|
||||
ctx.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
|
||||
ie->indirect_info->otr_type);
|
||||
ctx.combine_with (ie_context, ie->indirect_info->otr_type);
|
||||
targets = possible_polymorphic_call_targets
|
||||
(ie->indirect_info->otr_type,
|
||||
ie->indirect_info->otr_token,
|
||||
ctx, &final);
|
||||
if (final && targets.length () <= 1)
|
||||
{
|
||||
struct ipa_polymorphic_call_context ctx (binfo,
|
||||
ie->indirect_info->otr_type,
|
||||
ie->indirect_info->offset);
|
||||
updated |= ie->indirect_info->context.combine_with
|
||||
(ctx, ie->indirect_info->otr_type);
|
||||
if (targets.length () == 1)
|
||||
target = targets[0]->decl;
|
||||
else
|
||||
target = ipa_impossible_devirt_target (ie, NULL_TREE);
|
||||
}
|
||||
|
||||
if (updated)
|
||||
else if (!target && flag_devirtualize_speculatively
|
||||
&& !ie->speculative && ie->maybe_hot_p ())
|
||||
{
|
||||
ipa_polymorphic_call_context context (ie);
|
||||
vec <cgraph_node *>targets;
|
||||
bool final;
|
||||
|
||||
targets = possible_polymorphic_call_targets
|
||||
(ie->indirect_info->otr_type,
|
||||
ie->indirect_info->otr_token,
|
||||
context, &final);
|
||||
if (final && targets.length () <= 1)
|
||||
cgraph_node *n;
|
||||
n = try_speculative_devirtualization (ie->indirect_info->otr_type,
|
||||
ie->indirect_info->otr_token,
|
||||
ie->indirect_info->context);
|
||||
if (n)
|
||||
{
|
||||
if (targets.length () == 1)
|
||||
target = targets[0]->decl;
|
||||
else
|
||||
target = ipa_impossible_devirt_target (ie, NULL_TREE);
|
||||
}
|
||||
else if (!target && flag_devirtualize_speculatively
|
||||
&& !ie->speculative && ie->maybe_hot_p ())
|
||||
{
|
||||
cgraph_node *n = try_speculative_devirtualization (ie->indirect_info->otr_type,
|
||||
ie->indirect_info->otr_token,
|
||||
ie->indirect_info->context);
|
||||
if (n)
|
||||
{
|
||||
target = n->decl;
|
||||
speculative = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (binfo && TREE_CODE (binfo) == TREE_BINFO)
|
||||
{
|
||||
binfo = get_binfo_at_offset (binfo, ie->indirect_info->offset,
|
||||
ie->indirect_info->otr_type);
|
||||
if (binfo)
|
||||
{
|
||||
tree t = gimple_get_virt_method_for_binfo (ie->indirect_info->otr_token,
|
||||
binfo);
|
||||
if (t)
|
||||
{
|
||||
target = t;
|
||||
speculative = false;
|
||||
}
|
||||
target = n->decl;
|
||||
speculative = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (target)
|
||||
{
|
||||
if (!possible_polymorphic_call_target_p (ie, cgraph_node::get_create (target)))
|
||||
if (!possible_polymorphic_call_target_p
|
||||
(ie, cgraph_node::get_create (target)))
|
||||
{
|
||||
if (speculative)
|
||||
return NULL;
|
||||
|
@ -3336,11 +3307,9 @@ update_indirect_edges_after_inlining (struct cgraph_edge *cs,
|
|||
new_direct_edge = NULL;
|
||||
else if (ici->polymorphic)
|
||||
{
|
||||
ipa_polymorphic_call_context *ctx;
|
||||
ctx = ipa_get_ith_polymorhic_call_context (top, param_index);
|
||||
new_direct_edge = try_make_edge_direct_virtual_call (ie, jfunc,
|
||||
new_root_info,
|
||||
ctx);
|
||||
ipa_polymorphic_call_context ctx;
|
||||
ctx = ipa_context_from_jfunc (new_root_info, cs, param_index, jfunc);
|
||||
new_direct_edge = try_make_edge_direct_virtual_call (ie, jfunc, ctx);
|
||||
}
|
||||
else
|
||||
new_direct_edge = try_make_edge_direct_simple_call (ie, jfunc,
|
||||
|
@ -3474,7 +3443,7 @@ propagate_controlled_uses (struct cgraph_edge *cs)
|
|||
{
|
||||
struct cgraph_node *n;
|
||||
struct ipa_ref *ref;
|
||||
tree t = new_root_info->known_vals[src_idx];
|
||||
tree t = new_root_info->known_csts[src_idx];
|
||||
|
||||
if (t && TREE_CODE (t) == ADDR_EXPR
|
||||
&& TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL
|
||||
|
@ -3617,7 +3586,8 @@ ipa_free_node_params_substructures (struct ipa_node_params *info)
|
|||
free (info->lattices);
|
||||
/* Lattice values and their sources are deallocated with their alocation
|
||||
pool. */
|
||||
info->known_vals.release ();
|
||||
info->known_csts.release ();
|
||||
info->known_contexts.release ();
|
||||
memset (info, 0, sizeof (*info));
|
||||
}
|
||||
|
||||
|
@ -3892,7 +3862,8 @@ ipa_free_all_structures_after_ipa_cp (void)
|
|||
ipa_free_all_edge_args ();
|
||||
ipa_free_all_node_params ();
|
||||
free_alloc_pool (ipcp_sources_pool);
|
||||
free_alloc_pool (ipcp_values_pool);
|
||||
free_alloc_pool (ipcp_cst_values_pool);
|
||||
free_alloc_pool (ipcp_poly_ctx_values_pool);
|
||||
free_alloc_pool (ipcp_agg_lattice_pool);
|
||||
ipa_unregister_cgraph_hooks ();
|
||||
if (ipa_refdesc_pool)
|
||||
|
@ -3911,8 +3882,10 @@ ipa_free_all_structures_after_iinln (void)
|
|||
ipa_unregister_cgraph_hooks ();
|
||||
if (ipcp_sources_pool)
|
||||
free_alloc_pool (ipcp_sources_pool);
|
||||
if (ipcp_values_pool)
|
||||
free_alloc_pool (ipcp_values_pool);
|
||||
if (ipcp_cst_values_pool)
|
||||
free_alloc_pool (ipcp_cst_values_pool);
|
||||
if (ipcp_poly_ctx_values_pool)
|
||||
free_alloc_pool (ipcp_poly_ctx_values_pool);
|
||||
if (ipcp_agg_lattice_pool)
|
||||
free_alloc_pool (ipcp_agg_lattice_pool);
|
||||
if (ipa_refdesc_pool)
|
||||
|
|
|
@ -278,13 +278,14 @@ ipa_get_jf_pass_through_agg_preserved (struct ipa_jump_func *jfunc)
|
|||
return jfunc->value.pass_through.agg_preserved;
|
||||
}
|
||||
|
||||
/* Return the type_preserved flag of a pass through jump function JFUNC. */
|
||||
/* Return true if pass through jump function JFUNC preserves type
|
||||
information. */
|
||||
|
||||
static inline bool
|
||||
ipa_get_jf_pass_through_type_preserved (struct ipa_jump_func *jfunc)
|
||||
{
|
||||
gcc_checking_assert (jfunc->type == IPA_JF_PASS_THROUGH);
|
||||
return jfunc->value.pass_through.type_preserved;
|
||||
return jfunc->value.pass_through.agg_preserved;
|
||||
}
|
||||
|
||||
/* Return the offset of an ancestor jump function JFUNC. */
|
||||
|
@ -324,13 +325,13 @@ ipa_get_jf_ancestor_agg_preserved (struct ipa_jump_func *jfunc)
|
|||
return jfunc->value.ancestor.agg_preserved;
|
||||
}
|
||||
|
||||
/* Return the type_preserved flag of an ancestor jump function JFUNC. */
|
||||
/* Return true if ancestor jump function JFUNC presrves type information. */
|
||||
|
||||
static inline bool
|
||||
ipa_get_jf_ancestor_type_preserved (struct ipa_jump_func *jfunc)
|
||||
{
|
||||
gcc_checking_assert (jfunc->type == IPA_JF_ANCESTOR);
|
||||
return jfunc->value.ancestor.type_preserved;
|
||||
return jfunc->value.ancestor.agg_preserved;
|
||||
}
|
||||
|
||||
/* Summary describing a single formal parameter. */
|
||||
|
@ -363,9 +364,12 @@ struct ipa_node_params
|
|||
/* Only for versioned nodes this field would not be NULL,
|
||||
it points to the node that IPA cp cloned from. */
|
||||
struct cgraph_node *ipcp_orig_node;
|
||||
/* If this node is an ipa-cp clone, these are the known values that describe
|
||||
what it has been specialized for. */
|
||||
vec<tree> known_vals;
|
||||
/* If this node is an ipa-cp clone, these are the known constants that
|
||||
describe what it has been specialized for. */
|
||||
vec<tree> known_csts;
|
||||
/* If this node is an ipa-cp clone, these are the known polymorphic contexts
|
||||
that describe what it has been specialized for. */
|
||||
vec<ipa_polymorphic_call_context> known_contexts;
|
||||
/* Whether the param uses analysis and jump function computation has already
|
||||
been performed. */
|
||||
unsigned analysis_done : 1;
|
||||
|
@ -592,7 +596,7 @@ bool ipa_propagate_indirect_call_infos (struct cgraph_edge *cs,
|
|||
/* Indirect edge and binfo processing. */
|
||||
tree ipa_get_indirect_edge_target (struct cgraph_edge *ie,
|
||||
vec<tree> ,
|
||||
vec<tree> ,
|
||||
vec<ipa_polymorphic_call_context>,
|
||||
vec<ipa_agg_jump_function_p> );
|
||||
struct cgraph_edge *ipa_make_edge_direct_to_target (struct cgraph_edge *, tree,
|
||||
bool speculative = false);
|
||||
|
@ -615,7 +619,8 @@ void ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node);
|
|||
void ipa_print_all_jump_functions (FILE * f);
|
||||
void ipcp_verify_propagated_values (void);
|
||||
|
||||
extern alloc_pool ipcp_values_pool;
|
||||
extern alloc_pool ipcp_cst_values_pool;
|
||||
extern alloc_pool ipcp_poly_ctx_values_pool;
|
||||
extern alloc_pool ipcp_sources_pool;
|
||||
extern alloc_pool ipcp_agg_lattice_pool;
|
||||
|
||||
|
@ -716,6 +721,10 @@ int ipa_get_param_decl_index (struct ipa_node_params *, tree);
|
|||
tree ipa_value_from_jfunc (struct ipa_node_params *info,
|
||||
struct ipa_jump_func *jfunc);
|
||||
unsigned int ipcp_transform_function (struct cgraph_node *node);
|
||||
ipa_polymorphic_call_context ipa_context_from_jfunc (ipa_node_params *,
|
||||
cgraph_edge *,
|
||||
int,
|
||||
ipa_jump_func *);
|
||||
void ipa_dump_param (FILE *, struct ipa_node_params *info, int i);
|
||||
bool ipa_modify_expr (tree *, bool, ipa_parm_adjustment_vec);
|
||||
ipa_parm_adjustment *ipa_get_adjustment_candidate (tree **, bool *,
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
2014-11-14 Martin Jambor <mjambor@suse.cz>
|
||||
|
||||
* g++.dg/ipa/devirt-11.C: Dont't run ipa-cp, remove times constraint
|
||||
from the dump scan.
|
||||
* g++.dg/ipa/devirt-21.C: Xfail.
|
||||
* g++.dg/ipa/devirt-24.C: Likewise.
|
||||
* g++.dg/ipa/devirt-10.C: Removed times constraint from the dump scan.
|
||||
* g++.dg/ipa/devirt-41.C: Updated the dump scan.
|
||||
* g++.dg/ipa/devirt-44.C: Likewise.
|
||||
* g++.dg/ipa/devirt-43.C: Xfail.
|
||||
|
||||
2014-11-14 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* g++.dg/abi/abi-tag11.C: New.
|
||||
|
|
|
@ -27,8 +27,6 @@ struct wxBufferedPaintDC : public wxBufferedDC {
|
|||
void OnPaint(wxPaintEvent & event) {
|
||||
wxBufferedPaintDC dc;
|
||||
}
|
||||
/* IPA-CP should really discover both cases, but for time being the second is handled by inliner. */
|
||||
/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target" 1 "inline" } } */
|
||||
/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target" 1 "cp" } } */
|
||||
/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target" 2 "cp" } } */
|
||||
/* { dg-final { cleanup-ipa-dump "inline" } } */
|
||||
/* { dg-final { cleanup-ipa-dump "cp" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-ipa-inline -fno-devirtualize-speculatively" } */
|
||||
/* { dg-options "-O2 -fno-ipa-cp -fdump-ipa-inline -fno-devirtualize-speculatively" } */
|
||||
int baz ();
|
||||
struct A
|
||||
{
|
||||
|
@ -42,7 +42,5 @@ bar ()
|
|||
baz ();
|
||||
c + d;
|
||||
}
|
||||
/* While inlining function called once we should devirtualize a new call to fn3.
|
||||
Because fn2 is already removed, we should not devirtualize. */
|
||||
/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target" 1 "inline" } } */
|
||||
/* { dg-final { scan-ipa-dump "Discovered a virtual call to a known target" "inline" } } */
|
||||
/* { dg-final { cleanup-ipa-dump "inline" } } */
|
||||
|
|
|
@ -37,5 +37,5 @@ main()
|
|||
{
|
||||
class C c;
|
||||
}
|
||||
/* { dg-final { scan-ipa-dump "Discovered a virtual call to" "cp" { xfail *-*-* } } } */
|
||||
/* { dg-final { scan-ipa-dump "Discovered a virtual call to" "cp" } } */
|
||||
/* { dg-final { cleanup-ipa-dump "cp" } } */
|
||||
|
|
|
@ -36,7 +36,7 @@ C *b = new (C);
|
|||
sort(f, *b);
|
||||
}
|
||||
}
|
||||
/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target" 1 "inline" } } */
|
||||
/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target" 1 "inline" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-ipa-dump "inline" } } */
|
||||
/* { dg-final { scan-ipa-dump-times "Aggregate passed by reference" 1 "cp" } } */
|
||||
/* { dg-final { cleanup-ipa-dump "cp" } } */
|
||||
|
|
|
@ -26,6 +26,6 @@ main()
|
|||
|
||||
Because the type is in static storage, we know it won't change type in dostuff
|
||||
and from callstack we can tell that is is not in construction/destruction. */
|
||||
/* { dg-final { scan-ipa-dump-times "First type is base of second" 1 "inline" } } */
|
||||
/* { dg-final { scan-ipa-dump "Second type is base of first" "inline" } } */
|
||||
/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target" 1 "inline" } } */
|
||||
/* { dg-final { cleanup-ipa-dump "inline" } } */
|
||||
|
|
|
@ -23,5 +23,5 @@ t(struct B *b)
|
|||
of type B. This makes A fully specified and we know C::foo is unlikely.
|
||||
FIXME: We could most probably can devirtualize unconditonally because dereference of b in
|
||||
&b->a makes the type known. GIMPLE does not represent this. */
|
||||
/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a speculative target" 1 "inline" } } */
|
||||
/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a speculative target" 1 "inline" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-ipa-dump "inline" } } */
|
||||
|
|
|
@ -26,7 +26,7 @@ main()
|
|||
/* Here one invocation of foo is while type is in construction, while other is not.
|
||||
Check that we handle that. */
|
||||
|
||||
/* { dg-final { scan-ipa-dump-times "First type is base of second" 1 "inline" } } */
|
||||
/* { dg-final { scan-ipa-dump "Second type is base of first" "inline" } } */
|
||||
/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target\[^\\n\]*A::foo" 1 "inline" } } */
|
||||
/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target\[^\\n\]*B::foo" 1 "inline" } } */
|
||||
/* { dg-final { cleanup-ipa-dump "inline" } } */
|
||||
|
|
Loading…
Reference in New Issue