aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@redhat.com>2019-08-21 19:27:27 +0000
committerAldy Hernandez <aldyh@redhat.com>2019-08-21 19:27:27 +0000
commit7e8e73b58a234ef65e525200557d101dfe92ef5c (patch)
tree9e069322868c62a7d64563933a114145a404ede6
parent9ae915856d1eb04162e28aa435c4fe1be52c0e11 (diff)
Implement new range-ops API.
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/ssa-range@274808 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/grange.cc5
-rw-r--r--gcc/range-op.cc811
-rw-r--r--gcc/range-op.h20
-rw-r--r--gcc/ssa-range-cache.cc12
-rw-r--r--gcc/ssa-range-gori.cc2
-rw-r--r--gcc/ssa-range.cc6
-rw-r--r--gcc/tree-vrp.c28
-rw-r--r--gcc/vr-values.c6
8 files changed, 444 insertions, 446 deletions
diff --git a/gcc/grange.cc b/gcc/grange.cc
index fb9b01909af..6c6bdec7d48 100644
--- a/gcc/grange.cc
+++ b/gcc/grange.cc
@@ -297,7 +297,10 @@ grange_op::fold (irange &res, const irange &r1, const irange &r2) const
if (grange_adjust_handler ())
adj = grange_adjust_handler()->lhs_adjust (adj_range, this);
if (handler ())
- hand = handler()->fold_range (res, gimple_expr_type (this), r1, r2);
+ {
+ hand = true;
+ res = handler()->fold_range (gimple_expr_type (this), r1, r2);
+ }
// Handle common case first where res was set by handler
// This handles whatever handler() would ahve returned.
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 0d36e384cf2..cf70f097add 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -47,32 +47,43 @@ along with GCC; see the file COPYING3. If not see
#include "range-op.h"
#include "wide-int-range.h"
+// Auxiliary routine to return the upper limit for a type.
-// Default wide_int fold operation does nothing.
-bool
-range_operator::wi_fold (irange &r ATTRIBUTE_UNUSED,
- tree type ATTRIBUTE_UNUSED,
+inline wide_int
+max_limit (const_tree type)
+{
+ return wi::max_value (TYPE_PRECISION (type) , TYPE_SIGN (type));
+}
+
+// Auxiliary routine to return the lower limit for a type.
+
+inline wide_int
+min_limit (const_tree type)
+{
+ return wi::min_value (TYPE_PRECISION (type) , TYPE_SIGN (type));
+}
+
+
+// Default wide_int fold operation returns [min , max].
+irange
+range_operator::wi_fold (tree type,
const wide_int &lh_lb ATTRIBUTE_UNUSED,
const wide_int &lh_ub ATTRIBUTE_UNUSED,
const wide_int &rh_lb ATTRIBUTE_UNUSED,
const wide_int &rh_ub ATTRIBUTE_UNUSED) const
{
- return false;
+ return irange (type);
}
// The default for fold is to break all ranges into subranges
// and invoke the 'wi_fold' method on each subrange pair.
-bool
-range_operator::fold_range (irange &r, tree type, const irange &lh,
- const irange &rh) const
+irange
+range_operator::fold_range (tree type, const irange &lh,
+ const irange &rh) const
{
- bool res = false;
-
- // Clear and set result type.
- r.set_undefined ();
-
+ irange r;
if (lh.undefined_p () || rh.undefined_p ())
- return true;
+ return r;
for (unsigned x = 0; x < lh.num_pairs (); ++x)
for (unsigned y = 0; y < rh.num_pairs (); ++y)
@@ -81,12 +92,12 @@ range_operator::fold_range (irange &r, tree type, const irange &lh,
wide_int lh_ub = lh.upper_bound (x);
wide_int rh_lb = rh.lower_bound (y);
wide_int rh_ub = rh.upper_bound (y);
- res = wi_fold (r, type, lh_lb, lh_ub, rh_lb, rh_ub);
- if (!res)
- return false;
+ r.union_ (wi_fold (type, lh_lb, lh_ub, rh_lb, rh_ub));
+ if (r.varying_p ())
+ return r;
}
- return res && !r.varying_p ();
+ return r;
}
// The default for op1_range is to return false.
@@ -112,22 +123,6 @@ range_operator::op2_range (irange &r ATTRIBUTE_UNUSED,
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
-// Auxillary routine to return the upper limit for a type.
-
-inline wide_int
-max_limit (const_tree type)
-{
- return wi::max_value (TYPE_PRECISION (type) , TYPE_SIGN (type));
-}
-
-// Auxillary routine to return the lower limit for a type.
-
-inline wide_int
-min_limit (const_tree type)
-{
- return wi::min_value (TYPE_PRECISION (type) , TYPE_SIGN (type));
-}
-
// If the range of either op1 or op2 is undefined, set the result to
// undefined and return true.
@@ -179,7 +174,7 @@ adjust_overflow_bound (irange &r, tree type, const wide_int &wmin,
}
// Given newly calculated lbound and ubound, examine their respective
-// overflow bits to determine how to add [lbound, ubound] into range R.
+// overflow bits to determine how to add [lbound, ubound] into range R.
static void
accumulate_range (irange &r, tree type, const wide_int &wmin,
@@ -330,23 +325,24 @@ get_bool_state (irange &r, const irange &lhs, tree val_type)
class operator_equal : public range_operator
{
public:
- virtual bool fold_range (irange &r, tree type, const irange &op1,
- const irange &op2) const;
+ virtual irange fold_range (tree type,
+ const irange &op1, const irange &op2) const;
virtual bool op1_range (irange &r, tree type, const irange &lhs,
- const irange &val) const;
+ const irange &val) const;
virtual bool op2_range (irange &r, tree type, const irange &lhs,
- const irange &val) const;
+ const irange &val) const;
} op_equal;
/* Fold comparison of the 2 ranges. */
-bool
-operator_equal::fold_range (irange &r, tree type, const irange &op1,
- const irange &op2) const
+irange
+operator_equal::fold_range (tree type,
+ const irange &op1, const irange &op2) const
{
+ irange r;
if (empty_range_check (r, op1, op2))
- return true;
+ return r;
/* We can be sure the values are always equal or not if both ranges
consist of a single value, and then compare them. */
@@ -369,7 +365,7 @@ operator_equal::fold_range (irange &r, tree type, const irange &op1,
r = range_true_and_false (type);
}
- return true;
+ return r;
}
bool
@@ -412,8 +408,8 @@ operator_equal::op2_range (irange &r, tree type, const irange &lhs,
class operator_not_equal : public range_operator
{
public:
- virtual bool fold_range (irange &r, tree type, const irange &op1,
- const irange &op2) const;
+ virtual irange fold_range (tree type,
+ const irange &op1, const irange &op2) const;
virtual bool op1_range (irange &r, tree type, const irange &lhs,
const irange &op2) const;
virtual bool op2_range (irange &r, tree type, const irange &lhs,
@@ -421,12 +417,13 @@ public:
} op_not_equal;
/* Fold comparison of the 2 ranges. */
-bool
-operator_not_equal::fold_range (irange &r, tree type, const irange &op1,
- const irange &op2) const
+irange
+operator_not_equal::fold_range (tree type,
+ const irange &op1, const irange &op2) const
{
+ irange r;
if (empty_range_check (r, op1, op2))
- return true;
+ return r;
/* We can be sure the values are always equal or not if both ranges
consist of a single value, and then compare them. */
@@ -449,7 +446,7 @@ operator_not_equal::fold_range (irange &r, tree type, const irange &op1,
r = range_true_and_false (type);
}
- return true;
+ return r;
}
/* Calculate the range of op1 being == to VAL based on LHS. */
@@ -534,19 +531,20 @@ build_ge (irange &r, tree type, const wide_int &val)
class operator_lt : public range_operator
{
public:
- virtual bool fold_range (irange &r, tree type, const irange &op1,
- const irange &op2) const;
+ virtual irange fold_range (tree type,
+ const irange &op1, const irange &op2) const;
virtual bool op1_range (irange &r, tree type, const irange &lhs,
const irange &op2) const;
virtual bool op2_range (irange &r, tree type, const irange &lhs,
const irange &op1) const;
} op_lt;
-bool
-operator_lt::fold_range (irange &r, tree type, const irange &op1, const irange &op2) const
+irange
+operator_lt::fold_range (tree type, const irange &op1, const irange &op2) const
{
+ irange r;
if (empty_range_check (r, op1, op2))
- return true;
+ return r;
signop sign = TYPE_SIGN (op1.type ());
gcc_checking_assert (sign == TYPE_SIGN (op2.type ()));
@@ -558,7 +556,7 @@ operator_lt::fold_range (irange &r, tree type, const irange &op1, const irange &
r = range_false (type);
else
r = range_true_and_false (type);
- return true;
+ return r;
}
@@ -605,19 +603,20 @@ operator_lt::op2_range (irange &r, tree type, const irange &lhs, const irange &o
class operator_le : public range_operator
{
public:
- virtual bool fold_range (irange &r, tree type, const irange &op1,
- const irange &op2) const;
- virtual bool op1_range (irange &r, tree type, const irange &lhs,
- const irange &op2) const;
- virtual bool op2_range (irange &r, tree type, const irange &lhs,
- const irange &op1) const;
+ virtual irange fold_range (tree type,
+ const irange &op1, const irange &op2) const;
+ virtual bool op1_range (irange &r, tree type,
+ const irange &lhs, const irange &op2) const;
+ virtual bool op2_range (irange &r, tree type,
+ const irange &lhs, const irange &op1) const;
} op_le;
-bool
-operator_le::fold_range (irange &r, tree type, const irange &op1, const irange &op2) const
+irange
+operator_le::fold_range (tree type, const irange &op1, const irange &op2) const
{
+ irange r;
if (empty_range_check (r, op1, op2))
- return true;
+ return r;
signop sign = TYPE_SIGN (op1.type ());
gcc_checking_assert (sign == TYPE_SIGN (op2.type ()));
@@ -629,7 +628,7 @@ operator_le::fold_range (irange &r, tree type, const irange &op1, const irange &
r = range_false (type);
else
r = range_true_and_false (type);
- return true;
+ return r;
}
bool
@@ -676,19 +675,20 @@ operator_le::op2_range (irange &r, tree type, const irange &lhs, const irange &o
class operator_gt : public range_operator
{
public:
- virtual bool fold_range (irange &r, tree type, const irange &op1,
- const irange &op2) const;
- virtual bool op1_range (irange &r, tree type, const irange &lhs,
- const irange &op2) const;
- virtual bool op2_range (irange &r, tree type, const irange &lhs,
- const irange &op1) const;
+ virtual irange fold_range (tree type,
+ const irange &op1, const irange &op2) const;
+ virtual bool op1_range (irange &r, tree type,
+ const irange &lhs, const irange &op2) const;
+ virtual bool op2_range (irange &r, tree type,
+ const irange &lhs, const irange &op1) const;
} op_gt;
-bool
-operator_gt::fold_range (irange &r, tree type, const irange &op1, const irange &op2) const
+irange
+operator_gt::fold_range (tree type, const irange &op1, const irange &op2) const
{
+ irange r;
if (empty_range_check (r, op1, op2))
- return true;
+ return r;
signop sign = TYPE_SIGN (op1.type ());
gcc_checking_assert (sign == TYPE_SIGN (op2.type ()));
@@ -701,7 +701,7 @@ operator_gt::fold_range (irange &r, tree type, const irange &op1, const irange &
else
r = range_true_and_false (type);
- return true;
+ return r;
}
bool
@@ -748,19 +748,20 @@ operator_gt::op2_range (irange &r, tree type, const irange &lhs, const irange &o
class operator_ge : public range_operator
{
public:
- virtual bool fold_range (irange &r, tree type, const irange &op1,
- const irange &op2) const;
- virtual bool op1_range (irange &r, tree type, const irange &lhs,
- const irange &op2) const;
- virtual bool op2_range (irange &r, tree type, const irange &lhs,
- const irange &op1) const;
+ virtual irange fold_range (tree type,
+ const irange &op1, const irange &op2) const;
+ virtual bool op1_range (irange &r, tree type,
+ const irange &lhs, const irange &op2) const;
+ virtual bool op2_range (irange &r, tree type,
+ const irange &lhs, const irange &op1) const;
} op_ge;
-bool
-operator_ge::fold_range (irange &r, tree type, const irange &op1, const irange &op2) const
+irange
+operator_ge::fold_range (tree type, const irange &op1, const irange &op2) const
{
+ irange r;
if (empty_range_check (r, op1, op2))
- return true;
+ return r;
signop sign = TYPE_SIGN (op1.type ());
gcc_checking_assert (sign == TYPE_SIGN (op2.type ()));
@@ -773,7 +774,7 @@ operator_ge::fold_range (irange &r, tree type, const irange &op1, const irange &
else
r = range_true_and_false (type);
- return true;
+ return r;
}
bool
@@ -825,15 +826,16 @@ public:
const irange &op2) const;
virtual bool op2_range (irange &r, tree type, const irange &lhs,
const irange &op1) const;
- bool wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const;
+ virtual irange wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_plus;
-bool operator_plus::wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const
+irange
+operator_plus::wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const
{
wide_int new_lb, new_ub, tmp;
wi::overflow_type ov_lb, ov_ub;
@@ -841,24 +843,27 @@ bool operator_plus::wi_fold (irange &r, tree type,
new_lb = wi::add (lh_lb, rh_lb, s, &ov_lb);
new_ub = wi::add (lh_ub, rh_ub, s, &ov_ub);
+ irange r;
accumulate_range (r, type, new_lb, new_ub, ov_lb, ov_ub);
- return true;
+ return r;
}
/* Adjust irange to be in terms of op1.
Given [range] = op1 + val, op1 = [range] - val. */
bool
operator_plus::op1_range (irange &r, tree type, const irange &lhs,
- const irange &op2) const
+ const irange &op2) const
{
- return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, lhs, op2);
+ r = range_op_handler (MINUS_EXPR, type)->fold_range (type, lhs, op2);
+ return true;
}
bool
operator_plus::op2_range (irange &r, tree type, const irange &lhs,
- const irange &op1) const
+ const irange &op1) const
{
- return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, lhs, op1);
+ r = range_op_handler (MINUS_EXPR, type)->fold_range (type, lhs, op1);
+ return true;
}
// ----------------------------------------------------------------------------
@@ -870,16 +875,16 @@ public:
const irange &op2) const;
virtual bool op2_range (irange &r, tree type, const irange &lhs,
const irange &op1) const;
- bool wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const;
+ virtual irange wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_minus;
-bool
-operator_minus::wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const
+irange
+operator_minus::wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const
{
wide_int new_lb, new_ub, tmp;
wi::overflow_type ov_lb, ov_ub;
@@ -887,8 +892,9 @@ operator_minus::wi_fold (irange &r, tree type,
new_lb = wi::sub (lh_lb, rh_ub, s, &ov_lb);
new_ub = wi::sub (lh_ub, rh_lb, s, &ov_ub);
+ irange r;
accumulate_range (r, type, new_lb, new_ub, ov_lb, ov_ub);
- return true;
+ return r;
}
/* Adjust irange to be in terms of op1.
@@ -897,7 +903,8 @@ bool
operator_minus::op1_range (irange &r, tree type, const irange &lhs,
const irange &op2) const
{
- return range_op_handler (PLUS_EXPR, type)->fold_range (r, type, lhs, op2);
+ r = range_op_handler (PLUS_EXPR, type)->fold_range (type, lhs, op2);
+ return true;
}
/* Adjust irange to be in terms of op2.
@@ -906,7 +913,8 @@ bool
operator_minus::op2_range (irange &r, tree type, const irange &lhs,
const irange &op1) const
{
- return fold_range (r, type, op1, lhs);
+ r = fold_range (type, op1, lhs);
+ return true;
}
// ----------------------------------------------------------------------------
@@ -914,25 +922,25 @@ operator_minus::op2_range (irange &r, tree type, const irange &lhs,
class operator_min : public range_operator
{
public:
- bool wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const;
+ virtual irange wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_min;
-bool
-operator_min::wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const
+irange
+operator_min::wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const
{
-
wide_int new_lb, new_ub;
signop s = TYPE_SIGN (type);
new_lb = wi::min (lh_lb, rh_lb, s);
new_ub = wi::min (lh_ub, rh_ub, s);
+ irange r;
accumulate_range (r, type, new_lb, new_ub);
- return true;
+ return r;
}
// ----------------------------------------------------------------------------
@@ -940,24 +948,24 @@ operator_min::wi_fold (irange &r, tree type,
class operator_max : public range_operator
{
public:
- bool wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const;
+ virtual irange wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_max;
-bool
-operator_max::wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const
+irange
+operator_max::wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const
{
-
wide_int new_lb, new_ub;
signop s = TYPE_SIGN (type);
new_lb = wi::max (lh_lb, rh_lb, s);
new_ub = wi::max (lh_ub, rh_ub, s);
+ irange r;
accumulate_range (r, type, new_lb, new_ub);
- return true;
+ return r;
}
@@ -966,16 +974,16 @@ operator_max::wi_fold (irange &r, tree type,
class operator_mult : public range_operator
{
public:
- bool wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const;
+ virtual irange wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_mult;
-bool
-operator_mult::wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const
+irange
+operator_mult::wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const
{
bool res;
wide_int new_lb, new_ub;
@@ -991,11 +999,11 @@ operator_mult::wi_fold (irange &r, tree type,
lh_lb, lh_ub, rh_lb, rh_ub);
if (res)
{
+ irange r;
accumulate_possibly_reversed_range (r, type, new_lb, new_ub);
- return true;
+ return r;
}
-
- return false;
+ return irange (type);
}
@@ -1005,9 +1013,9 @@ class operator_div : public range_operator
{
public:
operator_div (enum tree_code c) { code = c; }
- bool wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const;
+ virtual irange wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const;
private:
enum tree_code code;
};
@@ -1017,10 +1025,10 @@ operator_div op_floor_div(FLOOR_DIV_EXPR);
operator_div op_round_div (ROUND_DIV_EXPR);
operator_div op_ceil_div (CEIL_DIV_EXPR);
-bool
-operator_div::wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const
+irange
+operator_div::wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const
{
wide_int new_lb, new_ub;
wide_int extra_min, extra_max;
@@ -1029,7 +1037,7 @@ operator_div::wi_fold (irange &r, tree type,
/* If we know we will divide by zero, return an empty range,
which will be interpreted as undefined. */
if (rh_lb == 0 && rh_ub == 0)
- return true;
+ return irange ();
if (wide_int_range_div (new_lb, new_ub, code, TYPE_SIGN (type),
TYPE_PRECISION (type),
@@ -1038,12 +1046,13 @@ operator_div::wi_fold (irange &r, tree type,
TYPE_OVERFLOW_UNDEFINED (type),
extra_range_p, extra_min, extra_max))
{
+ irange r;
accumulate_range (r, type, new_lb, new_ub);
if (extra_range_p)
accumulate_range (r, type, extra_min, extra_max);
- return true;
+ return r;
}
- return false;
+ return irange (type);
}
@@ -1072,10 +1081,12 @@ operator_exact_divide::op1_range (irange &r, tree type,
// TRUE accuraacy is [6,6][9,9][12,12]. This is unlikely to matter most of
// the time however.
// If op2 is a multiple of 2, we would be able to set some non-zero bits.
- if (op2.singleton_p (&offset)
- && range_op_handler (MULT_EXPR, type)->fold_range (r, type, lhs, op2)
+ if (op2.singleton_p (&offset)
&& !integer_zerop (offset))
- return true;
+ {
+ r = range_op_handler (MULT_EXPR, type)->fold_range (type, lhs, op2);
+ return true;
+ }
return false;
}
@@ -1084,35 +1095,36 @@ operator_exact_divide::op1_range (irange &r, tree type,
class operator_lshift : public range_operator
{
public:
- bool fold_range (irange& r, tree type, const irange& op1,
- const irange& op2) const;
+ virtual irange fold_range (tree type,
+ const irange &op1, const irange &op2) const;
- bool wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const;
+ virtual irange wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_lshift;
-bool
-operator_lshift::fold_range (irange& r, tree type, const irange& op1,
- const irange& op2) const
+irange
+operator_lshift::fold_range (tree type,
+ const irange &op1, const irange &op2) const
{
// Check to see if the shift amount is undefined, and return if so.
- if (op2.undefined_p () ||
- wide_int_range_shift_undefined_p (TYPE_SIGN (op2.type ()),
+ if (op2.undefined_p ())
+ return irange ();
+
+ if (wide_int_range_shift_undefined_p (TYPE_SIGN (op2.type ()),
TYPE_PRECISION (type),
op2.lower_bound (),
op2.upper_bound ()))
- return false;
+ return irange (type);
// Otherwise just invoke the normal fold routine.
- return range_operator::fold_range (r, type, op1, op2);
-
+ return range_operator::fold_range (type, op1, op2);
}
-bool
-operator_lshift::wi_fold (irange &r, tree type,
+irange
+operator_lshift::wi_fold (tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb, const wide_int &rh_ub) const
{
@@ -1123,10 +1135,11 @@ operator_lshift::wi_fold (irange &r, tree type,
lh_lb, lh_ub, rh_lb, rh_ub,
TYPE_OVERFLOW_UNDEFINED (type)))
{
+ irange r;
accumulate_possibly_reversed_range (r, type, new_lb, new_ub);
- return true;
+ return r;
}
- return false;
+ return irange (type);
}
// ----------------------------------------------------------------------------
@@ -1134,34 +1147,37 @@ operator_lshift::wi_fold (irange &r, tree type,
class operator_rshift : public range_operator
{
public:
- bool fold_range (irange& r, tree type, const irange& op1,
- const irange& op2) const;
- bool wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const;
+ virtual irange fold_range (tree type,
+ const irange &op1, const irange &op2) const;
+ virtual irange wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_rshift;
-bool
-operator_rshift::fold_range (irange& r, tree type, const irange& op1,
- const irange& op2) const
+irange
+operator_rshift::fold_range (tree type,
+ const irange &op1, const irange &op2) const
{
// Check to see if the shift amount is undefined, and return if so.
- if (op2.undefined_p () ||
- wide_int_range_shift_undefined_p (TYPE_SIGN (op2.type ()),
+ if (op2.undefined_p ())
+ return irange ();
+
+ if (wide_int_range_shift_undefined_p (TYPE_SIGN (op2.type ()),
TYPE_PRECISION (type),
op2.lower_bound (),
op2.upper_bound ()))
- return false;
+ return irange (type);
// Otherwise just invoke the normal fold routine.
- return range_operator::fold_range (r, type, op1, op2);
+ return range_operator::fold_range (type, op1, op2);
}
-bool
-operator_rshift::wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const
+
+irange
+operator_rshift::wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const
{
wide_int new_lb, new_ub;
signop s = TYPE_SIGN (type);
@@ -1171,10 +1187,11 @@ operator_rshift::wi_fold (irange &r, tree type,
lh_lb, lh_ub, rh_lb, rh_ub,
TYPE_OVERFLOW_UNDEFINED (type)))
{
+ irange r;
accumulate_possibly_reversed_range (r, type, new_lb, new_ub);
- return true;
+ return r;
}
- return false;
+ return irange (type);
}
// ----------------------------------------------------------------------------
@@ -1183,10 +1200,10 @@ operator_rshift::wi_fold (irange &r, tree type,
class operator_cast: public range_operator
{
public:
- virtual bool fold_range (irange &r, tree type, const irange &op1,
- const irange &op2) const;
- virtual bool op1_range (irange &r, tree type, const irange &lhs,
- const irange &op2) const;
+ virtual irange fold_range (tree type,
+ const irange &op1, const irange &op2) const;
+ virtual bool op1_range (irange &r, tree type,
+ const irange &lhs, const irange &op2) const;
} op_convert;
@@ -1194,12 +1211,13 @@ public:
/* Return the range of lh converted to the type of rh:
r = (type_of(rh)) lh. */
-bool
-operator_cast::fold_range (irange &r, tree type ATTRIBUTE_UNUSED,
+irange
+operator_cast::fold_range (tree type ATTRIBUTE_UNUSED,
const irange &lh, const irange &rh) const
{
+ irange r;
if (empty_range_check (r, lh, rh))
- return true;
+ return r;
if (lh.type () != rh.type ())
{
@@ -1212,16 +1230,15 @@ operator_cast::fold_range (irange &r, tree type ATTRIBUTE_UNUSED,
/* If they are the same type, the result should be the intersection of
the two ranges. */
r = range_intersect (lh, rh);
- return true;
+ return r;
}
bool
-operator_cast::op1_range (irange &r, tree type, const irange &lhs,
- const irange &op2) const
+operator_cast::op1_range (irange &r, tree type,
+ const irange &lhs, const irange &op2) const
{
tree lhs_type = lhs.type ();
- gcc_checking_assert (op2.type() == type);
- irange op_type;
+ gcc_checking_assert (types_compatible_p (op2.type(), type));
/* If the precision of the LHS is smaller than the precision of the RHS,
then there would be truncation of the value on the RHS, and so we can tell
@@ -1244,7 +1261,7 @@ operator_cast::op1_range (irange &r, tree type, const irange &lhs,
}
/* Special case if the LHS is a boolean. A 0 means the RHS is zero,
and a 1 means the RHS is non-zero. */
- else if (TREE_CODE (lhs_type) == BOOLEAN_TYPE)
+ if (TREE_CODE (lhs_type) == BOOLEAN_TYPE)
{
/* If the LHS is unknown, the result is whatever op2 already is. */
if (!lhs.singleton_p ())
@@ -1264,10 +1281,10 @@ operator_cast::op1_range (irange &r, tree type, const irange &lhs,
wi::zero (prec), wi::zero (prec));
/* And intersect it with what we know about op2. */
r.intersect (op2);
- return true;
}
- /* Otherwise we'll have to assume it's whatever we know about op2. */
- r = op2;
+ else
+ /* Otherwise we'll have to assume it's whatever we know about op2. */
+ r = op2;
return true;
}
@@ -1276,7 +1293,7 @@ operator_cast::op1_range (irange &r, tree type, const irange &lhs,
if (TYPE_PRECISION (lhs_type) > TYPE_PRECISION (type))
{
/* Cast the range of the RHS to the type of the LHS. */
- op_type.set_varying (type);
+ irange op_type (type);
op_type.cast (lhs_type);
/* Intersect this with the LHS range will produce the RHS range. */
@@ -1287,7 +1304,6 @@ operator_cast::op1_range (irange &r, tree type, const irange &lhs,
/* Cast the calculated range to the type of the RHS. */
r.cast (type);
-
return true;
}
@@ -1298,7 +1314,7 @@ operator_cast::op1_range (irange &r, tree type, const irange &lhs,
class operator_logical_and : public range_operator
{
public:
- virtual bool fold_range (irange &r, tree type, const irange &lh, const irange &rh) const;
+ virtual irange fold_range (tree type, const irange &lh, const irange &rh) const;
virtual bool op1_range (irange &r, tree type, const irange &lhs,
const irange &op2) const;
virtual bool op2_range (irange &r, tree type, const irange &lhs,
@@ -1306,38 +1322,34 @@ public:
} op_logical_and;
-bool
-operator_logical_and::fold_range (irange &r, tree type, const irange &lh,
- const irange &rh) const
+irange
+operator_logical_and::fold_range (tree type,
+ const irange &lh, const irange &rh) const
{
+ irange r;
if (empty_range_check (r, lh, rh))
- return true;
+ return r;
// 0 && anything is 0
if ((wi::eq_p (lh.lower_bound (), 0) && wi::eq_p (lh.upper_bound (), 0))
|| (wi::eq_p (lh.lower_bound (), 0) && wi::eq_p (rh.upper_bound (), 0)))
- {
- r = range_false (type);
- return true;
- }
+ return range_false (type);
// To reach this point, there must be a logical 1 on each side, and the only
// remaining question is whether there is a zero or not.
if (lh.contains_p (build_zero_cst (lh.type ()))
|| rh.contains_p (build_zero_cst (rh.type ())))
- r = range_true_and_false (type);
- else
- r = range_true (type);
+ return range_true_and_false (type);
- return true;
+ return range_true (type);
}
bool
operator_logical_and::op1_range (irange &r, tree type, const irange &lhs,
- const irange &op2 ATTRIBUTE_UNUSED) const
+ const irange &op2 ATTRIBUTE_UNUSED) const
{
switch (get_bool_state (r, lhs, type))
{
@@ -1355,8 +1367,8 @@ operator_logical_and::op1_range (irange &r, tree type, const irange &lhs,
}
bool
-operator_logical_and::op2_range (irange &r, tree type, const irange &lhs,
- const irange &op1) const
+operator_logical_and::op2_range (irange &r, tree type,
+ const irange &lhs, const irange &op1) const
{
return operator_logical_and::op1_range (r, type, lhs, op1);
}
@@ -1365,17 +1377,17 @@ class operator_bitwise_and : public range_operator
{
public:
virtual bool op1_range (irange &r, tree type, const irange &lhs,
- const irange &op2) const;
+ const irange &op2) const;
virtual bool op2_range (irange &r, tree type, const irange &lhs,
- const irange &op1) const;
- bool wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const;
+ const irange &op1) const;
+ virtual irange wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_bitwise_and;
-bool
-operator_bitwise_and::wi_fold (irange &r, tree type,
+irange
+operator_bitwise_and::wi_fold (tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb, const wide_int &rh_ub) const
{
@@ -1401,17 +1413,15 @@ operator_bitwise_and::wi_fold (irange &r, tree type,
// For AND, calculate each subrange separately, and then union
// the results.
irange tmp;
- tmp.set_undefined ();
accumulate_range (tmp, type, new_lb, new_ub);
- r.union_ (tmp);
- return true;
+ return tmp;
}
- return false;
+ return irange (type);
}
bool
-operator_bitwise_and::op1_range (irange &r, tree type, const irange &lhs,
- const irange &op2) const
+operator_bitwise_and::op1_range (irange &r, tree type,
+ const irange &lhs, const irange &op2) const
{
/* If this is really a logical wi_fold, call that. */
if (types_compatible_p (type, boolean_type_node))
@@ -1433,28 +1443,29 @@ operator_bitwise_and::op2_range (irange &r, tree type, const irange &lhs,
class operator_logical_or : public range_operator
{
public:
- virtual bool fold_range (irange &r, tree type, const irange &lh, const irange &rh) const;
- virtual bool op1_range (irange &r, tree type, const irange &lhs,
- const irange &op2) const;
- virtual bool op2_range (irange &r, tree type, const irange &lhs,
- const irange &op1) const;
+ virtual irange fold_range (tree type,
+ const irange &lh, const irange &rh) const;
+ virtual bool op1_range (irange &r, tree type,
+ const irange &lhs, const irange &op2) const;
+ virtual bool op2_range (irange &r, tree type,
+ const irange &lhs, const irange &op1) const;
} op_logical_or;
-bool
-operator_logical_or::fold_range (irange &r, tree type ATTRIBUTE_UNUSED,
+irange
+operator_logical_or::fold_range (tree type ATTRIBUTE_UNUSED,
const irange &lh, const irange &rh) const
{
+ irange r;
if (empty_range_check (r, lh, rh))
- return true;
+ return r;
- r = range_union (lh, rh);
- return true;
+ return range_union (lh, rh);
}
bool
operator_logical_or::op1_range (irange &r, tree type, const irange &lhs,
- const irange &op2 ATTRIBUTE_UNUSED) const
+ const irange &op2 ATTRIBUTE_UNUSED) const
{
switch (get_bool_state (r, lhs, type))
{
@@ -1485,14 +1496,14 @@ public:
const irange &op2) const;
virtual bool op2_range (irange &r, tree type, const irange &lhs,
const irange &op1) const;
- bool wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const;
+ virtual irange wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_bitwise_or;
-bool
-operator_bitwise_or::wi_fold (irange &r, tree type,
+irange
+operator_bitwise_or::wi_fold (tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb, const wide_int &rh_ub) const
{
@@ -1515,15 +1526,16 @@ operator_bitwise_or::wi_fold (irange &r, tree type,
must_be_nonzero_rh,
may_be_nonzero_rh))
{
+ irange r;
accumulate_range (r, type, new_lb, new_ub);
- return true;
+ return r;
}
- return false;
+ return irange (type);
}
bool
-operator_bitwise_or::op1_range (irange &r, tree type, const irange &lhs,
- const irange &op2) const
+operator_bitwise_or::op1_range (irange &r, tree type,
+ const irange &lhs, const irange &op2) const
{
/* If this is really a logical wi_fold, call that. */
if (types_compatible_p (type, boolean_type_node))
@@ -1535,8 +1547,8 @@ operator_bitwise_or::op1_range (irange &r, tree type, const irange &lhs,
}
bool
-operator_bitwise_or::op2_range (irange &r, tree type, const irange &lhs,
- const irange &op1) const
+operator_bitwise_or::op2_range (irange &r, tree type,
+ const irange &lhs, const irange &op1) const
{
return operator_bitwise_or::op1_range (r, type, lhs, op1);
}
@@ -1544,16 +1556,16 @@ operator_bitwise_or::op2_range (irange &r, tree type, const irange &lhs,
class operator_bitwise_xor : public range_operator
{
public:
- bool wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const;
+ virtual irange wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_bitwise_xor;
-bool
-operator_bitwise_xor::wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const
+irange
+operator_bitwise_xor::wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const
{
wide_int new_lb, new_ub, tmp;
signop s = TYPE_SIGN (type);
@@ -1572,47 +1584,50 @@ operator_bitwise_xor::wi_fold (irange &r, tree type,
must_be_nonzero_rh,
may_be_nonzero_rh))
{
+ irange r;
accumulate_range (r, type, new_lb, new_ub);
- return true;
+ return r;
}
- return false;
+ return irange (type);
}
class operator_trunc_mod : public range_operator
{
public:
- bool wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const;
+ virtual irange wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_trunc_mod;
-bool
-operator_trunc_mod::wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const
+irange
+operator_trunc_mod::wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const
{
wide_int new_lb, new_ub, tmp;
signop s = TYPE_SIGN (type);
- /* Mod 0 is undefined, so no need to accumulate a range. */
+ /* Mod 0 is undefined. Return undefined. */
if (wide_int_range_zero_p (rh_lb, rh_ub, TYPE_PRECISION (type)))
- return true;
+ return irange ();
wide_int_range_trunc_mod (new_lb, new_ub, s, TYPE_PRECISION (type),
lh_lb, lh_ub, rh_lb, rh_ub);
+ irange r;
accumulate_range (r, type, new_lb, new_ub);
- return true;
+ return r;
}
class operator_logical_not : public range_operator
{
public:
- virtual bool fold_range (irange &r, tree type, const irange &lh, const irange &rh) const;
- virtual bool op1_range (irange &r, tree type, const irange &lhs,
- const irange &op2) const;
+ virtual irange fold_range (tree type,
+ const irange &lh, const irange &rh) const;
+ virtual bool op1_range (irange &r, tree type,
+ const irange &lhs, const irange &op2) const;
} op_logical_not;
@@ -1629,19 +1644,20 @@ public:
b_2 = x_1 < 20 [0,0] = x_1 < 20, false, so x_1 == [20, 255]
which is the result we are looking for.. so.. pass it thru. */
-bool
-operator_logical_not::fold_range (irange &r, tree type, const irange &lh,
+irange
+operator_logical_not::fold_range (tree type, const irange &lh,
const irange &rh ATTRIBUTE_UNUSED) const
{
+ irange r;
if (empty_range_check (r, lh, rh))
- return true;
+ return r;
if (lh.varying_p () || lh.undefined_p ())
r = lh;
else
r = range_invert (lh);
gcc_checking_assert (lh.type() == type);
- return true;
+ return r;
}
bool
@@ -1660,32 +1676,35 @@ operator_logical_not::op1_range (irange &r, tree type ATTRIBUTE_UNUSED,
class operator_bitwise_not : public range_operator
{
public:
- virtual bool fold_range (irange &r, tree type, const irange &lh, const irange &rh) const;
- virtual bool op1_range (irange &r, tree type, const irange &lhs,
- const irange &op2) const;
+ virtual irange fold_range (tree type,
+ const irange &lh, const irange &rh) const;
+ virtual bool op1_range (irange &r, tree type,
+ const irange &lhs, const irange &op2) const;
} op_bitwise_not;
-bool
-operator_bitwise_not::fold_range (irange &r, tree type, const irange &lh,
- const irange &rh) const
+irange
+operator_bitwise_not::fold_range (tree type,
+ const irange &lh, const irange &rh) const
{
+ irange r;
if (empty_range_check (r, lh, rh))
- return true;
+ return r;
// ~X is simply -1 - X.
irange minusone (type,
wi::minus_one (TYPE_PRECISION (type)),
wi::minus_one (TYPE_PRECISION (type)));
- return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, minusone, lh);
-// return op_binary (MINUS_EXPR, r, type, minusone, lh);
+ r = range_op_handler (MINUS_EXPR, type)->fold_range (type, minusone, lh);
+ return r;
}
bool
-operator_bitwise_not::op1_range (irange &r, tree type, const irange &lhs,
- const irange &op2) const
+operator_bitwise_not::op1_range (irange &r, tree type,
+ const irange &lhs, const irange &op2) const
{
// ~X is -1 - X and since bitwise NOT is involutary...do it again.
- return fold_range (r, type, lhs, op2);
+ r = fold_range (type, lhs, op2);
+ return true;
}
@@ -1695,18 +1714,17 @@ operator_bitwise_not::op1_range (irange &r, tree type, const irange &lhs,
class operator_cst : public range_operator
{
public:
- virtual bool fold_range (irange &r, tree type, const irange &op1,
- const irange &op2) const;
+ virtual irange fold_range (tree type,
+ const irange &op1, const irange &op2) const;
} op_integer_cst;
-bool
-operator_cst::fold_range (irange &r, tree type ATTRIBUTE_UNUSED,
+irange
+operator_cst::fold_range (tree type ATTRIBUTE_UNUSED,
const irange &lh,
const irange &rh ATTRIBUTE_UNUSED) const
{
- r = lh;
- return true;
+ return lh;
}
/* ---------------------------------------------------------------------- */
@@ -1715,19 +1733,18 @@ operator_cst::fold_range (irange &r, tree type ATTRIBUTE_UNUSED,
class operator_identity : public range_operator
{
public:
- virtual bool fold_range (irange &r, tree type, const irange &op1,
- const irange &op2) const;
+ virtual irange fold_range (tree type,
+ const irange &op1, const irange &op2) const;
virtual bool op1_range (irange &r, tree type, const irange &lhs,
const irange &op2) const;
} op_identity;
-bool
-operator_identity::fold_range (irange &r, tree type ATTRIBUTE_UNUSED,
+irange
+operator_identity::fold_range (tree type ATTRIBUTE_UNUSED,
const irange &lh,
const irange &rh ATTRIBUTE_UNUSED) const
{
- r = lh;
- return true;
+ return lh;
}
bool
@@ -1745,19 +1762,19 @@ operator_identity::op1_range (irange &r, tree type ATTRIBUTE_UNUSED,
class operator_abs : public range_operator
{
public:
- bool wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const;
+ virtual irange wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs, const irange &op2) const;
} op_abs;
-bool
-operator_abs::wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb ATTRIBUTE_UNUSED,
- const wide_int &rh_ub ATTRIBUTE_UNUSED) const
+irange
+operator_abs::wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb ATTRIBUTE_UNUSED,
+ const wide_int &rh_ub ATTRIBUTE_UNUSED) const
{
wide_int new_lb, new_ub, tmp;
@@ -1766,11 +1783,8 @@ operator_abs::wi_fold (irange &r, tree type,
TYPE_PRECISION (type),
lh_lb, lh_ub,
TYPE_OVERFLOW_UNDEFINED (type)))
- {
- r.union_ (irange (type, new_lb, new_ub));
- return true;
- }
- return false;
+ return irange (type, new_lb, new_ub);
+ return irange (type);
}
@@ -1801,16 +1815,16 @@ operator_abs::op1_range (irange &r, tree type,
class operator_absu : public range_operator
{
public:
- bool wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const;
+ virtual irange wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_absu;
-bool
-operator_absu::wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb ATTRIBUTE_UNUSED,
- const wide_int &rh_ub ATTRIBUTE_UNUSED) const
+irange
+operator_absu::wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb ATTRIBUTE_UNUSED,
+ const wide_int &rh_ub ATTRIBUTE_UNUSED) const
{
wide_int new_lb, new_ub;
@@ -1840,58 +1854,65 @@ operator_absu::wi_fold (irange &r, tree type,
// r.union_ (irange (unsigned_type_for (type), new_lb, new_ub));
gcc_checking_assert (TYPE_UNSIGNED (type));
- r.union_ (irange (type, new_lb, new_ub));
- return true;
+ return irange (type, new_lb, new_ub);
}
class operator_negate : public range_operator
{
public:
- virtual bool fold_range (irange &r, tree type, const irange &op1,
- const irange &op2) const;
+ virtual irange fold_range (tree type,
+ const irange &op1, const irange &op2) const;
virtual bool op1_range (irange &r, tree type, const irange &lhs,
- const irange &op2) const
- { return fold_range (r, type, lhs, op2); } // NEGATE is involutory :-P.
+ const irange &op2) const;
} op_negate;
/* Return the negated range of lh with the type of rh. */
-bool
-operator_negate::fold_range (irange &r, tree type,
+irange
+operator_negate::fold_range (tree type,
const irange &lh, const irange &rh) const
{
+ irange r;
if (empty_range_check (r, lh, rh))
- return true;
+ return r;
// -X is simply 0 - X.
- return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, range_zero (type),
- lh);
+ return
+ range_op_handler (MINUS_EXPR, type)->fold_range (type,
+ range_zero (type), lh);
+}
+
+bool
+operator_negate::op1_range (irange &r, tree type,
+ const irange &lhs, const irange &op2) const
+{
+ // NEGATE is involutory.
+ r = fold_range (type, lhs, op2);
+ return true;
}
class operator_addr_expr : public range_operator
{
public:
- virtual bool fold_range (irange &r, tree type, const irange &op1,
- const irange &op2) const;
+ virtual irange fold_range (tree type,
+ const irange &op1, const irange &op2) const;
virtual bool op1_range (irange &r, tree type, const irange &lhs,
- const irange &op2) const;
+ const irange &op2) const;
} op_addr;
-bool
-operator_addr_expr::fold_range (irange &r, tree type, const irange &lh,
- const irange &rh) const
+irange
+operator_addr_expr::fold_range (tree type,
+ const irange &lh, const irange &rh) const
{
+ irange r;
if (empty_range_check (r, lh, rh))
- return true;
+ return r;
// Return a non-null pointer of the LHS type (passed in op2)
if (lh.zero_p ())
- r = range_zero (type);
- else
- if (!lh.contains_p (build_zero_cst (lh.type ())))
- r = range_nonzero (type);
- else
- return false;
- return true;
+ return range_zero (type);
+ if (!lh.contains_p (build_zero_cst (lh.type ())))
+ return range_nonzero (type);
+ return irange (type);
}
// The same functionality for fold() applies to op1_range...
@@ -1900,7 +1921,8 @@ bool
operator_addr_expr::op1_range (irange &r, tree type, const irange &lhs,
const irange &op2) const
{
- return operator_addr_expr::fold_range (r, type, lhs, op2);
+ r = operator_addr_expr::fold_range (type, lhs, op2);
+ return true;
}
// ----------------------------------------------------------------------
@@ -1910,16 +1932,16 @@ operator_addr_expr::op1_range (irange &r, tree type, const irange &lhs,
class pointer_plus_operator : public range_operator
{
public:
- virtual bool wi_fold (irange &r, tree type,
+ virtual irange wi_fold (tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_pointer_plus;
-bool
-pointer_plus_operator::wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const
+irange
+pointer_plus_operator::wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const
{
unsigned prec = lh_lb.get_precision ();
signop sign = TYPE_SIGN (type);
@@ -1944,13 +1966,11 @@ pointer_plus_operator::wi_fold (irange &r, tree type,
&& !TYPE_OVERFLOW_WRAPS (type)
&& (flag_delete_null_pointer_checks
|| !wi::sign_mask (rh_ub)))
- r.union_ (range_nonzero (type));
- else if (wide_int_range_zero_p (lh_lb, lh_ub, prec)
- && wide_int_range_zero_p (rh_lb, rh_ub, prec))
- r.union_ (range_zero (type));
- else
- r.set_varying (type);
- return true;
+ return range_nonzero (type);
+ if (wide_int_range_zero_p (lh_lb, lh_ub, prec)
+ && wide_int_range_zero_p (rh_lb, rh_ub, prec))
+ return range_zero (type);
+ return irange (type);
}
// ---------------------------------------------------------------------------
@@ -1958,14 +1978,14 @@ pointer_plus_operator::wi_fold (irange &r, tree type,
class pointer_min_max_operator : public range_operator
{
public:
- virtual bool wi_fold (irange &r, tree type,
+ virtual irange wi_fold (tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_ptr_min_max;
-bool
-pointer_min_max_operator::wi_fold (irange &r, tree type,
+irange
+pointer_min_max_operator::wi_fold (tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
const wide_int &rh_lb,
@@ -1981,13 +2001,11 @@ pointer_min_max_operator::wi_fold (irange &r, tree type,
if (!wide_int_range_includes_zero_p (lh_lb, lh_ub, sign)
&& !wide_int_range_includes_zero_p (rh_lb, rh_ub, sign))
- r.union_ (range_nonzero (type));
- else if (wide_int_range_zero_p (lh_lb, lh_ub, prec)
- && wide_int_range_zero_p (rh_lb, rh_ub, prec))
- r.union_ (range_zero (type));
- else
- r.set_varying (type);
- return true;
+ return range_nonzero (type);
+ if (wide_int_range_zero_p (lh_lb, lh_ub, prec)
+ && wide_int_range_zero_p (rh_lb, rh_ub, prec))
+ return range_zero (type);
+ return irange (type);
}
// ---------------------------------------------------------------------------
@@ -1995,14 +2013,14 @@ pointer_min_max_operator::wi_fold (irange &r, tree type,
class pointer_and_operator : public range_operator
{
public:
- virtual bool wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const;
+ virtual irange wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_pointer_and;
-bool
-pointer_and_operator::wi_fold (irange &r, tree type,
+irange
+pointer_and_operator::wi_fold (tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb, const wide_int &rh_ub) const
{
@@ -2014,13 +2032,12 @@ pointer_and_operator::wi_fold (irange &r, tree type,
if (!wide_int_range_includes_zero_p (lh_lb, lh_ub, sign)
&& !wide_int_range_includes_zero_p (rh_lb, rh_ub, sign))
- r.union_ (range_nonzero (type));
- else if (wide_int_range_zero_p (lh_lb, lh_ub, prec)
- || wide_int_range_zero_p (lh_lb, lh_ub, prec))
- r.union_ (range_zero (type));
- else
- r.set_varying (type);
- return true;
+ return range_nonzero (type);
+ if (wide_int_range_zero_p (lh_lb, lh_ub, prec)
+ || wide_int_range_zero_p (lh_lb, lh_ub, prec))
+ return range_zero (type);
+
+ return irange (type);
}
@@ -2030,16 +2047,16 @@ pointer_and_operator::wi_fold (irange &r, tree type,
class pointer_or_operator : public range_operator
{
public:
- virtual bool wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const;
+ virtual irange wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_pointer_or;
-bool
-pointer_or_operator::wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const
+irange
+pointer_or_operator::wi_fold (tree type,
+ const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const
{
unsigned prec = lh_lb.get_precision ();
signop sign = TYPE_SIGN (type);
@@ -2049,13 +2066,11 @@ pointer_or_operator::wi_fold (irange &r, tree type,
if (!wide_int_range_includes_zero_p (lh_lb, lh_ub, sign)
&& !wide_int_range_includes_zero_p (rh_lb, rh_ub, sign))
- r.union_ (range_nonzero (type));
- else if (wide_int_range_zero_p (lh_lb, lh_ub, prec)
- && wide_int_range_zero_p (rh_lb, rh_ub, prec))
- r.union_ (range_zero (type));
- else
- r.set_varying (type);
- return true;
+ return range_nonzero (type);
+ if (wide_int_range_zero_p (lh_lb, lh_ub, prec)
+ && wide_int_range_zero_p (rh_lb, rh_ub, prec))
+ return range_zero (type);
+ return irange (type);
}
diff --git a/gcc/range-op.h b/gcc/range-op.h
index a2b110e72ef..fb950c4500b 100644
--- a/gcc/range-op.h
+++ b/gcc/range-op.h
@@ -46,29 +46,27 @@ along with GCC; see the file COPYING3. If not see
class range_operator
{
public:
+ // Perform this operation on 2 sub ranges, return the result as a range of TYPE.
+ virtual irange wi_fold (tree type, const wide_int &lh_lb, const wide_int &lh_ub,
+ const wide_int &rh_lb, const wide_int &rh_ub) const;
+
// Set a range based on this operation between 2 operands.
// TYPE is the expected type of the range.
- // Return the TRUE if a valid range is created.
- virtual bool fold_range (irange &r, tree type, const irange &op1,
- const irange &op2) const;
+ virtual irange fold_range (tree type, const irange &lh,
+ const irange &rh) const;
// Set the range for op? in the general case. LHS is the range for
// the LHS of the expression, OP[12]is the range for the other
// TYPE is the expected type of the range.
// operand, and the result is returned in R.
- // Return TRUE if the operation could be performed and the range is
- // valid.
+ // Return TRUE if the operation is performed and a valid range is available.
// ie [LHS] = ??? + OP2
// is re-formed as R = [LHS] - OP2.
virtual bool op1_range (irange &r, tree type, const irange &lhs,
- const irange &op2) const;
+ const irange &op2) const;
virtual bool op2_range (irange &r, tree type, const irange &lhs,
- const irange &op1) const;
+ const irange &op1) const;
- // Perform this operation on 2 sub ranges, accumulating the result into R.
- virtual bool wi_fold (irange &r, tree type,
- const wide_int &lh_lb, const wide_int &lh_ub,
- const wide_int &rh_lb, const wide_int &rh_ub) const;
};
extern range_operator *range_op_handler(enum tree_code code, tree type);
diff --git a/gcc/ssa-range-cache.cc b/gcc/ssa-range-cache.cc
index 43be4bde056..d9de7f66e10 100644
--- a/gcc/ssa-range-cache.cc
+++ b/gcc/ssa-range-cache.cc
@@ -304,7 +304,7 @@ block_range_cache::set_bb_varying (tree name, const basic_block bb)
return get_block_ranges (name).set_bb_varying (bb);
}
-// Return the range for NAME on entry to BB in R. return true if here is one.
+// Return the range for NAME on entry to BB in R. Return true if here is one.
bool
block_range_cache::get_bb_range (irange &r, tree name, const basic_block bb)
@@ -419,10 +419,10 @@ ssa_global_cache::get_global_range (irange &r, tree name) const
return true;
}
-// Set the range for NAME to R in the glonbal cache.
+// Set the range for NAME to R in the global cache.
void
-ssa_global_cache::set_global_range (tree name, const irange& r)
+ssa_global_cache::set_global_range (tree name, const irange &r)
{
unsigned v = SSA_NAME_VERSION (name);
if (v >= m_tab.length ())
@@ -513,9 +513,9 @@ gori_cache::dump_block (FILE *f, basic_block bb)
}
-// Return a static range for NAMe on entry to basic block BB in R.
-// If calc is true, Fill any cache entries required between BB and the Def
-// block for NAME. Otherwise, return false if the cache is empty
+// Return a static range for NAME on entry to basic block BB in R.
+// If calc is true, Fill any cache entries required between BB and the def
+// block for NAME. Otherwise, return false if the cache is empty.
bool
gori_cache::block_range (irange &r, basic_block bb, tree name, bool calc)
diff --git a/gcc/ssa-range-gori.cc b/gcc/ssa-range-gori.cc
index fc13d2a3283..7278553f70a 100644
--- a/gcc/ssa-range-gori.cc
+++ b/gcc/ssa-range-gori.cc
@@ -471,7 +471,7 @@ gori_map::dump(FILE *f)
}
}
-// Set range from an SSA_NAME's available range. If there is no
+// Return a range from an SSA_NAME's available range. If there is no
// available range, build a range for its entire domain.
irange
diff --git a/gcc/ssa-range.cc b/gcc/ssa-range.cc
index 3e1ce85966c..9a1dc15b097 100644
--- a/gcc/ssa-range.cc
+++ b/gcc/ssa-range.cc
@@ -387,7 +387,8 @@ ssa_ranger::range_on_edge (irange &r, edge e, tree name)
gcc_checking_assert (valid_ssa_p (name));
range_on_exit (r, e->src, name);
- gcc_checking_assert (r.undefined_p () || r.type() == TREE_TYPE (name));
+ gcc_checking_assert (r.undefined_p ()
+ || types_compatible_p (r.type(), TREE_TYPE (name)));
// Check to see if NAME is defined on edge e.
if (outgoing_edge_range_p (edge_range, e, name, &r))
@@ -509,7 +510,8 @@ ssa_ranger::range_on_exit (irange &r, basic_block bb, tree name)
range_on_entry (r, bb, name);
else
gcc_assert (range_of_expr (r, name, s));
- gcc_checking_assert (r.undefined_p () || r.type() == TREE_TYPE (name));
+ gcc_checking_assert (r.undefined_p ()
+ || types_compatible_p (r.type(), TREE_TYPE (name)));
}
// Calculate a range for range_op statement S given RANGE1 and RANGE2 and
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index d47712fa2c6..edc08892449 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -2385,7 +2385,7 @@ range_ops_fold_binary_expr (value_range_base *vr,
const value_range_base *vr0_,
const value_range_base *vr1_)
{
- /* Mimic any behavior users of extract_range_from_unary_expr may
+ /* Mimic any behavior users of extract_range_from_binary_expr may
expect. */
range_operator *op = range_op_handler (code, expr_type);
if (!op)
@@ -2419,16 +2419,7 @@ range_ops_fold_binary_expr (value_range_base *vr,
/* Do the range-ops dance. */
value_range_base n0 = normalize_for_range_ops (vr0);
value_range_base n1 = normalize_for_range_ops (vr1);
-#if USE_IRANGE
- irange ir;
- if (op->fold_range (ir, expr_type, n0, n1))
- *vr = ir;
- else
- vr->set_varying (expr_type);
-#else
- if (!op->fold_range (*vr, expr_type, n0, n1))
- vr->set_varying (expr_type);
-#endif
+ *vr = op->fold_range (expr_type, n0, n1);
}
/* Fold a unary expression of a value_range with range-ops. */
@@ -2486,16 +2477,7 @@ range_ops_fold_unary_expr (value_range_base *vr,
/* Do the range-ops dance. */
value_range_base n0 = normalize_for_range_ops (*vr0);
value_range_base n1 (expr_type);
-#if USE_IRANGE
- irange ir;
- if (op->fold_range (ir, expr_type, n0, n1))
- *vr = ir;
- else
- vr->set_varying (expr_type);
-#else
- if (!op->fold_range (*vr, expr_type, n0, n1))
- vr->set_varying (expr_type);
-#endif
+ *vr = op->fold_range (expr_type, n0, n1);
}
/* Generic folding of a binary expression between two value_ranges.
@@ -2524,7 +2506,7 @@ range_fold_binary_expr (value_range_base *vr,
{
value_range_base old;
extract_range_from_binary_expr (&old, code, expr_type, vr0, vr1);
- if (flag_ranges_mode & RANGES_CHECKING)
+ if (flag_ranges_mode == RANGES_CHECKING)
assert_compare_value_ranges (&old, vr, code, vr0, vr1);
else
*vr = old;
@@ -2554,7 +2536,7 @@ range_fold_unary_expr (value_range_base *vr,
{
value_range_base old;
extract_range_from_unary_expr (&old, code, expr_type, vr0, vr0_type);
- if (flag_ranges_mode & RANGES_CHECKING)
+ if (flag_ranges_mode == RANGES_CHECKING)
{
value_range_base vr1 (expr_type);
assert_compare_value_ranges (&old, vr, code, vr0, &vr1);
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index c37c007606d..04e7573e3ad 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -3337,10 +3337,8 @@ range_misc::simplify_min_or_max_using_ranges (gimple_stmt_iterator *gsi,
tree t;
irange res;
enum tree_code code = gimple_assign_rhs_code (stmt);
- if (!range_op_handler (code, TREE_TYPE (op0))->fold_range (res,
- TREE_TYPE (op0),
- ir0, ir1))
- res.set_varying (TREE_TYPE (op0));
+ res = range_op_handler (code, TREE_TYPE (op0))->fold_range (TREE_TYPE (op0),
+ ir0, ir1);
if (res == ir0)
t = op0;