PR c++/68795: fix uninitialized close_paren_loc in cp_parser_postfix_expression
[gcc.git] / gcc / tree-vrp.c
index 7ca05284ede099a4cb3aa1f6117f6e2910a78e9e..920a9b1818dabc0521d62b2c74a10c2973e3c1a0 100644 (file)
@@ -1,5 +1,5 @@
 /* Support routines for Value Range Propagation (VRP).
-   Copyright (C) 2005-2014 Free Software Foundation, Inc.
+   Copyright (C) 2005-2016 Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>.
 
 This file is part of GCC.
@@ -21,52 +21,47 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
-#include "flags.h"
+#include "backend.h"
+#include "insn-codes.h"
+#include "rtl.h"
 #include "tree.h"
+#include "gimple.h"
+#include "cfghooks.h"
+#include "tree-pass.h"
+#include "ssa.h"
+#include "optabs-tree.h"
+#include "gimple-pretty-print.h"
+#include "diagnostic-core.h"
+#include "flags.h"
+#include "fold-const.h"
 #include "stor-layout.h"
 #include "calls.h"
-#include "basic-block.h"
-#include "tree-ssa-alias.h"
-#include "internal-fn.h"
+#include "cfganal.h"
 #include "gimple-fold.h"
 #include "tree-eh.h"
-#include "gimple-expr.h"
-#include "is-a.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"
-#include "diagnostic-core.h"
 #include "intl.h"
 #include "cfgloop.h"
 #include "tree-scalar-evolution.h"
 #include "tree-ssa-propagate.h"
 #include "tree-chrec.h"
 #include "tree-ssa-threadupdate.h"
-#include "expr.h"
-#include "optabs.h"
+#include "tree-ssa-scopedtables.h"
 #include "tree-ssa-threadedge.h"
-#include "wide-int.h"
-
-
+#include "omp-low.h"
+#include "target.h"
+#include "case-cfn-macros.h"
 
 /* Range of values that can be associated with an SSA_NAME after VRP
    has executed.  */
-struct value_range_d
+struct value_range
 {
   /* Lattice value represented by this range.  */
   enum value_range_type type;
@@ -90,8 +85,6 @@ struct value_range_d
   bitmap equiv;
 };
 
-typedef struct value_range_d value_range_t;
-
 #define VR_INITIALIZER { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL }
 
 /* Set of SSA names found live during the RPO traversal of the function
@@ -110,8 +103,8 @@ live_on_edge (edge e, tree name)
 /* Local functions.  */
 static int compare_values (tree val1, tree val2);
 static int compare_values_warnv (tree val1, tree val2, bool *);
-static void vrp_meet (value_range_t *, value_range_t *);
-static void vrp_intersect_ranges (value_range_t *, value_range_t *);
+static void vrp_meet (value_range *, value_range *);
+static void vrp_intersect_ranges (value_range *, value_range *);
 static tree vrp_evaluate_conditional_warnv_with_ops (enum tree_code,
                                                     tree, tree, bool, bool *,
                                                     bool *);
