]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/tree-vrp.c
Merge from trunk.
[thirdparty/gcc.git] / gcc / tree-vrp.c
index 6ed353f07de7f7ea586ab2290fe5c687809f4f01..2da3b2b3f75710c39fd477334996ad6e2970f319 100644 (file)
@@ -25,8 +25,23 @@ along with GCC; see the file COPYING3.  If not see
 #include "ggc.h"
 #include "flags.h"
 #include "tree.h"
+#include "stor-layout.h"
+#include "calls.h"
 #include "basic-block.h"
-#include "tree-flow.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "gimple-walk.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "stringpool.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-ssa-loop.h"
+#include "tree-into-ssa.h"
+#include "tree-ssa.h"
 #include "tree-pass.h"
 #include "tree-dump.h"
 #include "gimple-pretty-print.h"
@@ -36,14 +51,13 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-scalar-evolution.h"
 #include "tree-ssa-propagate.h"
 #include "tree-chrec.h"
-#include "gimple-fold.h"
+#include "tree-ssa-threadupdate.h"
 #include "expr.h"
 #include "optabs.h"
+#include "tree-ssa-threadedge.h"
+#include "wide-int.h"
 
 
-/* Type of value ranges.  See value_range_d for a description of these
-   types.  */
-enum value_range_type { VR_UNDEFINED, VR_RANGE, VR_ANTI_RANGE, VR_VARYING };
 
 /* Range of values that can be associated with an SSA_NAME after VRP
    has executed.  */
@@ -884,8 +898,8 @@ static inline bool
 range_int_cst_singleton_p (value_range_t *vr)
 {
   return (range_int_cst_p (vr)
-         && !TREE_OVERFLOW (vr->min)
-         && !TREE_OVERFLOW (vr->max)
+         && !is_overflow_infinity (vr->min)
+         && !is_overflow_infinity (vr->max)
          && tree_int_cst_equal (vr->min, vr->max));
 }
 
@@ -1041,7 +1055,7 @@ gimple_assign_nonzero_warnv_p (gimple stmt, bool *strict_overflow_p)
     }
 }
 
-/* Return true if STMT is know to to compute a non-zero value.
+/* Return true if STMT is known to compute a non-zero value.
    If the return value is based on the assumption that signed overflow is
    undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change
    *STRICT_OVERFLOW_P.*/
@@ -1054,7 +1068,19 @@ gimple_stmt_nonzero_warnv_p (gimple stmt, bool *strict_overflow_p)
     case GIMPLE_ASSIGN:
       return gimple_assign_nonzero_warnv_p (stmt, strict_overflow_p);
     case GIMPLE_CALL:
-      return gimple_alloca_call_p (stmt);
+      {
+       tree fndecl = gimple_call_fndecl (stmt);
+       if (!fndecl) return false;
+       if (flag_delete_null_pointer_checks && !flag_check_new
+           && DECL_IS_OPERATOR_NEW (fndecl)
+           && !TREE_NOTHROW (fndecl))
+         return true;
+       if (flag_delete_null_pointer_checks && 
+           lookup_attribute ("returns_nonnull",
+                             TYPE_ATTRIBUTES (gimple_call_fntype (stmt))))
+         return true;
+       return gimple_alloca_call_p (stmt);
+      }
     default:
       gcc_unreachable ();
     }
@@ -1116,15 +1142,7 @@ operand_less_p (tree val, tree val2)
 {
   /* LT is folded faster than GE and others.  Inline the common case.  */
   if (TREE_CODE (val) == INTEGER_CST && TREE_CODE (val2) == INTEGER_CST)
-    {
-      if (TYPE_UNSIGNED (TREE_TYPE (val)))
-       return INT_CST_LT_UNSIGNED (val, val2);
-      else
-       {
-         if (INT_CST_LT (val, val2))
-           return 1;
-       }
-    }
+    return INT_CST_LT (val, val2);
   else
     {
       tree tcmp;
@@ -1444,24 +1462,6 @@ value_range_nonnegative_p (value_range_t *vr)
   return false;
 }
 
-/* Return true if T, an SSA_NAME, is known to be nonnegative.  Return
-   false otherwise or if no value range information is available.  */
-
-bool
-ssa_name_nonnegative_p (const_tree t)
-{
-  value_range_t *vr = get_value_range (t);
-
-  if (INTEGRAL_TYPE_P (t)
-      && TYPE_UNSIGNED (t))
-    return true;
-
-  if (!vr)
-    return false;
-
-  return value_range_nonnegative_p (vr);
-}
-
 /* If *VR has a value rante that is a single constant value return that,
    otherwise return NULL_TREE.  */
 
@@ -1614,10 +1614,8 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
       /* Make sure to not set TREE_OVERFLOW on the final type
         conversion.  We are willingly interpreting large positive
         unsigned values as negative singed values here.  */
-      min = force_fit_type_double (TREE_TYPE (var), tree_to_double_int (min),
-                                  0, false);
-      max = force_fit_type_double (TREE_TYPE (var), tree_to_double_int (max),
-                                  0, false);
+      min = force_fit_type (TREE_TYPE (var), wi::to_widest (min), 0, false);
+      max = force_fit_type (TREE_TYPE (var), wi::to_widest (max), 0, false);
 
       /* We can transform a max, min range to an anti-range or
          vice-versa.  Use set_and_canonicalize_value_range which does
@@ -1721,7 +1719,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
         all should be optimized away above us.  */
       if ((cond_code == LT_EXPR
           && compare_values (max, min) == 0)
-         || (CONSTANT_CLASS_P (max) && TREE_OVERFLOW (max)))
+         || is_overflow_infinity (max))
        set_value_range_to_varying (vr_p);
       else
        {
@@ -1761,7 +1759,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
         all should be optimized away above us.  */
       if ((cond_code == GT_EXPR
           && compare_values (min, max) == 0)
-         || (CONSTANT_CLASS_P (min) && TREE_OVERFLOW (min)))
+         || is_overflow_infinity (min))
        set_value_range_to_varying (vr_p);
       else
        {
@@ -1873,6 +1871,10 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2)
     /* If the singed operation wraps then int_const_binop has done
        everything we want.  */
     ;
+  /* Signed division of -1/0 overflows and by the time it gets here
+     returns NULL_TREE.  */
+  else if (!res)
+    return NULL_TREE;
   else if ((TREE_OVERFLOW (res)
            && !TREE_OVERFLOW (val1)
            && !TREE_OVERFLOW (val2))
@@ -1964,54 +1966,42 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2)
 }
 
 
-/* For range VR compute two double_int bitmasks.  In *MAY_BE_NONZERO
+/* For range VR compute two wide_int bitmasks.  In *MAY_BE_NONZERO
    bitmask if some bit is unset, it means for all numbers in the range
    the bit is 0, otherwise it might be 0 or 1.  In *MUST_BE_NONZERO
    bitmask if some bit is set, it means for all numbers in the range
    the bit is 1, otherwise it might be 0 or 1.  */
 
 static bool
-zero_nonzero_bits_from_vr (value_range_t *vr,
-                          double_int *may_be_nonzero,
-                          double_int *must_be_nonzero)
+zero_nonzero_bits_from_vr (const tree expr_type,
+                          value_range_t *vr,
+                          wide_int *may_be_nonzero,
+                          wide_int *must_be_nonzero)
 {
-  *may_be_nonzero = double_int_minus_one;
-  *must_be_nonzero = double_int_zero;
+  *may_be_nonzero = wi::minus_one (TYPE_PRECISION (expr_type));
+  *must_be_nonzero = wi::zero (TYPE_PRECISION (expr_type));
   if (!range_int_cst_p (vr)
-      || TREE_OVERFLOW (vr->min)
-      || TREE_OVERFLOW (vr->max))
+      || is_overflow_infinity (vr->min)
+      || is_overflow_infinity (vr->max))
     return false;
 
   if (range_int_cst_singleton_p (vr))
     {
-      *may_be_nonzero = tree_to_double_int (vr->min);
+      *may_be_nonzero = vr->min;
       *must_be_nonzero = *may_be_nonzero;
     }
   else if (tree_int_cst_sgn (vr->min) >= 0
           || tree_int_cst_sgn (vr->max) < 0)
     {
-      double_int dmin = tree_to_double_int (vr->min);
-      double_int dmax = tree_to_double_int (vr->max);
-      double_int xor_mask = dmin ^ dmax;
-      *may_be_nonzero = dmin | dmax;
-      *must_be_nonzero = dmin & dmax;
-      if (xor_mask.high != 0)
-       {
-         unsigned HOST_WIDE_INT mask
-             = ((unsigned HOST_WIDE_INT) 1
-                << floor_log2 (xor_mask.high)) - 1;
-         may_be_nonzero->low = ALL_ONES;
-         may_be_nonzero->high |= mask;
-         must_be_nonzero->low = 0;
-         must_be_nonzero->high &= ~mask;
-       }
-      else if (xor_mask.low != 0)
+      wide_int xor_mask = wi::bit_xor (vr->min, vr->max);
+      *may_be_nonzero = wi::bit_or (vr->min, vr->max);
+      *must_be_nonzero = wi::bit_and (vr->min, vr->max);
+      if (xor_mask != 0)
        {
-         unsigned HOST_WIDE_INT mask
-             = ((unsigned HOST_WIDE_INT) 1
-                << floor_log2 (xor_mask.low)) - 1;
-         may_be_nonzero->low |= mask;
-         must_be_nonzero->low &= ~mask;
+         wide_int mask = wi::mask (wi::floor_log2 (xor_mask), false,
+                                   (*may_be_nonzero).get_precision ());
+         *may_be_nonzero = (*may_be_nonzero) | mask;
+         *must_be_nonzero = (*must_be_nonzero).and_not (mask);
        }
     }
 
