On 7/4/19 6:33 AM, Richard Biener wrote:
On Wed, Jul 3, 2019 at 2:17 PM Aldy Hernandez <al...@redhat.com> wrote:
On 7/3/19 7:08 AM, Richard Biener wrote:
On Wed, Jul 3, 2019 at 11:19 AM Aldy Hernandez <al...@redhat.com> wrote:
How about we keep VARYING and UNDEFINED typeless until right before we
call into the ranger. At which point, we have can populate min/max
because we have the tree_code and the type handy. So right before we
call into the ranger do:
if (varying_p ())
foo->set_varying(TYPE);
This would avoid the type cache, and keep the ranger happy.
you cannot do set_varying on the static const range but instead you'd do
value_range tem (*foo);
if (varying_p ())
tem->set_full_range (TYPE);
which I think we already do in some places. Thus my question _where_
you actually need this.
Basically, everywhere. By having a type for varying/undefined, we don't
have to special case anything. Sure, we could for example, special case
the invert operation for undefined / varying. And we could special case
everything dealing with ranges to handle varying and undefined, but why?
We could also pass a type argument everywhere, but that's just ugly.
However, I do understand your objection to the type cache.
How about the attached approach? Set the type for varying/undefined
when we know it, while avoiding touching the CONST varying. Then right
before calling the ranger, pass down a new varying node with min/max for
any varyings that were still typeless until that point.
I have taken care of never adding a set_varying() that was not already
there. Would this keep the const happy?
Technically we don't need to set varying/undef types for every instance
in VRP, but we need it at least for the code that will be shared with
range-ops (extract_range_from_multiplicative_op, union, intersect, etc).
I just figured if we have the information, might as well set it for
consistency.
If you like this approach, I can rebase the other patches that depend on
this one.
Aldy
commit 9ad503e1d6a2edd8b74b1d8cc9a8d9d4ee31386e
Author: Aldy Hernandez <al...@redhat.com>
Date: Mon Jul 8 12:45:40 2019 +0200
Allow min/max in VR_VARYING and VR_UNDEFINED ranges.
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b0d78ee6871..2cb308bb568 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,62 @@
+2019-07-01 Aldy Hernandez <al...@redhat.com>
+
+ * gimple-ssa-evrp-analyze.c (record_ranges_from_phis): Skip PHIs
+ who's result are not valid for a value_range.
+ Set type for varying value_range.
+ * tree-ssa-threadedge.c (record_temporary_equivalences_from_phis):
+ Same.
+ * tree-ssanames.c (get_range_info): Same.
+ * tree-vrp.c (value_range_base::value_range_base): New constructor.
+ (value_range_base::check): Remove assert for empty min/max.
+ (value_range_base::equal_p): Allow comparison of typeless undefs.
+ (value_range_base::set_undefined): Add type.
+ (value_range::set_undefined): Same.
+ (value_range_base::set_varying): Same.
+ (value_range::set_varying): Same.
+ (value_range_base::type): Remove assert.
+ (value_range_base::dump): Display type for varying/undef.
+ (value_range_base::dump): Add argument-less overload.
+ (value_range::dump): Same.
+ (vrp_val_max): Add handle_pointers argument.
+ (vrp_val_min): Same.
+ (vrp_val_is_max): Same.
+ (vrp_val_is_min): Same.
+ (value_range_base::set_and_canonicalize): Adjust so type is
+ allowed for varying/undef.
+ (ranges_from_anti_range): Same.
+ (extract_range_from_muliplicative_op): Same.
+ (extract_range_from_binary_expr): Same.
+ (extract_range_from_unary_expr): Same.
+ (vrp_prop::vrp_initialize): Same.
+ (vrp_prop::visit_stmt): Same.
+ (value_range_base::union_helper): Same.
+ (value_range_base::normalize_symbolics): Same.
+ (determine_value_range_1): Same.
+ * tree-vrp.h (value_range_base): Add value_range_base(tree type)
+ constructor.
+ Add dump (), supports_type_p,
+ value_range_base_normalize_symbolics, set_varying, and
+ set_undefined.
+ (value_range): Add set_varying, set_undefined, and dump().
+ (vrp_val_is_min): Add argument.
+ (vrp_val_is_max): Same.
+ (vrp_val_min): Same.
+ (vrp_val_max): Same.
+ (range_includes_zero_p): Adjust for varying/undef with types.
+ * vr-values.c (set_value_range_to_truthvalue): Adjust for
+ varying/undef with types.
+ (get_value_range): Same.
+ (vr_values::set_defs_to_varying): Same.
+ (vr_values::update_value_range): Same.
+ (extract_range_for_var_from_comparison_expr): Same.
+ (extract_range_from_binary_expr): Same.
+ (extract_range_from_cond_expr): Same.
+ (check_for_binary_op_overflow): Same.
+ (extract_range_basic): Same.
+ (extract_range_from_assignment): Same.
+ (extract_range_from_phi_node): Adjust for varying/undef with
+ types.
+
2019-07-01 Aldy Hernandez <al...@redhat.com>
* tree-vrp.c (intersect_ranges): If we know the intersection is
diff --git a/gcc/gimple-ssa-evrp-analyze.c b/gcc/gimple-ssa-evrp-analyze.c
index 4c68af847e1..467ca57061f 100644
--- a/gcc/gimple-ssa-evrp-analyze.c
+++ b/gcc/gimple-ssa-evrp-analyze.c
@@ -251,6 +251,11 @@ evrp_range_analyzer::record_ranges_from_phis (basic_block bb)
if (virtual_operand_p (lhs))
continue;
+ /* Skips floats and other things we can't represent in a
+ range. */
+ if (!value_range_base::supports_type_p (TREE_TYPE (lhs)))
+ continue;
+
value_range vr_result;
bool interesting = stmt_interesting_for_vrp (phi);
if (!has_unvisited_preds && interesting)
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index 785227df690..781f802f365 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -183,7 +183,7 @@ record_temporary_equivalences_from_phis (edge e,
else if (TREE_CODE (src) == INTEGER_CST)
new_vr->set (src);
else
- new_vr->set_varying ();
+ new_vr->set_varying (TREE_TYPE (src));
/* This is a temporary range for DST, so push it. */
evrp_range_analyzer->push_value_range (dst, new_vr);
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 8b80bce8945..343e98488a9 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -440,14 +440,16 @@ get_range_info (const_tree name, value_range_base &vr)
wide_int wmin, wmax;
enum value_range_kind kind = get_range_info (name, &wmin, &wmax);
- if (kind == VR_VARYING || kind == VR_UNDEFINED)
- min = max = NULL;
+ if (kind == VR_VARYING)
+ vr.set_varying (TREE_TYPE (name));
+ else if (kind == VR_UNDEFINED)
+ vr.set_undefined (TREE_TYPE (name));
else
{
min = wide_int_to_tree (TREE_TYPE (name), wmin);
max = wide_int_to_tree (TREE_TYPE (name), wmax);
+ vr.set (kind, min, max);
}
- vr.set (kind, min, max);
return kind;
}
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 594ee9adc17..c5a18686909 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -134,6 +134,11 @@ value_range::value_range (const value_range_base &other)
set (other.kind (), other.min(), other.max (), NULL);
}
+value_range_base::value_range_base (tree type)
+{
+ set_varying (type);
+}
+
/* Like set, but keep the equivalences in place. */
void
@@ -190,7 +195,6 @@ value_range_base::check ()
}
case VR_UNDEFINED:
case VR_VARYING:
- gcc_assert (!min () && !max ());
break;
default:
gcc_unreachable ();
@@ -217,6 +221,10 @@ value_range::check ()
bool
value_range_base::equal_p (const value_range_base &other) const
{
+ /* Ignore types for undefined. All undefines are equal. */
+ if (undefined_p ())
+ return m_kind == other.m_kind;
+
return (m_kind == other.m_kind
&& vrp_operand_equal_p (m_min, other.m_min)
&& vrp_operand_equal_p (m_max, other.m_max));
@@ -259,27 +267,43 @@ value_range_base::constant_p () const
}
void
-value_range_base::set_undefined ()
+value_range_base::set_undefined (tree type)
{
- set (VR_UNDEFINED, NULL, NULL);
+ m_kind = VR_UNDEFINED;
+ if (type)
+ {
+ m_min = vrp_val_min (type, true);
+ m_max = vrp_val_max (type, true);
+ }
+ else
+ m_min = m_max = NULL;
}
void
-value_range::set_undefined ()
+value_range::set_undefined (tree type)
{
- set (VR_UNDEFINED, NULL, NULL, NULL);
+ value_range_base::set_undefined (type);
+ equiv_clear ();
}
void
-value_range_base::set_varying ()
+value_range_base::set_varying (tree type)
{
- set (VR_VARYING, NULL, NULL);
+ m_kind = VR_VARYING;
+ if (type)
+ {
+ m_min = vrp_val_min (type, true);
+ m_max = vrp_val_max (type, true);
+ }
+ else
+ m_min = m_max = NULL;
}
void
-value_range::set_varying ()
+value_range::set_varying (tree type)
{
- set (VR_VARYING, NULL, NULL, NULL);
+ value_range_base::set_varying (type);
+ equiv_clear ();
}
/* Return TRUE if it is possible that range contains VAL. */
@@ -338,21 +362,29 @@ value_range_base::singleton_p (tree *result) const
tree
value_range_base::type () const
{
- /* Types are only valid for VR_RANGE and VR_ANTI_RANGE, which are
- known to have non-zero min/max. */
- gcc_assert (min ());
return TREE_TYPE (min ());
}
void
value_range_base::dump (FILE *file) const
{
+ tree ttype;
+ if (m_min)
+ ttype = TREE_TYPE (m_min);
+ else
+ ttype = NULL;
+
if (undefined_p ())
- fprintf (file, "UNDEFINED");
+ {
+ if (ttype)
+ {
+ print_generic_expr (file, ttype);
+ fprintf (file, " ");
+ }
+ fprintf (file, "UNDEFINED");
+ }
else if (m_kind == VR_RANGE || m_kind == VR_ANTI_RANGE)
{
- tree ttype = type ();
-
print_generic_expr (file, ttype);
fprintf (file, " ");
@@ -378,11 +410,24 @@ value_range_base::dump (FILE *file) const
fprintf (file, "]");
}
else if (varying_p ())
- fprintf (file, "VARYING");
+ {
+ if (ttype)
+ {
+ print_generic_expr (file, ttype);
+ fprintf (file, " ");
+ }
+ fprintf (file, "VARYING");
+ }
else
gcc_unreachable ();
}
+void
+value_range_base::dump () const
+{
+ dump (stderr);
+}
+
void
value_range::dump (FILE *file) const
{
@@ -406,6 +451,12 @@ value_range::dump (FILE *file) const
}
}
+void
+value_range::dump () const
+{
+ dump (stderr);
+}
+
void
dump_value_range (FILE *file, const value_range *vr)
{
@@ -499,10 +550,18 @@ static assert_locus **asserts_for;
/* Return the maximum value for TYPE. */
tree
-vrp_val_max (const_tree type)
+vrp_val_max (const_tree type, bool handle_pointers)
{
if (!INTEGRAL_TYPE_P (type))
- return NULL_TREE;
+ {
+ if (POINTER_TYPE_P (type) && handle_pointers)
+ {
+ wide_int max = wi::max_value (TYPE_PRECISION (type),
+ TYPE_SIGN (type));
+ return wide_int_to_tree (const_cast<tree> (type), max);
+ }
+ return NULL_TREE;
+ }
return TYPE_MAX_VALUE (type);
}
@@ -510,23 +569,22 @@ vrp_val_max (const_tree type)
/* Return the minimum value for TYPE. */
tree
-vrp_val_min (const_tree type)
+vrp_val_min (const_tree type, bool handle_pointers)
{
if (!INTEGRAL_TYPE_P (type))
- return NULL_TREE;
+ {
+ if (POINTER_TYPE_P (type) && handle_pointers)
+ return build_zero_cst (const_cast<tree> (type));
+ return NULL_TREE;
+ }
return TYPE_MIN_VALUE (type);
}
-/* Return whether VAL is equal to the maximum value of its type.
- We can't do a simple equality comparison with TYPE_MAX_VALUE because
- C typedefs and Ada subtypes can produce types whose TYPE_MAX_VALUE
- is not == to the integer constant with the same value in the type. */
-
bool
-vrp_val_is_max (const_tree val)
+vrp_val_is_max (const_tree val, bool handle_pointers)
{
- tree type_max = vrp_val_max (TREE_TYPE (val));
+ tree type_max = vrp_val_max (TREE_TYPE (val), handle_pointers);
return (val == type_max
|| (type_max != NULL_TREE
&& operand_equal_p (val, type_max, 0)));
@@ -535,9 +593,9 @@ vrp_val_is_max (const_tree val)
/* Return whether VAL is equal to the minimum value of its type. */
bool
-vrp_val_is_min (const_tree val)
+vrp_val_is_min (const_tree val, bool handle_pointers)
{
- tree type_min = vrp_val_min (TREE_TYPE (val));
+ tree type_min = vrp_val_min (TREE_TYPE (val), handle_pointers);
return (val == type_min
|| (type_min != NULL_TREE
&& operand_equal_p (val, type_min, 0)));
@@ -629,15 +687,20 @@ void
value_range_base::set_and_canonicalize (enum value_range_kind kind,
tree min, tree max)
{
- /* Use the canonical setters for VR_UNDEFINED and VR_VARYING. */
if (kind == VR_UNDEFINED)
{
- set_undefined ();
+ if (min)
+ set_undefined (TREE_TYPE (min));
+ else
+ set_undefined ();
return;
}
else if (kind == VR_VARYING)
{
- set_varying ();
+ if (min)
+ set_varying (TREE_TYPE (min));
+ else
+ set_varying ();
return;
}
@@ -660,7 +723,7 @@ value_range_base::set_and_canonicalize (enum value_range_kind kind,
for VR_ANTI_RANGE empty range, so drop to varying as well. */
if (TYPE_PRECISION (TREE_TYPE (min)) == 1)
{
- set_varying ();
+ set_varying (TREE_TYPE (min));
return;
}
@@ -674,7 +737,7 @@ value_range_base::set_and_canonicalize (enum value_range_kind kind,
to varying in this case. */
if (tree_int_cst_lt (max, min))
{
- set_varying ();
+ set_varying (TREE_TYPE (min));
return;
}
@@ -696,7 +759,7 @@ value_range_base::set_and_canonicalize (enum value_range_kind kind,
{
/* We cannot deal with empty ranges, drop to varying.
??? This could be VR_UNDEFINED instead. */
- set_varying ();
+ set_varying (type);
return;
}
else if (TYPE_PRECISION (TREE_TYPE (min)) == 1
@@ -1178,8 +1241,8 @@ ranges_from_anti_range (const value_range_base *ar,
{
tree type = ar->type ();
- vr0->set_undefined ();
- vr1->set_undefined ();
+ vr0->set_undefined (type);
+ vr1->set_undefined (type);
/* As a future improvement, we could handle ~[0, A] as: [-INF, -1] U
[A+1, +INF]. Not sure if this helps in practice, though. */
@@ -1202,7 +1265,7 @@ ranges_from_anti_range (const value_range_base *ar,
if (vr0->undefined_p ())
{
*vr0 = *vr1;
- vr1->set_undefined ();
+ vr1->set_undefined (type);
}
return !vr0->undefined_p ();
@@ -1240,7 +1303,8 @@ static void
extract_range_from_multiplicative_op (value_range_base *vr,
enum tree_code code,
const value_range_base *vr0,
- const value_range_base *vr1)
+ const value_range_base *vr1,
+ tree type)
{
gcc_assert (code == MULT_EXPR
|| code == TRUNC_DIV_EXPR
@@ -1250,13 +1314,31 @@ extract_range_from_multiplicative_op (value_range_base *vr,
|| code == ROUND_DIV_EXPR
|| code == RSHIFT_EXPR
|| code == LSHIFT_EXPR);
- gcc_assert (vr0->kind () == VR_RANGE
- && vr0->kind () == vr1->kind ());
+ if (!range_int_cst_p (vr1))
+ {
+ vr->set_varying (type);
+ return;
+ }
+
+ /* 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]. */
+ value_range_base tem = vr0->normalize_symbolics (type);
+ tree vr0_min, vr0_max;
+ if (tem.kind () == VR_RANGE)
+ {
+ vr0_min = tem.min ();
+ vr0_max = tem.max ();
+ }
+ else
+ {
+ vr0_min = vrp_val_min (type);
+ vr0_max = vrp_val_max (type);
+ }
- 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 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);
@@ -1270,7 +1352,7 @@ extract_range_from_multiplicative_op (value_range_base *vr,
wide_int_to_tree (type, res_lb),
wide_int_to_tree (type, res_ub));
else
- vr->set_varying ();
+ vr->set_varying (type);
}
/* If BOUND will include a symbolic bound, adjust it accordingly,
@@ -1479,7 +1561,7 @@ extract_range_from_binary_expr (value_range_base *vr,
if (!INTEGRAL_TYPE_P (expr_type)
&& !POINTER_TYPE_P (expr_type))
{
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
@@ -1503,14 +1585,14 @@ extract_range_from_binary_expr (value_range_base *vr,
&& code != BIT_IOR_EXPR
&& code != BIT_XOR_EXPR)
{
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
/* If both ranges are UNDEFINED, so is the result. */
if (vr0.undefined_p () && vr1.undefined_p ())
{
- vr->set_undefined ();
+ vr->set_undefined (expr_type);
return;
}
/* If one of the ranges is UNDEFINED drop it to VARYING for the following
@@ -1518,9 +1600,9 @@ extract_range_from_binary_expr (value_range_base *vr,
have UNDEFINED result for all or some value-ranges of the not UNDEFINED
operand. */
else if (vr0.undefined_p ())
- vr0.set_varying ();
+ vr0.set_varying (expr_type);
else if (vr1.undefined_p ())
- vr1.set_varying ();
+ vr1.set_varying (expr_type);
/* We get imprecise results from ranges_from_anti_range when
code is EXACT_DIV_EXPR. We could mask out bits in the resulting
@@ -1592,7 +1674,7 @@ extract_range_from_binary_expr (value_range_base *vr,
|| vr0.symbolic_p ()
|| vr1.symbolic_p ()))
{
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
@@ -1610,7 +1692,7 @@ extract_range_from_binary_expr (value_range_base *vr,
else if (vr0.zero_p () && vr1.zero_p ())
vr->set_zero (expr_type);
else
- vr->set_varying ();
+ vr->set_varying (expr_type);
}
else if (code == POINTER_PLUS_EXPR)
{
@@ -1639,7 +1721,7 @@ extract_range_from_binary_expr (value_range_base *vr,
else if (vr0.zero_p () && vr1.zero_p ())
vr->set_zero (expr_type);
else
- vr->set_varying ();
+ vr->set_varying (expr_type);
}
else if (code == BIT_AND_EXPR)
{
@@ -1650,10 +1732,10 @@ extract_range_from_binary_expr (value_range_base *vr,
else if (vr0.zero_p () || vr1.zero_p ())
vr->set_zero (expr_type);
else
- vr->set_varying ();
+ vr->set_varying (expr_type);
}
else
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
@@ -1720,7 +1802,7 @@ extract_range_from_binary_expr (value_range_base *vr,
if (((bool)min_ovf && sym_min_op0 != sym_min_op1)
|| ((bool)max_ovf && sym_max_op0 != sym_max_op1))
{
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
@@ -1731,7 +1813,7 @@ extract_range_from_binary_expr (value_range_base *vr,
wmin, wmax, min_ovf, max_ovf);
if (type == VR_VARYING)
{
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
@@ -1757,7 +1839,7 @@ extract_range_from_binary_expr (value_range_base *vr,
a single range or anti-range as the above is
[-INF+1, +INF(OVF)] intersected with ~[5, 5]
but one could use a scheme similar to equivalences for this. */
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
}
@@ -1774,7 +1856,7 @@ extract_range_from_binary_expr (value_range_base *vr,
vr->set (VR_RANGE, wide_int_to_tree (expr_type, wmin),
wide_int_to_tree (expr_type, wmax));
else
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
else if (code == MULT_EXPR)
@@ -1782,10 +1864,10 @@ extract_range_from_binary_expr (value_range_base *vr,
if (!range_int_cst_p (&vr0)
|| !range_int_cst_p (&vr1))
{
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
- extract_range_from_multiplicative_op (vr, code, &vr0, &vr1);
+ extract_range_from_multiplicative_op (vr, code, &vr0, &vr1, expr_type);
return;
}
else if (code == RSHIFT_EXPR
@@ -1800,13 +1882,8 @@ extract_range_from_binary_expr (value_range_base *vr,
{
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.kind () != VR_RANGE || vr0.symbolic_p ())
- vr0.set (VR_RANGE, vrp_val_min (expr_type),
- vrp_val_max (expr_type));
- extract_range_from_multiplicative_op (vr, code, &vr0, &vr1);
+ extract_range_from_multiplicative_op (vr, code, &vr0, &vr1,
+ expr_type);
return;
}
else if (code == LSHIFT_EXPR
@@ -1827,7 +1904,7 @@ extract_range_from_binary_expr (value_range_base *vr,
}
}
}
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
else if (code == TRUNC_DIV_EXPR
@@ -1843,7 +1920,7 @@ extract_range_from_binary_expr (value_range_base *vr,
/* Special case explicit division by zero as undefined. */
if (vr1.zero_p ())
{
- vr->set_undefined ();
+ vr->set_undefined (expr_type);
return;
}
@@ -1864,7 +1941,7 @@ extract_range_from_binary_expr (value_range_base *vr,
TYPE_OVERFLOW_UNDEFINED (expr_type),
extra_range_p, extra_min, extra_max))
{
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
vr->set (VR_RANGE, wide_int_to_tree (expr_type, wmin),
@@ -1882,7 +1959,7 @@ extract_range_from_binary_expr (value_range_base *vr,
{
if (vr1.zero_p ())
{
- vr->set_undefined ();
+ vr->set_undefined (expr_type);
return;
}
wide_int wmin, wmax, tmp;
@@ -1923,7 +2000,7 @@ extract_range_from_binary_expr (value_range_base *vr,
vr->set (VR_RANGE, min, max);
}
else
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
else if (code == BIT_IOR_EXPR)
@@ -1941,7 +2018,7 @@ extract_range_from_binary_expr (value_range_base *vr,
vr->set (VR_RANGE, min, max);
}
else
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
else if (code == BIT_XOR_EXPR)
@@ -1957,7 +2034,7 @@ extract_range_from_binary_expr (value_range_base *vr,
vr->set (VR_RANGE, min, max);
}
else
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
}
@@ -1971,7 +2048,7 @@ extract_range_from_binary_expr (value_range_base *vr,
|| max == NULL_TREE
|| TREE_OVERFLOW_P (max))
{
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
@@ -1980,7 +2057,7 @@ extract_range_from_binary_expr (value_range_base *vr,
Note that we do accept [-INF, -INF] and [+INF, +INF]. */
if (vrp_val_is_min (min) && vrp_val_is_max (max))
{
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
@@ -1990,7 +2067,7 @@ extract_range_from_binary_expr (value_range_base *vr,
/* If the new range has its limits swapped around (MIN > MAX),
then the operation caused one of them to wrap around, mark
the new range VARYING. */
- vr->set_varying ();
+ vr->set_varying (expr_type);
}
else
vr->set (type, min, max);
@@ -2016,14 +2093,14 @@ extract_range_from_unary_expr (value_range_base *vr,
|| !(INTEGRAL_TYPE_P (type)
|| POINTER_TYPE_P (type)))
{
- vr->set_varying ();
+ vr->set_varying (type);
return;
}
/* If VR0 is UNDEFINED, so is the result. */
if (vr0.undefined_p ())
{
- vr->set_undefined ();
+ vr->set_undefined (type);
return;
}
@@ -2088,7 +2165,7 @@ extract_range_from_unary_expr (value_range_base *vr,
else if (vr0.zero_p ())
vr->set_zero (type);
else
- vr->set_varying ();
+ vr->set_varying (type);
return;
}
@@ -2123,7 +2200,7 @@ extract_range_from_unary_expr (value_range_base *vr,
vr->set_and_canonicalize (VR_RANGE, min, max);
}
else
- vr->set_varying ();
+ vr->set_varying (outer_type);
return;
}
else if (code == ABS_EXPR)
@@ -2136,7 +2213,7 @@ extract_range_from_unary_expr (value_range_base *vr,
vr->set (VR_RANGE, wide_int_to_tree (type, wmin),
wide_int_to_tree (type, wmax));
else
- vr->set_varying ();
+ vr->set_varying (type);
return;
}
else if (code == ABSU_EXPR)
@@ -2151,7 +2228,7 @@ extract_range_from_unary_expr (value_range_base *vr,
}
/* For unhandled operations fall back to varying. */
- vr->set_varying ();
+ vr->set_varying (type);
return;
}
@@ -5147,7 +5224,7 @@ vrp_prop::vrp_initialize ()
if (!stmt_interesting_for_vrp (phi))
{
tree lhs = PHI_RESULT (phi);
- get_value_range (lhs)->set_varying ();
+ get_value_range (lhs)->set_varying (TREE_TYPE (lhs));
prop_set_simulate_again (phi, false);
}
else
@@ -5342,7 +5419,7 @@ vrp_prop::visit_stmt (gimple *stmt, edge *taken_edge_p, tree *output_p)
use_operand_p use_p;
enum ssa_prop_result res = SSA_PROP_VARYING;
- get_value_range (lhs)->set_varying ();
+ get_value_range (lhs)->set_varying (TREE_TYPE (lhs));
FOR_EACH_IMM_USE_FAST (use_p, iter, lhs)
{
@@ -6132,7 +6209,12 @@ value_range_base::union_helper (const value_range_base *vr0,
/* Work on a temporary so we can still use vr0 when union returns varying. */
value_range_base tem;
- tem.set_and_canonicalize (vr0type, vr0min, vr0max);
+ if (vr0type == VR_UNDEFINED)
+ tem.set_undefined (TREE_TYPE (vr0->min ()));
+ else if (vr0type == VR_VARYING)
+ tem.set_varying (TREE_TYPE (vr0->min ()));
+ else
+ tem.set_and_canonicalize (vr0type, vr0min, vr0max);
/* Failed to find an efficient meet. Before giving up and setting
the result to VARYING, see if we can at least derive a useful
@@ -6212,6 +6294,49 @@ value_range::union_ (const value_range *other)
}
}
+/* Normalize symbolics into constants. */
+
+value_range_base
+value_range_base::normalize_symbolics (tree ttype) const
+{
+ if (varying_p () || undefined_p ())
+ return *this;
+ bool min_symbolic = !is_gimple_min_invariant (min ());
+ bool max_symbolic = !is_gimple_min_invariant (max ());
+ if (!min_symbolic && !max_symbolic)
+ return *this;
+
+ // [SYM, SYM] -> VARYING
+ if (min_symbolic && max_symbolic)
+ return value_range_base (ttype);
+ if (kind () == VR_RANGE)
+ {
+ // [SYM, NUM] -> [-MIN, NUM]
+ if (min_symbolic)
+ return value_range_base (VR_RANGE, vrp_val_min (ttype), max ());
+ // [NUM, SYM] -> [NUM, +MAX]
+ return value_range_base (VR_RANGE, min (), vrp_val_max (ttype));
+ }
+ gcc_assert (kind () == VR_ANTI_RANGE);
+ // ~[SYM, NUM] -> [NUM + 1, +MAX]
+ if (min_symbolic)
+ {
+ if (!vrp_val_is_max (max ()))
+ {
+ tree n = wide_int_to_tree (ttype, wi::to_wide (max ()) + 1);
+ return value_range_base (VR_RANGE, n, vrp_val_max (ttype));
+ }
+ return value_range_base (ttype);
+ }
+ // ~[NUM, SYM] -> [-MIN, NUM - 1]
+ if (!vrp_val_is_min (min ()))
+ {
+ tree n = wide_int_to_tree (ttype, wi::to_wide (min ()) - 1);
+ return value_range_base (VR_RANGE, vrp_val_min (ttype), n);
+ }
+ return value_range_base (ttype);
+}
+
/* 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. */
@@ -6885,7 +7010,7 @@ determine_value_range_1 (value_range_base *vr, tree expr)
vr->set (kind, wide_int_to_tree (TREE_TYPE (expr), min),
wide_int_to_tree (TREE_TYPE (expr), max));
else
- vr->set_varying ();
+ vr->set_varying (TREE_TYPE (expr));
}
}
diff --git a/gcc/tree-vrp.h b/gcc/tree-vrp.h
index 4ec974f5fdb..b1ddf484aa7 100644
--- a/gcc/tree-vrp.h
+++ b/gcc/tree-vrp.h
@@ -43,6 +43,7 @@ class GTY((for_user)) value_range_base
public:
value_range_base ();
value_range_base (value_range_kind, tree, tree);
+ value_range_base (tree type);
void set (value_range_kind, tree, tree);
void set (tree);
@@ -58,8 +59,8 @@ public:
bool constant_p () const;
bool undefined_p () const;
bool varying_p () const;
- void set_varying ();
- void set_undefined ();
+ void set_varying (tree = NULL);
+ void set_undefined (tree = NULL);
void union_ (const value_range_base *);
void intersect (const value_range_base *);
@@ -76,6 +77,10 @@ public:
bool nonzero_p () const;
bool singleton_p (tree *result = NULL) const;
void dump (FILE *) const;
+ void dump () const;
+
+ static bool supports_type_p (tree);
+ value_range_base normalize_symbolics (tree) const;
protected:
void check ();
@@ -133,8 +138,8 @@ class GTY((user)) value_range : public value_range_base
bool equal_p (const value_range &, bool ignore_equivs) const;
/* Types of value ranges. */
- void set_undefined ();
- void set_varying ();
+ void set_undefined (tree = NULL);
+ void set_varying (tree = NULL);
/* Equivalence bitmap methods. */
bitmap equiv () const;
@@ -145,6 +150,7 @@ class GTY((user)) value_range : public value_range_base
void deep_copy (const value_range *);
void set_and_canonicalize (enum value_range_kind, tree, tree, bitmap = NULL);
void dump (FILE *) const;
+ void dump () const;
private:
/* Deep-copies bitmap argument. */
@@ -254,6 +260,17 @@ struct assert_info
tree expr;
};
+// Return true if TYPE is a valid type for value_range to operate on.
+// Otherwise return FALSE.
+
+inline bool
+value_range_base::supports_type_p (tree type)
+{
+ if (type && (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)))
+ return type;
+ return NULL;
+}
+
extern void register_edge_assert_for (tree, edge, enum tree_code,
tree, tree, vec<assert_info> &);
extern bool stmt_interesting_for_vrp (gimple *);
@@ -267,11 +284,11 @@ extern bool range_int_cst_singleton_p (const value_range_base *);
extern int compare_values (tree, tree);
extern int compare_values_warnv (tree, tree, bool *);
extern int operand_less_p (tree, tree);
-extern bool vrp_val_is_min (const_tree);
-extern bool vrp_val_is_max (const_tree);
+extern bool vrp_val_is_min (const_tree, bool handle_pointers = false);
+extern bool vrp_val_is_max (const_tree, bool handle_pointers = false);
-extern tree vrp_val_min (const_tree);
-extern tree vrp_val_max (const_tree);
+extern tree vrp_val_min (const_tree, bool handle_pointers = false);
+extern tree vrp_val_max (const_tree, bool handle_pointers = false);
extern void extract_range_from_unary_expr (value_range_base *vr,
enum tree_code code,
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index 3f20c1a6fe8..f0efb6eca3d 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see
#include "attribs.h"
#include "vr-values.h"
#include "cfghooks.h"
+#include "wide-int-range.h"
/* Set value range VR to a non-negative range of type TYPE. */
@@ -64,7 +65,7 @@ static inline void
set_value_range_to_truthvalue (value_range *vr, tree type)
{
if (TYPE_PRECISION (type) == 1)
- vr->set_varying ();
+ vr->set_varying (type);
else
vr->update (VR_RANGE, build_int_cst (type, 0), build_int_cst (type, 1));
}
@@ -126,10 +127,10 @@ vr_values::get_value_range (const_tree var)
{
get_range_info (var, *vr);
if (vr->undefined_p ())
- vr->set_varying ();
+ vr->set_varying (TREE_TYPE (sym));
}
else
- vr->set_varying ();
+ vr->set_varying (TREE_TYPE (sym));
}
else if (TREE_CODE (sym) == RESULT_DECL
&& DECL_BY_REFERENCE (sym))
@@ -198,13 +199,13 @@ vr_values::update_value_range (const_tree var, value_range *new_vr)
called, if we are anyway, keep it VARYING. */
if (old_vr->varying_p ())
{
- new_vr->set_varying ();
+ new_vr->set_varying (new_vr->type ());
is_new = false;
}
else if (new_vr->undefined_p ())
{
- old_vr->set_varying ();
- new_vr->set_varying ();
+ old_vr->set_varying (TREE_TYPE (var));
+ new_vr->set_varying (TREE_TYPE (var));
return true;
}
else
@@ -435,7 +436,7 @@ vr_values::extract_range_for_var_from_comparison_expr (tree var,
if ((POINTER_TYPE_P (type) && cond_code != NE_EXPR && cond_code != EQ_EXPR)
|| limit == var)
{
- vr_p->set_varying ();
+ vr_p->set_varying (type);
return;
}
@@ -595,7 +596,7 @@ vr_values::extract_range_for_var_from_comparison_expr (tree var,
all should be optimized away above us. */
if (cond_code == LT_EXPR
&& compare_values (max, min) == 0)
- vr_p->set_varying ();
+ vr_p->set_varying (TREE_TYPE (min));
else
{
/* For LT_EXPR, we create the range [MIN, MAX - 1]. */
@@ -635,7 +636,7 @@ vr_values::extract_range_for_var_from_comparison_expr (tree var,
all should be optimized away above us. */
if (cond_code == GT_EXPR
&& compare_values (min, max) == 0)
- vr_p->set_varying ();
+ vr_p->set_varying (TREE_TYPE (min));
else
{
/* For GT_EXPR, we create the range [MIN + 1, MAX]. */
@@ -743,14 +744,14 @@ vr_values::extract_range_from_binary_expr (value_range *vr,
else if (is_gimple_min_invariant (op0))
vr0.set (op0);
else
- vr0.set_varying ();
+ vr0.set_varying (TREE_TYPE (op0));
if (TREE_CODE (op1) == SSA_NAME)
vr1 = *(get_value_range (op1));
else if (is_gimple_min_invariant (op1))
vr1.set (op1);
else
- vr1.set_varying ();
+ vr1.set_varying (TREE_TYPE (op1));
/* If one argument is varying, we can sometimes still deduce a
range for the output: any + [3, +INF] is in [MIN+3, +INF]. */
@@ -891,7 +892,7 @@ vr_values::extract_range_from_unary_expr (value_range *vr, enum tree_code code,
else if (is_gimple_min_invariant (op0))
vr0.set (op0);
else
- vr0.set_varying ();
+ vr0.set_varying (type);
::extract_range_from_unary_expr (vr, code, type, &vr0, TREE_TYPE (op0));
}
@@ -913,7 +914,7 @@ vr_values::extract_range_from_cond_expr (value_range *vr, gassign *stmt)
else if (is_gimple_min_invariant (op0))
tem0.set (op0);
else
- tem0.set_varying ();
+ tem0.set_varying (TREE_TYPE (op0));
tree op1 = gimple_assign_rhs3 (stmt);
value_range tem1;
@@ -923,7 +924,7 @@ vr_values::extract_range_from_cond_expr (value_range *vr, gassign *stmt)
else if (is_gimple_min_invariant (op1))
tem1.set (op1);
else
- tem1.set_varying ();
+ tem1.set_varying (TREE_TYPE (op1));
/* The resulting value range is the union of the operand ranges */
vr->deep_copy (vr0);
@@ -975,14 +976,14 @@ vr_values::check_for_binary_op_overflow (enum tree_code subcode, tree type,
else if (TREE_CODE (op0) == INTEGER_CST)
vr0.set (op0);
else
- vr0.set_varying ();
+ vr0.set_varying (TREE_TYPE (op0));
if (TREE_CODE (op1) == SSA_NAME)
vr1 = *get_value_range (op1);
else if (TREE_CODE (op1) == INTEGER_CST)
vr1.set (op1);
else
- vr1.set_varying ();
+ vr1.set_varying (TREE_TYPE (op1));
tree vr0min = vr0.min (), vr0max = vr0.max ();
tree vr1min = vr1.min (), vr1max = vr1.max ();
@@ -1310,7 +1311,7 @@ vr_values::extract_range_basic (value_range *vr, gimple *stmt)
if (vr->kind () == VR_RANGE
&& (vr->min () == vr->max ()
|| operand_equal_p (vr->min (), vr->max (), 0)))
- vr->set_varying ();
+ vr->set_varying (vr->type ());
return;
}
}
@@ -1366,7 +1367,7 @@ vr_values::extract_range_basic (value_range *vr, gimple *stmt)
vr->set (build_int_cst (type, ovf));
else if (TYPE_PRECISION (type) == 1
&& !TYPE_UNSIGNED (type))
- vr->set_varying ();
+ vr->set_varying (type);
else
vr->set (VR_RANGE, build_int_cst (type, 0),
build_int_cst (type, 1));
@@ -1411,7 +1412,7 @@ vr_values::extract_range_basic (value_range *vr, gimple *stmt)
vr->equiv_clear ();
}
else
- vr->set_varying ();
+ vr->set_varying (type);
}
@@ -1447,7 +1448,7 @@ vr_values::extract_range_from_assignment (value_range *vr, gassign *stmt)
&& is_gimple_min_invariant (gimple_assign_rhs1 (stmt)))
vr->set (gimple_assign_rhs1 (stmt));
else
- vr->set_varying ();
+ vr->set_varying (TREE_TYPE (gimple_assign_lhs (stmt)));
if (vr->varying_p ())
extract_range_basic (vr, stmt);
@@ -2856,7 +2857,7 @@ vr_values::extract_range_from_phi_node (gphi *phi, value_range *vr_result)
vr_arg_tem.set (vr_arg_->kind (), vr_arg_->min (),
vr_arg_->max (), NULL);
if (vr_arg_tem.symbolic_p ())
- vr_arg_tem.set_varying ();
+ vr_arg_tem.set_varying (TREE_TYPE (arg));
}
else
vr_arg = vr_arg_;
@@ -2978,7 +2979,7 @@ vr_values::extract_range_from_phi_node (gphi *phi, value_range *vr_result)
goto update_range;
varying:
- vr_result->set_varying ();
+ vr_result->set_varying (TREE_TYPE (lhs));
scev_check:
/* If this is a loop PHI node SCEV may known more about its value-range.
@@ -2999,7 +3000,7 @@ infinite_check:
|| compare_values (vr_result->min (), vr_result->max ()) > 0))
;
else
- vr_result->set_varying ();
+ vr_result->set_varying (TREE_TYPE (lhs));
/* If the new range is different than the previous value, keep
iterating. */