]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Implement new range-ops API.
authorAldy Hernandez <aldyh@gcc.gnu.org>
Wed, 21 Aug 2019 19:27:27 +0000 (19:27 +0000)
committerAldy Hernandez <aldyh@gcc.gnu.org>
Wed, 21 Aug 2019 19:27:27 +0000 (19:27 +0000)
From-SVN: r274808

gcc/grange.cc
gcc/range-op.cc
gcc/range-op.h
gcc/ssa-range-cache.cc
gcc/ssa-range-gori.cc
gcc/ssa-range.cc
gcc/tree-vrp.c
gcc/vr-values.c

index fb9b01909af29ee009edd0b35b8789f6149153d4..6c6bdec7d485c92952f7b5faf200ab32f2e35444 100644 (file)
@@ -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.
index 0d36e384cf24b2c40541e2903718f8271be992f7..cf70f097add458e92131a368bd74d56e33b36b5b 100644 (file)
@@ -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 irangeop2) 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 irangeop2) 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);
 }
 
 
index a2b110e72efc0f0fb93628330acb53ac9f1ca3f2..fb950c4500bb45d5c3a2bd35ff1d33e1a9b356b5 100644 (file)
@@ -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);
index 43be4bde056342a9ed804817459b2ab7aa9348c3..d9de7f66e1087745000b3d4b7fc22702886baf3b 100644 (file)
@@ -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 iranger)
+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)
index fc13d2a3283af11dc829570823daddb0a3051c64..7278553f70a71acaa2b448e66c3046b501b4f420 100644 (file)
@@ -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
index 3e1ce85966cd9346cc588c314cb4bb39ee48924b..9a1dc15b097b636a45e8d89ae17dcff2d9cb7c1b 100644 (file)
@@ -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 
index d47712fa2c67d660c1e828eb7989469a1a059bda..edc08892449fea754105b4e35210f885e0b0b0f9 100644 (file)
@@ -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);
index c37c007606d98e635acc1ba9a0a493f4b5b348e2..04e7573e3ad86444449cdddcf568d3bb6dc17b3d 100644 (file)
@@ -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;