Commit eb270950 by Feng Xue Committed by Feng Xue

Support extended aggregate jump function in ipa-cp

2019-11-14  Feng Xue  <fxue@os.amperecomputing.com>

	PR ipa/91682
	* ipa-prop.h (jump_func_type): New value IPA_JF_LOAD_AGG.
	(ipa_load_agg_data, ipa_agg_value, ipa_agg_value_set): New structs.
	(ipa_agg_jf_item): Add new field jftype and type, redefine field value.
	(ipa_agg_jump_function): Remove member function equal_to.
	(ipa_agg_jump_function_p): Remove typedef.
	(ipa_copy_agg_values, ipa_release_agg_values): New functions.
	* ipa-prop.c (ipa_print_node_jump_functions_for_edge): Dump
	information for aggregate jump function.
	(get_ssa_def_if_simple_copy): Add new parameter rhs_stmt to
	record last definition statement.
	(load_from_unmodified_param_or_agg): New function.
	(ipa_known_agg_contents_list): Add new field type and value, remove
	field constant.
	(build_agg_jump_func_from_list): Rename parameter const_count to
	value_count, build aggregate jump function from ipa_load_agg_data.
	(analyze_agg_content_value): New function.
	(extract_mem_content): Analyze memory store assignment to prepare
	information for aggregate jump function generation.
	(determine_known_aggregate_parts): Add new parameter fbi, remove
	parameter aa_walk_budeget_p.
	(update_jump_functions_after_inlining): Update aggregate jump function.
	(ipa_find_agg_cst_for_param): Change type of parameter agg.
	(try_make_edge_direct_simple_call): Add new parameter new_root.
	(try_make_edge_direct_virtual_call): Add new parameter new_root and
	new_root_info.
	(update_indirect_edges_after_inlining): Pass new argument to
	try_make_edge_direct_simple_call and try_make_edge_direct_virtual_call.
	(ipa_write_jump_function): Write aggregate jump function to file.
	(ipa_read_jump_function): Read aggregate jump function from file.
	(ipa_agg_value::equal_to): Migrate from ipa_agg_jf_item::equal_to.
	* ipa-cp.c (ipa_get_jf_arith_result): New function.
	(ipa_agg_value_from_node): Likewise.
	(ipa_agg_value_set_from_jfunc): Likewise.
	(propagate_vals_across_arith_jfunc): Likewise.
	(propagate_aggregate_lattice): Likewise.
	(ipa_get_jf_pass_through_result): Call ipa_get_jf_arith_result.
	(propagate_vals_across_pass_through): Call
	propagate_vals_across_arith_jfunc.
	(get_clone_agg_value): Move forward.
	(propagate_aggs_across_jump_function): Handle value propagation for
	aggregate jump function.
	(agg_jmp_p_vec_for_t_vec): Remove.
	(context_independent_aggregate_values): Replace vec<ipa_agg_jf_item>
	with vec<ipa_agg_value>.
	(copy_plats_to_inter, intersect_with_plats): Likewise.
	(agg_replacements_to_vector, intersect_with_agg_replacements): Likewise.
	(intersect_aggregate_with_edge): Likewise.
	(find_aggregate_values_for_callers_subset): Likewise.
	(cgraph_edge_brings_all_agg_vals_for_node): Likewise.
	(estimate_local_effects): Replace vec<ipa_agg_jump_function> and
	vec<ipa_agg_jump_function_p> with vec<ipa_agg_value_set>.
	(gather_context_independent_values): Likewise.
	(perform_estimation_of_a_value, decide_whether_version_node): Likewise.
	* ipa-fnsummary.c (evaluate_conditions_for_known_args): Replace
	vec<ipa_agg_jump_function_p> with vec<ipa_agg_value_set>.
	(evaluate_properties_for_edge): Likewise.
	(estimate_edge_devirt_benefit): Likewise.
	(estimate_edge_size_and_time):  Likewise.
	(estimate_calls_size_and_time): Likewise.
	(ipa_call_context::ipa_call_context): Likewise.
	(estimate_ipcp_clone_size_and_time):  Likewise.
	* ipa-fnsummary.h (ipa_call_context): Replace
	vec<ipa_agg_jump_function_p> with vec<ipa_agg_value_set>.
	* ipa-inline-analysis.c (do_estimate_edge_time): Replace
	vec<ipa_agg_jump_function_p> with vec<ipa_agg_value_set>.
	(do_estimate_edge_size): Likewise.
	(do_estimate_edge_hints): Likewise.