@@ -2043,16 +2033,12 @@ ranges_from_anti_range (value_range_t *ar,
     {
       vr0->type = VR_RANGE;
       vr0->min = vrp_val_min (type);
-      vr0->max
-       = double_int_to_tree (type,
-                             tree_to_double_int (ar->min) - double_int_one);
+      vr0->max = wide_int_to_tree (type, wi::sub (ar->min, 1));
     }
   if (!vrp_val_is_max (ar->max))
     {
       vr1->type = VR_RANGE;
-      vr1->min
-       = double_int_to_tree (type,
-                             tree_to_double_int (ar->max) + double_int_one);
+      vr1->min = wide_int_to_tree (type, wi::add (ar->max, 1));
       vr1->max = vrp_val_max (type);
     }
   if (vr0->type == VR_UNDEFINED)
@@ -2218,28 +2204,6 @@ extract_range_from_multiplicative_op_1 (value_range_t *vr,
     set_value_range (vr, type, min, max, NULL);
 }
 
-/* Some quadruple precision helpers.  */
-static int
-quad_int_cmp (double_int l0, double_int h0,
-             double_int l1, double_int h1, bool uns)
-{
-  int c = h0.cmp (h1, uns);
-  if (c != 0) return c;
-  return l0.ucmp (l1);
-}
-
-static void
-quad_int_pair_sort (double_int *l0, double_int *h0,
-                   double_int *l1, double_int *h1, bool uns)
-{
-  if (quad_int_cmp (*l0, *h0, *l1, *h1, uns) > 0)
-    {
-      double_int tmp;
-      tmp = *l0; *l0 = *l1; *l1 = tmp;
-      tmp = *h0; *h0 = *h1; *h1 = tmp;
-    }
-}
-
 /* Extract range information from a binary operation CODE based on
    the ranges of each of its operands, *VR0 and *VR1 with resulting
    type EXPR_TYPE.  The resulting range is stored in *VR.  */
@@ -2411,43 +2375,36 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
       /* If we have a PLUS_EXPR with two VR_RANGE integer constant
          ranges compute the precise range for such case if possible.  */
       if (range_int_cst_p (&vr0)
-         && range_int_cst_p (&vr1)
-         /* We need as many bits as the possibly unsigned inputs.  */
-         && TYPE_PRECISION (expr_type) <= HOST_BITS_PER_DOUBLE_INT)
-       {
-         double_int min0 = tree_to_double_int (vr0.min);
-         double_int max0 = tree_to_double_int (vr0.max);
-         double_int min1 = tree_to_double_int (vr1.min);
-         double_int max1 = tree_to_double_int (vr1.max);
-         bool uns = TYPE_UNSIGNED (expr_type);
-         double_int type_min
-           = double_int::min_value (TYPE_PRECISION (expr_type), uns);
-         double_int type_max
-           = double_int::max_value (TYPE_PRECISION (expr_type), uns);
-         double_int dmin, dmax;
+         && range_int_cst_p (&vr1))
+       {
+         signop sgn = TYPE_SIGN (expr_type);
+         unsigned int prec = TYPE_PRECISION (expr_type);
+         wide_int type_min = wi::min_value (TYPE_PRECISION (expr_type), sgn);
+         wide_int type_max = wi::max_value (TYPE_PRECISION (expr_type), sgn);
+         wide_int wmin, wmax;
          int min_ovf = 0;
          int max_ovf = 0;
 
          if (code == PLUS_EXPR)
            {
-             dmin = min0 + min1;
-             dmax = max0 + max1;
-
-             /* Check for overflow in double_int.  */
-             if (min1.cmp (double_int_zero, uns) != dmin.cmp (min0, uns))
-               min_ovf = min0.cmp (dmin, uns);
-             if (max1.cmp (double_int_zero, uns) != dmax.cmp (max0, uns))
-               max_ovf = max0.cmp (dmax, uns);
+             wmin = wi::add (vr0.min, vr1.min);
+             wmax = wi::add (vr0.max, vr1.max);
+
+             /* Check for overflow.  */
+             if (wi::cmp (vr1.min, 0, sgn) != wi::cmp (wmin, vr0.min, sgn))
+               min_ovf = wi::cmp (vr0.min, wmin, sgn);
+             if (wi::cmp (vr1.max, 0, sgn) != wi::cmp (wmax, vr0.max, sgn))
+               max_ovf = wi::cmp (vr0.max, wmax, sgn);
            }
          else /* if (code == MINUS_EXPR) */
            {
-             dmin = min0 - max1;
-             dmax = max0 - min1;
+             wmin = wi::sub (vr0.min, vr1.max);
+             wmax = wi::sub (vr0.max, vr1.min);
 
-             if (double_int_zero.cmp (max1, uns) != dmin.cmp (min0, uns))
-               min_ovf = min0.cmp (max1, uns);
-             if (double_int_zero.cmp (min1, uns) != dmax.cmp (max0, uns))
-               max_ovf = max0.cmp (min1, uns);
+             if (wi::cmp (0, vr1.max, sgn) != wi::cmp (wmin, vr0.min, sgn))
+               min_ovf = wi::cmp (vr0.min, vr1.max, sgn);
+             if (wi::cmp (0, vr1.min, sgn) != wi::cmp (wmax, vr0.max, sgn))
+               max_ovf = wi::cmp (vr0.max, vr1.min, sgn);
            }
 
          /* For non-wrapping arithmetic look at possibly smaller
@@ -2455,24 +2412,24 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
          if (!TYPE_OVERFLOW_WRAPS (expr_type))
            {
              if (vrp_val_min (expr_type))
-               type_min = tree_to_double_int (vrp_val_min (expr_type));
+               type_min = vrp_val_min (expr_type);
              if (vrp_val_max (expr_type))
-               type_max = tree_to_double_int (vrp_val_max (expr_type));
+               type_max = vrp_val_max (expr_type);
            }
 
          /* Check for type overflow.  */
          if (min_ovf == 0)
            {
-             if (dmin.cmp (type_min, uns) == -1)
+             if (wi::cmp (wmin, type_min, sgn) == -1)
                min_ovf = -1;
-             else if (dmin.cmp (type_max, uns) == 1)
+             else if (wi::cmp (wmin, type_max, sgn) == 1)
                min_ovf = 1;
            }
          if (max_ovf == 0)
            {
-             if (dmax.cmp (type_min, uns) == -1)
+             if (wi::cmp (wmax, type_min, sgn) == -1)
                max_ovf = -1;
-             else if (dmax.cmp (type_max, uns) == 1)
+             else if (wi::cmp (wmax, type_max, sgn) == 1)
                max_ovf = 1;
            }
 
@@ -2480,16 +2437,14 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
            {
              /* If overflow wraps, truncate the values and adjust the
                 range kind and bounds appropriately.  */
-             double_int tmin
-               = dmin.ext (TYPE_PRECISION (expr_type), uns);
-             double_int tmax
-               = dmax.ext (TYPE_PRECISION (expr_type), uns);
+             wide_int tmin = wide_int::from (wmin, prec, sgn);
+             wide_int tmax = wide_int::from (wmax, prec, sgn);
              if (min_ovf == max_ovf)
                {
                  /* No overflow or both overflow or underflow.  The
                     range kind stays VR_RANGE.  */
-                 min = double_int_to_tree (expr_type, tmin);
-                 max = double_int_to_tree (expr_type, tmax);
+                 min = wide_int_to_tree (expr_type, tmin);
+                 max = wide_int_to_tree (expr_type, tmax);
                }
              else if (min_ovf == -1
                       && max_ovf == 1)
@@ -2503,26 +2458,26 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
                  /* Min underflow or max overflow.  The range kind
                     changes to VR_ANTI_RANGE.  */
                  bool covers = false;
-                 double_int tem = tmin;
+                 wide_int tem = tmin;
                  gcc_assert ((min_ovf == -1 && max_ovf == 0)
                              || (max_ovf == 1 && min_ovf == 0));
                  type = VR_ANTI_RANGE;
-                 tmin = tmax + double_int_one;
-                 if (tmin.cmp (tmax, uns) < 0)
+                 tmin = tmax + 1;
+                 if (wi::cmp (tmin, tmax, sgn) < 0)
                    covers = true;
-                 tmax = tem + double_int_minus_one;
-                 if (tmax.cmp (tem, uns) > 0)
+                 tmax = tem - 1;
+                 if (wi::cmp (tmax, tem, sgn) > 0)
                    covers = true;
                  /* If the anti-range would cover nothing, drop to varying.
                     Likewise if the anti-range bounds are outside of the
                     types values.  */
-                 if (covers || tmin.cmp (tmax, uns) > 0)
+                 if (covers || wi::cmp (tmin, tmax, sgn) > 0)
                    {
                      set_value_range_to_varying (vr);
                      return;
                    }
-                 min = double_int_to_tree (expr_type, tmin);
-                 max = double_int_to_tree (expr_type, tmax);
+                 min = wide_int_to_tree (expr_type, tmin);
+                 max = wide_int_to_tree (expr_type, tmax);
                }
            }
          else
@@ -2535,7 +2490,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
                      && supports_overflow_infinity (expr_type))
                    min = negative_overflow_infinity (expr_type);
                  else
-                   min = double_int_to_tree (expr_type, type_min);
+                   min = wide_int_to_tree (expr_type, type_min);
                }
              else if (min_ovf == 1)
                {
@@ -2543,10 +2498,10 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
                      && supports_overflow_infinity (expr_type))
                    min = positive_overflow_infinity (expr_type);
                  else
-                   min = double_int_to_tree (expr_type, type_max);
+                   min = wide_int_to_tree (expr_type, type_max);
                }
              else
-               min = double_int_to_tree (expr_type, dmin);
+               min = wide_int_to_tree (expr_type, wmin);
 
              if (max_ovf == -1)
                {
@@ -2554,7 +2509,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
                      && supports_overflow_infinity (expr_type))
                    max = negative_overflow_infinity (expr_type);
                  else
-                   max = double_int_to_tree (expr_type, type_min);
+                   max = wide_int_to_tree (expr_type, type_min);
                }
              else if (max_ovf == 1)
                {
@@ -2562,10 +2517,10 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
                      && supports_overflow_infinity (expr_type))
                    max = positive_overflow_infinity (expr_type);
                  else
-                   max = double_int_to_tree (expr_type, type_max);
+                   max = wide_int_to_tree (expr_type, type_max);
                }
              else
-               max = double_int_to_tree (expr_type, dmax);
+               max = wide_int_to_tree (expr_type, wmax);
            }
          if (needs_overflow_infinity (expr_type)
              && supports_overflow_infinity (expr_type))
