OSDN Git Service

2008-10-13 Matthias Klose <doko@ubuntu.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree-vrp.c
index fe39a24..949b73c 100644 (file)
@@ -1,5 +1,5 @@
 /* Support routines for Value Range Propagation (VRP).
-   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>.
 
 This file is part of GCC.
@@ -38,16 +38,27 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-propagate.h"
 #include "tree-chrec.h"
 
-/* Set of SSA names found during the dominator traversal of a
-   sub-graph in find_assert_locations.  */
-static sbitmap found_in_subgraph;
+
+/* Set of SSA names found live during the RPO traversal of the function
+   for still active basic-blocks.  */
+static sbitmap *live;
+
+/* Return true if the SSA name NAME is live on the edge E.  */
+
+static bool
+live_on_edge (edge e, tree name)
+{
+  return (live[e->dest->index]
+         && TEST_BIT (live[e->dest->index], SSA_NAME_VERSION (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 tree vrp_evaluate_conditional_warnv_with_ops (enum tree_code,
-                                                    tree, tree, bool, bool *);
+                                                    tree, tree, bool, bool *,
+                                                    bool *);
 
 /* Location information for ASSERT_EXPRs.  Each instance of this
    structure describes an ASSERT_EXPR for an SSA name.  Since a single
@@ -64,7 +75,7 @@ struct assert_locus_d
   edge e;
 
   /* Pointer to the statement that generated this assertion.  */
-  block_stmt_iterator si;
+  gimple_stmt_iterator si;
 
   /* Predicate code for the ASSERT_EXPR.  Must be COMPARISON_CLASS_P.  */
   enum tree_code comp_code;
@@ -90,10 +101,6 @@ static bitmap need_assert_for;
    ASSERT_EXPRs for SSA name N_I should be inserted.  */
 static assert_locus_t *asserts_for;
 
-/* Set of blocks visited in find_assert_locations.  Used to avoid
-   visiting the same block more than once.  */
-static sbitmap blocks_visited;
-
 /* Value range array.  After propagation, VR_VALUE[I] holds the range
    of values that SSA name N_I may take.  */
 static value_range_t **vr_value;
@@ -104,7 +111,7 @@ static value_range_t **vr_value;
 static int *vr_phi_edge_counts;
 
 typedef struct {
-  tree stmt;
+  gimple stmt;
   tree vec;
 } switch_update;
 
@@ -276,6 +283,18 @@ is_overflow_infinity (const_tree val)
          && (vrp_val_is_min (val) || vrp_val_is_max (val)));
 }
 
+/* Return whether STMT has a constant rhs that is_overflow_infinity. */
+
+static inline bool
+stmt_overflow_infinity (gimple stmt)
+{
+  if (is_gimple_assign (stmt)
+      && get_gimple_rhs_class (gimple_assign_rhs_code (stmt)) ==
+      GIMPLE_SINGLE_RHS)
+    return is_overflow_infinity (gimple_assign_rhs1 (stmt));
+  return false;
+}
+
 /* If VAL is now an overflow infinity, return VAL.  Otherwise, return
    the same value with TREE_OVERFLOW clear.  This can be used to avoid
    confusing a regular value with an overflow value.  */
@@ -777,21 +796,143 @@ vrp_expr_computes_nonnegative (tree expr, bool *strict_overflow_p)
              && ssa_name_nonnegative_p (expr)));
 }
 
+/* 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_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)
+{
+  enum tree_code code = gimple_assign_rhs_code (stmt);
+  switch (get_gimple_rhs_class (code))
+    {
+    case GIMPLE_UNARY_RHS:
+      return tree_unary_nonzero_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_nonzero_warnv_p (gimple_assign_rhs_code (stmt),
+                                         gimple_expr_type (stmt),
+                                         gimple_assign_rhs1 (stmt),
+                                         gimple_assign_rhs2 (stmt),
+                                         strict_overflow_p);
+    case GIMPLE_SINGLE_RHS:
+      return tree_single_nonzero_warnv_p (gimple_assign_rhs1 (stmt),
+                                         strict_overflow_p);
+    case GIMPLE_INVALID_RHS:
+      gcc_unreachable ();
+    default:
+      gcc_unreachable ();
+    }
+}
+
+/* Return true if STMT is know to to compute a non-zero value.
+   If the return value is based on the assumption that signed overflow is
+   undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change
+   *STRICT_OVERFLOW_P.*/
+
+static bool
+gimple_stmt_nonzero_warnv_p (gimple stmt, bool *strict_overflow_p)
+{
+  switch (gimple_code (stmt))
+    {
+    case GIMPLE_ASSIGN:
+      return gimple_assign_nonzero_warnv_p (stmt, strict_overflow_p);
+    case GIMPLE_CALL:
+      return gimple_alloca_call_p (stmt);
+    default:
+      gcc_unreachable ();
+    }
+}
+
 /* Like tree_expr_nonzero_warnv_p, but this function uses value ranges
    obtained so far.  */
 
 static bool