@@ -121,7 +114,7 @@ static tree vrp_evaluate_conditional_warnv_with_ops (enum tree_code,
    SSA name may have more than one assertion associated with it, these
    locations are kept in a linked list attached to the corresponding
    SSA name.  */
-struct assert_locus_d
+struct assert_locus
 {
   /* Basic block where the assertion would be inserted.  */
   basic_block bb;
@@ -143,11 +136,9 @@ struct assert_locus_d
   tree expr;
 
   /* Next node in the linked list.  */
-  struct assert_locus_d *next;
+  assert_locus *next;
 };
 
-typedef struct assert_locus_d *assert_locus_t;
-
 /* If bit I is present, it means that SSA name N_i has a list of
    assertions that should be inserted in the IL.  */
 static bitmap need_assert_for;
@@ -155,12 +146,12 @@ static bitmap need_assert_for;
 /* Array of locations lists where to insert assertions.  ASSERTS_FOR[I]
    holds a list of ASSERT_LOCUS_T nodes that describe where
    ASSERT_EXPRs for SSA name N_I should be inserted.  */
-static assert_locus_t *asserts_for;
+static assert_locus **asserts_for;
 
 /* Value range array.  After propagation, VR_VALUE[I] holds the range
    of values that SSA name N_I may take.  */
 static unsigned num_vr_values;
-static value_range_t **vr_value;
+static value_range **vr_value;
 static bool values_propagated;
 
 /* For a PHI node which sets SSA name N_I, VR_COUNTS[I] holds the
@@ -168,10 +159,10 @@ static bool values_propagated;
    node.  */
 static int *vr_phi_edge_counts;
 
-typedef struct {
-  gimple stmt;
+struct switch_update {
+  gswitch *stmt;
   tree vec;
-} switch_update;
+};
 
 static vec<edge> to_remove_edges;
 static vec<switch_update> to_update_switch_stmts;
@@ -249,9 +240,7 @@ static inline bool
 supports_overflow_infinity (const_tree type)
 {
   tree min = vrp_val_min (type), max = vrp_val_max (type);
-#ifdef ENABLE_CHECKING
-  gcc_assert (needs_overflow_infinity (type));
-#endif
+  gcc_checking_assert (needs_overflow_infinity (type));
   return (min != NULL_TREE
          && CONSTANT_CLASS_P (min)
          && max != NULL_TREE
@@ -321,7 +310,7 @@ is_overflow_infinity (const_tree val)
 /* Return whether STMT has a constant rhs that is_overflow_infinity. */
 
 static inline bool
-stmt_overflow_infinity (gimple stmt)
+stmt_overflow_infinity (gimple *stmt)
 {
   if (is_gimple_assign (stmt)
       && get_gimple_rhs_class (gimple_assign_rhs_code (stmt)) ==
@@ -350,61 +339,10 @@ avoid_overflow_infinity (tree val)
 }
 
 
-/* Return true if ARG is marked with the nonnull attribute in the
-   current function signature.  */
-
-static bool
-nonnull_arg_p (const_tree arg)
-{
-  tree t, attrs, fntype;
-  unsigned HOST_WIDE_INT arg_num;
-
-  gcc_assert (TREE_CODE (arg) == PARM_DECL && POINTER_TYPE_P (TREE_TYPE (arg)));
-
-  /* The static chain decl is always non null.  */
-  if (arg == cfun->static_chain_decl)
-    return true;
-
-  fntype = TREE_TYPE (current_function_decl);
-  for (attrs = TYPE_ATTRIBUTES (fntype); attrs; attrs = TREE_CHAIN (attrs))
-    {
-      attrs = lookup_attribute ("nonnull", attrs);
-
-      /* If "nonnull" wasn't specified, we know nothing about the argument.  */
-      if (attrs == NULL_TREE)
-       return false;
-
-      /* If "nonnull" applies to all the arguments, then ARG is non-null.  */
-      if (TREE_VALUE (attrs) == NULL_TREE)
-       return true;
-
-      /* Get the position number for ARG in the function signature.  */
-      for (arg_num = 1, t = DECL_ARGUMENTS (current_function_decl);
-          t;
-          t = DECL_CHAIN (t), arg_num++)
-       {
-         if (t == arg)
-           break;
-       }
-
-      gcc_assert (t == arg);
-
-      /* Now see if ARG_NUM is mentioned in the nonnull list.  */
-      for (t = TREE_VALUE (attrs); t; t = TREE_CHAIN (t))
-       {
-         if (compare_tree_int (TREE_VALUE (t), arg_num) == 0)
-           return true;
-       }
-    }
-
-  return false;
-}
-
-
 /* Set value range VR to VR_UNDEFINED.  */
 
 static inline void
-set_value_range_to_undefined (value_range_t *vr)
+set_value_range_to_undefined (value_range *vr)
 {
   vr->type = VR_UNDEFINED;
   vr->min = vr->max = NULL_TREE;
@@ -416,7 +354,7 @@ set_value_range_to_undefined (value_range_t *vr)
 /* Set value range VR to VR_VARYING.  */
 
 static inline void
-set_value_range_to_varying (value_range_t *vr)
+set_value_range_to_varying (value_range *vr)
 {
   vr->type = VR_VARYING;
   vr->min = vr->max = NULL_TREE;
@@ -428,12 +366,12 @@ set_value_range_to_varying (value_range_t *vr)
 /* Set value range VR to {T, MIN, MAX, EQUIV}.  */
 
 static void
-set_value_range (value_range_t *vr, enum value_range_type t, tree min,
+set_value_range (value_range *vr, enum value_range_type t, tree min,
                 tree max, bitmap equiv)
 {
-#if defined ENABLE_CHECKING
   /* Check the validity of the range.  */
-  if (t == VR_RANGE || t == VR_ANTI_RANGE)
+  if (flag_checking
+      && (t == VR_RANGE || t == VR_ANTI_RANGE))
     {
       int cmp;
 
@@ -453,12 +391,12 @@ set_value_range (value_range_t *vr, enum value_range_type t, tree min,
                    || !is_overflow_infinity (max));
     }
 
-  if (t == VR_UNDEFINED || t == VR_VARYING)
-    gcc_assert (min == NULL_TREE && max == NULL_TREE);
-
-  if (t == VR_UNDEFINED || t == VR_VARYING)
-    gcc_assert (equiv == NULL || bitmap_empty_p (equiv));
-#endif
+  if (flag_checking
+      && (t == VR_UNDEFINED || t == VR_VARYING))
+    {
+      gcc_assert (min == NULL_TREE && max == NULL_TREE);
+      gcc_assert (equiv == NULL || bitmap_empty_p (equiv));
+    }
 
   vr->type = t;
   vr->min = min;
@@ -490,7 +428,7 @@ set_value_range (value_range_t *vr, enum value_range_type t, tree min,
    extract ranges from var + CST op limit.  */
 
 static void
-set_and_canonicalize_value_range (value_range_t *vr, enum value_range_type t,
+set_and_canonicalize_value_range (value_range *vr, enum value_range_type t,
                                  tree min, tree max, bitmap equiv)
 {
   /* Use the canonical setters for VR_UNDEFINED and VR_VARYING.  */
@@ -603,7 +541,7 @@ set_and_canonicalize_value_range (value_range_t *vr, enum value_range_type t,
 /* Copy value range FROM into value range TO.  */
 
 static inline void
-copy_value_range (value_range_t *to, value_range_t *from)
+copy_value_range (value_range *to, value_range *from)
 {
   set_value_range (to, from->type, from->min, from->max, from->equiv);
 }
@@ -614,7 +552,7 @@ copy_value_range (value_range_t *to, value_range_t *from)
    infinity when we shouldn't.  */
 
 static inline void
-set_value_range_to_value (value_range_t *vr, tree val, bitmap equiv)
+set_value_range_to_value (value_range *vr, tree val, bitmap equiv)
 {
   gcc_assert (is_gimple_min_invariant (val));
   if (TREE_OVERFLOW_P (val))
@@ -629,7 +567,7 @@ set_value_range_to_value (value_range_t *vr, tree val, bitmap equiv)
    overflow does not occur.  */
 
 static inline void
-set_value_range_to_nonnegative (value_range_t *vr, tree type,
+set_value_range_to_nonnegative (value_range *vr, tree type,
                                bool overflow_infinity)
 {
   tree zero;
@@ -651,7 +589,7 @@ set_value_range_to_nonnegative (value_range_t *vr, tree type,
 /* Set value range VR to a non-NULL range of type TYPE.  */
 
 static inline void
-set_value_range_to_nonnull (value_range_t *vr, tree type)
+set_value_range_to_nonnull (value_range *vr, tree type)
 {
   tree zero = build_int_cst (type, 0);
   set_value_range (vr, VR_ANTI_RANGE, zero, zero, vr->equiv);
@@ -661,7 +599,7 @@ set_value_range_to_nonnull (value_range_t *vr, tree type)
 /* Set value range VR to a NULL range of type TYPE.  */
 
 static inline void
-set_value_range_to_null (value_range_t *vr, tree type)
+set_value_range_to_null (value_range *vr, tree type)
 {
   set_value_range_to_value (vr, build_int_cst (type, 0), vr->equiv);
 }
@@ -670,7 +608,7 @@ set_value_range_to_null (value_range_t *vr, tree type)
 /* Set value range VR to a range of a truthvalue of type TYPE.  */
 
 static inline void
-set_value_range_to_truthvalue (value_range_t *vr, tree type)
+set_value_range_to_truthvalue (value_range *vr, tree type)
 {
   if (TYPE_PRECISION (type) == 1)
     set_value_range_to_varying (vr);
@@ -685,7 +623,7 @@ set_value_range_to_truthvalue (value_range_t *vr, tree type)
    abs (min) >= abs (max), set VR to [-min, min].  */
 
 static void
-abs_extent_range (value_range_t *vr, tree min, tree max)
+abs_extent_range (value_range *vr, tree min, tree max)
 {
   int cmp;
 
@@ -722,12 +660,12 @@ abs_extent_range (value_range_t *vr, tree min, tree max)
    If we have no values ranges recorded (ie, VRP is not running), then
    return NULL.  Otherwise create an empty range if none existed for VAR.  */
 
-static value_range_t *
+static value_range *
 get_value_range (const_tree var)
 {
-  static const struct value_range_d vr_const_varying
+  static const value_range vr_const_varying
     = { VR_VARYING, NULL_TREE, NULL_TREE, NULL };
-  value_range_t *vr;
+  value_range *vr;
   tree sym;
   unsigned ver = SSA_NAME_VERSION (var);
 
@@ -739,7 +677,7 @@ get_value_range (const_tree var)
      We should get here at most from the substitute-and-fold stage which
      will never try to change values.  */
   if (ver >= num_vr_values)
-    return CONST_CAST (value_range_t *, &vr_const_varying);
+    return CONST_CAST (value_range *, &vr_const_varying);
 
   vr = vr_value[ver];
   if (vr)
@@ -747,10 +685,10 @@ get_value_range (const_tree var)
 
   /* After propagation finished do not allocate new value-ranges.  */
   if (values_propagated)
-    return CONST_CAST (value_range_t *, &vr_const_varying);
+    return CONST_CAST (value_range *, &vr_const_varying);
 
   /* Create a default value range.  */
-  vr_value[ver] = vr = XCNEW (value_range_t);
+  vr_value[ver] = vr = XCNEW (value_range);
 
   /* Defer allocating the equivalence set.  */
   vr->equiv = NULL;
@@ -814,11 +752,28 @@ vrp_bitmap_equal_p (const_bitmap b1, const_bitmap b2)
    is the range object associated with another SSA name.  */
 
 static inline bool
-update_value_range (const_tree var, value_range_t *new_vr)
+update_value_range (const_tree var, value_range *new_vr)
 {
-  value_range_t *old_vr;
+  value_range *old_vr;
   bool is_new;
 
+  /* If there is a value-range on the SSA name from earlier analysis
+     factor that in.  */
+  if (INTEGRAL_TYPE_P (TREE_TYPE (var)))
+    {
+      wide_int min, max;
+      value_range_type rtype = get_range_info (var, &min, &max);
+      if (rtype == VR_RANGE || rtype == VR_ANTI_RANGE)
+       {
+         value_range nr;
+         nr.type = rtype;
+         nr.min = wide_int_to_tree (TREE_TYPE (var), min);
+         nr.max = wide_int_to_tree (TREE_TYPE (var), max);
+         nr.equiv = NULL;
+         vrp_intersect_ranges (new_vr, &nr);
+       }
+    }
+
   /* Update the value range, if necessary.  */
   old_vr = get_value_range (var);
   is_new = old_vr->type != new_vr->type
@@ -829,13 +784,18 @@ update_value_range (const_tree var, value_range_t *new_vr)
   if (is_new)
     {
       /* Do not allow transitions up the lattice.  The following
-         is slightly more awkward than just new_vr->type < old_vr->type
+        is slightly more awkward than just new_vr->type < old_vr->type
         because VR_RANGE and VR_ANTI_RANGE need to be considered
         the same.  We may not have is_new when transitioning to
-        UNDEFINED or from VARYING.  */
-      if (new_vr->type == VR_UNDEFINED
-         || old_vr->type == VR_VARYING)
-       set_value_range_to_varying (old_vr);
+        UNDEFINED.  If old_vr->type is VARYING, we shouldn't be
+        called.  */
+      if (new_vr->type == VR_UNDEFINED)
+       {
+         BITMAP_FREE (new_vr->equiv);
+         set_value_range_to_varying (old_vr);
+         set_value_range_to_varying (new_vr);
+         return true;
+       }
       else
        set_value_range (old_vr, new_vr->type, new_vr->min, new_vr->max,
                         new_vr->equiv);
@@ -854,7 +814,7 @@ static void
 add_equivalence (bitmap *equiv, const_tree var)
 {
   unsigned ver = SSA_NAME_VERSION (var);
-  value_range_t *vr = vr_value[ver];
+  value_range *vr = vr_value[ver];
 
   if (*equiv == NULL)
     *equiv = BITMAP_ALLOC (NULL);
@@ -867,7 +827,7 @@ add_equivalence (bitmap *equiv, const_tree var)
 /* Return true if VR is ~[0, 0].  */
 
 static inline bool
-range_is_nonnull (value_range_t *vr)
+range_is_nonnull (value_range *vr)
 {
   return vr->type == VR_ANTI_RANGE
         && integer_zerop (vr->min)
@@ -878,7 +838,7 @@ range_is_nonnull (value_range_t *vr)
 /* Return true if VR is [0, 0].  */
 
 static inline bool
-range_is_null (value_range_t *vr)
+range_is_null (value_range *vr)
 {
   return vr->type == VR_RANGE
         && integer_zerop (vr->min)
@@ -889,7 +849,7 @@ range_is_null (value_range_t *vr)
    a singleton.  */
 
 static inline bool
-range_int_cst_p (value_range_t *vr)
+range_int_cst_p (value_range *vr)
 {
   return (vr->type == VR_RANGE
          && TREE_CODE (vr->max) == INTEGER_CST
@@ -899,7 +859,7 @@ range_int_cst_p (value_range_t *vr)
 /* Return true if VR is a INTEGER_CST singleton.  */
 
 static inline bool
-range_int_cst_singleton_p (value_range_t *vr)
+range_int_cst_singleton_p (value_range *vr)
 {
   return (range_int_cst_p (vr)
          && !is_overflow_infinity (vr->min)
@@ -910,7 +870,7 @@ range_int_cst_singleton_p (value_range_t *vr)
 /* Return true if value range VR involves at least one symbol.  */
 
 static inline bool
-symbolic_range_p (value_range_t *vr)
+symbolic_range_p (value_range *vr)
 {
   return (!is_gimple_min_invariant (vr->min)
           || !is_gimple_min_invariant (vr->max));
@@ -986,7 +946,7 @@ build_symbolic_expr (tree type, tree sym, bool neg, tree inv)
 /* Return true if value range VR involves exactly one symbol SYM.  */
 
 static bool
-symbolic_range_based_on_p (value_range_t *vr, const_tree sym)
+symbolic_range_based_on_p (value_range *vr, const_tree sym)
 {
   bool neg, min_has_symbol, max_has_symbol;
   tree inv;
@@ -1011,7 +971,7 @@ symbolic_range_based_on_p (value_range_t *vr, const_tree sym)
 /* Return true if value range VR uses an overflow infinity.  */
 
 static inline bool
-overflow_infinity_range_p (value_range_t *vr)
+overflow_infinity_range_p (value_range *vr)
 {
   return (vr->type == VR_RANGE
          && (is_overflow_infinity (vr->min)
@@ -1025,7 +985,7 @@ overflow_infinity_range_p (value_range_t *vr)
    uses an overflow infinity.  */
 
 static bool
-usable_range_p (value_range_t *vr, bool *strict_overflow_p)
+usable_range_p (value_range *vr, bool *strict_overflow_p)
 {
   gcc_assert (vr->type == VR_RANGE);
   if (is_overflow_infinity (vr->min))
@@ -1043,87 +1003,13 @@ usable_range_p (value_range_t *vr, bool *strict_overflow_p)
   return true;
 }
 
-
-/* Return true if the result of assignment STMT is know to be non-negative.
-   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.*/
-
-static bool
-gimple_assign_nonnegative_warnv_p (gimple stmt, bool *strict_overflow_p)
-{
-  enum tree_code code = gimple_assign_rhs_code (stmt);
-  switch (get_gimple_rhs_class (code))
-    {
-    case GIMPLE_UNARY_RHS:
-      return tree_unary_nonnegative_warnv_p (gimple_assign_rhs_code (stmt),
-                                            gimple_expr_type (stmt),
-                                            gimple_assign_rhs1 (stmt),
-                                            strict_overflow_p);
-    case GIMPLE_BINARY_RHS:
-      return tree_binary_nonnegative_warnv_p (gimple_assign_rhs_code (stmt),
-                                             gimple_expr_type (stmt),
-                                             gimple_assign_rhs1 (stmt),
-                                             gimple_assign_rhs2 (stmt),
-                                             strict_overflow_p);
-    case GIMPLE_TERNARY_RHS:
-      return false;
-    case GIMPLE_SINGLE_RHS:
-      return tree_single_nonnegative_warnv_p (gimple_assign_rhs1 (stmt),
-                                             strict_overflow_p);
-    case GIMPLE_INVALID_RHS:
-      gcc_unreachable ();
-    default:
-      gcc_unreachable ();
-    }
-}
-
-/* Return true if return value of call STMT is know to be non-negative.
-   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.*/
-
-static bool
-gimple_call_nonnegative_warnv_p (gimple stmt, bool *strict_overflow_p)
-{
-  tree arg0 = gimple_call_num_args (stmt) > 0 ?
-    gimple_call_arg (stmt, 0) : NULL_TREE;
-  tree arg1 = gimple_call_num_args (stmt) > 1 ?
-    gimple_call_arg (stmt, 1) : NULL_TREE;
-
-  return tree_call_nonnegative_warnv_p (gimple_expr_type (stmt),
-                                       gimple_call_fndecl (stmt),
-                                       arg0,
-                                       arg1,
-                                       strict_overflow_p);
-}
-
-/* Return true if STMT is know to to compute a non-negative 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.*/
-
-static bool
-gimple_stmt_nonnegative_warnv_p (gimple stmt, bool *strict_overflow_p)
-{
-  switch (gimple_code (stmt))
-    {
-    case GIMPLE_ASSIGN:
-      return gimple_assign_nonnegative_warnv_p (stmt, strict_overflow_p);
-    case GIMPLE_CALL:
-      return gimple_call_nonnegative_warnv_p (stmt, strict_overflow_p);
-    default:
-      gcc_unreachable ();
-    }
-}
-
 /* Return true if the result of assignment STMT is know to be non-zero.
    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.*/
 
 static bool
-gimple_assign_nonzero_warnv_p (gimple stmt, bool *strict_overflow_p)
+gimple_assign_nonzero_warnv_p (gimple *stmt, bool *strict_overflow_p)
 {
   enum tree_code code = gimple_assign_rhs_code (stmt);
   switch (get_gimple_rhs_class (code))
@@ -1157,7 +1043,7 @@ gimple_assign_nonzero_warnv_p (gimple stmt, bool *strict_overflow_p)
    *STRICT_OVERFLOW_P.*/
 
 static bool
-gimple_stmt_nonzero_warnv_p (gimple stmt, bool *strict_overflow_p)
+gimple_stmt_nonzero_warnv_p (gimple *stmt, bool *strict_overflow_p)
 {
   switch (gimple_code (stmt))
     {
@@ -1171,6 +1057,10 @@ gimple_stmt_nonzero_warnv_p (gimple stmt, bool *strict_overflow_p)
            && DECL_IS_OPERATOR_NEW (fndecl)
            && !TREE_NOTHROW (fndecl))
          return true;
+       /* References are always non-NULL.  */
+       if (flag_delete_null_pointer_checks
+           && TREE_CODE (TREE_TYPE (fndecl)) == REFERENCE_TYPE)
+         return true;
        if (flag_delete_null_pointer_checks && 
            lookup_attribute ("returns_nonnull",
                              TYPE_ATTRIBUTES (gimple_call_fntype (stmt))))
@@ -1186,7 +1076,7 @@ gimple_stmt_nonzero_warnv_p (gimple stmt, bool *strict_overflow_p)
    obtained so far.  */
 
 static bool
-vrp_stmt_computes_nonzero (gimple stmt, bool *strict_overflow_p)
+vrp_stmt_computes_nonzero (gimple *stmt, bool *strict_overflow_p)
 {
   if (gimple_stmt_nonzero_warnv_p (stmt, strict_overflow_p))
     return true;
@@ -1203,7 +1093,7 @@ vrp_stmt_computes_nonzero (gimple stmt, bool *strict_overflow_p)
          && TREE_CODE (base) == MEM_REF
          && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
        {
-         value_range_t *vr = get_value_range (TREE_OPERAND (base, 0));
+         value_range *vr = get_value_range (TREE_OPERAND (base, 0));
          if (range_is_nonnull (vr))
            return true;
        }
@@ -1527,7 +1417,7 @@ value_inside_range (tree val, tree min, tree max)
    */
 
 static inline bool
-value_ranges_intersect_p (value_range_t *vr0, value_range_t *vr1)
+value_ranges_intersect_p (value_range *vr0, value_range *vr1)
 {
   /* The value ranges do not intersect if the maximum of the first range is
      less than the minimum of the second range or vice versa.
@@ -1553,7 +1443,7 @@ range_includes_zero_p (tree min, tree max)
 /* Return true if *VR is know to only contain nonnegative values.  */
 
 static inline bool
-value_range_nonnegative_p (value_range_t *vr)
+value_range_nonnegative_p (value_range *vr)
 {
   /* Testing for VR_ANTI_RANGE is not useful here as any anti-range
      which would return a useful value should be encoded as a 
@@ -1571,7 +1461,7 @@ value_range_nonnegative_p (value_range_t *vr)
    otherwise return NULL_TREE.  */
 
 static tree
-value_range_constant_singleton (value_range_t *vr)
+value_range_constant_singleton (value_range *vr)
 {
   if (vr->type == VR_RANGE
       && operand_equal_p (vr->min, vr->max, 0)
@@ -1602,7 +1492,7 @@ op_with_constant_singleton_value_range (tree op)
 static bool
 op_with_boolean_value_range_p (tree op)
 {
-  value_range_t *vr;
+  value_range *vr;
 
   if (TYPE_PRECISION (TREE_TYPE (op)) == 1)
     return true;
@@ -1624,10 +1514,10 @@ op_with_boolean_value_range_p (tree op)
    it in *VR_P.  */
 
 static void
-extract_range_from_assert (value_range_t *vr_p, tree expr)
+extract_range_from_assert (value_range *vr_p, tree expr)
 {
   tree var, cond, limit, min, max, type;
-  value_range_t *limit_vr;
+  value_range *limit_vr;
   enum tree_code cond_code;
 
   var = ASSERT_EXPR_VAR (expr);
@@ -1718,7 +1608,7 @@ 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.  */
+        unsigned values as negative signed values here.  */
       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);
 
@@ -1907,9 +1797,9 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
     always false.  */
 
 static void
-extract_range_from_ssa_name (value_range_t *vr, tree var)
+extract_range_from_ssa_name (value_range *vr, tree var)
 {
-  value_range_t *var_vr = get_value_range (var);
+  value_range *var_vr = get_value_range (var);
 
   if (var_vr->type != VR_VARYING)
     copy_value_range (vr, var_vr);
@@ -2079,7 +1969,7 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2)
 
 static bool
 zero_nonzero_bits_from_vr (const tree expr_type,
-                          value_range_t *vr,
+                          value_range *vr,
                           wide_int *may_be_nonzero,
                           wide_int *must_be_nonzero)
 {
@@ -2119,8 +2009,8 @@ zero_nonzero_bits_from_vr (const tree expr_type,
    *VR1 will be VR_UNDEFINED.  */
 
 static bool
-ranges_from_anti_range (value_range_t *ar,
-                       value_range_t *vr0, value_range_t *vr1)
+ranges_from_anti_range (value_range *ar,
+                       value_range *vr0, value_range *vr1)
 {
   tree type = TREE_TYPE (ar->min);
 
@@ -2159,9 +2049,9 @@ ranges_from_anti_range (value_range_t *ar,
    *VR0 CODE *VR1.  */
 
 static void
-extract_range_from_multiplicative_op_1 (value_range_t *vr,
+extract_range_from_multiplicative_op_1 (value_range *vr,
                                        enum tree_code code,
-                                       value_range_t *vr0, value_range_t *vr1)
+                                       value_range *vr0, value_range *vr1)
 {
   enum value_range_type type;
   tree val[4];
@@ -2314,12 +2204,12 @@ extract_range_from_multiplicative_op_1 (value_range_t *vr,
    type EXPR_TYPE.  The resulting range is stored in *VR.  */
 
 static void
-extract_range_from_binary_expr_1 (value_range_t *vr,
+extract_range_from_binary_expr_1 (value_range *vr,
                                  enum tree_code code, tree expr_type,
-                                 value_range_t *vr0_, value_range_t *vr1_)
+                                 value_range *vr0_, value_range *vr1_)
 {
-  value_range_t vr0 = *vr0_, vr1 = *vr1_;
-  value_range_t vrtem0 = VR_INITIALIZER, vrtem1 = VR_INITIALIZER;
+  value_range vr0 = *vr0_, vr1 = *vr1_;
+  value_range vrtem0 = VR_INITIALIZER, vrtem1 = VR_INITIALIZER;
   enum value_range_type type;
   tree min = NULL_TREE, max = NULL_TREE;
   int cmp;
@@ -2378,7 +2268,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
       extract_range_from_binary_expr_1 (vr, code, expr_type, &vrtem0, vr1_);
       if (vrtem1.type != VR_UNDEFINED)
        {
-         value_range_t vrres = VR_INITIALIZER;
+         value_range vrres = VR_INITIALIZER;
          extract_range_from_binary_expr_1 (&vrres, code, expr_type,
                                            &vrtem1, vr1_);
          vrp_meet (vr, &vrres);
@@ -2392,7 +2282,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
       extract_range_from_binary_expr_1 (vr, code, expr_type, vr0_, &vrtem0);
       if (vrtem1.type != VR_UNDEFINED)
        {
-         value_range_t vrres = VR_INITIALIZER;
+         value_range vrres = VR_INITIALIZER;
          extract_range_from_binary_expr_1 (&vrres, code, expr_type,
                                            vr0_, &vrtem1);
          vrp_meet (vr, &vrres);
@@ -2422,6 +2312,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
       && code != MAX_EXPR
       && code != PLUS_EXPR
       && code != MINUS_EXPR
+      && code != RSHIFT_EXPR
       && (vr0.type == VR_VARYING
          || vr1.type == VR_VARYING
          || vr0.type != vr1.type
@@ -2859,33 +2750,17 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
             prod3.  */
          /* min0min1 > max0max1 */
          if (wi::gts_p (prod0, prod3))
-           {
-             vrp_int tmp = prod3;
-             prod3 = prod0;
-             prod0 = tmp;
-           }
+           std::swap (prod0, prod3);
 
          /* min0max1 > max0min1 */
          if (wi::gts_p (prod1, prod2))
-           {
-             vrp_int tmp = prod2;
-             prod2 = prod1;
-             prod1 = tmp;
-           }
+           std::swap (prod1, prod2);
 
          if (wi::gts_p (prod0, prod1))
-           {
-             vrp_int tmp = prod1;
-             prod1 = prod0;
-             prod0 = tmp;
-           }
+           std::swap (prod0, prod1);
 
          if (wi::gts_p (prod2, prod3))
-           {
-             vrp_int tmp = prod3;
-             prod3 = prod2;
-             prod2 = tmp;
-           }
+           std::swap (prod2, prod3);
 
          /* diff = max - min.  */
          prod2 = prod3 - prod0;
@@ -2936,6 +2811,15 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
        {
          if (code == RSHIFT_EXPR)
            {
+             /* Even if vr0 is VARYING or otherwise not usable, we can derive
+                useful ranges just from the shift count.  E.g.
+                x >> 63 for signed 64-bit x is always [-1, 0].  */
+             if (vr0.type != VR_RANGE || symbolic_range_p (&vr0))
+               {
+                 vr0.type = type = VR_RANGE;
+                 vr0.min = vrp_val_min (expr_type);
+                 vr0.max = vrp_val_max (expr_type);
+               }
              extract_range_from_multiplicative_op_1 (vr, code, &vr0, &vr1);
              return;
            }
@@ -2944,7 +2828,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
                   && range_int_cst_singleton_p (&vr1))
            {
              bool saved_flag_wrapv;
-             value_range_t vr1p = VR_INITIALIZER;
+             value_range vr1p = VR_INITIALIZER;
              vr1p.type = VR_RANGE;
              vr1p.min = (wide_int_to_tree
                          (expr_type,
@@ -3085,14 +2969,33 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
                 and all numbers from min to 0 for negative min.  */
              cmp = compare_values (vr0.max, zero);
              if (cmp == -1)
-               max = zero;
+               {
+                 /* When vr0.max < 0, vr1.min != 0 and value
+                    ranges for dividend and divisor are available.  */
+                 if (vr1.type == VR_RANGE
+                     && !symbolic_range_p (&vr0)
+                     && !symbolic_range_p (&vr1)
+                     && compare_values (vr1.min, zero) != 0)
+                   max = int_const_binop (code, vr0.max, vr1.min);
+                 else
+                   max = zero;
+               }
              else if (cmp == 0 || cmp == 1)
                max = vr0.max;
              else
                type = VR_VARYING;
              cmp = compare_values (vr0.min, zero);
              if (cmp == 1)
-               min = zero;
+               {
+                 /* For unsigned division when value ranges for dividend
+                    and divisor are available.  */
+                 if (vr1.type == VR_RANGE
+                     && !symbolic_range_p (&vr0)
+                     && !symbolic_range_p (&vr1))
+                   min = int_const_binop (code, vr0.min, vr1.max);
+                 else
+                   min = zero;
+               }
              else if (cmp == 0 || cmp == -1)
                min = vr0.min;
              else
@@ -3112,7 +3015,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
              return;
            }
        }
-      else
+      else if (!symbolic_range_p (&vr0) && !symbolic_range_p (&vr1))
        {
          extract_range_from_multiplicative_op_1 (vr, code, &vr0, &vr1);
          return;
@@ -3120,26 +3023,60 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
     }
   else if (code == TRUNC_MOD_EXPR)
     {
-      if (vr1.type != VR_RANGE
-         || range_includes_zero_p (vr1.min, vr1.max) != 0
-         || vrp_val_is_min (vr1.min))
+      if (range_is_null (&vr1))
        {
-         set_value_range_to_varying (vr);
+         set_value_range_to_undefined (vr);
          return;
        }
+      /* ABS (A % B) < ABS (B) and either
+        0 <= A % B <= A or A <= A % B <= 0.  */
       type = VR_RANGE;
-      /* Compute MAX <|vr1.min|, |vr1.max|> - 1.  */
-      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, 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)
-         || value_range_nonnegative_p (&vr0))
-       min = build_int_cst (TREE_TYPE (max), 0);
+      signop sgn = TYPE_SIGN (expr_type);
+      unsigned int prec = TYPE_PRECISION (expr_type);
+      wide_int wmin, wmax, tmp;
+      wide_int zero = wi::zero (prec);
+      wide_int one = wi::one (prec);
+      if (vr1.type == VR_RANGE && !symbolic_range_p (&vr1))
+       {
+         wmax = wi::sub (vr1.max, one);
+         if (sgn == SIGNED)
+           {
+             tmp = wi::sub (wi::minus_one (prec), vr1.min);
+             wmax = wi::smax (wmax, tmp);
+           }
+       }
+      else
+       {
+         wmax = wi::max_value (prec, sgn);
+         /* X % INT_MIN may be INT_MAX.  */
+         if (sgn == UNSIGNED)
+           wmax = wmax - one;
+       }
+
+      if (sgn == UNSIGNED)
+       wmin = zero;
       else
-       min = fold_unary_to_constant (NEGATE_EXPR, expr_type, max);
+       {
+         wmin = -wmax;
+         if (vr0.type == VR_RANGE && TREE_CODE (vr0.min) == INTEGER_CST)
+           {
+             tmp = vr0.min;
+             if (wi::gts_p (tmp, zero))
+               tmp = zero;
+             wmin = wi::smax (wmin, tmp);
+           }
+       }
+
+      if (vr0.type == VR_RANGE && TREE_CODE (vr0.max) == INTEGER_CST)
+       {
+         tmp = vr0.max;
+         if (sgn == SIGNED && wi::neg_p (tmp))
+           tmp = zero;
+         wmax = wi::min (wmax, tmp, sgn);
+       }
+
+      min = wide_int_to_tree (expr_type, wmin);
+      max = wide_int_to_tree (expr_type, wmax);
     }
   else if (code == BIT_AND_EXPR || code == BIT_IOR_EXPR || code == BIT_XOR_EXPR)
     {
@@ -3267,12 +3204,12 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
    The resulting range is stored in *VR.  */
 
 static void
-extract_range_from_binary_expr (value_range_t *vr,
+extract_range_from_binary_expr (value_range *vr,
                                enum tree_code code,
                                tree expr_type, tree op0, tree op1)
 {
-  value_range_t vr0 = VR_INITIALIZER;
-  value_range_t vr1 = VR_INITIALIZER;
+  value_range vr0 = VR_INITIALIZER;
+  value_range vr1 = VR_INITIALIZER;
 
   /* Get value ranges for each operand.  For constant operands, create
      a new value range with the operand to simplify processing.  */
@@ -3304,7 +3241,7 @@ extract_range_from_binary_expr (value_range_t *vr,
       && symbolic_range_based_on_p (&vr0, op1))
     {
       const bool minus_p = (code == MINUS_EXPR);
-      value_range_t n_vr1 = VR_INITIALIZER;
+      value_range n_vr1 = VR_INITIALIZER;
 
       /* Try with VR0 and [-INF, OP1].  */
       if (is_gimple_min_invariant (minus_p ? vr0.max : vr0.min))
@@ -3328,7 +3265,7 @@ extract_range_from_binary_expr (value_range_t *vr,
       && symbolic_range_based_on_p (&vr1, op0))
     {
       const bool minus_p = (code == MINUS_EXPR);
-      value_range_t n_vr0 = VR_INITIALIZER;
+      value_range n_vr0 = VR_INITIALIZER;
 
       /* Try with [-INF, OP0] and VR1.  */
       if (is_gimple_min_invariant (minus_p ? vr1.max : vr1.min))
@@ -3348,14 +3285,14 @@ extract_range_from_binary_expr (value_range_t *vr,
 
 /* Extract range information from a unary operation CODE based on
    the range of its operand *VR0 with type OP0_TYPE with resulting type TYPE.
-   The The resulting range is stored in *VR.  */
+   The resulting range is stored in *VR.  */
 
 static void
-extract_range_from_unary_expr_1 (value_range_t *vr,
+extract_range_from_unary_expr_1 (value_range *vr,
                                 enum tree_code code, tree type,
-                                value_range_t *vr0_, tree op0_type)
+                                value_range *vr0_, tree op0_type)
 {
-  value_range_t vr0 = *vr0_, vrtem0 = VR_INITIALIZER, vrtem1 = VR_INITIALIZER;
+  value_range vr0 = *vr0_, vrtem0 = VR_INITIALIZER, vrtem1 = VR_INITIALIZER;
 
   /* VRP only operates on integral and pointer types.  */
   if (!(INTEGRAL_TYPE_P (op0_type)
@@ -3385,7 +3322,7 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
     {
       /* -X is simply 0 - X, so re-use existing code that also handles
          anti-ranges fine.  */
-      value_range_t zero = VR_INITIALIZER;
+      value_range zero = VR_INITIALIZER;
       set_value_range_to_value (&zero, build_int_cst (type, 0), NULL);
       extract_range_from_binary_expr_1 (vr, MINUS_EXPR, type, &zero, &vr0);
       return;
@@ -3394,7 +3331,7 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
     {
       /* ~X is simply -1 - X, so re-use existing code that also handles
          anti-ranges fine.  */
-      value_range_t minusone = VR_INITIALIZER;
+      value_range minusone = VR_INITIALIZER;
       set_value_range_to_value (&minusone, build_int_cst (type, -1), NULL);
       extract_range_from_binary_expr_1 (vr, MINUS_EXPR,
                                        type, &minusone, &vr0);
@@ -3409,7 +3346,7 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
       extract_range_from_unary_expr_1 (vr, code, type, &vrtem0, op0_type);
       if (vrtem1.type != VR_UNDEFINED)
        {
-         value_range_t vrres = VR_INITIALIZER;
+         value_range vrres = VR_INITIALIZER;
          extract_range_from_unary_expr_1 (&vrres, code, type,
                                           &vrtem1, op0_type);
          vrp_meet (vr, &vrres);
@@ -3625,11 +3562,7 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
        {
           /* If the range was reversed, swap MIN and MAX.  */
          if (cmp == 1)
-           {
-             tree t = min;
-             min = max;
-             max = t;
-           }
+           std::swap (min, max);
        }
 
       cmp = compare_values (min, max);
@@ -3656,10 +3589,10 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
    The resulting range is stored in *VR.  */
 
 static void
-extract_range_from_unary_expr (value_range_t *vr, enum tree_code code,
+extract_range_from_unary_expr (value_range *vr, enum tree_code code,
                               tree type, tree op0)
 {
-  value_range_t vr0 = VR_INITIALIZER;
+  value_range vr0 = VR_INITIALIZER;
 
   /* Get value ranges for the operand.  For constant operands, create
      a new value range with the operand to simplify processing.  */
@@ -3678,11 +3611,11 @@ extract_range_from_unary_expr (value_range_t *vr, enum tree_code code,
    the ranges of each of its operands and the expression code.  */
 
 static void
-extract_range_from_cond_expr (value_range_t *vr, gimple stmt)
+extract_range_from_cond_expr (value_range *vr, gassign *stmt)
 {
   tree op0, op1;
-  value_range_t vr0 = VR_INITIALIZER;
-  value_range_t vr1 = VR_INITIALIZER;
+  value_range vr0 = VR_INITIALIZER;
+  value_range vr1 = VR_INITIALIZER;
 
   /* Get value ranges for each operand.  For constant operands, create
      a new value range with the operand to simplify processing.  */
@@ -3712,7 +3645,7 @@ extract_range_from_cond_expr (value_range_t *vr, gimple stmt)
    on the range of its operand and the expression code.  */
 
 static void
-extract_range_from_comparison (value_range_t *vr, enum tree_code code,
+extract_range_from_comparison (value_range *vr, enum tree_code code,
                               tree type, tree op0, tree op1)
 {
   bool sop = false;
@@ -3742,24 +3675,133 @@ extract_range_from_comparison (value_range_t *vr, enum tree_code code,
     set_value_range_to_truthvalue (vr, type);
 }
 
+/* Helper function for simplify_internal_call_using_ranges and
+   extract_range_basic.  Return true if OP0 SUBCODE OP1 for
+   SUBCODE {PLUS,MINUS,MULT}_EXPR is known to never overflow or
+   always overflow.  Set *OVF to true if it is known to always
+   overflow.  */
+
+static bool
+check_for_binary_op_overflow (enum tree_code subcode, tree type,
+                             tree op0, tree op1, bool *ovf)
+{
+  value_range vr0 = VR_INITIALIZER;
+  value_range vr1 = VR_INITIALIZER;
+  if (TREE_CODE (op0) == SSA_NAME)
+    vr0 = *get_value_range (op0);
+  else if (TREE_CODE (op0) == INTEGER_CST)
+    set_value_range_to_value (&vr0, op0, NULL);
+  else
+    set_value_range_to_varying (&vr0);
+
+  if (TREE_CODE (op1) == SSA_NAME)
+    vr1 = *get_value_range (op1);
+  else if (TREE_CODE (op1) == INTEGER_CST)
+    set_value_range_to_value (&vr1, op1, NULL);
+  else
+    set_value_range_to_varying (&vr1);
+
+  if (!range_int_cst_p (&vr0)
+      || TREE_OVERFLOW (vr0.min)
+      || TREE_OVERFLOW (vr0.max))
+    {
+      vr0.min = vrp_val_min (TREE_TYPE (op0));
+      vr0.max = vrp_val_max (TREE_TYPE (op0));
+    }
+  if (!range_int_cst_p (&vr1)
+      || TREE_OVERFLOW (vr1.min)
+      || TREE_OVERFLOW (vr1.max))
+    {
+      vr1.min = vrp_val_min (TREE_TYPE (op1));
+      vr1.max = vrp_val_max (TREE_TYPE (op1));
+    }
+  *ovf = arith_overflowed_p (subcode, type, vr0.min,
+                            subcode == MINUS_EXPR ? vr1.max : vr1.min);
+  if (arith_overflowed_p (subcode, type, vr0.max,
+                         subcode == MINUS_EXPR ? vr1.min : vr1.max) != *ovf)
+    return false;
+  if (subcode == MULT_EXPR)
+    {
+      if (arith_overflowed_p (subcode, type, vr0.min, vr1.max) != *ovf
+         || arith_overflowed_p (subcode, type, vr0.max, vr1.min) != *ovf)
+       return false;
+    }
+  if (*ovf)
+    {
+      /* So far we found that there is an overflow on the boundaries.
+        That doesn't prove that there is an overflow even for all values
+        in between the boundaries.  For that compute widest_int range
+        of the result and see if it doesn't overlap the range of
+        type.  */
+      widest_int wmin, wmax;
+      widest_int w[4];
+      int i;
+      w[0] = wi::to_widest (vr0.min);
+      w[1] = wi::to_widest (vr0.max);
+      w[2] = wi::to_widest (vr1.min);
+      w[3] = wi::to_widest (vr1.max);
+      for (i = 0; i < 4; i++)
+       {
+         widest_int wt;
+         switch (subcode)
+           {
+           case PLUS_EXPR:
+             wt = wi::add (w[i & 1], w[2 + (i & 2) / 2]);
+             break;
+           case MINUS_EXPR:
+             wt = wi::sub (w[i & 1], w[2 + (i & 2) / 2]);
+             break;
+           case MULT_EXPR:
+             wt = wi::mul (w[i & 1], w[2 + (i & 2) / 2]);
+             break;
+           default:
+             gcc_unreachable ();
+           }
+         if (i == 0)
+           {
+             wmin = wt;
+             wmax = wt;
+           }
+         else
+           {
+             wmin = wi::smin (wmin, wt);
+             wmax = wi::smax (wmax, wt);
+           }
+       }
+      /* The result of op0 CODE op1 is known to be in range
+        [wmin, wmax].  */
+      widest_int wtmin = wi::to_widest (vrp_val_min (type));
+      widest_int wtmax = wi::to_widest (vrp_val_max (type));
+      /* If all values in [wmin, wmax] are smaller than
+        [wtmin, wtmax] or all are larger than [wtmin, wtmax],
+        the arithmetic operation will always overflow.  */
+      if (wi::lts_p (wmax, wtmin) || wi::gts_p (wmin, wtmax))
+       return true;
+      return false;
+    }
+  return true;
+}
+
 /* Try to derive a nonnegative or nonzero range out of STMT relying
    primarily on generic routines in fold in conjunction with range data.
    Store the result in *VR */
 
 static void
-extract_range_basic (value_range_t *vr, gimple stmt)
+extract_range_basic (value_range *vr, gimple *stmt)
 {
   bool sop = false;
   tree type = gimple_expr_type (stmt);
 
-  if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
+  if (is_gimple_call (stmt))
     {
-      tree fndecl = gimple_call_fndecl (stmt), arg;
+      tree arg;
       int mini, maxi, zerov = 0, prec;
+      enum tree_code subcode = ERROR_MARK;
+      combined_fn cfn = gimple_call_combined_fn (stmt);
 
-      switch (DECL_FUNCTION_CODE (fndecl))
+      switch (cfn)
        {
-       case BUILT_IN_CONSTANT_P:
+       case CFN_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.
@@ -3775,15 +3817,15 @@ extract_range_basic (value_range_t *vr, gimple stmt)
          break;
          /* Both __builtin_ffs* and __builtin_popcount return
             [0, prec].  */
-       CASE_INT_FN (BUILT_IN_FFS):
-       CASE_INT_FN (BUILT_IN_POPCOUNT):
+       CASE_CFN_FFS:
+       CASE_CFN_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);
+             value_range *vr0 = get_value_range (arg);
              /* If arg is non-zero, then ffs or popcount
                 are non-zero.  */
              if (((vr0->type == VR_RANGE
@@ -3804,7 +3846,7 @@ extract_range_basic (value_range_t *vr, gimple stmt)
            }
          goto bitop_builtin;
          /* __builtin_parity* returns [0, 1].  */
-       CASE_INT_FN (BUILT_IN_PARITY):
+       CASE_CFN_PARITY:
          mini = 0;
          maxi = 1;
          goto bitop_builtin;
@@ -3813,7 +3855,7 @@ extract_range_basic (value_range_t *vr, gimple stmt)
             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):
+       CASE_CFN_CLZ:
          arg = gimple_call_arg (stmt, 0);
          prec = TYPE_PRECISION (TREE_TYPE (arg));
          mini = 0;
@@ -3829,7 +3871,7 @@ extract_range_basic (value_range_t *vr, gimple stmt)
            mini = -2;
          if (TREE_CODE (arg) == SSA_NAME)
            {
-             value_range_t *vr0 = get_value_range (arg);
+             value_range *vr0 = get_value_range (arg);
              /* From clz of VR_RANGE minimum we can compute
                 result maximum.  */
              if (vr0->type == VR_RANGE
@@ -3868,7 +3910,7 @@ extract_range_basic (value_range_t *vr, gimple stmt)
             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):
+       CASE_CFN_CTZ:
          arg = gimple_call_arg (stmt, 0);
          prec = TYPE_PRECISION (TREE_TYPE (arg));
          mini = 0;
@@ -3890,7 +3932,7 @@ extract_range_basic (value_range_t *vr, gimple stmt)
            }
          if (TREE_CODE (arg) == SSA_NAME)
            {
-             value_range_t *vr0 = get_value_range (arg);
+             value_range *vr0 = get_value_range (arg);
              /* If arg is non-zero, then use [0, prec - 1].  */
              if (((vr0->type == VR_RANGE
                    && integer_nonzerop (vr0->min))
@@ -3917,7 +3959,7 @@ extract_range_basic (value_range_t *vr, gimple stmt)
            break;
          goto bitop_builtin;
          /* __builtin_clrsb* returns [0, prec-1].  */
-       CASE_INT_FN (BUILT_IN_CLRSB):
+       CASE_CFN_CLRSB:
          arg = gimple_call_arg (stmt, 0);
          prec = TYPE_PRECISION (TREE_TYPE (arg));
          mini = 0;
@@ -3927,25 +3969,37 @@ extract_range_basic (value_range_t *vr, gimple stmt)
          set_value_range (vr, VR_RANGE, build_int_cst (type, mini),
                           build_int_cst (type, maxi), NULL);
          return;
-       default:
-         break;
-       }
-    }
-  else if (is_gimple_call (stmt)
-          && gimple_call_internal_p (stmt))
-    {
-      enum tree_code subcode = ERROR_MARK;
-      switch (gimple_call_internal_fn (stmt))
-       {
-       case IFN_UBSAN_CHECK_ADD:
+       case CFN_UBSAN_CHECK_ADD:
          subcode = PLUS_EXPR;
          break;
-       case IFN_UBSAN_CHECK_SUB:
+       case CFN_UBSAN_CHECK_SUB:
          subcode = MINUS_EXPR;
          break;
-       case IFN_UBSAN_CHECK_MUL:
+       case CFN_UBSAN_CHECK_MUL:
          subcode = MULT_EXPR;
          break;
+       case CFN_GOACC_DIM_SIZE:
+       case CFN_GOACC_DIM_POS:
+         /* Optimizing these two internal functions helps the loop
+            optimizer eliminate outer comparisons.  Size is [1,N]
+            and pos is [0,N-1].  */
+         {
+           bool is_pos = cfn == CFN_GOACC_DIM_POS;
+           int axis = get_oacc_ifn_dim_arg (stmt);
+           int size = get_oacc_fn_dim_size (current_function_decl, axis);
+
+           if (!size)
+             /* If it's dynamic, the backend might know a hardware
+                limitation.  */
+             size = targetm.goacc.dim_limit (axis);
+
+           tree type = TREE_TYPE (gimple_call_lhs (stmt));
+           set_value_range (vr, VR_RANGE,
+                            build_int_cst (type, is_pos ? 0 : 1),
+                            size ? build_int_cst (type, size - is_pos)
+                                 : vrp_val_max (type), NULL);
+         }
+         return;
        default:
          break;
        }
@@ -3972,6 +4026,84 @@ extract_range_basic (value_range_t *vr, gimple stmt)
          return;
        }
     }
+  /* Handle extraction of the two results (result of arithmetics and
+     a flag whether arithmetics overflowed) from {ADD,SUB,MUL}_OVERFLOW
+     internal function.  */
+  else if (is_gimple_assign (stmt)
+          && (gimple_assign_rhs_code (stmt) == REALPART_EXPR
+              || gimple_assign_rhs_code (stmt) == IMAGPART_EXPR)
+          && INTEGRAL_TYPE_P (type))
+    {
+      enum tree_code code = gimple_assign_rhs_code (stmt);
+      tree op = gimple_assign_rhs1 (stmt);
+      if (TREE_CODE (op) == code && TREE_CODE (TREE_OPERAND (op, 0)) == SSA_NAME)
+       {
+         gimple *g = SSA_NAME_DEF_STMT (TREE_OPERAND (op, 0));
+         if (is_gimple_call (g) && gimple_call_internal_p (g))
+           {
+             enum tree_code subcode = ERROR_MARK;
+             switch (gimple_call_internal_fn (g))
+               {
+               case IFN_ADD_OVERFLOW:
+                 subcode = PLUS_EXPR;
+                 break;
+               case IFN_SUB_OVERFLOW:
+                 subcode = MINUS_EXPR;
+                 break;
+               case IFN_MUL_OVERFLOW:
+                 subcode = MULT_EXPR;
+                 break;
+               default:
+                 break;
+               }
+             if (subcode != ERROR_MARK)
+               {
+                 tree op0 = gimple_call_arg (g, 0);
+                 tree op1 = gimple_call_arg (g, 1);
+                 if (code == IMAGPART_EXPR)
+                   {
+                     bool ovf = false;
+                     if (check_for_binary_op_overflow (subcode, type,
+                                                       op0, op1, &ovf))
+                       set_value_range_to_value (vr,
+                                                 build_int_cst (type, ovf),
+                                                 NULL);
+                     else
+                       set_value_range (vr, VR_RANGE, build_int_cst (type, 0),
+                                        build_int_cst (type, 1), NULL);
+                   }
+                 else if (types_compatible_p (type, TREE_TYPE (op0))
+                          && types_compatible_p (type, TREE_TYPE (op1)))
+                   {
+                     bool saved_flag_wrapv = flag_wrapv;
+                     /* Pretend the arithmetics is wrapping.  If there is
+                        any overflow, IMAGPART_EXPR will be set.  */
+                     flag_wrapv = 1;
+                     extract_range_from_binary_expr (vr, subcode, type,
+                                                     op0, op1);
+                     flag_wrapv = saved_flag_wrapv;
+                   }
+                 else
+                   {
+                     value_range vr0 = VR_INITIALIZER;
+                     value_range vr1 = VR_INITIALIZER;
+                     bool saved_flag_wrapv = flag_wrapv;
+                     /* Pretend the arithmetics is wrapping.  If there is
+                        any overflow, IMAGPART_EXPR will be set.  */
+                     flag_wrapv = 1;
+                     extract_range_from_unary_expr (&vr0, NOP_EXPR,
+                                                    type, op0);
+                     extract_range_from_unary_expr (&vr1, NOP_EXPR,
+                                                    type, op1);
+                     extract_range_from_binary_expr_1 (vr, subcode, type,
+                                                       &vr0, &vr1);
+                     flag_wrapv = saved_flag_wrapv;
+                   }
+                 return;
+               }
+           }
+       }
+    }
   if (INTEGRAL_TYPE_P (type)
       && gimple_stmt_nonnegative_warnv_p (stmt, &sop))
     set_value_range_to_nonnegative (vr, type,
@@ -3988,7 +4120,7 @@ extract_range_basic (value_range_t *vr, gimple stmt)
    in *VR.  */
 
 static void
-extract_range_from_assignment (value_range_t *vr, gimple stmt)
+extract_range_from_assignment (value_range *vr, gassign *stmt)
 {
   enum tree_code code = gimple_assign_rhs_code (stmt);
 
@@ -4027,8 +4159,8 @@ extract_range_from_assignment (value_range_t *vr, gimple stmt)
    for VAR.  If so, update VR with the new limits.  */
 
 static void
-adjust_range_with_scev (value_range_t *vr, struct loop *loop,
-                       gimple stmt, tree var)
+adjust_range_with_scev (value_range *vr, struct loop *loop,
+                       gimple *stmt, tree var)
 {
   tree init, step, chrec, tmin, tmax, min, max, type, tem;
   enum ev_direction dir;
@@ -4105,7 +4237,7 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop,
         the number of latch executions is the correct thing to use.  */
       if (max_loop_iterations (loop, &nit))
        {
-         value_range_t maxvr = VR_INITIALIZER;
+         value_range maxvr = VR_INITIALIZER;
          signop sgn = TYPE_SIGN (TREE_TYPE (step));
          bool overflow;
 
@@ -4191,6 +4323,17 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop,
          && is_positive_overflow_infinity (max)))
     return;
 
+  /* Even for valid range info, sometimes overflow flag will leak in.
+     As GIMPLE IL should have no constants with TREE_OVERFLOW set, we
+     drop them except for +-overflow_infinity which still need special
+     handling in vrp pass.  */
+  if (TREE_OVERFLOW_P (min)
+      && ! is_negative_overflow_infinity (min))
+    min = drop_tree_overflow (min);
+  if (TREE_OVERFLOW_P (max)
+      && ! is_positive_overflow_infinity (max))
+    max = drop_tree_overflow (max);
+
   set_value_range (vr, VR_RANGE, min, max, vr->equiv);
 }
 
@@ -4210,7 +4353,7 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop,
 
 
 static tree
-compare_ranges (enum tree_code comp, value_range_t *vr0, value_range_t *vr1,
+compare_ranges (enum tree_code comp, value_range *vr0, value_range *vr1,
                bool *strict_overflow_p)
 {
   /* VARYING or UNDEFINED ranges cannot be compared.  */
@@ -4240,7 +4383,7 @@ compare_ranges (enum tree_code comp, value_range_t *vr0, value_range_t *vr1,
       if (vr0->type == VR_RANGE)
        {
          /* To simplify processing, make VR0 the anti-range.  */
-         value_range_t *tmp = vr0;
+         value_range *tmp = vr0;
          vr0 = vr1;
          vr1 = tmp;
        }
@@ -4262,11 +4405,8 @@ compare_ranges (enum tree_code comp, value_range_t *vr0, value_range_t *vr1,
      operands around and change the comparison code.  */
   if (comp == GT_EXPR || comp == GE_EXPR)
     {
-      value_range_t *tmp;
       comp = (comp == GT_EXPR) ? LT_EXPR : LE_EXPR;
-      tmp = vr0;
-      vr0 = vr1;
-      vr1 = tmp;
+      std::swap (vr0, vr1);
     }
 
   if (comp == EQ_EXPR)
@@ -4367,7 +4507,7 @@ compare_ranges (enum tree_code comp, value_range_t *vr0, value_range_t *vr1,
    infinity was used in the test.  */
 
 static tree
-compare_range_with_value (enum tree_code comp, value_range_t *vr, tree val,
+compare_range_with_value (enum tree_code comp, value_range *vr, tree val,
                          bool *strict_overflow_p)
 {
   if (vr->type == VR_VARYING || vr->type == VR_UNDEFINED)
@@ -4489,8 +4629,8 @@ compare_range_with_value (enum tree_code comp, value_range_t *vr, tree val,
 
 /* Debugging dumps.  */
 
-void dump_value_range (FILE *, value_range_t *);
-void debug_value_range (value_range_t *);
+void dump_value_range (FILE *, value_range *);
+void debug_value_range (value_range *);
 void dump_all_value_ranges (FILE *);
 void debug_all_value_ranges (void);
 void dump_vr_equiv (FILE *, bitmap);
@@ -4500,7 +4640,7 @@ void debug_vr_equiv (bitmap);
 /* Dump value range VR to FILE.  */
 
 void
-dump_value_range (FILE *file, value_range_t *vr)
+dump_value_range (FILE *file, value_range *vr)
 {
   if (vr == NULL)
     fprintf (file, "[]");
@@ -4560,7 +4700,7 @@ dump_value_range (FILE *file, value_range_t *vr)
 /* Dump value range VR to stderr.  */
 
 DEBUG_FUNCTION void
-debug_value_range (value_range_t *vr)
+debug_value_range (value_range *vr)
 {
   dump_value_range (stderr, vr);
   fprintf (stderr, "\n");
@@ -4602,11 +4742,11 @@ debug_all_value_ranges (void)
    create a new SSA name N and return the assertion assignment
    'N = ASSERT_EXPR <V, V OP W>'.  */
 
-static gimple
+static gimple *
 build_assert_expr_for (tree cond, tree v)
 {
   tree a;
-  gimple assertion;
+  gassign *assertion;
 
   gcc_assert (TREE_CODE (v) == SSA_NAME
              && COMPARISON_CLASS_P (cond));
@@ -4628,7 +4768,7 @@ build_assert_expr_for (tree cond, tree v)
    point values.  */
 
 static inline bool
-fp_predicate (gimple stmt)
+fp_predicate (gimple *stmt)
 {
   GIMPLE_CHECK (stmt, GIMPLE_COND);
 
@@ -4641,7 +4781,7 @@ fp_predicate (gimple stmt)
    inferred.  */
 
 static bool
-infer_value_range (gimple stmt, tree op, enum tree_code *comp_code_p, tree *val_p)
+infer_value_range (gimple *stmt, tree op, tree_code *comp_code_p, tree *val_p)
 {
   *val_p = NULL_TREE;
   *comp_code_p = ERROR_MARK;
@@ -4672,7 +4812,7 @@ infer_value_range (gimple stmt, tree op, enum tree_code *comp_code_p, tree *val_
        return false;
     }
 
-  if (infer_nonnull_range (stmt, op, true, true))
+  if (infer_nonnull_range (stmt, op))
     {
       *val_p = build_int_cst (TREE_TYPE (op), 0);
       *comp_code_p = NE_EXPR;
@@ -4693,7 +4833,7 @@ void debug_all_asserts (void);
 void
 dump_asserts_for (FILE *file, tree name)
 {
-  assert_locus_t loc;
+  assert_locus *loc;
 
   fprintf (file, "Assertions to be inserted for ");
   print_generic_expr (file, name, 0);
@@ -4775,7 +4915,7 @@ register_new_assert_for (tree name, tree expr,
                         edge e,
                         gimple_stmt_iterator si)
 {
-  assert_locus_t n, loc, last_loc;
+  assert_locus *n, *loc, *last_loc;
   basic_block dest_bb;
 
   gcc_checking_assert (bb == NULL || e == NULL);
@@ -4850,7 +4990,7 @@ register_new_assert_for (tree name, tree expr,
   /* If we didn't find an assertion already registered for
      NAME COMP_CODE VAL, add a new one at the end of the list of
      assertions associated with NAME.  */
-  n = XNEW (struct assert_locus_d);
+  n = XNEW (struct assert_locus);
   n->bb = dest_bb;
   n->e = e;
   n->si = si;
@@ -4965,32 +5105,27 @@ masked_increment (const wide_int &val_in, const wide_int &mask,
 
 /* Try to register an edge assertion for SSA name NAME on edge E for
    the condition COND contributing to the conditional jump pointed to by BSI.
-   Invert the condition COND if INVERT is true.
-   Return true if an assertion for NAME could be registered.  */
+   Invert the condition COND if INVERT is true.  */
 
-static bool
+static void
 register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
                            enum tree_code cond_code,
                            tree cond_op0, tree cond_op1, bool invert)
 {
   tree val;
   enum tree_code comp_code;
-  bool retval = false;
 
   if (!extract_code_and_val_from_cond_with_ops (name, cond_code,
                                                cond_op0,
                                                cond_op1,
                                                invert, &comp_code, &val))
-    return false;
+    return;
 
   /* Only register an ASSERT_EXPR if NAME was found in the sub-graph
      reachable from E.  */
   if (live_on_edge (e, name)
       && !has_single_use (name))
-    {
-      register_new_assert_for (name, name, comp_code, val, NULL, e, bsi);
-      retval = true;
-    }
+    register_new_assert_for (name, name, comp_code, val, NULL, e, bsi);
 
   /* In the case of NAME <= CST and NAME being defined as
      NAME = (unsigned) NAME2 + CST2 we can assert NAME2 >= -CST2
@@ -5001,7 +5136,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
       && TREE_CODE (val) == INTEGER_CST
       && TYPE_UNSIGNED (TREE_TYPE (val)))
     {
-      gimple def_stmt = SSA_NAME_DEF_STMT (name);
+      gimple *def_stmt = SSA_NAME_DEF_STMT (name);
       tree cst2 = NULL_TREE, name2 = NULL_TREE, name3 = NULL_TREE;
 
       /* Extract CST2 from the (optional) addition.  */
@@ -5051,8 +5186,6 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
            }
 
          register_new_assert_for (name3, tmp, comp_code, val, NULL, e, bsi);
-
-         retval = true;
        }
 
       /* If name2 is used later, create an ASSERT_EXPR for it.  */
@@ -5082,54 +5215,69 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
            }
 
          register_new_assert_for (name2, tmp, comp_code, val, NULL, e, bsi);
-
-         retval = true;
        }
     }
 
   /* In the case of post-in/decrement tests like if (i++) ... and uses
      of the in/decremented value on the edge the extra name we want to
      assert for is not on the def chain of the name compared.  Instead
-     it is in the set of use stmts.  */
+     it is in the set of use stmts.
+     Similar cases happen for conversions that were simplified through
+     fold_{sign_changed,widened}_comparison.  */
   if ((comp_code == NE_EXPR
        || comp_code == EQ_EXPR)
       && TREE_CODE (val) == INTEGER_CST)
     {
       imm_use_iterator ui;
-      gimple use_stmt;
+      gimple *use_stmt;
       FOR_EACH_IMM_USE_STMT (use_stmt, ui, name)
        {
-         /* Cut off to use-stmts that are in the predecessor.  */
-         if (gimple_bb (use_stmt) != e->src)
-           continue;
-
          if (!is_gimple_assign (use_stmt))
            continue;
 
-         enum tree_code code = gimple_assign_rhs_code (use_stmt);
-         if (code != PLUS_EXPR
-             && code != MINUS_EXPR)
+         /* Cut off to use-stmts that are dominating the predecessor.  */
+         if (!dominated_by_p (CDI_DOMINATORS, e->src, gimple_bb (use_stmt)))
            continue;
 
-         tree cst = gimple_assign_rhs2 (use_stmt);
-         if (TREE_CODE (cst) != INTEGER_CST)
+         tree name2 = gimple_assign_lhs (use_stmt);
+         if (TREE_CODE (name2) != SSA_NAME
+             || !live_on_edge (e, name2))
            continue;
 
-         tree name2 = gimple_assign_lhs (use_stmt);
-         if (live_on_edge (e, name2))
+         enum tree_code code = gimple_assign_rhs_code (use_stmt);
+         tree cst;
+         if (code == PLUS_EXPR
+             || code == MINUS_EXPR)
            {
+             cst = gimple_assign_rhs2 (use_stmt);
+             if (TREE_CODE (cst) != INTEGER_CST)
+               continue;
              cst = int_const_binop (code, val, cst);
-             register_new_assert_for (name2, name2, comp_code, cst,
-                                      NULL, e, bsi);
-             retval = true;
            }
+         else if (CONVERT_EXPR_CODE_P (code))
+           {
+             /* For truncating conversions we cannot record
+                an inequality.  */
+             if (comp_code == NE_EXPR
+                 && (TYPE_PRECISION (TREE_TYPE (name2))
+                     < TYPE_PRECISION (TREE_TYPE (name))))
+               continue;
+             cst = fold_convert (TREE_TYPE (name2), val);
+           }
+         else
+           continue;
+
+         if (TREE_OVERFLOW_P (cst))
+           cst = drop_tree_overflow (cst);
+         register_new_assert_for (name2, name2, comp_code, cst,
+                                  NULL, e, bsi);
        }
     }
  
   if (TREE_CODE_CLASS (comp_code) == tcc_comparison
       && TREE_CODE (val) == INTEGER_CST)
     {
-      gimple def_stmt = SSA_NAME_DEF_STMT (name);
+      gimple *def_stmt = SSA_NAME_DEF_STMT (name);
       tree name2 = NULL_TREE, names[2], cst2 = NULL_TREE;
       tree val2 = NULL_TREE;
       unsigned int prec = TYPE_PRECISION (TREE_TYPE (val));
@@ -5185,8 +5333,6 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
 
              register_new_assert_for (name2, tmp, new_comp_code, cst, NULL,
                                       e, bsi);
-
-             retval = true;
            }
        }
 
@@ -5264,7 +5410,6 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
 
              register_new_assert_for (name2, tmp, new_comp_code, new_val,
                                       NULL, e, bsi);
-             retval = true;
            }
        }
 
@@ -5285,8 +5430,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
              && TREE_CODE (TREE_TYPE (val)) == INTEGER_TYPE
              && TYPE_UNSIGNED (TREE_TYPE (val))
              && TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (def_stmt)))
-                > prec
-             && !retval))
+                > prec))
        {
          name2 = gimple_assign_rhs1 (def_stmt);
          if (rhs_code == BIT_AND_EXPR)
@@ -5303,7 +5447,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
              && (nprec > 1
                  || TYPE_UNSIGNED (TREE_TYPE (val))))
            {
-             gimple def_stmt2 = SSA_NAME_DEF_STMT (name2);
+             gimple *def_stmt2 = SSA_NAME_DEF_STMT (name2);
              if (gimple_assign_cast_p (def_stmt2))
                {
                  names[1] = gimple_assign_rhs1 (def_stmt2);
@@ -5510,13 +5654,10 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
 
                    register_new_assert_for (names[i], tmp, LE_EXPR,
                                             new_val, NULL, e, bsi);
-                   retval = true;
                  }
            }
        }
     }
-
-  return retval;
 }
 
 /* OP is an operand of a truth value expression which is known to have
@@ -5526,18 +5667,17 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
    If CODE is EQ_EXPR, then we want to register OP is zero (false),
    if CODE is NE_EXPR, then we want to register OP is nonzero (true).   */
 
-static bool
+static void
 register_edge_assert_for_1 (tree op, enum tree_code code,
                            edge e, gimple_stmt_iterator bsi)
 {
-  bool retval = false;
-  gimple op_def;
+  gimple *op_def;
   tree val;
   enum tree_code rhs_code;
 
   /* We only care about SSA_NAMEs.  */
   if (TREE_CODE (op) != SSA_NAME)
-    return false;
+    return;
 
   /* We know that OP will have a zero or nonzero value.  If OP is used
      more than once go ahead and register an assert for OP.  */
@@ -5546,7 +5686,6 @@ register_edge_assert_for_1 (tree op, enum tree_code code,
     {
       val = build_int_cst (TREE_TYPE (op), 0);
       register_new_assert_for (op, op, code, val, NULL, e, bsi);
-      retval = true;
     }
 
   /* Now look at how OP is set.  If it's set from a comparison,
@@ -5554,7 +5693,7 @@ register_edge_assert_for_1 (tree op, enum tree_code code,
      to register information about the operands of that assignment.  */
   op_def = SSA_NAME_DEF_STMT (op);
   if (gimple_code (op_def) != GIMPLE_ASSIGN)
-    return retval;
+    return;
 
   rhs_code = gimple_assign_rhs_code (op_def);
 
@@ -5565,11 +5704,9 @@ register_edge_assert_for_1 (tree op, enum tree_code code,
       tree op1 = gimple_assign_rhs2 (op_def);
 
       if (TREE_CODE (op0) == SSA_NAME)
-        retval |= register_edge_assert_for_2 (op0, e, bsi, rhs_code, op0, op1,
-                                             invert);
+        register_edge_assert_for_2 (op0, e, bsi, rhs_code, op0, op1, invert);
       if (TREE_CODE (op1) == SSA_NAME)
-        retval |= register_edge_assert_for_2 (op1, e, bsi, rhs_code, op0, op1,
-                                             invert);
+        register_edge_assert_for_2 (op1, e, bsi, rhs_code, op0, op1, invert);
     }
   else if ((code == NE_EXPR
            && gimple_assign_rhs_code (op_def) == BIT_AND_EXPR)
@@ -5581,24 +5718,22 @@ register_edge_assert_for_1 (tree op, enum tree_code code,
       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);
+       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);
+       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)
     {
       /* Recurse, flipping CODE.  */
       code = invert_tree_comparison (code, false);
-      retval |= register_edge_assert_for_1 (gimple_assign_rhs1 (op_def),
-                                           code, e, bsi);
+      register_edge_assert_for_1 (gimple_assign_rhs1 (op_def), code, e, bsi);
     }
   else if (gimple_assign_rhs_code (op_def) == SSA_NAME)
     {
       /* Recurse through the copy.  */
-      retval |= register_edge_assert_for_1 (gimple_assign_rhs1 (op_def),
-                                           code, e, bsi);
+      register_edge_assert_for_1 (gimple_assign_rhs1 (op_def), code, e, bsi);
     }
   else if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (op_def)))
     {
@@ -5608,40 +5743,37 @@ register_edge_assert_for_1 (tree op, enum tree_code code,
       if (INTEGRAL_TYPE_P (TREE_TYPE (rhs))
          && (TYPE_PRECISION (TREE_TYPE (rhs))
              <= TYPE_PRECISION (TREE_TYPE (op))))
-       retval |= register_edge_assert_for_1 (rhs, code, e, bsi);
+       register_edge_assert_for_1 (rhs, code, e, bsi);
     }
-
-  return retval;
 }
 
 /* Try to register an edge assertion for SSA name NAME on edge E for
-   the condition COND contributing to the conditional jump pointed to by SI.
-   Return true if an assertion for NAME could be registered.  */
+   the condition COND contributing to the conditional jump pointed to by
+   SI.  */
 
-static bool
+static void
 register_edge_assert_for (tree name, edge e, gimple_stmt_iterator si,
                          enum tree_code cond_code, tree cond_op0,
                          tree cond_op1)
 {
   tree val;
   enum tree_code comp_code;
-  bool retval = false;
   bool is_else_edge = (e->flags & EDGE_FALSE_VALUE) != 0;
 
   /* Do not attempt to infer anything in names that flow through
      abnormal edges.  */
   if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
-    return false;
+    return;
 
   if (!extract_code_and_val_from_cond_with_ops (name, cond_code,
                                                cond_op0, cond_op1,
                                                is_else_edge,
                                                &comp_code, &val))
-    return false;
+    return;
 
   /* Register ASSERT_EXPRs for name.  */
-  retval |= register_edge_assert_for_2 (name, e, si, cond_code, cond_op0,
-                                       cond_op1, is_else_edge);
+  register_edge_assert_for_2 (name, e, si, cond_code, cond_op0,
+                             cond_op1, is_else_edge);
 
 
   /* If COND is effectively an equality test of an SSA_NAME against
@@ -5654,15 +5786,15 @@ register_edge_assert_for (tree name, edge e, gimple_stmt_iterator si,
   if (((comp_code == EQ_EXPR && integer_onep (val))
        || (comp_code == NE_EXPR && integer_zerop (val))))
     {
-      gimple def_stmt = SSA_NAME_DEF_STMT (name);
+      gimple *def_stmt = SSA_NAME_DEF_STMT (name);
 
       if (is_gimple_assign (def_stmt)
          && gimple_assign_rhs_code (def_stmt) == BIT_AND_EXPR)
        {
          tree op0 = gimple_assign_rhs1 (def_stmt);
          tree op1 = gimple_assign_rhs2 (def_stmt);
-         retval |= register_edge_assert_for_1 (op0, NE_EXPR, e, si);
-         retval |= register_edge_assert_for_1 (op1, NE_EXPR, e, si);
+         register_edge_assert_for_1 (op0, NE_EXPR, e, si);
+         register_edge_assert_for_1 (op1, NE_EXPR, e, si);
        }
     }
 
@@ -5672,7 +5804,7 @@ register_edge_assert_for (tree name, edge e, gimple_stmt_iterator si,
   if (((comp_code == EQ_EXPR && integer_zerop (val))
        || (comp_code == NE_EXPR && integer_onep (val))))
     {
-      gimple def_stmt = SSA_NAME_DEF_STMT (name);
+      gimple *def_stmt = SSA_NAME_DEF_STMT (name);
 
       /* For BIT_IOR_EXPR only if NAME == 0 both operands have
         necessarily zero value, or if type-precision is one.  */
@@ -5683,12 +5815,10 @@ register_edge_assert_for (tree name, edge e, gimple_stmt_iterator si,
        {
          tree op0 = gimple_assign_rhs1 (def_stmt);
          tree op1 = gimple_assign_rhs2 (def_stmt);
-         retval |= register_edge_assert_for_1 (op0, EQ_EXPR, e, si);
-         retval |= register_edge_assert_for_1 (op1, EQ_EXPR, e, si);
+         register_edge_assert_for_1 (op0, EQ_EXPR, e, si);
+         register_edge_assert_for_1 (op1, EQ_EXPR, e, si);
        }
     }
-
-  return retval;
 }
 
 
@@ -5700,17 +5830,15 @@ register_edge_assert_for (tree name, edge e, gimple_stmt_iterator si,
    the predicate operands, an assert location node is added to the
    list of assertions for the corresponding operands.  */
 
-static bool
-find_conditional_asserts (basic_block bb, gimple last)
+static void
+find_conditional_asserts (basic_block bb, gcond *last)
 {
-  bool need_assert;
   gimple_stmt_iterator bsi;
   tree op;
   edge_iterator ei;
   edge e;
   ssa_op_iter iter;
 
-  need_assert = false;
   bsi = gsi_for_stmt (last);
 
   /* Look for uses of the operands in each of the sub-graphs
@@ -5725,15 +5853,11 @@ find_conditional_asserts (basic_block bb, gimple last)
       /* Register the necessary assertions for each operand in the
         conditional predicate.  */
       FOR_EACH_SSA_TREE_OPERAND (op, last, iter, SSA_OP_USE)
-       {
-         need_assert |= register_edge_assert_for (op, e, bsi,
-                                                  gimple_cond_code (last),
-                                                  gimple_cond_lhs (last),
-                                                  gimple_cond_rhs (last));
-       }
+       register_edge_assert_for (op, e, bsi,
+                                 gimple_cond_code (last),
+                                 gimple_cond_lhs (last),
+                                 gimple_cond_rhs (last));
     }
-
-  return need_assert;
 }
 
 struct case_info
@@ -5778,10 +5902,9 @@ compare_case_labels (const void *p1, const void *p2)
    the predicate operands, an assert location node is added to the
    list of assertions for the corresponding operands.  */
 
-static bool
-find_switch_asserts (basic_block bb, gimple last)
+static void
+find_switch_asserts (basic_block bb, gswitch *last)
 {
-  bool need_assert;
   gimple_stmt_iterator bsi;
   tree op;
   edge e;
@@ -5794,11 +5917,10 @@ find_switch_asserts (basic_block bb, gimple last)
   volatile unsigned int idx;
 #endif
 
-  need_assert = false;
   bsi = gsi_for_stmt (last);
   op = gimple_switch_index (last);
   if (TREE_CODE (op) != SSA_NAME)
-    return false;
+    return;
 
   /* Build a vector of case labels sorted by destination label.  */
   ci = XNEWVEC (struct case_info, n);
@@ -5845,22 +5967,15 @@ find_switch_asserts (basic_block bb, gimple last)
 
       /* Register the necessary assertions for the operand in the
         SWITCH_EXPR.  */
-      need_assert |= register_edge_assert_for (op, e, bsi,
-                                              max ? GE_EXPR : EQ_EXPR,
-                                              op,
-                                              fold_convert (TREE_TYPE (op),
-                                                            min));
+      register_edge_assert_for (op, e, bsi,
+                               max ? GE_EXPR : EQ_EXPR,
+                               op, fold_convert (TREE_TYPE (op), min));
       if (max)
-       {
-         need_assert |= register_edge_assert_for (op, e, bsi, LE_EXPR,
-                                                  op,
-                                                  fold_convert (TREE_TYPE (op),
-                                                                max));
-       }
+       register_edge_assert_for (op, e, bsi, LE_EXPR, op,
+                                 fold_convert (TREE_TYPE (op), max));
     }
 
   XDELETEVEC (ci);
-  return need_assert;
 }
 
 
@@ -5921,20 +6036,13 @@ find_switch_asserts (basic_block bb, gimple last)
    registered assertions to prevent adding unnecessary assertions.
    For instance, if a pointer P_4 is dereferenced more than once in a
    dominator tree, only the location dominating all the dereference of
-   P_4 will receive an ASSERT_EXPR.
-
-   If this function returns true, then it means that there are names
-   for which we need to generate ASSERT_EXPRs.  Those assertions are
-   inserted by process_assert_insertions.  */
+   P_4 will receive an ASSERT_EXPR.  */
 
-static bool
+static void
 find_assert_locations_1 (basic_block bb, sbitmap live)
 {
-  gimple_stmt_iterator si;
-  gimple last;
-  bool need_assert;
+  gimple *last;
 
-  need_assert = false;
   last = last_stmt (bb);
 
   /* If BB's last statement is a conditional statement involving integer
@@ -5943,20 +6051,21 @@ find_assert_locations_1 (basic_block bb, sbitmap live)
       && gimple_code (last) == GIMPLE_COND
       && !fp_predicate (last)
       && !ZERO_SSA_OPERANDS (last, SSA_OP_USE))
-    need_assert |= find_conditional_asserts (bb, last);
+    find_conditional_asserts (bb, as_a <gcond *> (last));
 
   /* If BB's last statement is a switch statement involving integer
      operands, determine if we need to add ASSERT_EXPRs.  */
   if (last
       && gimple_code (last) == GIMPLE_SWITCH
       && !ZERO_SSA_OPERANDS (last, SSA_OP_USE))
-    need_assert |= find_switch_asserts (bb, last);
+    find_switch_asserts (bb, as_a <gswitch *> (last));
 
   /* Traverse all the statements in BB marking used names and looking
      for statements that may infer assertions for their used operands.  */
-  for (si = gsi_last_bb (bb); !gsi_end_p (si); gsi_prev (&si))
+  for (gimple_stmt_iterator si = gsi_last_bb (bb); !gsi_end_p (si);
+       gsi_prev (&si))
     {
-      gimple stmt;
+      gimple *stmt;
       tree op;
       ssa_op_iter i;
 
@@ -5990,10 +6099,11 @@ find_assert_locations_1 (basic_block bb, sbitmap live)
              if (comp_code == NE_EXPR && integer_zerop (value))
                {
                  tree t = op;
-                 gimple def_stmt = SSA_NAME_DEF_STMT (t);
+                 gimple *def_stmt = SSA_NAME_DEF_STMT (t);
 
                  while (is_gimple_assign (def_stmt)
-                        && gimple_assign_rhs_code (def_stmt)  == NOP_EXPR
+                        && CONVERT_EXPR_CODE_P
+                            (gimple_assign_rhs_code (def_stmt))
                         && TREE_CODE
                             (gimple_assign_rhs1 (def_stmt)) == SSA_NAME
                         && POINTER_TYPE_P
@@ -6006,16 +6116,12 @@ find_assert_locations_1 (basic_block bb, sbitmap live)
                         operand of the NOP_EXPR after SI, not after the
                         conversion.  */
                      if (! has_single_use (t))
-                       {
-                         register_new_assert_for (t, t, comp_code, value,
-                                                  bb, NULL, si);
-                         need_assert = true;
-                       }
+                       register_new_assert_for (t, t, comp_code, value,
+                                                bb, NULL, si);
                    }
                }
 
              register_new_assert_for (op, op, comp_code, value, bb, NULL, si);
-             need_assert = true;
            }
        }
 
@@ -6027,11 +6133,12 @@ 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 (gphi_iterator si = gsi_start_phis (bb); !gsi_end_p (si);
+       gsi_next (&si))
     {
       use_operand_p arg_p;
       ssa_op_iter i;
-      gimple phi = gsi_stmt (si);
+      gphi *phi = si.phi ();
       tree res = gimple_phi_result (phi);
 
       if (virtual_operand_p (res))
@@ -6046,22 +6153,18 @@ find_assert_locations_1 (basic_block bb, sbitmap live)
 
       bitmap_clear_bit (live, SSA_NAME_VERSION (res));
     }
-
-  return need_assert;
 }
 
 /* Do an RPO walk over the function computing SSA name liveness
-   on-the-fly and deciding on assert expressions to insert.
-   Returns true if there are assert expressions to be inserted.  */
+   on-the-fly and deciding on assert expressions to insert.  */
 
-static bool
+static void
 find_assert_locations (void)
 {
   int *rpo = XNEWVEC (int, last_basic_block_for_fn (cfun));
   int *bb_rpo = XNEWVEC (int, last_basic_block_for_fn (cfun));
   int *last_rpo = XCNEWVEC (int, last_basic_block_for_fn (cfun));
   int rpo_cnt, i;
-  bool need_asserts;
 
   live = XCNEWVEC (sbitmap, last_basic_block_for_fn (cfun));
   rpo_cnt = pre_and_rev_post_order_compute (NULL, rpo, false);
@@ -6076,10 +6179,10 @@ find_assert_locations (void)
     {
       i = loop->latch->index;
       unsigned int j = single_succ_edge (loop->latch)->dest_idx;
-      for (gimple_stmt_iterator gsi = gsi_start_phis (loop->header);
+      for (gphi_iterator gsi = gsi_start_phis (loop->header);
           !gsi_end_p (gsi); gsi_next (&gsi))
        {
-         gimple phi = gsi_stmt (gsi);
+         gphi *phi = gsi.phi ();
          if (virtual_operand_p (gimple_phi_result (phi)))
            continue;
          tree arg = gimple_phi_arg_def (phi, j);
@@ -6095,7 +6198,6 @@ find_assert_locations (void)
        }
     }
 
-  need_asserts = false;
   for (i = rpo_cnt - 1; i >= 0; --i)
     {
       basic_block bb = BASIC_BLOCK_FOR_FN (cfun, rpo[i]);
@@ -6110,7 +6212,7 @@ find_assert_locations (void)
 
       /* Process BB and update the live information with uses in
          this block.  */
-      need_asserts |= find_assert_locations_1 (bb, live[rpo[i]]);
+      find_assert_locations_1 (bb, live[rpo[i]]);
 
       /* Merge liveness into the predecessor blocks and free it.  */
       if (!bitmap_empty_p (live[rpo[i]]))
@@ -6161,20 +6263,18 @@ find_assert_locations (void)
     if (live[i])
       sbitmap_free (live[i]);
   XDELETEVEC (live);
-
-  return need_asserts;
 }
 
 /* Create an ASSERT_EXPR for NAME and insert it in the location
    indicated by LOC.  Return true if we made any edge insertions.  */
 
 static bool
-process_assert_insertions_for (tree name, assert_locus_t loc)
+process_assert_insertions_for (tree name, assert_locus *loc)
 {
   /* Build the comparison expression NAME_i COMP_CODE VAL.  */
-  gimple stmt;
+  gimple *stmt;
   tree cond;
-  gimple assert_stmt;
+  gimple *assert_stmt;
   edge_iterator ei;
   edge e;
 
@@ -6237,12 +6337,12 @@ process_assert_insertions (void)
 
   EXECUTE_IF_SET_IN_BITMAP (need_assert_for, 0, i, bi)
     {
-      assert_locus_t loc = asserts_for[i];
+      assert_locus *loc = asserts_for[i];
       gcc_assert (loc);
 
       while (loc)
        {
-         assert_locus_t next = loc->next;
+         assert_locus *next = loc->next;
          update_edges_p |= process_assert_insertions_for (ssa_name (i), loc);
          free (loc);
          loc = next;
@@ -6294,11 +6394,12 @@ static void
 insert_range_assertions (void)
 {
   need_assert_for = BITMAP_ALLOC (NULL);
-  asserts_for = XCNEWVEC (assert_locus_t, num_ssa_names);
+  asserts_for = XCNEWVEC (assert_locus *, num_ssa_names);
 
   calculate_dominance_info (CDI_DOMINATORS);
 
-  if (find_assert_locations ())
+  find_assert_locations ();
+  if (!bitmap_empty_p (need_assert_for))
     {
       process_assert_insertions ();
       update_ssa (TODO_update_ssa_no_phi);
@@ -6324,7 +6425,7 @@ insert_range_assertions (void)
 static void
 check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
 {
-  value_range_t* vr = NULL;
+  value_range *vr = NULL;
   tree low_sub, up_sub;
   tree low_bound, up_bound, up_bound_p1;
   tree base;
@@ -6343,7 +6444,8 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
   /* Accesses to trailing arrays via pointers may access storage
      beyond the types array bounds.  */
   base = get_base_address (ref);
-  if (base && TREE_CODE (base) == MEM_REF)
+  if ((warn_array_bounds < 2)
+      && base && TREE_CODE (base) == MEM_REF)
     {
       tree cref, next = NULL_TREE;
 
@@ -6367,6 +6469,14 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
   up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound,
                                 build_int_cst (TREE_TYPE (up_bound), 1));
 
+  /* Empty array.  */
+  if (tree_int_cst_equal (low_bound, up_bound_p1))
+    {
+      warning_at (location, OPT_Warray_bounds,
+                 "array subscript is above array bounds");
+      TREE_NO_WARNING (ref) = 1;
+    }
+
   if (TREE_CODE (low_sub) == SSA_NAME)
     {
       vr = get_value_range (low_sub);
@@ -6380,9 +6490,11 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
   if (vr && vr->type == VR_ANTI_RANGE)
     {
       if (TREE_CODE (up_sub) == INTEGER_CST
-          && tree_int_cst_lt (up_bound, up_sub)
+          && (ignore_off_by_one
+             ? tree_int_cst_lt (up_bound, up_sub)
+             : tree_int_cst_le (up_bound, up_sub))
           && TREE_CODE (low_sub) == INTEGER_CST
-          && tree_int_cst_lt (low_sub, low_bound))
+          && tree_int_cst_le (low_sub, low_bound))
         {
           warning_at (location, OPT_Warray_bounds,
                      "array subscript is outside array bounds");
@@ -6391,10 +6503,8 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
     }
   else if (TREE_CODE (up_sub) == INTEGER_CST
           && (ignore_off_by_one
-              ? (tree_int_cst_lt (up_bound, up_sub)
-                 && !tree_int_cst_equal (up_bound_p1, up_sub))
-              : (tree_int_cst_lt (up_bound, up_sub)
-                 || tree_int_cst_equal (up_bound_p1, up_sub))))
+              ? !tree_int_cst_le (up_sub, up_bound_p1)
+              : !tree_int_cst_le (up_sub, up_bound)))
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
        {
@@ -6427,25 +6537,6 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
 static void
 search_for_addr_array (tree t, location_t location)
 {
-  while (TREE_CODE (t) == SSA_NAME)
-    {
-      gimple g = SSA_NAME_DEF_STMT (t);
-
-      if (gimple_code (g) != GIMPLE_ASSIGN)
-       return;
-
-      if (get_gimple_rhs_class (gimple_assign_rhs_code (g))
-         != GIMPLE_SINGLE_RHS)
-       return;
-
-      t = gimple_assign_rhs1 (g);
-    }
-
-
-  /* We are only interested in addresses of ARRAY_REF's.  */
-  if (TREE_CODE (t) != ADDR_EXPR)
-    return;
-
   /* Check each ARRAY_REFs in the reference chain. */
   do
     {
@@ -6535,12 +6626,11 @@ check_array_bounds (tree *tp, int *walk_subtree, void *data)
   if (TREE_CODE (t) == ARRAY_REF)
     check_array_ref (location, t, false /*ignore_off_by_one*/);
 
-  if (TREE_CODE (t) == MEM_REF
-      || (TREE_CODE (t) == RETURN_EXPR && TREE_OPERAND (t, 0)))
-    search_for_addr_array (TREE_OPERAND (t, 0), location);
-
-  if (TREE_CODE (t) == ADDR_EXPR)
-    *walk_subtree = FALSE;
+  else if (TREE_CODE (t) == ADDR_EXPR)
+    {
+      search_for_addr_array (t, location);
+      *walk_subtree = FALSE;
+    }
 
   return NULL_TREE;
 }
@@ -6568,31 +6658,20 @@ check_all_array_refs (void)
 
       for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
        {
-         gimple stmt = gsi_stmt (si);
+         gimple *stmt = gsi_stmt (si);
          struct walk_stmt_info wi;
-         if (!gimple_has_location (stmt))
+         if (!gimple_has_location (stmt)
+             || is_gimple_debug (stmt))
            continue;
 
-         if (is_gimple_call (stmt))
-           {
-             size_t i;
-             size_t n = gimple_call_num_args (stmt);
-             for (i = 0; i < n; i++)
-               {
-                 tree arg = gimple_call_arg (stmt, i);
-                 search_for_addr_array (arg, gimple_location (stmt));
-               }
-           }
-         else
-           {
-             memset (&wi, 0, sizeof (wi));
-             wi.info = CONST_CAST (void *, (const void *)
-                                   gimple_location_ptr (stmt));
+         memset (&wi, 0, sizeof (wi));
 
-             walk_gimple_op (gsi_stmt (si),
-                             check_array_bounds,
-                             &wi);
-           }
+         location_t loc = gimple_location (stmt);
+         wi.info = &loc;
+
+         walk_gimple_op (gsi_stmt (si),
+                         check_array_bounds,
+                         &wi);
        }
     }
 }
@@ -6602,7 +6681,7 @@ check_all_array_refs (void)
    in basic block COND_BB.  */
 
 static bool
-all_imm_uses_in_stmt_or_feed_cond (tree var, gimple stmt, basic_block cond_bb)
+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;
@@ -6610,7 +6689,7 @@ all_imm_uses_in_stmt_or_feed_cond (tree var, gimple stmt, basic_block cond_bb)
   FOR_EACH_IMM_USE_FAST (use_p, iter, var)
     if (USE_STMT (use_p) != stmt)
       {
-       gimple use_stmt = USE_STMT (use_p), use_stmt2;
+       gimple *use_stmt = USE_STMT (use_p), *use_stmt2;
        if (is_gimple_debug (use_stmt))
          continue;
        while (is_gimple_assign (use_stmt)
@@ -6644,7 +6723,7 @@ 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);
+  gimple *stmt = last_stmt (cond_bb);
   tree cst;
 
   if (stmt == NULL
@@ -6662,7 +6741,7 @@ maybe_set_nonzero_bits (basic_block bb, tree var)
     return;
   if (gimple_assign_rhs1 (stmt) != var)
     {
-      gimple stmt2;
+      gimple *stmt2;
 
       if (TREE_CODE (gimple_assign_rhs1 (stmt)) != SSA_NAME)
        return;
@@ -6718,8 +6797,8 @@ remove_range_assertions (void)
   FOR_EACH_BB_FN (bb, cfun)
     for (si = gsi_after_labels (bb), is_unreachable = -1; !gsi_end_p (si);)
       {
-       gimple stmt = gsi_stmt (si);
-       gimple use_stmt;
+       gimple *stmt = gsi_stmt (si);
+       gimple *use_stmt;
 
        if (is_gimple_assign (stmt)
            && gimple_assign_rhs_code (stmt) == ASSERT_EXPR)
@@ -6727,12 +6806,9 @@ remove_range_assertions (void)
            tree lhs = gimple_assign_lhs (stmt);
            tree rhs = gimple_assign_rhs1 (stmt);
            tree var;
-           tree cond = fold (ASSERT_EXPR_COND (rhs));
            use_operand_p use_p;
            imm_use_iterator iter;
 
-           gcc_assert (cond != boolean_false_node);
-
            var = ASSERT_EXPR_VAR (rhs);
            gcc_assert (TREE_CODE (var) == SSA_NAME);
 
@@ -6788,7 +6864,7 @@ remove_range_assertions (void)
 /* Return true if STMT is interesting for VRP.  */
 
 static bool
-stmt_interesting_for_vrp (gimple stmt)
+stmt_interesting_for_vrp (gimple *stmt)
 {
   if (gimple_code (stmt) == GIMPLE_PHI)
     {
@@ -6810,6 +6886,20 @@ stmt_interesting_for_vrp (gimple stmt)
          && (is_gimple_call (stmt)
              || !gimple_vuse (stmt)))
        return true;
+      else if (is_gimple_call (stmt) && gimple_call_internal_p (stmt))
+       switch (gimple_call_internal_fn (stmt))
+         {
+         case IFN_ADD_OVERFLOW:
+         case IFN_SUB_OVERFLOW:
+         case IFN_MUL_OVERFLOW:
+           /* These internal calls return _Complex integer type,
+              but are interesting to VRP nevertheless.  */
+           if (lhs && TREE_CODE (lhs) == SSA_NAME)
+             return true;
+           break;
+         default:
+           break;
+         }
     }
   else if (gimple_code (stmt) == GIMPLE_COND
           || gimple_code (stmt) == GIMPLE_SWITCH)
@@ -6828,16 +6918,15 @@ vrp_initialize (void)
 
   values_propagated = false;
   num_vr_values = num_ssa_names;
-  vr_value = XCNEWVEC (value_range_t *, num_vr_values);
+  vr_value = XCNEWVEC (value_range *, num_vr_values);
   vr_phi_edge_counts = XCNEWVEC (int, num_ssa_names);
 
   FOR_EACH_BB_FN (bb, cfun)
     {
-      gimple_stmt_iterator si;
-
-      for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
+      for (gphi_iterator si = gsi_start_phis (bb); !gsi_end_p (si);
+          gsi_next (&si))
        {
-         gimple phi = gsi_stmt (si);
+         gphi *phi = si.phi ();
          if (!stmt_interesting_for_vrp (phi))
            {
              tree lhs = PHI_RESULT (phi);
@@ -6848,9 +6937,10 @@ vrp_initialize (void)
            prop_set_simulate_again (phi, true);
        }
 
-      for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
+      for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si);
+          gsi_next (&si))
         {
-         gimple stmt = gsi_stmt (si);
+         gimple *stmt = gsi_stmt (si);
 
          /* If the statement is a control insn, then we do not
             want to avoid simulating the statement once.  Failure
@@ -6878,7 +6968,7 @@ vrp_valueize (tree name)
 {
   if (TREE_CODE (name) == SSA_NAME)
     {
-      value_range_t *vr = get_value_range (name);
+      value_range *vr = get_value_range (name);
       if (vr->type == VR_RANGE
          && (vr->min == vr->max
              || operand_equal_p (vr->min, vr->max, 0)))
@@ -6887,11 +6977,33 @@ vrp_valueize (tree name)
   return name;
 }
 
+/* Return the singleton value-range for NAME if that is a constant
+   but signal to not follow SSA edges.  */
+
+static inline tree
+vrp_valueize_1 (tree name)
+{
+  if (TREE_CODE (name) == SSA_NAME)
+    {
+      /* If the definition may be simulated again we cannot follow
+         this SSA edge as the SSA propagator does not necessarily
+        re-visit the use.  */
+      gimple *def_stmt = SSA_NAME_DEF_STMT (name);
+      if (!gimple_nop_p (def_stmt)
+         && prop_simulate_again_p (def_stmt))
+       return NULL_TREE;
+      value_range *vr = get_value_range (name);
+      if (range_int_cst_singleton_p (vr))
+       return vr->min;
+    }
+  return name;
+}
+
 /* Visit assignment STMT.  If it produces an interesting range, record
    the SSA name in *OUTPUT_P.  */
 
 static enum ssa_prop_result
-vrp_visit_assignment_or_call (gimple stmt, tree *output_p)
+vrp_visit_assignment_or_call (gimple *stmt, tree *output_p)
 {
   tree def, lhs;
   ssa_op_iter iter;
@@ -6907,17 +7019,18 @@ vrp_visit_assignment_or_call (gimple stmt, tree *output_p)
           && TYPE_MAX_VALUE (TREE_TYPE (lhs)))
          || POINTER_TYPE_P (TREE_TYPE (lhs))))
     {
-      value_range_t new_vr = VR_INITIALIZER;
+      value_range new_vr = VR_INITIALIZER;
 
       /* Try folding the statement to a constant first.  */
-      tree tem = gimple_fold_stmt_to_constant (stmt, vrp_valueize);
-      if (tem)
+      tree tem = gimple_fold_stmt_to_constant_1 (stmt, vrp_valueize,
+                                                vrp_valueize_1);
+      if (tem && is_gimple_min_invariant (tem))
        set_value_range_to_value (&new_vr, 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);
+       extract_range_from_assignment (&new_vr, as_a <gassign *> (stmt));
 
       if (update_value_range (lhs, &new_vr))
        {
@@ -6940,6 +7053,74 @@ vrp_visit_assignment_or_call (gimple stmt, tree *output_p)
 
       return SSA_PROP_NOT_INTERESTING;
     }
+  else if (is_gimple_call (stmt) && gimple_call_internal_p (stmt))
+    switch (gimple_call_internal_fn (stmt))
+      {
+      case IFN_ADD_OVERFLOW:
+      case IFN_SUB_OVERFLOW:
+      case IFN_MUL_OVERFLOW:
+       /* These internal calls return _Complex integer type,
+          which VRP does not track, but the immediate uses
+          thereof might be interesting.  */
+       if (lhs && TREE_CODE (lhs) == SSA_NAME)
+         {
+           imm_use_iterator iter;
+           use_operand_p use_p;
+           enum ssa_prop_result res = SSA_PROP_VARYING;
+
+           set_value_range_to_varying (get_value_range (lhs));
+
+           FOR_EACH_IMM_USE_FAST (use_p, iter, lhs)
+             {
+               gimple *use_stmt = USE_STMT (use_p);
+               if (!is_gimple_assign (use_stmt))
+                 continue;
+               enum tree_code rhs_code = gimple_assign_rhs_code (use_stmt);
+               if (rhs_code != REALPART_EXPR && rhs_code != IMAGPART_EXPR)
+                 continue;
+               tree rhs1 = gimple_assign_rhs1 (use_stmt);
+               tree use_lhs = gimple_assign_lhs (use_stmt);
+               if (TREE_CODE (rhs1) != rhs_code
+                   || TREE_OPERAND (rhs1, 0) != lhs
+                   || TREE_CODE (use_lhs) != SSA_NAME
+                   || !stmt_interesting_for_vrp (use_stmt)
+                   || (!INTEGRAL_TYPE_P (TREE_TYPE (use_lhs))
+                       || !TYPE_MIN_VALUE (TREE_TYPE (use_lhs))
+                       || !TYPE_MAX_VALUE (TREE_TYPE (use_lhs))))
+                 continue;
+
+               /* If there is a change in the value range for any of the
+                  REALPART_EXPR/IMAGPART_EXPR immediate uses, return
+                  SSA_PROP_INTERESTING.  If there are any REALPART_EXPR
+                  or IMAGPART_EXPR immediate uses, but none of them have
+                  a change in their value ranges, return
+                  SSA_PROP_NOT_INTERESTING.  If there are no
+                  {REAL,IMAG}PART_EXPR uses at all,
+                  return SSA_PROP_VARYING.  */
+               value_range new_vr = VR_INITIALIZER;
+               extract_range_basic (&new_vr, use_stmt);
+               value_range *old_vr = get_value_range (use_lhs);
+               if (old_vr->type != new_vr.type
+                   || !vrp_operand_equal_p (old_vr->min, new_vr.min)
+                   || !vrp_operand_equal_p (old_vr->max, new_vr.max)
+                   || !vrp_bitmap_equal_p (old_vr->equiv, new_vr.equiv))
+                 res = SSA_PROP_INTERESTING;
+               else
+                 res = SSA_PROP_NOT_INTERESTING;
+               BITMAP_FREE (new_vr.equiv);
+               if (res == SSA_PROP_INTERESTING)
+                 {
+                   *output_p = lhs;
+                   return res;
+                 }
+             }
+
+           return res;
+         }
+       break;
+      default:
+       break;
+      }
 
   /* Every other statement produces no useful ranges.  */
   FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF)
@@ -6952,10 +7133,10 @@ vrp_visit_assignment_or_call (gimple stmt, tree *output_p)
    or a symbolic range containing the SSA_NAME only if the value range
    is varying or undefined.  */
 
-static inline value_range_t
+static inline value_range
 get_vr_for_comparison (int i)
 {
-  value_range_t vr = *get_value_range (ssa_name (i));
+  value_range vr = *get_value_range (ssa_name (i));
 
   /* If name N_i does not have a valid range, use N_i as its own
      range.  This allows us to compare against names that may
@@ -6985,7 +7166,7 @@ compare_name_with_value (enum tree_code comp, tree var, tree val,
   tree retval, t;
   int used_strict_overflow;
   bool sop;
-  value_range_t equiv_vr;
+  value_range equiv_vr;
 
   /* Get the set of equivalences for VAR.  */
   e = get_value_range (var)->equiv;
@@ -7108,14 +7289,14 @@ compare_names (enum tree_code comp, tree n1, tree n2,
      of the loop just to check N1 and N2 ranges.  */
   EXECUTE_IF_SET_IN_BITMAP (e1, 0, i1, bi1)
     {
-      value_range_t vr1 = get_vr_for_comparison (i1);
+      value_range vr1 = get_vr_for_comparison (i1);
 
       t = retval = NULL_TREE;
       EXECUTE_IF_SET_IN_BITMAP (e2, 0, i2, bi2)
        {
          bool sop = false;
 
-         value_range_t vr2 = get_vr_for_comparison (i2);
+         value_range vr2 = get_vr_for_comparison (i2);
 
          t = compare_ranges (comp, &vr1, &vr2, &sop);
          if (t)
@@ -7157,14 +7338,15 @@ compare_names (enum tree_code comp, tree n1, tree n2,
   return NULL_TREE;
 }
 
-/* Helper function for vrp_evaluate_conditional_warnv.  */
+/* Helper function for vrp_evaluate_conditional_warnv & other
+   optimizers.  */
 
 static tree
 vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code code,
                                                      tree op0, tree op1,
                                                      bool * strict_overflow_p)
 {
-  value_range_t *vr0, *vr1;
+  value_range *vr0, *vr1;
 
   vr0 = (TREE_CODE (op0) == SSA_NAME) ? get_value_range (op0) : NULL;
   vr1 = (TREE_CODE (op1) == SSA_NAME) ? get_value_range (op1) : NULL;
@@ -7225,7 +7407,7 @@ vrp_evaluate_conditional_warnv_with_ops (enum tree_code code, tree op0,
    appropriate.  */
 
 static tree
-vrp_evaluate_conditional (enum tree_code code, tree op0, tree op1, gimple stmt)
+vrp_evaluate_conditional (tree_code code, tree op0, tree op1, gimple *stmt)
 {
   bool sop;
   tree ret;
@@ -7284,9 +7466,9 @@ vrp_evaluate_conditional (enum tree_code code, tree op0, tree op1, gimple stmt)
         always fold regardless of the value of OP0.  If -Wtype-limits
         was specified, emit a warning.  */
       tree type = TREE_TYPE (op0);
-      value_range_t *vr0 = get_value_range (op0);
+      value_range *vr0 = get_value_range (op0);
 
-      if (vr0->type != VR_VARYING
+      if (vr0->type == VR_RANGE
          && INTEGRAL_TYPE_P (type)
          && vrp_val_is_min (vr0->min)
          && vrp_val_is_max (vr0->max)
@@ -7318,7 +7500,7 @@ vrp_evaluate_conditional (enum tree_code code, tree op0, tree op1, gimple stmt)
    SSA_PROP_VARYING.  */
 
 static enum ssa_prop_result
-vrp_visit_cond_stmt (gimple stmt, edge *taken_edge_p)
+vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p)
 {
   tree val;
   bool sop;
@@ -7433,7 +7615,7 @@ vrp_visit_cond_stmt (gimple stmt, edge *taken_edge_p)
    returned. */
 
 static bool
-find_case_label_index (gimple stmt, size_t start_idx, tree val, size_t *idx)
+find_case_label_index (gswitch *stmt, size_t start_idx, tree val, size_t *idx)
 {
   size_t n = gimple_switch_num_labels (stmt);
   size_t low, high;
@@ -7483,7 +7665,7 @@ find_case_label_index (gimple stmt, size_t start_idx, tree val, size_t *idx)
    Returns true if the default label is not needed. */
 
 static bool
-find_case_label_range (gimple stmt, tree min, tree max, size_t *min_idx,
+find_case_label_range (gswitch *stmt, tree min, tree max, size_t *min_idx,
                       size_t *max_idx)
 {
   size_t i, j;
@@ -7539,7 +7721,7 @@ find_case_label_range (gimple stmt, tree min, tree max, size_t *min_idx,
    Returns true if the default label is not needed.  */
 
 static bool
-find_case_label_ranges (gimple stmt, value_range_t *vr, size_t *min_idx1,
+find_case_label_ranges (gswitch *stmt, value_range *vr, size_t *min_idx1,
                        size_t *max_idx1, size_t *min_idx2,
                        size_t *max_idx2)
 {
@@ -7617,10 +7799,10 @@ find_case_label_ranges (gimple stmt, value_range_t *vr, size_t *min_idx1,
    SSA_PROP_VARYING.  */
 
 static enum ssa_prop_result
-vrp_visit_switch_stmt (gimple stmt, edge *taken_edge_p)
+vrp_visit_switch_stmt (gswitch *stmt, edge *taken_edge_p)
 {
   tree op, val;
-  value_range_t *vr;
+  value_range *vr;
   size_t i = 0, j = 0, k, l;
   bool take_default;
 
@@ -7714,7 +7896,7 @@ vrp_visit_switch_stmt (gimple stmt, edge *taken_edge_p)
    If STMT produces a varying value, return SSA_PROP_VARYING.  */
 
 static enum ssa_prop_result
-vrp_visit_stmt (gimple stmt, edge *taken_edge_p, tree *output_p)
+vrp_visit_stmt (gimple *stmt, edge *taken_edge_p, tree *output_p)
 {
   tree def;
   ssa_op_iter iter;
@@ -7730,9 +7912,9 @@ vrp_visit_stmt (gimple stmt, edge *taken_edge_p, tree *output_p)
   else if (is_gimple_assign (stmt) || is_gimple_call (stmt))
     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);
+    return vrp_visit_cond_stmt (as_a <gcond *> (stmt), taken_edge_p);
   else if (gimple_code (stmt) == GIMPLE_SWITCH)
-    return vrp_visit_switch_stmt (stmt, taken_edge_p);
+    return vrp_visit_switch_stmt (as_a <gswitch *> (stmt), taken_edge_p);
 
   /* All other statements produce nothing of interest for VRP, so mark
      their outputs varying and prevent further simulation.  */
@@ -8293,9 +8475,9 @@ intersect_ranges (enum value_range_type *vr0type,
    in *VR0.  This may not be the smallest possible such range.  */
 
 static void
-vrp_intersect_ranges_1 (value_range_t *vr0, value_range_t *vr1)
+vrp_intersect_ranges_1 (value_range *vr0, value_range *vr1)
 {
-  value_range_t saved;
+  value_range saved;
 
   /* If either range is VR_VARYING the other one wins.  */
   if (vr1->type == VR_VARYING)
@@ -8345,7 +8527,7 @@ vrp_intersect_ranges_1 (value_range_t *vr0, value_range_t *vr1)
 }
 
 static void
-vrp_intersect_ranges (value_range_t *vr0, value_range_t *vr1)
+vrp_intersect_ranges (value_range *vr0, value_range *vr1)
 {
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
@@ -8369,9 +8551,9 @@ vrp_intersect_ranges (value_range_t *vr0, value_range_t *vr1)
    may not be the smallest possible such range.  */
 
 static void
-vrp_meet_1 (value_range_t *vr0, value_range_t *vr1)
+vrp_meet_1 (value_range *vr0, value_range *vr1)
 {
-  value_range_t saved;
+  value_range saved;
 
   if (vr0->type == VR_UNDEFINED)
     {
@@ -8442,7 +8624,7 @@ vrp_meet_1 (value_range_t *vr0, value_range_t *vr1)
 }
 
 static void
-vrp_meet (value_range_t *vr0, value_range_t *vr1)
+vrp_meet (value_range *vr0, value_range *vr1)
 {
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
@@ -8467,12 +8649,12 @@ vrp_meet (value_range_t *vr0, value_range_t *vr1)
    value ranges, set a new range for the LHS of PHI.  */
 
 static enum ssa_prop_result
-vrp_visit_phi_node (gimple phi)
+vrp_visit_phi_node (gphi *phi)
 {
   size_t i;
   tree lhs = PHI_RESULT (phi);
-  value_range_t *lhs_vr = get_value_range (lhs);
-  value_range_t vr_result = VR_INITIALIZER;
+  value_range *lhs_vr = get_value_range (lhs);
+  value_range vr_result = VR_INITIALIZER;
   bool first = true;
   int edges, old_edges;
   struct loop *l;
@@ -8499,7 +8681,7 @@ vrp_visit_phi_node (gimple phi)
       if (e->flags & EDGE_EXECUTABLE)
        {
          tree arg = PHI_ARG_DEF (phi, i);
-         value_range_t vr_arg;
+         value_range vr_arg;
 
          ++edges;
 
@@ -8602,7 +8784,7 @@ vrp_visit_phi_node (gimple phi)
          && (cmp_min != 0 || cmp_max != 0))
        goto varying;
 
-      /* If the new minimum is larger than than the previous one
+      /* If the new minimum is larger than the previous one
         retain the old value.  If the new minimum value is smaller
         than the previous one and not -INF go all the way to -INF + 1.
         In the first case, to avoid infinite bouncing between different
@@ -8631,20 +8813,11 @@ vrp_visit_phi_node (gimple phi)
 
       /* 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
+      if (cmp_min > 0 || cmp_min < 0
           || cmp_max < 0 || cmp_max > 0)
-         && (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;
+       goto scev_check;
+
+      goto infinite_check;
     }
 
   /* If the new range is different than the previous value, keep
@@ -8661,14 +8834,37 @@ update_range:
          fprintf (dump_file, "\n");
        }
 
+      if (vr_result.type == VR_VARYING)
+       return SSA_PROP_VARYING;
+
       return SSA_PROP_INTERESTING;
     }
 
   /* Nothing changed, don't add outgoing edges.  */
   return SSA_PROP_NOT_INTERESTING;
 
-  /* No match found.  Set the LHS to VARYING.  */
 varying:
+  set_value_range_to_varying (&vr_result);
+
+scev_check:
+  /* If this is a loop PHI node SCEV may known more about its value-range.
+     scev_check can be reached from two paths, one is a fall through from above
+     "varying" label, the other is direct goto from code block which tries to
+     avoid infinite simulation.  */
+  if ((l = loop_containing_stmt (phi))
+      && l->header == gimple_bb (phi))
+    adjust_range_with_scev (&vr_result, l, phi, lhs);
+
+infinite_check:
+  /* 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 ((vr_result.type == VR_RANGE || vr_result.type == VR_ANTI_RANGE)
+      && !((vrp_val_is_max (vr_result.max) && vrp_val_is_min (vr_result.min))
+          || compare_values (vr_result.min, vr_result.max) > 0))
+    goto update_range;
+
+  /* No match found.  Set the LHS to VARYING.  */
   set_value_range_to_varying (lhs_vr);
   return SSA_PROP_VARYING;
 }
@@ -8676,7 +8872,7 @@ varying:
 /* Simplify boolean operations if the source is known
    to be already a boolean.  */
 static bool
-simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
+simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
 {
   enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
   tree lhs, op0, op1;
@@ -8719,15 +8915,15 @@ simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
   if (integer_zerop (op1))
     gimple_assign_set_rhs_with_ops (gsi,
                                    need_conversion
-                                   ? NOP_EXPR : TREE_CODE (op0),
-                                   op0, NULL_TREE);
+                                   ? NOP_EXPR : TREE_CODE (op0), op0);
   /* For A != B we substitute A ^ B.  Either with conversion.  */
   else if (need_conversion)
     {
-      tree tem = make_ssa_name (TREE_TYPE (op0), NULL);
-      gimple newop = gimple_build_assign_with_ops (BIT_XOR_EXPR, tem, op0, op1);
+      tree tem = make_ssa_name (TREE_TYPE (op0));
+      gassign *newop
+       = gimple_build_assign (tem, BIT_XOR_EXPR, op0, op1);
       gsi_insert_before (gsi, newop, GSI_SAME_STMT);
-      gimple_assign_set_rhs_with_ops (gsi, NOP_EXPR, tem, NULL_TREE);
+      gimple_assign_set_rhs_with_ops (gsi, NOP_EXPR, tem);
     }
   /* Or without.  */
   else
@@ -8739,21 +8935,55 @@ simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
 
 /* Simplify a division or modulo operator to a right shift or
    bitwise and if the first operand is unsigned or is greater
-   than zero and the second operand is an exact power of two.  */
+   than zero and the second operand is an exact power of two.
+   For TRUNC_MOD_EXPR op0 % op1 with constant op1, optimize it
+   into just op0 if op0's range is known to be a subset of
+   [-op1 + 1, op1 - 1] for signed and [0, op1 - 1] for unsigned
+   modulo.  */
 
 static bool
-simplify_div_or_mod_using_ranges (gimple stmt)
+simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
 {
   enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
   tree val = NULL;
   tree op0 = gimple_assign_rhs1 (stmt);
   tree op1 = gimple_assign_rhs2 (stmt);
-  value_range_t *vr = get_value_range (gimple_assign_rhs1 (stmt));
+  value_range *vr = get_value_range (op0);
+
+  if (rhs_code == TRUNC_MOD_EXPR
+      && TREE_CODE (op1) == INTEGER_CST
+      && tree_int_cst_sgn (op1) == 1
+      && range_int_cst_p (vr)
+      && tree_int_cst_lt (vr->max, op1))
+    {
+      if (TYPE_UNSIGNED (TREE_TYPE (op0))
+         || tree_int_cst_sgn (vr->min) >= 0
+         || tree_int_cst_lt (fold_unary (NEGATE_EXPR, TREE_TYPE (op1), op1),
+                             vr->min))
+       {
+         /* If op0 already has the range op0 % op1 has,
+            then TRUNC_MOD_EXPR won't change anything.  */
+         gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+         gimple_assign_set_rhs_from_tree (&gsi, op0);
+         update_stmt (stmt);
+         return true;
+       }
+    }
 
-  if (TYPE_UNSIGNED (TREE_TYPE (op0)))
+  if (!integer_pow2p (op1))
     {
-      val = integer_one_node;
+      /* X % -Y can be only optimized into X % Y either if
+        X is not INT_MIN, or Y is not -1.  Fold it now, as after
+        remove_range_assertions the range info might be not available
+        anymore.  */
+      if (rhs_code == TRUNC_MOD_EXPR
+         && fold_stmt (gsi, follow_single_use_edges))
+       return true;
+      return false;
     }
+
+  if (TYPE_UNSIGNED (TREE_TYPE (op0)))
+    val = integer_one_node;
   else
     {
       bool sop = false;
@@ -8806,44 +9036,80 @@ simplify_div_or_mod_using_ranges (gimple stmt)
   return false;
 }
 
+/* Simplify a min or max if the ranges of the two operands are
+   disjoint.   Return true if we do simplify.  */
+
+static bool
+simplify_min_or_max_using_ranges (gimple *stmt)
+{
+  tree op0 = gimple_assign_rhs1 (stmt);
+  tree op1 = gimple_assign_rhs2 (stmt);
+  bool sop = false;
+  tree val;
+
+  val = (vrp_evaluate_conditional_warnv_with_ops_using_ranges
+        (LE_EXPR, op0, op1, &sop));
+  if (!val)
+    {
+      sop = false;
+      val = (vrp_evaluate_conditional_warnv_with_ops_using_ranges
+            (LT_EXPR, op0, op1, &sop));
+    }
+
+  if (val)
+    {
+      if (sop && issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_MISC))
+       {
+         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 %<min/max (X,Y)%> to %<X%> or %<Y%>");
+       }
+
+      /* VAL == TRUE -> OP0 < or <= op1
+        VAL == FALSE -> OP0 > or >= op1.  */
+      tree res = ((gimple_assign_rhs_code (stmt) == MAX_EXPR)
+                 == integer_zerop (val)) ? op0 : op1;
+      gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+      gimple_assign_set_rhs_from_tree (&gsi, res);
+      update_stmt (stmt);
+      return true;
+    }
+
+  return false;
+}
+
 /* If the operand to an ABS_EXPR is >= 0, then eliminate the
    ABS_EXPR.  If the operand is <= 0, then simplify the
    ABS_EXPR into a NEGATE_EXPR.  */
 
 static bool
-simplify_abs_using_ranges (gimple stmt)
+simplify_abs_using_ranges (gimple *stmt)
 {
-  tree val = NULL;
   tree op = gimple_assign_rhs1 (stmt);
-  tree type = TREE_TYPE (op);
-  value_range_t *vr = get_value_range (op);
+  value_range *vr = get_value_range (op);
 
-  if (TYPE_UNSIGNED (type))
-    {
-      val = integer_zero_node;
-    }
-  else if (vr)
+  if (vr)
     {
+      tree val = NULL;
       bool sop = false;
 
       val = compare_range_with_value (LE_EXPR, vr, integer_zero_node, &sop);
       if (!val)
        {
+         /* The range is neither <= 0 nor > 0.  Now see if it is
+            either < 0 or >= 0.  */
          sop = false;
-         val = compare_range_with_value (GE_EXPR, vr, integer_zero_node,
+         val = compare_range_with_value (LT_EXPR, vr, integer_zero_node,
                                          &sop);
-
-         if (val)
-           {
-             if (integer_zerop (val))
-               val = integer_one_node;
-             else if (integer_onep (val))
-               val = integer_zero_node;
-           }
        }
 
-      if (val
-         && (integer_onep (val) || integer_zerop (val)))
+      if (val)
        {
          if (sop && issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_MISC))
            {
@@ -8859,10 +9125,10 @@ simplify_abs_using_ranges (gimple stmt)
            }
 
          gimple_assign_set_rhs1 (stmt, op);
-         if (integer_onep (val))
-           gimple_assign_set_rhs_code (stmt, NEGATE_EXPR);
-         else
+         if (integer_zerop (val))
            gimple_assign_set_rhs_code (stmt, SSA_NAME);
+         else
+           gimple_assign_set_rhs_code (stmt, NEGATE_EXPR);
          update_stmt (stmt);
          return true;
        }
@@ -8878,13 +9144,13 @@ simplify_abs_using_ranges (gimple stmt)
    operation is redundant.  */
 
 static bool
-simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
+simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
 {
   tree op0 = gimple_assign_rhs1 (stmt);
   tree op1 = gimple_assign_rhs2 (stmt);
   tree op = NULL_TREE;
-  value_range_t vr0 = VR_INITIALIZER;
-  value_range_t vr1 = VR_INITIALIZER;
+  value_range vr0 = VR_INITIALIZER;
+  value_range vr1 = VR_INITIALIZER;
   wide_int may_be_nonzero0, may_be_nonzero1;
   wide_int must_be_nonzero0, must_be_nonzero1;
   wide_int mask;
@@ -8947,7 +9213,7 @@ simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
   if (op == NULL_TREE)
     return false;
 
-  gimple_assign_set_rhs_with_ops (gsi, TREE_CODE (op), op, NULL);
+  gimple_assign_set_rhs_with_ops (gsi, TREE_CODE (op), op);
   update_stmt (gsi_stmt (*gsi));
   return true;
 }
@@ -8956,11 +9222,15 @@ simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
    a known value range VR.
 
    If there is one and only one value which will satisfy the
-   conditional, then return that value.  Else return NULL.  */
+   conditional, then return that value.  Else return NULL.
+
+   If signed overflow must be undefined for the value to satisfy
+   the conditional, then set *STRICT_OVERFLOW_P to true.  */
 
 static tree
 test_for_singularity (enum tree_code cond_code, tree op0,
-                     tree op1, value_range_t *vr)
+                     tree op1, value_range *vr,
+                     bool *strict_overflow_p)
 {
   tree min = NULL;
   tree max = NULL;
@@ -9011,7 +9281,16 @@ test_for_singularity (enum tree_code cond_code, tree op0,
         then there is only one value which can satisfy the condition,
         return that value.  */
       if (operand_equal_p (min, max, 0) && is_gimple_min_invariant (min))
-       return min;
+       {
+         if ((cond_code == LE_EXPR || cond_code == LT_EXPR)
+             && is_overflow_infinity (vr->max))
+           *strict_overflow_p = true;
+         if ((cond_code == GE_EXPR || cond_code == GT_EXPR)
+             && is_overflow_infinity (vr->min))
+           *strict_overflow_p = true;
+
+         return min;
+       }
     }
   return NULL;
 }
@@ -9020,7 +9299,7 @@ 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 dest_precision, signop dest_sgn)
+range_fits_type_p (value_range *vr, unsigned dest_precision, signop dest_sgn)
 {
   tree src_type;
   unsigned src_precision;
@@ -9073,7 +9352,7 @@ range_fits_type_p (value_range_t *vr, unsigned dest_precision, signop dest_sgn)
    the original conditional.  */
 
 static bool
-simplify_cond_using_ranges (gimple stmt)
+simplify_cond_using_ranges (gcond *stmt)
 {
   tree op0 = gimple_cond_lhs (stmt);
   tree op1 = gimple_cond_rhs (stmt);
@@ -9085,15 +9364,18 @@ simplify_cond_using_ranges (gimple stmt)
       && INTEGRAL_TYPE_P (TREE_TYPE (op0))
       && is_gimple_min_invariant (op1))
     {
-      value_range_t *vr = get_value_range (op0);
+      value_range *vr = get_value_range (op0);
 
       /* If we have range information for OP0, then we might be
         able to simplify this conditional. */
       if (vr->type == VR_RANGE)
        {
-         tree new_tree = test_for_singularity (cond_code, op0, op1, vr);
+         enum warn_strict_overflow_code wc = WARN_STRICT_OVERFLOW_COMPARISON;
+         bool sop = false;
+         tree new_tree = test_for_singularity (cond_code, op0, op1, vr, &sop);
 
-         if (new_tree)
+         if (new_tree
+             && (!sop || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0))))
            {
              if (dump_file)
                {
@@ -9114,16 +9396,30 @@ simplify_cond_using_ranges (gimple stmt)
                  fprintf (dump_file, "\n");
                }
 
+             if (sop && issue_strict_overflow_warning (wc))
+               {
+                 location_t location = input_location;
+                 if (gimple_has_location (stmt))
+                   location = gimple_location (stmt);
+
+                 warning_at (location, OPT_Wstrict_overflow,
+                             "assuming signed overflow does not occur when "
+                             "simplifying conditional");
+               }
+
              return true;
            }
 
          /* Try again after inverting the condition.  We only deal
             with integral types here, so no need to worry about
             issues with inverting FP comparisons.  */
-         cond_code = invert_tree_comparison (cond_code, false);
-         new_tree = test_for_singularity (cond_code, op0, op1, vr);
+         sop = false;
+         new_tree = test_for_singularity
+                      (invert_tree_comparison (cond_code, false),
+                       op0, op1, vr, &sop);
 
-         if (new_tree)
+         if (new_tree
+             && (!sop || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0))))
            {
              if (dump_file)
                {
@@ -9144,6 +9440,17 @@ simplify_cond_using_ranges (gimple stmt)
                  fprintf (dump_file, "\n");
                }
 
+             if (sop && issue_strict_overflow_warning (wc))
+               {
+                 location_t location = input_location;
+                 if (gimple_has_location (stmt))
+                   location = gimple_location (stmt);
+
+                 warning_at (location, OPT_Wstrict_overflow,
+                             "assuming signed overflow does not occur when "
+                             "simplifying conditional");
+               }
+
              return true;
            }
        }
@@ -9160,7 +9467,7 @@ simplify_cond_using_ranges (gimple stmt)
   if (TREE_CODE (op0) == SSA_NAME
       && TREE_CODE (op1) == INTEGER_CST)
     {
-      gimple def_stmt = SSA_NAME_DEF_STMT (op0);
+      gimple *def_stmt = SSA_NAME_DEF_STMT (op0);
       tree innerop;
 
       if (!is_gimple_assign (def_stmt)
@@ -9170,9 +9477,11 @@ simplify_cond_using_ranges (gimple stmt)
       innerop = gimple_assign_rhs1 (def_stmt);
 
       if (TREE_CODE (innerop) == SSA_NAME
-         && !POINTER_TYPE_P (TREE_TYPE (innerop)))
+         && !POINTER_TYPE_P (TREE_TYPE (innerop))
+         && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (innerop)
+         && desired_pro_or_demotion_p (TREE_TYPE (innerop), TREE_TYPE (op0)))
        {
-         value_range_t *vr = get_value_range (innerop);
+         value_range *vr = get_value_range (innerop);
 
          if (range_int_cst_p (vr)
              && range_fits_type_p (vr,
@@ -9201,8 +9510,8 @@ simplify_cond_using_ranges (gimple stmt)
                  else
                    location = gimple_location (stmt);
                  warning_at (location, OPT_Wstrict_overflow,
-                     "assuming signed overflow does not occur when "
-                     "simplifying conditional");
+                             "assuming signed overflow does not occur when "
+                             "simplifying conditional");
                }
 
              tree newconst = fold_convert (TREE_TYPE (innerop), op1);
@@ -9220,10 +9529,10 @@ simplify_cond_using_ranges (gimple stmt)
    argument.  */
 
 static bool
-simplify_switch_using_ranges (gimple stmt)
+simplify_switch_using_ranges (gswitch *stmt)
 {
   tree op = gimple_switch_index (stmt);
-  value_range_t *vr;
+  value_range *vr;
   bool take_default;
   edge e;
   edge_iterator ei;
@@ -9318,11 +9627,11 @@ simplify_switch_using_ranges (gimple stmt)
 /* Simplify an integral conversion from an SSA name in STMT.  */
 
 static bool
-simplify_conversion_using_ranges (gimple stmt)
+simplify_conversion_using_ranges (gimple *stmt)
 {
   tree innerop, middleop, finaltype;
-  gimple def_stmt;
-  value_range_t *innervr;
+  gimple *def_stmt;
+  value_range *innervr;
   signop inner_sgn, middle_sgn, final_sgn;
   unsigned inner_prec, middle_prec, final_prec;
   widest_int innermin, innermed, innermax, middlemin, middlemed, middlemax;
@@ -9397,14 +9706,15 @@ simplify_conversion_using_ranges (gimple stmt)
 /* Simplify a conversion from integral SSA name to float in STMT.  */
 
 static bool
-simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
+simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
+                                       gimple *stmt)
 {
   tree rhs1 = gimple_assign_rhs1 (stmt);
-  value_range_t *vr = get_value_range (rhs1);
-  enum machine_mode fltmode = TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt)));
-  enum machine_mode mode;
+  value_range *vr = get_value_range (rhs1);
+  machine_mode fltmode = TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt)));
+  machine_mode mode;
   tree tem;
-  gimple conv;
+  gassign *conv;
 
   /* We can only handle constant ranges.  */
   if (vr->type != VR_RANGE
@@ -9450,8 +9760,8 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
   /* It works, insert a truncation or sign-change before the
      float conversion.  */
   tem = make_ssa_name (build_nonstandard_integer_type
-                         (GET_MODE_PRECISION (mode), 0), NULL);
-  conv = gimple_build_assign_with_ops (NOP_EXPR, tem, rhs1, NULL_TREE);
+                         (GET_MODE_PRECISION (mode), 0));
+  conv = gimple_build_assign (tem, NOP_EXPR, rhs1);
   gsi_insert_before (gsi, conv, GSI_SAME_STMT);
   gimple_assign_set_rhs1 (stmt, tem);
   update_stmt (stmt);
@@ -9462,88 +9772,96 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
 /* Simplify an internal fn call using ranges if possible.  */
 
 static bool
-simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
+simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
 {
   enum tree_code subcode;
+  bool is_ubsan = false;
+  bool ovf = false;
   switch (gimple_call_internal_fn (stmt))
     {
     case IFN_UBSAN_CHECK_ADD:
       subcode = PLUS_EXPR;
+      is_ubsan = true;
       break;
     case IFN_UBSAN_CHECK_SUB:
       subcode = MINUS_EXPR;
+      is_ubsan = true;
       break;
     case IFN_UBSAN_CHECK_MUL:
+      subcode = MULT_EXPR;
+      is_ubsan = true;
+      break;
+    case IFN_ADD_OVERFLOW:
+      subcode = PLUS_EXPR;
+      break;
+    case IFN_SUB_OVERFLOW:
+      subcode = MINUS_EXPR;
+      break;
+    case IFN_MUL_OVERFLOW:
       subcode = MULT_EXPR;
       break;
     default:
       return false;
     }
 
-  value_range_t vr0 = VR_INITIALIZER;
-  value_range_t vr1 = VR_INITIALIZER;
   tree op0 = gimple_call_arg (stmt, 0);
   tree op1 = gimple_call_arg (stmt, 1);
-
-  if (TREE_CODE (op0) == SSA_NAME)
-    vr0 = *get_value_range (op0);
-  else if (TREE_CODE (op0) == INTEGER_CST)
-    set_value_range_to_value (&vr0, op0, NULL);
+  tree type;
+  if (is_ubsan)
+    type = TREE_TYPE (op0);
+  else if (gimple_call_lhs (stmt) == NULL_TREE)
+    return false;
   else
-    set_value_range_to_varying (&vr0);
+    type = TREE_TYPE (TREE_TYPE (gimple_call_lhs (stmt)));
+  if (!check_for_binary_op_overflow (subcode, type, op0, op1, &ovf)
+      || (is_ubsan && ovf))
+    return false;
 
-  if (TREE_CODE (op1) == SSA_NAME)
-    vr1 = *get_value_range (op1);
-  else if (TREE_CODE (op1) == INTEGER_CST)
-    set_value_range_to_value (&vr1, op1, NULL);
+  gimple *g;
+  location_t loc = gimple_location (stmt);
+  if (is_ubsan)
+    g = gimple_build_assign (gimple_call_lhs (stmt), subcode, op0, op1);
   else
-    set_value_range_to_varying (&vr1);
-
-  if (!range_int_cst_p (&vr0))
     {
-      /* If one range is VR_ANTI_RANGE, VR_VARYING etc.,
-        optimize at least x = y + 0; x = y - 0; x = y * 0;
-        and x = y * 1; which never overflow.  */
-      if (!range_int_cst_p (&vr1))
-       return false;
-      if (tree_int_cst_sgn (vr1.min) == -1)
-       return false;
-      if (compare_tree_int (vr1.max, subcode == MULT_EXPR) == 1)
-       return false;
-    }
-  else if (!range_int_cst_p (&vr1))
-    {
-      /* If one range is VR_ANTI_RANGE, VR_VARYING etc.,
-        optimize at least x = 0 + y; x = 0 * y; and x = 1 * y;
-        which never overflow.  */
-      if (subcode == MINUS_EXPR)
-       return false;
-      if (!range_int_cst_p (&vr0))
-       return false;
-      if (tree_int_cst_sgn (vr0.min) == -1)
-       return false;
-      if (compare_tree_int (vr0.max, subcode == MULT_EXPR) == 1)
-       return false;
-    }
-  else
-    {
-      tree r1 = int_const_binop (subcode, vr0.min, vr1.min);
-      tree r2 = int_const_binop (subcode, vr0.max, vr1.max);
-      if (r1 == NULL_TREE || TREE_OVERFLOW (r1)
-         || r2 == NULL_TREE || TREE_OVERFLOW (r2))
-       return false;
-      if (subcode == MULT_EXPR)
+      int prec = TYPE_PRECISION (type);
+      tree utype = type;
+      if (ovf
+         || !useless_type_conversion_p (type, TREE_TYPE (op0))
+         || !useless_type_conversion_p (type, TREE_TYPE (op1)))
+       utype = build_nonstandard_integer_type (prec, 1);
+      if (TREE_CODE (op0) == INTEGER_CST)
+       op0 = fold_convert (utype, op0);
+      else if (!useless_type_conversion_p (utype, TREE_TYPE (op0)))
+       {
+         g = gimple_build_assign (make_ssa_name (utype), NOP_EXPR, op0);
+         gimple_set_location (g, loc);
+         gsi_insert_before (gsi, g, GSI_SAME_STMT);
+         op0 = gimple_assign_lhs (g);
+       }
+      if (TREE_CODE (op1) == INTEGER_CST)
+       op1 = fold_convert (utype, op1);
+      else if (!useless_type_conversion_p (utype, TREE_TYPE (op1)))
        {
-         tree r3 = int_const_binop (subcode, vr0.min, vr1.max);
-         tree r4 = int_const_binop (subcode, vr0.max, vr1.min);
-         if (r3 == NULL_TREE || TREE_OVERFLOW (r3)
-             || r4 == NULL_TREE || TREE_OVERFLOW (r4))
-           return false;
+         g = gimple_build_assign (make_ssa_name (utype), NOP_EXPR, op1);
+         gimple_set_location (g, loc);
+         gsi_insert_before (gsi, g, GSI_SAME_STMT);
+         op1 = gimple_assign_lhs (g);
        }
+      g = gimple_build_assign (make_ssa_name (utype), subcode, op0, op1);
+      gimple_set_location (g, loc);
+      gsi_insert_before (gsi, g, GSI_SAME_STMT);
+      if (utype != type)
+       {
+         g = gimple_build_assign (make_ssa_name (type), NOP_EXPR,
+                                  gimple_assign_lhs (g));
+         gimple_set_location (g, loc);
+         gsi_insert_before (gsi, g, GSI_SAME_STMT);
+       }
+      g = gimple_build_assign (gimple_call_lhs (stmt), COMPLEX_EXPR,
+                              gimple_assign_lhs (g),
+                              build_int_cst (type, ovf));
     }
-
-  gimple g = gimple_build_assign_with_ops (subcode, gimple_call_lhs (stmt),
-                                          op0, op1);
+  gimple_set_location (g, loc);
   gsi_replace (gsi, g, false);
   return true;
 }
@@ -9553,7 +9871,7 @@ simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
 static bool
 simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
 {
-  gimple stmt = gsi_stmt (*gsi);
+  gimple *stmt = gsi_stmt (*gsi);
   if (is_gimple_assign (stmt))
     {
       enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
@@ -9572,12 +9890,15 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
 
       /* Transform TRUNC_DIV_EXPR and TRUNC_MOD_EXPR into RSHIFT_EXPR
         and BIT_AND_EXPR respectively if the first operand is greater
-        than zero and the second operand is an exact power of two.  */
+        than zero and the second operand is an exact power of two.
+        Also optimize TRUNC_MOD_EXPR away if the second operand is
+        constant and the first operand already has the right value
+        range.  */
        case TRUNC_DIV_EXPR:
        case TRUNC_MOD_EXPR:
-         if (INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
-             && integer_pow2p (gimple_assign_rhs2 (stmt)))
-           return simplify_div_or_mod_using_ranges (stmt);
+         if (TREE_CODE (rhs1) == SSA_NAME
+             && INTEGRAL_TYPE_P (TREE_TYPE (rhs1)))
+           return simplify_div_or_mod_using_ranges (gsi, stmt);
          break;
 
       /* Transform ABS (X) into X or -X as appropriate.  */
@@ -9608,14 +9929,19 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
            return simplify_float_conversion_using_ranges (gsi, stmt);
          break;
 
+       case MIN_EXPR:
+       case MAX_EXPR:
+         return simplify_min_or_max_using_ranges (stmt);
+         break;
+
        default:
          break;
        }
     }
   else if (gimple_code (stmt) == GIMPLE_COND)
-    return simplify_cond_using_ranges (stmt);
+    return simplify_cond_using_ranges (as_a <gcond *> (stmt));
   else if (gimple_code (stmt) == GIMPLE_SWITCH)
-    return simplify_switch_using_ranges (stmt);
+    return simplify_switch_using_ranges (as_a <gswitch *> (stmt));
   else if (is_gimple_call (stmt)
           && gimple_call_internal_p (stmt))
     return simplify_internal_call_using_ranges (gsi, stmt);
@@ -9632,7 +9958,7 @@ fold_predicate_in (gimple_stmt_iterator *si)
 {
   bool assignment_p = false;
   tree val;
-  gimple stmt = gsi_stmt (*si);
+  gimple *stmt = gsi_stmt (*si);
 
   if (is_gimple_assign (stmt)
       && TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) == tcc_comparison)
@@ -9643,10 +9969,10 @@ fold_predicate_in (gimple_stmt_iterator *si)
                                      gimple_assign_rhs2 (stmt),
                                      stmt);
     }
-  else if (gimple_code (stmt) == GIMPLE_COND)
-    val = vrp_evaluate_conditional (gimple_cond_code (stmt),
-                                   gimple_cond_lhs (stmt),
-                                   gimple_cond_rhs (stmt),
+  else if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
+    val = vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
+                                   gimple_cond_lhs (cond_stmt),
+                                   gimple_cond_rhs (cond_stmt),
                                    stmt);
   else
     return false;
@@ -9670,10 +9996,11 @@ fold_predicate_in (gimple_stmt_iterator *si)
       else
        {
          gcc_assert (gimple_code (stmt) == GIMPLE_COND);
+         gcond *cond_stmt = as_a <gcond *> (stmt);
          if (integer_zerop (val))
-           gimple_cond_make_false (stmt);
+           gimple_cond_make_false (cond_stmt);
          else if (integer_onep (val))
-           gimple_cond_make_true (stmt);
+           gimple_cond_make_true (cond_stmt);
          else
            gcc_unreachable ();
        }
@@ -9695,12 +10022,8 @@ vrp_fold_stmt (gimple_stmt_iterator *si)
   return simplify_stmt_using_ranges (si);
 }
 
-/* Stack of dest,src equivalency pairs that need to be restored after
-   each attempt to thread a block's incoming edge to an outgoing edge.
-
-   A NULL entry is used to mark the end of pairs which need to be
-   restored.  */
-static vec<tree> equiv_stack;
+/* Unwindable const/copy equivalences.  */
+const_and_copies *equiv_stack;
 
 /* A trivial wrapper so that we can present the generic jump threading
    code with a simple API for simplifying statements.  STMT is the
@@ -9708,23 +10031,25 @@ static vec<tree> equiv_stack;
    for any overflow warnings.  */
 
 static tree
-simplify_stmt_for_jump_threading (gimple stmt, gimple within_stmt)
+simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
+    class avail_exprs_stack *avail_exprs_stack ATTRIBUTE_UNUSED)
 {
-  if (gimple_code (stmt) == GIMPLE_COND)
-    return vrp_evaluate_conditional (gimple_cond_code (stmt),
-                                    gimple_cond_lhs (stmt),
-                                    gimple_cond_rhs (stmt), within_stmt);
+  if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
+    return vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
+                                    gimple_cond_lhs (cond_stmt),
+                                    gimple_cond_rhs (cond_stmt),
+                                    within_stmt);
 
-  if (gimple_code (stmt) == GIMPLE_ASSIGN)
+  if (gassign *assign_stmt = dyn_cast <gassign *> (stmt))
     {
-      value_range_t new_vr = VR_INITIALIZER;
-      tree lhs = gimple_assign_lhs (stmt);
+      value_range new_vr = VR_INITIALIZER;
+      tree lhs = gimple_assign_lhs (assign_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);
+         extract_range_from_assignment (&new_vr, assign_stmt);
          if (range_int_cst_singleton_p (&new_vr))
            return new_vr.min;
        }
@@ -9757,7 +10082,7 @@ static void
 identify_jump_threads (void)
 {
   basic_block bb;
-  gimple dummy;
+  gcond *dummy;
   int i;
   edge e;
 
@@ -9774,13 +10099,13 @@ identify_jump_threads (void)
   mark_dfs_back_edges ();
 
   /* Do not thread across edges we are about to remove.  Just marking
-     them as EDGE_DFS_BACK will do.  */
+     them as EDGE_IGNORE will do.  */
   FOR_EACH_VEC_ELT (to_remove_edges, i, e)
-    e->flags |= EDGE_DFS_BACK;
+    e->flags |= EDGE_IGNORE;
 
   /* Allocate our unwinder stack to unwind any temporary equivalences
      that might be recorded.  */
-  equiv_stack.create (20);
+  equiv_stack = new const_and_copies ();
 
   /* To avoid lots of silly node creation, we create a single
      conditional and just modify it in-place when attempting to
@@ -9797,23 +10122,27 @@ identify_jump_threads (void)
      point in compilation.  */
   FOR_EACH_BB_FN (bb, cfun)
     {
-      gimple last;
+      gimple *last;
 
       /* If the generic jump threading code does not find this block
         interesting, then there is nothing to do.  */
       if (! potentially_threadable_block (bb))
        continue;
 
-      /* We only care about blocks ending in a COND_EXPR.  While there
-        may be some value in handling SWITCH_EXPR here, I doubt it's
-        terribly important.  */
-      last = gsi_stmt (gsi_last_bb (bb));
+      last = last_stmt (bb);
 
       /* 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
+        check it explicitly. 
+
+        We also handle the case where there are no statements in the
+        block.  This come up with forwarder blocks that are not
+        optimized away because they lead to a loop header.  But we do
+        want to thread through them as we can sometimes thread to the
+        loop exit which is obviously profitable.  */
+      if (!last
+         || 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)))
@@ -9829,17 +10158,21 @@ identify_jump_threads (void)
             it to a specific successor.  */
          FOR_EACH_EDGE (e, ei, bb->preds)
            {
-             /* Do not thread across back edges or abnormal edges
-                in the CFG.  */
-             if (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX))
+             /* Do not thread across edges marked to ignoreor abnormal
+                edges in the CFG.  */
+             if (e->flags & (EDGE_IGNORE | EDGE_COMPLEX))
                continue;
 
-             thread_across_edge (dummy, e, true, &equiv_stack,
+             thread_across_edge (dummy, e, true, equiv_stack, NULL,
                                  simplify_stmt_for_jump_threading);
            }
        }
     }
 
+  /* Clear EDGE_IGNORE.  */
+  FOR_EACH_VEC_ELT (to_remove_edges, i, e)
+    e->flags &= ~EDGE_IGNORE;
+
   /* We do not actually update the CFG or SSA graphs at this point as
      ASSERT_EXPRs are still in the IL and cfg cleanup code does not yet
      handle ASSERT_EXPRs gracefully.  */
@@ -9855,14 +10188,14 @@ static void
 finalize_jump_threads (void)
 {
   thread_through_all_blocks (false);
-  equiv_stack.release ();
+  delete equiv_stack;
 }
 
 
 /* Traverse all the blocks folding conditionals with known ranges.  */
 
 static void
-vrp_finalize (void)
+vrp_finalize (bool warn_array_bounds_p)
 {
   size_t i;
 
@@ -9875,16 +10208,6 @@ vrp_finalize (void)
       fprintf (dump_file, "\n");
     }
 
-  substitute_and_fold (op_with_constant_singleton_value_range,
-                      vrp_fold_stmt, false);
-
-  if (warn_array_bounds)
-    check_all_array_refs ();
-
-  /* We must identify jump threading opportunities before we release
-     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])
@@ -9897,14 +10220,24 @@ vrp_finalize (void)
          || (vr_value[i]->type == VR_UNDEFINED))
        continue;
 
-       if ((TREE_CODE (vr_value[i]->min) == INTEGER_CST)
-           && (TREE_CODE (vr_value[i]->max) == INTEGER_CST)
-           && (vr_value[i]->type == VR_RANGE
-               || vr_value[i]->type == VR_ANTI_RANGE))
-         set_range_info (name, vr_value[i]->type, vr_value[i]->min,
-                         vr_value[i]->max);
+      if ((TREE_CODE (vr_value[i]->min) == INTEGER_CST)
+         && (TREE_CODE (vr_value[i]->max) == INTEGER_CST)
+         && (vr_value[i]->type == VR_RANGE
+             || vr_value[i]->type == VR_ANTI_RANGE))
+       set_range_info (name, vr_value[i]->type, vr_value[i]->min,
+                       vr_value[i]->max);
       }
 
+  substitute_and_fold (op_with_constant_singleton_value_range,
+                      vrp_fold_stmt, false);
+
+  if (warn_array_bounds && warn_array_bounds_p)
+    check_all_array_refs ();
+
+  /* We must identify jump threading opportunities before we release
+     the datastructures built by VRP.  */
+  identify_jump_threads ();
+
   /* Free allocated memory.  */
   for (i = 0; i < num_vr_values; i++)
     if (vr_value[i])
@@ -9968,7 +10301,7 @@ vrp_finalize (void)
    probabilities to aid branch prediction.  */
 
 static unsigned int
-execute_vrp (void)
+execute_vrp (bool warn_array_bounds_p)
 {
   int i;
   edge e;
@@ -9992,9 +10325,9 @@ execute_vrp (void)
 
   vrp_initialize ();
   ssa_propagate (vrp_visit_stmt, vrp_visit_phi_node);
-  vrp_finalize ();
+  vrp_finalize (warn_array_bounds_p);
 
-  free_numbers_of_iterations_estimates ();
+  free_numbers_of_iterations_estimates (cfun);
 
   /* ASSERT_EXPRs must be removed before finalizing jump threads
      as finalizing jump threads calls the CFG cleanup code which
@@ -10065,14 +10398,22 @@ class pass_vrp : public gimple_opt_pass
 {
 public:
   pass_vrp (gcc::context *ctxt)
-    : gimple_opt_pass (pass_data_vrp, ctxt)
+    : gimple_opt_pass (pass_data_vrp, ctxt), warn_array_bounds_p (false)
   {}
 
   /* opt_pass methods: */
   opt_pass * clone () { return new pass_vrp (m_ctxt); }
+  void set_pass_param (unsigned int n, bool param)
+    {
+      gcc_assert (n == 0);
+      warn_array_bounds_p = param;
+    }
   virtual bool gate (function *) { return flag_tree_vrp != 0; }
-  virtual unsigned int execute (function *) { return execute_vrp (); }
+  virtual unsigned int execute (function *)
+    { return execute_vrp (warn_array_bounds_p); }
 
+ private:
+  bool warn_array_bounds_p;
 }; // class pass_vrp
 
 } // anon namespace