@@ -2651,97 +2606,84 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
   else if (code == MULT_EXPR)
     {
       /* Fancy code so that with unsigned, [-3,-1]*[-3,-1] does not
-        drop to varying.  */
+        drop to varying.  This test requires 2*prec bits if both
+        operands are signed and 2*prec + 2 bits if either is not.  */
+
+      signop sign = TYPE_SIGN (expr_type);
+      unsigned int prec = TYPE_PRECISION (expr_type);
+      unsigned int prec2 = (prec * 2) + (sign == UNSIGNED ? 2 : 0);
+
       if (range_int_cst_p (&vr0)
          && range_int_cst_p (&vr1)
          && TYPE_OVERFLOW_WRAPS (expr_type))
        {
-         double_int min0, max0, min1, max1, sizem1, size;
-         double_int prod0l, prod0h, prod1l, prod1h,
-                    prod2l, prod2h, prod3l, prod3h;
-         bool uns0, uns1, uns;
-
-         sizem1 = double_int::max_value (TYPE_PRECISION (expr_type), true);
-         size = sizem1 + double_int_one;
+         wide_int sizem1 = wi::mask (prec, false, prec2);
+         wide_int size = sizem1 + 1;
 
-         min0 = tree_to_double_int (vr0.min);
-         max0 = tree_to_double_int (vr0.max);
-         min1 = tree_to_double_int (vr1.min);
-         max1 = tree_to_double_int (vr1.max);
-
-         uns0 = TYPE_UNSIGNED (expr_type);
-         uns1 = uns0;
+         /* Extend the values using the sign of the result to PREC2.
+            From here on out, everthing is just signed math no matter
+            what the input types were.  */ 
+         wide_int min0 = wide_int::from (vr0.min, prec2, sign);
+         wide_int max0 = wide_int::from (vr0.max, prec2, sign);
+         wide_int min1 = wide_int::from (vr1.min, prec2, sign);
+         wide_int max1 = wide_int::from (vr1.max, prec2, sign);
 
          /* Canonicalize the intervals.  */
-         if (TYPE_UNSIGNED (expr_type))
+         if (sign == UNSIGNED)
            {
-             double_int min2 = size - min0;
-             if (!min2.is_zero () && min2.cmp (max0, true) < 0)
+             if (wi::ltu_p (size, min0 + max0))
                {
-                 min0 = -min2;
+                 min0 -= size;
                  max0 -= size;
-                 uns0 = false;
                }
 
-             min2 = size - min1;
-             if (!min2.is_zero () && min2.cmp (max1, true) < 0)
+             if (wi::ltu_p (size, min1 + max1))
                {
-                 min1 = -min2;
+                 min1 -= size;
                  max1 -= size;
-                 uns1 = false;
                }
            }
-         uns = uns0 & uns1;
 
-         bool overflow;
-         prod0l = min0.wide_mul_with_sign (min1, true, &prod0h, &overflow);
-         if (!uns0 && min0.is_negative ())
-           prod0h -= min1;
-         if (!uns1 && min1.is_negative ())
-           prod0h -= min0;
-
-         prod1l = min0.wide_mul_with_sign (max1, true, &prod1h, &overflow);
-         if (!uns0 && min0.is_negative ())
-           prod1h -= max1;
-         if (!uns1 && max1.is_negative ())
-           prod1h -= min0;
-
-         prod2l = max0.wide_mul_with_sign (min1, true, &prod2h, &overflow);
-         if (!uns0 && max0.is_negative ())
-           prod2h -= min1;
-         if (!uns1 && min1.is_negative ())
-           prod2h -= max0;
-
-         prod3l = max0.wide_mul_with_sign (max1, true, &prod3h, &overflow);
-         if (!uns0 && max0.is_negative ())
-           prod3h -= max1;
-         if (!uns1 && max1.is_negative ())
-           prod3h -= max0;
-
-         /* Sort the 4 products.  */
-         quad_int_pair_sort (&prod0l, &prod0h, &prod3l, &prod3h, uns);
-         quad_int_pair_sort (&prod1l, &prod1h, &prod2l, &prod2h, uns);
-         quad_int_pair_sort (&prod0l, &prod0h, &prod1l, &prod1h, uns);
-         quad_int_pair_sort (&prod2l, &prod2h, &prod3l, &prod3h, uns);
-
-         /* Max - min.  */
-         if (prod0l.is_zero ())
+         wide_int prod0 = min0 * min1;
+         wide_int prod1 = min0 * max1;
+         wide_int prod2 = max0 * min1;
+         wide_int prod3 = max0 * max1;
+
+         /* Sort the 4 products so that min is in prod0 and max is in
+            prod3.  */
+         /* min0min1 > max0max1 */
+         if (wi::gts_p (prod0, prod3))
            {
-             prod1l = double_int_zero;
-             prod1h = -prod0h;
+             wide_int tmp = prod3;
+             prod3 = prod0;
+             prod0 = tmp;
            }
-         else
+
+         /* min0max1 > max0min1 */
+         if (wi::gts_p (prod1, prod2))
+           {
+             wide_int tmp = prod2;
+             prod2 = prod1;
+             prod1 = tmp;
+           }
+
+         if (wi::gts_p (prod0, prod1))
+           {
+             wide_int tmp = prod1;
+             prod1 = prod0;
+             prod0 = tmp;
+           }
+
+         if (wi::gts_p (prod2, prod3))
            {
-             prod1l = -prod0l;
-             prod1h = ~prod0h;
+             wide_int tmp = prod3;
+             prod3 = prod2;
+             prod2 = tmp;
            }
-         prod2l = prod3l + prod1l;
-         prod2h = prod3h + prod1h;
-         if (prod2l.ult (prod3l))
-           prod2h += double_int_one; /* carry */
 
-         if (!prod2h.is_zero ()
-             || prod2l.cmp (sizem1, true) >= 0)
+         /* diff = max - min.  */
+         prod2 = prod3 - prod0;
+         if (wi::geu_p (prod2, sizem1))
            {
              /* the range covers all values.  */
              set_value_range_to_varying (vr);
@@ -2750,8 +2692,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
 
          /* The following should handle the wrapping and selecting
             VR_ANTI_RANGE for us.  */
-         min = double_int_to_tree (expr_type, prod0l);
-         max = double_int_to_tree (expr_type, prod3l);
+         min = wide_int_to_tree (expr_type, prod0);
+         max = wide_int_to_tree (expr_type, prod3);
          set_and_canonicalize_value_range (vr, VR_RANGE, min, max, NULL);
          return;
        }
@@ -2798,11 +2740,10 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
              bool saved_flag_wrapv;
              value_range_t vr1p = VR_INITIALIZER;
              vr1p.type = VR_RANGE;
-             vr1p.min
-               = double_int_to_tree (expr_type,
-                                     double_int_one
-                                     .llshift (TREE_INT_CST_LOW (vr1.min),
-                                               TYPE_PRECISION (expr_type)));
+             vr1p.min = (wide_int_to_tree
+                         (expr_type,
+                          wi::set_bit_in_zero (tree_to_shwi (vr1.min),
+                                               TYPE_PRECISION (expr_type))));
              vr1p.max = vr1p.min;
              /* We have to use a wrapping multiply though as signed overflow
                 on lshifts is implementation defined in C89.  */
@@ -2819,34 +2760,34 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
              int prec = TYPE_PRECISION (expr_type);
              int overflow_pos = prec;
              int bound_shift;
-             double_int bound, complement, low_bound, high_bound;
+             wide_int low_bound, high_bound;
              bool uns = TYPE_UNSIGNED (expr_type);
              bool in_bounds = false;
 
              if (!uns)
                overflow_pos -= 1;
 
-             bound_shift = overflow_pos - TREE_INT_CST_LOW (vr1.max);
-             /* If bound_shift == HOST_BITS_PER_DOUBLE_INT, the llshift can
+             bound_shift = overflow_pos - tree_to_shwi (vr1.max);
+             /* If bound_shift == HOST_BITS_PER_WIDE_INT, the llshift can
                 overflow.  However, for that to happen, vr1.max needs to be
                 zero, which means vr1 is a singleton range of zero, which
                 means it should be handled by the previous LSHIFT_EXPR
                 if-clause.  */
-             bound = double_int_one.llshift (bound_shift, prec);
-             complement = ~(bound - double_int_one);
+             wide_int bound = wi::set_bit_in_zero (bound_shift, prec);
+             wide_int complement = ~(bound - 1);
 
              if (uns)
                {
-                 low_bound = bound.zext (prec);
-                 high_bound = complement.zext (prec);
-                 if (tree_to_double_int (vr0.max).ult (low_bound))
+                 low_bound = bound;
+                 high_bound = complement;
+                 if (wi::ltu_p (vr0.max, low_bound))
                    {
                      /* [5, 6] << [1, 2] == [10, 24].  */
                      /* We're shifting out only zeroes, the value increases
                         monotonically.  */
                      in_bounds = true;
                    }
-                 else if (high_bound.ult (tree_to_double_int (vr0.min)))
+                 else if (wi::ltu_p (high_bound, vr0.min))
                    {
                      /* [0xffffff00, 0xffffffff] << [1, 2]
                         == [0xfffffc00, 0xfffffffe].  */
@@ -2858,10 +2799,10 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
              else
                {
                  /* [-1, 1] << [1, 2] == [-4, 4].  */
-                 low_bound = complement.sext (prec);
+                 low_bound = complement;
                  high_bound = bound;
-                 if (tree_to_double_int (vr0.max).slt (high_bound)
-                     && low_bound.slt (tree_to_double_int (vr0.min)))
+                 if (wi::lts_p (vr0.max, high_bound)
+                     && wi::lts_p (low_bound, vr0.min))
                    {
                      /* For non-negative numbers, we're shifting out only
                         zeroes, the value increases monotonically.
@@ -2985,7 +2926,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
       max = fold_unary_to_constant (ABS_EXPR, expr_type, vr1.min);
       if (tree_int_cst_lt (max, vr1.max))
        max = vr1.max;
-      max = int_const_binop (MINUS_EXPR, max, integer_one_node);
+      max = int_const_binop (MINUS_EXPR, max, build_int_cst (TREE_TYPE (max), 1));
       /* If the dividend is non-negative the modulus will be
         non-negative as well.  */
       if (TYPE_UNSIGNED (expr_type)
@@ -2997,21 +2938,22 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
   else if (code == BIT_AND_EXPR || code == BIT_IOR_EXPR || code == BIT_XOR_EXPR)
     {
       bool int_cst_range0, int_cst_range1;
-      double_int may_be_nonzero0, may_be_nonzero1;
-      double_int must_be_nonzero0, must_be_nonzero1;
+      wide_int may_be_nonzero0, may_be_nonzero1;
+      wide_int must_be_nonzero0, must_be_nonzero1;
 
-      int_cst_range0 = zero_nonzero_bits_from_vr (&vr0, &may_be_nonzero0,
+      int_cst_range0 = zero_nonzero_bits_from_vr (expr_type, &vr0,
+                                                 &may_be_nonzero0,
                                                  &must_be_nonzero0);
-      int_cst_range1 = zero_nonzero_bits_from_vr (&vr1, &may_be_nonzero1,
+      int_cst_range1 = zero_nonzero_bits_from_vr (expr_type, &vr1,
+                                                 &may_be_nonzero1,
                                                  &must_be_nonzero1);
 
       type = VR_RANGE;
       if (code == BIT_AND_EXPR)
        {
-         double_int dmax;
-         min = double_int_to_tree (expr_type,
-                                   must_be_nonzero0 & must_be_nonzero1);
-         dmax = may_be_nonzero0 & may_be_nonzero1;
+         min = wide_int_to_tree (expr_type,
+                                 must_be_nonzero0 & must_be_nonzero1);
+         wide_int wmax = may_be_nonzero0 & may_be_nonzero1;
          /* If both input ranges contain only negative values we can
             truncate the result range maximum to the minimum of the
             input range maxima.  */
@@ -3019,28 +2961,23 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
              && tree_int_cst_sgn (vr0.max) < 0
              && tree_int_cst_sgn (vr1.max) < 0)
            {
-             dmax = dmax.min (tree_to_double_int (vr0.max),
-                                    TYPE_UNSIGNED (expr_type));
-             dmax = dmax.min (tree_to_double_int (vr1.max),
-                                    TYPE_UNSIGNED (expr_type));
+             wmax = wi::min (wmax, vr0.max, TYPE_SIGN (expr_type));
+             wmax = wi::min (wmax, vr1.max, TYPE_SIGN (expr_type));
            }
          /* If either input range contains only non-negative values
             we can truncate the result range maximum to the respective
             maximum of the input range.  */
          if (int_cst_range0 && tree_int_cst_sgn (vr0.min) >= 0)
-           dmax = dmax.min (tree_to_double_int (vr0.max),
-                                  TYPE_UNSIGNED (expr_type));
+           wmax = wi::min (wmax, vr0.max, TYPE_SIGN (expr_type));
          if (int_cst_range1 && tree_int_cst_sgn (vr1.min) >= 0)
-           dmax = dmax.min (tree_to_double_int (vr1.max),
-                                  TYPE_UNSIGNED (expr_type));
-         max = double_int_to_tree (expr_type, dmax);
+           wmax = wi::min (wmax, vr1.max, TYPE_SIGN (expr_type));
+         max = wide_int_to_tree (expr_type, wmax);
        }
       else if (code == BIT_IOR_EXPR)
        {
-         double_int dmin;
-         max = double_int_to_tree (expr_type,
-                                   may_be_nonzero0 | may_be_nonzero1);
-         dmin = must_be_nonzero0 | must_be_nonzero1;
+         max = wide_int_to_tree (expr_type,
+                                 may_be_nonzero0 | may_be_nonzero1);
+         wide_int wmin = must_be_nonzero0 | must_be_nonzero1;
          /* If the input ranges contain only positive values we can
             truncate the minimum of the result range to the maximum
             of the input range minima.  */
@@ -3048,31 +2985,27 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
              && tree_int_cst_sgn (vr0.min) >= 0
              && tree_int_cst_sgn (vr1.min) >= 0)
            {
-             dmin = dmin.max (tree_to_double_int (vr0.min),
-                              TYPE_UNSIGNED (expr_type));
-             dmin = dmin.max (tree_to_double_int (vr1.min),
-                              TYPE_UNSIGNED (expr_type));
+             wmin = wi::max (wmin, vr0.min, TYPE_SIGN (expr_type));
+             wmin = wi::max (wmin, vr1.min, TYPE_SIGN (expr_type));
            }
          /* If either input range contains only negative values
             we can truncate the minimum of the result range to the
             respective minimum range.  */
          if (int_cst_range0 && tree_int_cst_sgn (vr0.max) < 0)
-           dmin = dmin.max (tree_to_double_int (vr0.min),
-                            TYPE_UNSIGNED (expr_type));
+           wmin = wi::max (wmin, vr0.min, TYPE_SIGN (expr_type));
          if (int_cst_range1 && tree_int_cst_sgn (vr1.max) < 0)
-           dmin = dmin.max (tree_to_double_int (vr1.min),
-                            TYPE_UNSIGNED (expr_type));
-         min = double_int_to_tree (expr_type, dmin);
+           wmin = wi::max (wmin, vr1.min, TYPE_SIGN (expr_type));
+         min = wide_int_to_tree (expr_type, wmin);
        }
       else if (code == BIT_XOR_EXPR)
        {
-         double_int result_zero_bits, result_one_bits;
-         result_zero_bits = (must_be_nonzero0 & must_be_nonzero1)
-                            | ~(may_be_nonzero0 | may_be_nonzero1);
-         result_one_bits = must_be_nonzero0.and_not (may_be_nonzero1)
-                           | must_be_nonzero1.and_not (may_be_nonzero0);
-         max = double_int_to_tree (expr_type, ~result_zero_bits);
-         min = double_int_to_tree (expr_type, result_one_bits);
+         wide_int result_zero_bits = ((must_be_nonzero0 & must_be_nonzero1)
+                                      | ~(may_be_nonzero0 | may_be_nonzero1));
+         wide_int result_one_bits
+           = (must_be_nonzero0.and_not (may_be_nonzero1)
+              | must_be_nonzero1.and_not (may_be_nonzero0));
+         max = wide_int_to_tree (expr_type, ~result_zero_bits);
+         min = wide_int_to_tree (expr_type, result_one_bits);
          /* If the range has all positive or all negative values the
             result is better than VARYING.  */
          if (tree_int_cst_sgn (min) < 0
@@ -3287,15 +3220,13 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
          if (is_overflow_infinity (vr0.min))
            new_min = negative_overflow_infinity (outer_type);
          else
-           new_min = force_fit_type_double (outer_type,
-                                            tree_to_double_int (vr0.min),
-                                            0, false);
+           new_min = force_fit_type (outer_type, wi::to_widest (vr0.min),
+                                     0, false);
          if (is_overflow_infinity (vr0.max))
            new_max = positive_overflow_infinity (outer_type);
          else
-           new_max = force_fit_type_double (outer_type,
-                                            tree_to_double_int (vr0.max),
-                                            0, false);
+           new_max = force_fit_type (outer_type, wi::to_widest (vr0.max),
+                                     0, false);
          set_and_canonicalize_value_range (vr, vr0.type,
                                            new_min, new_max, NULL);
          return;
@@ -3393,7 +3324,7 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
 
                  min = (vr0.min != type_min_value
                         ? int_const_binop (PLUS_EXPR, type_min_value,
-                                           integer_one_node)
+                                           build_int_cst (TREE_TYPE (type_min_value), 1))
                         : type_min_value);
                }
              else
@@ -3565,20 +3496,184 @@ extract_range_basic (value_range_t *vr, gimple stmt)
   bool sop = false;
   tree type = gimple_expr_type (stmt);
 
-  /* If the call is __builtin_constant_p and the argument is a
-     function parameter resolve it to false.  This avoids bogus
-     array bound warnings.
-     ???  We could do this as early as inlining is finished.  */
-  if (gimple_call_builtin_p (stmt, BUILT_IN_CONSTANT_P))
+  if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
     {
-      tree arg = gimple_call_arg (stmt, 0);
-      if (TREE_CODE (arg) == SSA_NAME
-         && SSA_NAME_IS_DEFAULT_DEF (arg)
-         && TREE_CODE (SSA_NAME_VAR (arg)) == PARM_DECL)
-       set_value_range_to_null (vr, type);
+      tree fndecl = gimple_call_fndecl (stmt), arg;
+      int mini, maxi, zerov = 0, prec;
+
+      switch (DECL_FUNCTION_CODE (fndecl))
+       {
+       case BUILT_IN_CONSTANT_P:
+         /* If the call is __builtin_constant_p and the argument is a
+            function parameter resolve it to false.  This avoids bogus
+            array bound warnings.
+            ???  We could do this as early as inlining is finished.  */
+         arg = gimple_call_arg (stmt, 0);
+         if (TREE_CODE (arg) == SSA_NAME
+             && SSA_NAME_IS_DEFAULT_DEF (arg)
+             && TREE_CODE (SSA_NAME_VAR (arg)) == PARM_DECL)
+           {
+             set_value_range_to_null (vr, type);
+             return;
+           }
+         break;
+         /* Both __builtin_ffs* and __builtin_popcount return
+            [0, prec].  */
+       CASE_INT_FN (BUILT_IN_FFS):
+       CASE_INT_FN (BUILT_IN_POPCOUNT):
+         arg = gimple_call_arg (stmt, 0);
+         prec = TYPE_PRECISION (TREE_TYPE (arg));
+         mini = 0;
+         maxi = prec;
+         if (TREE_CODE (arg) == SSA_NAME)
+           {
+             value_range_t *vr0 = get_value_range (arg);
+             /* If arg is non-zero, then ffs or popcount
+                are non-zero.  */
+             if (((vr0->type == VR_RANGE
+                   && integer_nonzerop (vr0->min))
+                  || (vr0->type == VR_ANTI_RANGE
+                      && integer_zerop (vr0->min)))
+                 && !is_overflow_infinity (vr0->min))
+               mini = 1;
+             /* If some high bits are known to be zero,
+                we can decrease the maximum.  */
+             if (vr0->type == VR_RANGE
+                 && TREE_CODE (vr0->max) == INTEGER_CST
+                 && !is_overflow_infinity (vr0->max))
+               maxi = tree_floor_log2 (vr0->max) + 1;
+           }
+         goto bitop_builtin;
+         /* __builtin_parity* returns [0, 1].  */
+       CASE_INT_FN (BUILT_IN_PARITY):
+         mini = 0;
+         maxi = 1;
+         goto bitop_builtin;
+         /* __builtin_c[lt]z* return [0, prec-1], except for
+            when the argument is 0, but that is undefined behavior.
+            On many targets where the CLZ RTL or optab value is defined
+            for 0 the value is prec, so include that in the range
+            by default.  */
+       CASE_INT_FN (BUILT_IN_CLZ):
+         arg = gimple_call_arg (stmt, 0);
+         prec = TYPE_PRECISION (TREE_TYPE (arg));
+         mini = 0;
+         maxi = prec;
+         if (optab_handler (clz_optab, TYPE_MODE (TREE_TYPE (arg)))
+             != CODE_FOR_nothing
+             && CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (TREE_TYPE (arg)),
+                                           zerov)
+             /* Handle only the single common value.  */
+             && zerov != prec)
+           /* Magic value to give up, unless vr0 proves
+              arg is non-zero.  */
+           mini = -2;
+         if (TREE_CODE (arg) == SSA_NAME)
+           {
+             value_range_t *vr0 = get_value_range (arg);
+             /* From clz of VR_RANGE minimum we can compute
+                result maximum.  */
+             if (vr0->type == VR_RANGE
+                 && TREE_CODE (vr0->min) == INTEGER_CST
+                 && !is_overflow_infinity (vr0->min))
+               {
+                 maxi = prec - 1 - tree_floor_log2 (vr0->min);
+                 if (maxi != prec)
+                   mini = 0;
+               }
+             else if (vr0->type == VR_ANTI_RANGE
+                      && integer_zerop (vr0->min)
+                      && !is_overflow_infinity (vr0->min))
+               {
+                 maxi = prec - 1;
+                 mini = 0;
+               }
+             if (mini == -2)
+               break;
+             /* From clz of VR_RANGE maximum we can compute
+                result minimum.  */
+             if (vr0->type == VR_RANGE
+                 && TREE_CODE (vr0->max) == INTEGER_CST
+                 && !is_overflow_infinity (vr0->max))
+               {
+                 mini = prec - 1 - tree_floor_log2 (vr0->max);
+                 if (mini == prec)
+                   break;
+               }
+           }
+         if (mini == -2)
+           break;
+         goto bitop_builtin;
+         /* __builtin_ctz* return [0, prec-1], except for
+            when the argument is 0, but that is undefined behavior.
+            If there is a ctz optab for this mode and
+            CTZ_DEFINED_VALUE_AT_ZERO, include that in the range,
+            otherwise just assume 0 won't be seen.  */
+       CASE_INT_FN (BUILT_IN_CTZ):
+         arg = gimple_call_arg (stmt, 0);
+         prec = TYPE_PRECISION (TREE_TYPE (arg));
+         mini = 0;
+         maxi = prec - 1;
+         if (optab_handler (ctz_optab, TYPE_MODE (TREE_TYPE (arg)))
+             != CODE_FOR_nothing
+             && CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (TREE_TYPE (arg)),
+                                           zerov))
+           {
+             /* Handle only the two common values.  */
+             if (zerov == -1)
+               mini = -1;
+             else if (zerov == prec)
+               maxi = prec;
+             else
+               /* Magic value to give up, unless vr0 proves
+                  arg is non-zero.  */
+               mini = -2;
+           }
+         if (TREE_CODE (arg) == SSA_NAME)
+           {
+             value_range_t *vr0 = get_value_range (arg);
+             /* If arg is non-zero, then use [0, prec - 1].  */
+             if (((vr0->type == VR_RANGE
+                   && integer_nonzerop (vr0->min))
+                  || (vr0->type == VR_ANTI_RANGE
+                      && integer_zerop (vr0->min)))
+                 && !is_overflow_infinity (vr0->min))
+               {
+                 mini = 0;
+                 maxi = prec - 1;
+               }
+             /* If some high bits are known to be zero,
+                we can decrease the result maximum.  */
+             if (vr0->type == VR_RANGE
+                 && TREE_CODE (vr0->max) == INTEGER_CST
+                 && !is_overflow_infinity (vr0->max))
+               {
+                 maxi = tree_floor_log2 (vr0->max);
+                 /* For vr0 [0, 0] give up.  */
+                 if (maxi == -1)
+                   break;
+               }
+           }
+         if (mini == -2)
+           break;
+         goto bitop_builtin;
+         /* __builtin_clrsb* returns [0, prec-1].  */
+       CASE_INT_FN (BUILT_IN_CLRSB):
+         arg = gimple_call_arg (stmt, 0);
+         prec = TYPE_PRECISION (TREE_TYPE (arg));
+         mini = 0;
+         maxi = prec - 1;
+         goto bitop_builtin;
+       bitop_builtin:
+         set_value_range (vr, VR_RANGE, build_int_cst (type, mini),
+                          build_int_cst (type, maxi), NULL);
+         return;
+       default:
+         break;
+       }
     }
-  else if (INTEGRAL_TYPE_P (type)
-          && gimple_stmt_nonnegative_warnv_p (stmt, &sop))
+  if (INTEGRAL_TYPE_P (type)
+      && gimple_stmt_nonnegative_warnv_p (stmt, &sop))
     set_value_range_to_nonnegative (vr, type,
                                    sop || stmt_overflow_infinity (stmt));
   else if (vrp_stmt_computes_nonzero (stmt, &sop)
@@ -3704,30 +3799,28 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop,
       && (TREE_CODE (init) != SSA_NAME
          || get_value_range (init)->type == VR_RANGE))
     {
-      double_int nit;
+      widest_int nit;
 
       /* We are only entering here for loop header PHI nodes, so using
         the number of latch executions is the correct thing to use.  */
       if (max_loop_iterations (loop, &nit))
        {
          value_range_t maxvr = VR_INITIALIZER;
-         double_int dtmp;
-         bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (step));
-         bool overflow = false;
-
-         dtmp = tree_to_double_int (step)
-                .mul_with_sign (nit, unsigned_p, &overflow);
+         signop sgn = TYPE_SIGN (TREE_TYPE (step));
+         bool overflow;
+         
+         wide_int wtmp = wi::mul (wi::to_widest (step), nit, sgn, &overflow);
          /* If the multiplication overflowed we can't do a meaningful
             adjustment.  Likewise if the result doesn't fit in the type
             of the induction variable.  For a signed type we have to
             check whether the result has the expected signedness which
             is that of the step as number of iterations is unsigned.  */
          if (!overflow
-             && double_int_fits_to_tree_p (TREE_TYPE (init), dtmp)
-             && (unsigned_p
-                 || ((dtmp.high ^ TREE_INT_CST_HIGH (step)) >= 0)))
+             && wi::fits_to_tree_p (wtmp, TREE_TYPE (init))
+             && (sgn == UNSIGNED
+                 || wi::gts_p (wtmp, 0) == wi::gts_p (step, 0)))
            {
-             tem = double_int_to_tree (TREE_TYPE (init), dtmp);
+             tem = wide_int_to_tree (TREE_TYPE (init), wtmp);
              extract_range_from_binary_expr (&maxvr, PLUS_EXPR,
                                              TREE_TYPE (init), init, tem);
              /* Likewise if the addition did.  */
@@ -4292,7 +4385,6 @@ fp_predicate (gimple stmt)
   return FLOAT_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)));
 }
 
-
 /* If the range of values taken by OP can be inferred after STMT executes,
    return the comparison code (COMP_CODE_P) and value (VAL_P) that
    describes the inferred range.  Return true if a range could be
@@ -4310,7 +4402,7 @@ infer_value_range (gimple stmt, tree op, enum tree_code *comp_code_p, tree *val_
     return false;
 
   /* Similarly, don't infer anything from statements that may throw
-     exceptions.  */
+     exceptions. ??? Relax this requirement?  */
   if (stmt_could_throw_p (stmt))
     return false;
 
@@ -4321,21 +4413,11 @@ infer_value_range (gimple stmt, tree op, enum tree_code *comp_code_p, tree *val_
   if (stmt_ends_bb_p (stmt) && EDGE_COUNT (gimple_bb (stmt)->succs) == 0)
     return false;
 
-  /* We can only assume that a pointer dereference will yield
-     non-NULL if -fdelete-null-pointer-checks is enabled.  */
-  if (flag_delete_null_pointer_checks
-      && POINTER_TYPE_P (TREE_TYPE (op))
-      && gimple_code (stmt) != GIMPLE_ASM)
+  if (infer_nonnull_range (stmt, op))
     {
-      unsigned num_uses, num_loads, num_stores;
-
-      count_uses_and_derefs (op, stmt, &num_uses, &num_loads, &num_stores);
-      if (num_loads + num_stores > 0)
-       {
-         *val_p = build_int_cst (TREE_TYPE (op), 0);
-         *comp_code_p = NE_EXPR;
-         return true;
-       }
+      *val_p = build_int_cst (TREE_TYPE (op), 0);
+      *comp_code_p = NE_EXPR;
+      return true;
     }
 
   return false;
@@ -4372,7 +4454,7 @@ dump_asserts_for (FILE *file, tree name)
        }
       fprintf (file, "\n\tPREDICATE: ");
       print_generic_expr (file, name, 0);
-      fprintf (file, " %s ", tree_code_name[(int)loc->comp_code]);
+      fprintf (file, " %s ", get_tree_code_name (loc->comp_code));
       print_generic_expr (file, loc->val, 0);
       fprintf (file, "\n\n");
       loc = loc->next;
@@ -4446,10 +4528,8 @@ register_new_assert_for (tree name, tree expr,
   /* Never build an assert comparing against an integer constant with
      TREE_OVERFLOW set.  This confuses our undefined overflow warning
      machinery.  */
-  if (TREE_CODE (val) == INTEGER_CST
-      && TREE_OVERFLOW (val))
-    val = build_int_cst_wide (TREE_TYPE (val),
-                             TREE_INT_CST_LOW (val), TREE_INT_CST_HIGH (val));
+  if (TREE_OVERFLOW_P (val))
+    val = drop_tree_overflow (val);
 
   /* The new assertion A will be inserted at BB or E.  We need to
      determine if the new location is dominated by a previously
@@ -4602,23 +4682,23 @@ extract_code_and_val_from_cond_with_ops (tree name, enum tree_code cond_code,
    (to transform signed values into unsigned) and at the end xor
    SGNBIT back.  */
 
-static double_int
-masked_increment (double_int val, double_int mask, double_int sgnbit,
+static wide_int
+masked_increment (wide_int val, wide_int mask, wide_int sgnbit,
                  unsigned int prec)
 {
-  double_int bit = double_int_one, res;
+  wide_int bit = wi::one (prec), res;
   unsigned int i;
 
   val ^= sgnbit;
   for (i = 0; i < prec; i++, bit += bit)
     {
       res = mask;
-      if ((res & bit).is_zero ())
+      if ((res & bit) == 0)
        continue;
-      res = bit - double_int_one;
+      res = bit - 1;
       res = (val + bit).and_not (res);
       res &= mask;
-      if (res.ugt (val))
+      if (wi::gtu_p (res, val))
        return res ^ sgnbit;
     }
   return val ^ sgnbit;
@@ -4793,8 +4873,8 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
       gimple def_stmt = SSA_NAME_DEF_STMT (name);
       tree name2 = NULL_TREE, names[2], cst2 = NULL_TREE;
       tree val2 = NULL_TREE;
-      double_int mask = double_int_zero;
       unsigned int prec = TYPE_PRECISION (TREE_TYPE (val));
+      wide_int mask = wi::zero (prec);
       unsigned int nprec = prec;
       enum tree_code rhs_code = ERROR_MARK;
 
@@ -4860,15 +4940,14 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
          name2 = gimple_assign_rhs1 (def_stmt);
          cst2 = gimple_assign_rhs2 (def_stmt);
          if (TREE_CODE (name2) == SSA_NAME
-             && host_integerp (cst2, 1)
+             && tree_fits_uhwi_p (cst2)
              && INTEGRAL_TYPE_P (TREE_TYPE (name2))
-             && IN_RANGE (tree_low_cst (cst2, 1), 1, prec - 1)
-             && prec <= HOST_BITS_PER_DOUBLE_INT
+             && IN_RANGE (tree_to_uhwi (cst2), 1, prec - 1)
              && prec == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (val)))
              && live_on_edge (e, name2)
              && !has_single_use (name2))
            {
-             mask = double_int::mask (tree_low_cst (cst2, 1));
+             mask = wi::mask (tree_to_uhwi (cst2), false, prec);
              val2 = fold_binary (LSHIFT_EXPR, TREE_TYPE (val), val, cst2);
            }
        }
@@ -4891,26 +4970,26 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
                  val2 = fold_convert (type, val2);
                }
              tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (tmp), tmp, val2);
-             new_val = double_int_to_tree (TREE_TYPE (tmp), mask);
+             new_val = wide_int_to_tree (TREE_TYPE (tmp), mask);
              new_comp_code = comp_code == EQ_EXPR ? LE_EXPR : GT_EXPR;
            }
          else if (comp_code == LT_EXPR || comp_code == GE_EXPR)
            {
-             double_int minval
-               = double_int::min_value (prec, TYPE_UNSIGNED (TREE_TYPE (val)));
+             wide_int minval
+               = wi::min_value (prec, TYPE_SIGN (TREE_TYPE (val)));
              new_val = val2;
-             if (minval == tree_to_double_int (new_val))
+             if (minval == new_val)
                new_val = NULL_TREE;
            }
          else
            {
-             double_int maxval
-               = double_int::max_value (prec, TYPE_UNSIGNED (TREE_TYPE (val)));
-             mask |= tree_to_double_int (val2);
+             wide_int maxval
+               = wi::max_value (prec, TYPE_SIGN (TREE_TYPE (val)));
+             mask |= val2;
              if (mask == maxval)
                new_val = NULL_TREE;
              else
-               new_val = double_int_to_tree (TREE_TYPE (val2), mask);
+               new_val = wide_int_to_tree (TREE_TYPE (val2), mask);
            }
 
          if (new_val)