-vrp_expr_computes_nonzero (tree expr, bool *strict_overflow_p)
+vrp_stmt_computes_nonzero (gimple stmt, bool *strict_overflow_p)
 {
-  if (tree_expr_nonzero_warnv_p (expr, strict_overflow_p)
-      || (TREE_CODE (expr) == SSA_NAME
-         && ssa_name_nonzero_p (expr)))
+  if (gimple_stmt_nonzero_warnv_p (stmt, strict_overflow_p))
     return true;
 
   /* If we have an expression of the form &X->a, then the expression
      is nonnull if X is nonnull.  */
-  if (TREE_CODE (expr) == ADDR_EXPR)
+  if (is_gimple_assign (stmt)
+      && gimple_assign_rhs_code (stmt) == ADDR_EXPR)
     {
+      tree expr = gimple_assign_rhs1 (stmt);
       tree base = get_base_address (TREE_OPERAND (expr, 0));
 
       if (base != NULL_TREE
@@ -1213,6 +1354,30 @@ ssa_name_nonzero_p (const_tree t)
   return false;
 }
 
+/* If OP has a value range with a single constant value return that,
+   otherwise return NULL_TREE.  This returns OP itself if OP is a
+   constant.  */
+
+static tree
+op_with_constant_singleton_value_range (tree op)
+{
+  value_range_t *vr;
+
+  if (is_gimple_min_invariant (op))
+    return op;
+
+  if (TREE_CODE (op) != SSA_NAME)
+    return NULL_TREE;
+
+  vr = get_value_range (op);
+  if (vr->type == VR_RANGE
+      && operand_equal_p (vr->min, vr->max, 0)
+      && is_gimple_min_invariant (vr->min))
+    return vr->min;
+
+  return NULL_TREE;
+}
+
 
 /* Extract value range information from an ASSERT_EXPR EXPR and store
    it in *VR_P.  */
@@ -1585,7 +1750,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
                3a. If the high limit of the VR_ANTI_RANGE resides
                    within the VR_RANGE, then the result is a new
                    VR_RANGE starting at the high limit of the
-                   the VR_ANTI_RANGE + 1 and extending to the
+                   VR_ANTI_RANGE + 1 and extending to the
                    high limit of the original VR_RANGE.
 
                3b. If the low limit of the VR_ANTI_RANGE resides
@@ -1890,9 +2055,26 @@ extract_range_from_binary_expr (value_range_t *vr,
       && code != MIN_EXPR
       && code != MAX_EXPR
       && code != BIT_AND_EXPR
+      && code != BIT_IOR_EXPR
       && code != TRUTH_AND_EXPR
       && code != TRUTH_OR_EXPR)
     {
+      /* We can still do constant propagation here.  */
+      tree const_op0 = op_with_constant_singleton_value_range (op0);
+      tree const_op1 = op_with_constant_singleton_value_range (op1);
+      if (const_op0 || const_op1)
+       {
+         tree tem = fold_binary (code, expr_type,
+                                 const_op0 ? const_op0 : op0,
+                                 const_op1 ? const_op1 : op1);
+         if (tem
+             && is_gimple_min_invariant (tem)
+             && !is_overflow_infinity (tem))
+           {
+             set_value_range (vr, VR_RANGE, tem, tem, NULL);
+             return;
+           }
+       }
       set_value_range_to_varying (vr);
       return;
     }
@@ -2234,6 +2416,45 @@ extract_range_from_binary_expr (value_range_t *vr,
          return;
        }
     }
+  else if (code == BIT_IOR_EXPR)
+    {
+      if (vr0.type == VR_RANGE
+          && vr1.type == VR_RANGE
+         && TREE_CODE (vr0.min) == INTEGER_CST
+         && TREE_CODE (vr1.min) == INTEGER_CST
+         && TREE_CODE (vr0.max) == INTEGER_CST
+         && TREE_CODE (vr1.max) == INTEGER_CST
+         && tree_int_cst_sgn (vr0.min) >= 0
+         && tree_int_cst_sgn (vr1.min) >= 0)
+       {
+         double_int vr0_max = tree_to_double_int (vr0.max);
+         double_int vr1_max = tree_to_double_int (vr1.max);
+         double_int ior_max;
+
+         /* Set all bits to the right of the most significant one to 1.
+            For example, [0, 4] | [4, 4] = [4, 7]. */
+         ior_max.low = vr0_max.low | vr1_max.low;
+         ior_max.high = vr0_max.high | vr1_max.high;
+         if (ior_max.high != 0)
+           {
+             ior_max.low = ~0u;
+             ior_max.high |= ((HOST_WIDE_INT) 1
+                              << floor_log2 (ior_max.high)) - 1;
+           }
+         else
+           ior_max.low |= ((unsigned HOST_WIDE_INT) 1u
+                           << floor_log2 (ior_max.low)) - 1;
+
+         /* Both of these endpoints are conservative.  */
+          min = vrp_int_const_binop (MAX_EXPR, vr0.min, vr1.min);
+          max = double_int_to_tree (expr_type, ior_max);
+       }
+      else
+       {
+         set_value_range_to_varying (vr);
+         return;
+       }
+    }
   else
     gcc_unreachable ();
 
@@ -2297,6 +2518,18 @@ extract_range_from_unary_expr (value_range_t *vr, enum tree_code code,
       || code == BIT_NOT_EXPR
       || code == CONJ_EXPR)
     {
+      /* We can still do constant propagation here.  */
+      if ((op0 = op_with_constant_singleton_value_range (op0)) != NULL_TREE)
+       {
+         tree tem = fold_unary (code, type, op0);
+         if (tem
+             && is_gimple_min_invariant (tem)
+             && !is_overflow_infinity (tem))
+           {
+             set_value_range (vr, VR_RANGE, tem, tem, NULL);
+             return;
+           }
+       }
       set_value_range_to_varying (vr);
       return;
     }
@@ -2348,8 +2581,7 @@ extract_range_from_unary_expr (value_range_t *vr, enum tree_code code,
     }
 
   /* Handle unary expressions on integer ranges.  */
-  if ((code == NOP_EXPR
-       || code == CONVERT_EXPR)
+  if (CONVERT_EXPR_CODE_P (code)
       && INTEGRAL_TYPE_P (type)
       && INTEGRAL_TYPE_P (TREE_TYPE (op0)))
     {
@@ -2519,7 +2751,10 @@ extract_range_from_unary_expr (value_range_t *vr, enum tree_code code,
        max = fold_unary_to_constant (code, type, vr0.max);
       else if (!needs_overflow_infinity (type))
        max = TYPE_MAX_VALUE (type);
-      else if (supports_overflow_infinity (type))
+      else if (supports_overflow_infinity (type)
+              /* We shouldn't generate [+INF, +INF] as set_value_range
+                 doesn't like this and ICEs.  */
+              && !is_positive_overflow_infinity (min))
        max = positive_overflow_infinity (type);
       else
        {
@@ -2709,10 +2944,10 @@ extract_range_from_comparison (value_range_t *vr, enum tree_code code,
                               tree type, tree op0, tree op1)
 {
   bool sop = false;
-  tree val = vrp_evaluate_conditional_warnv_with_ops (code,
-                                                     op0,
-                                                     op1,
-                                                     false, &sop);
+  tree val;
+  
+  val = vrp_evaluate_conditional_warnv_with_ops (code, op0, op1, false, &sop,
+                                                NULL);
 
   /* A disadvantage of using a special infinity as an overflow
      representation is that we lose the ability to record overflow
@@ -2735,56 +2970,67 @@ extract_range_from_comparison (value_range_t *vr, enum tree_code code,
     set_value_range_to_truthvalue (vr, type);
 }
 
+/* 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 */
 
-/* Try to compute a useful range out of expression EXPR and store it
+static void
+extract_range_basic (value_range_t *vr, gimple stmt)
+{
+  bool sop = false;
+  tree type = gimple_expr_type (stmt);
+
+  if (INTEGRAL_TYPE_P (type)
+      && gimple_stmt_nonnegative_warnv_p (stmt, &sop))
+    set_value_range_to_nonnegative (vr, type,
+                                   sop || stmt_overflow_infinity (stmt));
+  else if (vrp_stmt_computes_nonzero (stmt, &sop)
+          && !sop)
+    set_value_range_to_nonnull (vr, type);
+  else
+    set_value_range_to_varying (vr);
+}
+
+
+/* Try to compute a useful range out of assignment STMT and store it
    in *VR.  */
 
 static void
-extract_range_from_expr (value_range_t *vr, tree expr)
+extract_range_from_assignment (value_range_t *vr, gimple stmt)
 {
-  enum tree_code code = TREE_CODE (expr);
+  enum tree_code code = gimple_assign_rhs_code (stmt);
 
   if (code == ASSERT_EXPR)
-    extract_range_from_assert (vr, expr);
+    extract_range_from_assert (vr, gimple_assign_rhs1 (stmt));
   else if (code == SSA_NAME)
-    extract_range_from_ssa_name (vr, expr);
+    extract_range_from_ssa_name (vr, gimple_assign_rhs1 (stmt));
   else if (TREE_CODE_CLASS (code) == tcc_binary
           || code == TRUTH_AND_EXPR
           || code == TRUTH_OR_EXPR
           || code == TRUTH_XOR_EXPR)
-    extract_range_from_binary_expr (vr, TREE_CODE (expr), TREE_TYPE (expr),
-                                   TREE_OPERAND (expr, 0),
-                                   TREE_OPERAND (expr, 1));
+    extract_range_from_binary_expr (vr, gimple_assign_rhs_code (stmt),
+                                   gimple_expr_type (stmt),
+                                   gimple_assign_rhs1 (stmt),
+                                   gimple_assign_rhs2 (stmt));
   else if (TREE_CODE_CLASS (code) == tcc_unary)
-    extract_range_from_unary_expr (vr, TREE_CODE (expr), TREE_TYPE (expr),
-                                  TREE_OPERAND (expr, 0));
+    extract_range_from_unary_expr (vr, gimple_assign_rhs_code (stmt),
+                                  gimple_expr_type (stmt),
+                                  gimple_assign_rhs1 (stmt));
   else if (code == COND_EXPR)
-    extract_range_from_cond_expr (vr, expr);
+    extract_range_from_cond_expr (vr, gimple_assign_rhs1 (stmt));
   else if (TREE_CODE_CLASS (code) == tcc_comparison)
-    extract_range_from_comparison (vr, TREE_CODE (expr), TREE_TYPE (expr),
-                                  TREE_OPERAND (expr, 0),
-                                  TREE_OPERAND (expr, 1));
-  else if (is_gimple_min_invariant (expr))
-    set_value_range_to_value (vr, expr, NULL);
+    extract_range_from_comparison (vr, gimple_assign_rhs_code (stmt),
+                                  gimple_expr_type (stmt),
+                                  gimple_assign_rhs1 (stmt),
+                                  gimple_assign_rhs2 (stmt));
+  else if (get_gimple_rhs_class (code) == GIMPLE_SINGLE_RHS
+          && is_gimple_min_invariant (gimple_assign_rhs1 (stmt)))
+    set_value_range_to_value (vr, gimple_assign_rhs1 (stmt), NULL);
   else
     set_value_range_to_varying (vr);
 
-  /* If we got a varying range from the tests above, try a final
-     time to derive a nonnegative or nonzero range.  This time
-     relying primarily on generic routines in fold in conjunction
-     with range data.  */
   if (vr->type == VR_VARYING)
-    {
-      bool sop = false;
-
-      if (INTEGRAL_TYPE_P (TREE_TYPE (expr))
-         && vrp_expr_computes_nonnegative (expr, &sop))
-       set_value_range_to_nonnegative (vr, TREE_TYPE (expr),
-                                       sop || is_overflow_infinity (expr));
-      else if (vrp_expr_computes_nonzero (expr, &sop)
-              && !sop)
-        set_value_range_to_nonnull (vr, TREE_TYPE (expr));
-    }
+    extract_range_basic (vr, stmt);
 }
 
 /* Given a range VR, a LOOP and a variable VAR, determine whether it
@@ -2792,8 +3038,8 @@ extract_range_from_expr (value_range_t *vr, tree expr)
    for VAR.  If so, update VR with the new limits.  */
 
 static void
-adjust_range_with_scev (value_range_t *vr, struct loop *loop, tree stmt,
-                       tree var)
+adjust_range_with_scev (value_range_t *vr, struct loop *loop,
+                       gimple stmt, tree var)
 {
   tree init, step, chrec, tmin, tmax, min, max, type;
   enum ev_direction dir;
@@ -2926,7 +3172,7 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop, tree stmt,
    overflow.  */
 
 static bool
-vrp_var_may_overflow (tree var, tree stmt)
+vrp_var_may_overflow (tree var, gimple stmt)
 {
   struct loop *l;
   tree chrec, init, step;
@@ -3374,31 +3620,32 @@ debug_all_value_ranges (void)
    create a new SSA name N and return the assertion assignment
    'V = ASSERT_EXPR <V, V OP W>'.  */
 
-static tree
+static gimple
 build_assert_expr_for (tree cond, tree v)
 {
-  tree n, assertion;
+  tree n;
+  gimple assertion;
 
   gcc_assert (TREE_CODE (v) == SSA_NAME);
-  n = duplicate_ssa_name (v, NULL_TREE);
+  n = duplicate_ssa_name (v, NULL);
 
   if (COMPARISON_CLASS_P (cond))
     {
       tree a = build2 (ASSERT_EXPR, TREE_TYPE (v), v, cond); 
-      assertion = build_gimple_modify_stmt (n, a);
+      assertion = gimple_build_assign (n, a);
     }
   else if (TREE_CODE (cond) == TRUTH_NOT_EXPR)
     {
       /* Given !V, build the assignment N = false.  */
       tree op0 = TREE_OPERAND (cond, 0);
       gcc_assert (op0 == v);
-      assertion = build_gimple_modify_stmt (n, boolean_false_node);
+      assertion = gimple_build_assign (n, boolean_false_node);
     }
   else if (TREE_CODE (cond) == SSA_NAME)
     {
       /* Given V, build the assignment N = true.  */
       gcc_assert (v == cond);
-      assertion = build_gimple_modify_stmt (n, boolean_true_node);
+      assertion = gimple_build_assign (n, boolean_true_node);
     }
   else
     gcc_unreachable ();
@@ -3419,10 +3666,11 @@ build_assert_expr_for (tree cond, tree v)
    point values.  */
 
 static inline bool
-fp_predicate (const_tree expr)
+fp_predicate (gimple stmt)
 {
-  return (COMPARISON_CLASS_P (expr)
-         && FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0))));
+  GIMPLE_CHECK (stmt, GIMPLE_COND);
+
+  return FLOAT_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)));
 }
 
 
@@ -3432,7 +3680,7 @@ fp_predicate (const_tree expr)
    inferred.  */
 
 static bool
-infer_value_range (tree stmt, tree op, enum tree_code *comp_code_p, tree *val_p)
+infer_value_range (gimple stmt, tree op, enum tree_code *comp_code_p, tree *val_p)
 {
   *val_p = NULL_TREE;
   *comp_code_p = ERROR_MARK;
@@ -3444,19 +3692,21 @@ infer_value_range (tree stmt, tree op, enum tree_code *comp_code_p, tree *val_p)
 
   /* Similarly, don't infer anything from statements that may throw
      exceptions.  */
-  if (tree_could_throw_p (stmt))
+  if (stmt_could_throw_p (stmt))
     return false;
 
   /* If STMT is the last statement of a basic block with no
      successors, there is no point inferring anything about any of its
      operands.  We would not be able to find a proper insertion point
      for the assertion, anyway.  */
-  if (stmt_ends_bb_p (stmt) && EDGE_COUNT (bb_for_stmt (stmt)->succs) == 0)
+  if (stmt_ends_bb_p (stmt) && EDGE_COUNT (gimple_bb (stmt)->succs) == 0)
     return false;
 
   /* We can only assume that a pointer dereference will yield
      non-NULL if -fdelete-null-pointer-checks is enabled.  */
-  if (flag_delete_null_pointer_checks && POINTER_TYPE_P (TREE_TYPE (op)))
+  if (flag_delete_null_pointer_checks
+      && POINTER_TYPE_P (TREE_TYPE (op))
+      && gimple_code (stmt) != GIMPLE_ASM)
     {
       unsigned num_uses, num_loads, num_stores;
 
@@ -3493,7 +3743,7 @@ dump_asserts_for (FILE *file, tree name)
   while (loc)
     {
       fprintf (file, "\t");
-      print_generic_expr (file, bsi_stmt (loc->si), 0);
+      print_gimple_stmt (file, gsi_stmt (loc->si), 0, 0);
       fprintf (file, "\n\tBB #%d", loc->bb->index);
       if (loc->e)
        {
@@ -3563,7 +3813,7 @@ register_new_assert_for (tree name, tree expr,
                         tree val,
                         basic_block bb,
                         edge e,
-                        block_stmt_iterator si)
+                        gimple_stmt_iterator si)
 {
   assert_locus_t n, loc, last_loc;
   bool found;
@@ -3573,10 +3823,18 @@ register_new_assert_for (tree name, tree expr,
   gcc_assert (bb == NULL || e == NULL);
 
   if (e == NULL)
-    gcc_assert (TREE_CODE (bsi_stmt (si)) != COND_EXPR
-               && TREE_CODE (bsi_stmt (si)) != SWITCH_EXPR);
+    gcc_assert (gimple_code (gsi_stmt (si)) != GIMPLE_COND
+               && gimple_code (gsi_stmt (si)) != GIMPLE_SWITCH);
 #endif
 
+  /* Never build an assert comparing against an integer constant with
+     TREE_OVERFLOW set.  This confuses our undefined overflow warning
+     machinery.  */
+  if (TREE_CODE (val) == INTEGER_CST
+      && TREE_OVERFLOW (val))
+    val = build_int_cst_wide (TREE_TYPE (val),
+                             TREE_INT_CST_LOW (val), TREE_INT_CST_HIGH (val));
+
   /* The new assertion A will be inserted at BB or E.  We need to
      determine if the new location is dominated by a previously
      registered location for A.  If we are doing an edge insertion,
@@ -3746,7 +4004,7 @@ extract_code_and_val_from_cond_with_ops (tree name, enum tree_code cond_code,
    Return true if an assertion for NAME could be registered.  */
 
 static bool
-register_edge_assert_for_2 (tree name, edge e, block_stmt_iterator bsi,
+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)
 {
@@ -3762,7 +4020,7 @@ register_edge_assert_for_2 (tree name, edge e, block_stmt_iterator bsi,
 
   /* Only register an ASSERT_EXPR if NAME was found in the sub-graph
      reachable from E.  */
-  if (TEST_BIT (found_in_subgraph, SSA_NAME_VERSION (name))
+  if (live_on_edge (e, name)
       && !has_single_use (name))
     {
       register_new_assert_for (name, name, comp_code, val, NULL, e, bsi);
@@ -3778,30 +4036,28 @@ register_edge_assert_for_2 (tree name, edge e, block_stmt_iterator bsi,
       && TREE_CODE (val) == INTEGER_CST
       && TYPE_UNSIGNED (TREE_TYPE (val)))
     {
-      tree 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.  */
-      if (TREE_CODE (def_stmt) == GIMPLE_MODIFY_STMT
-         && TREE_CODE (GIMPLE_STMT_OPERAND (def_stmt, 1)) == PLUS_EXPR)
+      if (is_gimple_assign (def_stmt)
+         && gimple_assign_rhs_code (def_stmt) == PLUS_EXPR)
        {
-         name2 = TREE_OPERAND (GIMPLE_STMT_OPERAND (def_stmt, 1), 0);
-         cst2 = TREE_OPERAND (GIMPLE_STMT_OPERAND (def_stmt, 1), 1);
+         name2 = gimple_assign_rhs1 (def_stmt);
+         cst2 = gimple_assign_rhs2 (def_stmt);
          if (TREE_CODE (name2) == SSA_NAME
              && TREE_CODE (cst2) == INTEGER_CST)
            def_stmt = SSA_NAME_DEF_STMT (name2);
        }
 
       /* Extract NAME2 from the (optional) sign-changing cast.  */
-      if (TREE_CODE (def_stmt) == GIMPLE_MODIFY_STMT
-          && CONVERT_EXPR_P (GIMPLE_STMT_OPERAND (def_stmt, 1)))
+      if (gimple_assign_cast_p (def_stmt))
        {
-         tree rhs = GIMPLE_STMT_OPERAND (def_stmt, 1);
-         if (CONVERT_EXPR_P (rhs)
-             && ! TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (rhs, 0)))
-             && (TYPE_PRECISION (TREE_TYPE (rhs))
-                 == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (rhs, 0)))))
-           name3 = TREE_OPERAND (GIMPLE_STMT_OPERAND (def_stmt, 1), 0);
+         if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt))
+             && ! TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (def_stmt)))
+             && (TYPE_PRECISION (gimple_expr_type (def_stmt))
+                 == TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (def_stmt)))))
+           name3 = gimple_assign_rhs1 (def_stmt);
        }
 
       /* If name3 is used later, create an ASSERT_EXPR for it.  */
@@ -3810,7 +4066,7 @@ register_edge_assert_for_2 (tree name, edge e, block_stmt_iterator bsi,
          && (cst2 == NULL_TREE
              || TREE_CODE (cst2) == INTEGER_CST)
          && INTEGRAL_TYPE_P (TREE_TYPE (name3))
-         && TEST_BIT (found_in_subgraph, SSA_NAME_VERSION (name3))
+         && live_on_edge (e, name3)
          && !has_single_use (name3))
        {
          tree tmp;
@@ -3839,7 +4095,7 @@ register_edge_assert_for_2 (tree name, edge e, block_stmt_iterator bsi,
          && TREE_CODE (name2) == SSA_NAME
          && TREE_CODE (cst2) == INTEGER_CST
          && INTEGRAL_TYPE_P (TREE_TYPE (name2))
-         && TEST_BIT (found_in_subgraph, SSA_NAME_VERSION (name2))
+         && live_on_edge (e, name2)
          && !has_single_use (name2))
        {
          tree tmp;
@@ -3878,10 +4134,11 @@ register_edge_assert_for_2 (tree name, edge e, block_stmt_iterator bsi,
 
 static bool
 register_edge_assert_for_1 (tree op, enum tree_code code,
-                           edge e, block_stmt_iterator bsi)
+                           edge e, gimple_stmt_iterator bsi)
 {
   bool retval = false;
-  tree op_def, rhs, val;
+  gimple op_def;
+  tree val;
   enum tree_code rhs_code;
 
   /* We only care about SSA_NAMEs.  */
@@ -3905,17 +4162,16 @@ register_edge_assert_for_1 (tree op, enum tree_code code,
      a truth operation or some bit operations, then we may be able
      to register information about the operands of that assignment.  */
   op_def = SSA_NAME_DEF_STMT (op);
-  if (TREE_CODE (op_def) != GIMPLE_MODIFY_STMT)
+  if (gimple_code (op_def) != GIMPLE_ASSIGN)
     return retval;
 
-  rhs = GIMPLE_STMT_OPERAND (op_def, 1);
-  rhs_code = TREE_CODE (rhs);
+  rhs_code = gimple_assign_rhs_code (op_def);
 
-  if (COMPARISON_CLASS_P (rhs))
+  if (TREE_CODE_CLASS (rhs_code) == tcc_comparison)
     {
       bool invert = (code == EQ_EXPR ? true : false);
-      tree op0 = TREE_OPERAND (rhs, 0);
-      tree op1 = TREE_OPERAND (rhs, 1);
+      tree op0 = gimple_assign_rhs1 (op_def);
+      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,
@@ -3925,34 +4181,35 @@ register_edge_assert_for_1 (tree op, enum tree_code code,
                                              invert);
     }
   else if ((code == NE_EXPR
-           && (TREE_CODE (rhs) == TRUTH_AND_EXPR
-               || TREE_CODE (rhs) == BIT_AND_EXPR))
+           && (gimple_assign_rhs_code (op_def) == TRUTH_AND_EXPR
+               || gimple_assign_rhs_code (op_def) == BIT_AND_EXPR))
           || (code == EQ_EXPR
-              && (TREE_CODE (rhs) == TRUTH_OR_EXPR
-                  || TREE_CODE (rhs) == BIT_IOR_EXPR)))
+              && (gimple_assign_rhs_code (op_def) == TRUTH_OR_EXPR
+                  || gimple_assign_rhs_code (op_def) == BIT_IOR_EXPR)))
     {
       /* Recurse on each operand.  */
-      retval |= register_edge_assert_for_1 (TREE_OPERAND (rhs, 0),
+      retval |= register_edge_assert_for_1 (gimple_assign_rhs1 (op_def),
                                            code, e, bsi);
-      retval |= register_edge_assert_for_1 (TREE_OPERAND (rhs, 1),
+      retval |= register_edge_assert_for_1 (gimple_assign_rhs2 (op_def),
                                            code, e, bsi);
     }
-  else if (TREE_CODE (rhs) == TRUTH_NOT_EXPR)
+  else if (gimple_assign_rhs_code (op_def) == TRUTH_NOT_EXPR)
     {
       /* Recurse, flipping CODE.  */
       code = invert_tree_comparison (code, false);
-      retval |= register_edge_assert_for_1 (TREE_OPERAND (rhs, 0),
+      retval |= register_edge_assert_for_1 (gimple_assign_rhs1 (op_def),
                                            code, e, bsi);
     }
-  else if (TREE_CODE (rhs) == SSA_NAME)
+  else if (gimple_assign_rhs_code (op_def) == SSA_NAME)
     {
       /* Recurse through the copy.  */
-      retval |= register_edge_assert_for_1 (rhs, code, e, bsi);
+      retval |= register_edge_assert_for_1 (gimple_assign_rhs1 (op_def),
+                                           code, e, bsi);
     }
-  else if (CONVERT_EXPR_P (rhs))
+  else if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (op_def)))
     { 
       /* Recurse through the type conversion.  */
-      retval |= register_edge_assert_for_1 (TREE_OPERAND (rhs, 0),
+      retval |= register_edge_assert_for_1 (gimple_assign_rhs1 (op_def),
                                            code, e, bsi);
     }
 
@@ -3964,7 +4221,7 @@ register_edge_assert_for_1 (tree op, enum tree_code code,
    Return true if an assertion for NAME could be registered.  */
 
 static bool
-register_edge_assert_for (tree name, edge e, block_stmt_iterator si,
+register_edge_assert_for (tree name, edge e, gimple_stmt_iterator si,
                          enum tree_code cond_code, tree cond_op0,
                          tree cond_op1)
 {
@@ -3999,14 +4256,14 @@ register_edge_assert_for (tree name, edge e, block_stmt_iterator si,
   if (((comp_code == EQ_EXPR && integer_onep (val))
        || (comp_code == NE_EXPR && integer_zerop (val))))
     {
-      tree def_stmt = SSA_NAME_DEF_STMT (name);
+      gimple def_stmt = SSA_NAME_DEF_STMT (name);
 
-      if (TREE_CODE (def_stmt) == GIMPLE_MODIFY_STMT
-         && (TREE_CODE (GIMPLE_STMT_OPERAND (def_stmt, 1)) == TRUTH_AND_EXPR
-             || TREE_CODE (GIMPLE_STMT_OPERAND (def_stmt, 1)) == BIT_AND_EXPR))
+      if (is_gimple_assign (def_stmt)
+         && (gimple_assign_rhs_code (def_stmt) == TRUTH_AND_EXPR
+             || gimple_assign_rhs_code (def_stmt) == BIT_AND_EXPR))
        {
-         tree op0 = TREE_OPERAND (GIMPLE_STMT_OPERAND (def_stmt, 1), 0);
-         tree op1 = TREE_OPERAND (GIMPLE_STMT_OPERAND (def_stmt, 1), 1);
+         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);
        }
@@ -4018,18 +4275,17 @@ register_edge_assert_for (tree name, edge e, block_stmt_iterator si,
   if (((comp_code == EQ_EXPR && integer_zerop (val))
        || (comp_code == NE_EXPR && integer_onep (val))))
     {
-      tree def_stmt = SSA_NAME_DEF_STMT (name);
+      gimple def_stmt = SSA_NAME_DEF_STMT (name);
 
-      if (TREE_CODE (def_stmt) == GIMPLE_MODIFY_STMT
-         && (TREE_CODE (GIMPLE_STMT_OPERAND (def_stmt, 1)) == TRUTH_OR_EXPR
+      if (is_gimple_assign (def_stmt)
+         && (gimple_assign_rhs_code (def_stmt) == TRUTH_OR_EXPR
              /* For BIT_IOR_EXPR only if NAME == 0 both operands have
                 necessarily zero value.  */
              || (comp_code == EQ_EXPR
-                 && (TREE_CODE (GIMPLE_STMT_OPERAND (def_stmt, 1))
-                       == BIT_IOR_EXPR))))
+                 && (gimple_assign_rhs_code (def_stmt) == BIT_IOR_EXPR))))
        {
-         tree op0 = TREE_OPERAND (GIMPLE_STMT_OPERAND (def_stmt, 1), 0);
-         tree op1 = TREE_OPERAND (GIMPLE_STMT_OPERAND (def_stmt, 1), 1);
+         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);
        }
@@ -4039,8 +4295,6 @@ register_edge_assert_for (tree name, edge e, block_stmt_iterator si,
 }
 
 
-static bool find_assert_locations (basic_block bb);
-
 /* Determine whether the outgoing edges of BB should receive an
    ASSERT_EXPR for each of the operands of BB's LAST statement.
    The last statement of BB must be a COND_EXPR.
@@ -4050,17 +4304,17 @@ static bool find_assert_locations (basic_block bb);
    list of assertions for the corresponding operands.  */
 
 static bool
-find_conditional_asserts (basic_block bb, tree last)
+find_conditional_asserts (basic_block bb, gimple last)
 {
   bool need_assert;
-  block_stmt_iterator bsi;
+  gimple_stmt_iterator bsi;
   tree op;
   edge_iterator ei;
   edge e;
   ssa_op_iter iter;
 
   need_assert = false;
-  bsi = bsi_for_stmt (last);
+  bsi = gsi_for_stmt (last);
 
   /* Look for uses of the operands in each of the sub-graphs
      rooted at BB.  We need to check each of the outgoing edges
@@ -4071,56 +4325,17 @@ find_conditional_asserts (basic_block bb, tree last)
       if (e->dest == bb)
        continue;
 
-      /* Remove the COND_EXPR operands from the FOUND_IN_SUBGRAPH bitmap.
-        Otherwise, when we finish traversing each of the sub-graphs, we
-        won't know whether the variables were found in the sub-graphs or
-        if they had been found in a block upstream from BB. 
-
-        This is actually a bad idea is some cases, particularly jump
-        threading.  Consider a CFG like the following:
-
-                    0
-                   /|
-                  1 |
-                   \|
-                    2
-                   / \
-                  3   4
-
-        Assume that one or more operands in the conditional at the
-        end of block 0 are used in a conditional in block 2, but not
-        anywhere in block 1.  In this case we will not insert any
-        assert statements in block 1, which may cause us to miss
-        opportunities to optimize, particularly for jump threading.  */
-      FOR_EACH_SSA_TREE_OPERAND (op, last, iter, SSA_OP_USE)
-       RESET_BIT (found_in_subgraph, SSA_NAME_VERSION (op));
-
-      /* Traverse the strictly dominated sub-graph rooted at E->DEST
-        to determine if any of the operands in the conditional
-        predicate are used.  */
-      need_assert |= find_assert_locations (e->dest);
-
       /* Register the necessary assertions for each operand in the
         conditional predicate.  */
       FOR_EACH_SSA_TREE_OPERAND (op, last, iter, SSA_OP_USE)
        {
-         tree cond = COND_EXPR_COND (last);
-         if (op != cond)
-           need_assert |= register_edge_assert_for (op, e, bsi,
-                                                    TREE_CODE (cond),
-                                                    TREE_OPERAND (cond, 0),
-                                                    TREE_OPERAND (cond, 1));
-         else
-           need_assert |= register_edge_assert_for (op, e, bsi, EQ_EXPR, op,
-                                                    boolean_true_node);
+         need_assert |= register_edge_assert_for (op, e, bsi,
+                                                  gimple_cond_code (last),
+                                                  gimple_cond_lhs (last),
+                                                  gimple_cond_rhs (last));
        }
     }
 
-  /* Finally, indicate that we have found the operands in the
-     conditional.  */
-  FOR_EACH_SSA_TREE_OPERAND (op, last, iter, SSA_OP_USE)
-    SET_BIT (found_in_subgraph, SSA_NAME_VERSION (op));
-
   return need_assert;
 }
 
@@ -4160,26 +4375,31 @@ compare_case_labels (const void *p1, const void *p2)
    list of assertions for the corresponding operands.  */
 
 static bool
-find_switch_asserts (basic_block bb, tree last)
+find_switch_asserts (basic_block bb, gimple last)
 {
   bool need_assert;
-  block_stmt_iterator bsi;
+  gimple_stmt_iterator bsi;
   tree op;
   edge e;
-  tree vec = SWITCH_LABELS (last), vec2;
-  size_t n = TREE_VEC_LENGTH (vec);
+  tree vec2;
+  size_t n = gimple_switch_num_labels(last);
+#if GCC_VERSION >= 4000
   unsigned int idx;
+#else
+  /* Work around GCC 3.4 bug (PR 37086).  */
+  volatile unsigned int idx;
+#endif
 
   need_assert = false;
-  bsi = bsi_for_stmt (last);
-  op = TREE_OPERAND (last, 0);
+  bsi = gsi_for_stmt (last);
+  op = gimple_switch_index (last);
   if (TREE_CODE (op) != SSA_NAME)
     return false;
 
   /* Build a vector of case labels sorted by destination label.  */
   vec2 = make_tree_vec (n);
   for (idx = 0; idx < n; ++idx)
-    TREE_VEC_ELT (vec2, idx) = TREE_VEC_ELT (vec, idx);
+    TREE_VEC_ELT (vec2, idx) = gimple_switch_label (last, idx);
   qsort (&TREE_VEC_ELT (vec2, 0), n, sizeof (tree), compare_case_labels);
 
   for (idx = 0; idx < n; ++idx)
@@ -4217,18 +4437,6 @@ find_switch_asserts (basic_block bb, tree last)
       /* Find the edge to register the assert expr on.  */
       e = find_edge (bb, label_to_block (CASE_LABEL (cl)));
 
-      /* Remove the SWITCH_EXPR operand from the FOUND_IN_SUBGRAPH bitmap.
-        Otherwise, when we finish traversing each of the sub-graphs, we
-        won't know whether the variables were found in the sub-graphs or
-        if they had been found in a block upstream from BB.  */
-      RESET_BIT (found_in_subgraph, SSA_NAME_VERSION (op));
-
-      /* Traverse the strictly dominated sub-graph rooted at E->DEST
-        to determine if any of the operands in the conditional
-        predicate are used.  */
-      if (e->dest != bb)
-       need_assert |= find_assert_locations (e->dest);
-
       /* Register the necessary assertions for the operand in the
         SWITCH_EXPR.  */
       need_assert |= register_edge_assert_for (op, e, bsi,
@@ -4245,10 +4453,6 @@ find_switch_asserts (basic_block bb, tree last)
        }
     }
 
-  /* Finally, indicate that we have found the operand in the
-     SWITCH_EXPR.  */
-  SET_BIT (found_in_subgraph, SSA_NAME_VERSION (op));
-
   return need_assert;
 }
 
@@ -4317,46 +4521,40 @@ find_switch_asserts (basic_block bb, tree last)
    inserted by process_assert_insertions.  */
 
 static bool
-find_assert_locations (basic_block bb)
+find_assert_locations_1 (basic_block bb, sbitmap live)
 {
-  block_stmt_iterator si;
-  tree last, phi;
+  gimple_stmt_iterator si;
+  gimple last;
+  gimple phi;
   bool need_assert;
-  basic_block son;
-
-  if (TEST_BIT (blocks_visited, bb->index))
-    return false;
-
-  SET_BIT (blocks_visited, bb->index);
 
   need_assert = false;
+  last = last_stmt (bb);
 
-  /* Traverse all PHI nodes in BB marking used operands.  */
-  for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
-    {
-      use_operand_p arg_p;
-      ssa_op_iter i;
+  /* If BB's last statement is a conditional statement involving integer
+     operands, determine if we need to add ASSERT_EXPRs.  */
+  if (last
+      && gimple_code (last) == GIMPLE_COND
+      && !fp_predicate (last)
+      && !ZERO_SSA_OPERANDS (last, SSA_OP_USE))
+    need_assert |= find_conditional_asserts (bb, last);
 
-      FOR_EACH_PHI_ARG (arg_p, phi, i, SSA_OP_USE)
-       {
-         tree arg = USE_FROM_PTR (arg_p);
-         if (TREE_CODE (arg) == SSA_NAME)
-           {
-             gcc_assert (is_gimple_reg (PHI_RESULT (phi)));
-             SET_BIT (found_in_subgraph, SSA_NAME_VERSION (arg));
-           }
-       }
-    }
+  /* 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);
 
   /* Traverse all the statements in BB marking used names and looking
      for statements that may infer assertions for their used operands.  */
-  last = NULL_TREE;
-  for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
+  for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
     {
-      tree stmt, op;
+      gimple stmt;
+      tree op;
       ssa_op_iter i;
 
-      stmt = bsi_stmt (si);
+      stmt = gsi_stmt (si);
 
       /* See if we can derive an assertion for any of STMT's operands.  */
       FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_USE)
@@ -4364,12 +4562,8 @@ find_assert_locations (basic_block bb)
          tree value;
          enum tree_code comp_code;
 
-         /* Mark OP in bitmap FOUND_IN_SUBGRAPH.  If STMT is inside
-            the sub-graph of a conditional block, when we return from
-            this recursive walk, our parent will use the
-            FOUND_IN_SUBGRAPH bitset to determine if one of the
-            operands it was looking for was present in the sub-graph.  */
-         SET_BIT (found_in_subgraph, SSA_NAME_VERSION (op));
+         /* Mark OP in our live bitmap.  */
+         SET_BIT (live, SSA_NAME_VERSION (op));
 
          /* If OP is used in such a way that we can infer a value
             range for it, and we don't find a previous assertion for
@@ -4385,20 +4579,16 @@ find_assert_locations (basic_block bb)
              if (comp_code == NE_EXPR && integer_zerop (value))
                {
                  tree t = op;
-                 tree def_stmt = SSA_NAME_DEF_STMT (t);
+                 gimple def_stmt = SSA_NAME_DEF_STMT (t);
        
-                 while (TREE_CODE (def_stmt) == GIMPLE_MODIFY_STMT
+                 while (is_gimple_assign (def_stmt)
+                        && gimple_assign_rhs_code (def_stmt)  == NOP_EXPR
                         && TREE_CODE
-                            (GIMPLE_STMT_OPERAND (def_stmt, 1)) == NOP_EXPR
-                        && TREE_CODE
-                            (TREE_OPERAND (GIMPLE_STMT_OPERAND (def_stmt, 1),
-                                           0)) == SSA_NAME
+                            (gimple_assign_rhs1 (def_stmt)) == SSA_NAME
                         && POINTER_TYPE_P
-                            (TREE_TYPE (TREE_OPERAND
-                                         (GIMPLE_STMT_OPERAND (def_stmt,
-                                                               1), 0))))
+                            (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
                    {
-                     t = TREE_OPERAND (GIMPLE_STMT_OPERAND (def_stmt, 1), 0);
+                     t = gimple_assign_rhs1 (def_stmt);
                      def_stmt = SSA_NAME_DEF_STMT (t);
 
                      /* Note we want to register the assert for the
@@ -4424,34 +4614,113 @@ find_assert_locations (basic_block bb)
                }
            }
        }
-
-      /* Remember the last statement of the block.  */
-      last = stmt;
     }
 
-  /* If BB's last statement is a conditional expression
-     involving integer operands, recurse into each of the sub-graphs
-     rooted at BB to determine if we need to add ASSERT_EXPRs.  */
-  if (last
-      && TREE_CODE (last) == COND_EXPR
-      && !fp_predicate (COND_EXPR_COND (last))
-      && !ZERO_SSA_OPERANDS (last, SSA_OP_USE))
-    need_assert |= find_conditional_asserts (bb, last);
-
-  if (last
-      && TREE_CODE (last) == SWITCH_EXPR
-      && !ZERO_SSA_OPERANDS (last, SSA_OP_USE))
-    need_assert |= find_switch_asserts (bb, last);
+  /* Traverse all PHI nodes in BB marking used operands.  */
+  for (si = gsi_start_phis (bb); !gsi_end_p(si); gsi_next (&si))
+    {
+      use_operand_p arg_p;
+      ssa_op_iter i;
+      phi = gsi_stmt (si);
 
-  /* Recurse into the dominator children of BB.  */
-  for (son = first_dom_son (CDI_DOMINATORS, bb);
-       son;
-       son = next_dom_son (CDI_DOMINATORS, son))
-    need_assert |= find_assert_locations (son);
+      FOR_EACH_PHI_ARG (arg_p, phi, i, SSA_OP_USE)
+       {
+         tree arg = USE_FROM_PTR (arg_p);
+         if (TREE_CODE (arg) == SSA_NAME)
+           SET_BIT (live, SSA_NAME_VERSION (arg));
+       }
+    }
 
   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.  */
+
+static bool
+find_assert_locations (void)
+{
+  int *rpo = XCNEWVEC (int, last_basic_block + NUM_FIXED_BLOCKS);
+  int *bb_rpo = XCNEWVEC (int, last_basic_block + NUM_FIXED_BLOCKS);
+  int *last_rpo = XCNEWVEC (int, last_basic_block + NUM_FIXED_BLOCKS);
+  int rpo_cnt, i;
+  bool need_asserts;
+
+  live = XCNEWVEC (sbitmap, last_basic_block + NUM_FIXED_BLOCKS);
+  rpo_cnt = pre_and_rev_post_order_compute (NULL, rpo, false);
+  for (i = 0; i < rpo_cnt; ++i)
+    bb_rpo[rpo[i]] = i;
+
+  need_asserts = false;
+  for (i = rpo_cnt-1; i >= 0; --i)
+    {
+      basic_block bb = BASIC_BLOCK (rpo[i]);
+      edge e;
+      edge_iterator ei;
+
+      if (!live[rpo[i]])
+       {
+         live[rpo[i]] = sbitmap_alloc (num_ssa_names);
+         sbitmap_zero (live[rpo[i]]);
+       }
+
+      /* Process BB and update the live information with uses in
+         this block.  */
+      need_asserts |= find_assert_locations_1 (bb, live[rpo[i]]);
+
+      /* Merge liveness into the predecessor blocks and free it.  */
+      if (!sbitmap_empty_p (live[rpo[i]]))
+       {
+         int pred_rpo = i;
+         FOR_EACH_EDGE (e, ei, bb->preds)
+           {
+             int pred = e->src->index;
+             if (e->flags & EDGE_DFS_BACK)
+               continue;
+
+             if (!live[pred])
+               {
+                 live[pred] = sbitmap_alloc (num_ssa_names);
+                 sbitmap_zero (live[pred]);
+               }
+             sbitmap_a_or_b (live[pred], live[pred], live[rpo[i]]);
+
+             if (bb_rpo[pred] < pred_rpo)
+               pred_rpo = bb_rpo[pred];
+           }
+
+         /* Record the RPO number of the last visited block that needs
+            live information from this block.  */
+         last_rpo[rpo[i]] = pred_rpo;
+       }
+      else
+       {
+         sbitmap_free (live[rpo[i]]);
+         live[rpo[i]] = NULL;
+       }
+
+      /* We can free all successors live bitmaps if all their
+         predecessors have been visited already.  */
+      FOR_EACH_EDGE (e, ei, bb->succs)
+       if (last_rpo[e->dest->index] == i
+           && live[e->dest->index])
+         {
+           sbitmap_free (live[e->dest->index]);
+           live[e->dest->index] = NULL;
+         }
+    }
+
+  XDELETEVEC (rpo);
+  XDELETEVEC (bb_rpo);
+  XDELETEVEC (last_rpo);
+  for (i = 0; i < last_basic_block + NUM_FIXED_BLOCKS; ++i)
+    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.  */
@@ -4460,32 +4729,33 @@ static bool
 process_assert_insertions_for (tree name, assert_locus_t loc)
 {
   /* Build the comparison expression NAME_i COMP_CODE VAL.  */
-  tree stmt, cond, assert_expr;
+  gimple stmt;
+  tree cond;
+  gimple assert_stmt;
   edge_iterator ei;
   edge e;
 
   cond = build2 (loc->comp_code, boolean_type_node, loc->expr, loc->val);
-  assert_expr = build_assert_expr_for (cond, name);
-
+  assert_stmt = build_assert_expr_for (cond, name);
   if (loc->e)
     {
       /* We have been asked to insert the assertion on an edge.  This
         is used only by COND_EXPR and SWITCH_EXPR assertions.  */
 #if defined ENABLE_CHECKING
-      gcc_assert (TREE_CODE (bsi_stmt (loc->si)) == COND_EXPR
-         || TREE_CODE (bsi_stmt (loc->si)) == SWITCH_EXPR);
+      gcc_assert (gimple_code (gsi_stmt (loc->si)) == GIMPLE_COND
+         || gimple_code (gsi_stmt (loc->si)) == GIMPLE_SWITCH);
 #endif
 
-      bsi_insert_on_edge (loc->e, assert_expr);
+      gsi_insert_on_edge (loc->e, assert_stmt);
       return true;
     }
 
   /* Otherwise, we can insert right after LOC->SI iff the
      statement must not be the last statement in the block.  */
-  stmt = bsi_stmt (loc->si);
+  stmt = gsi_stmt (loc->si);
   if (!stmt_ends_bb_p (stmt))
     {
-      bsi_insert_after (&loc->si, assert_expr, BSI_SAME_STMT);
+      gsi_insert_after (&loc->si, assert_stmt, GSI_SAME_STMT);
       return false;
     }
 
@@ -4496,7 +4766,7 @@ process_assert_insertions_for (tree name, assert_locus_t loc)
   FOR_EACH_EDGE (e, ei, loc->bb->succs)
     if (!(e->flags & EDGE_ABNORMAL))
       {
-       bsi_insert_on_edge (e, assert_expr);
+       gsi_insert_on_edge (e, assert_stmt);
        return true;
       }
 
@@ -4535,7 +4805,7 @@ process_assert_insertions (void)
     }
 
   if (update_edges_p)
-    bsi_commit_edge_inserts ();
+    gsi_commit_edge_inserts ();
 
   statistics_counter_event (cfun, "Number of ASSERT_EXPR expressions inserted",
                            num_asserts);
@@ -4577,27 +4847,12 @@ process_assert_insertions (void)
 static void
 insert_range_assertions (void)
 {
-  edge e;
-  edge_iterator ei;
-  bool update_ssa_p;
-  
-  found_in_subgraph = sbitmap_alloc (num_ssa_names);
-  sbitmap_zero (found_in_subgraph);
-
-  blocks_visited = sbitmap_alloc (last_basic_block);
-  sbitmap_zero (blocks_visited);
-
   need_assert_for = BITMAP_ALLOC (NULL);
   asserts_for = XCNEWVEC (assert_locus_t, num_ssa_names);
 
   calculate_dominance_info (CDI_DOMINATORS);
 
-  update_ssa_p = false;
-  FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
-    if (find_assert_locations (e->dest))
-      update_ssa_p = true;
-
-  if (update_ssa_p)
+  if (find_assert_locations ())
     {
       process_assert_insertions ();
       update_ssa (TODO_update_ssa_no_phi);
@@ -4609,7 +4864,6 @@ insert_range_assertions (void)
       dump_function_to_file (current_function_decl, dump_file, dump_flags);
     }
 
-  sbitmap_free (found_in_subgraph);
   free (asserts_for);
   BITMAP_FREE (need_assert_for);
 }
@@ -4622,7 +4876,7 @@ insert_range_assertions (void)
    IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR.  */
 
 static void
-check_array_ref (tree ref, location_t* locus, bool ignore_off_by_one)
+check_array_ref (tree ref, const location_t *location, bool ignore_off_by_one)
 {
   value_range_t* vr = NULL;
   tree low_sub, up_sub;
@@ -4662,7 +4916,7 @@ check_array_ref (tree ref, location_t* locus, bool ignore_off_by_one)
           && tree_int_cst_lt (low_sub, low_bound))
         {
           warning (OPT_Warray_bounds,
-                   "%Harray subscript is outside array bounds", locus);
+                   "%Harray subscript is outside array bounds", location);
           TREE_NO_WARNING (ref) = 1;
         }
     }
@@ -4677,14 +4931,14 @@ check_array_ref (tree ref, location_t* locus, bool ignore_off_by_one)
                                        up_sub)))
     {
       warning (OPT_Warray_bounds, "%Harray subscript is above array bounds",
-               locus);
+               location);
       TREE_NO_WARNING (ref) = 1;
     }
   else if (TREE_CODE (low_sub) == INTEGER_CST
            && tree_int_cst_lt (low_sub, low_bound))
     {
       warning (OPT_Warray_bounds, "%Harray subscript is below array bounds",
-               locus);
+               location);
       TREE_NO_WARNING (ref) = 1;
     }
 }
