This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
RFC: Implementing a new API for value_range
- From: Aldy Hernandez <aldyh at redhat dot com>
- To: Richard Biener <richard dot guenther at gmail dot com>
- Cc: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 3 Oct 2018 02:36:15 -0400
- Subject: RFC: Implementing a new API for value_range
Hi Richard. Hi folks.
I'd like to implement a clean API that disallows direct access to any of
the value_range internals. My aim is a clean API with no change in
functionality.
This is mostly a clean-up, but could also pave the way for possibly
changing the underlying implementation in the future so we can unite VPR
and the on-demand work with a single common code base.
I am quoting the main structure below to give an idea where I'd like to
head, and am also attaching a proof-of-concept patch to tree-vrp.[hc].
It is untested and only builds cc1.
Ideally I'd like to evolve this to include other methods that make the
VRP / vr-values code more readable.
Note: I have added a tree type field (m_type) to make it easy to
determine the tree type of the range. Right now a value_range looses
the range type if UNDEFINED or VARYING, as both min/max are NULL. If
there is strong objection to the extra word, we could set min/max to
integer_zero_node in the type if UNDEFINED/VARYING. But really, all
this will be hidden in the API, so we could change the underlying
representation at will.
Would you be ok with this if I continue down this path?
Thanks.
Aldy
struct GTY((for_user)) value_range
{
value_range ();
value_range (tree type);
value_range (tree type, value_range_type, tree, tree, bitmap = NULL);
value_range (const value_range &);
bool operator== (const value_range &) const;
bool operator!= (const value_range &) const;
void intersect (const value_range *);
void union_ (const value_range *);
/* Types of value ranges. */
bool undefined_p () const;
bool varying_p () const;
bool symbolic_p () const;
bool numeric_p () const;
void set_undefined ();
void set_varying ();
/* Equivalence bitmap methods. */
bitmap equiv () const;
void set_equiv (bitmap);
void equiv_free ();
void equiv_copy (const value_range *);
void equiv_clear ();
void equiv_and (const value_range *);
void equiv_ior (const value_range *);
/* Misc methods. */
tree type () const;
bool null_p () const;
bool may_contain_p (tree) const;
tree singleton () const;
void canonicalize ();
void copy_with_equiv_update (const value_range *);
void dump () const;
/* Temporary accessors that should eventually be removed. */
enum value_range_type vrtype () const;
tree min () const;
tree max () const;
/* private: These are public because of GTY stupidity. */
enum value_range_type m_vrtype;
tree m_min;
tree m_max;
tree m_type;
/* 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. */
bitmap m_equiv;
private:
void init (tree type, value_range_type, tree, tree, bitmap);
void check ();
};
diff --git a/gcc/tree-vrp.h b/gcc/tree-vrp.h
index 655cf055f0a..b2b9f971bae 100644
--- a/gcc/tree-vrp.h
+++ b/gcc/tree-vrp.h
@@ -29,31 +29,177 @@ enum value_range_type { VR_UNDEFINED, VR_RANGE,
has executed. */
struct GTY((for_user)) value_range
{
- /* Lattice value represented by this range. */
- enum value_range_type type;
+ value_range ();
+ value_range (tree type);
+ value_range (tree type, value_range_type, tree, tree, bitmap = NULL);
+ value_range (const value_range &);
+ bool operator== (const value_range &) const;
+ bool operator!= (const value_range &) const;
+ void intersect (const value_range *);
+ void union_ (const value_range *);
- /* Minimum and maximum values represented by this range. These
- values should be interpreted as follows:
+ /* Types of value ranges. */
+ bool undefined_p () const;
+ bool varying_p () const;
+ bool symbolic_p () const;
+ bool numeric_p () const;
+ void set_undefined ();
+ void set_varying ();
- - If TYPE is VR_UNDEFINED or VR_VARYING then MIN and MAX must
- be NULL.
+ /* Equivalence bitmap methods. */
+ bitmap equiv () const;
+ void set_equiv (bitmap);
+ void equiv_free ();
+ void equiv_copy (const value_range *);
+ void equiv_clear ();
+ void equiv_and (const value_range *);
+ void equiv_ior (const value_range *);
- - If TYPE == VR_RANGE then MIN holds the minimum value and
- MAX holds the maximum value of the range [MIN, MAX].
+ /* Misc methods. */
+ tree type () const;
+ bool null_p () const;
+ bool may_contain_p (tree) const;
+ tree singleton () const;
+ void canonicalize ();
+ void copy_with_equiv_update (const value_range *);
+ void dump () const;
- - If TYPE == ANTI_RANGE the variable is known to NOT
- take any values in the range [MIN, MAX]. */
- tree min;
- tree max;
+ /* Temporary accessors that should eventually be removed. */
+ enum value_range_type vrtype () const;
+ tree min () const;
+ tree max () const;
+ /* private: These are public because of GTY stupidity. */
+ enum value_range_type m_vrtype;
+ tree m_min;
+ tree m_max;
+ tree m_type;
/* 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. */
- bitmap equiv;
+ bitmap m_equiv;
- /* Dump value range to stderr. */
- void dump () const;
+ private:
+ void init (tree type, value_range_type, tree, tree, bitmap);
+ void check ();
};
+value_range::value_range ()
+{
+ m_type = m_min = m_max = NULL;
+ m_vrtype = VR_UNDEFINED;
+ m_equiv = NULL;
+}
+
+value_range::value_range (tree type)
+{
+ m_vrtype = VR_UNDEFINED;
+ m_min = m_max = NULL;
+ m_equiv = NULL;
+ m_type = type;
+}
+
+value_range::value_range (const value_range &other)
+{
+ *this = other;
+}
+
+inline value_range_type
+value_range::vrtype () const
+{
+ return m_vrtype;
+}
+
+inline tree
+value_range::type () const
+{
+ return m_type;
+}
+
+inline bitmap
+value_range::equiv () const
+{
+ return m_equiv;
+}
+
+inline tree
+value_range::min () const
+{
+ return m_min;
+}
+
+inline tree
+value_range::max () const
+{
+ return m_max;
+}
+
+inline void
+value_range::set_undefined ()
+{
+ if (m_equiv)
+ bitmap_clear (m_equiv);
+ *this = value_range (m_type, VR_UNDEFINED, NULL, NULL, m_equiv);
+}
+
+inline void
+value_range::set_varying ()
+{
+ if (m_equiv)
+ bitmap_clear (m_equiv);
+ *this = value_range (m_type, VR_VARYING, NULL, NULL, m_equiv);
+}
+
+inline bool
+value_range::varying_p () const
+{
+ return m_vrtype == VR_VARYING;
+}
+
+inline bool
+value_range::undefined_p () const
+{
+ return m_vrtype == VR_UNDEFINED;
+}
+
+inline void
+value_range::equiv_free ()
+{
+ BITMAP_FREE (m_equiv);
+ m_equiv = NULL;
+}
+
+inline void
+value_range::set_equiv (bitmap b)
+{
+ m_equiv = b;
+}
+
+inline void
+value_range::equiv_copy (const value_range *other)
+{
+ bitmap_copy (m_equiv, other->m_equiv);
+}
+
+inline void
+value_range::equiv_clear ()
+{
+ if (m_equiv)
+ bitmap_clear (m_equiv);
+}
+
+inline void
+value_range::equiv_and (const value_range *other)
+{
+ if (m_equiv && other->m_equiv)
+ bitmap_and_into (m_equiv, other->m_equiv);
+}
+
+inline void
+value_range::equiv_ior (const value_range *other)
+{
+ bitmap_ior_into (m_equiv, other->m_equiv);
+}
+
extern void vrp_intersect_ranges (value_range *vr0, const value_range *vr1);
extern void vrp_meet (value_range *vr0, const value_range *vr1);
extern void dump_value_range (FILE *, const value_range *);
@@ -97,7 +243,6 @@ extern void set_and_canonicalize_value_range (value_range *,
tree, tree, bitmap);
extern bool vrp_bitmap_equal_p (const_bitmap, const_bitmap);
extern tree value_range_constant_singleton (const value_range *);
-extern bool symbolic_range_p (const value_range *);
extern int compare_values (tree, tree);
extern int compare_values_warnv (tree, tree, bool *);
extern bool vrp_val_is_min (const_tree);
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 005fc2ffe2d..34d76b5b5a6 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -73,6 +73,260 @@ along with GCC; see the file COPYING3. If not see
for still active basic-blocks. */
static sbitmap *live;
+void
+value_range::init (tree type, enum value_range_type vrtype,
+ tree min, tree max, bitmap equiv)
+{
+ m_type = type;
+ m_vrtype = vrtype;
+ m_min = min;
+ m_max = max;
+
+ /* Since updating the equivalence set involves deep copying the
+ bitmaps, only do it if absolutely necessary.
+
+ All equivalence bitmaps are allocated from the same obstack. So
+ we can use the obstack associated with EQUIV to allocate vr->equiv. */
+ if (m_equiv == NULL
+ && equiv != NULL)
+ m_equiv = BITMAP_ALLOC (equiv->obstack);
+
+ if (equiv != m_equiv)
+ {
+ if (equiv && !bitmap_empty_p (equiv))
+ bitmap_copy (m_equiv, equiv);
+ else
+ bitmap_clear (m_equiv);
+ }
+}
+
+value_range::value_range (tree type, value_range_type vrtype,
+ tree min, tree max, bitmap equiv)
+{
+ m_equiv = NULL;
+ init (type, vrtype, min, max, equiv);
+ if (flag_checking)
+ check ();
+}
+
+void
+value_range::copy_with_equiv_update (const value_range *from)
+{
+ init (from->m_type, from->m_vrtype, from->m_min, from->m_max,
+ from->m_equiv);
+}
+
+/* Check the validity of the range. */
+
+void
+value_range::check ()
+{
+ if (flag_checking
+ && (m_vrtype == VR_RANGE || m_vrtype == VR_ANTI_RANGE))
+ {
+ int cmp;
+
+ gcc_assert (m_min && m_max);
+
+ gcc_assert (!TREE_OVERFLOW_P (m_min) && !TREE_OVERFLOW_P (m_max));
+
+ if (INTEGRAL_TYPE_P (TREE_TYPE (m_min)) && m_vrtype == VR_ANTI_RANGE)
+ gcc_assert (!vrp_val_is_min (m_min) || !vrp_val_is_max (m_max));
+
+ cmp = compare_values (m_min, m_max);
+ gcc_assert (cmp == 0 || cmp == -1 || cmp == -2);
+ }
+
+ if (flag_checking
+ && (m_vrtype == VR_UNDEFINED || m_vrtype == VR_VARYING))
+ {
+ gcc_assert (m_min == NULL_TREE && m_max == NULL_TREE);
+ gcc_assert (m_equiv == NULL || bitmap_empty_p (m_equiv));
+ }
+
+}
+
+bool
+value_range::operator== (const value_range &other) const
+{
+ return (m_type == other.m_type
+ && m_vrtype == other.m_vrtype
+ && vrp_operand_equal_p (m_min, other.m_min)
+ && vrp_operand_equal_p (m_max, other.m_max)
+ && vrp_bitmap_equal_p (m_equiv, other.m_equiv));
+}
+
+bool
+value_range::operator!= (const value_range &other) const
+{
+ return !(*this == other);
+}
+
+bool
+value_range::null_p () const
+{
+ return (m_vrtype == VR_RANGE
+ && integer_zerop (m_min)
+ && integer_zerop (m_max));
+}
+
+bool
+value_range::symbolic_p () const
+{
+ return (!varying_p ()
+ && !undefined_p ()
+ && (!is_gimple_min_invariant (m_min)
+ || !is_gimple_min_invariant (m_max)));
+}
+
+/* NOTE: Numeric is not the inverse of symbolic_p because the range
+ could also be varying or undefined. Ideally they should be inverse
+ of each other, with varying only applying to symbolics. Varying of
+ numerics would be represented as [-MIN, +MAX]. */
+
+bool
+value_range::numeric_p () const
+{
+ return (!varying_p ()
+ && !undefined_p ()
+ && TREE_CODE (m_min) == INTEGER_CST
+ && TREE_CODE (m_max) == INTEGER_CST);
+}
+
+bool
+value_range::may_contain_p (tree val) const
+{
+ if (varying_p ())
+ return true;
+
+ if (undefined_p ())
+ return true;
+
+ if (m_vrtype == VR_ANTI_RANGE)
+ {
+ int res = value_inside_range (val, m_min, m_max);
+ return res == 0 || res == -2;
+ }
+ return value_inside_range (val, m_min, m_max) != 0;
+}
+
+tree
+value_range::singleton () const
+{
+ if (range_int_cst_p (this) && vrp_operand_equal_p (m_min, m_max))
+ {
+ gcc_assert (is_gimple_min_invariant (m_min));
+ return m_min;
+ }
+ return NULL;
+}
+
+/* Canonicalize the current value_range. This means adjusting for
+ wrapping ranges with MAX < MIN covering [MIN, type_max] U
+ [type_min, MAX] as anti-rage ~[MAX+1, MIN-1]. Likewise for
+ wrapping anti-ranges. In corner cases where MAX+1 or MIN-1 wraps
+ this will fall back to varying. This routine exists to ease
+ canonicalization in the case where we extract ranges from var + CST
+ op limit. */
+
+void
+value_range::canonicalize ()
+{
+ if (undefined_p () || varying_p ())
+ return;
+
+ /* Nothing to canonicalize for symbolic ranges. */
+ if (TREE_CODE (m_min) != INTEGER_CST
+ || TREE_CODE (m_max) != INTEGER_CST)
+ return;
+
+ /* Wrong order for min and max, to swap them and the VR type we need
+ to adjust them. */
+ if (tree_int_cst_lt (m_max, m_min))
+ {
+ tree one, tmp;
+
+ /* For one bit precision if max < min, then the swapped
+ range covers all values, so for VR_RANGE it is varying and
+ for VR_ANTI_RANGE empty range, so drop to varying as well. */
+ if (TYPE_PRECISION (TREE_TYPE (m_min)) == 1)
+ {
+ set_varying ();
+ return;
+ }
+
+ one = build_int_cst (TREE_TYPE (m_min), 1);
+ tmp = int_const_binop (PLUS_EXPR, m_max, one);
+ m_max = int_const_binop (MINUS_EXPR, m_min, one);
+ m_min = tmp;
+
+ /* There's one corner case, if we had [C+1, C] before we now have
+ that again. But this represents an empty value range, so drop
+ to varying in this case. */
+ if (tree_int_cst_lt (m_max, m_min))
+ {
+ set_varying ();
+ return;
+ }
+
+ m_vrtype = m_vrtype == VR_RANGE ? VR_ANTI_RANGE : VR_RANGE;
+ }
+
+ /* Anti-ranges that can be represented as ranges should be so. */
+ if (m_vrtype == VR_ANTI_RANGE)
+ {
+ /* For -fstrict-enums we may receive out-of-range ranges so consider
+ values < -INF and values > INF as -INF/INF as well. */
+ tree type = TREE_TYPE (m_min);
+ bool is_min = (INTEGRAL_TYPE_P (type)
+ && tree_int_cst_compare (m_min,
+ TYPE_MIN_VALUE (type)) <= 0);
+ bool is_max = (INTEGRAL_TYPE_P (type)
+ && tree_int_cst_compare (m_max,
+ TYPE_MAX_VALUE (type)) >= 0);
+
+ if (is_min && is_max)
+ {
+ /* We cannot deal with empty ranges, drop to varying.
+ ??? This could be VR_UNDEFINED instead. */
+ set_varying ();
+ return;
+ }
+ else if (TYPE_PRECISION (TREE_TYPE (m_min)) == 1
+ && (is_min || is_max))
+ {
+ /* Non-empty boolean ranges can always be represented
+ as a singleton range. */
+ if (is_min)
+ m_min = m_max = vrp_val_max (TREE_TYPE (m_min));
+ else
+ m_min = m_max = vrp_val_min (TREE_TYPE (m_min));
+ m_vrtype = VR_RANGE;
+ }
+ else if (is_min
+ /* As a special exception preserve non-null ranges. */
+ && !(TYPE_UNSIGNED (TREE_TYPE (m_min))
+ && integer_zerop (m_max)))
+ {
+ tree one = build_int_cst (TREE_TYPE (m_max), 1);
+ m_min = int_const_binop (PLUS_EXPR, m_max, one);
+ m_max = vrp_val_max (TREE_TYPE (m_max));
+ m_vrtype = VR_RANGE;
+ }
+ else if (is_max)
+ {
+ tree one = build_int_cst (TREE_TYPE (m_min), 1);
+ m_max = int_const_binop (MINUS_EXPR, m_min, one);
+ m_min = vrp_val_min (TREE_TYPE (m_min));
+ m_vrtype = VR_RANGE;
+ }
+ }
+
+ /* Do not drop [-INF(OVF), +INF(OVF)] to varying. (OVF) has to be sticky
+ to make sure VRP iteration terminates, otherwise we can get into
+ oscillations. */
+}
+
/* Return true if the SSA name NAME is live on the edge E. */
static bool
@@ -245,10 +499,7 @@ intersect_range_with_nonzero_bits (enum value_range_type vr_type,
static inline void
set_value_range_to_undefined (value_range *vr)
{
- vr->type = VR_UNDEFINED;
- vr->min = vr->max = NULL_TREE;
- if (vr->equiv)
- bitmap_clear (vr->equiv);
+ vr->set_undefined ();
}
/* Set value range VR to VR_VARYING. */
@@ -256,183 +507,26 @@ set_value_range_to_undefined (value_range *vr)
void
set_value_range_to_varying (value_range *vr)
{
- vr->type = VR_VARYING;
- vr->min = vr->max = NULL_TREE;
- if (vr->equiv)
- bitmap_clear (vr->equiv);
+ vr->set_varying ();
}
/* Set value range VR to {T, MIN, MAX, EQUIV}. */
void
-set_value_range (value_range *vr, enum value_range_type t, tree min,
- tree max, bitmap equiv)
+set_value_range (value_range *vr, tree type, enum value_range_type vrtype,
+ tree min, tree max, bitmap equiv)
{
- /* Check the validity of the range. */
- if (flag_checking
- && (t == VR_RANGE || t == VR_ANTI_RANGE))
- {
- int cmp;
-
- gcc_assert (min && max);
-
- gcc_assert (!TREE_OVERFLOW_P (min) && !TREE_OVERFLOW_P (max));
-
- if (INTEGRAL_TYPE_P (TREE_TYPE (min)) && t == VR_ANTI_RANGE)
- gcc_assert (!vrp_val_is_min (min) || !vrp_val_is_max (max));
-
- cmp = compare_values (min, max);
- gcc_assert (cmp == 0 || cmp == -1 || cmp == -2);
- }
-
- if (flag_checking
- && (t == VR_UNDEFINED || t == VR_VARYING))
- {
- gcc_assert (min == NULL_TREE && max == NULL_TREE);
- gcc_assert (equiv == NULL || bitmap_empty_p (equiv));
- }
-
- vr->type = t;
- vr->min = min;
- vr->max = max;
-
- /* Since updating the equivalence set involves deep copying the
- bitmaps, only do it if absolutely necessary.
-
- All equivalence bitmaps are allocated from the same obstack. So
- we can use the obstack associated with EQUIV to allocate vr->equiv. */
- if (vr->equiv == NULL
- && equiv != NULL)
- vr->equiv = BITMAP_ALLOC (equiv->obstack);
-
- if (equiv != vr->equiv)
- {
- if (equiv && !bitmap_empty_p (equiv))
- bitmap_copy (vr->equiv, equiv);
- else
- bitmap_clear (vr->equiv);
- }
+ value_range tmp (type, vrtype, min, max, equiv);
+ vr->copy_with_equiv_update (&tmp);
}
-
-/* Set value range VR to the canonical form of {T, MIN, MAX, EQUIV}.
- This means adjusting T, MIN and MAX representing the case of a
- wrapping range with MAX < MIN covering [MIN, type_max] U [type_min, MAX]
- as anti-rage ~[MAX+1, MIN-1]. Likewise for wrapping anti-ranges.
- In corner cases where MAX+1 or MIN-1 wraps this will fall back
- to varying.
- This routine exists to ease canonicalization in the case where we
- extract ranges from var + CST op limit. */
-
void
-set_and_canonicalize_value_range (value_range *vr, enum value_range_type t,
+set_and_canonicalize_value_range (value_range *vr,
+ enum value_range_type vrtype,
tree min, tree max, bitmap equiv)
{
- /* Use the canonical setters for VR_UNDEFINED and VR_VARYING. */
- if (t == VR_UNDEFINED)
- {
- set_value_range_to_undefined (vr);
- return;
- }
- else if (t == VR_VARYING)
- {
- set_value_range_to_varying (vr);
- return;
- }
-
- /* Nothing to canonicalize for symbolic ranges. */
- if (TREE_CODE (min) != INTEGER_CST
- || TREE_CODE (max) != INTEGER_CST)
- {
- set_value_range (vr, t, min, max, equiv);
- return;
- }
-
- /* Wrong order for min and max, to swap them and the VR type we need
- to adjust them. */
- if (tree_int_cst_lt (max, min))
- {
- tree one, tmp;
-
- /* For one bit precision if max < min, then the swapped
- range covers all values, so for VR_RANGE it is varying and
- for VR_ANTI_RANGE empty range, so drop to varying as well. */
- if (TYPE_PRECISION (TREE_TYPE (min)) == 1)
- {
- set_value_range_to_varying (vr);
- return;
- }
-
- one = build_int_cst (TREE_TYPE (min), 1);
- tmp = int_const_binop (PLUS_EXPR, max, one);
- max = int_const_binop (MINUS_EXPR, min, one);
- min = tmp;
-
- /* There's one corner case, if we had [C+1, C] before we now have
- that again. But this represents an empty value range, so drop
- to varying in this case. */
- if (tree_int_cst_lt (max, min))
- {
- set_value_range_to_varying (vr);
- return;
- }
-
- t = t == VR_RANGE ? VR_ANTI_RANGE : VR_RANGE;
- }
-
- /* Anti-ranges that can be represented as ranges should be so. */
- if (t == VR_ANTI_RANGE)
- {
- /* For -fstrict-enums we may receive out-of-range ranges so consider
- values < -INF and values > INF as -INF/INF as well. */
- tree type = TREE_TYPE (min);
- bool is_min = (INTEGRAL_TYPE_P (type)
- && tree_int_cst_compare (min, TYPE_MIN_VALUE (type)) <= 0);
- bool is_max = (INTEGRAL_TYPE_P (type)
- && tree_int_cst_compare (max, TYPE_MAX_VALUE (type)) >= 0);
-
- if (is_min && is_max)
- {
- /* We cannot deal with empty ranges, drop to varying.
- ??? This could be VR_UNDEFINED instead. */
- set_value_range_to_varying (vr);
- return;
- }
- else if (TYPE_PRECISION (TREE_TYPE (min)) == 1
- && (is_min || is_max))
- {
- /* Non-empty boolean ranges can always be represented
- as a singleton range. */
- if (is_min)
- min = max = vrp_val_max (TREE_TYPE (min));
- else
- min = max = vrp_val_min (TREE_TYPE (min));
- t = VR_RANGE;
- }
- else if (is_min
- /* As a special exception preserve non-null ranges. */
- && !(TYPE_UNSIGNED (TREE_TYPE (min))
- && integer_zerop (max)))
- {
- tree one = build_int_cst (TREE_TYPE (max), 1);
- min = int_const_binop (PLUS_EXPR, max, one);
- max = vrp_val_max (TREE_TYPE (max));
- t = VR_RANGE;
- }
- else if (is_max)
- {
- tree one = build_int_cst (TREE_TYPE (min), 1);
- max = int_const_binop (MINUS_EXPR, min, one);
- min = vrp_val_min (TREE_TYPE (min));
- t = VR_RANGE;
- }
- }
-
- /* Do not drop [-INF(OVF), +INF(OVF)] to varying. (OVF) has to be sticky
- to make sure VRP iteration terminates, otherwise we can get into
- oscillations. */
-
- set_value_range (vr, t, min, max, equiv);
+ *vr = value_range (vr->type (), vrtype, min, max, equiv);
+ vr->canonicalize ();
}
/* Copy value range FROM into value range TO. */
@@ -440,7 +534,7 @@ set_and_canonicalize_value_range (value_range *vr, enum value_range_type t,
void
copy_value_range (value_range *to, const value_range *from)
{
- set_value_range (to, from->type, from->min, from->max, from->equiv);
+ to->copy_with_equiv_update (from);
}
/* Set value range VR to a single value. This function is only called
@@ -462,7 +556,7 @@ void
set_value_range_to_nonnull (value_range *vr, tree type)
{
tree zero = build_int_cst (type, 0);
- set_value_range (vr, VR_ANTI_RANGE, zero, zero, vr->equiv);
+ set_value_range (vr, VR_ANTI_RANGE, zero, zero, vr->equiv ());
}
@@ -471,7 +565,7 @@ set_value_range_to_nonnull (value_range *vr, tree type)
void
set_value_range_to_null (value_range *vr, tree type)
{
- set_value_range_to_value (vr, build_int_cst (type, 0), vr->equiv);
+ set_value_range_to_value (vr, build_int_cst (type, 0), vr->equiv ());
}
/* Return true, if VAL1 and VAL2 are equal values for VRP purposes. */
@@ -503,9 +597,15 @@ vrp_bitmap_equal_p (const_bitmap b1, const_bitmap b2)
static inline bool
range_is_null (const value_range *vr)
{
- return vr->type == VR_RANGE
- && integer_zerop (vr->min)
- && integer_zerop (vr->max);
+ return vr->null_p ();
+}
+
+static inline bool
+range_is_nonnull (const value_range *vr)
+{
+ return (vr->vrtype () == VR_ANTI_RANGE
+ && vr->min () == vr->max ()
+ && integer_zerop (vr->min ()));
}
/* Return true if max and min of VR are INTEGER_CST. It's not necessary
@@ -514,9 +614,9 @@ range_is_null (const value_range *vr)
bool
range_int_cst_p (const value_range *vr)
{
- return (vr->type == VR_RANGE
- && TREE_CODE (vr->max) == INTEGER_CST
- && TREE_CODE (vr->min) == INTEGER_CST);
+ return (vr->vrtype () == VR_RANGE
+ && TREE_CODE (vr->min ()) == INTEGER_CST
+ && TREE_CODE (vr->max ()) == INTEGER_CST);
}
/* Return true if VR is a INTEGER_CST singleton. */
@@ -525,16 +625,7 @@ bool
range_int_cst_singleton_p (const value_range *vr)
{
return (range_int_cst_p (vr)
- && tree_int_cst_equal (vr->min, vr->max));
-}
-
-/* Return true if value range VR involves at least one symbol. */
-
-bool
-symbolic_range_p (const value_range *vr)
-{
- return (!is_gimple_min_invariant (vr->min)
- || !is_gimple_min_invariant (vr->max));
+ && tree_int_cst_equal (vr->min (), vr->max ()));
}
/* Return the single symbol (an SSA_NAME) contained in T if any, or NULL_TREE
@@ -849,20 +940,8 @@ value_inside_range (tree val, tree min, tree max)
bool
range_includes_zero_p (const value_range *vr)
{
- if (vr->type == VR_VARYING)
- return true;
-
- /* Ughh, we don't know. We choose not to optimize. */
- if (vr->type == VR_UNDEFINED)
- return true;
-
- tree zero = build_int_cst (TREE_TYPE (vr->min), 0);
- if (vr->type == VR_ANTI_RANGE)
- {
- int res = value_inside_range (zero, vr->min, vr->max);
- return res == 0 || res == -2;
- }
- return value_inside_range (zero, vr->min, vr->max) != 0;
+ tree zero = build_int_cst (TREE_TYPE (vr->type ()), 0);
+ return vr->may_contain_p (zero);
}
/* If *VR has a value rante that is a single constant value return that,
@@ -871,12 +950,7 @@ range_includes_zero_p (const value_range *vr)
tree
value_range_constant_singleton (const value_range *vr)
{
- if (vr->type == VR_RANGE
- && vrp_operand_equal_p (vr->min, vr->max)
- && is_gimple_min_invariant (vr->min))
- return vr->min;
-
- return NULL_TREE;
+ return vr->singleton ();
}
/* Value range wrapper for wide_int_range_set_zero_nonzero_bits.
@@ -899,8 +973,8 @@ vrp_set_zero_nonzero_bits (const tree expr_type,
return false;
}
wide_int_range_set_zero_nonzero_bits (TYPE_SIGN (expr_type),
- wi::to_wide (vr->min),
- wi::to_wide (vr->max),
+ wi::to_wide (vr->min ()),
+ wi::to_wide (vr->max ()),
*may_be_nonzero, *must_be_nonzero);
return true;
}
@@ -914,40 +988,36 @@ static bool
ranges_from_anti_range (const value_range *ar,
value_range *vr0, value_range *vr1)
{
- tree type = TREE_TYPE (ar->min);
+ tree type = TREE_TYPE (ar->type ());
- vr0->type = VR_UNDEFINED;
- vr1->type = VR_UNDEFINED;
+ vr0->set_undefined ();
+ vr1->set_undefined ();
/* As a future improvement, we could handle ~[0, A] as: [-INF, -1] U
[A+1, +INF]. Not sure if this helps in practice, though. */
- if (ar->type != VR_ANTI_RANGE
- || TREE_CODE (ar->min) != INTEGER_CST
- || TREE_CODE (ar->max) != INTEGER_CST
+ if (ar->vrtype () != VR_ANTI_RANGE
+ || TREE_CODE (ar->min ()) != INTEGER_CST
+ || TREE_CODE (ar->max ()) != INTEGER_CST
|| !vrp_val_min (type)
|| !vrp_val_max (type))
return false;
- if (!vrp_val_is_min (ar->min))
- {
- vr0->type = VR_RANGE;
- vr0->min = vrp_val_min (type);
- vr0->max = wide_int_to_tree (type, wi::to_wide (ar->min) - 1);
- }
- if (!vrp_val_is_max (ar->max))
- {
- vr1->type = VR_RANGE;
- vr1->min = wide_int_to_tree (type, wi::to_wide (ar->max) + 1);
- vr1->max = vrp_val_max (type);
- }
- if (vr0->type == VR_UNDEFINED)
+ if (!vrp_val_is_min (ar->min ()))
+ *vr0 = value_range (type, VR_RANGE,
+ vrp_val_min (type),
+ wide_int_to_tree (type, wi::to_wide (ar->min ()) - 1));
+ if (!vrp_val_is_max (ar->max ()))
+ *vr1 = value_range (type, VR_RANGE,
+ wide_int_to_tree (type, wi::to_wide (ar->max ()) + 1),
+ vrp_val_max (type));
+ if (vr0->undefined_p ())
{
*vr0 = *vr1;
- vr1->type = VR_UNDEFINED;
+ vr1->set_undefined ();
}
- return vr0->type != VR_UNDEFINED;
+ return !vr0->undefined_p ();
}
/* Extract the components of a value range into a pair of wide ints in
@@ -961,13 +1031,11 @@ extract_range_into_wide_ints (const value_range *vr,
signop sign, unsigned prec,
wide_int &wmin, wide_int &wmax)
{
- if ((vr->type == VR_RANGE
- || vr->type == VR_ANTI_RANGE)
- && TREE_CODE (vr->min) == INTEGER_CST
- && TREE_CODE (vr->max) == INTEGER_CST)
+ gcc_assert (vr->vrtype () != VR_ANTI_RANGE);
+ if (range_int_cst_p (vr))
{
- wmin = wi::to_wide (vr->min);
- wmax = wi::to_wide (vr->max);
+ wmin = wi::to_wide (vr->min ());
+ wmax = wi::to_wide (vr->max ());
}
else
{
@@ -994,14 +1062,15 @@ extract_range_from_multiplicative_op (value_range *vr,
|| code == ROUND_DIV_EXPR
|| code == RSHIFT_EXPR
|| code == LSHIFT_EXPR);
- gcc_assert (vr0->type == VR_RANGE && vr0->type == vr1->type);
+ gcc_assert (vr0->vrtype () == VR_RANGE
+ && vr0->vrtype () == vr1->vrtype ());
- tree type = TREE_TYPE (vr0->min);
+ tree type = vr0->type ();
wide_int res_lb, res_ub;
- wide_int vr0_lb = wi::to_wide (vr0->min);
- wide_int vr0_ub = wi::to_wide (vr0->max);
- wide_int vr1_lb = wi::to_wide (vr1->min);
- wide_int vr1_ub = wi::to_wide (vr1->max);
+ wide_int vr0_lb = wi::to_wide (vr0->min ());
+ wide_int vr0_ub = wi::to_wide (vr0->max ());
+ wide_int vr1_lb = wi::to_wide (vr1->min ());
+ wide_int vr1_ub = wi::to_wide (vr1->max ());
bool overflow_undefined = TYPE_OVERFLOW_UNDEFINED (type);
bool overflow_wraps = TYPE_OVERFLOW_WRAPS (type);
unsigned prec = TYPE_PRECISION (type);
@@ -1114,8 +1183,6 @@ set_value_range_with_overflow (value_range &vr,
{
const signop sgn = TYPE_SIGN (type);
const unsigned int prec = TYPE_PRECISION (type);
- vr.type = VR_RANGE;
- vr.equiv = NULL;
if (TYPE_OVERFLOW_WRAPS (type))
{
/* If overflow wraps, truncate the values and adjust the
@@ -1126,8 +1193,10 @@ set_value_range_with_overflow (value_range &vr,
{
/* No overflow or both overflow or underflow. The
range kind stays VR_RANGE. */
- vr.min = wide_int_to_tree (type, tmin);
- vr.max = wide_int_to_tree (type, tmax);
+ vr = value_range (type, VR_RANGE,
+ wide_int_to_tree (type, tmin),
+ wide_int_to_tree (type, tmax));
+ return;
}
else if ((min_ovf == wi::OVF_UNDERFLOW && max_ovf == wi::OVF_NONE)
|| (max_ovf == wi::OVF_OVERFLOW && min_ovf == wi::OVF_NONE))
@@ -1136,7 +1205,6 @@ set_value_range_with_overflow (value_range &vr,
changes to VR_ANTI_RANGE. */
bool covers = false;
wide_int tem = tmin;
- vr.type = VR_ANTI_RANGE;
tmin = tmax + 1;
if (wi::cmp (tmin, tmax, sgn) < 0)
covers = true;
@@ -1151,8 +1219,10 @@ set_value_range_with_overflow (value_range &vr,
set_value_range_to_varying (&vr);
return;
}
- vr.min = wide_int_to_tree (type, tmin);
- vr.max = wide_int_to_tree (type, tmax);
+ vr = value_range (type, VR_ANTI_RANGE,
+ wide_int_to_tree (type, tmin),
+ wide_int_to_tree (type, tmax));
+ return;
}
else
{
@@ -1167,19 +1237,21 @@ set_value_range_with_overflow (value_range &vr,
value. */
wide_int type_min = wi::min_value (prec, sgn);
wide_int type_max = wi::max_value (prec, sgn);
+ tree min, max;
if (min_ovf == wi::OVF_UNDERFLOW)
- vr.min = wide_int_to_tree (type, type_min);
+ min = wide_int_to_tree (type, type_min);
else if (min_ovf == wi::OVF_OVERFLOW)
- vr.min = wide_int_to_tree (type, type_max);
+ min = wide_int_to_tree (type, type_max);
else
- vr.min = wide_int_to_tree (type, wmin);
+ min = wide_int_to_tree (type, wmin);
if (max_ovf == wi::OVF_UNDERFLOW)
- vr.max = wide_int_to_tree (type, type_min);
+ max = wide_int_to_tree (type, type_min);
else if (max_ovf == wi::OVF_OVERFLOW)
- vr.max = wide_int_to_tree (type, type_max);
+ max = wide_int_to_tree (type, type_max);
else
- vr.max = wide_int_to_tree (type, wmax);
+ max = wide_int_to_tree (type, wmax);
+ vr = value_range (type, VR_RANGE, min, max);
}
}
@@ -1196,7 +1268,7 @@ extract_range_from_binary_expr_1 (value_range *vr,
signop sign = TYPE_SIGN (expr_type);
unsigned int prec = TYPE_PRECISION (expr_type);
value_range vr0 = *vr0_, vr1 = *vr1_;
- value_range vrtem0 = VR_INITIALIZER, vrtem1 = VR_INITIALIZER;
+ value_range vrtem0 (expr_type), vrtem1 (expr_type);
enum value_range_type type;
tree min = NULL_TREE, max = NULL_TREE;
int cmp;
@@ -1233,7 +1305,7 @@ extract_range_from_binary_expr_1 (value_range *vr,
}
/* If both ranges are UNDEFINED, so is the result. */
- if (vr0.type == VR_UNDEFINED && vr1.type == VR_UNDEFINED)
+ if (vr0.undefined_p () && vr1.undefined_p ())
{
set_value_range_to_undefined (vr);
return;
@@ -1242,19 +1314,16 @@ extract_range_from_binary_expr_1 (value_range *vr,
code. At some point we may want to special-case operations that
have UNDEFINED result for all or some value-ranges of the not UNDEFINED
operand. */
- else if (vr0.type == VR_UNDEFINED)
+ else if (vr0.undefined_p ())
set_value_range_to_varying (&vr0);
- else if (vr1.type == VR_UNDEFINED)
+ else if (vr1.undefined_p ())
set_value_range_to_varying (&vr1);
/* We get imprecise results from ranges_from_anti_range when
code is EXACT_DIV_EXPR. We could mask out bits in the resulting
range, but then we also need to hack up vrp_meet. It's just
easier to special case when vr0 is ~[0,0] for EXACT_DIV_EXPR. */
- if (code == EXACT_DIV_EXPR
- && vr0.type == VR_ANTI_RANGE
- && vr0.min == vr0.max
- && integer_zerop (vr0.min))
+ if (code == EXACT_DIV_EXPR && range_is_nonnull (&vr0))
{
set_value_range_to_nonnull (vr, expr_type);
return;
@@ -1262,27 +1331,26 @@ extract_range_from_binary_expr_1 (value_range *vr,
/* Now canonicalize anti-ranges to ranges when they are not symbolic
and express ~[] op X as ([]' op X) U ([]'' op X). */
- if (vr0.type == VR_ANTI_RANGE
+ if (vr0.vrtype () == VR_ANTI_RANGE
&& ranges_from_anti_range (&vr0, &vrtem0, &vrtem1))
{
extract_range_from_binary_expr_1 (vr, code, expr_type, &vrtem0, vr1_);
- if (vrtem1.type != VR_UNDEFINED)
+ if (!vrtem1.undefined_p ())
{
- value_range vrres = VR_INITIALIZER;
- extract_range_from_binary_expr_1 (&vrres, code, expr_type,
- &vrtem1, vr1_);
+ value_range vrres (expr_type);
+ extract_range_from_binary_expr_1 (&vrres, code, expr_type, &vrtem1, vr1_);
vrp_meet (vr, &vrres);
}
return;
}
/* Likewise for X op ~[]. */
- if (vr1.type == VR_ANTI_RANGE
+ if (vr1.vrtype () == VR_ANTI_RANGE
&& ranges_from_anti_range (&vr1, &vrtem0, &vrtem1))
{
extract_range_from_binary_expr_1 (vr, code, expr_type, vr0_, &vrtem0);
- if (vrtem1.type != VR_UNDEFINED)
+ if (!vrtem1.undefined_p ())
{
- value_range vrres = VR_INITIALIZER;
+ value_range vrres (expr_type);
extract_range_from_binary_expr_1 (&vrres, code, expr_type,
vr0_, &vrtem1);
vrp_meet (vr, &vrres);
@@ -1291,7 +1359,7 @@ extract_range_from_binary_expr_1 (value_range *vr,
}
/* The type of the resulting value range defaults to VR0.TYPE. */
- type = vr0.type;
+ type = vr0.vrtype ();
/* Refuse to operate on VARYING ranges, ranges of different kinds
and symbolic ranges. As an exception, we allow BIT_{AND,IOR}
@@ -1314,11 +1382,11 @@ extract_range_from_binary_expr_1 (value_range *vr,
&& code != MINUS_EXPR
&& code != RSHIFT_EXPR
&& code != POINTER_PLUS_EXPR
- && (vr0.type == VR_VARYING
- || vr1.type == VR_VARYING
- || vr0.type != vr1.type
- || symbolic_range_p (&vr0)
- || symbolic_range_p (&vr1)))
+ && (vr0.varying_p ()
+ || vr1.varying_p ()
+ || vr0.vrtype () != vr1.vrtype ()
+ || vr0.symbolic_p ()
+ || vr1.symbolic_p ()))
{
set_value_range_to_varying (vr);
return;
@@ -1376,24 +1444,20 @@ extract_range_from_binary_expr_1 (value_range *vr,
/* This will normalize things such that calculating
[0,0] - VR_VARYING is not dropped to varying, but is
calculated as [MIN+1, MAX]. */
- if (vr0.type == VR_VARYING)
- {
- vr0.type = VR_RANGE;
- vr0.min = vrp_val_min (expr_type);
- vr0.max = vrp_val_max (expr_type);
- }
- if (vr1.type == VR_VARYING)
- {
- vr1.type = VR_RANGE;
- vr1.min = vrp_val_min (expr_type);
- vr1.max = vrp_val_max (expr_type);
- }
+ if (vr0.varying_p ())
+ vr0 = value_range (vr0.type (), VR_RANGE,
+ vrp_val_min (expr_type),
+ vrp_val_max (expr_type), vr0.equiv ());
+ if (vr1.varying_p ())
+ vr1 = value_range (vr1.type (), VR_RANGE,
+ vrp_val_min (expr_type),
+ vrp_val_max (expr_type), vr0.equiv ());
const bool minus_p = (code == MINUS_EXPR);
- tree min_op0 = vr0.min;
- tree min_op1 = minus_p ? vr1.max : vr1.min;
- tree max_op0 = vr0.max;
- tree max_op1 = minus_p ? vr1.min : vr1.max;
+ tree min_op0 = vr0.min ();
+ tree min_op1 = minus_p ? vr1.max () : vr1.min ();
+ tree max_op0 = vr0.max ();
+ tree max_op1 = minus_p ? vr1.min () : vr1.max ();
tree sym_min_op0 = NULL_TREE;
tree sym_min_op1 = NULL_TREE;
tree sym_max_op0 = NULL_TREE;
@@ -1406,7 +1470,7 @@ extract_range_from_binary_expr_1 (value_range *vr,
single-symbolic ranges, try to compute the precise resulting range,
but only if we know that this resulting range will also be constant
or single-symbolic. */
- if (vr0.type == VR_RANGE && vr1.type == VR_RANGE
+ if (vr0.vrtype () == VR_RANGE && vr1.vrtype () == VR_RANGE
&& (TREE_CODE (min_op0) == INTEGER_CST
|| (sym_min_op0
= get_single_symbol (min_op0, &neg_min_op0, &min_op0)))
@@ -1446,21 +1510,19 @@ extract_range_from_binary_expr_1 (value_range *vr,
/* Adjust the range for possible overflow. */
set_value_range_with_overflow (*vr, expr_type,
wmin, wmax, min_ovf, max_ovf);
- if (vr->type == VR_VARYING)
+ if (vr->varying_p ())
return;
/* Build the symbolic bounds if needed. */
- adjust_symbolic_bound (vr->min, code, expr_type,
+ min = vr->min ();
+ max = vr->max ();
+ adjust_symbolic_bound (min, code, expr_type,
sym_min_op0, sym_min_op1,
neg_min_op0, neg_min_op1);
- adjust_symbolic_bound (vr->max, code, expr_type,
+ adjust_symbolic_bound (max, code, expr_type,
sym_max_op0, sym_max_op1,
neg_max_op0, neg_max_op1);
- /* ?? It would probably be cleaner to eliminate min/max/type
- entirely and hold these values in VR directly. */
- min = vr->min;
- max = vr->max;
- type = vr->type;
+ type = vr->vrtype ();
}
else
{
@@ -1513,19 +1575,21 @@ extract_range_from_binary_expr_1 (value_range *vr,
{
if (range_int_cst_p (&vr1)
&& !wide_int_range_shift_undefined_p (prec,
- wi::to_wide (vr1.min),
- wi::to_wide (vr1.max)))
+ wi::to_wide (vr1.min ()),
+ wi::to_wide (vr1.max ())))
{
if (code == RSHIFT_EXPR)
{
/* Even if vr0 is VARYING or otherwise not usable, we can derive
useful ranges just from the shift count. E.g.
x >> 63 for signed 64-bit x is always [-1, 0]. */
- if (vr0.type != VR_RANGE || symbolic_range_p (&vr0))
+ if (vr0.vrtype () != VR_RANGE || vr0.symbolic_p ())
{
- vr0.type = type = VR_RANGE;
- vr0.min = vrp_val_min (expr_type);
- vr0.max = vrp_val_max (expr_type);
+ type = VR_RANGE;
+ vr0 = value_range (vr0.type (), type,
+ vrp_val_min (expr_type),
+ vrp_val_max (expr_type),
+ vr0.equiv ());
}
extract_range_from_multiplicative_op (vr, code, &vr0, &vr1);
return;
@@ -1535,10 +1599,10 @@ extract_range_from_binary_expr_1 (value_range *vr,
{
wide_int res_lb, res_ub;
if (wide_int_range_lshift (res_lb, res_ub, sign, prec,
- wi::to_wide (vr0.min),
- wi::to_wide (vr0.max),
- wi::to_wide (vr1.min),
- wi::to_wide (vr1.max),
+ wi::to_wide (vr0.min ()),
+ wi::to_wide (vr0.max ()),
+ wi::to_wide (vr1.min ()),
+ wi::to_wide (vr1.max ()),
TYPE_OVERFLOW_UNDEFINED (expr_type),
TYPE_OVERFLOW_WRAPS (expr_type)))
{
@@ -1596,7 +1660,7 @@ extract_range_from_binary_expr_1 (value_range *vr,
wide_int_to_tree (expr_type, wmax), NULL);
if (extra_range_p)
{
- value_range extra_range = VR_INITIALIZER;
+ value_range extra_range (expr_type);
set_value_range (&extra_range, VR_RANGE,
wide_int_to_tree (expr_type, extra_min),
wide_int_to_tree (expr_type, extra_max), NULL);
@@ -1733,7 +1797,9 @@ extract_range_from_unary_expr (value_range *vr,
{
signop sign = TYPE_SIGN (type);
unsigned int prec = TYPE_PRECISION (type);
- value_range vr0 = *vr0_, vrtem0 = VR_INITIALIZER, vrtem1 = VR_INITIALIZER;
+ value_range vr0 = *vr0_;
+ value_range vrtem0 (vr0.type ());
+ value_range vrtem1 (vr0.type ());
/* VRP only operates on integral and pointer types. */
if (!(INTEGRAL_TYPE_P (op0_type)
@@ -1746,7 +1812,7 @@ extract_range_from_unary_expr (value_range *vr,
}
/* If VR0 is UNDEFINED, so is the result. */
- if (vr0.type == VR_UNDEFINED)
+ if (vr0.undefined_p ())
{
set_value_range_to_undefined (vr);
return;
@@ -1763,7 +1829,7 @@ extract_range_from_unary_expr (value_range *vr,
{
/* -X is simply 0 - X, so re-use existing code that also handles
anti-ranges fine. */
- value_range zero = VR_INITIALIZER;
+ value_range zero (type);
set_value_range_to_value (&zero, build_int_cst (type, 0), NULL);
extract_range_from_binary_expr_1 (vr, MINUS_EXPR, type, &zero, &vr0);
return;
@@ -1772,7 +1838,7 @@ extract_range_from_unary_expr (value_range *vr,
{
/* ~X is simply -1 - X, so re-use existing code that also handles
anti-ranges fine. */
- value_range minusone = VR_INITIALIZER;
+ value_range minusone (type);
set_value_range_to_value (&minusone, build_int_cst (type, -1), NULL);
extract_range_from_binary_expr_1 (vr, MINUS_EXPR,
type, &minusone, &vr0);
@@ -1781,13 +1847,13 @@ extract_range_from_unary_expr (value_range *vr,
/* Now canonicalize anti-ranges to ranges when they are not symbolic
and express op ~[] as (op []') U (op []''). */
- if (vr0.type == VR_ANTI_RANGE
+ if (vr0.vrtype () == VR_ANTI_RANGE
&& ranges_from_anti_range (&vr0, &vrtem0, &vrtem1))
{
extract_range_from_unary_expr (vr, code, type, &vrtem0, op0_type);
- if (vrtem1.type != VR_UNDEFINED)
+ if (!vrtem1.undefined_p ())
{
- value_range vrres = VR_INITIALIZER;
+ value_range vrres (type);
extract_range_from_unary_expr (&vrres, code, type,
&vrtem1, op0_type);
vrp_meet (vr, &vrres);
@@ -1822,8 +1888,8 @@ extract_range_from_unary_expr (value_range *vr,
pointer anti-ranges. Any remaining anti-ranges at this point
will be integer conversions from SSA names that will be
normalized into VARYING. For instance: ~[x_55, x_55]. */
- gcc_assert (vr0.type != VR_ANTI_RANGE
- || TREE_CODE (vr0.min) != INTEGER_CST);
+ gcc_assert (vr0.vrtype () != VR_ANTI_RANGE
+ || TREE_CODE (vr0.min ()) != INTEGER_CST);
/* NOTES: Previously we were returning VARYING for all symbolics, but
we can do better by treating them as [-MIN, +MAX]. For
@@ -1888,39 +1954,39 @@ dump_value_range (FILE *file, const value_range *vr)
{
if (vr == NULL)
fprintf (file, "[]");
- else if (vr->type == VR_UNDEFINED)
+ else if (vr->undefined_p ())
fprintf (file, "UNDEFINED");
- else if (vr->type == VR_RANGE || vr->type == VR_ANTI_RANGE)
+ else if (vr->vrtype () == VR_RANGE || vr->vrtype () == VR_ANTI_RANGE)
{
- tree type = TREE_TYPE (vr->min);
+ tree type = TREE_TYPE (vr->min ());
- fprintf (file, "%s[", (vr->type == VR_ANTI_RANGE) ? "~" : "");
+ fprintf (file, "%s[", (vr->vrtype () == VR_ANTI_RANGE) ? "~" : "");
if (INTEGRAL_TYPE_P (type)
&& !TYPE_UNSIGNED (type)
- && vrp_val_is_min (vr->min))
+ && vrp_val_is_min (vr->min ()))
fprintf (file, "-INF");
else
- print_generic_expr (file, vr->min);
+ print_generic_expr (file, vr->min ());
fprintf (file, ", ");
if (INTEGRAL_TYPE_P (type)
- && vrp_val_is_max (vr->max))
+ && vrp_val_is_max (vr->max ()))
fprintf (file, "+INF");
else
- print_generic_expr (file, vr->max);
+ print_generic_expr (file, vr->max ());
fprintf (file, "]");
- if (vr->equiv)
+ if (vr->equiv ())
{
bitmap_iterator bi;
unsigned i, c = 0;
fprintf (file, " EQUIVALENCES: { ");
- EXECUTE_IF_SET_IN_BITMAP (vr->equiv, 0, i, bi)
+ EXECUTE_IF_SET_IN_BITMAP (vr->equiv (), 0, i, bi)
{
print_generic_expr (file, ssa_name (i));
fprintf (file, " ");
@@ -1930,7 +1996,7 @@ dump_value_range (FILE *file, const value_range *vr)
fprintf (file, "} (%u elements)", c);
}
}
- else if (vr->type == VR_VARYING)
+ else if (vr->varying_p ())
fprintf (file, "VARYING");
else
fprintf (file, "INVALID RANGE");
@@ -4193,14 +4259,14 @@ vrp_prop::check_array_ref (location_t location, tree ref,
if (TREE_CODE (low_sub) == SSA_NAME)
{
vr = get_value_range (low_sub);
- if (vr->type == VR_RANGE || vr->type == VR_ANTI_RANGE)
+ if (!vr->undefined_p () && !vr->varying_p ())
{
- low_sub = vr->type == VR_RANGE ? vr->max : vr->min;
- up_sub = vr->type == VR_RANGE ? vr->min : vr->max;
+ low_sub = vr->vrtype () == VR_RANGE ? vr->max () : vr->min ();
+ up_sub = vr->vrtype () == VR_RANGE ? vr->min () : vr->max ();
}
}
- if (vr && vr->type == VR_ANTI_RANGE)
+ if (vr && vr->vrtype () == VR_ANTI_RANGE)
{
if (up_bound
&& TREE_CODE (up_sub) == INTEGER_CST
@@ -4328,21 +4394,24 @@ vrp_prop::check_mem_ref (location_t location, tree ref,
break;
vr = get_value_range (varoff);
- if (!vr || vr->type == VR_UNDEFINED || !vr->min || !vr->max)
+ // FIXME: If this never triggers, both tests below simplify to:
+ // if (!vr || !vr->numeric_p ())
+ if (!vr->min () || !vr->max ())
+ gcc_assert (vr->varying_p ());
+ if (!vr || vr->undefined_p () || !vr->min () || !vr->max ())
break;
- if (TREE_CODE (vr->min) != INTEGER_CST
- || TREE_CODE (vr->max) != INTEGER_CST)
+ if (!vr->numeric_p ())
break;
- if (vr->type == VR_RANGE)
+ if (vr->vrtype () == VR_RANGE)
{
- if (tree_int_cst_lt (vr->min, vr->max))
+ if (tree_int_cst_lt (vr->min (), vr->max ()))
{
offset_int min
- = wi::to_offset (fold_convert (ptrdiff_type_node, vr->min));
+ = wi::to_offset (fold_convert (ptrdiff_type_node, vr->min ()));
offset_int max
- = wi::to_offset (fold_convert (ptrdiff_type_node, vr->max));
+ = wi::to_offset (fold_convert (ptrdiff_type_node, vr->max ()));
if (min < max)
{
offrange[0] += min;
@@ -5114,8 +5183,8 @@ find_case_label_range (gswitch *stmt, tree min, tree max, size_t *min_idx,
enum ssa_prop_result
vrp_prop::visit_stmt (gimple *stmt, edge *taken_edge_p, tree *output_p)
{
- value_range vr = VR_INITIALIZER;
tree lhs = gimple_get_lhs (stmt);
+ value_range vr (TREE_TYPE (lhs));
extract_range_from_stmt (stmt, taken_edge_p, output_p, &vr);
if (*output_p)
@@ -5131,7 +5200,7 @@ vrp_prop::visit_stmt (gimple *stmt, edge *taken_edge_p, tree *output_p)
fprintf (dump_file, "\n");
}
- if (vr.type == VR_VARYING)
+ if (vr.varying_p ())
return SSA_PROP_VARYING;
return SSA_PROP_INTERESTING;
@@ -5184,17 +5253,14 @@ vrp_prop::visit_stmt (gimple *stmt, edge *taken_edge_p, tree *output_p)
SSA_PROP_NOT_INTERESTING. If there are no
{REAL,IMAG}PART_EXPR uses at all,
return SSA_PROP_VARYING. */
- value_range new_vr = VR_INITIALIZER;
+ value_range new_vr (TREE_TYPE (lhs));
extract_range_basic (&new_vr, use_stmt);
const value_range *old_vr = get_value_range (use_lhs);
- if (old_vr->type != new_vr.type
- || !vrp_operand_equal_p (old_vr->min, new_vr.min)
- || !vrp_operand_equal_p (old_vr->max, new_vr.max)
- || !vrp_bitmap_equal_p (old_vr->equiv, new_vr.equiv))
+ if (*old_vr != new_vr)
res = SSA_PROP_INTERESTING;
else
res = SSA_PROP_NOT_INTERESTING;
- BITMAP_FREE (new_vr.equiv);
+ new_vr.equiv_free ();
if (res == SSA_PROP_INTERESTING)
{
*output_p = lhs;
@@ -5805,8 +5871,6 @@ intersect_ranges (enum value_range_type *vr0type,
*vr0min = vr1min;
*vr0max = vr1max;
}
-
- return;
}
@@ -5816,12 +5880,10 @@ intersect_ranges (enum value_range_type *vr0type,
static void
vrp_intersect_ranges_1 (value_range *vr0, const value_range *vr1)
{
- value_range saved;
-
/* If either range is VR_VARYING the other one wins. */
- if (vr1->type == VR_VARYING)
+ if (vr1->varying_p ())
return;
- if (vr0->type == VR_VARYING)
+ if (vr0->varying_p ())
{
copy_value_range (vr0, vr1);
return;
@@ -5829,9 +5891,9 @@ vrp_intersect_ranges_1 (value_range *vr0, const value_range *vr1)
/* When either range is VR_UNDEFINED the resulting range is
VR_UNDEFINED, too. */
- if (vr0->type == VR_UNDEFINED)
+ if (vr0->undefined_p ())
return;
- if (vr1->type == VR_UNDEFINED)
+ if (vr1->undefined_p ())
{
set_value_range_to_undefined (vr0);
return;
@@ -5839,34 +5901,38 @@ vrp_intersect_ranges_1 (value_range *vr0, const value_range *vr1)
/* Save the original vr0 so we can return it as conservative intersection
result when our worker turns things to varying. */
- saved = *vr0;
- intersect_ranges (&vr0->type, &vr0->min, &vr0->max,
- vr1->type, vr1->min, vr1->max);
+ value_range saved (*vr0);
+
+ value_range_type vr0type = vr0->vrtype ();
+ tree vr0min = vr0->min ();
+ tree vr0max = vr0->max ();
+ intersect_ranges (&vr0type, &vr0min, &vr0max,
+ vr1->vrtype (), vr1->min (), vr1->max ());
+ *vr0 = value_range (vr0->type (), vr0type, vr0min, vr0max, vr0->equiv ());
/* Make sure to canonicalize the result though as the inversion of a
VR_RANGE can still be a VR_RANGE. */
- set_and_canonicalize_value_range (vr0, vr0->type,
- vr0->min, vr0->max, vr0->equiv);
+ vr0->canonicalize ();
/* If that failed, use the saved original VR0. */
- if (vr0->type == VR_VARYING)
+ if (vr0->varying_p ())
{
*vr0 = saved;
return;
}
/* If the result is VR_UNDEFINED there is no need to mess with
the equivalencies. */
- if (vr0->type == VR_UNDEFINED)
+ if (vr0->undefined_p ())
return;
/* The resulting set of equivalences for range intersection is the union of
the two sets. */
- if (vr0->equiv && vr1->equiv && vr0->equiv != vr1->equiv)
- bitmap_ior_into (vr0->equiv, vr1->equiv);
- else if (vr1->equiv && !vr0->equiv)
+ if (vr0->equiv () && vr1->equiv () && vr0->equiv () != vr1->equiv ())
+ vr0->equiv_ior (vr1);
+ else if (vr1->equiv () && !vr0->equiv ())
{
/* All equivalence bitmaps are allocated from the same obstack. So
we can use the obstack associated with VR to allocate vr0->equiv. */
- vr0->equiv = BITMAP_ALLOC (vr1->equiv->obstack);
- bitmap_copy (vr0->equiv, vr1->equiv);
+ vr0->set_equiv (BITMAP_ALLOC (vr1->equiv ()->obstack));
+ vr0->equiv_copy (vr1);
}
}
@@ -5897,36 +5963,39 @@ vrp_intersect_ranges (value_range *vr0, const value_range *vr1)
static void
vrp_meet_1 (value_range *vr0, const value_range *vr1)
{
- value_range saved;
-
- if (vr0->type == VR_UNDEFINED)
+ if (vr0->undefined_p ())
{
- set_value_range (vr0, vr1->type, vr1->min, vr1->max, vr1->equiv);
+ set_value_range (vr0, vr1->vrtype (), vr1->min (), vr1->max (),
+ vr1->equiv ());
return;
}
- if (vr1->type == VR_UNDEFINED)
+ if (vr1->undefined_p ())
{
/* VR0 already has the resulting range. */
return;
}
- if (vr0->type == VR_VARYING)
+ if (vr0->varying_p ())
{
/* Nothing to do. VR0 already has the resulting range. */
return;
}
- if (vr1->type == VR_VARYING)
+ if (vr1->varying_p ())
{
set_value_range_to_varying (vr0);
return;
}
- saved = *vr0;
- union_ranges (&vr0->type, &vr0->min, &vr0->max,
- vr1->type, vr1->min, vr1->max);
- if (vr0->type == VR_VARYING)
+ value_range saved (*vr0);
+ value_range_type vr0type = vr0->vrtype ();
+ tree vr0min = vr0->min ();
+ tree vr0max = vr0->max ();
+ union_ranges (&vr0type, &vr0min, &vr0max,
+ vr1->vrtype (), vr1->min (), vr1->max ());
+ *vr0 = value_range (vr0->type (), vr0type, vr0min, vr0max, vr0->equiv ());
+ if (vr0->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
@@ -5934,29 +6003,27 @@ vrp_meet_1 (value_range *vr0, const value_range *vr1)
if (range_includes_zero_p (&saved) == 0
&& range_includes_zero_p (vr1) == 0)
{
- set_value_range_to_nonnull (vr0, TREE_TYPE (saved.min));
+ set_value_range_to_nonnull (vr0, saved.type ());
/* Since this meet operation did not result from the meeting of
two equivalent names, VR0 cannot have any equivalences. */
- if (vr0->equiv)
- bitmap_clear (vr0->equiv);
+ vr0->equiv_clear ();
return;
}
set_value_range_to_varying (vr0);
return;
}
- set_and_canonicalize_value_range (vr0, vr0->type, vr0->min, vr0->max,
- vr0->equiv);
- if (vr0->type == VR_VARYING)
+ vr0->canonicalize ();
+ if (vr0->varying_p ())
return;
/* The resulting set of equivalences is always the intersection of
the two sets. */
- if (vr0->equiv && vr1->equiv && vr0->equiv != vr1->equiv)
- bitmap_and_into (vr0->equiv, vr1->equiv);
- else if (vr0->equiv && !vr1->equiv)
- bitmap_clear (vr0->equiv);
+ if (vr0->equiv () != vr1->equiv ())
+ vr0->equiv_and (vr1);
+ else if (!vr1->equiv ())
+ vr0->equiv_clear ();
}
void
@@ -5988,7 +6055,7 @@ enum ssa_prop_result
vrp_prop::visit_phi (gphi *phi)
{
tree lhs = PHI_RESULT (phi);
- value_range vr_result = VR_INITIALIZER;
+ value_range vr_result (TREE_TYPE (lhs));
extract_range_from_phi_node (phi, &vr_result);
if (update_value_range (lhs, &vr_result))
{
@@ -6001,7 +6068,7 @@ vrp_prop::visit_phi (gphi *phi)
fprintf (dump_file, "\n");
}
- if (vr_result.type == VR_VARYING)
+ if (vr_result.varying_p ())
return SSA_PROP_VARYING;
return SSA_PROP_INTERESTING;
@@ -6185,16 +6252,17 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
op = lhs_of_dominating_assert (op, bb, stmt);
const value_range *vr = vr_values->get_value_range (op);
- if ((vr->type != VR_RANGE && vr->type != VR_ANTI_RANGE)
- || symbolic_range_p (vr))
+ if (vr->undefined_p ()
+ || vr->varying_p ()
+ || vr->symbolic_p ())
return NULL_TREE;
- if (vr->type == VR_RANGE)
+ if (vr->vrtype () == VR_RANGE)
{
size_t i, j;
/* Get the range of labels that contain a part of the operand's
value range. */
- find_case_label_range (switch_stmt, vr->min, vr->max, &i, &j);
+ find_case_label_range (switch_stmt, vr->min (), vr->max (), &i, &j);
/* Is there only one such label? */
if (i == j)
@@ -6204,10 +6272,13 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
/* The i'th label will be taken only if the value range of the
operand is entirely within the bounds of this label. */
if (CASE_HIGH (label) != NULL_TREE
- ? (tree_int_cst_compare (CASE_LOW (label), vr->min) <= 0
- && tree_int_cst_compare (CASE_HIGH (label), vr->max) >= 0)
- : (tree_int_cst_equal (CASE_LOW (label), vr->min)
- && tree_int_cst_equal (vr->min, vr->max)))
+ // FIXME: Rewrite in terms of an API call
+ // vr->contains_p() or some such.
+ ? (tree_int_cst_compare (CASE_LOW (label), vr->min ()) <= 0
+ && tree_int_cst_compare (CASE_HIGH (label),
+ vr->max ()) >= 0)
+ : (tree_int_cst_equal (CASE_LOW (label), vr->min ())
+ && tree_int_cst_equal (vr->min (), vr->max ())))
return label;
}
@@ -6217,7 +6288,7 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
return gimple_switch_label (switch_stmt, 0);
}
- if (vr->type == VR_ANTI_RANGE)
+ if (vr->vrtype () == VR_ANTI_RANGE)
{
unsigned n = gimple_switch_num_labels (switch_stmt);
tree min_label = gimple_switch_label (switch_stmt, 1);
@@ -6226,10 +6297,14 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
/* The default label will be taken only if the anti-range of the
operand is entirely outside the bounds of all the (non-default)
case labels. */
- if (tree_int_cst_compare (vr->min, CASE_LOW (min_label)) <= 0
+ // FIXME: Rewrite in terms of an API call vr->contains_p()
+ // or some such.
+ if (tree_int_cst_compare (vr->min (), CASE_LOW (min_label)) <= 0
&& (CASE_HIGH (max_label) != NULL_TREE
- ? tree_int_cst_compare (vr->max, CASE_HIGH (max_label)) >= 0
- : tree_int_cst_compare (vr->max, CASE_LOW (max_label)) >= 0))
+ ? tree_int_cst_compare (vr->max (),
+ CASE_HIGH (max_label)) >= 0
+ : tree_int_cst_compare (vr->max (),
+ CASE_LOW (max_label)) >= 0))
return gimple_switch_label (switch_stmt, 0);
}
@@ -6246,11 +6321,12 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
{
edge dummy_e;
tree dummy_tree;
- value_range new_vr = VR_INITIALIZER;
+ value_range new_vr (TREE_TYPE (lhs));
vr_values->extract_range_from_stmt (stmt, &dummy_e,
&dummy_tree, &new_vr);
- if (range_int_cst_singleton_p (&new_vr))
- return new_vr.min;
+ tree singleton = new_vr.singleton ();
+ if (singleton)
+ return singleton;
}
}
@@ -6422,20 +6498,16 @@ vrp_prop::vrp_finalize (bool warn_array_bounds_p)
continue;
const value_range *vr = get_value_range (name);
- if (!name
- || (vr->type == VR_VARYING)
- || (vr->type == VR_UNDEFINED)
- || (TREE_CODE (vr->min) != INTEGER_CST)
- || (TREE_CODE (vr->max) != INTEGER_CST))
+ if (!name || vr->numeric_p ())
continue;
if (POINTER_TYPE_P (TREE_TYPE (name))
&& range_includes_zero_p (vr) == 0)
set_ptr_nonnull (name);
else if (!POINTER_TYPE_P (TREE_TYPE (name)))
- set_range_info (name, vr->type,
- wi::to_wide (vr->min),
- wi::to_wide (vr->max));
+ set_range_info (name, vr->vrtype (),
+ wi::to_wide (vr->min ()),
+ wi::to_wide (vr->max ()));
}
/* If we're checking array refs, we want to merge information on
@@ -6627,7 +6699,8 @@ determine_value_range_1 (value_range *vr, tree expr)
{
if (BINARY_CLASS_P (expr))
{
- value_range vr0 = VR_INITIALIZER, vr1 = VR_INITIALIZER;
+ value_range vr0 (TREE_TYPE (TREE_OPERAND (expr, 0)));
+ value_range vr1 (TREE_TYPE (TREE_OPERAND (expr, 1)));
determine_value_range_1 (&vr0, TREE_OPERAND (expr, 0));
determine_value_range_1 (&vr1, TREE_OPERAND (expr, 1));
extract_range_from_binary_expr_1 (vr, TREE_CODE (expr), TREE_TYPE (expr),
@@ -6635,7 +6708,7 @@ determine_value_range_1 (value_range *vr, tree expr)
}
else if (UNARY_CLASS_P (expr))
{
- value_range vr0 = VR_INITIALIZER;
+ value_range vr0 (TREE_TYPE (TREE_OPERAND (expr, 0)));
determine_value_range_1 (&vr0, TREE_OPERAND (expr, 0));
extract_range_from_unary_expr (vr, TREE_CODE (expr), TREE_TYPE (expr),
&vr0, TREE_TYPE (TREE_OPERAND (expr, 0)));
@@ -6664,15 +6737,13 @@ determine_value_range_1 (value_range *vr, tree expr)
value_range_type
determine_value_range (tree expr, wide_int *min, wide_int *max)
{
- value_range vr = VR_INITIALIZER;
+ value_range vr (TREE_TYPE (expr));
determine_value_range_1 (&vr, expr);
- if ((vr.type == VR_RANGE
- || vr.type == VR_ANTI_RANGE)
- && !symbolic_range_p (&vr))
+ if (vr.numeric_p ())
{
- *min = wi::to_wide (vr.min);
- *max = wi::to_wide (vr.max);
- return vr.type;
+ *min = wi::to_wide (vr.min ());
+ *max = wi::to_wide (vr.max ());
+ return vr.vrtype ();
}
return VR_VARYING;