@@ -4962,7 +5041,6 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
              && INTEGRAL_TYPE_P (TREE_TYPE (name2))
              && TREE_CODE (cst2) == INTEGER_CST
              && !integer_zerop (cst2)
-             && nprec <= HOST_BITS_PER_DOUBLE_INT
              && (nprec > 1
                  || TYPE_UNSIGNED (TREE_TYPE (val))))
            {
@@ -4985,17 +5063,17 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
        }
       if (names[0] || names[1])
        {
-         double_int minv, maxv = double_int_zero, valv, cst2v;
-         double_int tem, sgnbit;
+         wide_int minv, maxv, valv, cst2v;
+         wide_int tem, sgnbit;
          bool valid_p = false, valn = false, cst2n = false;
          enum tree_code ccode = comp_code;
 
-         valv = tree_to_double_int (val).zext (nprec);
-         cst2v = tree_to_double_int (cst2).zext (nprec);
-         if (!TYPE_UNSIGNED (TREE_TYPE (val)))
+         valv = wide_int::from (val, nprec, UNSIGNED);
+         cst2v = wide_int::from (cst2, nprec, UNSIGNED);
+         if (TYPE_SIGN (TREE_TYPE (val)) == SIGNED)
            {
-             valn = valv.sext (nprec).is_negative ();
-             cst2n = cst2v.sext (nprec).is_negative ();
+             valn = wi::neg_p (wi::sext (valv, nprec));
+             cst2n = wi::neg_p (wi::sext (cst2v, nprec));
            }
          /* If CST2 doesn't have most significant bit set,
             but VAL is negative, we have comparison like
@@ -5003,9 +5081,9 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
          if (!cst2n && valn)
            ccode = ERROR_MARK;
          if (cst2n)
-           sgnbit = double_int_one.llshift (nprec - 1, nprec).zext (nprec);
+           sgnbit = wi::set_bit_in_zero (nprec - 1, nprec);
          else
-           sgnbit = double_int_zero;
+           sgnbit = wi::zero (nprec);
          minv = valv & cst2v;
          switch (ccode)
            {
@@ -5015,33 +5093,32 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
                 have folded the comparison into false) and
                 maximum unsigned value is VAL | ~CST2.  */
              maxv = valv | ~cst2v;
-             maxv = maxv.zext (nprec);
+             maxv = wi::zext (maxv, nprec);
              valid_p = true;
              break;
+
            case NE_EXPR:
              tem = valv | ~cst2v;
-             tem = tem.zext (nprec);
+             tem = wi::zext (tem, nprec);
              /* If VAL is 0, handle (X & CST2) != 0 as (X & CST2) > 0U.  */
-             if (valv.is_zero ())
+             if (valv == 0)
                {
                  cst2n = false;
-                 sgnbit = double_int_zero;
+                 sgnbit = wi::zero (nprec);
                  goto gt_expr;
                }
              /* If (VAL | ~CST2) is all ones, handle it as
                 (X & CST2) < VAL.  */
-             if (tem == double_int::mask (nprec))
+             if (tem == -1)
                {
                  cst2n = false;
                  valn = false;
-                 sgnbit = double_int_zero;
+                 sgnbit = wi::zero (nprec);
                  goto lt_expr;
                }
-             if (!cst2n
-                 && cst2v.sext (nprec).is_negative ())
-               sgnbit
-                 = double_int_one.llshift (nprec - 1, nprec).zext (nprec);
-             if (!sgnbit.is_zero ())
+             if (!cst2n && wi::neg_p (wi::sext (cst2v, nprec)))
+               sgnbit = wi::set_bit_in_zero (nprec - 1, nprec);
+             if (sgnbit != 0)
                {
                  if (valv == sgnbit)
                    {
@@ -5049,15 +5126,16 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
                      valn = true;
                      goto gt_expr;
                    }
-                 if (tem == double_int::mask (nprec - 1))
+                 if (tem == wi::mask (nprec - 1, false, nprec))
                    {
                      cst2n = true;
                      goto lt_expr;
                    }
                  if (!cst2n)
-                   sgnbit = double_int_zero;
+                   sgnbit = wi::zero (nprec);
                }
              break;
+
            case GE_EXPR:
              /* Minimum unsigned value for >= if (VAL & CST2) == VAL
                 is VAL and maximum unsigned value is ~0.  For signed
@@ -5072,9 +5150,10 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
                  if (minv == valv)
                    break;
                }
-             maxv = double_int::mask (nprec - (cst2n ? 1 : 0));
+             maxv = wi::mask (nprec - (cst2n ? 1 : 0), false, nprec);
              valid_p = true;
              break;
+
            case GT_EXPR:
            gt_expr:
              /* Find out smallest MINV where MINV > VAL
@@ -5083,9 +5162,10 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
              minv = masked_increment (valv, cst2v, sgnbit, nprec);
              if (minv == valv)
                break;
-             maxv = double_int::mask (nprec - (cst2n ? 1 : 0));
+             maxv = wi::mask (nprec - (cst2n ? 1 : 0), false, nprec);
              valid_p = true;
              break;
+
            case LE_EXPR:
              /* Minimum unsigned value for <= is 0 and maximum
                 unsigned value is VAL | ~CST2 if (VAL & CST2) == VAL.
@@ -5102,13 +5182,14 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
                  maxv = masked_increment (valv, cst2v, sgnbit, nprec);
                  if (maxv == valv)
                    break;
-                 maxv -= double_int_one;
+                 maxv -= 1;
                }
              maxv |= ~cst2v;
-             maxv = maxv.zext (nprec);
+             maxv = wi::zext (maxv, nprec);
              minv = sgnbit;
              valid_p = true;
              break;
+
            case LT_EXPR:
            lt_expr:
              /* Minimum unsigned value for < is 0 and maximum
@@ -5131,17 +5212,18 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
                  if (maxv == valv)
                    break;
                }
-             maxv -= double_int_one;
+             maxv -= 1;
              maxv |= ~cst2v;
-             maxv = maxv.zext (nprec);
+             maxv = wi::zext (maxv, nprec);
              minv = sgnbit;
              valid_p = true;
              break;
+
            default:
              break;
            }
          if (valid_p
-             && (maxv - minv).zext (nprec) != double_int::mask (nprec))
+             && wi::zext (maxv - minv, nprec) != wi::minus_one (nprec))
            {
              tree tmp, new_val, type;
              int i;
@@ -5149,7 +5231,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
              for (i = 0; i < 2; i++)
                if (names[i])
                  {
-                   double_int maxv2 = maxv;
+                   wide_int maxv2 = maxv;
                    tmp = names[i];
                    type = TREE_TYPE (names[i]);
                    if (!TYPE_UNSIGNED (type))
@@ -5157,13 +5239,13 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
                        type = build_nonstandard_integer_type (nprec, 1);
                        tmp = build1 (NOP_EXPR, type, names[i]);
                      }
-                   if (!minv.is_zero ())
+                   if (minv != 0)
                      {
                        tmp = build2 (PLUS_EXPR, type, tmp,
-                                     double_int_to_tree (type, -minv));
+                                     wide_int_to_tree (type, -minv));
                        maxv2 = maxv - minv;
                      }
-                   new_val = double_int_to_tree (type, maxv2);
+                   new_val = wide_int_to_tree (type, maxv2);
 
                    if (dump_file)
                      {
@@ -5246,10 +5328,14 @@ register_edge_assert_for_1 (tree op, enum tree_code code,
               && gimple_assign_rhs_code (op_def) == BIT_IOR_EXPR))
     {
       /* Recurse on each operand.  */
-      retval |= register_edge_assert_for_1 (gimple_assign_rhs1 (op_def),
-                                           code, e, bsi);
-      retval |= register_edge_assert_for_1 (gimple_assign_rhs2 (op_def),
-                                           code, e, bsi);
+      tree op0 = gimple_assign_rhs1 (op_def);
+      tree op1 = gimple_assign_rhs2 (op_def);
+      if (TREE_CODE (op0) == SSA_NAME
+         && has_single_use (op0))
+       retval |= register_edge_assert_for_1 (op0, code, e, bsi);
+      if (TREE_CODE (op1) == SSA_NAME
+         && has_single_use (op1))
+       retval |= register_edge_assert_for_1 (op1, code, e, bsi);
     }
   else if (gimple_assign_rhs_code (op_def) == BIT_NOT_EXPR
           && TYPE_PRECISION (TREE_TYPE (gimple_assign_lhs (op_def))) == 1)
