OSDN Git Service

2011-05-27 Alexander Monakov <amonakov@ispras.ru>
[pf3gnuchains/gcc-fork.git] / gcc / tree-vrp.c
index 35d12b3..8fcf629 100644 (file)
@@ -1,5 +1,5 @@
 /* Support routines for Value Range Propagation (VRP).
-   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010
+   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>.
 
@@ -34,12 +34,12 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-pretty-print.h"
 #include "gimple-pretty-print.h"
 #include "diagnostic-core.h"
-#include "toplev.h"
 #include "intl.h"
 #include "cfgloop.h"
 #include "tree-scalar-evolution.h"
 #include "tree-ssa-propagate.h"
 #include "tree-chrec.h"
+#include "gimple-fold.h"
 
 
 /* Type of value ranges.  See value_range_d for a description of these
@@ -243,9 +243,7 @@ supports_overflow_infinity (const_tree type)
 static inline tree
 make_overflow_infinity (tree val)
 {
-#ifdef ENABLE_CHECKING
-  gcc_assert (val != NULL_TREE && CONSTANT_CLASS_P (val));
-#endif
+  gcc_checking_assert (val != NULL_TREE && CONSTANT_CLASS_P (val));
   val = copy_node (val);
   TREE_OVERFLOW (val) = 1;
   return val;
@@ -256,9 +254,7 @@ make_overflow_infinity (tree val)
 static inline tree
 negative_overflow_infinity (tree type)
 {
-#ifdef ENABLE_CHECKING
-  gcc_assert (supports_overflow_infinity (type));
-#endif
+  gcc_checking_assert (supports_overflow_infinity (type));
   return make_overflow_infinity (vrp_val_min (type));
 }
 
@@ -267,9 +263,7 @@ negative_overflow_infinity (tree type)
 static inline tree
 positive_overflow_infinity (tree type)
 {
-#ifdef ENABLE_CHECKING
-  gcc_assert (supports_overflow_infinity (type));
-#endif
+  gcc_checking_assert (supports_overflow_infinity (type));
   return make_overflow_infinity (vrp_val_max (type));
 }
 
@@ -332,9 +326,7 @@ avoid_overflow_infinity (tree val)
     return vrp_val_max (TREE_TYPE (val));
   else
     {
-#ifdef ENABLE_CHECKING
-      gcc_assert (vrp_val_is_min (val));
-#endif
+      gcc_checking_assert (vrp_val_is_min (val));
       return vrp_val_min (TREE_TYPE (val));
     }
 }
@@ -480,8 +472,8 @@ set_and_canonicalize_value_range (value_range_t *vr, enum value_range_type t,
   if (tree_int_cst_lt (max, min))
     {
       tree one = build_int_cst (TREE_TYPE (min), 1);
-      tree tmp = int_const_binop (PLUS_EXPR, max, one, 0);
-      max = int_const_binop (MINUS_EXPR, min, one, 0);
+      tree tmp = int_const_binop (PLUS_EXPR, max, one);
+      max = int_const_binop (MINUS_EXPR, min, one);
       min = tmp;
 
       /* There's one corner case, if we had [C+1, C] before we now have
@@ -514,14 +506,14 @@ set_and_canonicalize_value_range (value_range_t *vr, enum value_range_type t,
                    && integer_zerop (max)))
         {
          tree one = build_int_cst (TREE_TYPE (max), 1);
-         min = int_const_binop (PLUS_EXPR, max, one, 0);
+         min = int_const_binop (PLUS_EXPR, max, one);
          max = vrp_val_max (TREE_TYPE (max));
          t = VR_RANGE;
         }
       else if (is_max)
         {
          tree one = build_int_cst (TREE_TYPE (min), 1);
-         max = int_const_binop (MINUS_EXPR, min, one, 0);
+         max = int_const_binop (MINUS_EXPR, min, one);
          min = vrp_val_min (TREE_TYPE (min));
          t = VR_RANGE;
         }
@@ -723,6 +715,8 @@ static inline bool
 vrp_bitmap_equal_p (const_bitmap b1, const_bitmap b2)
 {
   return (b1 == b2
+         || ((!b1 || bitmap_empty_p (b1))
+             && (!b2 || bitmap_empty_p (b2)))
          || (b1 && b2
              && bitmap_equal_p (b1, b2)));
 }
@@ -1532,7 +1526,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
         {
           min = fold_build1 (NEGATE_EXPR, TREE_TYPE (TREE_OPERAND (cond, 1)),
                             TREE_OPERAND (cond, 1));
-          max = int_const_binop (PLUS_EXPR, limit, min, 0);
+          max = int_const_binop (PLUS_EXPR, limit, min);
          cond = TREE_OPERAND (cond, 0);
        }
       else
@@ -1960,7 +1954,7 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2)
 {
   tree res;
 
-  res = int_const_binop (code, val1, val2, 0);
+  res = int_const_binop (code, val1, val2);
 
   /* If we are using unsigned arithmetic, operate symbolically
      on -INF and +INF as int_const_binop only handles signed overflow.  */