2019-11-14  Feng Xue  <fxue@os.amperecomputing.com>

        PR ipa/91682
        * gcc.dg/ipa/ipcp-agg-10.c: Change dg-scan string.
        * gcc.dg/ipa/ipcp-agg-11.c: New test.

From-SVN: r278193
parent 3e7cf2e6
2019-11-14 Feng Xue <fxue@os.amperecomputing.com>
PR ipa/91682
* ipa-prop.h (jump_func_type): New value IPA_JF_LOAD_AGG.
(ipa_load_agg_data, ipa_agg_value, ipa_agg_value_set): New structs.
(ipa_agg_jf_item): Add new field jftype and type, redefine field value.
(ipa_agg_jump_function): Remove member function equal_to.
(ipa_agg_jump_function_p): Remove typedef.
(ipa_copy_agg_values, ipa_release_agg_values): New functions.
* ipa-prop.c (ipa_print_node_jump_functions_for_edge): Dump
information for aggregate jump function.
(get_ssa_def_if_simple_copy): Add new parameter rhs_stmt to
record last definition statement.
(load_from_unmodified_param_or_agg): New function.
(ipa_known_agg_contents_list): Add new field type and value, remove
field constant.
(build_agg_jump_func_from_list): Rename parameter const_count to
value_count, build aggregate jump function from ipa_load_agg_data.
(analyze_agg_content_value): New function.
(extract_mem_content): Analyze memory store assignment to prepare
information for aggregate jump function generation.
(determine_known_aggregate_parts): Add new parameter fbi, remove
parameter aa_walk_budeget_p.
(update_jump_functions_after_inlining): Update aggregate jump function.
(ipa_find_agg_cst_for_param): Change type of parameter agg.
(try_make_edge_direct_simple_call): Add new parameter new_root.
(try_make_edge_direct_virtual_call): Add new parameter new_root and
new_root_info.
(update_indirect_edges_after_inlining): Pass new argument to
try_make_edge_direct_simple_call and try_make_edge_direct_virtual_call.
(ipa_write_jump_function): Write aggregate jump function to file.
(ipa_read_jump_function): Read aggregate jump function from file.
(ipa_agg_value::equal_to): Migrate from ipa_agg_jf_item::equal_to.
* ipa-cp.c (ipa_get_jf_arith_result): New function.
(ipa_agg_value_from_node): Likewise.
(ipa_agg_value_set_from_jfunc): Likewise.
(propagate_vals_across_arith_jfunc): Likewise.
(propagate_aggregate_lattice): Likewise.
(ipa_get_jf_pass_through_result): Call ipa_get_jf_arith_result.
(propagate_vals_across_pass_through): Call
propagate_vals_across_arith_jfunc.
(get_clone_agg_value): Move forward.
(propagate_aggs_across_jump_function): Handle value propagation for
aggregate jump function.
(agg_jmp_p_vec_for_t_vec): Remove.
(context_independent_aggregate_values): Replace vec<ipa_agg_jf_item>
with vec<ipa_agg_value>.
(copy_plats_to_inter, intersect_with_plats): Likewise.
(agg_replacements_to_vector, intersect_with_agg_replacements): Likewise.
(intersect_aggregate_with_edge): Likewise.
(find_aggregate_values_for_callers_subset): Likewise.
(cgraph_edge_brings_all_agg_vals_for_node): Likewise.
(estimate_local_effects): Replace vec<ipa_agg_jump_function> and
vec<ipa_agg_jump_function_p> with vec<ipa_agg_value_set>.
(gather_context_independent_values): Likewise.
(perform_estimation_of_a_value, decide_whether_version_node): Likewise.
* ipa-fnsummary.c (evaluate_conditions_for_known_args): Replace
vec<ipa_agg_jump_function_p> with vec<ipa_agg_value_set>.
(evaluate_properties_for_edge): Likewise.
(estimate_edge_devirt_benefit): Likewise.
(estimate_edge_size_and_time): Likewise.
(estimate_calls_size_and_time): Likewise.
(ipa_call_context::ipa_call_context): Likewise.
(estimate_ipcp_clone_size_and_time): Likewise.
* ipa-fnsummary.h (ipa_call_context): Replace
vec<ipa_agg_jump_function_p> with vec<ipa_agg_value_set>.
* ipa-inline-analysis.c (do_estimate_edge_time): Replace
vec<ipa_agg_jump_function_p> with vec<ipa_agg_value_set>.
(do_estimate_edge_size): Likewise.
(do_estimate_edge_hints): Likewise.
2019-11-13 Jan Hubicka <hubicka@ucw.cz>
* ipa-cp.c (propagate_vr_across_jump_function): Propagate also across
......@@ -306,9 +306,9 @@ set_hint_predicate (predicate **p, predicate new_predicate)
the fact that parameter is indeed a constant.
KNOWN_VALS is partial mapping of parameters of NODE to constant values.
KNOWN_AGGS is a vector of aggreggate jump functions for each parameter.
Return clause of possible truths. When INLINE_P is true, assume that we are
inlining.
KNOWN_AGGS is a vector of aggreggate known offset/value set for each
parameter. Return clause of possible truths. When INLINE_P is true, assume
that we are inlining.
ERROR_MARK means compile time invariant. */
......@@ -316,8 +316,7 @@ static void
evaluate_conditions_for_known_args (struct cgraph_node *node,
bool inline_p,
vec<tree> known_vals,
vec<ipa_agg_jump_function_p>
known_aggs,
vec<ipa_agg_value_set> known_aggs,
clause_t *ret_clause,
clause_t *ret_nonspec_clause)
{
......@@ -349,7 +348,7 @@ evaluate_conditions_for_known_args (struct cgraph_node *node,
if (c->agg_contents)
{
struct ipa_agg_jump_function *agg;
struct ipa_agg_value_set *agg;
if (c->code == predicate::changed
&& !c->by_ref
......@@ -358,7 +357,7 @@ evaluate_conditions_for_known_args (struct cgraph_node *node,
if (known_aggs.exists ())
{
agg = known_aggs[c->operand_num];
agg = &known_aggs[c->operand_num];
val = ipa_find_agg_cst_for_param (agg, known_vals[c->operand_num],
c->offset, c->by_ref);
}
......@@ -445,12 +444,12 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p,
vec<tree> *known_vals_ptr,
vec<ipa_polymorphic_call_context>
*known_contexts_ptr,
vec<ipa_agg_jump_function_p> *known_aggs_ptr)
vec<ipa_agg_value_set> *known_aggs_ptr)
{
struct cgraph_node *callee = e->callee->ultimate_alias_target ();
class ipa_fn_summary *info = ipa_fn_summaries->get (callee);
vec<tree> known_vals = vNULL;
vec<ipa_agg_jump_function_p> known_aggs = vNULL;
vec<ipa_agg_value_set> known_aggs = vNULL;
class ipa_edge_args *args;
if (clause_ptr)
......@@ -465,14 +464,16 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p,
&& ((clause_ptr && info->conds) || known_vals_ptr || known_contexts_ptr)
&& (args = IPA_EDGE_REF (e)) != NULL)
{
struct cgraph_node *caller;
class ipa_node_params *caller_parms_info, *callee_pi;
class ipa_call_summary *es = ipa_call_summaries->get (e);
int i, count = ipa_get_cs_argument_count (args);
if (e->caller->inlined_to)
caller_parms_info = IPA_NODE_REF (e->caller->inlined_to);
caller = e->caller->inlined_to;
else
caller_parms_info = IPA_NODE_REF (e->caller);
caller = e->caller;
caller_parms_info = IPA_NODE_REF (caller);
callee_pi = IPA_NODE_REF (callee);
if (count && (info->conds || known_vals_ptr))
......@@ -508,10 +509,9 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p,
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;
known_aggs[i] = ipa_agg_value_set_from_jfunc (caller_parms_info,
caller, &jf->agg);
}
else
gcc_assert (callee->thunk.thunk_p);
......@@ -545,7 +545,7 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p,
if (known_aggs_ptr)
*known_aggs_ptr = known_aggs;
else
known_aggs.release ();
ipa_release_agg_values (known_aggs);
}
......@@ -2838,7 +2838,7 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie,
int *size, int *time,
vec<tree> known_vals,
vec<ipa_polymorphic_call_context> known_contexts,
vec<ipa_agg_jump_function_p> known_aggs)
vec<ipa_agg_value_set> known_aggs)
{
tree target;
struct cgraph_node *callee;
......@@ -2887,7 +2887,7 @@ estimate_edge_size_and_time (struct cgraph_edge *e, int *size, int *min_size,
int prob,
vec<tree> known_vals,
vec<ipa_polymorphic_call_context> known_contexts,
vec<ipa_agg_jump_function_p> known_aggs,
vec<ipa_agg_value_set> known_aggs,
ipa_hints *hints)
{
class ipa_call_summary *es = ipa_call_summaries->get (e);
......@@ -2923,7 +2923,7 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size,
clause_t possible_truths,
vec<tree> known_vals,
vec<ipa_polymorphic_call_context> known_contexts,
vec<ipa_agg_jump_function_p> known_aggs)
vec<ipa_agg_value_set> known_aggs)
{
struct cgraph_edge *e;
for (e = node->callees; e; e = e->next_callee)
......@@ -2983,7 +2983,7 @@ ipa_call_context::ipa_call_context (cgraph_node *node,
vec<tree> known_vals,
vec<ipa_polymorphic_call_context>
known_contexts,
vec<ipa_agg_jump_function_p> known_aggs,
vec<ipa_agg_value_set> known_aggs,
vec<inline_param_summary>
inline_param_summary)
: m_node (node), m_possible_truths (possible_truths),
......@@ -3057,9 +3057,9 @@ ipa_call_context::duplicate_from (const ipa_call_context &ctx)
for (unsigned int i = 0; i < n; i++)
if (ipa_is_param_used_by_indirect_call (params_summary, i)
&& ctx.m_known_aggs[i])
&& !ctx.m_known_aggs[i].is_empty ())
{
m_known_aggs = ctx.m_known_aggs.copy ();
m_known_aggs = ipa_copy_agg_values (ctx.m_known_aggs);
break;
}
}
......@@ -3078,7 +3078,7 @@ ipa_call_context::release (bool all)
return;
m_known_vals.release ();
m_known_contexts.release ();
m_known_aggs.release ();
ipa_release_agg_values (m_known_aggs);
if (all)
m_inline_param_summary.release ();
}
......@@ -3179,19 +3179,22 @@ ipa_call_context::equal_to (const ipa_call_context &ctx)
{
if (!ipa_is_param_used_by_indirect_call (params_summary, i))
continue;
if (i >= m_known_aggs.length () || !m_known_aggs[i])
if (i >= m_known_aggs.length () || m_known_aggs[i].is_empty ())
{
if (i < ctx.m_known_aggs.length () && ctx.m_known_aggs[i])
if (i < ctx.m_known_aggs.length ()
&& !ctx.m_known_aggs[i].is_empty ())
return false;
continue;
}
if (i >= ctx.m_known_aggs.length () || !ctx.m_known_aggs[i])
if (i >= ctx.m_known_aggs.length ()
|| ctx.m_known_aggs[i].is_empty ())
{
if (i < m_known_aggs.length () && m_known_aggs[i])
if (i < m_known_aggs.length ()
&& !m_known_aggs[i].is_empty ())
return false;
continue;
}
if (m_known_aggs[i] != ctx.m_known_aggs[i])
if (!m_known_aggs[i].equal_to (ctx.m_known_aggs[i]))
return false;
}
}
......@@ -3348,7 +3351,7 @@ estimate_ipcp_clone_size_and_time (struct cgraph_node *node,
vec<tree> known_vals,
vec<ipa_polymorphic_call_context>
known_contexts,
vec<ipa_agg_jump_function_p> known_aggs,
vec<ipa_agg_value_set> known_aggs,
int *ret_size, sreal *ret_time,
sreal *ret_nonspec_time,
ipa_hints *hints)
......
......@@ -293,7 +293,7 @@ public:
clause_t nonspec_possible_truths,
vec<tree> known_vals,
vec<ipa_polymorphic_call_context> known_contexts,
vec<ipa_agg_jump_function_p> known_aggs,
vec<ipa_agg_value_set> known_aggs,
vec<inline_param_summary> m_inline_param_summary);
ipa_call_context ()
: m_node(NULL)
......@@ -329,7 +329,7 @@ private:
/* Vector describing known polymorphic call contexts. */
vec<ipa_polymorphic_call_context> m_known_contexts;
/* Vector describing known aggregate values. */
vec<ipa_agg_jump_function_p> m_known_aggs;
vec<ipa_agg_value_set> m_known_aggs;
};
extern fast_call_summary <ipa_call_summary *, va_heap> *ipa_call_summaries;
......@@ -345,7 +345,7 @@ void inline_analyze_function (struct cgraph_node *node);
void estimate_ipcp_clone_size_and_time (struct cgraph_node *,
vec<tree>,
vec<ipa_polymorphic_call_context>,
vec<ipa_agg_jump_function_p>,
vec<ipa_agg_value_set>,
int *, sreal *, sreal *,
ipa_hints *);
void ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge);
......@@ -360,7 +360,7 @@ void evaluate_properties_for_edge (struct cgraph_edge *e,
vec<tree> *known_vals_ptr,
vec<ipa_polymorphic_call_context>
*known_contexts_ptr,
vec<ipa_agg_jump_function_p> *);
vec<ipa_agg_value_set> *);
void ipa_fnsummary_c_finalize (void);
HOST_WIDE_INT ipa_get_stack_frame_offset (struct cgraph_node *node);
......
......@@ -188,7 +188,7 @@ do_estimate_edge_time (struct cgraph_edge *edge)
clause_t clause, nonspec_clause;
vec<tree> known_vals;
vec<ipa_polymorphic_call_context> known_contexts;
vec<ipa_agg_jump_function_p> known_aggs;
vec<ipa_agg_value_set> known_aggs;
class ipa_call_summary *es = ipa_call_summaries->get (edge);
int min_size = -1;
......@@ -308,7 +308,7 @@ do_estimate_edge_size (struct cgraph_edge *edge)
clause_t clause, nonspec_clause;
vec<tree> known_vals;
vec<ipa_polymorphic_call_context> known_contexts;
vec<ipa_agg_jump_function_p> known_aggs;
vec<ipa_agg_value_set> known_aggs;
/* When we do caching, use do_estimate_edge_time to populate the entry. */
......@@ -347,7 +347,7 @@ do_estimate_edge_hints (struct cgraph_edge *edge)
clause_t clause, nonspec_clause;
vec<tree> known_vals;
vec<ipa_polymorphic_call_context> known_contexts;
vec<ipa_agg_jump_function_p> known_aggs;
vec<ipa_agg_value_set> known_aggs;
/* When we do caching, use do_estimate_edge_time to populate the entry. */
......
......@@ -39,6 +39,15 @@ along with GCC; see the file COPYING3. If not see
argument.
Unknown - neither of the above.
IPA_JF_LOAD_AGG is a compound pass-through jump function, in which primary
operation on formal parameter is memory dereference that loads a value from
a part of an aggregate, which is represented or pointed to by the formal
parameter. Moreover, an additional unary/binary operation can be applied on
the loaded value, and final result is passed as actual argument of callee
(e.g. *(param_1(D) + 4) op 24 ). It is meant to describe usage of aggregate
parameter or by-reference parameter referenced in argument passing, commonly
found in C++ and Fortran.
IPA_JF_ANCESTOR is a special pass-through jump function, which means that
the result is an address of a part of the object pointed to by the formal
parameter to which the function refers. It is mainly intended to represent
......@@ -60,6 +69,7 @@ enum jump_func_type
IPA_JF_UNKNOWN = 0, /* newly allocated and zeroed jump functions default */
IPA_JF_CONST, /* represented by field costant */
IPA_JF_PASS_THROUGH, /* represented by field pass_through */
IPA_JF_LOAD_AGG, /* represented by field load_agg */
IPA_JF_ANCESTOR /* represented by field ancestor */
};
......@@ -97,6 +107,26 @@ struct GTY(()) ipa_pass_through_data
unsigned agg_preserved : 1;
};
/* Structure holding data required to describe a load-value-from-aggregate
jump function. */
struct GTY(()) ipa_load_agg_data
{
/* Inherit from pass through jump function, describing unary/binary
operation on the value loaded from aggregate that is represented or
pointed to by the formal parameter, specified by formal_id in this
pass_through jump function data structure. */
struct ipa_pass_through_data pass_through;
/* Type of the value loaded from the aggregate. */
tree type;
/* Offset at which the value is located within the aggregate. */
HOST_WIDE_INT offset;
/* True if loaded by reference (the aggregate is pointed to by the formal
parameter) or false if loaded by value (the aggregate is represented
by the formal parameter). */
bool by_ref;
};
/* Structure holding data required to describe an ancestor pass-through
jump function. */
......@@ -110,58 +140,139 @@ struct GTY(()) ipa_ancestor_jf_data
unsigned agg_preserved : 1;
};
/* An element in an aggegate part of a jump function describing a known value
at a given offset. When it is part of a pass-through jump function with
agg_preserved set or an ancestor jump function with agg_preserved set, all
unlisted positions are assumed to be preserved but the value can be a type
node, which means that the particular piece (starting at offset and having
the size of the type) is clobbered with an unknown value. When
agg_preserved is false or the type of the containing jump function is
different, all unlisted parts are assumed to be unknown and all values must
fulfill is_gimple_ip_invariant. */
/* A jump function for an aggregate part at a given offset, which describes how
it content value is generated. All unlisted positions are assumed to have a
value defined in an unknown way. */
struct GTY(()) ipa_agg_jf_item
{
/* The offset at which the known value is located within the aggregate. */
/* The offset for the aggregate part. */
HOST_WIDE_INT offset;
/* The known constant or type if this is a clobber. */
tree value;
/* Data type of the aggregate part. */
tree type;
/* Return true if OTHER describes same agg item. */
bool equal_to (const ipa_agg_jf_item &other);
};
/* Jump function type. */
enum jump_func_type jftype;
/* Represents a value of jump function. constant represents the actual constant
in constant jump function content. pass_through is used only in simple pass
through jump function context. load_agg is for load-value-from-aggregate
jump function context. */
union jump_func_agg_value
{
tree GTY ((tag ("IPA_JF_CONST"))) constant;
struct ipa_pass_through_data GTY ((tag ("IPA_JF_PASS_THROUGH"))) pass_through;
struct ipa_load_agg_data GTY ((tag ("IPA_JF_LOAD_AGG"))) load_agg;
} GTY ((desc ("%1.jftype"))) value;
};
/* Aggregate jump function - i.e. description of contents of aggregates passed
either by reference or value. */
/* Jump functions describing a set of aggregate contents. */
struct GTY(()) ipa_agg_jump_function
{
/* Description of the individual items. */
/* Description of the individual jump function item. */
vec<ipa_agg_jf_item, va_gc> *items;
/* True if the data was passed by reference (as opposed to by value). */
bool by_ref;
};
/* An element in an aggregate part describing a known value at a given offset.
All unlisted positions are assumed to be unknown and all listed values must
fulfill is_gimple_ip_invariant. */
struct ipa_agg_value
{
/* The offset at which the known value is located within the aggregate. */
HOST_WIDE_INT offset;
/* The known constant. */
tree value;
/* Return true if OTHER describes same agg value. */
bool equal_to (const ipa_agg_value &other);
};
/* Structure describing a set of known offset/value for aggregate. */
struct ipa_agg_value_set
{
/* Description of the individual item. */
vec<ipa_agg_value> items;
/* True if the data was passed by reference (as opposed to by value). */
bool by_ref;
/* Return true if OTHER describes same agg items. */
bool equal_to (const ipa_agg_jump_function &other)
/* Return true if OTHER describes same agg values. */
bool equal_to (const ipa_agg_value_set &other)
{
if (by_ref != other.by_ref)
return false;
if (items != NULL && other.items == NULL)
if (items.length () != other.items.length ())
return false;
if (!items)
return other.items == NULL;
if (items->length () != other.items->length ())
return false;
for (unsigned int i = 0; i < items->length (); i++)
if (!(*items)[i].equal_to ((*other.items)[i]))
for (unsigned int i = 0; i < items.length (); i++)
if (!items[i].equal_to (other.items[i]))
return false;
return true;
}
/* Return true if there is any value for aggregate. */
bool is_empty () const
{
return items.is_empty ();
}
ipa_agg_value_set copy () const
{
ipa_agg_value_set new_copy;
new_copy.items = items.copy ();
new_copy.by_ref = by_ref;
return new_copy;
}
void release ()
{
items.release ();
}
};
typedef struct ipa_agg_jump_function *ipa_agg_jump_function_p;
/* Return copy of a vec<ipa_agg_value_set>. */
static inline vec<ipa_agg_value_set>
ipa_copy_agg_values (const vec<ipa_agg_value_set> &aggs)
{
vec<ipa_agg_value_set> aggs_copy = vNULL;
if (!aggs.is_empty ())
{
ipa_agg_value_set *agg;
int i;
aggs_copy.reserve_exact (aggs.length ());
FOR_EACH_VEC_ELT (aggs, i, agg)
aggs_copy.quick_push (agg->copy ());
}
return aggs_copy;
}
/* For vec<ipa_agg_value_set>, DO NOT call release(), use below function
instead. Because ipa_agg_value_set contains a field of vector type, we
should release this child vector in each element before reclaiming the
whole vector. */
static inline void
ipa_release_agg_values (vec<ipa_agg_value_set> &aggs)
{
ipa_agg_value_set *agg;
int i;
FOR_EACH_VEC_ELT (aggs, i, agg)
agg->release ();
aggs.release ();
}
/* Information about zero/non-zero bits. */
class GTY(()) ipa_bits
......@@ -193,8 +304,8 @@ public:
types of jump functions supported. */
struct GTY (()) ipa_jump_func
{
/* Aggregate contants description. See struct ipa_agg_jump_function and its
description. */
/* Aggregate jump function description. See struct ipa_agg_jump_function
and its description. */
struct ipa_agg_jump_function agg;
/* Information about zero/non-zero bits. The pointed to structure is shared
......@@ -857,9 +968,9 @@ 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>,
vec<ipa_agg_value_set>,
bool *);
struct cgraph_edge *ipa_make_edge_direct_to_target (struct cgraph_edge *, tree,
bool speculative = false);
......@@ -872,7 +983,7 @@ ipa_bits *ipa_get_ipa_bits_for_value (const widest_int &value,
void ipa_analyze_node (struct cgraph_node *);
/* Aggregate jump function related functions. */
tree ipa_find_agg_cst_for_param (struct ipa_agg_jump_function *agg, tree scalar,
tree ipa_find_agg_cst_for_param (struct ipa_agg_value_set *agg, tree scalar,
HOST_WIDE_INT offset, bool by_ref,
bool *from_global_constant = NULL);
bool ipa_load_from_parm_agg (struct ipa_func_body_info *fbi,
......@@ -918,6 +1029,9 @@ ipa_polymorphic_call_context ipa_context_from_jfunc (ipa_node_params *,
cgraph_edge *,
int,
ipa_jump_func *);
ipa_agg_value_set ipa_agg_value_set_from_jfunc (ipa_node_params *,
cgraph_node *,
ipa_agg_jump_function *);
void ipa_dump_param (FILE *, class ipa_node_params *info, int i);
void ipa_release_body_info (struct ipa_func_body_info *);
tree ipa_get_callee_param_type (struct cgraph_edge *e, int i);
......
2019-11-14 Feng Xue <fxue@os.amperecomputing.com>
PR ipa/91682
* gcc.dg/ipa/ipcp-agg-10.c: Change dg-scan string.
* gcc.dg/ipa/ipcp-agg-11.c: New test.
2019-11-14 Jakub Jelinek <jakub@redhat.com>
PR ipa/92421
......
......@@ -72,7 +72,7 @@ int caller2(void)
return sum;
}
/* { dg-final { scan-ipa-dump-times "offset: 0, cst: 1" 1 "cp" } } */
/* { dg-final { scan-ipa-dump-times "offset: 0, cst: 2" 1 "cp" } } */
/* { dg-final { scan-ipa-dump-times "offset: 0, cst: 3" 1 "cp" } } */
/* { dg-final { scan-ipa-dump-times "offset: 64, cst: 4" 1 "cp" } } */
/* { dg-final { scan-ipa-dump-times "offset: 0, type: int, CONST: 1" 1 "cp" } } */
/* { dg-final { scan-ipa-dump-times "offset: 0, type: int, CONST: 2" 1 "cp" } } */
/* { dg-final { scan-ipa-dump-times "offset: 0, type: int, CONST: 3" 1 "cp" } } */
/* { dg-final { scan-ipa-dump-times "offset: 64, type: int, CONST: 4" 1 "cp" } } */
/* { dg-do compile } */
/* { dg-options "-O3 -fno-ipa-sra -fdump-ipa-cp-details -fno-early-inlining" } */
/* { dg-add-options bind_pic_locally } */
struct S
{
int a, b, c;
};
void *blah(int, void *);
#define foo_body(p)\
{ \
int i, c = (p)->c; \
int b = (p)->b; \
void *v = (void *) (p); \
\
for (i= 0; i< c; i++) \
v = blah(b + i, v); \
}
static void __attribute__ ((noinline))
foo_v (struct S s)
{
foo_body (&s);
}
static void __attribute__ ((noinline))
foo_r (struct S *p)
{
foo_body (p);
}
static void
goo_v (int a, int *p)
{
struct S s;
s.a = 101;
s.b = a % 7;
s.c = *p + 6;
foo_v (s);
}
static void
goo_r (int a, struct S n)
{
struct S s;
s.a = 1;
s.b = a + 5;
s.c = -n.b;
foo_r (&s);
}
void
entry ()
{
int a;
int v;
struct S s;
a = 9;
v = 3;
goo_v (a, &v);
a = 100;
s.b = 18;
goo_r (a, s);
}
/* { dg-final { scan-ipa-dump "offset: 0, type: int, CONST: 1" "cp" } } */
/* { dg-final { scan-ipa-dump "offset: 32, type: int, PASS THROUGH: 0, op plus_expr 5" "cp" } } */
/* { dg-final { scan-ipa-dump "offset: 64, type: int, LOAD AGG: 1 \\\[offset: 32, by value], op negate_expr" "cp" } } */
/* { dg-final { scan-ipa-dump "offset: 0, type: int, CONST: 101" "cp" } } */
/* { dg-final { scan-ipa-dump "offset: 32, type: int, PASS THROUGH: 0, op trunc_mod_expr 7" "cp" } } */
/* { dg-final { scan-ipa-dump "offset: 64, type: int, LOAD AGG: 1 \\\[offset: 0, by reference], op plus_expr 6" "cp" } } */
/* { dg-final { scan-ipa-dump "Aggregate replacements: 0\\\[0]=1, 0\\\[32]=105, 0\\\[64]=-18" "cp" } } */
/* { dg-final { scan-ipa-dump "Aggregate replacements: 0\\\[0]=101, 0\\\[32]=2, 0\\\[64]=9" "cp" } } */
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