@@ -5688,7 +5774,7 @@ find_assert_locations_1 (basic_block bb, sbitmap live)
     }
 
   /* Traverse all PHI nodes in BB, updating live.  */
-  for (si = gsi_start_phis (bb); !gsi_end_p(si); gsi_next (&si))
+  for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
     {
       use_operand_p arg_p;
       ssa_op_iter i;
@@ -5729,6 +5815,33 @@ find_assert_locations (void)
   for (i = 0; i < rpo_cnt; ++i)
     bb_rpo[rpo[i]] = i;
 
+  /* Pre-seed loop latch liveness from loop header PHI nodes.  Due to
+     the order we compute liveness and insert asserts we otherwise
+     fail to insert asserts into the loop latch.  */
+  loop_p loop;
+  FOR_EACH_LOOP (loop, 0)
+    {
+      i = loop->latch->index;
+      unsigned int j = single_succ_edge (loop->latch)->dest_idx;
+      for (gimple_stmt_iterator gsi = gsi_start_phis (loop->header);
+          !gsi_end_p (gsi); gsi_next (&gsi))
+       {
+         gimple phi = gsi_stmt (gsi);
+         if (virtual_operand_p (gimple_phi_result (phi)))
+           continue;
+         tree arg = gimple_phi_arg_def (phi, j);
+         if (TREE_CODE (arg) == SSA_NAME)
+           {
+             if (live[i] == NULL)
+               {
+                 live[i] = sbitmap_alloc (num_ssa_names);
+                 bitmap_clear (live[i]);
+               }
+             bitmap_set_bit (live[i], SSA_NAME_VERSION (arg));
+           }
+       }
+    }
+
   need_asserts = false;
   for (i = rpo_cnt - 1; i >= 0; --i)
     {
@@ -5998,7 +6111,8 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
     }
 
   low_bound = array_ref_low_bound (ref);
-  up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound, integer_one_node);
+  up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound, 
+                                build_int_cst (TREE_TYPE (up_bound), 1));
 
   if (TREE_CODE (low_sub) == SSA_NAME)
     {
@@ -6095,7 +6209,7 @@ search_for_addr_array (tree t, location_t location)
     {
       tree tem = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
       tree low_bound, up_bound, el_sz;
-      double_int idx;
+      offset_int idx;
       if (TREE_CODE (TREE_TYPE (tem)) != ARRAY_TYPE
          || TREE_CODE (TREE_TYPE (TREE_TYPE (tem))) == ARRAY_TYPE
          || !TYPE_DOMAIN (TREE_TYPE (tem)))
@@ -6113,8 +6227,8 @@ search_for_addr_array (tree t, location_t location)
        return;
 
       idx = mem_ref_offset (t);
-      idx = idx.sdiv (tree_to_double_int (el_sz), TRUNC_DIV_EXPR);
-      if (idx.slt (double_int_zero))
+      idx = wi::sdiv_trunc (idx, wi::to_offset (el_sz));
+      if (wi::lts_p (idx, 0))
        {
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
@@ -6126,9 +6240,8 @@ search_for_addr_array (tree t, location_t location)
                      "array subscript is below array bounds");
          TREE_NO_WARNING (t) = 1;
        }
-      else if (idx.sgt (tree_to_double_int (up_bound)
-                       - tree_to_double_int (low_bound)
-                       + double_int_one))
+      else if (wi::gts_p (idx, (wi::to_offset (up_bound)
+                               - wi::to_offset (low_bound) + 1)))
        {
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
@@ -6231,6 +6344,88 @@ check_all_array_refs (void)
     }
 }
 