@@ -1987,7 +1981,7 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2)
        {
          tree tmp = int_const_binop (TRUNC_DIV_EXPR,
                                      res,
-                                     val1, 0);
+                                     val1);
          int check = compare_values (tmp, val2);
 
          if (check != 0)
@@ -2364,17 +2358,27 @@ extract_range_from_binary_expr (value_range_t *vr,
         op0 + op1 == 0, so we cannot claim that the sum is in ~[0,0].
         Note that we are guaranteed to have vr0.type == vr1.type at
         this point.  */
-      if (code == PLUS_EXPR && vr0.type == VR_ANTI_RANGE)
+      if (vr0.type == VR_ANTI_RANGE)
        {
-         set_value_range_to_varying (vr);
-         return;
+         if (code == PLUS_EXPR)
+           {
+             set_value_range_to_varying (vr);
+             return;
+           }
+         /* For MIN_EXPR and MAX_EXPR with two VR_ANTI_RANGEs,
+            the resulting VR_ANTI_RANGE is the same - intersection
+            of the two ranges.  */
+         min = vrp_int_const_binop (MAX_EXPR, vr0.min, vr1.min);
+         max = vrp_int_const_binop (MIN_EXPR, vr0.max, vr1.max);
+       }
+      else
+       {
+         /* For operations that make the resulting range directly
+            proportional to the original ranges, apply the operation to
+            the same end of each range.  */
+         min = vrp_int_const_binop (code, vr0.min, vr1.min);
+         max = vrp_int_const_binop (code, vr0.max, vr1.max);
        }
-
-      /* For operations that make the resulting range directly
-        proportional to the original ranges, apply the operation to
-        the same end of each range.  */
-      min = vrp_int_const_binop (code, vr0.min, vr1.min);
-      max = vrp_int_const_binop (code, vr0.max, vr1.max);
 
       /* If both additions overflowed the range kind is still correct.
         This happens regularly with subtracting something in unsigned
@@ -2464,6 +2468,22 @@ extract_range_from_binary_expr (value_range_t *vr,
            }
        }
 
+      /* For divisions, if flag_non_call_exceptions is true, we must
+        not eliminate a division by zero.  */
+      if ((code == TRUNC_DIV_EXPR
+          || code == FLOOR_DIV_EXPR
+          || code == CEIL_DIV_EXPR
+          || code == EXACT_DIV_EXPR
+          || code == ROUND_DIV_EXPR)
+         && cfun->can_throw_non_call_exceptions
+         && (vr1.type != VR_RANGE
+             || symbolic_range_p (&vr1)
+             || range_includes_zero_p (&vr1)))
+       {
+         set_value_range_to_varying (vr);
+         return;
+       }
+
       /* For divisions, if op0 is VR_RANGE, we can deduce a range
         even if op1 is VR_VARYING, VR_ANTI_RANGE, symbolic or can
         include 0.  */
@@ -2626,7 +2646,7 @@ extract_range_from_binary_expr (value_range_t *vr,
       max = fold_unary_to_constant (ABS_EXPR, TREE_TYPE (vr1.min), vr1.min);
       if (tree_int_cst_lt (max, vr1.max))
        max = vr1.max;
-      max = int_const_binop (MINUS_EXPR, max, integer_one_node, 0);
+      max = int_const_binop (MINUS_EXPR, max, integer_one_node);
       /* If the dividend is non-negative the modulus will be
         non-negative as well.  */
       if (TYPE_UNSIGNED (TREE_TYPE (max))
@@ -2671,7 +2691,7 @@ extract_range_from_binary_expr (value_range_t *vr,
 
       type = VR_RANGE;
       if (vr0_int_cst_singleton_p && vr1_int_cst_singleton_p)
-       min = max = int_const_binop (code, vr0.max, vr1.max, 0);
+       min = max = int_const_binop (code, vr0.max, vr1.max);
       else if (!int_cst_range0 && !int_cst_range1)
        {
          set_value_range_to_varying (vr);
@@ -2895,8 +2915,8 @@ extract_range_from_unary_expr (value_range_t *vr, enum tree_code code,
          && (TYPE_PRECISION (outer_type) >= TYPE_PRECISION (inner_type)
              || (vr0.type == VR_RANGE
                  && integer_zerop (int_const_binop (RSHIFT_EXPR,
-                      int_const_binop (MINUS_EXPR, vr0.max, vr0.min, 0),
-                        size_int (TYPE_PRECISION (outer_type)), 0)))))
+                      int_const_binop (MINUS_EXPR, vr0.max, vr0.min),
+                        size_int (TYPE_PRECISION (outer_type)))))))
        {
          tree new_min, new_max;
          new_min = force_fit_type_double (outer_type,
@@ -3063,7 +3083,7 @@ extract_range_from_unary_expr (value_range_t *vr, enum tree_code code,
 
                  min = (vr0.min != type_min_value
                         ? int_const_binop (PLUS_EXPR, type_min_value,
-                                           integer_one_node, 0)
+                                           integer_one_node)
                         : type_min_value);
                }
              else
@@ -3382,6 +3402,43 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop,
   else
     tmax = TYPE_MAX_VALUE (type);
 
+  /* Try to use estimated number of iterations for the loop to constrain the
+     final value in the evolution.
+     We are interested in the number of executions of the latch, while
+     nb_iterations_upper_bound includes the last execution of the exit test.  */
+  if (TREE_CODE (step) == INTEGER_CST
+      && loop->any_upper_bound
+      && !double_int_zero_p (loop->nb_iterations_upper_bound)
+      && is_gimple_val (init)
+      && (TREE_CODE (init) != SSA_NAME
+         || get_value_range (init)->type == VR_RANGE))
+    {
+      value_range_t maxvr = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
+      double_int dtmp;
+      bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (step));
+      int overflow = 0;
+
+      dtmp = double_int_mul_with_sign (tree_to_double_int (step),
+                                       double_int_sub (
+                                           loop->nb_iterations_upper_bound,
+                                           double_int_one),
+                                       unsigned_p, &overflow);
+      tem = double_int_to_tree (TREE_TYPE (init), dtmp);
+      /* If the multiplication overflowed we can't do a meaningful
+        adjustment.  */
+      if (!overflow && double_int_equal_p (dtmp, tree_to_double_int (tem)))
+       {
+         extract_range_from_binary_expr (&maxvr, PLUS_EXPR,
+                                         TREE_TYPE (init), init, tem);
+         /* Likewise if the addition did.  */
+         if (maxvr.type == VR_RANGE)
+           {
+             tmin = maxvr.min;
+             tmax = maxvr.max;
+           }
+       }
+    }
+
   if (vr->type == VR_VARYING || vr->type == VR_UNDEFINED)
     {
       min = tmin;
@@ -3414,40 +3471,35 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop,
          /* INIT is the maximum value.  If INIT is lower than VR->MAX
             but no smaller than VR->MIN, set VR->MAX to INIT.  */
          if (compare_values (init, max) == -1)
-           {
-             max = init;
-
-             /* If we just created an invalid range with the minimum
-                greater than the maximum, we fail conservatively.
-                This should happen only in unreachable
-                parts of code, or for invalid programs.  */
-             if (compare_values (min, max) == 1)
-               return;
-           }
+           max = init;
 
          /* According to the loop information, the variable does not
             overflow.  If we think it does, probably because of an
             overflow due to arithmetic on a different INF value,
             reset now.  */
-         if (is_negative_overflow_infinity (min))
+         if (is_negative_overflow_infinity (min)
+             || compare_values (min, tmin) == -1)
            min = tmin;
+
        }
       else
        {
          /* If INIT is bigger than VR->MIN, set VR->MIN to INIT.  */
          if (compare_values (init, min) == 1)
-           {
-             min = init;
-
-             /* Again, avoid creating invalid range by failing.  */
-             if (compare_values (min, max) == 1)
-               return;
-           }
+           min = init;
 
-         if (is_positive_overflow_infinity (max))
+         if (is_positive_overflow_infinity (max)
+             || compare_values (tmax, max) == -1)
            max = tmax;
        }
 