@@ -4693,14 +4947,20 @@ check_array_ref (tree ref, location_t* locus, bool ignore_off_by_one)
    address of an ARRAY_REF, and call check_array_ref on it.  */
 
 static void
-search_for_addr_array(tree t, location_t* location)
+search_for_addr_array(tree t, const location_t *location)
 {
   while (TREE_CODE (t) == SSA_NAME)
     {
-      t = SSA_NAME_DEF_STMT (t);
-      if (TREE_CODE (t) != GIMPLE_MODIFY_STMT)
+      gimple g = SSA_NAME_DEF_STMT (t);
+
+      if (gimple_code (g) != GIMPLE_ASSIGN)
        return;
-      t = GIMPLE_STMT_OPERAND (t, 1);
+
+      if (get_gimple_rhs_class (gimple_assign_rhs_code (g)) !=
+         GIMPLE_SINGLE_RHS)
+       return;
+
+      t = gimple_assign_rhs1 (g);
     }
 
 
@@ -4729,14 +4989,8 @@ static tree
 check_array_bounds (tree *tp, int *walk_subtree, void *data)
 {
   tree t = *tp;
-  tree stmt = (tree)data;
-  location_t *location = EXPR_LOCUS (stmt);
-
-  if (!EXPR_HAS_LOCATION (stmt))
-    {
-      *walk_subtree = FALSE;
-      return NULL_TREE;
-    }
+  struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
+  const location_t *location = (const location_t *) wi->info;
 
   *walk_subtree = TRUE;
 
@@ -4746,14 +5000,6 @@ check_array_bounds (tree *tp, int *walk_subtree, void *data)
   if (TREE_CODE (t) == INDIRECT_REF
       || (TREE_CODE (t) == RETURN_EXPR && TREE_OPERAND (t, 0)))
     search_for_addr_array (TREE_OPERAND (t, 0), location);
-  else if (TREE_CODE (t) == CALL_EXPR)
-    {
-      tree arg;
-      call_expr_arg_iterator iter;
-
-      FOR_EACH_CALL_EXPR_ARG (arg, iter, t) 
-       search_for_addr_array (arg, location);
-    }
 
   if (TREE_CODE (t) == ADDR_EXPR)
     *walk_subtree = FALSE;
@@ -4768,7 +5014,7 @@ static void
 check_all_array_refs (void)
 {
   basic_block bb;
-  block_stmt_iterator si;
+  gimple_stmt_iterator si;
 
   FOR_EACH_BB (bb)
     {
@@ -4776,21 +5022,46 @@ check_all_array_refs (void)
       if (single_pred_p (bb))
       {
        basic_block pred_bb = EDGE_PRED (bb, 0)->src;
-       tree ls = NULL_TREE;
+       gimple ls = NULL;
 
-       if (!bsi_end_p (bsi_last (pred_bb)))
-         ls = bsi_stmt (bsi_last (pred_bb));
+       if (!gsi_end_p (gsi_last_bb (pred_bb)))
+         ls = gsi_stmt (gsi_last_bb (pred_bb));
 
-       if (ls && TREE_CODE (ls) == COND_EXPR
-           && ((COND_EXPR_COND (ls) == boolean_false_node
+       if (ls && gimple_code (ls) == GIMPLE_COND
+           && ((gimple_cond_false_p (ls)
                 && (EDGE_PRED (bb, 0)->flags & EDGE_TRUE_VALUE))
-               || (COND_EXPR_COND (ls) == boolean_true_node
+               || (gimple_cond_true_p (ls)
                    && (EDGE_PRED (bb, 0)->flags & EDGE_FALSE_VALUE))))
          continue;
       }
-      for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
-       walk_tree (bsi_stmt_ptr (si), check_array_bounds,
-                  bsi_stmt (si), NULL);
+      for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
+       {
+         gimple stmt = gsi_stmt (si);
+         const location_t *location = gimple_location_ptr (stmt);
+         struct walk_stmt_info wi;
+         if (!gimple_has_location (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, location);
+               }
+           }
+         else
+           {
+             memset (&wi, 0, sizeof (wi));
+             wi.info = CONST_CAST (void *, (const void *) location);
+
+             walk_gimple_op (gsi_stmt (si),
+                             check_array_bounds,
+                             &wi);
+           }
+       }
     }
 }
 
@@ -4822,21 +5093,22 @@ static void
 remove_range_assertions (void)
 {
   basic_block bb;
-  block_stmt_iterator si;
+  gimple_stmt_iterator si;
 
   /* Note that the BSI iterator bump happens at the bottom of the
      loop and no bump is necessary if we're removing the statement
      referenced by the current BSI.  */
   FOR_EACH_BB (bb)
-    for (si = bsi_start (bb); !bsi_end_p (si);)
+    for (si = gsi_start_bb (bb); !gsi_end_p (si);)
       {
-       tree stmt = bsi_stmt (si);
-       tree use_stmt;
+       gimple stmt = gsi_stmt (si);
+       gimple use_stmt;
 
-       if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
-           && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == ASSERT_EXPR)
+       if (is_gimple_assign (stmt)
+           && gimple_assign_rhs_code (stmt) == ASSERT_EXPR)
          {
-           tree rhs = GIMPLE_STMT_OPERAND (stmt, 1), var;
+           tree rhs = gimple_assign_rhs1 (stmt);
+           tree var;
            tree cond = fold (ASSERT_EXPR_COND (rhs));
            use_operand_p use_p;
            imm_use_iterator iter;
@@ -4846,7 +5118,7 @@ remove_range_assertions (void)
            /* Propagate the RHS into every use of the LHS.  */
            var = ASSERT_EXPR_VAR (rhs);
            FOR_EACH_IMM_USE_STMT (use_stmt, iter,
-                                  GIMPLE_STMT_OPERAND (stmt, 0))
+                                  gimple_assign_lhs (stmt))
              FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
                {
                  SET_USE (use_p, var);
@@ -4854,46 +5126,43 @@ remove_range_assertions (void)
                }
 
            /* And finally, remove the copy, it is not needed.  */
-           bsi_remove (&si, true);
+           gsi_remove (&si, true);
            release_defs (stmt); 
          }
        else
-         bsi_next (&si);
+         gsi_next (&si);
       }
-
-  sbitmap_free (blocks_visited);
 }
 
 
 /* Return true if STMT is interesting for VRP.  */
 
 static bool
-stmt_interesting_for_vrp (tree stmt)
+stmt_interesting_for_vrp (gimple stmt)
 {
-  if (TREE_CODE (stmt) == PHI_NODE
-      && is_gimple_reg (PHI_RESULT (stmt))
-      && (INTEGRAL_TYPE_P (TREE_TYPE (PHI_RESULT (stmt)))
-         || POINTER_TYPE_P (TREE_TYPE (PHI_RESULT (stmt)))))
+  if (gimple_code (stmt) == GIMPLE_PHI
+      && is_gimple_reg (gimple_phi_result (stmt))
+      && (INTEGRAL_TYPE_P (TREE_TYPE (gimple_phi_result (stmt)))
+         || POINTER_TYPE_P (TREE_TYPE (gimple_phi_result (stmt)))))
     return true;
-  else if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT)
+  else if (is_gimple_assign (stmt) || is_gimple_call (stmt))
     {
-      tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
-      tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
+      tree lhs = gimple_get_lhs (stmt);
 
       /* In general, assignments with virtual operands are not useful
         for deriving ranges, with the obvious exception of calls to
         builtin functions.  */
-      if (TREE_CODE (lhs) == SSA_NAME
+      if (lhs && TREE_CODE (lhs) == SSA_NAME
          && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
              || POINTER_TYPE_P (TREE_TYPE (lhs)))
-         && ((TREE_CODE (rhs) == CALL_EXPR
-              && TREE_CODE (CALL_EXPR_FN (rhs)) == ADDR_EXPR
-              && DECL_P (TREE_OPERAND (CALL_EXPR_FN (rhs), 0))
-              && DECL_IS_BUILTIN (TREE_OPERAND (CALL_EXPR_FN (rhs), 0)))
+         && ((is_gimple_call (stmt)
+              && gimple_call_fndecl (stmt) != NULL_TREE
+              && DECL_IS_BUILTIN (gimple_call_fndecl (stmt)))
              || ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS)))
        return true;
     }
-  else if (TREE_CODE (stmt) == COND_EXPR || TREE_CODE (stmt) == SWITCH_EXPR)
+  else if (gimple_code (stmt) == GIMPLE_COND
+          || gimple_code (stmt) == GIMPLE_SWITCH)
     return true;
 
   return false;
@@ -4912,24 +5181,24 @@ vrp_initialize (void)
 
   FOR_EACH_BB (bb)
     {
-      block_stmt_iterator si;
-      tree phi;
+      gimple_stmt_iterator si;
 
-      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+      for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
        {
+         gimple phi = gsi_stmt (si);
          if (!stmt_interesting_for_vrp (phi))
            {
              tree lhs = PHI_RESULT (phi);
              set_value_range_to_varying (get_value_range (lhs));
-             DONT_SIMULATE_AGAIN (phi) = true;
+             prop_set_simulate_again (phi, false);
            }
          else
-           DONT_SIMULATE_AGAIN (phi) = false;
+           prop_set_simulate_again (phi, true);
        }
 
-      for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
+      for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
         {
-         tree stmt = bsi_stmt (si);
+         gimple stmt = gsi_stmt (si);
 
          if (!stmt_interesting_for_vrp (stmt))
            {
@@ -4937,11 +5206,11 @@ vrp_initialize (void)
              tree def;
              FOR_EACH_SSA_TREE_OPERAND (def, stmt, i, SSA_OP_DEF)
                set_value_range_to_varying (get_value_range (def));
-             DONT_SIMULATE_AGAIN (stmt) = true;
+             prop_set_simulate_again (stmt, false);
            }
          else
            {
-             DONT_SIMULATE_AGAIN (stmt) = false;
+             prop_set_simulate_again (stmt, true);
            }
        }
     }
@@ -4952,13 +5221,12 @@ vrp_initialize (void)
    the SSA name in *OUTPUT_P.  */
 
 static enum ssa_prop_result
-vrp_visit_assignment (tree stmt, tree *output_p)
+vrp_visit_assignment_or_call (gimple stmt, tree *output_p)
 {
-  tree lhs, rhs, def;
+  tree def, lhs;
   ssa_op_iter iter;
-
-  lhs = GIMPLE_STMT_OPERAND (stmt, 0);
-  rhs = GIMPLE_STMT_OPERAND (stmt, 1);
+  enum gimple_code code = gimple_code (stmt);
+  lhs = gimple_get_lhs (stmt);
 
   /* We only keep track of ranges in integral and pointer types.  */
   if (TREE_CODE (lhs) == SSA_NAME
@@ -4972,7 +5240,10 @@ vrp_visit_assignment (tree stmt, tree *output_p)
       struct loop *l;
       value_range_t new_vr = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
 
-      extract_range_from_expr (&new_vr, rhs);
+      if (code == GIMPLE_CALL)
+       extract_range_basic (&new_vr, stmt);
+      else
+       extract_range_from_assignment (&new_vr, stmt);
 
       /* If STMT is inside a loop, we may be able to know something
         else about the range of LHS by examining scalar evolution
@@ -5218,13 +5489,39 @@ compare_names (enum tree_code comp, tree n1, tree n2,
   return NULL_TREE;
 }
 
+/* Helper function for vrp_evaluate_conditional_warnv.  */
+
+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;
+
+  vr0 = (TREE_CODE (op0) == SSA_NAME) ? get_value_range (op0) : NULL;
+  vr1 = (TREE_CODE (op1) == SSA_NAME) ? get_value_range (op1) : NULL;
+
+  if (vr0 && vr1)
+    return compare_ranges (code, vr0, vr1, strict_overflow_p);
+  else if (vr0 && vr1 == NULL)
+    return compare_range_with_value (code, vr0, op1, strict_overflow_p);
+  else if (vr0 == NULL && vr1)
+    return (compare_range_with_value
+           (swap_tree_comparison (code), vr1, op0, strict_overflow_p));
+  return NULL;
+}
+
 /* Helper function for vrp_evaluate_conditional_warnv. */
 
 static tree
 vrp_evaluate_conditional_warnv_with_ops (enum tree_code code, tree op0,
                                         tree op1, bool use_equiv_p,
-                                        bool *strict_overflow_p)
+                                        bool *strict_overflow_p, bool *only_ranges)
 {
+  tree ret;
+  if (only_ranges)
+    *only_ranges = true;
+
   /* We only deal with integral and pointer types.  */
   if (!INTEGRAL_TYPE_P (TREE_TYPE (op0))
       && !POINTER_TYPE_P (TREE_TYPE (op0)))
@@ -5232,35 +5529,22 @@ vrp_evaluate_conditional_warnv_with_ops (enum tree_code code, tree op0,
 
   if (use_equiv_p)
     {
+      if (only_ranges
+          && (ret = vrp_evaluate_conditional_warnv_with_ops_using_ranges
+                     (code, op0, op1, strict_overflow_p)))
+       return ret;
+      *only_ranges = false;
       if (TREE_CODE (op0) == SSA_NAME && TREE_CODE (op1) == SSA_NAME)
-       return compare_names (code, op0, op1,
-                             strict_overflow_p);
+       return compare_names (code, op0, op1, strict_overflow_p);
       else if (TREE_CODE (op0) == SSA_NAME)
-       return compare_name_with_value (code, op0, op1,
-                                       strict_overflow_p);
+       return compare_name_with_value (code, op0, op1, strict_overflow_p);
       else if (TREE_CODE (op1) == SSA_NAME)
        return (compare_name_with_value
-               (swap_tree_comparison (code), op1, op0,
-                strict_overflow_p));
+               (swap_tree_comparison (code), op1, op0, strict_overflow_p));
     }
   else
-    {
-      value_range_t *vr0, *vr1;
-
-      vr0 = (TREE_CODE (op0) == SSA_NAME) ? get_value_range (op0) : NULL;
-      vr1 = (TREE_CODE (op1) == SSA_NAME) ? get_value_range (op1) : NULL;
-
-      if (vr0 && vr1)
-       return compare_ranges (code, vr0, vr1,
-                              strict_overflow_p);
-      else if (vr0 && vr1 == NULL)
-       return compare_range_with_value (code, vr0, op1,
-                                        strict_overflow_p);
-      else if (vr0 == NULL && vr1)
-       return (compare_range_with_value
-               (swap_tree_comparison (code), vr1, op0,
-                strict_overflow_p));
-    }
+    return vrp_evaluate_conditional_warnv_with_ops_using_ranges (code, op0, op1,
+                                                                strict_overflow_p);
   return NULL_TREE;
 }
 
@@ -5272,17 +5556,15 @@ vrp_evaluate_conditional_warnv_with_ops (enum tree_code code, tree op0,
    appropriate.  */
 
 tree
-vrp_evaluate_conditional (enum tree_code code, tree op0, tree op1, tree stmt)
+vrp_evaluate_conditional (enum tree_code code, tree op0, tree op1, gimple stmt)
 {
   bool sop;
   tree ret;
+  bool only_ranges;
 
   sop = false;
-  ret = vrp_evaluate_conditional_warnv_with_ops (code,
-                                                op0,
-                                                op1,
-                                                true,
-                                                &sop);
+  ret = vrp_evaluate_conditional_warnv_with_ops (code, op0, op1, true, &sop,
+                                                &only_ranges);
 
   if (ret && sop)
     {
@@ -5304,18 +5586,18 @@ vrp_evaluate_conditional (enum tree_code code, tree op0, tree op1, tree stmt)
 
       if (issue_strict_overflow_warning (wc))
        {
-         location_t locus;
+         location_t location;
 
-         if (!EXPR_HAS_LOCATION (stmt))
-           locus = input_location;
+         if (!gimple_has_location (stmt))
+           location = input_location;
          else
-           locus = EXPR_LOCATION (stmt);
-         warning (OPT_Wstrict_overflow, "%H%s", &locus, warnmsg);
+           location = gimple_location (stmt);
+         warning (OPT_Wstrict_overflow, "%H%s", &location, warnmsg);
        }
     }
 
   if (warn_type_limits
-      && ret
+      && ret && only_ranges
       && TREE_CODE_CLASS (code) == tcc_comparison
       && TREE_CODE (op0) == SSA_NAME)
     {
@@ -5344,14 +5626,14 @@ vrp_evaluate_conditional (enum tree_code code, tree op0, tree op1, tree stmt)
 
       if (warnmsg)
        {
-         location_t locus;
+         location_t location;
 
-         if (!EXPR_HAS_LOCATION (stmt))
-           locus = input_location;
+         if (!gimple_has_location (stmt))
+           location = input_location;
          else
-           locus = EXPR_LOCATION (stmt);
+           location = gimple_location (stmt);
 
-         warning (OPT_Wtype_limits, "%H%s", &locus, warnmsg);
+         warning (OPT_Wtype_limits, "%H%s", &location, warnmsg);
        }
     }
 
@@ -5365,13 +5647,12 @@ vrp_evaluate_conditional (enum tree_code code, tree op0, tree op1, tree stmt)
    SSA_PROP_VARYING.  */
 
 static enum ssa_prop_result
-vrp_visit_cond_stmt (tree stmt, edge *taken_edge_p)
+vrp_visit_cond_stmt (gimple stmt, edge *taken_edge_p)
 {
-  tree cond, val;
+  tree val;
   bool sop;
 
   *taken_edge_p = NULL;
-  cond = COND_EXPR_COND (stmt);
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
@@ -5379,7 +5660,7 @@ vrp_visit_cond_stmt (tree stmt, edge *taken_edge_p)
       ssa_op_iter i;
 
       fprintf (dump_file, "\nVisiting conditional with predicate: ");
-      print_generic_expr (dump_file, cond, 0);
+      print_gimple_stmt (dump_file, stmt, 0, 0);
       fprintf (dump_file, "\nWith known ranges\n");
       
       FOR_EACH_SSA_TREE_OPERAND (use, stmt, i, SSA_OP_USE)
@@ -5437,22 +5718,14 @@ vrp_visit_cond_stmt (tree stmt, edge *taken_edge_p)
      4 more predicates folded in SPEC.  */
   sop = false;
 
-  if (TREE_CODE (cond) == SSA_NAME)
-    val = vrp_evaluate_conditional_warnv_with_ops (EQ_EXPR,
-                                                  cond,
-                                                  boolean_true_node,
-                                                  false,
-                                                  &sop);
-  else
-    val = vrp_evaluate_conditional_warnv_with_ops (TREE_CODE (cond),
-                                                  TREE_OPERAND (cond, 0),
-                                                  TREE_OPERAND (cond, 1),
-                                                  false,
-                                                  &sop);
+  val = vrp_evaluate_conditional_warnv_with_ops (gimple_cond_code (stmt),
+                                                gimple_cond_lhs (stmt),
+                                                gimple_cond_rhs (stmt),
+                                                false, &sop, NULL);
   if (val)
     {
       if (!sop)
-       *taken_edge_p = find_taken_edge (bb_for_stmt (stmt), val);
+       *taken_edge_p = find_taken_edge (gimple_bb (stmt), val);
       else
        {
          if (dump_file && (dump_flags & TDF_DETAILS))
@@ -5477,7 +5750,7 @@ vrp_visit_cond_stmt (tree stmt, edge *taken_edge_p)
 
 /* Searches the case label vector VEC for the index *IDX of the CASE_LABEL
    that includes the value VAL.  The search is restricted to the range
-   [START_IDX, n - 2] where n is the size of VEC (n - 1 is the default label).
+   [START_IDX, n - 1] where n is the size of VEC.
 
    If there is a CASE_LABEL for VAL, its index is placed in IDX and true is
    returned.
@@ -5485,25 +5758,25 @@ vrp_visit_cond_stmt (tree stmt, edge *taken_edge_p)
    If there is no CASE_LABEL for VAL and the is one that is larger than VAL,
    it is placed in IDX and false is returned.
 
-   If VAL is larger than any CASE_LABEL, n - 1 is placed on IDX and false is
+   If VAL is larger than any CASE_LABEL, n is placed on IDX and false is
    returned. */
 
 static bool
-find_case_label_index (tree vec, size_t start_idx, tree val, size_t *idx)
+find_case_label_index (gimple stmt, size_t start_idx, tree val, size_t *idx)
 {
-  size_t n = TREE_VEC_LENGTH (vec);
+  size_t n = gimple_switch_num_labels (stmt);
   size_t low, high;
 
   /* Find case label for minimum of the value range or the next one.
      At each iteration we are searching in [low, high - 1]. */
 
-  for (low = start_idx, high = n - 1; high != low; )
+  for (low = start_idx, high = n; high != low; )
     {
       tree t;
       int cmp;
-      /* Note that i != high, so we never ask for n - 1. */
+      /* Note that i != high, so we never ask for n. */
       size_t i = (high + low) / 2;
-      t = TREE_VEC_ELT (vec, i);
+      t = gimple_switch_label (stmt, i);
 
       /* Cache the result of comparing CASE_LOW and val.  */
       cmp = tree_int_cst_compare (CASE_LOW (t), val);
@@ -5539,11 +5812,12 @@ find_case_label_index (tree vec, size_t start_idx, tree val, size_t *idx)
    Returns true if the default label is not needed. */
 
 static bool
-find_case_label_range (tree vec, tree min, tree max, size_t *min_idx, size_t *max_idx)
+find_case_label_range (gimple stmt, tree min, tree max, size_t *min_idx,
+                      size_t *max_idx)
 {
   size_t i, j;
-  bool min_take_default = !find_case_label_index (vec, 0, min, &i);
-  bool max_take_default = !find_case_label_index (vec, i, max, &j);
+  bool min_take_default = !find_case_label_index (stmt, 1, min, &i);
+  bool max_take_default = !find_case_label_index (stmt, i, max, &j);
 
   if (i == j
       && min_take_default
@@ -5566,20 +5840,20 @@ find_case_label_range (tree vec, tree min, tree max, size_t *min_idx, size_t *ma
 
       /* If the case label range is continuous, we do not need
         the default case label.  Verify that.  */
-      high = CASE_LOW (TREE_VEC_ELT (vec, i));
-      if (CASE_HIGH (TREE_VEC_ELT (vec, i)))
-       high = CASE_HIGH (TREE_VEC_ELT (vec, i));
+      high = CASE_LOW (gimple_switch_label (stmt, i));
+      if (CASE_HIGH (gimple_switch_label (stmt, i)))
+       high = CASE_HIGH (gimple_switch_label (stmt, i));
       for (k = i + 1; k <= j; ++k)
        {
-         low = CASE_LOW (TREE_VEC_ELT (vec, k));
+         low = CASE_LOW (gimple_switch_label (stmt, k));
          if (!integer_onep (int_const_binop (MINUS_EXPR, low, high, 0)))
            {
              take_default = true;
              break;
            }
          high = low;
-         if (CASE_HIGH (TREE_VEC_ELT (vec, k)))
-           high = CASE_HIGH (TREE_VEC_ELT (vec, k));
+         if (CASE_HIGH (gimple_switch_label (stmt, k)))
+           high = CASE_HIGH (gimple_switch_label (stmt, k));
        }
 
       *min_idx = i;
@@ -5594,16 +5868,15 @@ find_case_label_range (tree vec, tree min, tree max, size_t *min_idx, size_t *ma
    SSA_PROP_VARYING.  */
 
 static enum ssa_prop_result
-vrp_visit_switch_stmt (tree stmt, edge *taken_edge_p)
+vrp_visit_switch_stmt (gimple stmt, edge *taken_edge_p)
 {
   tree op, val;
   value_range_t *vr;
   size_t i = 0, j = 0, n;
-  tree vec;
   bool take_default;
 
   *taken_edge_p = NULL;
-  op = TREE_OPERAND (stmt, 0);
+  op = gimple_switch_index (stmt);
   if (TREE_CODE (op) != SSA_NAME)
     return SSA_PROP_VARYING;
 
@@ -5622,26 +5895,26 @@ vrp_visit_switch_stmt (tree stmt, edge *taken_edge_p)
     return SSA_PROP_VARYING;
 
   /* Find the single edge that is taken from the switch expression.  */
-  vec = SWITCH_LABELS (stmt);
-  n = TREE_VEC_LENGTH (vec);
+  n = gimple_switch_num_labels (stmt);
 
-  take_default = !find_case_label_range (vec, vr->min, vr->max, &i, &j);
+  take_default = !find_case_label_range (stmt, vr->min, vr->max, &i, &j);
 
   /* Check if the range spans no CASE_LABEL. If so, we only reach the default
      label */
   if (j < i)
     {
       gcc_assert (take_default);
-      val = TREE_VEC_ELT (vec, n - 1);
+      val = gimple_switch_default_label (stmt);
     }
   else
     {
       /* Check if labels with index i to j and maybe the default label
         are all reaching the same label.  */
 
-      val = TREE_VEC_ELT (vec, i);
+      val = gimple_switch_label (stmt, i);
       if (take_default
-         && CASE_LABEL (TREE_VEC_ELT (vec, n - 1)) != CASE_LABEL (val))
+         && CASE_LABEL (gimple_switch_default_label (stmt))
+         != CASE_LABEL (val))
        {
          if (dump_file && (dump_flags & TDF_DETAILS))
            fprintf (dump_file, "  not a single destination for this "
@@ -5650,7 +5923,7 @@ vrp_visit_switch_stmt (tree stmt, edge *taken_edge_p)
        }
       for (++i; i <= j; ++i)
         {
-          if (CASE_LABEL (TREE_VEC_ELT (vec, i)) != CASE_LABEL (val))
+          if (CASE_LABEL (gimple_switch_label (stmt, i)) != CASE_LABEL (val))
            {
              if (dump_file && (dump_flags & TDF_DETAILS))
                fprintf (dump_file, "  not a single destination for this "
@@ -5660,7 +5933,7 @@ vrp_visit_switch_stmt (tree stmt, edge *taken_edge_p)
         }
     }
 
-  *taken_edge_p = find_edge (bb_for_stmt (stmt),
+  *taken_edge_p = find_edge (gimple_bb (stmt),
                             label_to_block (CASE_LABEL (val)));
 
   if (dump_file && (dump_flags & TDF_DETAILS))
@@ -5683,37 +5956,33 @@ vrp_visit_switch_stmt (tree stmt, edge *taken_edge_p)
    If STMT produces a varying value, return SSA_PROP_VARYING.  */
 
 static enum ssa_prop_result
-vrp_visit_stmt (tree 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;
-  stmt_ann_t ann;
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
       fprintf (dump_file, "\nVisiting statement:\n");
-      print_generic_stmt (dump_file, stmt, dump_flags);
+      print_gimple_stmt (dump_file, stmt, 0, dump_flags);
       fprintf (dump_file, "\n");
     }
 
-  ann = stmt_ann (stmt);
-  if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT)
+  if (is_gimple_assign (stmt) || is_gimple_call (stmt))
     {
-      tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
-
       /* In general, assignments with virtual operands are not useful
         for deriving ranges, with the obvious exception of calls to
         builtin functions.  */
-      if ((TREE_CODE (rhs) == CALL_EXPR
-          && TREE_CODE (CALL_EXPR_FN (rhs)) == ADDR_EXPR
-          && DECL_P (TREE_OPERAND (CALL_EXPR_FN (rhs), 0))
-          && DECL_IS_BUILTIN (TREE_OPERAND (CALL_EXPR_FN (rhs), 0)))
+
+      if ((is_gimple_call (stmt)
+          && gimple_call_fndecl (stmt) != NULL_TREE
+          && DECL_IS_BUILTIN (gimple_call_fndecl (stmt)))
          || ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
-       return vrp_visit_assignment (stmt, output_p);
+       return vrp_visit_assignment_or_call (stmt, output_p);
     }
-  else if (TREE_CODE (stmt) == COND_EXPR)
+  else if (gimple_code (stmt) == GIMPLE_COND)
     return vrp_visit_cond_stmt (stmt, taken_edge_p);
-  else if (TREE_CODE (stmt) == SWITCH_EXPR)
+  else if (gimple_code (stmt) == GIMPLE_SWITCH)
     return vrp_visit_switch_stmt (stmt, taken_edge_p);
 
   /* All other statements produce nothing of interest for VRP, so mark
@@ -5876,9 +6145,9 @@ give_up:
    value ranges, set a new range for the LHS of PHI.  */
 
 static enum ssa_prop_result
-vrp_visit_phi_node (tree phi)
+vrp_visit_phi_node (gimple phi)
 {
-  int i;
+  size_t i;
   tree lhs = PHI_RESULT (phi);
   value_range_t *lhs_vr = get_value_range (lhs);
   value_range_t vr_result = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
@@ -5889,19 +6158,19 @@ vrp_visit_phi_node (tree phi)
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
       fprintf (dump_file, "\nVisiting PHI node: ");
-      print_generic_expr (dump_file, phi, dump_flags);
+      print_gimple_stmt (dump_file, phi, 0, dump_flags);
     }
 
   edges = 0;
-  for (i = 0; i < PHI_NUM_ARGS (phi); i++)
+  for (i = 0; i < gimple_phi_num_args (phi); i++)
     {
-      edge e = PHI_ARG_EDGE (phi, i);
+      edge e = gimple_phi_arg_edge (phi, i);
 
       if (dump_file && (dump_flags & TDF_DETAILS))
        {
          fprintf (dump_file,
              "\n    Argument #%d (%d -> %d %sexecutable)\n",
-             i, e->src->index, e->dest->index,
+             (int) i, e->src->index, e->dest->index,
              (e->flags & EDGE_EXECUTABLE) ? "" : "not ");
        }
 
@@ -6022,18 +6291,154 @@ varying:
   return SSA_PROP_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)
+{
+  enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
+  tree val = NULL;
+  tree op0, op1;
+  value_range_t *vr;
+  bool sop = false;
+  bool need_conversion;
+
+  op0 = gimple_assign_rhs1 (stmt);
+  if (TYPE_PRECISION (TREE_TYPE (op0)) != 1)
+    {
+      if (TREE_CODE (op0) != SSA_NAME)
+       return false;
+      vr = get_value_range (op0);
+
+      val = compare_range_with_value (GE_EXPR, vr, integer_zero_node, &sop);
+      if (!val || !integer_onep (val))
+        return false;
+
+      val = compare_range_with_value (LE_EXPR, vr, integer_one_node, &sop);
+      if (!val || !integer_onep (val))
+        return false;
+    }
+
+  if (rhs_code == TRUTH_NOT_EXPR)
+    {
+      rhs_code = NE_EXPR;
+      op1 = build_int_cst (TREE_TYPE (op0), 1);
+    }
+  else
+    {
+      op1 = gimple_assign_rhs2 (stmt);
+
+      /* Reduce number of cases to handle.  */
+      if (is_gimple_min_invariant (op1))
+       {
+          /* Exclude anything that should have been already folded.  */
+         if (rhs_code != EQ_EXPR
+             && rhs_code != NE_EXPR
+             && rhs_code != TRUTH_XOR_EXPR)
+           return false;
+
+         if (!integer_zerop (op1)
+             && !integer_onep (op1)
+             && !integer_all_onesp (op1))
+           return false;
+
+         /* Limit the number of cases we have to consider.  */
+         if (rhs_code == EQ_EXPR)
+           {
+             rhs_code = NE_EXPR;
+             op1 = fold_unary (TRUTH_NOT_EXPR, TREE_TYPE (op1), op1);
+           }
+       }
+      else
+       {
+         /* Punt on A == B as there is no BIT_XNOR_EXPR.  */
+         if (rhs_code == EQ_EXPR)
+           return false;
+
+         if (TYPE_PRECISION (TREE_TYPE (op1)) != 1)
+           {
+             vr = get_value_range (op1);
+             val = compare_range_with_value (GE_EXPR, vr, integer_zero_node, &sop);
+             if (!val || !integer_onep (val))
+               return false;
+
+             val = compare_range_with_value (LE_EXPR, vr, integer_one_node, &sop);
+             if (!val || !integer_onep (val))
+               return false;
+           }
+       }
+    }
+
+  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);
+
+      if (rhs_code == TRUTH_AND_EXPR || rhs_code == TRUTH_OR_EXPR)
+        warning_at (location, OPT_Wstrict_overflow,
+                   _("assuming signed overflow does not occur when "
+                     "simplifying && or || to & or |"));
+      else
+        warning_at (location, OPT_Wstrict_overflow,
+                   _("assuming signed overflow does not occur when "
+                     "simplifying ==, != or ! to identity or ^"));
+    }
+
+  need_conversion =
+    !useless_type_conversion_p (TREE_TYPE (gimple_assign_lhs (stmt)),
+                               TREE_TYPE (op0));
+
+  switch (rhs_code)
+    {
+    case TRUTH_AND_EXPR:
+      rhs_code = BIT_AND_EXPR;
+      break;
+    case TRUTH_OR_EXPR:
+      rhs_code = BIT_IOR_EXPR;
+      break;
+    case TRUTH_XOR_EXPR:
+    case NE_EXPR:
+      if (integer_zerop (op1))
+       {
+         gimple_assign_set_rhs_with_ops (gsi,
+                                         need_conversion ? NOP_EXPR : SSA_NAME,
+                                         op0, NULL);
+         update_stmt (gsi_stmt (*gsi));
+         return true;
+       }
+
+      rhs_code = BIT_XOR_EXPR;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  if (need_conversion)
+    return false;
+
+  gimple_assign_set_rhs_with_ops (gsi, rhs_code, op0, op1);
+  update_stmt (gsi_stmt (*gsi));
+  return true;
+}
+
 /* 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.  */
 
-static void
-simplify_div_or_mod_using_ranges (tree stmt, tree rhs, enum tree_code rhs_code)
+static bool
+simplify_div_or_mod_using_ranges (gimple stmt)
 {
+  enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
   tree val = NULL;
-  tree op = TREE_OPERAND (rhs, 0);
-  value_range_t *vr = get_value_range (TREE_OPERAND (rhs, 0));
+  tree op0 = gimple_assign_rhs1 (stmt);
+  tree op1 = gimple_assign_rhs2 (stmt);
+  value_range_t *vr = get_value_range (gimple_assign_rhs1 (stmt));
 
-  if (TYPE_UNSIGNED (TREE_TYPE (op)))
+  if (TYPE_UNSIGNED (TREE_TYPE (op0)))
     {
       val = integer_one_node;
     }
@@ -6048,54 +6453,59 @@ simplify_div_or_mod_using_ranges (tree stmt, tree rhs, enum tree_code rhs_code)
          && integer_onep (val)
          && issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_MISC))
        {
-         location_t locus;
+         location_t location;
 
-         if (!EXPR_HAS_LOCATION (stmt))
-           locus = input_location;
+         if (!gimple_has_location (stmt))
+           location = input_location;
          else
-           locus = EXPR_LOCATION (stmt);
+           location = gimple_location (stmt);
          warning (OPT_Wstrict_overflow,
                   ("%Hassuming signed overflow does not occur when "
                    "simplifying / or %% to >> or &"),
-                  &locus);
+                  &location);
        }
     }
 
   if (val && integer_onep (val))
     {
       tree t;
-      tree op0 = TREE_OPERAND (rhs, 0);
-      tree op1 = TREE_OPERAND (rhs, 1);
 
       if (rhs_code == TRUNC_DIV_EXPR)
        {
          t = build_int_cst (NULL_TREE, tree_log2 (op1));
-         t = build2 (RSHIFT_EXPR, TREE_TYPE (op0), op0, t);
+         gimple_assign_set_rhs_code (stmt, RSHIFT_EXPR);
+         gimple_assign_set_rhs1 (stmt, op0);
+         gimple_assign_set_rhs2 (stmt, t);
        }
       else
        {
          t = build_int_cst (TREE_TYPE (op1), 1);
          t = int_const_binop (MINUS_EXPR, op1, t, 0);
          t = fold_convert (TREE_TYPE (op0), t);
-         t = build2 (BIT_AND_EXPR, TREE_TYPE (op0), op0, t);
+
+         gimple_assign_set_rhs_code (stmt, BIT_AND_EXPR);
+         gimple_assign_set_rhs1 (stmt, op0);
+         gimple_assign_set_rhs2 (stmt, t);
        }
 
-      GIMPLE_STMT_OPERAND (stmt, 1) = t;
       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 void
-simplify_abs_using_ranges (tree stmt, tree rhs)
+static bool
+simplify_abs_using_ranges (gimple stmt)
 {
   tree val = NULL;
-  tree op = TREE_OPERAND (rhs, 0);
+  tree op = gimple_assign_rhs1 (stmt);
   tree type = TREE_TYPE (op);
-  value_range_t *vr = get_value_range (TREE_OPERAND (rhs, 0));
+  value_range_t *vr = get_value_range (op);
 
   if (TYPE_UNSIGNED (type))
     {
@@ -6124,31 +6534,31 @@ simplify_abs_using_ranges (tree stmt, tree rhs)
       if (val
          && (integer_onep (val) || integer_zerop (val)))
        {
-         tree t;
-
          if (sop && issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_MISC))
            {
-             location_t locus;
+             location_t location;
 
-             if (!EXPR_HAS_LOCATION (stmt))
-               locus = input_location;
+             if (!gimple_has_location (stmt))
+               location = input_location;
              else
-               locus = EXPR_LOCATION (stmt);
+               location = gimple_location (stmt);
              warning (OPT_Wstrict_overflow,
                       ("%Hassuming signed overflow does not occur when "
                        "simplifying abs (X) to X or -X"),
-                      &locus);
+                      &location);
            }
 
+         gimple_assign_set_rhs1 (stmt, op);
          if (integer_onep (val))
-           t = build1 (NEGATE_EXPR, TREE_TYPE (op), op);
+           gimple_assign_set_rhs_code (stmt, NEGATE_EXPR);
          else
-           t = op;
-
-         GIMPLE_STMT_OPERAND (stmt, 1) = t;
+           gimple_assign_set_rhs_code (stmt, SSA_NAME);
          update_stmt (stmt);
+         return true;
        }
     }
+
+  return false;
 }
 
 /* We are comparing trees OP0 and OP1 using COND_CODE.  OP0 has
@@ -6223,13 +6633,12 @@ test_for_singularity (enum tree_code cond_code, tree op0,
    test if the range information indicates only one value can satisfy
    the original conditional.  */
 
-static void
-simplify_cond_using_ranges (tree stmt)
+static bool
+simplify_cond_using_ranges (gimple stmt)
 {
-  tree cond = COND_EXPR_COND (stmt);
-  tree op0 = TREE_OPERAND (cond, 0);
-  tree op1 = TREE_OPERAND (cond, 1);
-  enum tree_code cond_code = TREE_CODE (cond);
+  tree op0 = gimple_cond_lhs (stmt);
+  tree op1 = gimple_cond_rhs (stmt);
+  enum tree_code cond_code = gimple_cond_code (stmt);
 
   if (cond_code != NE_EXPR
       && cond_code != EQ_EXPR
@@ -6243,116 +6652,123 @@ simplify_cond_using_ranges (tree stmt)
         able to simplify this conditional. */
       if (vr->type == VR_RANGE)
        {
-         tree new = test_for_singularity (cond_code, op0, op1, vr);
+         tree new_tree = test_for_singularity (cond_code, op0, op1, vr);
 
-         if (new)
+         if (new_tree)
            {
              if (dump_file)
                {
                  fprintf (dump_file, "Simplified relational ");
-                 print_generic_expr (dump_file, cond, 0);
+                 print_gimple_stmt (dump_file, stmt, 0, 0);
                  fprintf (dump_file, " into ");
                }
 
-             COND_EXPR_COND (stmt)
-               = build2 (EQ_EXPR, boolean_type_node, op0, new);
+             gimple_cond_set_code (stmt, EQ_EXPR);
+             gimple_cond_set_lhs (stmt, op0);
+             gimple_cond_set_rhs (stmt, new_tree);
+
              update_stmt (stmt);
 
              if (dump_file)
                {
-                 print_generic_expr (dump_file, COND_EXPR_COND (stmt), 0);
+                 print_gimple_stmt (dump_file, stmt, 0, 0);
                  fprintf (dump_file, "\n");
                }
-             return;
 
+             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 = test_for_singularity (cond_code, op0, op1, vr);
+         new_tree = test_for_singularity (cond_code, op0, op1, vr);
 
-         if (new)
+         if (new_tree)
            {
              if (dump_file)
                {
                  fprintf (dump_file, "Simplified relational ");
-                 print_generic_expr (dump_file, cond, 0);
+                 print_gimple_stmt (dump_file, stmt, 0, 0);
                  fprintf (dump_file, " into ");
                }
 
-             COND_EXPR_COND (stmt)
-               = build2 (NE_EXPR, boolean_type_node, op0, new);
+             gimple_cond_set_code (stmt, NE_EXPR);
+             gimple_cond_set_lhs (stmt, op0);
+             gimple_cond_set_rhs (stmt, new_tree);
+
              update_stmt (stmt);
 
              if (dump_file)
                {
-                 print_generic_expr (dump_file, COND_EXPR_COND (stmt), 0);
+                 print_gimple_stmt (dump_file, stmt, 0, 0);
                  fprintf (dump_file, "\n");
                }
-             return;
 
+             return true;
            }
        }
     }
+
+  return false;
 }
 
 /* Simplify a switch statement using the value range of the switch
    argument.  */
 
-static void
-simplify_switch_using_ranges (tree stmt)
+static bool
+simplify_switch_using_ranges (gimple stmt)
 {
-  tree op = TREE_OPERAND (stmt, 0);
+  tree op = gimple_switch_index (stmt);
   value_range_t *vr;
   bool take_default;
   edge e;
   edge_iterator ei;
   size_t i = 0, j = 0, n, n2;
-  tree vec, vec2;
+  tree vec2;
   switch_update su;
 
   if (TREE_CODE (op) != SSA_NAME)
-    return;
+    return false;
 
   vr = get_value_range (op);
 
   /* We can only handle integer ranges.  */
   if (vr->type != VR_RANGE
       || symbolic_range_p (vr))
-    return;
+    return false;
 
   /* Find case label for min/max of the value range.  */
-  vec = SWITCH_LABELS (stmt);
-  n = TREE_VEC_LENGTH (vec);
-  take_default = !find_case_label_range (vec, vr->min, vr->max, &i, &j);
+  n = gimple_switch_num_labels (stmt);
+  take_default = !find_case_label_range (stmt, vr->min, vr->max, &i, &j);
 
   /* Bail out if this is just all edges taken.  */
-  if (i == 0
-      && j == n - 2
+  if (i == 1
+      && j == n - 1
       && take_default)
-    return;
+    return false;
 
   /* Build a new vector of taken case labels.  */
   vec2 = make_tree_vec (j - i + 1 + (int)take_default);
-  for (n2 = 0; i <= j; ++i, ++n2)
-    TREE_VEC_ELT (vec2, n2) = TREE_VEC_ELT (vec, i);
+  n2 = 0;
 
   /* Add the default edge, if necessary.  */
   if (take_default)
-    TREE_VEC_ELT (vec2, n2++) = TREE_VEC_ELT (vec, n - 1);
+    TREE_VEC_ELT (vec2, n2++) = gimple_switch_default_label (stmt);
+
+  for (; i <= j; ++i, ++n2)
+    TREE_VEC_ELT (vec2, n2) = gimple_switch_label (stmt, i);
 
   /* Mark needed edges.  */
   for (i = 0; i < n2; ++i)
     {
-      e = find_edge (bb_for_stmt (stmt),
+      e = find_edge (gimple_bb (stmt),
                     label_to_block (CASE_LABEL (TREE_VEC_ELT (vec2, i))));
       e->aux = (void *)-1;
     }
 
   /* Queue not needed edges for later removal.  */
-  FOR_EACH_EDGE (e, ei, bb_for_stmt (stmt)->succs)
+  FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->succs)
     {
       if (e->aux == (void *)-1)
        {
@@ -6371,37 +6787,62 @@ simplify_switch_using_ranges (tree stmt)
   su.stmt = stmt;
   su.vec = vec2;
   VEC_safe_push (switch_update, heap, to_update_switch_stmts, &su);
+  return false;
 }
 
 /* Simplify STMT using ranges if possible.  */
 
-void
-simplify_stmt_using_ranges (tree stmt)
+bool
+simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
 {
-  if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT)
+  gimple stmt = gsi_stmt (*gsi);
+  if (is_gimple_assign (stmt))
     {
-      tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
-      enum tree_code rhs_code = TREE_CODE (rhs);
+      enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
+
+      switch (rhs_code)
+       {
+       case EQ_EXPR:
+       case NE_EXPR:
+       case TRUTH_NOT_EXPR:
+       case TRUTH_AND_EXPR:
+       case TRUTH_OR_EXPR:
+        case TRUTH_XOR_EXPR:
+          /* Transform EQ_EXPR, NE_EXPR, TRUTH_NOT_EXPR into BIT_XOR_EXPR
+            or identity if the RHS is zero or one, and the LHS are known
+            to be boolean values.  Transform all TRUTH_*_EXPR into
+             BIT_*_EXPR if both arguments are known to be boolean values.  */
+         if (INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt))))
+           return simplify_truth_ops_using_ranges (gsi, stmt);
+         break;
 
       /* 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.  */
-      if ((rhs_code == TRUNC_DIV_EXPR || rhs_code == TRUNC_MOD_EXPR)
-         && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (rhs, 0)))
-         && integer_pow2p (TREE_OPERAND (rhs, 1)))
-       simplify_div_or_mod_using_ranges (stmt, rhs, rhs_code);
+       case TRUNC_DIV_EXPR:
+       case TRUNC_MOD_EXPR:
+         if (INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt)))
+             && integer_pow2p (gimple_assign_rhs2 (stmt)))
+           return simplify_div_or_mod_using_ranges (stmt);
+         break;
 
       /* Transform ABS (X) into X or -X as appropriate.  */
-      if (rhs_code == ABS_EXPR
-         && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME
-         && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (rhs, 0))))
-       simplify_abs_using_ranges (stmt, rhs);
-    }
-  else if (TREE_CODE (stmt) == COND_EXPR
-          && COMPARISON_CLASS_P (COND_EXPR_COND (stmt)))
-    simplify_cond_using_ranges (stmt);
-  else if (TREE_CODE (stmt) == SWITCH_EXPR)
-    simplify_switch_using_ranges (stmt);
+       case ABS_EXPR:
+         if (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
+             && INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt))))
+           return simplify_abs_using_ranges (stmt);
+         break;
+
+       default:
+         break;
+       }
+    }
+  else if (gimple_code (stmt) == GIMPLE_COND)
+    return simplify_cond_using_ranges (stmt);
+  else if (gimple_code (stmt) == GIMPLE_SWITCH)
+    return simplify_switch_using_ranges (stmt);
+
+  return false;
 }
 
 /* Stack of dest,src equivalency pairs that need to be restored after
@@ -6417,30 +6858,21 @@ static VEC(tree,heap) *stack;
    for any overflow warnings.  */
 
 static tree
-simplify_stmt_for_jump_threading (tree stmt, tree within_stmt)
+simplify_stmt_for_jump_threading (gimple stmt, gimple within_stmt)
 {
-  tree conditional;
   /* We only use VRP information to simplify conditionals.  This is
      overly conservative, but it's unclear if doing more would be
      worth the compile time cost.  */
-  if (TREE_CODE (stmt) != COND_EXPR)
+  if (gimple_code (stmt) != GIMPLE_COND)
     return NULL;
 
-  conditional = COND_EXPR_COND (stmt);
-  if (TREE_CODE (conditional) == SSA_NAME)
-    return vrp_evaluate_conditional (EQ_EXPR,
-                                    conditional,
-                                    boolean_true_node,
-                                    within_stmt);
-  else
-    return vrp_evaluate_conditional (TREE_CODE (conditional),
-                                    TREE_OPERAND (conditional, 0),
-                                    TREE_OPERAND (conditional, 1),
-                                    within_stmt);
+  return vrp_evaluate_conditional (gimple_cond_code (stmt),
+                                  gimple_cond_lhs (stmt),
+                                  gimple_cond_rhs (stmt), within_stmt);
 }
 
 /* Blocks which have more than one predecessor and more than
-   one successor present jump threading opportunities.  ie,
+   one successor present jump threading opportunities, i.e.,
    when the block is reached from a specific predecessor, we
    may be able to determine which of the outgoing edges will
    be traversed.  When this optimization applies, we are able
@@ -6463,7 +6895,7 @@ static void
 identify_jump_threads (void)
 {
   basic_block bb;
-  tree dummy;
+  gimple dummy;
   int i;
   edge e;
 
@@ -6491,8 +6923,9 @@ identify_jump_threads (void)
   /* To avoid lots of silly node creation, we create a single
      conditional and just modify it in-place when attempting to
      thread jumps.  */
-  dummy = build2 (EQ_EXPR, boolean_type_node, NULL, NULL);
-  dummy = build3 (COND_EXPR, void_type_node, dummy, NULL, NULL);
+  dummy = gimple_build_cond (EQ_EXPR,
+                            integer_zero_node, integer_zero_node,
+                            NULL, NULL);
 
   /* Walk through all the blocks finding those which present a
      potential jump threading opportunity.  We could set this up
@@ -6502,7 +6935,7 @@ identify_jump_threads (void)
      point in compilation.  */
   FOR_EACH_BB (bb)
     {
-      tree last, cond;
+      gimple last;
 
       /* If the generic jump threading code does not find this block
         interesting, then there is nothing to do.  */
@@ -6512,21 +6945,17 @@ identify_jump_threads (void)
       /* 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 = bsi_stmt (bsi_last (bb));
-      if (TREE_CODE (last) != COND_EXPR)
+      last = gsi_stmt (gsi_last_bb (bb));
+      if (gimple_code (last) != GIMPLE_COND)
        continue;
 
       /* We're basically looking for any kind of conditional with
         integral type arguments.  */
-      cond = COND_EXPR_COND (last);
-      if ((TREE_CODE (cond) == SSA_NAME
-          && INTEGRAL_TYPE_P (TREE_TYPE (cond)))
-         || (COMPARISON_CLASS_P (cond)
-             && TREE_CODE (TREE_OPERAND (cond, 0)) == SSA_NAME
-             && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (cond, 0)))
-             && (TREE_CODE (TREE_OPERAND (cond, 1)) == SSA_NAME
-                 || is_gimple_min_invariant (TREE_OPERAND (cond, 1)))
-             && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (cond, 1)))))
+      if (TREE_CODE (gimple_cond_lhs (last)) == SSA_NAME
+         && INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (last)))
+         && (TREE_CODE (gimple_cond_rhs (last)) == SSA_NAME
+             || is_gimple_min_invariant (gimple_cond_rhs (last)))
+         && INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_rhs (last))))
        {
          edge_iterator ei;
 
@@ -6541,8 +6970,7 @@ identify_jump_threads (void)
              if (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX))
                continue;
 