+/* Return true if all imm uses of VAR are either in STMT, or
+   feed (optionally through a chain of single imm uses) GIMPLE_COND
+   in basic block COND_BB.  */
+
+static bool
+all_imm_uses_in_stmt_or_feed_cond (tree var, gimple stmt, basic_block cond_bb)
+{
+  use_operand_p use_p, use2_p;
+  imm_use_iterator iter;
+
+  FOR_EACH_IMM_USE_FAST (use_p, iter, var)
+    if (USE_STMT (use_p) != stmt)
+      {
+       gimple use_stmt = USE_STMT (use_p), use_stmt2;
+       if (is_gimple_debug (use_stmt))
+         continue;
+       while (is_gimple_assign (use_stmt)
+              && TREE_CODE (gimple_assign_lhs (use_stmt)) == SSA_NAME
+              && single_imm_use (gimple_assign_lhs (use_stmt),
+                                 &use2_p, &use_stmt2))
+         use_stmt = use_stmt2;
+       if (gimple_code (use_stmt) != GIMPLE_COND
+           || gimple_bb (use_stmt) != cond_bb)
+         return false;
+      }
+  return true;
+}
+
+/* Handle
+   _4 = x_3 & 31;
+   if (_4 != 0)
+     goto <bb 6>;
+   else
+     goto <bb 7>;
+   <bb 6>:
+   __builtin_unreachable ();
+   <bb 7>:
+   x_5 = ASSERT_EXPR <x_3, ...>;
+   If x_3 has no other immediate uses (checked by caller),
+   var is the x_3 var from ASSERT_EXPR, we can clear low 5 bits
+   from the non-zero bitmask.  */
+
+static void
+maybe_set_nonzero_bits (basic_block bb, tree var)
+{
+  edge e = single_pred_edge (bb);
+  basic_block cond_bb = e->src;
+  gimple stmt = last_stmt (cond_bb);
+  tree cst;
+
+  if (stmt == NULL
+      || gimple_code (stmt) != GIMPLE_COND
+      || gimple_cond_code (stmt) != ((e->flags & EDGE_TRUE_VALUE)
+                                    ? EQ_EXPR : NE_EXPR)
+      || TREE_CODE (gimple_cond_lhs (stmt)) != SSA_NAME
+      || !integer_zerop (gimple_cond_rhs (stmt)))
+    return;
+
+  stmt = SSA_NAME_DEF_STMT (gimple_cond_lhs (stmt));
+  if (!is_gimple_assign (stmt)
+      || gimple_assign_rhs_code (stmt) != BIT_AND_EXPR
+      || TREE_CODE (gimple_assign_rhs2 (stmt)) != INTEGER_CST)
+    return;
+  if (gimple_assign_rhs1 (stmt) != var)
+    {
+      gimple stmt2;
+
+      if (TREE_CODE (gimple_assign_rhs1 (stmt)) != SSA_NAME)
+       return;
+      stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
+      if (!gimple_assign_cast_p (stmt2)
+         || gimple_assign_rhs1 (stmt2) != var
+         || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt2))
+         || (TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (stmt)))
+                             != TYPE_PRECISION (TREE_TYPE (var))))
+       return;
+    }
+  cst = gimple_assign_rhs2 (stmt);
+  set_nonzero_bits (var, (get_nonzero_bits (var)
+                         & ~wi::to_widest (cst)));
+}
+
 /* Convert range assertion expressions into the implied copies and
    copy propagate away the copies.  Doing the trivial copy propagation
    here avoids the need to run the full copy propagation pass after
@@ -6260,12 +6455,16 @@ remove_range_assertions (void)
 {
   basic_block bb;
   gimple_stmt_iterator si;
+  /* 1 if looking at ASSERT_EXPRs immediately at the beginning of
+     a basic block preceeded by GIMPLE_COND branching to it and
+     __builtin_trap, -1 if not yet checked, 0 otherwise.  */
+  int is_unreachable;
 
   /* Note that the BSI iterator bump happens at the bottom of the
      loop and no bump is necessary if we're removing the statement
      referenced by the current BSI.  */
   FOR_EACH_BB (bb)
-    for (si = gsi_start_bb (bb); !gsi_end_p (si);)
+    for (si = gsi_after_labels (bb), is_unreachable = -1; !gsi_end_p (si);)
       {
        gimple stmt = gsi_stmt (si);
        gimple use_stmt;
@@ -6273,6 +6472,7 @@ remove_range_assertions (void)
        if (is_gimple_assign (stmt)
            && gimple_assign_rhs_code (stmt) == ASSERT_EXPR)
          {
+           tree lhs = gimple_assign_lhs (stmt);
            tree rhs = gimple_assign_rhs1 (stmt);
            tree var;
            tree cond = fold (ASSERT_EXPR_COND (rhs));
@@ -6281,22 +6481,52 @@ remove_range_assertions (void)
 
            gcc_assert (cond != boolean_false_node);
 
-           /* Propagate the RHS into every use of the LHS.  */
            var = ASSERT_EXPR_VAR (rhs);
-           FOR_EACH_IMM_USE_STMT (use_stmt, iter,
-                                  gimple_assign_lhs (stmt))
+           gcc_assert (TREE_CODE (var) == SSA_NAME);
+
+           if (!POINTER_TYPE_P (TREE_TYPE (lhs))
+               && SSA_NAME_RANGE_INFO (lhs))
+             {
+               if (is_unreachable == -1)
+                 {
+                   is_unreachable = 0;
+                   if (single_pred_p (bb)
+                       && assert_unreachable_fallthru_edge_p
+                                                   (single_pred_edge (bb)))
+                     is_unreachable = 1;
+                 }
+               /* Handle
+                  if (x_7 >= 10 && x_7 < 20)
+                    __builtin_unreachable ();
+                  x_8 = ASSERT_EXPR <x_7, ...>;
+                  if the only uses of x_7 are in the ASSERT_EXPR and
+                  in the condition.  In that case, we can copy the
+                  range info from x_8 computed in this pass also
+                  for x_7.  */
+               if (is_unreachable
+                   && all_imm_uses_in_stmt_or_feed_cond (var, stmt,
+                                                         single_pred (bb)))
+                 {
+                   set_range_info (var, SSA_NAME_RANGE_INFO (lhs)->min,
+                                   SSA_NAME_RANGE_INFO (lhs)->max);
+                   maybe_set_nonzero_bits (bb, var);
+                 }
+             }
+
+           /* Propagate the RHS into every use of the LHS.  */
+           FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
              FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
-               {
-                 SET_USE (use_p, var);
-                 gcc_assert (TREE_CODE (var) == SSA_NAME);
-               }
+               SET_USE (use_p, var);
 
            /* And finally, remove the copy, it is not needed.  */
            gsi_remove (&si, true);
            release_defs (stmt);
          }
        else
-         gsi_next (&si);
+         {
+           gsi_next (&si);
+           is_unreachable = 0;
+         }
       }
 }
 
@@ -6323,9 +6553,7 @@ stmt_interesting_for_vrp (gimple stmt)
       if (lhs && TREE_CODE (lhs) == SSA_NAME
          && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
              || POINTER_TYPE_P (TREE_TYPE (lhs)))
-         && ((is_gimple_call (stmt)
-              && gimple_call_fndecl (stmt) != NULL_TREE
-              && DECL_BUILT_IN (gimple_call_fndecl (stmt)))
+         && (is_gimple_call (stmt)
              || !gimple_vuse (stmt)))
        return true;
     }
@@ -7246,16 +7474,7 @@ vrp_visit_stmt (gimple stmt, edge *taken_edge_p, tree *output_p)
   if (!stmt_interesting_for_vrp (stmt))
     gcc_assert (stmt_ends_bb_p (stmt));
   else if (is_gimple_assign (stmt) || is_gimple_call (stmt))
-    {
-      /* In general, assignments with virtual operands are not useful
-        for deriving ranges, with the obvious exception of calls to
-        builtin functions.  */
-      if ((is_gimple_call (stmt)
-          && gimple_call_fndecl (stmt) != NULL_TREE
-          && DECL_BUILT_IN (gimple_call_fndecl (stmt)))
-         || !gimple_vuse (stmt))
-       return vrp_visit_assignment_or_call (stmt, output_p);
-    }
+    return vrp_visit_assignment_or_call (stmt, output_p);
   else if (gimple_code (stmt) == GIMPLE_COND)
     return vrp_visit_cond_stmt (stmt, taken_edge_p);
   else if (gimple_code (stmt) == GIMPLE_SWITCH)