+      /* If we just created an invalid range with the minimum
+        greater than the maximum, we fail conservatively.
+        This should happen only in unreachable
+        parts of code, or for invalid programs.  */
+      if (compare_values (min, max) == 1)
+       return;
+
       set_value_range (vr, VR_RANGE, min, max, vr->equiv);
     }
 }
@@ -4104,13 +4156,11 @@ register_new_assert_for (tree name, tree expr,
   assert_locus_t n, loc, last_loc;
   basic_block dest_bb;
 
-#if defined ENABLE_CHECKING
-  gcc_assert (bb == NULL || e == NULL);
+  gcc_checking_assert (bb == NULL || e == NULL);
 
   if (e == NULL)
-    gcc_assert (gimple_code (gsi_stmt (si)) != GIMPLE_COND
-               && gimple_code (gsi_stmt (si)) != GIMPLE_SWITCH);
-#endif
+    gcc_checking_assert (gimple_code (gsi_stmt (si)) != GIMPLE_COND
+                        && gimple_code (gsi_stmt (si)) != GIMPLE_SWITCH);
 
   /* Never build an assert comparing against an integer constant with
      TREE_OVERFLOW set.  This confuses our undefined overflow warning
@@ -4623,28 +4673,35 @@ find_conditional_asserts (basic_block bb, gimple last)
   return need_assert;
 }
 
-/* Compare two case labels sorting first by the destination label uid
+struct case_info
+{
+  tree expr;
+  basic_block bb;
+};
+
+/* Compare two case labels sorting first by the destination bb index
    and then by the case value.  */
 
 static int
 compare_case_labels (const void *p1, const void *p2)
 {
-  const_tree const case1 = *(const_tree const*)p1;
-  const_tree const case2 = *(const_tree const*)p2;
-  unsigned int uid1 = DECL_UID (CASE_LABEL (case1));
-  unsigned int uid2 = DECL_UID (CASE_LABEL (case2));
+  const struct case_info *ci1 = (const struct case_info *) p1;
+  const struct case_info *ci2 = (const struct case_info *) p2;
+  int idx1 = ci1->bb->index;
+  int idx2 = ci2->bb->index;
 
-  if (uid1 < uid2)
+  if (idx1 < idx2)
     return -1;
-  else if (uid1 == uid2)
+  else if (idx1 == idx2)
     {
       /* Make sure the default label is first in a group.  */
-      if (!CASE_LOW (case1))
+      if (!CASE_LOW (ci1->expr))
        return -1;
-      else if (!CASE_LOW (case2))
+      else if (!CASE_LOW (ci2->expr))
        return 1;
       else
-        return tree_int_cst_compare (CASE_LOW (case1), CASE_LOW (case2));
+       return tree_int_cst_compare (CASE_LOW (ci1->expr),
+                                    CASE_LOW (ci2->expr));
     }
   else
     return 1;
@@ -4665,8 +4722,8 @@ find_switch_asserts (basic_block bb, gimple last)
   gimple_stmt_iterator bsi;
   tree op;
   edge e;
-  tree vec2;
-  size_t n = gimple_switch_num_labels(last);
+  struct case_info *ci;
+  size_t n = gimple_switch_num_labels (last);
 #if GCC_VERSION >= 4000
   unsigned int idx;
 #else
@@ -4681,36 +4738,38 @@ find_switch_asserts (basic_block bb, gimple last)
     return false;
 
   /* Build a vector of case labels sorted by destination label.  */
-  vec2 = make_tree_vec (n);
+  ci = XNEWVEC (struct case_info, n);
   for (idx = 0; idx < n; ++idx)
-    TREE_VEC_ELT (vec2, idx) = gimple_switch_label (last, idx);
-  qsort (&TREE_VEC_ELT (vec2, 0), n, sizeof (tree), compare_case_labels);
+    {
+      ci[idx].expr = gimple_switch_label (last, idx);
+      ci[idx].bb = label_to_block (CASE_LABEL (ci[idx].expr));
+    }
+  qsort (ci, n, sizeof (struct case_info), compare_case_labels);
 
   for (idx = 0; idx < n; ++idx)
     {
       tree min, max;
-      tree cl = TREE_VEC_ELT (vec2, idx);
+      tree cl = ci[idx].expr;
+      basic_block cbb = ci[idx].bb;
 
       min = CASE_LOW (cl);
       max = CASE_HIGH (cl);
 
       /* If there are multiple case labels with the same destination
         we need to combine them to a single value range for the edge.  */
-      if (idx + 1 < n
-         && CASE_LABEL (cl) == CASE_LABEL (TREE_VEC_ELT (vec2, idx + 1)))
+      if (idx + 1 < n && cbb == ci[idx + 1].bb)
        {
          /* Skip labels until the last of the group.  */
          do {
            ++idx;
-         } while (idx < n
-                  && CASE_LABEL (cl) == CASE_LABEL (TREE_VEC_ELT (vec2, idx)));
+         } while (idx < n && cbb == ci[idx].bb);
          --idx;
 
          /* Pick up the maximum of the case label range.  */
-         if (CASE_HIGH (TREE_VEC_ELT (vec2, idx)))
-           max = CASE_HIGH (TREE_VEC_ELT (vec2, idx));
+         if (CASE_HIGH (ci[idx].expr))
+           max = CASE_HIGH (ci[idx].expr);
          else
-           max = CASE_LOW (TREE_VEC_ELT (vec2, idx));
+           max = CASE_LOW (ci[idx].expr);
        }
 
       /* Nothing to do if the range includes the default label until we
@@ -4719,7 +4778,7 @@ find_switch_asserts (basic_block bb, gimple last)
        continue;
 
       /* Find the edge to register the assert expr on.  */
-      e = find_edge (bb, label_to_block (CASE_LABEL (cl)));
+      e = find_edge (bb, cbb);
 
       /* Register the necessary assertions for the operand in the
         SWITCH_EXPR.  */
@@ -4737,6 +4796,7 @@ find_switch_asserts (basic_block bb, gimple last)
        }
     }
 
