Convert ipcp_vr_lattice to type agnostic framework.

This converts the lattice to store ranges in Value_Range instead of
value_range (*) to make it type agnostic, and adjust all users
accordingly.

I've been careful to make sure Value_Range never ends up on GC, since
it contains an int_range_max and can expand on-demand onto the heap.
Longer term storage for ranges should be done with vrange_storage, as
per the previous patch ("Provide an API for ipa_vr").

gcc/ChangeLog:

	* ipa-cp.cc (ipcp_vr_lattice::init): Take type argument.
	(ipcp_vr_lattice::print): Call dump method.
	(ipcp_vr_lattice::meet_with): Adjust for m_vr being a
	Value_Range.
	(ipcp_vr_lattice::meet_with_1): Make argument a reference.
	(ipcp_vr_lattice::set_to_bottom): Set varying for an unsupported
	range.
	(initialize_node_lattices): Pass type when appropriate.
	(ipa_vr_operation_and_type_effects): Make type agnostic.
	(ipa_value_range_from_jfunc): Same.
	(propagate_vr_across_jump_function): Same.
	* ipa-fnsummary.cc (evaluate_conditions_for_known_args): Same.
	(evaluate_properties_for_edge): Same.
	* ipa-prop.cc (ipa_vr::get_vrange): Same.
	(ipcp_update_vr): Same.
	* ipa-prop.h (ipa_value_range_from_jfunc): Same.
	(ipa_range_set_and_normalize): Same.
This commit is contained in:
Aldy Hernandez 2023-05-17 11:29:34 +02:00
parent 273a33b285
commit bc5a2c2e79
4 changed files with 101 additions and 88 deletions

View file