-             thread_across_edge (dummy, e, true,
-                                 &stack,
+             thread_across_edge (dummy, e, true, &stack,
                                  simplify_stmt_for_jump_threading);
            }
        }
@@ -6718,7 +7146,20 @@ execute_vrp (void)
     remove_edge (e);
   /* Update SWITCH_EXPR case label vector.  */
   for (i = 0; VEC_iterate (switch_update, to_update_switch_stmts, i, su); ++i)
-    SWITCH_LABELS (su->stmt) = su->vec;
+    {
+      size_t j;
+      size_t n = TREE_VEC_LENGTH (su->vec);
+      tree label;
+      gimple_switch_set_num_labels (su->stmt, n);
+      for (j = 0; j < n; j++)
+       gimple_switch_set_label (su->stmt, j, TREE_VEC_ELT (su->vec, j));
+      /* As we may have replaced the default label with a regular one
+        make sure to make it a real default label again.  This ensures
+        optimal expansion.  */
+      label = gimple_switch_default_label (su->stmt);
+      CASE_LOW (label) = NULL_TREE;
+      CASE_HIGH (label) = NULL_TREE;
+    }
 
   if (VEC_length (edge, to_remove_edges) > 0)
     free_dominance_info (CDI_DOMINATORS);
@@ -6728,7 +7169,6 @@ execute_vrp (void)
 
   scev_finalize ();
   loop_optimizer_finalize ();
-
   return 0;
 }