+  XDELETEVEC (ci);
   return need_assert;
 }
 
@@ -5032,10 +5092,9 @@ process_assert_insertions_for (tree name, assert_locus_t loc)
     {
       /* We have been asked to insert the assertion on an edge.  This
         is used only by COND_EXPR and SWITCH_EXPR assertions.  */
-#if defined ENABLE_CHECKING
-      gcc_assert (gimple_code (gsi_stmt (loc->si)) == GIMPLE_COND
-         || gimple_code (gsi_stmt (loc->si)) == GIMPLE_SWITCH);
-#endif
+      gcc_checking_assert (gimple_code (gsi_stmt (loc->si)) == GIMPLE_COND
+                          || (gimple_code (gsi_stmt (loc->si))
+                              == GIMPLE_SWITCH));
 
       gsi_insert_on_edge (loc->e, assert_stmt);
       return true;
@@ -5209,7 +5268,7 @@ 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, 0);
+  up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound, integer_one_node);
 
   if (TREE_CODE (low_sub) == SSA_NAME)
     {
@@ -5576,6 +5635,21 @@ vrp_initialize (void)
     }
 }
 
+/* Return the singleton value-range for NAME or NAME.  */
+
+static inline tree
+vrp_valueize (tree name)
+{
+  if (TREE_CODE (name) == SSA_NAME)
+    {
+      value_range_t *vr = get_value_range (name);
+      if (vr->type == VR_RANGE
+         && (vr->min == vr->max
+             || operand_equal_p (vr->min, vr->max, 0)))
+       return vr->min;
+    }
+  return name;
+}
 
 /* Visit assignment STMT.  If it produces an interesting range, record
    the SSA name in *OUTPUT_P.  */