@ -343,20 +343,29 @@ private:
class ipcp_vr_lattice
{
public:
value_range m_vr;
Value_Range m_vr;
inline bool bottom_p () const;
inline bool top_p () const;
inline bool set_to_bottom ();
bool meet_with (const value_range *p_vr);
bool meet_with (const vrange &p_vr);
bool meet_with (const ipcp_vr_lattice &other);
void init () { gcc_assert (m_vr.undefined_p ()); }
void init (tree type);
void print (FILE * f);
private:
bool meet_with_1 (const value_range *other_vr);
bool meet_with_1 (const vrange &other_vr);
};
inline void
ipcp_vr_lattice::init (tree type)
{
if (type)
m_vr.set_type (type);
// Otherwise m_vr will default to unsupported_range.
}
/* Structure containing lattices for a parameter itself and for pieces of
aggregates that are passed in the parameter or by a reference in a parameter
plus some other useful flags. */
@ -585,7 +594,7 @@ ipcp_bits_lattice::print (FILE *f)
void
ipcp_vr_lattice::print (FILE * f)
{
dump_value_range (f, &m_vr);
m_vr.dump (f);
}
/* Print all ipcp_lattices of all functions to F. */
@ -1016,39 +1025,39 @@ set_agg_lats_contain_variable (class ipcp_param_lattices *plats)
bool
ipcp_vr_lattice::meet_with (const ipcp_vr_lattice &other)
{
return meet_with_1 (&other.m_vr);
return meet_with_1 (other.m_vr);
}
/* Meet the current value of the lattice with value range described by VR
lattice. */
/* Meet the current value of the lattice with the range described by
P_VR. */
bool
ipcp_vr_lattice::meet_with (const value_range *p_vr)
ipcp_vr_lattice::meet_with (const vrange &p_vr)
{
return meet_with_1 (p_vr);
}
/* Meet the current value of the lattice with value range described by
OTHER_VR lattice. Return TRUE if anything changed. */
/* Meet the current value of the lattice with the range described by
OTHER_VR. Return TRUE if anything changed. */
bool
ipcp_vr_lattice::meet_with_1 (const value_range *other_vr)
ipcp_vr_lattice::meet_with_1 (const vrange &other_vr)
{
if (bottom_p ())
return false;
if (other_vr->varying_p ())
if (other_vr.varying_p ())
return set_to_bottom ();
bool res;
if (flag_checking)
{
value_range save (m_vr);
res = m_vr.union_ (*other_vr);
Value_Range save (m_vr);
res = m_vr.union_ (other_vr);
gcc_assert (res == (m_vr != save));
}
else
res = m_vr.union_ (*other_vr);
res = m_vr.union_ (other_vr);
return res;
}
@ -1077,12 +1086,15 @@ ipcp_vr_lattice::set_to_bottom ()
{
if (m_vr.varying_p ())
return false;
/* ?? We create all sorts of VARYING ranges for floats, structures,
and other types which we cannot handle as ranges. We should
probably avoid handling them throughout the pass, but it's easier
to create a sensible VARYING here and let the lattice
propagate. */
m_vr.set_varying (integer_type_node);
/* Setting an unsupported type here forces the temporary to default
to unsupported_range, which can handle VARYING/DEFINED ranges,
but nothing else (union, intersect, etc). This allows us to set
bottoms on any ranges, and is safe as all users of the lattice
check for bottom first. */
m_vr.set_type (void_type_node);
m_vr.set_varying (void_type_node);
return true;
}
@ -1653,6 +1665,7 @@ initialize_node_lattices (struct cgraph_node *node)
for (i = 0; i < ipa_get_param_count (info); i++)
{
ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
tree type = ipa_get_type (info, i);
if (disable
|| !ipa_get_type (info, i)
|| (pre_modified && (surviving_params.length () <= (unsigned) i
@ -1662,12 +1675,12 @@ initialize_node_lattices (struct cgraph_node *node)
plats->ctxlat.set_to_bottom ();
set_agg_lats_to_bottom (plats);
plats->bits_lattice.set_to_bottom ();
plats->m_value_range.m_vr = value_range ();
plats->m_value_range.init (type);
plats->m_value_range.set_to_bottom ();
}
else
{
plats->m_value_range.init ();
plats->m_value_range.init (type);
if (variable)
set_all_contains_variable (plats);
}
@ -1900,11 +1913,11 @@ ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx,
/* Emulate effects of unary OPERATION and/or conversion from SRC_TYPE to
DST_TYPE on value range in SRC_VR and store it to DST_VR. Return true if
the result is a range or an anti-range. */
the result is a range that is not VARYING nor UNDEFINED. */
static bool
ipa_vr_operation_and_type_effects (value_range *dst_vr,
value_range *src_vr,
ipa_vr_operation_and_type_effects (vrange &dst_vr,
const vrange &src_vr,
enum tree_code operation,
tree dst_type, tree src_type)
{
@ -1912,29 +1925,35 @@ ipa_vr_operation_and_type_effects (value_range *dst_vr,
return false;
range_op_handler handler (operation, dst_type);
return (handler
&& handler.fold_range (*dst_vr, dst_type,
*src_vr, value_range (dst_type))
&& !dst_vr->varying_p ()
&& !dst_vr->undefined_p ());
if (!handler)
return false;
Value_Range varying (dst_type);
varying.set_varying (dst_type);
return (handler.fold_range (dst_vr, dst_type, src_vr, varying)
&& !dst_vr.varying_p ()
&& !dst_vr.undefined_p ());
}
/* Determine range of JFUNC given that INFO describes the caller node or
the one it is inlined to, CS is the call graph edge corresponding to JFUNC
and PARM_TYPE of the parameter. */
value_range
ipa_value_range_from_jfunc (ipa_node_params *info, cgraph_edge *cs,
void
ipa_value_range_from_jfunc (vrange &vr,
ipa_node_params *info, cgraph_edge *cs,
ipa_jump_func *jfunc, tree parm_type)
{
value_range vr;
vr.set_undefined ();
if (jfunc->m_vr)
ipa_vr_operation_and_type_effects (&vr,
jfunc->m_vr,
ipa_vr_operation_and_type_effects (vr,
*jfunc->m_vr,
NOP_EXPR, parm_type,
jfunc->m_vr->type ());
if (vr.singleton_p ())
return vr;
return;
if (jfunc->type == IPA_JF_PASS_THROUGH)
{
int idx;
@ -1943,33 +1962,34 @@ ipa_value_range_from_jfunc (ipa_node_params *info, cgraph_edge *cs,
? cs->caller->inlined_to
: cs->caller);
if (!sum || !sum->m_vr)
return vr;
return;
idx = ipa_get_jf_pass_through_formal_id (jfunc);
if (!(*sum->m_vr)[idx].known_p ())
return vr;
return;
tree vr_type = ipa_get_type (info, idx);
value_range srcvr;
Value_Range srcvr;
(*sum->m_vr)[idx].get_vrange (srcvr);
enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
if (TREE_CODE_CLASS (operation) == tcc_unary)
{
value_range res;
Value_Range res (vr_type);
if (ipa_vr_operation_and_type_effects (&res,
&srcvr,
if (ipa_vr_operation_and_type_effects (res,
srcvr,
operation, parm_type,
vr_type))
vr.intersect (res);
}
else
{
value_range op_res, res;
Value_Range op_res (vr_type);
Value_Range res (vr_type);
tree op = ipa_get_jf_pass_through_operand (jfunc);
value_range op_vr;
Value_Range op_vr (vr_type);
range_op_handler handler (operation, vr_type);
ipa_range_set_and_normalize (op_vr, op);
@ -1979,14 +1999,13 @@ ipa_value_range_from_jfunc (ipa_node_params *info, cgraph_edge *cs,
|| !handler.fold_range (op_res, vr_type, srcvr, op_vr))
op_res.set_varying (vr_type);
if (ipa_vr_operation_and_type_effects (&res,
&op_res,
if (ipa_vr_operation_and_type_effects (res,
op_res,
NOP_EXPR, parm_type,
vr_type))
vr.intersect (res);
}
}
return vr;
}
/* Determine whether ITEM, jump function for an aggregate part, evaluates to a
@ -2753,10 +2772,10 @@ propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
if (src_lats->m_value_range.bottom_p ())
return dest_lat->set_to_bottom ();
value_range vr;
Value_Range vr (operand_type);
if (TREE_CODE_CLASS (operation) == tcc_unary)
ipa_vr_operation_and_type_effects (&vr,
&src_lats->m_value_range.m_vr,
ipa_vr_operation_and_type_effects (vr,
src_lats->m_value_range.m_vr,
operation, param_type,
operand_type);
/* A crude way to prevent unbounded number of value range updates
@ -2765,8 +2784,8 @@ propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
else if (!ipa_edge_within_scc (cs))
{
tree op = ipa_get_jf_pass_through_operand (jfunc);
value_range op_vr;
value_range op_res,res;
Value_Range op_vr (TREE_TYPE (op));
Value_Range op_res (operand_type);
range_op_handler handler (operation, operand_type);
ipa_range_set_and_normalize (op_vr, op);
@ -2777,8 +2796,8 @@ propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
src_lats->m_value_range.m_vr, op_vr))
op_res.set_varying (operand_type);
ipa_vr_operation_and_type_effects (&vr,
&op_res,
ipa_vr_operation_and_type_effects (vr,
op_res,
NOP_EXPR, param_type,
operand_type);
}
@ -2786,14 +2805,14 @@ propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
{
if (jfunc->m_vr)
{
value_range jvr;
if (ipa_vr_operation_and_type_effects (&jvr, jfunc->m_vr,
Value_Range jvr (param_type);
if (ipa_vr_operation_and_type_effects (jvr, *jfunc->m_vr,
NOP_EXPR,
param_type,
jfunc->m_vr->type ()))
vr.intersect (jvr);
}
return dest_lat->meet_with (&vr);
return dest_lat->meet_with (vr);
}
}
else if (jfunc->type == IPA_JF_CONST)
@ -2805,18 +2824,17 @@ propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
if (TREE_OVERFLOW_P (val))
val = drop_tree_overflow (val);
value_range tmpvr (TREE_TYPE (val),
wi::to_wide (val), wi::to_wide (val));
return dest_lat->meet_with (&tmpvr);
Value_Range tmpvr (val, val);
return dest_lat->meet_with (tmpvr);
}
}
value_range vr;
Value_Range vr (param_type);
if (jfunc->m_vr
&& ipa_vr_operation_and_type_effects (&vr, jfunc->m_vr, NOP_EXPR,
&& ipa_vr_operation_and_type_effects (vr, *jfunc->m_vr, NOP_EXPR,
param_type,
jfunc->m_vr->type ()))
return dest_lat->meet_with (&vr);
return dest_lat->meet_with (vr);
else
return dest_lat->set_to_bottom ();
}

View file

@ -475,7 +475,7 @@ evaluate_conditions_for_known_args (struct cgraph_node *node,
&& !c->agg_contents
&& (!val || TREE_CODE (val) != INTEGER_CST))
{
value_range vr = avals->m_known_value_ranges[c->operand_num];
Value_Range vr (avals->m_known_value_ranges[c->operand_num]);
if (!vr.undefined_p ()
&& !vr.varying_p ()
&& (TYPE_SIZE (c->type) == TYPE_SIZE (vr.type ())))
@ -630,8 +630,8 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p,
|| ipa_is_param_used_by_ipa_predicates (callee_pi, i))
{
/* Determine if we know constant value of the parameter. */
tree cst = ipa_value_from_jfunc (caller_parms_info, jf,
ipa_get_type (callee_pi, i));
tree type = ipa_get_type (callee_pi, i);
tree cst = ipa_value_from_jfunc (caller_parms_info, jf, type);
if (!cst && e->call_stmt
&& i < (int)gimple_call_num_args (e->call_stmt))
@ -659,10 +659,9 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p,
&& vrp_will_run_p (caller)
&& ipa_is_param_used_by_ipa_predicates (callee_pi, i))
{
value_range vr
= ipa_value_range_from_jfunc (caller_parms_info, e, jf,
ipa_get_type (callee_pi,
i));
Value_Range vr (type);
ipa_value_range_from_jfunc (vr, caller_parms_info, e, jf, type);
if (!vr.undefined_p () && !vr.varying_p ())
{
if (!avals->m_known_value_ranges.length ())
@ -670,7 +669,7 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p,
avals->m_known_value_ranges.safe_grow (count, true);
for (int i = 0; i < count; ++i)
new (&avals->m_known_value_ranges[i])
value_range ();
Value_Range ();
}
avals->m_known_value_ranges[i] = vr;
}

View file

@ -198,8 +198,9 @@ ipa_vr::equal_p (const vrange &r) const
}
void
ipa_vr::get_vrange (vrange &r) const
ipa_vr::get_vrange (Value_Range &r) const
{
r.set_type (m_type);
m_storage->get_vrange (r, m_type);
}
@ -5964,7 +5965,7 @@ ipcp_update_vr (struct cgraph_node *node)
if (vr[i].known_p ())
{
value_range tmp;
Value_Range tmp;
vr[i].get_vrange (tmp);
if (!tmp.undefined_p () && !tmp.varying_p ())

View file

@ -314,7 +314,7 @@ public:
void set_unknown ();
bool known_p () const { return m_storage != NULL; }
tree type () const { return m_type; }
void get_vrange (vrange &) const;
void get_vrange (Value_Range &) const;
bool equal_p (const vrange &) const;
const vrange_storage *storage () const { return m_storage; }
void streamer_read (lto_input_block *, data_in *);
@ -530,7 +530,7 @@ public:
auto_vec<ipa_argagg_value, 32> m_known_aggs;
/* Vector describing known value ranges of arguments. */
auto_vec<value_range, 32> m_known_value_ranges;
auto_vec<Value_Range, 32> m_known_value_ranges;
};
inline
@ -582,7 +582,7 @@ public:
vec<ipa_argagg_value> m_known_aggs = vNULL;
/* Vector describing known value ranges of arguments. */
vec<value_range> m_known_value_ranges = vNULL;
vec<Value_Range> m_known_value_ranges = vNULL;
};
inline
@ -1194,8 +1194,8 @@ ipa_polymorphic_call_context ipa_context_from_jfunc (ipa_node_params *,
cgraph_edge *,
int,
ipa_jump_func *);
value_range ipa_value_range_from_jfunc (ipa_node_params *, cgraph_edge *,
ipa_jump_func *, tree);
void ipa_value_range_from_jfunc (vrange &, ipa_node_params *, cgraph_edge *,
ipa_jump_func *, tree);
void ipa_push_agg_values_from_jfunc (ipa_node_params *info, cgraph_node *node,
ipa_agg_jump_function *agg_jfunc,
unsigned dst_index,
@ -1218,17 +1218,12 @@ void ipa_cp_cc_finalize (void);
non-zero. */
inline void
ipa_range_set_and_normalize (irange &r, tree val)
ipa_range_set_and_normalize (vrange &r, tree val)
{
if (TREE_CODE (val) == INTEGER_CST)
{
wide_int w = wi::to_wide (val);
r.set (TREE_TYPE (val), w, w);
}
else if (TREE_CODE (val) == ADDR_EXPR)
if (TREE_CODE (val) == ADDR_EXPR)
r.set_nonzero (TREE_TYPE (val));
else
r.set_varying (TREE_TYPE (val));
r.set (val, val);
}
#endif /* IPA_PROP_H */