Commit 2506b92c by Richard Biener Committed by Richard Biener

tree-vrp.h (class value_range_base): New base class for value_range containing…

tree-vrp.h (class value_range_base): New base class for value_range containing all but the m_equiv member.

2018-11-11  Richard Biener  <rguenther@suse.de>

	* tree-vrp.h (class value_range_base): New base class for
	value_range containing all but the m_equiv member.
	(dump_value_range_base): Add.
	(range_includes_zero_p): Work on value_range_base.
	* tree-vrp.c (value_range_base::set): Split out base handling
	from...
	(value_range::set): this.
	(value_range::set_equiv): New.
	(value_range_base::value_range_base): New constructors.
	(value_range_base::check): Split out base handling from...
	(value_range::check): this.
	(value_range::equal_p): Refactor in terms of
	ignore_equivs_equal_p which is now member of the base.
	(value_range_base::set_undefined): New.
	(value_range_base::set_varying): Likewise.
	(value_range_base::dump):Split out base handling from...
	(value_range::dump): this.
	(value_range_base::set_and_canonicalize): Split out base handling
	from...
	(value_range::set_and_canonicalize): this.
	(value_range_base::union_): New.
	* ipa-prop.h (struct ipa_jump_func): Use value_range_base *
	for m_vr.
	* ipa-cp.c (class ipcp_vr_lattice): Use value_range_base
	instead of value_range everywhere.
	(ipcp_vr_lattice::print): Use dump_value_range_base.
	(ipcp_vr_lattice::meet_with): Adjust.
	(ipcp_vr_lattice::meet_with_1): Likewise.
	(ipa_vr_operation_and_type_effects): Likewise.
	(propagate_vr_across_jump_function): Likewise.
	* ipa-prop.c (struct ipa_vr_ggc_hash_traits): Likewise.
	(ipa_get_value_range): Likewise.
	(ipa_set_jfunc_vr): Likewise.
	(ipa_compute_jump_functions_for_edge): Likewise.