@@ -5599,7 +5673,12 @@ vrp_visit_assignment_or_call (gimple stmt, tree *output_p)
     {
       value_range_t new_vr = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
 
-      if (code == GIMPLE_CALL)
+      /* Try folding the statement to a constant first.  */
+      tree tem = gimple_fold_stmt_to_constant (stmt, vrp_valueize);
+      if (tem && !is_overflow_infinity (tem))
+       set_value_range (&new_vr, VR_RANGE, tem, tem, NULL);
+      /* Then dispatch to value-range extracting functions.  */
+      else if (code == GIMPLE_CALL)
        extract_range_basic (&new_vr, stmt);
       else
        extract_range_from_assignment (&new_vr, stmt);
@@ -6201,7 +6280,7 @@ find_case_label_range (gimple stmt, tree min, tree max, size_t *min_idx,
       for (k = i + 1; k <= j; ++k)
        {
          low = CASE_LOW (gimple_switch_label (stmt, k));
-         if (!integer_onep (int_const_binop (MINUS_EXPR, low, high, 0)))
+         if (!integer_onep (int_const_binop (MINUS_EXPR, low, high)))
            {
              take_default = true;
              break;
@@ -6328,7 +6407,6 @@ vrp_visit_stmt (gimple stmt, edge *taken_edge_p, tree *output_p)
       /* 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_IS_BUILTIN (gimple_call_fndecl (stmt)))
@@ -6509,8 +6587,6 @@ vrp_visit_phi_node (gimple phi)
   int edges, old_edges;
   struct loop *l;
 
-  copy_value_range (&vr_result, lhs_vr);
-
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
       fprintf (dump_file, "\nVisiting PHI node: ");
@@ -6571,13 +6647,6 @@ vrp_visit_phi_node (gimple phi)
        }
     }
 
-  /* If this is a loop PHI node SCEV may known more about its
-     value-range.  */
-  if (current_loops
-      && (l = loop_containing_stmt (phi))
-      && l->header == gimple_bb (phi))
-    adjust_range_with_scev (&vr_result, l, phi, lhs);
-
   if (vr_result.type == VR_VARYING)
     goto varying;
 
@@ -6589,61 +6658,64 @@ vrp_visit_phi_node (gimple phi)
      previous one.  We don't do this if we have seen a new executable
      edge; this helps us avoid an overflow infinity for conditionals
      which are not in a loop.  */
-  if (lhs_vr->type == VR_RANGE && vr_result.type == VR_RANGE
-      && edges <= old_edges)
-    {
-      if (!POINTER_TYPE_P (TREE_TYPE (lhs)))
-       {
-         int cmp_min = compare_values (lhs_vr->min, vr_result.min);
-         int cmp_max = compare_values (lhs_vr->max, vr_result.max);
-
-         /* If the new minimum is smaller or larger than the previous
-            one, go all the way to -INF.  In the first case, to avoid
-            iterating millions of times to reach -INF, and in the
-            other case to avoid infinite bouncing between different
-            minimums.  */
-         if (cmp_min > 0 || cmp_min < 0)
-           {
-             /* If we will end up with a (-INF, +INF) range, set it to
-                VARYING.  Same if the previous max value was invalid for
-                the type and we'd end up with vr_result.min > vr_result.max.  */
-             if (vrp_val_is_max (vr_result.max)
-                 || compare_values (TYPE_MIN_VALUE (TREE_TYPE (vr_result.min)),
-                                    vr_result.max) > 0)
-               goto varying;
-
-             if (!needs_overflow_infinity (TREE_TYPE (vr_result.min))
-                 || !vrp_var_may_overflow (lhs, phi))
-               vr_result.min = TYPE_MIN_VALUE (TREE_TYPE (vr_result.min));
-             else if (supports_overflow_infinity (TREE_TYPE (vr_result.min)))
-               vr_result.min =
-                 negative_overflow_infinity (TREE_TYPE (vr_result.min));
-             else
-               goto varying;
-           }
-
-         /* Similarly, if the new maximum is smaller or larger than
-            the previous one, go all the way to +INF.  */
-         if (cmp_max < 0 || cmp_max > 0)
-           {
-             /* If we will end up with a (-INF, +INF) range, set it to
-                VARYING.  Same if the previous min value was invalid for
-                the type and we'd end up with vr_result.max < vr_result.min.  */
-             if (vrp_val_is_min (vr_result.min)
-                 || compare_values (TYPE_MAX_VALUE (TREE_TYPE (vr_result.max)),
-                                    vr_result.min) < 0)
-               goto varying;
-
-             if (!needs_overflow_infinity (TREE_TYPE (vr_result.max))
-                 || !vrp_var_may_overflow (lhs, phi))
-               vr_result.max = TYPE_MAX_VALUE (TREE_TYPE (vr_result.max));
-             else if (supports_overflow_infinity (TREE_TYPE (vr_result.max)))
-               vr_result.max =
-                 positive_overflow_infinity (TREE_TYPE (vr_result.max));
-             else
-               goto varying;
-           }
-       }
+  if (edges > 0
+      && gimple_phi_num_args (phi) > 1
+      && edges == old_edges)
+    {
+      int cmp_min = compare_values (lhs_vr->min, vr_result.min);
+      int cmp_max = compare_values (lhs_vr->max, vr_result.max);
+
+      /* For non VR_RANGE or for pointers fall back to varying if
+        the range changed.  */
+      if ((lhs_vr->type != VR_RANGE || vr_result.type != VR_RANGE
+          || POINTER_TYPE_P (TREE_TYPE (lhs)))
+         && (cmp_min != 0 || cmp_max != 0))
+       goto varying;
+
+      /* If the new minimum is smaller or larger than the previous
+        one, go all the way to -INF.  In the first case, to avoid
+        iterating millions of times to reach -INF, and in the
+        other case to avoid infinite bouncing between different
+        minimums.  */
+      if (cmp_min > 0 || cmp_min < 0)
+       {
+         if (!needs_overflow_infinity (TREE_TYPE (vr_result.min))
+             || !vrp_var_may_overflow (lhs, phi))
+           vr_result.min = TYPE_MIN_VALUE (TREE_TYPE (vr_result.min));
+         else if (supports_overflow_infinity (TREE_TYPE (vr_result.min)))
+           vr_result.min =
+               negative_overflow_infinity (TREE_TYPE (vr_result.min));
+       }
+
+      /* Similarly, if the new maximum is smaller or larger than
+        the previous one, go all the way to +INF.  */
+      if (cmp_max < 0 || cmp_max > 0)
+       {
+         if (!needs_overflow_infinity (TREE_TYPE (vr_result.max))
+             || !vrp_var_may_overflow (lhs, phi))
+           vr_result.max = TYPE_MAX_VALUE (TREE_TYPE (vr_result.max));
+         else if (supports_overflow_infinity (TREE_TYPE (vr_result.max)))
+           vr_result.max =
+               positive_overflow_infinity (TREE_TYPE (vr_result.max));
+       }
+
+      /* If we dropped either bound to +-INF then if this is a loop
+        PHI node SCEV may known more about its value-range.  */
+      if ((cmp_min > 0 || cmp_min < 0
+          || cmp_max < 0 || cmp_max > 0)
+         && current_loops
+         && (l = loop_containing_stmt (phi))
+         && l->header == gimple_bb (phi))
+       adjust_range_with_scev (&vr_result, l, phi, lhs);
+
+      /* If we will end up with a (-INF, +INF) range, set it to
+        VARYING.  Same if the previous max value was invalid for
+        the type and we end up with vr_result.min > vr_result.max.  */
+      if ((vrp_val_is_max (vr_result.max)
+          && vrp_val_is_min (vr_result.min))
+         || compare_values (vr_result.min,
+                            vr_result.max) > 0)
+       goto varying;
     }
 
   /* If the new range is different than the previous value, keep
@@ -6857,7 +6929,7 @@ simplify_div_or_mod_using_ranges (gimple stmt)
 
       if (rhs_code == TRUNC_DIV_EXPR)
        {
-         t = build_int_cst (NULL_TREE, tree_log2 (op1));
+         t = build_int_cst (integer_type_node, tree_log2 (op1));
          gimple_assign_set_rhs_code (stmt, RSHIFT_EXPR);
          gimple_assign_set_rhs1 (stmt, op0);
          gimple_assign_set_rhs2 (stmt, t);
@@ -6865,7 +6937,7 @@ simplify_div_or_mod_using_ranges (gimple stmt)
       else
        {
          t = build_int_cst (TREE_TYPE (op1), 1);
-         t = int_const_binop (MINUS_EXPR, op1, t, 0);
+         t = int_const_binop (MINUS_EXPR, op1, t);
          t = fold_convert (TREE_TYPE (op0), t);
 
          gimple_assign_set_rhs_code (stmt, BIT_AND_EXPR);
@@ -7470,7 +7542,7 @@ identify_jump_threads (void)
 
   /* Do not thread across edges we are about to remove.  Just marking
      them as EDGE_DFS_BACK will do.  */
-  for (i = 0; VEC_iterate (edge, to_remove_edges, i, e); ++i)
+  FOR_EACH_VEC_ELT (edge, to_remove_edges, i, e)
     e->flags |= EDGE_DFS_BACK;
 
   /* Allocate our unwinder stack to unwind any temporary equivalences
@@ -7503,23 +7575,25 @@ identify_jump_threads (void)
         may be some value in handling SWITCH_EXPR here, I doubt it's
         terribly important.  */
       last = gsi_stmt (gsi_last_bb (bb));
-      if (gimple_code (last) != GIMPLE_COND)
-       continue;
 
-      /* We're basically looking for any kind of conditional with
-        integral type arguments.  */
-      if (TREE_CODE (gimple_cond_lhs (last)) == SSA_NAME
-         && INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (last)))
-         && (TREE_CODE (gimple_cond_rhs (last)) == SSA_NAME
-             || is_gimple_min_invariant (gimple_cond_rhs (last)))
-         && INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_rhs (last))))
+      /* We're basically looking for a switch or any kind of conditional with
+        integral or pointer type arguments.  Note the type of the second
+        argument will be the same as the first argument, so no need to
+        check it explicitly.  */
+      if (gimple_code (last) == GIMPLE_SWITCH
+         || (gimple_code (last) == GIMPLE_COND
+             && TREE_CODE (gimple_cond_lhs (last)) == SSA_NAME
+             && (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (last)))
+                 || POINTER_TYPE_P (TREE_TYPE (gimple_cond_lhs (last))))
+             && (TREE_CODE (gimple_cond_rhs (last)) == SSA_NAME
+                 || is_gimple_min_invariant (gimple_cond_rhs (last)))))
        {
          edge_iterator ei;
 
          /* We've got a block with multiple predecessors and multiple
-            successors which also ends in a suitable conditional.  For
-            each predecessor, see if we can thread it to a specific
-            successor.  */
+            successors which also ends in a suitable conditional or
+            switch statement.  For each predecessor, see if we can thread
+            it to a specific successor.  */
          FOR_EACH_EDGE (e, ei, bb->preds)
            {
              /* Do not thread across back edges or abnormal edges
@@ -7650,6 +7724,12 @@ execute_vrp (void)
   rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
   scev_initialize ();
 
+  /* Estimate number of iterations - but do not use undefined behavior
+     for this.  We can't do this lazily as other functions may compute
+     this using undefined behavior.  */
+  free_numbers_of_iterations_estimates ();
+  estimate_numbers_of_iterations (false);
+
   insert_range_assertions ();
 
   to_remove_edges = VEC_alloc (edge, heap, 10);
@@ -7676,10 +7756,10 @@ execute_vrp (void)
 
   /* Remove dead edges from SWITCH_EXPR optimization.  This leaves the
      CFG in a broken state and requires a cfg_cleanup run.  */
-  for (i = 0; VEC_iterate (edge, to_remove_edges, i, e); ++i)
+  FOR_EACH_VEC_ELT (edge, to_remove_edges, i, e)
     remove_edge (e);
   /* Update SWITCH_EXPR case label vector.  */
-  for (i = 0; VEC_iterate (switch_update, to_update_switch_stmts, i, su); ++i)
+  FOR_EACH_VEC_ELT (switch_update, to_update_switch_stmts, i, su)
     {
       size_t j;
       size_t n = TREE_VEC_LENGTH (su->vec);
@@ -7729,9 +7809,10 @@ struct gimple_opt_pass pass_vrp =
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
   TODO_cleanup_cfg
-    | TODO_ggc_collect
+    | TODO_update_ssa
     | TODO_verify_ssa
+    | TODO_verify_flow
     | TODO_dump_func
-    | TODO_update_ssa                  /* todo_flags_finish */
+    | TODO_ggc_collect                 /* todo_flags_finish */
  }
 };