aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vrp.c
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@redhat.com>2018-10-17 15:59:25 +0000
committerAldy Hernandez <aldyh@gcc.gnu.org>2018-10-17 15:59:25 +0000
commit54994253d3fc00bcb7d3e9359ff31a81c0e4543a (patch)
tree416281f18a0c359b4d87a5aeac398be374184fb6 /gcc/tree-vrp.c
parent033eb5671769a4c681a44aad08a454e667e08502 (diff)
downloadgcc-54994253d3fc00bcb7d3e9359ff31a81c0e4543a.zip
gcc-54994253d3fc00bcb7d3e9359ff31a81c0e4543a.tar.gz
gcc-54994253d3fc00bcb7d3e9359ff31a81c0e4543a.tar.bz2
bitmap.c (bitmap_head::dump): New.
* bitmap.c (bitmap_head::dump): New. * bitmap.h (bitmap_head): Add dump(). * gimple-ssa-evrp-analyze.c (evrp_range_analyzer::try_find_new_range): Adjust for value_range API. (evrp_range_analyzer::set_ssa_range_info): Same. (evrp_range_analyzer::record_ranges_from_phis): Same. (evrp_range_analyzer::record_ranges_from_stmt): Same. * gimple-ssa-evrp.c (evrp_dom_walker::before_dom_children): Same. * gimple-ssa-sprintf.c (get_int_range): Same. (format_integer): Same. (sprintf_dom_walker::handle_gimple_call): Same. * ipa-cp.c (ipcp_vr_lattice::meet_with_1): Same. (ipcp_vr_lattice::top_p): Same. (ipcp_vr_lattice::bottom_p): Same. (ipcp_vr_lattice::set_to_bottom): Same. (ipa_vr_operation_and_type_effects): Same. (propagate_vr_across_jump_function): Same. (ipcp_store_vr_results): Same. * ipa-prop.c (struct ipa_vr_ggc_hash_traits): Same. (ipa_print_node_jump_functions_for_edge): Same. (ipa_get_value_range): Same. (ipa_compute_jump_functions_for_edge): Same. (ipa_write_jump_function): Same. * tree-ssa-dom.c (simplify_stmt_for_jump_threading): Same. * tree-ssa-threadedge.c (record_temporary_equivalences_from_phis): Same. * vr-values.c (set_value_range_to_nonnegative): Same. (set_value_range_to_truthvalue): Same. (vr_values::get_value_range): Same. (vr_values::set_defs_to_varying): Same. (vr_values::update_value_range): Same. (symbolic_range_based_on_p): Same. (vr_values::op_with_boolean_value_range_p): Same. (vr_values::extract_range_for_var_from_comparison_expr): Same. (vr_values::extract_range_from_ssa_name): Same. (vr_values::extract_range_from_binary_expr): Same. (vr_values::extract_range_from_unary_expr): Same. (vr_values::extract_range_from_cond_expr): Same. (vr_values::extract_range_from_comparison): Same. (vr_values::check_for_binary_op_overflow): Same. (vr_values::extract_range_basic): Same. (vr_values::extract_range_from_assignment): Same. (compare_ranges): Same. (compare_range_with_value): Same. (vr_values::adjust_range_with_scev): Same. (vrp_valueize): Same. (vrp_valueize_1): Same. (vr_values::get_vr_for_comparison): Same. (vr_values::compare_name_with_value): Same. (vr_values::compare_names): Same. (vr_values::vrp_evaluate_conditional): Same. (find_case_label_ranges): Same. (vr_values::vrp_visit_switch_stmt): Same. (vr_values::extract_range_from_phi_node): Same. (vr_values::simplify_div_or_mod_using_ranges): Same. (vr_values::simplify_bit_ops_using_ranges): Same. (test_for_singularity): Same. (range_fits_type_p): Same. (vr_values::simplify_cond_using_ranges_1): Same. (vr_values::simplify_switch_using_ranges): Same. (vr_values::simplify_float_conversion_using_ranges): Same. (vr_values::two_valued_val_range_p): Same. (vr_values::add_equivalence): Move to value_range::equiv_add. * vr-values.h (vr_values::add_equivalence): Remove. (VR_INITIALIZER): Remove. * tree-vrp.c (value_range::set): New. (value_range::equiv_add): New. (value_range::value_range): New. (value_range::deep_copy): New. (value_range::check): New. (value_range::equal_p): New. (value_range::ignore_equivs_equal_p): New. (value_range::operator==): New. (value_range::operator!=): New. (value_range::symbolic_p): New. (value_range::numeric_p): New. (value_range::set_undefined): New. (value_range::set_varying): New. (value_range::may_contain_p): New. (value_range::equiv_clear): New. (value_range::singleton_p): New. (value_range::intersect): New. (value_range::dump): New. (value_range::set_and_canonicalize): New. (set_value_range): Adjust for value_range API. (set_value_range_to_undefined): Same. (set_value_range_to_varying): Same. (set_and_canonicalize_value_range): Same. (set_value_range_to_nonnull): Same. (set_value_range_to_null): Same. (range_is_null): Same. (range_is_nonnull): Same. (range_int_cst_p): Same. (range_int_cst_singleton_p): Same. (symbolic_range_p): Same. (range_includes_zero_p): Same. (value_range_constant_singleton): Same. (vrp_set_zero_nonzero_bits): Same. (ranges_from_anti_range): Same. (extract_range_into_wide_ints): Same. (extract_range_from_multiplicative_op): Same. (set_value_range_with_overflow): Same. (extract_range_from_binary_expr_1): Same. (extract_range_from_unary_expr): Same. (dump_value_range): Same. (debug_value_range): Same. (vrp_prop::check_array_ref): Same. (vrp_prop::check_mem_ref): Same. (vrp_prop::vrp_initialize): Same. (vrp_prop::visit_stmt): Same. (intersect_ranges): Same. (vrp_prop::visit_phi): Same. (vrp_prop::vrp_finalize): Same. (determine_value_range_1): Same. (determine_value_range): Same. (vrp_intersect_ranges_1): Rename to... (vrp_intersect_1): this. (vrp_intersect_ranges): Rename to... (value_range::intersect_helper): ...this. (vrp_meet_1): Rename to... (value_range::union_helper): ...this. (vrp_meet): Rename to... (value_range::union_): ...this. (copy_value_range): Remove. * tree-vrp.h (struct value_range): Rewrite into a proper class. (value_range::vrtype): New. (value_range::type): New. (value_range::equiv): New. (value_range::min): New. (value_range::max): New. (value_range::varying_p): New. (value_range::undefined_p): New. (value_range::null_p): New. (value_range::equiv_add): New. (copy_value_range): Remove. From-SVN: r265241
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r--gcc/tree-vrp.c1026
1 files changed, 593 insertions, 433 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 0a42da7..d327639 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -73,6 +73,303 @@ 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)
+{
+ m_kind = kind;
+ 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);
+ }
+ if (flag_checking)
+ check ();
+}
+
+value_range::value_range (value_range_kind kind, tree min, tree max,
+ bitmap equiv)
+{
+ m_equiv = NULL;
+ set (kind, min, max, equiv);
+}
+
+/* Like above, but keep the equivalences intact. */
+
+void
+value_range::update (value_range_kind kind, tree min, tree max)
+{
+ set (kind, min, max, m_equiv);
+}
+
+/* Copy value_range in FROM into THIS while avoiding bitmap sharing.
+
+ Note: The code that avoids the bitmap sharing looks at the existing
+ this->m_equiv, so this function cannot be used to initalize an
+ object. Use the constructors for initialization. */
+
+void
+value_range::deep_copy (const value_range *from)
+{
+ set (from->m_kind, from->min (), from->max (), from->m_equiv);
+}
+
+/* Check the validity of the range. */
+
+void
+value_range::check ()
+{
+ switch (m_kind)
+ {
+ case VR_RANGE:
+ case VR_ANTI_RANGE:
+ {
+ int cmp;
+
+ gcc_assert (m_min && m_max);
+
+ gcc_assert (!TREE_OVERFLOW_P (m_min) && !TREE_OVERFLOW_P (m_max));
+
+ /* Creating ~[-MIN, +MAX] is stupid because that would be
+ the empty set. */
+ if (INTEGRAL_TYPE_P (TREE_TYPE (m_min)) && m_kind == 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);
+ break;
+ }
+ case VR_UNDEFINED:
+ case VR_VARYING:
+ gcc_assert (!m_min && !m_max);
+ gcc_assert (!m_equiv || bitmap_empty_p (m_equiv));
+ break;
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* 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)
+ && (ignore_equivs
+ || vrp_bitmap_equal_p (m_equiv, other.m_equiv)));
+}
+
+/* Return equality while ignoring equivalence bitmap. */
+
+bool
+value_range::ignore_equivs_equal_p (const value_range &other) const
+{
+ return equal_p (other, /*ignore_equivs=*/true);
+}
+
+bool
+value_range::operator== (const value_range &other) const
+{
+ return equal_p (other, /*ignore_equivs=*/false);
+}
+
+bool
+value_range::operator!= (const value_range &other) const
+{
+ return !(*this == other);
+}
+
+/* Return TRUE if this is a symbolic range. */
+
+bool
+value_range::symbolic_p () const
+{
+ return (!varying_p ()
+ && !undefined_p ()
+ && (!is_gimple_min_invariant (m_min)
+ || !is_gimple_min_invariant (m_max)));
+}
+
+/* NOTE: This 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
+ constants would be represented as [-MIN, +MAX]. */
+
+bool
+value_range::constant_p () const
+{
+ return (!varying_p ()
+ && !undefined_p ()
+ && TREE_CODE (m_min) == INTEGER_CST
+ && TREE_CODE (m_max) == INTEGER_CST);
+}
+
+void
+value_range::set_undefined ()
+{
+ equiv_clear ();
+ *this = value_range (VR_UNDEFINED, NULL, NULL, NULL);
+}
+
+void
+value_range::set_varying ()
+{
+ equiv_clear ();
+ *this = value_range (VR_VARYING, NULL, NULL, NULL);
+}
+
+/* Return TRUE if it is possible that range contains VAL. */
+
+bool
+value_range::may_contain_p (tree val) const
+{
+ if (varying_p ())
+ return true;
+
+ if (undefined_p ())
+ return true;
+
+ if (m_kind == 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;
+}
+
+void
+value_range::equiv_clear ()
+{
+ if (m_equiv)
+ bitmap_clear (m_equiv);
+}
+
+/* Add VAR and VAR's equivalence set (VAR_VR) to the equivalence
+ bitmap. If no equivalence table has been created, OBSTACK is the
+ obstack to use (NULL for the default obstack).
+
+ This is the central point where equivalence processing can be
+ turned on/off. */
+
+void
+value_range::equiv_add (const_tree var,
+ const value_range *var_vr,
+ bitmap_obstack *obstack)
+{
+ if (!m_equiv)
+ m_equiv = BITMAP_ALLOC (obstack);
+ unsigned ver = SSA_NAME_VERSION (var);
+ bitmap_set_bit (m_equiv, ver);
+ if (var_vr && var_vr->m_equiv)
+ bitmap_ior_into (m_equiv, var_vr->m_equiv);
+}
+
+/* If range is a singleton, place it in RESULT and return TRUE.
+ Note: A singleton can be any gimple invariant, not just constants.
+ So, [&x, &x] counts as a singleton. */
+
+bool
+value_range::singleton_p (tree *result) const
+{
+ if (m_kind == VR_RANGE
+ && vrp_operand_equal_p (m_min, m_max)
+ && is_gimple_min_invariant (m_min))
+ {
+ if (result)
+ *result = m_min;
+ return true;
+ }
+ return false;
+}
+
+tree
+value_range::type () const
+{
+ /* Types are only valid for VR_RANGE and VR_ANTI_RANGE, which are
+ known to have non-zero min/max. */
+ gcc_assert (m_min);
+ return TREE_TYPE (m_min);
+}
+
+/* Dump value range to FILE. */
+
+void
+value_range::dump (FILE *file) const
+{
+ if (undefined_p ())
+ fprintf (file, "UNDEFINED");
+ else if (m_kind == VR_RANGE || m_kind == VR_ANTI_RANGE)
+ {
+ tree type = TREE_TYPE (min ());
+
+ fprintf (file, "%s[", (m_kind == VR_ANTI_RANGE) ? "~" : "");
+
+ if (INTEGRAL_TYPE_P (type)
+ && !TYPE_UNSIGNED (type)
+ && vrp_val_is_min (min ()))
+ fprintf (file, "-INF");
+ else
+ print_generic_expr (file, min ());
+
+ fprintf (file, ", ");
+
+ if (INTEGRAL_TYPE_P (type)
+ && vrp_val_is_max (max ()))
+ fprintf (file, "+INF");
+ else
+ 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");
+ else
+ fprintf (file, "INVALID RANGE");
+}
+
+void
+value_range::dump () const
+{
+ dump_value_range (stderr, this);
+ fprintf (stderr, "\n");
+}
+
/* Return true if the SSA name NAME is live on the edge E. */
static bool
@@ -175,8 +472,8 @@ vrp_val_is_min (const_tree val)
SGN gives the sign of the values described by the range. */
-enum value_range_type
-intersect_range_with_nonzero_bits (enum value_range_type vr_type,
+enum value_range_kind
+intersect_range_with_nonzero_bits (enum value_range_kind vr_type,
wide_int *min, wide_int *max,
const wide_int &nonzero_bits,
signop sgn)
@@ -245,10 +542,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,67 +550,21 @@ 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, enum value_range_kind kind,
+ 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);
- }
+ *vr = value_range (kind, min, max, equiv);
}
-/* 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
+/* Set value range to the canonical form of {VRTYPE, MIN, MAX, EQUIV}.
+ This means adjusting VRTYPE, 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
@@ -325,18 +573,18 @@ set_value_range (value_range *vr, enum value_range_type t, tree min,
extract ranges from var + CST op limit. */
void
-set_and_canonicalize_value_range (value_range *vr, enum value_range_type t,
- tree min, tree max, bitmap equiv)
+value_range::set_and_canonicalize (enum value_range_kind kind,
+ tree min, tree max, bitmap equiv)
{
/* Use the canonical setters for VR_UNDEFINED and VR_VARYING. */
- if (t == VR_UNDEFINED)
+ if (kind == VR_UNDEFINED)
{
- set_value_range_to_undefined (vr);
+ set_undefined ();
return;
}
- else if (t == VR_VARYING)
+ else if (kind == VR_VARYING)
{
- set_value_range_to_varying (vr);
+ set_varying ();
return;
}
@@ -344,7 +592,7 @@ set_and_canonicalize_value_range (value_range *vr, enum value_range_type t,
if (TREE_CODE (min) != INTEGER_CST
|| TREE_CODE (max) != INTEGER_CST)
{
- set_value_range (vr, t, min, max, equiv);
+ set_value_range (this, kind, min, max, equiv);
return;
}
@@ -359,7 +607,7 @@ set_and_canonicalize_value_range (value_range *vr, enum value_range_type t,
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);
+ set_varying ();
return;
}
@@ -373,15 +621,15 @@ set_and_canonicalize_value_range (value_range *vr, enum value_range_type t,
to varying in this case. */
if (tree_int_cst_lt (max, min))
{
- set_value_range_to_varying (vr);
+ set_varying ();
return;
}
- t = t == VR_RANGE ? VR_ANTI_RANGE : VR_RANGE;
+ kind = kind == VR_RANGE ? VR_ANTI_RANGE : VR_RANGE;
}
/* Anti-ranges that can be represented as ranges should be so. */
- if (t == VR_ANTI_RANGE)
+ if (kind == 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. */
@@ -395,7 +643,7 @@ set_and_canonicalize_value_range (value_range *vr, enum value_range_type t,
{
/* We cannot deal with empty ranges, drop to varying.
??? This could be VR_UNDEFINED instead. */
- set_value_range_to_varying (vr);
+ set_varying ();
return;
}
else if (TYPE_PRECISION (TREE_TYPE (min)) == 1
@@ -407,7 +655,7 @@ set_and_canonicalize_value_range (value_range *vr, enum value_range_type t,
min = max = vrp_val_max (TREE_TYPE (min));
else
min = max = vrp_val_min (TREE_TYPE (min));
- t = VR_RANGE;
+ kind = VR_RANGE;
}
else if (is_min
/* As a special exception preserve non-null ranges. */
@@ -417,14 +665,14 @@ set_and_canonicalize_value_range (value_range *vr, enum value_range_type t,
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;
+ kind = 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;
+ kind = VR_RANGE;
}
}
@@ -432,15 +680,7 @@ set_and_canonicalize_value_range (value_range *vr, enum value_range_type t,
to make sure VRP iteration terminates, otherwise we can get into
oscillations. */
- set_value_range (vr, t, min, max, equiv);
-}
-
-/* Copy value range FROM into value range TO. */
-
-void
-copy_value_range (value_range *to, const value_range *from)
-{
- set_value_range (to, from->type, from->min, from->max, from->equiv);
+ set_value_range (this, kind, min, max, equiv);
}
/* Set value range VR to a single value. This function is only called
@@ -462,7 +702,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);
+ vr->update (VR_ANTI_RANGE, zero, zero);
}
@@ -471,7 +711,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 +743,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->kind () == 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 +760,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->kind () == 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 +771,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,34 +1086,25 @@ 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)
+ if (vr->varying_p () || vr->undefined_p ())
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 (vr->type (), 0);
+ return vr->may_contain_p (zero);
}
-/* If *VR has a value rante that is a single constant value return that,
- otherwise return NULL_TREE. */
+/* If *VR has a value range that is a single constant value return that,
+ otherwise return NULL_TREE.
+
+ ?? This actually returns TRUE for [&x, &x], so perhaps "constant"
+ is not the best name. */
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;
+ tree result = NULL;
+ if (vr->singleton_p (&result))
+ return result;
+ return NULL;
}
/* Value range wrapper for wide_int_range_set_zero_nonzero_bits.
@@ -899,8 +1127,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 +1142,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 = 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->kind () != 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 (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 (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 +1185,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->kind () != VR_ANTI_RANGE || vr->symbolic_p ());
+ 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 +1216,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->kind () == VR_RANGE
+ && vr0->kind () == vr1->kind ());
- 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);
unsigned prec = TYPE_PRECISION (type);
@@ -1009,9 +1232,9 @@ extract_range_from_multiplicative_op (value_range *vr,
code, TYPE_SIGN (type), prec,
vr0_lb, vr0_ub, vr1_lb, vr1_ub,
overflow_undefined))
- set_and_canonicalize_value_range (vr, VR_RANGE,
- wide_int_to_tree (type, res_lb),
- wide_int_to_tree (type, res_ub), NULL);
+ vr->set_and_canonicalize (VR_RANGE,
+ wide_int_to_tree (type, res_lb),
+ wide_int_to_tree (type, res_ub), NULL);
else
set_value_range_to_varying (vr);
}
@@ -1113,8 +1336,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;
/* For one bit precision if max < min, then the swapped
range covers all values. */
@@ -1132,10 +1353,18 @@ set_value_range_with_overflow (value_range &vr,
wide_int tmax = wide_int::from (wmax, prec, sgn);
if ((min_ovf != wi::OVF_NONE) == (max_ovf != wi::OVF_NONE))
{
- /* 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);
+ /* If the limits are swapped, we wrapped around and cover
+ the entire range. We have a similar check at the end of
+ extract_range_from_binary_expr_1. */
+ if (wi::gt_p (tmin, tmax, sgn))
+ vr.set_varying ();
+ else
+ /* No overflow or both overflow or underflow. The
+ range kind stays VR_RANGE. */
+ vr = value_range (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))
@@ -1144,7 +1373,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;
@@ -1159,8 +1387,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 (VR_ANTI_RANGE,
+ wide_int_to_tree (type, tmin),
+ wide_int_to_tree (type, tmax));
+ return;
}
else
{
@@ -1175,19 +1405,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 (VR_RANGE, min, max);
}
}
@@ -1204,8 +1436,8 @@ 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;
- enum value_range_type type;
+ value_range vrtem0, vrtem1;
+ enum value_range_kind type;
tree min = NULL_TREE, max = NULL_TREE;
int cmp;
@@ -1241,7 +1473,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;
@@ -1250,19 +1482,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
+ range, but then we also need to hack up vrp_union. 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;
@@ -1270,36 +1499,35 @@ 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.kind () == 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_);
- vrp_meet (vr, &vrres);
+ value_range vrres;
+ extract_range_from_binary_expr_1 (&vrres, code, expr_type, &vrtem1, vr1_);
+ vr->union_ (&vrres);
}
return;
}
/* Likewise for X op ~[]. */
- if (vr1.type == VR_ANTI_RANGE
+ if (vr1.kind () == 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;
extract_range_from_binary_expr_1 (&vrres, code, expr_type,
vr0_, &vrtem1);
- vrp_meet (vr, &vrres);
+ vr->union_ (&vrres);
}
return;
}
/* The type of the resulting value range defaults to VR0.TYPE. */
- type = vr0.type;
+ type = vr0.kind ();
/* Refuse to operate on VARYING ranges, ranges of different kinds
and symbolic ranges. As an exception, we allow BIT_{AND,IOR}
@@ -1322,11 +1550,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.kind () != vr1.kind ()
+ || vr0.symbolic_p ()
+ || vr1.symbolic_p ()))
{
set_value_range_to_varying (vr);
return;
@@ -1384,24 +1612,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.update (VR_RANGE,
+ vrp_val_min (expr_type),
+ vrp_val_max (expr_type));
+ if (vr1.varying_p ())
+ vr1.update (VR_RANGE,
+ vrp_val_min (expr_type),
+ vrp_val_max (expr_type));
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;
@@ -1414,7 +1638,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.kind () == VR_RANGE && vr1.kind () == VR_RANGE
&& (TREE_CODE (min_op0) == INTEGER_CST
|| (sym_min_op0
= get_single_symbol (min_op0, &neg_min_op0, &min_op0)))
@@ -1454,21 +1678,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->kind ();
}
else
{
@@ -1498,9 +1720,8 @@ extract_range_from_binary_expr_1 (value_range *vr,
extract_range_into_wide_ints (&vr1, sign, prec, vr1_min, vr1_max);
if (wide_int_range_min_max (wmin, wmax, code, sign, prec,
vr0_min, vr0_max, vr1_min, vr1_max))
- set_value_range (vr, VR_RANGE,
- wide_int_to_tree (expr_type, wmin),
- wide_int_to_tree (expr_type, wmax), NULL);
+ vr->update (VR_RANGE, wide_int_to_tree (expr_type, wmin),
+ wide_int_to_tree (expr_type, wmax));
else
set_value_range_to_varying (vr);
return;
@@ -1520,22 +1741,21 @@ extract_range_from_binary_expr_1 (value_range *vr,
|| code == LSHIFT_EXPR)
{
if (range_int_cst_p (&vr1)
- && !wide_int_range_shift_undefined_p (TYPE_SIGN (TREE_TYPE (vr1.min)),
- prec,
- wi::to_wide (vr1.min),
- wi::to_wide (vr1.max)))
+ && !wide_int_range_shift_undefined_p
+ (TYPE_SIGN (TREE_TYPE (vr1.min ())),
+ prec,
+ 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))
- {
- vr0.type = type = VR_RANGE;
- vr0.min = vrp_val_min (expr_type);
- vr0.max = vrp_val_max (expr_type);
- }
+ if (vr0.kind () != VR_RANGE || vr0.symbolic_p ())
+ vr0.update (VR_RANGE,
+ vrp_val_min (expr_type),
+ vrp_val_max (expr_type));
extract_range_from_multiplicative_op (vr, code, &vr0, &vr1);
return;
}
@@ -1544,16 +1764,15 @@ 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)))
{
min = wide_int_to_tree (expr_type, res_lb);
max = wide_int_to_tree (expr_type, res_ub);
- set_and_canonicalize_value_range (vr, VR_RANGE,
- min, max, NULL);
+ vr->set_and_canonicalize (VR_RANGE, min, max, NULL);
return;
}
}
@@ -1603,11 +1822,11 @@ 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;
set_value_range (&extra_range, VR_RANGE,
wide_int_to_tree (expr_type, extra_min),
wide_int_to_tree (expr_type, extra_max), NULL);
- vrp_meet (vr, &extra_range);
+ vr->union_ (&extra_range);
}
return;
}
@@ -1740,7 +1959,8 @@ 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, vrtem1;
/* VRP only operates on integral and pointer types. */
if (!(INTEGRAL_TYPE_P (op0_type)
@@ -1753,7 +1973,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,14 +1983,14 @@ extract_range_from_unary_expr (value_range *vr,
if (code == PAREN_EXPR || code == OBJ_TYPE_REF)
{
/* PAREN_EXPR and OBJ_TYPE_REF are simple copies. */
- copy_value_range (vr, &vr0);
+ vr->deep_copy (&vr0);
return;
}
else if (code == NEGATE_EXPR)
{
/* -X is simply 0 - X, so re-use existing code that also handles
anti-ranges fine. */
- value_range zero = VR_INITIALIZER;
+ value_range zero;
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;
@@ -1779,7 +1999,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;
set_value_range_to_value (&minusone, build_int_cst (type, -1), NULL);
extract_range_from_binary_expr_1 (vr, MINUS_EXPR,
type, &minusone, &vr0);
@@ -1788,16 +2008,16 @@ 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.kind () == 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;
extract_range_from_unary_expr (&vrres, code, type,
&vrtem1, op0_type);
- vrp_meet (vr, &vrres);
+ vr->union_ (&vrres);
}
return;
}
@@ -1829,8 +2049,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.kind () != 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
@@ -1853,7 +2073,7 @@ extract_range_from_unary_expr (value_range *vr,
{
tree min = wide_int_to_tree (outer_type, wmin);
tree max = wide_int_to_tree (outer_type, wmax);
- set_and_canonicalize_value_range (vr, VR_RANGE, min, max, NULL);
+ vr->set_and_canonicalize (VR_RANGE, min, max, NULL);
}
else
set_value_range_to_varying (vr);
@@ -1887,76 +2107,21 @@ void dump_all_value_ranges (FILE *);
void dump_vr_equiv (FILE *, bitmap);
void debug_vr_equiv (bitmap);
-
-/* Dump value range VR to FILE. */
-
void
dump_value_range (FILE *file, const value_range *vr)
{
- if (vr == NULL)
+ if (!vr)
fprintf (file, "[]");
- else if (vr->type == VR_UNDEFINED)
- fprintf (file, "UNDEFINED");
- else if (vr->type == VR_RANGE || vr->type == VR_ANTI_RANGE)
- {
- tree type = TREE_TYPE (vr->min);
-
- fprintf (file, "%s[", (vr->type == VR_ANTI_RANGE) ? "~" : "");
-
- if (INTEGRAL_TYPE_P (type)
- && !TYPE_UNSIGNED (type)
- && vrp_val_is_min (vr->min))
- fprintf (file, "-INF");
- else
- print_generic_expr (file, vr->min);
-
- fprintf (file, ", ");
-
- if (INTEGRAL_TYPE_P (type)
- && vrp_val_is_max (vr->max))
- fprintf (file, "+INF");
- else
- print_generic_expr (file, vr->max);
-
- fprintf (file, "]");
-
- if (vr->equiv)
- {
- bitmap_iterator bi;
- unsigned i, c = 0;
-
- fprintf (file, " EQUIVALENCES: { ");
-
- EXECUTE_IF_SET_IN_BITMAP (vr->equiv, 0, i, bi)
- {
- print_generic_expr (file, ssa_name (i));
- fprintf (file, " ");
- c++;
- }
-
- fprintf (file, "} (%u elements)", c);
- }
- }
- else if (vr->type == VR_VARYING)
- fprintf (file, "VARYING");
else
- fprintf (file, "INVALID RANGE");
+ vr->dump (file);
}
-
/* Dump value range VR to stderr. */
DEBUG_FUNCTION void
debug_value_range (const value_range *vr)
{
- dump_value_range (stderr, vr);
- fprintf (stderr, "\n");
-}
-
-void
-value_range::dump () const
-{
- debug_value_range (this);
+ vr->dump ();
}
@@ -4200,14 +4365,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->kind () == VR_RANGE ? vr->max () : vr->min ();
+ up_sub = vr->kind () == VR_RANGE ? vr->min () : vr->max ();
}
}
- if (vr && vr->type == VR_ANTI_RANGE)
+ if (vr && vr->kind () == VR_ANTI_RANGE)
{
if (up_bound
&& TREE_CODE (up_sub) == INTEGER_CST
@@ -4335,21 +4500,20 @@ 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)
+ if (!vr || vr->undefined_p () || vr->varying_p ())
break;
- if (TREE_CODE (vr->min) != INTEGER_CST
- || TREE_CODE (vr->max) != INTEGER_CST)
+ if (!vr->constant_p ())
break;
- if (vr->type == VR_RANGE)
+ if (vr->kind () == 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;
@@ -5121,8 +5285,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;
extract_range_from_stmt (stmt, taken_edge_p, output_p, &vr);
if (*output_p)
@@ -5138,7 +5302,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;
@@ -5191,17 +5355,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;
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_clear ();
if (res == SSA_PROP_INTERESTING)
{
*output_p = lhs;
@@ -5229,9 +5390,9 @@ vrp_prop::visit_stmt (gimple *stmt, edge *taken_edge_p, tree *output_p)
possible such range. The resulting range is not canonicalized. */
static void
-union_ranges (enum value_range_type *vr0type,
+union_ranges (enum value_range_kind *vr0type,
tree *vr0min, tree *vr0max,
- enum value_range_type vr1type,
+ enum value_range_kind vr1type,
tree vr1min, tree vr1max)
{
bool mineq = vrp_operand_equal_p (*vr0min, vr1min);
@@ -5500,9 +5661,9 @@ give_up:
possible such range. The resulting range is not canonicalized. */
static void
-intersect_ranges (enum value_range_type *vr0type,
+intersect_ranges (enum value_range_kind *vr0type,
tree *vr0min, tree *vr0max,
- enum value_range_type vr1type,
+ enum value_range_kind vr1type,
tree vr1min, tree vr1max)
{
bool mineq = vrp_operand_equal_p (*vr0min, vr1min);
@@ -5812,33 +5973,29 @@ intersect_ranges (enum value_range_type *vr0type,
*vr0min = vr1min;
*vr0max = vr1max;
}
-
- return;
}
/* Intersect the two value-ranges *VR0 and *VR1 and store the result
in *VR0. This may not be the smallest possible such range. */
-static void
-vrp_intersect_ranges_1 (value_range *vr0, const value_range *vr1)
+void
+value_range::intersect_helper (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);
+ vr0->deep_copy (vr1);
return;
}
/* 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;
@@ -5846,53 +6003,56 @@ 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_kind vr0type = vr0->kind ();
+ tree vr0min = vr0->min ();
+ tree vr0max = vr0->max ();
+ intersect_ranges (&vr0type, &vr0min, &vr0max,
+ vr1->kind (), vr1->min (), vr1->max ());
/* 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->set_and_canonicalize (vr0type, vr0min, vr0max, vr0->m_equiv);
/* 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->m_equiv && vr1->m_equiv && vr0->m_equiv != vr1->m_equiv)
+ bitmap_ior_into (vr0->m_equiv, vr1->m_equiv);
+ else if (vr1->m_equiv && !vr0->m_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->m_equiv = BITMAP_ALLOC (vr1->m_equiv->obstack);
+ bitmap_copy (m_equiv, vr1->m_equiv);
}
}
void
-vrp_intersect_ranges (value_range *vr0, const value_range *vr1)
+value_range::intersect (const value_range *other)
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Intersecting\n ");
- dump_value_range (dump_file, vr0);
+ dump_value_range (dump_file, this);
fprintf (dump_file, "\nand\n ");
- dump_value_range (dump_file, vr1);
+ dump_value_range (dump_file, other);
fprintf (dump_file, "\n");
}
- vrp_intersect_ranges_1 (vr0, vr1);
+ intersect_helper (this, other);
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "to\n ");
- dump_value_range (dump_file, vr0);
+ dump_value_range (dump_file, this);
fprintf (dump_file, "\n");
}
}
@@ -5901,39 +6061,41 @@ vrp_intersect_ranges (value_range *vr0, const value_range *vr1)
VR1, store in VR0 a range that contains both VR0 and VR1. This
may not be the smallest possible such range. */
-static void
-vrp_meet_1 (value_range *vr0, const value_range *vr1)
+void
+value_range::union_helper (value_range *vr0, const value_range *vr1)
{
- value_range saved;
-
- if (vr0->type == VR_UNDEFINED)
+ if (vr1->undefined_p ())
{
- set_value_range (vr0, vr1->type, vr1->min, vr1->max, vr1->equiv);
+ /* VR0 already has the resulting range. */
return;
}
- if (vr1->type == VR_UNDEFINED)
+ if (vr0->undefined_p ())
{
- /* VR0 already has the resulting range. */
+ vr0->deep_copy (vr1);
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_kind vr0type = vr0->kind ();
+ tree vr0min = vr0->min ();
+ tree vr0max = vr0->max ();
+ union_ranges (&vr0type, &vr0min, &vr0max,
+ vr1->kind (), vr1->min (), vr1->max ());
+ *vr0 = value_range (vr0type, vr0min, vr0max);
+ 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
@@ -5941,52 +6103,51 @@ 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);
+ if (vr0->m_equiv)
+ bitmap_clear (vr0->m_equiv);
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->set_and_canonicalize (vr0->kind (), vr0->min (), vr0->max (),
+ vr0->equiv ());
+ 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->m_equiv && vr1->m_equiv && vr0->m_equiv != vr1->m_equiv)
+ bitmap_and_into (vr0->m_equiv, vr1->m_equiv);
+ else if (vr0->m_equiv && !vr1->m_equiv)
+ bitmap_clear (vr0->m_equiv);
}
void
-vrp_meet (value_range *vr0, const value_range *vr1)
+value_range::union_ (const value_range *other)
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Meeting\n ");
- dump_value_range (dump_file, vr0);
+ dump_value_range (dump_file, this);
fprintf (dump_file, "\nand\n ");
- dump_value_range (dump_file, vr1);
+ dump_value_range (dump_file, other);
fprintf (dump_file, "\n");
}
- vrp_meet_1 (vr0, vr1);
+ union_helper (this, other);
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "to\n ");
- dump_value_range (dump_file, vr0);
+ dump_value_range (dump_file, this);
fprintf (dump_file, "\n");
}
}
-
/* Visit all arguments for PHI node PHI that flow through executable
edges. If a valid value range can be derived from all the incoming
value ranges, set a new range for the LHS of PHI. */
@@ -5995,7 +6156,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;
extract_range_from_phi_node (phi, &vr_result);
if (update_value_range (lhs, &vr_result))
{
@@ -6008,7 +6169,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;
@@ -6192,16 +6353,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->kind () == 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)
@@ -6211,10 +6373,11 @@ 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)))
+ ? (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;
}
@@ -6224,7 +6387,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->kind () == VR_ANTI_RANGE)
{
unsigned n = gimple_switch_num_labels (switch_stmt);
tree min_label = gimple_switch_label (switch_stmt, 1);
@@ -6233,10 +6396,12 @@ 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
+ 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);
}
@@ -6253,11 +6418,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;
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;
+ if (new_vr.singleton_p (&singleton))
+ return singleton;
}
}
@@ -6429,20 +6595,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->constant_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->kind (),
+ wi::to_wide (vr->min ()),
+ wi::to_wide (vr->max ()));
}
/* If we're checking array refs, we want to merge information on
@@ -6634,7 +6796,7 @@ 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, vr1;
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),
@@ -6642,7 +6804,7 @@ determine_value_range_1 (value_range *vr, tree expr)
}
else if (UNARY_CLASS_P (expr))
{
- value_range vr0 = VR_INITIALIZER;
+ value_range vr0;
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)));
@@ -6651,7 +6813,7 @@ determine_value_range_1 (value_range *vr, tree expr)
set_value_range_to_value (vr, expr, NULL);
else
{
- value_range_type kind;
+ value_range_kind kind;
wide_int min, max;
/* For SSA names try to extract range info computed by VRP. Otherwise
fall back to varying. */
@@ -6668,18 +6830,16 @@ determine_value_range_1 (value_range *vr, tree expr)
/* Compute a value-range for EXPR and set it in *MIN and *MAX. Return
the determined range type. */
-value_range_type
+value_range_kind
determine_value_range (tree expr, wide_int *min, wide_int *max)
{
- value_range vr = VR_INITIALIZER;
+ value_range vr;
determine_value_range_1 (&vr, expr);
- if ((vr.type == VR_RANGE
- || vr.type == VR_ANTI_RANGE)
- && !symbolic_range_p (&vr))
+ if (vr.constant_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.kind ();
}
return VR_VARYING;