@@ -7334,9 +7553,11 @@ union_ranges (enum value_range_type *vr0type,
                  && vrp_val_is_max (vr1max))
                {
                  tree min = int_const_binop (PLUS_EXPR,
-                                             *vr0max, integer_one_node);
+                                             *vr0max, 
+                                             build_int_cst (TREE_TYPE (*vr0max), 1));
                  tree max = int_const_binop (MINUS_EXPR,
-                                             vr1min, integer_one_node);
+                                             vr1min, 
+                                             build_int_cst (TREE_TYPE (vr1min), 1));
                  if (!operand_less_p (max, min))
                    {
                      *vr0type = VR_ANTI_RANGE;
@@ -7358,9 +7579,11 @@ union_ranges (enum value_range_type *vr0type,
                  && vrp_val_is_max (*vr0max))
                {
                  tree min = int_const_binop (PLUS_EXPR,
-                                             vr1max, integer_one_node);
+                                             vr1max,
+                                             build_int_cst (TREE_TYPE (vr1max), 1));
                  tree max = int_const_binop (MINUS_EXPR,
-                                             *vr0min, integer_one_node);
+                                             *vr0min,
+                                             build_int_cst (TREE_TYPE (*vr0min), 1));
                  if (!operand_less_p (max, min))
                    {
                      *vr0type = VR_ANTI_RANGE;
@@ -7396,9 +7619,11 @@ union_ranges (enum value_range_type *vr0type,
        {
          /* Arbitrarily choose the right or left gap.  */
          if (!mineq && TREE_CODE (vr1min) == INTEGER_CST)
-           *vr0max = int_const_binop (MINUS_EXPR, vr1min, integer_one_node);
+           *vr0max = int_const_binop (MINUS_EXPR, vr1min, 
+                                      build_int_cst (TREE_TYPE (vr1min), 1));
          else if (!maxeq && TREE_CODE (vr1max) == INTEGER_CST)
-           *vr0min = int_const_binop (PLUS_EXPR, vr1max, integer_one_node);
+           *vr0min = int_const_binop (PLUS_EXPR, vr1max,
+                                      build_int_cst (TREE_TYPE (vr1max), 1));
          else
            goto give_up;
        }
@@ -7429,12 +7654,14 @@ union_ranges (enum value_range_type *vr0type,
          *vr0type = VR_ANTI_RANGE;
          if (!mineq && TREE_CODE (*vr0min) == INTEGER_CST)
            {
-             *vr0max = int_const_binop (MINUS_EXPR, *vr0min, integer_one_node);
+             *vr0max = int_const_binop (MINUS_EXPR, *vr0min,
+                                        build_int_cst (TREE_TYPE (*vr0min), 1));
              *vr0min = vr1min;
            }
          else if (!maxeq && TREE_CODE (*vr0max) == INTEGER_CST)
            {
-             *vr0min = int_const_binop (PLUS_EXPR, *vr0max, integer_one_node);
+             *vr0min = int_const_binop (PLUS_EXPR, *vr0max,
+                                        build_int_cst (TREE_TYPE (*vr0max), 1));
              *vr0max = vr1max;
            }
          else
@@ -7462,7 +7689,8 @@ union_ranges (enum value_range_type *vr0type,
               && vr1type == VR_RANGE)
        {
          if (TREE_CODE (vr1min) == INTEGER_CST)
-           *vr0max = int_const_binop (MINUS_EXPR, vr1min, integer_one_node);
+           *vr0max = int_const_binop (MINUS_EXPR, vr1min, 
+                                      build_int_cst (TREE_TYPE (vr1min), 1));
          else
            goto give_up;
        }
@@ -7472,7 +7700,8 @@ union_ranges (enum value_range_type *vr0type,
          if (TREE_CODE (*vr0max) == INTEGER_CST)
            {
              *vr0type = vr1type;
-             *vr0min = int_const_binop (PLUS_EXPR, *vr0max, integer_one_node);
+             *vr0min = int_const_binop (PLUS_EXPR, *vr0max,
+                                        build_int_cst (TREE_TYPE (*vr0max), 1));
              *vr0max = vr1max;
            }
          else
@@ -7496,7 +7725,8 @@ union_ranges (enum value_range_type *vr0type,
               && vr1type == VR_RANGE)
        {
          if (TREE_CODE (vr1max) == INTEGER_CST)
-           *vr0min = int_const_binop (PLUS_EXPR, vr1max, integer_one_node);
+           *vr0min = int_const_binop (PLUS_EXPR, vr1max,
+                                      build_int_cst (TREE_TYPE (vr1max), 1));
          else
            goto give_up;
        }
@@ -7507,7 +7737,8 @@ union_ranges (enum value_range_type *vr0type,
            {
              *vr0type = vr1type;
              *vr0min = vr1min;
-             *vr0max = int_const_binop (MINUS_EXPR, *vr0min, integer_one_node);
+             *vr0max = int_const_binop (MINUS_EXPR, *vr0min,
+                                        build_int_cst (TREE_TYPE (*vr0min), 1));
            }
          else
            goto give_up;
@@ -7622,7 +7853,8 @@ intersect_ranges (enum value_range_type *vr0type,
          if (mineq)
            {
              if (TREE_CODE (vr1max) == INTEGER_CST)
-               *vr0min = int_const_binop (PLUS_EXPR, vr1max, integer_one_node);
+               *vr0min = int_const_binop (PLUS_EXPR, vr1max,
+                                          build_int_cst (TREE_TYPE (vr1max), 1));
              else
                *vr0min = vr1max;
            }
@@ -7631,7 +7863,7 @@ intersect_ranges (enum value_range_type *vr0type,
            {
              if (TREE_CODE (vr1min) == INTEGER_CST)
                *vr0max = int_const_binop (MINUS_EXPR, vr1min,
-                                          integer_one_node);
+                                          build_int_cst (TREE_TYPE (vr1min), 1));
              else
                *vr0max = vr1min;
            }
@@ -7677,7 +7909,7 @@ intersect_ranges (enum value_range_type *vr0type,
              *vr0type = VR_RANGE;
              if (TREE_CODE (*vr0max) == INTEGER_CST)
                *vr0min = int_const_binop (PLUS_EXPR, *vr0max,
-                                          integer_one_node);
+                                          build_int_cst (TREE_TYPE (*vr0max), 1));
              else
                *vr0min = *vr0max;
              *vr0max = vr1max;
@@ -7688,7 +7920,7 @@ intersect_ranges (enum value_range_type *vr0type,
              *vr0type = VR_RANGE;
              if (TREE_CODE (*vr0min) == INTEGER_CST)
                *vr0max = int_const_binop (MINUS_EXPR, *vr0min,
-                                          integer_one_node);
+                                          build_int_cst (TREE_TYPE (*vr0min), 1));
              else
                *vr0max = *vr0min;
              *vr0min = vr1min;
@@ -7740,7 +7972,7 @@ intersect_ranges (enum value_range_type *vr0type,
        {
          if (TREE_CODE (vr1min) == INTEGER_CST)
            *vr0max = int_const_binop (MINUS_EXPR, vr1min,
-                                      integer_one_node);
+                                      build_int_cst (TREE_TYPE (vr1min), 1));
          else
            *vr0max = vr1min;
        }
@@ -7750,7 +7982,7 @@ intersect_ranges (enum value_range_type *vr0type,
          *vr0type = VR_RANGE;
          if (TREE_CODE (*vr0max) == INTEGER_CST)
            *vr0min = int_const_binop (PLUS_EXPR, *vr0max,
-                                      integer_one_node);
+                                      build_int_cst (TREE_TYPE (*vr0max), 1));
          else
            *vr0min = *vr0max;
          *vr0max = vr1max;
@@ -7774,7 +8006,7 @@ intersect_ranges (enum value_range_type *vr0type,
        {
          if (TREE_CODE (vr1max) == INTEGER_CST)
            *vr0min = int_const_binop (PLUS_EXPR, vr1max,
-                                      integer_one_node);
+                                      build_int_cst (TREE_TYPE (vr1max), 1));
          else
            *vr0min = vr1max;
        }
@@ -7784,7 +8016,7 @@ intersect_ranges (enum value_range_type *vr0type,
          *vr0type = VR_RANGE;
          if (TREE_CODE (*vr0min) == INTEGER_CST)
            *vr0max = int_const_binop (MINUS_EXPR, *vr0min,
-                                      integer_one_node);
+                                      build_int_cst (TREE_TYPE (*vr0min), 1));
          else
            *vr0max = *vr0min;
          *vr0min = vr1min;
@@ -8037,10 +8269,7 @@ vrp_visit_phi_node (gimple phi)
          else
            {
              if (is_overflow_infinity (arg))
-               {
-                 arg = copy_node (arg);
-                 TREE_OVERFLOW (arg) = 0;
-               }
+               arg = drop_tree_overflow (arg);
 
              vr_arg.type = VR_RANGE;
              vr_arg.min = arg;
@@ -8194,7 +8423,8 @@ simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
   if (rhs_code == EQ_EXPR)
     {
       if (TREE_CODE (op1) == INTEGER_CST)
-       op1 = int_const_binop (BIT_XOR_EXPR, op1, integer_one_node);
+       op1 = int_const_binop (BIT_XOR_EXPR, op1, 
+                              build_int_cst (TREE_TYPE (op1), 1));
       else
        return false;
     }
@@ -8380,9 +8610,9 @@ simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
   tree op = NULL_TREE;
   value_range_t vr0 = VR_INITIALIZER;
   value_range_t vr1 = VR_INITIALIZER;
-  double_int may_be_nonzero0, may_be_nonzero1;
-  double_int must_be_nonzero0, must_be_nonzero1;
-  double_int mask;
+  wide_int may_be_nonzero0, may_be_nonzero1;
+  wide_int must_be_nonzero0, must_be_nonzero1;
+  wide_int mask;
 
   if (TREE_CODE (op0) == SSA_NAME)
     vr0 = *(get_value_range (op0));
@@ -8398,22 +8628,24 @@ simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
   else
     return false;
 
-  if (!zero_nonzero_bits_from_vr (&vr0, &may_be_nonzero0, &must_be_nonzero0))
+  if (!zero_nonzero_bits_from_vr (TREE_TYPE (op0), &vr0, &may_be_nonzero0,
+                                 &must_be_nonzero0))
     return false;
-  if (!zero_nonzero_bits_from_vr (&vr1, &may_be_nonzero1, &must_be_nonzero1))
+  if (!zero_nonzero_bits_from_vr (TREE_TYPE (op1), &vr1, &may_be_nonzero1,
+                                 &must_be_nonzero1))
     return false;
 
   switch (gimple_assign_rhs_code (stmt))
     {
     case BIT_AND_EXPR:
       mask = may_be_nonzero0.and_not (must_be_nonzero1);
-      if (mask.is_zero ())
+      if (mask == 0)
        {
          op = op0;
          break;
        }
       mask = may_be_nonzero1.and_not (must_be_nonzero0);
-      if (mask.is_zero ())
+      if (mask == 0)
        {
          op = op1;
          break;
@@ -8421,13 +8653,13 @@ simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
       break;
     case BIT_IOR_EXPR:
       mask = may_be_nonzero0.and_not (must_be_nonzero1);
-      if (mask.is_zero ())
+      if (mask == 0)
        {
          op = op1;
          break;
        }
       mask = may_be_nonzero1.and_not (must_be_nonzero0);
-      if (mask.is_zero ())
+      if (mask == 0)
        {
          op = op0;
          break;
@@ -8513,11 +8745,12 @@ test_for_singularity (enum tree_code cond_code, tree op0,
    by PRECISION and UNSIGNED_P.  */
 
 static bool
-range_fits_type_p (value_range_t *vr, unsigned precision, bool unsigned_p)
+range_fits_type_p (value_range_t *vr, unsigned dest_precision, signop dest_sgn)
 {
   tree src_type;
   unsigned src_precision;
-  double_int tem;
+  widest_int tem;
+  signop src_sgn;
 
   /* We can only handle integral and pointer types.  */
   src_type = TREE_TYPE (vr->min);
@@ -8525,13 +8758,13 @@ range_fits_type_p (value_range_t *vr, unsigned precision, bool unsigned_p)
       && !POINTER_TYPE_P (src_type))
     return false;
 
-  /* An extension is fine unless VR is signed and unsigned_p,
+  /* An extension is fine unless VR is SIGNED and dest_sgn is UNSIGNED,
      and so is an identity transform.  */
   src_precision = TYPE_PRECISION (TREE_TYPE (vr->min));
-  if ((src_precision < precision
-       && !(unsigned_p && !TYPE_UNSIGNED (src_type)))
-      || (src_precision == precision
-         && TYPE_UNSIGNED (src_type) == unsigned_p))
+  src_sgn = TYPE_SIGN (src_type);
+  if ((src_precision < dest_precision
+       && !(dest_sgn == UNSIGNED && src_sgn == SIGNED))
+      || (src_precision == dest_precision && src_sgn == dest_sgn))
     return true;
 
   /* Now we can only handle ranges with constant bounds.  */
@@ -8540,21 +8773,21 @@ range_fits_type_p (value_range_t *vr, unsigned precision, bool unsigned_p)
       || TREE_CODE (vr->max) != INTEGER_CST)
     return false;
 
-  /* For sign changes, the MSB of the double_int has to be clear.
+  /* For sign changes, the MSB of the wide_int has to be clear.
      An unsigned value with its MSB set cannot be represented by
-     a signed double_int, while a negative value cannot be represented
-     by an unsigned double_int.  */
-  if (TYPE_UNSIGNED (src_type) != unsigned_p
-      && (TREE_INT_CST_HIGH (vr->min) | TREE_INT_CST_HIGH (vr->max)) < 0)
+     a signed wide_int, while a negative value cannot be represented
+     by an unsigned wide_int.  */
+  if (src_sgn != dest_sgn
+      && (wi::lts_p (vr->min, 0) || wi::lts_p (vr->max, 0)))
     return false;
 
   /* Then we can perform the conversion on both ends and compare
      the result for equality.  */
-  tem = tree_to_double_int (vr->min).ext (precision, unsigned_p);
-  if (tree_to_double_int (vr->min) != tem)
+  tem = wi::ext (wi::to_widest (vr->min), dest_precision, dest_sgn);
+  if (tem != wi::to_widest (vr->min))
     return false;
-  tem = tree_to_double_int (vr->max).ext (precision, unsigned_p);
-  if (tree_to_double_int (vr->max) != tem)
+  tem = wi::ext (wi::to_widest (vr->max), dest_precision, dest_sgn);
+  if (tem != wi::to_widest (vr->max))
     return false;
 
   return true;
@@ -8661,15 +8894,41 @@ simplify_cond_using_ranges (gimple stmt)
 
       innerop = gimple_assign_rhs1 (def_stmt);
 
-      if (TREE_CODE (innerop) == SSA_NAME)
+      if (TREE_CODE (innerop) == SSA_NAME
+         && !POINTER_TYPE_P (TREE_TYPE (innerop)))
        {
          value_range_t *vr = get_value_range (innerop);
 
          if (range_int_cst_p (vr)
              && range_fits_type_p (vr,
                                    TYPE_PRECISION (TREE_TYPE (op0)),
-                                   TYPE_UNSIGNED (TREE_TYPE (op0))))
+                                   TYPE_SIGN (TREE_TYPE (op0)))
+             && int_fits_type_p (op1, TREE_TYPE (innerop))
+             /* The range must not have overflowed, or if it did overflow
+                we must not be wrapping/trapping overflow and optimizing
+                with strict overflow semantics.  */
+             && ((!is_negative_overflow_infinity (vr->min)
+                  && !is_positive_overflow_infinity (vr->max))
+                 || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (innerop))))
            {
+             /* If the range overflowed and the user has asked for warnings
+                when strict overflow semantics were used to optimize code,
+                issue an appropriate warning.  */
+             if ((is_negative_overflow_infinity (vr->min)
+                  || is_positive_overflow_infinity (vr->max))
+                 && issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_CONDITIONAL))
+               {
+                 location_t location;
+
+                 if (!gimple_has_location (stmt))
+                   location = input_location;
+                 else
+                   location = gimple_location (stmt);
+                 warning_at (location, OPT_Wstrict_overflow,
+                     "assuming signed overflow does not occur when "
+                     "simplifying conditional");
+               }
+
              tree newconst = fold_convert (TREE_TYPE (innerop), op1);
              gimple_cond_set_lhs (stmt, innerop);
              gimple_cond_set_rhs (stmt, newconst);
@@ -8788,9 +9047,9 @@ simplify_conversion_using_ranges (gimple stmt)
   tree innerop, middleop, finaltype;
   gimple def_stmt;
   value_range_t *innervr;
-  bool inner_unsigned_p, middle_unsigned_p, final_unsigned_p;
+  signop inner_sgn, middle_sgn, final_sgn;
   unsigned inner_prec, middle_prec, final_prec;
-  double_int innermin, innermed, innermax, middlemin, middlemed, middlemax;
+  widest_int innermin, innermed, innermax, middlemin, middlemed, middlemax;
 
   finaltype = TREE_TYPE (gimple_assign_lhs (stmt));
   if (!INTEGRAL_TYPE_P (finaltype))
@@ -8814,8 +9073,8 @@ simplify_conversion_using_ranges (gimple stmt)
 
   /* Simulate the conversion chain to check if the result is equal if
      the middle conversion is removed.  */
-  innermin = tree_to_double_int (innervr->min);
-  innermax = tree_to_double_int (innervr->max);
+  innermin = wi::to_widest (innervr->min);
+  innermax = wi::to_widest (innervr->max);
 
   inner_prec = TYPE_PRECISION (TREE_TYPE (innerop));
   middle_prec = TYPE_PRECISION (TREE_TYPE (middleop));
@@ -8823,34 +9082,35 @@ simplify_conversion_using_ranges (gimple stmt)
 
   /* If the first conversion is not injective, the second must not
      be widening.  */
-  if ((innermax - innermin).ugt (double_int::mask (middle_prec))
+  if (wi::gtu_p (innermax - innermin,
+                wi::mask <widest_int> (middle_prec, false))
       && middle_prec < final_prec)
     return false;
   /* We also want a medium value so that we can track the effect that
      narrowing conversions with sign change have.  */
-  inner_unsigned_p = TYPE_UNSIGNED (TREE_TYPE (innerop));
-  if (inner_unsigned_p)
-    innermed = double_int::mask (inner_prec).lrshift (1, inner_prec);
+  inner_sgn = TYPE_SIGN (TREE_TYPE (innerop));
+  if (inner_sgn == UNSIGNED)
+    innermed = wi::shifted_mask <widest_int> (1, inner_prec - 1, false);
   else
-    innermed = double_int_zero;
-  if (innermin.cmp (innermed, inner_unsigned_p) >= 0
-      || innermed.cmp (innermax, inner_unsigned_p) >= 0)
+    innermed = 0;
+  if (wi::cmp (innermin, innermed, inner_sgn) >= 0
+      || wi::cmp (innermed, innermax, inner_sgn) >= 0)
     innermed = innermin;
 
-  middle_unsigned_p = TYPE_UNSIGNED (TREE_TYPE (middleop));
-  middlemin = innermin.ext (middle_prec, middle_unsigned_p);
-  middlemed = innermed.ext (middle_prec, middle_unsigned_p);
-  middlemax = innermax.ext (middle_prec, middle_unsigned_p);
+  middle_sgn = TYPE_SIGN (TREE_TYPE (middleop));
+  middlemin = wi::ext (innermin, middle_prec, middle_sgn);
+  middlemed = wi::ext (innermed, middle_prec, middle_sgn);
+  middlemax = wi::ext (innermax, middle_prec, middle_sgn);
 
   /* Require that the final conversion applied to both the original
      and the intermediate range produces the same result.  */
-  final_unsigned_p = TYPE_UNSIGNED (finaltype);
-  if (middlemin.ext (final_prec, final_unsigned_p)
-        != innermin.ext (final_prec, final_unsigned_p)
-      || middlemed.ext (final_prec, final_unsigned_p)
-        != innermed.ext (final_prec, final_unsigned_p)
-      || middlemax.ext (final_prec, final_unsigned_p)
-        != innermax.ext (final_prec, final_unsigned_p))
+  final_sgn = TYPE_SIGN (finaltype);
+  if (wi::ext (middlemin, final_prec, final_sgn)
+        != wi::ext (innermin, final_prec, final_sgn)
+      || wi::ext (middlemed, final_prec, final_sgn)
+        != wi::ext (innermed, final_prec, final_sgn)
+      || wi::ext (middlemax, final_prec, final_sgn)
+        != wi::ext (innermax, final_prec, final_sgn))
     return false;
 
   gimple_assign_set_rhs1 (stmt, innerop);
@@ -8880,8 +9140,7 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
   if (TYPE_UNSIGNED (TREE_TYPE (rhs1))
       && (can_float_p (fltmode, TYPE_MODE (TREE_TYPE (rhs1)), 0)
          != CODE_FOR_nothing)
-      && range_fits_type_p (vr, GET_MODE_PRECISION
-                                 (TYPE_MODE (TREE_TYPE (rhs1))), 0))
+      && range_fits_type_p (vr, TYPE_PRECISION (TREE_TYPE (rhs1)), SIGNED))
     mode = TYPE_MODE (TREE_TYPE (rhs1));
   /* If we can do the conversion in the current input mode do nothing.  */
   else if (can_float_p (fltmode, TYPE_MODE (TREE_TYPE (rhs1)),
@@ -8898,7 +9157,7 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
             or if the value-range does not fit in the signed type
             try with a wider mode.  */
          if (can_float_p (fltmode, mode, 0) != CODE_FOR_nothing
-             && range_fits_type_p (vr, GET_MODE_PRECISION (mode), 0))
+             && range_fits_type_p (vr, GET_MODE_PRECISION (mode), SIGNED))
            break;
 
          mode = GET_MODE_WIDER_MODE (mode);
@@ -9083,15 +9342,27 @@ static vec<tree> equiv_stack;
 static tree
 simplify_stmt_for_jump_threading (gimple stmt, gimple within_stmt)
 {
-  /* We only use VRP information to simplify conditionals.  This is
-     overly conservative, but it's unclear if doing more would be
-     worth the compile time cost.  */
-  if (gimple_code (stmt) != GIMPLE_COND)
-    return NULL;
+  if (gimple_code (stmt) == GIMPLE_COND)
+    return vrp_evaluate_conditional (gimple_cond_code (stmt),
+                                    gimple_cond_lhs (stmt),
+                                    gimple_cond_rhs (stmt), within_stmt);
 
-  return vrp_evaluate_conditional (gimple_cond_code (stmt),
-                                  gimple_cond_lhs (stmt),
-                                  gimple_cond_rhs (stmt), within_stmt);
+  if (gimple_code (stmt) == GIMPLE_ASSIGN)
+    {
+      value_range_t new_vr = VR_INITIALIZER;
+      tree lhs = gimple_assign_lhs (stmt);
+
+      if (TREE_CODE (lhs) == SSA_NAME
+         && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+             || POINTER_TYPE_P (TREE_TYPE (lhs))))
+       {
+         extract_range_from_assignment (&new_vr, stmt);
+         if (range_int_cst_singleton_p (&new_vr))
+           return new_vr.min;
+       }
+    }
+
+  return NULL_TREE;
 }
 
 /* Blocks which have more than one predecessor and more than
@@ -9246,6 +9517,49 @@ vrp_finalize (void)
      the datastructures built by VRP.  */
   identify_jump_threads ();
 
+  /* Set value range to non pointer SSA_NAMEs.  */
+  for (i  = 0; i < num_vr_values; i++)
+    if (vr_value[i])
+      {
+       tree name = ssa_name (i);
+
+      if (!name
+         || POINTER_TYPE_P (TREE_TYPE (name))
+         || (vr_value[i]->type == VR_VARYING)
+         || (vr_value[i]->type == VR_UNDEFINED))
+       continue;
+
+       if ((TREE_CODE (vr_value[i]->min) == INTEGER_CST)
+           && (TREE_CODE (vr_value[i]->max) == INTEGER_CST))
+         {
+           if (vr_value[i]->type == VR_RANGE)
+             set_range_info (name, wi::to_widest (vr_value[i]->min),
+                             wi::to_widest (vr_value[i]->max));
+           else if (vr_value[i]->type == VR_ANTI_RANGE)
+             {
+               /* VR_ANTI_RANGE ~[min, max] is encoded compactly as
+                  [max + 1, min - 1] without additional attributes.
+                  When min value > max value, we know that it is
+                  VR_ANTI_RANGE; it is VR_RANGE otherwise.  */
+
+               /* ~[0,0] anti-range is represented as
+                  range.  */
+               if (TYPE_UNSIGNED (TREE_TYPE (name))
+                   && integer_zerop (vr_value[i]->min)
+                   && integer_zerop (vr_value[i]->max))
+                 {
+                   unsigned prec = TYPE_PRECISION (TREE_TYPE (name));
+                   set_range_info (name, 1,
+                                   wi::mask <widest_int> (prec, false));
+                 }
+               else
+                 set_range_info (name,
+                                 wi::to_widest (vr_value[i]->max) + 1,
+                                 wi::to_widest (vr_value[i]->min) - 1);
+             }
+         }
+      }
+
   /* Free allocated memory.  */
   for (i = 0; i < num_vr_values; i++)
     if (vr_value[i])
@@ -9394,25 +9708,43 @@ gate_vrp (void)
   return flag_tree_vrp != 0;
 }
 
-struct gimple_opt_pass pass_vrp =
-{
- {
-  GIMPLE_PASS,
-  "vrp",                               /* name */
-  OPTGROUP_NONE,                        /* optinfo_flags */
-  gate_vrp,                            /* gate */
-  execute_vrp,                         /* execute */
-  NULL,                                        /* sub */
-  NULL,                                        /* next */
-  0,                                   /* static_pass_number */
-  TV_TREE_VRP,                         /* tv_id */
-  PROP_ssa,                            /* properties_required */
-  0,                                   /* properties_provided */
-  0,                                   /* properties_destroyed */
-  0,                                   /* todo_flags_start */
-  TODO_cleanup_cfg
-    | TODO_update_ssa
+namespace {
+
+const pass_data pass_data_vrp =
+{
+  GIMPLE_PASS, /* type */
+  "vrp", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  true, /* has_gate */
+  true, /* has_execute */
+  TV_TREE_VRP, /* tv_id */
+  PROP_ssa, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  ( TODO_cleanup_cfg | TODO_update_ssa
     | TODO_verify_ssa
-    | TODO_verify_flow                 /* todo_flags_finish */
- }
+    | TODO_verify_flow ), /* todo_flags_finish */
 };
+
+class pass_vrp : public gimple_opt_pass
+{
+public:
+  pass_vrp (gcc::context *ctxt)
+    : gimple_opt_pass (pass_data_vrp, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  opt_pass * clone () { return new pass_vrp (m_ctxt); }
+  bool gate () { return gate_vrp (); }
+  unsigned int execute () { return execute_vrp (); }
+
+}; // class pass_vrp
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_vrp (gcc::context *ctxt)
+{
+  return new pass_vrp (ctxt);
+}