From-SVN: r266011
parent 3d18dc9d
2018-11-11 Richard Biener <rguenther@suse.de>
* tree-vrp.h (class value_range_base): New base class for
value_range containing all but the m_equiv member.
(dump_value_range_base): Add.
(range_includes_zero_p): Work on value_range_base.
* tree-vrp.c (value_range_base::set): Split out base handling
from...
(value_range::set): this.
(value_range::set_equiv): New.
(value_range_base::value_range_base): New constructors.
(value_range_base::check): Split out base handling from...
(value_range::check): this.
(value_range::equal_p): Refactor in terms of
ignore_equivs_equal_p which is now member of the base.
(value_range_base::set_undefined): New.
(value_range_base::set_varying): Likewise.
(value_range_base::dump):Split out base handling from...
(value_range::dump): this.
(value_range_base::set_and_canonicalize): Split out base handling
from...
(value_range::set_and_canonicalize): this.
(value_range_base::union_): New.
* ipa-prop.h (struct ipa_jump_func): Use value_range_base *
for m_vr.
* ipa-cp.c (class ipcp_vr_lattice): Use value_range_base
instead of value_range everywhere.
(ipcp_vr_lattice::print): Use dump_value_range_base.
(ipcp_vr_lattice::meet_with): Adjust.
(ipcp_vr_lattice::meet_with_1): Likewise.
(ipa_vr_operation_and_type_effects): Likewise.
(propagate_vr_across_jump_function): Likewise.
* ipa-prop.c (struct ipa_vr_ggc_hash_traits): Likewise.
(ipa_get_value_range): Likewise.
(ipa_set_jfunc_vr): Likewise.
(ipa_compute_jump_functions_for_edge): Likewise.
2018-11-10 Sandra Loosemore <sandra@codesourcery.com> 2018-11-10 Sandra Loosemore <sandra@codesourcery.com>
PR middle-end/65703 PR middle-end/65703
...@@ -307,18 +307,18 @@ private: ...@@ -307,18 +307,18 @@ private:
class ipcp_vr_lattice class ipcp_vr_lattice
{ {
public: public:
value_range m_vr; value_range_base m_vr;
inline bool bottom_p () const; inline bool bottom_p () const;
inline bool top_p () const; inline bool top_p () const;
inline bool set_to_bottom (); inline bool set_to_bottom ();
bool meet_with (const value_range *p_vr); bool meet_with (const value_range_base *p_vr);
bool meet_with (const ipcp_vr_lattice &other); bool meet_with (const ipcp_vr_lattice &other);
void init () { gcc_assert (m_vr.undefined_p ()); } void init () { gcc_assert (m_vr.undefined_p ()); }
void print (FILE * f); void print (FILE * f);
private: private:
bool meet_with_1 (const value_range *other_vr); bool meet_with_1 (const value_range_base *other_vr);
}; };
/* Structure containing lattices for a parameter itself and for pieces of /* Structure containing lattices for a parameter itself and for pieces of
...@@ -522,7 +522,7 @@ ipcp_bits_lattice::print (FILE *f) ...@@ -522,7 +522,7 @@ ipcp_bits_lattice::print (FILE *f)
void void
ipcp_vr_lattice::print (FILE * f) ipcp_vr_lattice::print (FILE * f)
{ {
dump_value_range (f, &m_vr); dump_value_range_base (f, &m_vr);
} }
/* Print all ipcp_lattices of all functions to F. */ /* Print all ipcp_lattices of all functions to F. */
...@@ -909,7 +909,7 @@ ipcp_vr_lattice::meet_with (const ipcp_vr_lattice &other) ...@@ -909,7 +909,7 @@ ipcp_vr_lattice::meet_with (const ipcp_vr_lattice &other)
lattice. */ lattice. */
bool bool
ipcp_vr_lattice::meet_with (const value_range *p_vr) ipcp_vr_lattice::meet_with (const value_range_base *p_vr)
{ {
return meet_with_1 (p_vr); return meet_with_1 (p_vr);
} }
...@@ -918,7 +918,7 @@ ipcp_vr_lattice::meet_with (const value_range *p_vr) ...@@ -918,7 +918,7 @@ ipcp_vr_lattice::meet_with (const value_range *p_vr)
OTHER_VR lattice. Return TRUE if anything changed. */ OTHER_VR lattice. Return TRUE if anything changed. */
bool bool
ipcp_vr_lattice::meet_with_1 (const value_range *other_vr) ipcp_vr_lattice::meet_with_1 (const value_range_base *other_vr)
{ {
if (bottom_p ()) if (bottom_p ())
return false; return false;
...@@ -926,7 +926,7 @@ ipcp_vr_lattice::meet_with_1 (const value_range *other_vr) ...@@ -926,7 +926,7 @@ ipcp_vr_lattice::meet_with_1 (const value_range *other_vr)
if (other_vr->varying_p ()) if (other_vr->varying_p ())
return set_to_bottom (); return set_to_bottom ();
value_range save (m_vr); value_range_base save (m_vr);
m_vr.union_ (other_vr); m_vr.union_ (other_vr);
return !m_vr.ignore_equivs_equal_p (save); return !m_vr.ignore_equivs_equal_p (save);
} }
...@@ -1871,12 +1871,17 @@ propagate_bits_across_jump_function (cgraph_edge *cs, int idx, ...@@ -1871,12 +1871,17 @@ propagate_bits_across_jump_function (cgraph_edge *cs, int idx,
the result is a range or an anti-range. */ the result is a range or an anti-range. */
static bool static bool
ipa_vr_operation_and_type_effects (value_range *dst_vr, value_range *src_vr, ipa_vr_operation_and_type_effects (value_range_base *dst_vr,
value_range_base *src_vr,
enum tree_code operation, enum tree_code operation,
tree dst_type, tree src_type) tree dst_type, tree src_type)
{ {
*dst_vr = value_range (); /* ??? We'd want to use value_range_base on the VRP workers. */
extract_range_from_unary_expr (dst_vr, operation, dst_type, src_vr, src_type); value_range dst_tem;
value_range src_tem (*src_vr);
extract_range_from_unary_expr (&dst_tem, operation, dst_type,
&src_tem, src_type);
*dst_vr = value_range_base (dst_tem.kind (), dst_tem.min (), dst_tem.max ());
if (dst_vr->varying_p () || dst_vr->undefined_p ()) if (dst_vr->varying_p () || dst_vr->undefined_p ())
return false; return false;
return true; return true;
...@@ -1915,7 +1920,7 @@ propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc, ...@@ -1915,7 +1920,7 @@ propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
if (src_lats->m_value_range.bottom_p ()) if (src_lats->m_value_range.bottom_p ())
return dest_lat->set_to_bottom (); return dest_lat->set_to_bottom ();
value_range vr; value_range_base vr;
if (ipa_vr_operation_and_type_effects (&vr, if (ipa_vr_operation_and_type_effects (&vr,
&src_lats->m_value_range.m_vr, &src_lats->m_value_range.m_vr,
operation, param_type, operation, param_type,
...@@ -1932,12 +1937,12 @@ propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc, ...@@ -1932,12 +1937,12 @@ propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
if (TREE_OVERFLOW_P (val)) if (TREE_OVERFLOW_P (val))
val = drop_tree_overflow (val); val = drop_tree_overflow (val);
value_range tmpvr (VR_RANGE, val, val); value_range_base tmpvr (VR_RANGE, val, val);
return dest_lat->meet_with (&tmpvr); return dest_lat->meet_with (&tmpvr);
} }
} }
value_range vr; value_range_base vr;
if (jfunc->m_vr 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, param_type,
......
...@@ -106,43 +106,42 @@ static GTY ((cache)) hash_table<ipa_bit_ggc_hash_traits> *ipa_bits_hash_table; ...@@ -106,43 +106,42 @@ static GTY ((cache)) hash_table<ipa_bit_ggc_hash_traits> *ipa_bits_hash_table;
/* Traits for a hash table for reusing value_ranges used for IPA. Note that /* Traits for a hash table for reusing value_ranges used for IPA. Note that
the equiv bitmap is not hashed and is expected to be NULL. */ the equiv bitmap is not hashed and is expected to be NULL. */
struct ipa_vr_ggc_hash_traits : public ggc_cache_remove <value_range *> struct ipa_vr_ggc_hash_traits : public ggc_cache_remove <value_range_base *>
{ {
typedef value_range *value_type; typedef value_range_base *value_type;
typedef value_range *compare_type; typedef value_range_base *compare_type;
static hashval_t static hashval_t
hash (const value_range *p) hash (const value_range_base *p)
{ {
gcc_checking_assert (!p->equiv ());
inchash::hash hstate (p->kind ()); inchash::hash hstate (p->kind ());
inchash::add_expr (p->min (), hstate); inchash::add_expr (p->min (), hstate);
inchash::add_expr (p->max (), hstate); inchash::add_expr (p->max (), hstate);
return hstate.end (); return hstate.end ();
} }
static bool static bool
equal (const value_range *a, const value_range *b) equal (const value_range_base *a, const value_range_base *b)
{ {
return a->ignore_equivs_equal_p (*b); return a->ignore_equivs_equal_p (*b);
} }
static void static void
mark_empty (value_range *&p) mark_empty (value_range_base *&p)
{ {
p = NULL; p = NULL;
} }
static bool static bool
is_empty (const value_range *p) is_empty (const value_range_base *p)
{ {
return p == NULL; return p == NULL;
} }
static bool static bool
is_deleted (const value_range *p) is_deleted (const value_range_base *p)
{ {
return p == reinterpret_cast<const value_range *> (1); return p == reinterpret_cast<const value_range_base *> (1);
} }
static void static void
mark_deleted (value_range *&p) mark_deleted (value_range_base *&p)
{ {
p = reinterpret_cast<value_range *> (1); p = reinterpret_cast<value_range_base *> (1);
} }
}; };
...@@ -1770,14 +1769,14 @@ ipa_set_jfunc_bits (ipa_jump_func *jf, const widest_int &value, ...@@ -1770,14 +1769,14 @@ ipa_set_jfunc_bits (ipa_jump_func *jf, const widest_int &value,
/* Return a pointer to a value_range just like *TMP, but either find it in /* Return a pointer to a value_range just like *TMP, but either find it in
ipa_vr_hash_table or allocate it in GC memory. TMP->equiv must be NULL. */ ipa_vr_hash_table or allocate it in GC memory. TMP->equiv must be NULL. */
static value_range * static value_range_base *
ipa_get_value_range (value_range *tmp) ipa_get_value_range (value_range_base *tmp)
{ {
value_range **slot = ipa_vr_hash_table->find_slot (tmp, INSERT); value_range_base **slot = ipa_vr_hash_table->find_slot (tmp, INSERT);
if (*slot) if (*slot)
return *slot; return *slot;
value_range *vr = ggc_alloc<value_range> (); value_range_base *vr = ggc_alloc<value_range_base> ();
*vr = *tmp; *vr = *tmp;
*slot = vr; *slot = vr;
...@@ -1788,10 +1787,10 @@ ipa_get_value_range (value_range *tmp) ...@@ -1788,10 +1787,10 @@ ipa_get_value_range (value_range *tmp)
equiv set. Use hash table in order to avoid creating multiple same copies of equiv set. Use hash table in order to avoid creating multiple same copies of
value_ranges. */ value_ranges. */
static value_range * static value_range_base *
ipa_get_value_range (enum value_range_kind type, tree min, tree max) ipa_get_value_range (enum value_range_kind type, tree min, tree max)
{ {
value_range tmp (type, min, max); value_range_base tmp (type, min, max);
return ipa_get_value_range (&tmp); return ipa_get_value_range (&tmp);
} }
...@@ -1810,7 +1809,7 @@ ipa_set_jfunc_vr (ipa_jump_func *jf, enum value_range_kind type, ...@@ -1810,7 +1809,7 @@ ipa_set_jfunc_vr (ipa_jump_func *jf, enum value_range_kind type,
copy from ipa_vr_hash_table or allocate a new on in GC memory. */ copy from ipa_vr_hash_table or allocate a new on in GC memory. */
static void static void
ipa_set_jfunc_vr (ipa_jump_func *jf, value_range *tmp) ipa_set_jfunc_vr (ipa_jump_func *jf, value_range_base *tmp)
{ {
jf->m_vr = ipa_get_value_range (tmp); jf->m_vr = ipa_get_value_range (tmp);
} }
...@@ -1886,6 +1885,8 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, ...@@ -1886,6 +1885,8 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
&& (type = get_range_info (arg, &min, &max)) && (type = get_range_info (arg, &min, &max))
&& (type == VR_RANGE || type == VR_ANTI_RANGE)) && (type == VR_RANGE || type == VR_ANTI_RANGE))
{ {
/* ??? We'd want to use value_range_base here but the
VRP workers need to be adjusted first. */
value_range resvr; value_range resvr;
value_range tmpvr (type, value_range tmpvr (type,
wide_int_to_tree (TREE_TYPE (arg), min), wide_int_to_tree (TREE_TYPE (arg), min),
......
...@@ -182,7 +182,7 @@ struct GTY (()) ipa_jump_func ...@@ -182,7 +182,7 @@ struct GTY (()) ipa_jump_func
/* Information about value range, containing valid data only when vr_known is /* Information about value range, containing valid data only when vr_known is
true. The pointed to structure is shared betweed different jump true. The pointed to structure is shared betweed different jump
functions. Use ipa_set_jfunc_vr to set this field. */ functions. Use ipa_set_jfunc_vr to set this field. */
struct value_range *m_vr; struct value_range_base *m_vr;
enum jump_func_type type; enum jump_func_type type;
/* Represents a value of a jump function. pass_through is used only in jump /* Represents a value of a jump function. pass_through is used only in jump
......
...@@ -73,16 +73,19 @@ along with GCC; see the file COPYING3. If not see ...@@ -73,16 +73,19 @@ along with GCC; see the file COPYING3. If not see
for still active basic-blocks. */ for still active basic-blocks. */
static sbitmap *live; static sbitmap *live;
/* Initialize value_range. */
void void
value_range::set (enum value_range_kind kind, tree min, tree max, value_range_base::set (enum value_range_kind kind, tree min, tree max)
bitmap equiv)
{ {
m_kind = kind; m_kind = kind;
m_min = min; m_min = min;
m_max = max; m_max = max;
if (flag_checking)
check ();
}
void
value_range::set_equiv (bitmap equiv)
{
/* Since updating the equivalence set involves deep copying the /* Since updating the equivalence set involves deep copying the
bitmaps, only do it if absolutely necessary. bitmaps, only do it if absolutely necessary.
...@@ -99,10 +102,25 @@ value_range::set (enum value_range_kind kind, tree min, tree max, ...@@ -99,10 +102,25 @@ value_range::set (enum value_range_kind kind, tree min, tree max,
else else
bitmap_clear (m_equiv); bitmap_clear (m_equiv);
} }
}
/* Initialize value_range. */
void
value_range::set (enum value_range_kind kind, tree min, tree max,
bitmap equiv)
{
value_range_base::set (kind, min, max);
set_equiv (equiv);
if (flag_checking) if (flag_checking)
check (); check ();
} }
value_range_base::value_range_base (value_range_kind kind, tree min, tree max)
{
set (kind, min, max);
}
value_range::value_range (value_range_kind kind, tree min, tree max, value_range::value_range (value_range_kind kind, tree min, tree max,
bitmap equiv) bitmap equiv)
{ {
...@@ -110,6 +128,12 @@ value_range::value_range (value_range_kind kind, tree min, tree max, ...@@ -110,6 +128,12 @@ value_range::value_range (value_range_kind kind, tree min, tree max,
set (kind, min, max, equiv); set (kind, min, max, equiv);
} }
value_range::value_range (const value_range_base &other)
{
m_equiv = NULL;
set (other.kind (), other.min(), other.max (), NULL);
}
/* Like above, but keep the equivalences intact. */ /* Like above, but keep the equivalences intact. */
void void
...@@ -133,7 +157,7 @@ value_range::deep_copy (const value_range *from) ...@@ -133,7 +157,7 @@ value_range::deep_copy (const value_range *from)
/* Check the validity of the range. */ /* Check the validity of the range. */
void void
value_range::check () value_range_base::check ()
{ {
switch (m_kind) switch (m_kind)
{ {
...@@ -158,22 +182,32 @@ value_range::check () ...@@ -158,22 +182,32 @@ value_range::check ()
case VR_UNDEFINED: case VR_UNDEFINED:
case VR_VARYING: case VR_VARYING:
gcc_assert (!min () && !max ()); gcc_assert (!min () && !max ());
gcc_assert (!m_equiv || bitmap_empty_p (m_equiv));
break; break;
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
} }
void
value_range::check ()
{
value_range_base::check ();
switch (m_kind)
{
case VR_UNDEFINED:
case VR_VARYING:
gcc_assert (!m_equiv || bitmap_empty_p (m_equiv));
default:;
}
}
/* Returns TRUE if THIS == OTHER. Ignores the equivalence bitmap if /* Returns TRUE if THIS == OTHER. Ignores the equivalence bitmap if
IGNORE_EQUIVS is TRUE. */ IGNORE_EQUIVS is TRUE. */
bool bool
value_range::equal_p (const value_range &other, bool ignore_equivs) const value_range::equal_p (const value_range &other, bool ignore_equivs) const
{ {
return (m_kind == other.m_kind return (ignore_equivs_equal_p (other)
&& vrp_operand_equal_p (m_min, other.m_min)
&& vrp_operand_equal_p (m_max, other.m_max)
&& (ignore_equivs && (ignore_equivs
|| vrp_bitmap_equal_p (m_equiv, other.m_equiv))); || vrp_bitmap_equal_p (m_equiv, other.m_equiv)));
} }
...@@ -181,9 +215,11 @@ value_range::equal_p (const value_range &other, bool ignore_equivs) const ...@@ -181,9 +215,11 @@ value_range::equal_p (const value_range &other, bool ignore_equivs) const
/* Return equality while ignoring equivalence bitmap. */ /* Return equality while ignoring equivalence bitmap. */
bool bool
value_range::ignore_equivs_equal_p (const value_range &other) const value_range_base::ignore_equivs_equal_p (const value_range_base &other) const
{ {
return equal_p (other, /*ignore_equivs=*/true); return (m_kind == other.m_kind
&& vrp_operand_equal_p (m_min, other.m_min)
&& vrp_operand_equal_p (m_max, other.m_max));
} }
bool bool
...@@ -224,6 +260,12 @@ value_range::constant_p () const ...@@ -224,6 +260,12 @@ value_range::constant_p () const
} }
void void
value_range_base::set_undefined ()
{
*this = value_range_base (VR_UNDEFINED, NULL, NULL);
}
void
value_range::set_undefined () value_range::set_undefined ()
{ {
equiv_clear (); equiv_clear ();
...@@ -231,6 +273,12 @@ value_range::set_undefined () ...@@ -231,6 +273,12 @@ value_range::set_undefined ()
} }
void void
value_range_base::set_varying ()
{
*this = value_range_base (VR_VARYING, NULL, NULL);
}
void
value_range::set_varying () value_range::set_varying ()
{ {
equiv_clear (); equiv_clear ();
...@@ -240,7 +288,7 @@ value_range::set_varying () ...@@ -240,7 +288,7 @@ value_range::set_varying ()
/* Return TRUE if it is possible that range contains VAL. */ /* Return TRUE if it is possible that range contains VAL. */
bool bool
value_range::may_contain_p (tree val) const value_range_base::may_contain_p (tree val) const
{ {
if (varying_p ()) if (varying_p ())
return true; return true;
...@@ -302,7 +350,7 @@ value_range::singleton_p (tree *result) const ...@@ -302,7 +350,7 @@ value_range::singleton_p (tree *result) const
} }
tree tree
value_range::type () const value_range_base::type () const
{ {
/* Types are only valid for VR_RANGE and VR_ANTI_RANGE, which are /* Types are only valid for VR_RANGE and VR_ANTI_RANGE, which are
known to have non-zero min/max. */ known to have non-zero min/max. */
...@@ -313,7 +361,7 @@ value_range::type () const ...@@ -313,7 +361,7 @@ value_range::type () const
/* Dump value range to FILE. */ /* Dump value range to FILE. */
void void
value_range::dump (FILE *file) const value_range_base::dump (FILE *file) const
{ {
if (undefined_p ()) if (undefined_p ())
fprintf (file, "UNDEFINED"); fprintf (file, "UNDEFINED");
...@@ -339,23 +387,6 @@ value_range::dump (FILE *file) const ...@@ -339,23 +387,6 @@ value_range::dump (FILE *file) const
print_generic_expr (file, max ()); print_generic_expr (file, max ());
fprintf (file, "]"); fprintf (file, "]");
if (m_equiv)
{
bitmap_iterator bi;
unsigned i, c = 0;
fprintf (file, " EQUIVALENCES: { ");
EXECUTE_IF_SET_IN_BITMAP (m_equiv, 0, i, bi)
{
print_generic_expr (file, ssa_name (i));
fprintf (file, " ");
c++;
}
fprintf (file, "} (%u elements)", c);
}
} }
else if (varying_p ()) else if (varying_p ())
fprintf (file, "VARYING"); fprintf (file, "VARYING");
...@@ -364,6 +395,29 @@ value_range::dump (FILE *file) const ...@@ -364,6 +395,29 @@ value_range::dump (FILE *file) const
} }
void void
value_range::dump (FILE *file) const
{
value_range_base::dump (file);
if ((m_kind == VR_RANGE || m_kind == VR_ANTI_RANGE)
&& m_equiv)
{
bitmap_iterator bi;
unsigned i, c = 0;
fprintf (file, " EQUIVALENCES: { ");
EXECUTE_IF_SET_IN_BITMAP (m_equiv, 0, i, bi)
{
print_generic_expr (file, ssa_name (i));
fprintf (file, " ");
c++;
}
fprintf (file, "} (%u elements)", c);
}
}
void
value_range::dump () const value_range::dump () const
{ {
dump_value_range (stderr, this); dump_value_range (stderr, this);
...@@ -573,8 +627,8 @@ set_value_range (value_range *vr, enum value_range_kind kind, ...@@ -573,8 +627,8 @@ set_value_range (value_range *vr, enum value_range_kind kind,
extract ranges from var + CST op limit. */ extract ranges from var + CST op limit. */
void void
value_range::set_and_canonicalize (enum value_range_kind kind, value_range_base::set_and_canonicalize (enum value_range_kind kind,
tree min, tree max, bitmap equiv) tree min, tree max)
{ {
/* Use the canonical setters for VR_UNDEFINED and VR_VARYING. */ /* Use the canonical setters for VR_UNDEFINED and VR_VARYING. */
if (kind == VR_UNDEFINED) if (kind == VR_UNDEFINED)
...@@ -592,7 +646,7 @@ value_range::set_and_canonicalize (enum value_range_kind kind, ...@@ -592,7 +646,7 @@ value_range::set_and_canonicalize (enum value_range_kind kind,
if (TREE_CODE (min) != INTEGER_CST if (TREE_CODE (min) != INTEGER_CST
|| TREE_CODE (max) != INTEGER_CST) || TREE_CODE (max) != INTEGER_CST)
{ {
set_value_range (this, kind, min, max, equiv); set (kind, min, max);
return; return;
} }
...@@ -680,7 +734,18 @@ value_range::set_and_canonicalize (enum value_range_kind kind, ...@@ -680,7 +734,18 @@ value_range::set_and_canonicalize (enum value_range_kind kind,
to make sure VRP iteration terminates, otherwise we can get into to make sure VRP iteration terminates, otherwise we can get into
oscillations. */ oscillations. */
set_value_range (this, kind, min, max, equiv); set (kind, min, max);
}
void
value_range::set_and_canonicalize (enum value_range_kind kind,
tree min, tree max, bitmap equiv)
{
value_range_base::set_and_canonicalize (kind, min, max);
if (this->kind () == VR_RANGE || this->kind () == VR_ANTI_RANGE)
set_equiv (equiv);
else
equiv_clear ();
} }
/* Set value range VR to a single value. This function is only called /* Set value range VR to a single value. This function is only called
...@@ -1084,7 +1149,7 @@ value_inside_range (tree val, tree min, tree max) ...@@ -1084,7 +1149,7 @@ value_inside_range (tree val, tree min, tree max)
/* Return TRUE if *VR includes the value zero. */ /* Return TRUE if *VR includes the value zero. */
bool bool
range_includes_zero_p (const value_range *vr) range_includes_zero_p (const value_range_base *vr)
{ {
if (vr->varying_p () || vr->undefined_p ()) if (vr->varying_p () || vr->undefined_p ())
return true; return true;
...@@ -2119,6 +2184,15 @@ dump_value_range (FILE *file, const value_range *vr) ...@@ -2119,6 +2184,15 @@ dump_value_range (FILE *file, const value_range *vr)
vr->dump (file); vr->dump (file);
} }
void
dump_value_range_base (FILE *file, const value_range_base *vr)
{
if (!vr)
fprintf (file, "[]");
else
vr->dump (file);
}
/* Dump value range VR to stderr. */ /* Dump value range VR to stderr. */
DEBUG_FUNCTION void DEBUG_FUNCTION void
...@@ -6018,6 +6092,63 @@ value_range::intersect (const value_range *other) ...@@ -6018,6 +6092,63 @@ value_range::intersect (const value_range *other)
may not be the smallest possible such range. */ may not be the smallest possible such range. */
void void
value_range_base::union_ (const value_range_base *other)
{
if (other->undefined_p ())
{
/* this already has the resulting range. */
return;
}
if (this->undefined_p ())
{
*this = *other;
return;
}
if (this->varying_p ())
{
/* Nothing to do. VR0 already has the resulting range. */
return;
}
if (other->varying_p ())
{
this->set_varying ();
return;
}
value_range saved (*this);
value_range_kind vr0type = this->kind ();
tree vr0min = this->min ();
tree vr0max = this->max ();
union_ranges (&vr0type, &vr0min, &vr0max,
other->kind (), other->min (), other->max ());
*this = value_range_base (vr0type, vr0min, vr0max);
if (this->varying_p ())
{
/* Failed to find an efficient meet. Before giving up and setting
the result to VARYING, see if we can at least derive a useful
anti-range. */
if (range_includes_zero_p (&saved) == 0
&& range_includes_zero_p (other) == 0)
{
tree zero = build_int_cst (saved.type (), 0);
*this = value_range_base (VR_ANTI_RANGE, zero, zero);
return;
}
this->set_varying ();
return;
}
this->set_and_canonicalize (this->kind (), this->min (), this->max ());
}
/* Meet operation for value ranges. Given two value ranges VR0 and
VR1, store in VR0 a range that contains both VR0 and VR1. This
may not be the smallest possible such range. */
void
value_range::union_helper (value_range *vr0, const value_range *vr1) value_range::union_helper (value_range *vr0, const value_range *vr1)
{ {
if (vr1->undefined_p ()) if (vr1->undefined_p ())
......
...@@ -35,12 +35,63 @@ enum value_range_kind ...@@ -35,12 +35,63 @@ enum value_range_kind
VR_LAST VR_LAST
}; };
/* Range of values that can be associated with an SSA_NAME after VRP /* Range of values that can be associated with an SSA_NAME after VRP
has executed. */ has executed. */
class GTY((for_user)) value_range class GTY((for_user)) value_range_base
{
public:
value_range_base ();
value_range_base (value_range_kind, tree, tree);
enum value_range_kind kind () const;
tree min () const;
tree max () const;
/* Types of value ranges. */
bool undefined_p () const;
bool varying_p () const;
void union_ (const value_range_base *);
bool ignore_equivs_equal_p (const value_range_base &) const;
void set_varying ();
void set_undefined ();
/* Misc methods. */
tree type () const;
bool may_contain_p (tree) const;
void set_and_canonicalize (enum value_range_kind, tree, tree);
void dump (FILE *) const;
protected:
void set (value_range_kind, tree, tree);
void check ();
enum value_range_kind m_kind;
tree m_min;
tree m_max;
friend void gt_ggc_mx_value_range_base (void *);
friend void gt_pch_p_16value_range_base (void *, void *,
gt_pointer_operator, void *);
friend void gt_pch_nx_value_range_base (void *);
friend void gt_ggc_mx (value_range_base &);
friend void gt_ggc_mx (value_range_base *&);
friend void gt_pch_nx (value_range_base &);
friend void gt_pch_nx (value_range_base *, gt_pointer_operator, void *);
};
/* Note value_range cannot currently be used with GC memory, only
value_range_base is fully set up for this. */
class GTY((user)) value_range : public value_range_base
{ {
public: public:
value_range (); value_range ();
value_range (const value_range_base &);
value_range (value_range_kind, tree, tree, bitmap = NULL); value_range (value_range_kind, tree, tree, bitmap = NULL);
void update (value_range_kind, tree, tree); void update (value_range_kind, tree, tree);
bool operator== (const value_range &) const; bool operator== (const value_range &) const;
...@@ -49,8 +100,6 @@ class GTY((for_user)) value_range ...@@ -49,8 +100,6 @@ class GTY((for_user)) value_range
void union_ (const value_range *); void union_ (const value_range *);
/* Types of value ranges. */ /* Types of value ranges. */
bool undefined_p () const;
bool varying_p () const;
bool symbolic_p () const; bool symbolic_p () const;
bool constant_p () const; bool constant_p () const;
void set_undefined (); void set_undefined ();
...@@ -62,49 +111,44 @@ class GTY((for_user)) value_range ...@@ -62,49 +111,44 @@ class GTY((for_user)) value_range
void equiv_add (const_tree, const value_range *, bitmap_obstack * = NULL); void equiv_add (const_tree, const value_range *, bitmap_obstack * = NULL);
/* Misc methods. */ /* Misc methods. */
tree type () const;
bool zero_p () const; bool zero_p () const;
bool may_contain_p (tree) const;
bool singleton_p (tree *result = NULL) const; bool singleton_p (tree *result = NULL) const;
void deep_copy (const value_range *); void deep_copy (const value_range *);
bool ignore_equivs_equal_p (const value_range &) const;
void set_and_canonicalize (enum value_range_kind, tree, tree, bitmap); void set_and_canonicalize (enum value_range_kind, tree, tree, bitmap);
void dump (FILE *) const; void dump (FILE *) const;
void dump () const; void dump () const;
enum value_range_kind kind () const;
tree min () const;
tree max () const;
private: private:
void set (value_range_kind, tree, tree, bitmap); void set (value_range_kind, tree, tree, bitmap);
void set_equiv (bitmap);
void check (); void check ();
bool equal_p (const value_range &, bool ignore_equivs) const; bool equal_p (const value_range &, bool ignore_equivs) const;
void intersect_helper (value_range *, const value_range *); void intersect_helper (value_range *, const value_range *);
void union_helper (value_range *, const value_range *); void union_helper (value_range *, const value_range *);
enum value_range_kind m_kind;
public:
/* These should be private, but GTY is a piece of crap. */
tree m_min;
tree m_max;
/* Set of SSA names whose value ranges are equivalent to this one. /* Set of SSA names whose value ranges are equivalent to this one.
This set is only valid when TYPE is VR_RANGE or VR_ANTI_RANGE. */ This set is only valid when TYPE is VR_RANGE or VR_ANTI_RANGE. */
bitmap m_equiv; bitmap m_equiv;
}; };
inline inline
value_range::value_range () value_range_base::value_range_base ()
{ {
m_kind = VR_UNDEFINED; m_kind = VR_UNDEFINED;
m_min = m_max = NULL; m_min = m_max = NULL;
}
inline
value_range::value_range ()
: value_range_base ()
{
m_equiv = NULL; m_equiv = NULL;
} }
/* Return the kind of this range. */ /* Return the kind of this range. */
inline value_range_kind inline value_range_kind
value_range::kind () const value_range_base::kind () const
{ {
return m_kind; return m_kind;
} }
...@@ -118,7 +162,7 @@ value_range::equiv () const ...@@ -118,7 +162,7 @@ value_range::equiv () const
/* Return the lower bound. */ /* Return the lower bound. */
inline tree inline tree
value_range::min () const value_range_base::min () const
{ {
return m_min; return m_min;
} }
...@@ -126,7 +170,7 @@ value_range::min () const ...@@ -126,7 +170,7 @@ value_range::min () const
/* Return the upper bound. */ /* Return the upper bound. */
inline tree inline tree
value_range::max () const value_range_base::max () const
{ {
return m_max; return m_max;
} }
...@@ -134,7 +178,7 @@ value_range::max () const ...@@ -134,7 +178,7 @@ value_range::max () const
/* Return TRUE if range spans the entire possible domain. */ /* Return TRUE if range spans the entire possible domain. */
inline bool inline bool
value_range::varying_p () const value_range_base::varying_p () const
{ {
return m_kind == VR_VARYING; return m_kind == VR_VARYING;
} }
...@@ -142,7 +186,7 @@ value_range::varying_p () const ...@@ -142,7 +186,7 @@ value_range::varying_p () const
/* Return TRUE if range is undefined (essentially the empty set). */ /* Return TRUE if range is undefined (essentially the empty set). */
inline bool inline bool
value_range::undefined_p () const value_range_base::undefined_p () const
{ {
return m_kind == VR_UNDEFINED; return m_kind == VR_UNDEFINED;
} }
...@@ -158,6 +202,7 @@ value_range::zero_p () const ...@@ -158,6 +202,7 @@ value_range::zero_p () const
} }
extern void dump_value_range (FILE *, const value_range *); extern void dump_value_range (FILE *, const value_range *);
extern void dump_value_range_base (FILE *, const value_range_base *);
extern void extract_range_from_unary_expr (value_range *vr, extern void extract_range_from_unary_expr (value_range *vr,
enum tree_code code, enum tree_code code,
tree type, tree type,
...@@ -187,7 +232,7 @@ extern void register_edge_assert_for (tree, edge, enum tree_code, ...@@ -187,7 +232,7 @@ extern void register_edge_assert_for (tree, edge, enum tree_code,
tree, tree, vec<assert_info> &); tree, tree, vec<assert_info> &);
extern bool stmt_interesting_for_vrp (gimple *); extern bool stmt_interesting_for_vrp (gimple *);
extern void set_value_range_to_varying (value_range *); extern void set_value_range_to_varying (value_range *);
extern bool range_includes_zero_p (const value_range *); extern bool range_includes_zero_p (const value_range_base *);
extern bool infer_value_range (gimple *, tree, tree_code *, tree *); extern bool infer_value_range (gimple *, tree, tree_code *, tree *);
extern void set_value_range_to_nonnull (value_range *, tree); extern void set_value_range_to_nonnull (value_range *, tree);
......
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