aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vrp.c
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2018-11-11 08:51:34 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2018-11-11 08:51:34 +0000
commit2506b92c5671effff294a9f1f80272d6e56b75d0 (patch)
tree732562c6401b328f3dea5c5aab7282991ba039d4 /gcc/tree-vrp.c
parent3d18dc9db0513eae3dba69fb143e35cbe8c34f20 (diff)
downloadgcc-2506b92c5671effff294a9f1f80272d6e56b75d0.zip
gcc-2506b92c5671effff294a9f1f80272d6e56b75d0.tar.gz
gcc-2506b92c5671effff294a9f1f80272d6e56b75d0.tar.bz2
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
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r--gcc/tree-vrp.c203
1 files changed, 167 insertions, 36 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 73b9e04..3ef676b 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -73,16 +73,19 @@ along with GCC; see the file COPYING3. If not see
for still active basic-blocks. */
static sbitmap *live;
-/* Initialize value_range. */
-
void
-value_range::set (enum value_range_kind kind, tree min, tree max,
- bitmap equiv)
+value_range_base::set (enum value_range_kind kind, tree min, tree max)
{
m_kind = kind;
m_min = min;
m_max = max;
+ if (flag_checking)
+ check ();
+}
+void
+value_range::set_equiv (bitmap equiv)
+{
/* Since updating the equivalence set involves deep copying the
bitmaps, only do it if absolutely necessary.
@@ -99,10 +102,25 @@ value_range::set (enum value_range_kind kind, tree min, tree max,
else
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)
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,
bitmap equiv)
{
@@ -110,6 +128,12 @@ value_range::value_range (value_range_kind kind, tree min, tree max,
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. */
void
@@ -133,7 +157,7 @@ value_range::deep_copy (const value_range *from)
/* Check the validity of the range. */
void
-value_range::check ()
+value_range_base::check ()
{
switch (m_kind)
{
@@ -158,22 +182,32 @@ value_range::check ()
case VR_UNDEFINED:
case VR_VARYING:
gcc_assert (!min () && !max ());
- gcc_assert (!m_equiv || bitmap_empty_p (m_equiv));
break;
default:
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
IGNORE_EQUIVS is TRUE. */
bool
value_range::equal_p (const value_range &other, bool ignore_equivs) const
{
- return (m_kind == other.m_kind
- && vrp_operand_equal_p (m_min, other.m_min)
- && vrp_operand_equal_p (m_max, other.m_max)
+ return (ignore_equivs_equal_p (other)
&& (ignore_equivs
|| 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
/* Return equality while ignoring equivalence bitmap. */
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
@@ -224,6 +260,12 @@ value_range::constant_p () const
}
void
+value_range_base::set_undefined ()
+{
+ *this = value_range_base (VR_UNDEFINED, NULL, NULL);
+}
+
+void
value_range::set_undefined ()
{
equiv_clear ();
@@ -231,6 +273,12 @@ value_range::set_undefined ()
}
void
+value_range_base::set_varying ()
+{
+ *this = value_range_base (VR_VARYING, NULL, NULL);
+}
+
+void
value_range::set_varying ()
{
equiv_clear ();
@@ -240,7 +288,7 @@ value_range::set_varying ()
/* Return TRUE if it is possible that range contains VAL. */
bool
-value_range::may_contain_p (tree val) const
+value_range_base::may_contain_p (tree val) const
{
if (varying_p ())
return true;
@@ -302,7 +350,7 @@ value_range::singleton_p (tree *result) const
}
tree
-value_range::type () const
+value_range_base::type () const
{
/* Types are only valid for VR_RANGE and VR_ANTI_RANGE, which are
known to have non-zero min/max. */
@@ -313,7 +361,7 @@ value_range::type () const
/* Dump value range to FILE. */
void
-value_range::dump (FILE *file) const
+value_range_base::dump (FILE *file) const
{
if (undefined_p ())
fprintf (file, "UNDEFINED");
@@ -339,23 +387,6 @@ value_range::dump (FILE *file) const
print_generic_expr (file, max ());
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 ())
fprintf (file, "VARYING");
@@ -364,6 +395,29 @@ value_range::dump (FILE *file) const
}
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
{
dump_value_range (stderr, this);
@@ -573,8 +627,8 @@ set_value_range (value_range *vr, enum value_range_kind kind,
extract ranges from var + CST op limit. */
void
-value_range::set_and_canonicalize (enum value_range_kind kind,
- tree min, tree max, bitmap equiv)
+value_range_base::set_and_canonicalize (enum value_range_kind kind,
+ tree min, tree max)
{
/* Use the canonical setters for VR_UNDEFINED and VR_VARYING. */
if (kind == VR_UNDEFINED)
@@ -592,7 +646,7 @@ value_range::set_and_canonicalize (enum value_range_kind kind,
if (TREE_CODE (min) != INTEGER_CST
|| TREE_CODE (max) != INTEGER_CST)
{
- set_value_range (this, kind, min, max, equiv);
+ set (kind, min, max);
return;
}
@@ -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
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
@@ -1084,7 +1149,7 @@ value_inside_range (tree val, tree min, tree max)
/* Return TRUE if *VR includes the value zero. */
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 ())
return true;
@@ -2119,6 +2184,15 @@ dump_value_range (FILE *file, const value_range *vr)
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. */
DEBUG_FUNCTION void
@@ -6018,6 +6092,63 @@ value_range::intersect (const value_range *other)
may not be the smallest possible such range. */
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)
{
if (vr1->undefined_p ())