OSDN Git Service

PR target/23552
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index af3f01c..0190c32 100644 (file)
@@ -16,8 +16,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 /*@@ This file should be rewritten to use an arbitrary precision
   @@ representation for "struct tree_int_cst" and "struct tree_real_cst".
@@ -132,7 +132,6 @@ static bool reorder_operands_p (tree, tree);
 static tree fold_negate_const (tree, tree);
 static tree fold_not_const (tree, tree);
 static tree fold_relational_const (enum tree_code, tree, tree, tree);
-static bool tree_expr_nonzero_p (tree);
 
 /* We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring
    overflow.  Suppose A, B and SUM have the same respective signs as A1, B1,
@@ -2020,7 +2019,7 @@ fold_convert (tree type, tree arg)
       gcc_assert (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)));
       gcc_assert (INTEGRAL_TYPE_P (orig) || POINTER_TYPE_P (orig)
                  || TREE_CODE (orig) == VECTOR_TYPE);
-      return fold_build1 (NOP_EXPR, type, arg);
+      return fold_build1 (VIEW_CONVERT_EXPR, type, arg);
 
     case VOID_TYPE:
       return fold_build1 (CONVERT_EXPR, type, fold_ignored_result (arg));
@@ -2030,7 +2029,7 @@ fold_convert (tree type, tree arg)
     }
 }
 \f
-/* Return false if expr can be assumed not to be an value, true
+/* Return false if expr can be assumed not to be an lvalue, true
    otherwise.  */
 
 static bool
@@ -2169,6 +2168,10 @@ swap_tree_comparison (enum tree_code code)
     {
     case EQ_EXPR:
     case NE_EXPR:
+    case ORDERED_EXPR:
+    case UNORDERED_EXPR:
+    case LTGT_EXPR:
+    case UNEQ_EXPR:
       return code;
     case GT_EXPR:
       return LT_EXPR;
@@ -2178,6 +2181,14 @@ swap_tree_comparison (enum tree_code code)
       return GT_EXPR;
     case LE_EXPR:
       return GE_EXPR;
+    case UNGT_EXPR:
+      return UNLT_EXPR;
+    case UNGE_EXPR:
+      return UNLE_EXPR;
+    case UNLT_EXPR:
+      return UNGT_EXPR;
+    case UNLE_EXPR:
+      return UNGE_EXPR;
     default:
       gcc_unreachable ();
     }
@@ -3329,11 +3340,11 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type,
       TREE_THIS_VOLATILE (lhs) = 1;
     }
 
-  rhs = fold (const_binop (BIT_AND_EXPR,
-                          const_binop (LSHIFT_EXPR,
-                                       fold_convert (unsigned_type, rhs),
-                                       size_int (lbitpos), 0),
-                          mask, 0));
+  rhs = const_binop (BIT_AND_EXPR,
+                    const_binop (LSHIFT_EXPR,
+                                 fold_convert (unsigned_type, rhs),
+                                 size_int (lbitpos), 0),
+                    mask, 0);
 
   return build2 (code, compare_type,
                 build2 (BIT_AND_EXPR, unsigned_type, lhs, mask),
@@ -3918,6 +3929,15 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high)
   tree etype = TREE_TYPE (exp);
   tree value;
 
+#ifdef HAVE_canonicalize_funcptr_for_compare
+  /* Disable this optimization for function pointer expressions
+     on targets that require function pointer canonicalization.  */
+  if (HAVE_canonicalize_funcptr_for_compare
+      && TREE_CODE (etype) == POINTER_TYPE
+      && TREE_CODE (TREE_TYPE (etype)) == FUNCTION_TYPE)
+    return NULL_TREE;
+#endif
+
   if (! in_p)
     {
       value = build_range_check (type, exp, 1, low, high);
@@ -3931,13 +3951,16 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high)
     return fold_convert (type, integer_one_node);
 
   if (low == 0)
-    return fold_build2 (LE_EXPR, type, exp, high);
+    return fold_build2 (LE_EXPR, type, exp,
+                       fold_convert (etype, high));
 
   if (high == 0)
-    return fold_build2 (GE_EXPR, type, exp, low);
+    return fold_build2 (GE_EXPR, type, exp,
+                       fold_convert (etype, low));
 
   if (operand_equal_p (low, high, 0))
-    return fold_build2 (EQ_EXPR, type, exp, low);
+    return fold_build2 (EQ_EXPR, type, exp,
+                       fold_convert (etype, low));
 
   if (integer_zerop (low))
     {
@@ -6445,7 +6468,7 @@ try_move_mult_to_index (enum tree_code code, tree addr, tree op1)
                                                     TREE_OPERAND (pos, 1)),
                                       fold_convert (itype, delta));
 
-  return build1 (ADDR_EXPR, TREE_TYPE (addr), ret);
+  return fold_build1 (ADDR_EXPR, TREE_TYPE (addr), ret);
 }
 
 
@@ -6493,300 +6516,6 @@ fold_to_nonsharp_ineq_using_bound (tree ineq, tree bound)
   return fold_build2 (GE_EXPR, type, a, y);
 }
 
-/* Fold complex addition when both components are accessible by parts.
-   Return non-null if successful.  CODE should be PLUS_EXPR for addition,
-   or MINUS_EXPR for subtraction.  */
-
-static tree
-fold_complex_add (tree type, tree ac, tree bc, enum tree_code code)
-{
-  tree ar, ai, br, bi, rr, ri, inner_type;
-
-  if (TREE_CODE (ac) == COMPLEX_EXPR)
-    ar = TREE_OPERAND (ac, 0), ai = TREE_OPERAND (ac, 1);
-  else if (TREE_CODE (ac) == COMPLEX_CST)
-    ar = TREE_REALPART (ac), ai = TREE_IMAGPART (ac);
-  else
-    return NULL;
-
-  if (TREE_CODE (bc) == COMPLEX_EXPR)
-    br = TREE_OPERAND (bc, 0), bi = TREE_OPERAND (bc, 1);
-  else if (TREE_CODE (bc) == COMPLEX_CST)
-    br = TREE_REALPART (bc), bi = TREE_IMAGPART (bc);
-  else
-    return NULL;
-
-  inner_type = TREE_TYPE (type);
-
-  rr = fold_build2 (code, inner_type, ar, br); 
-  ri = fold_build2 (code, inner_type, ai, bi); 
-
-  return fold_build2 (COMPLEX_EXPR, type, rr, ri);
-}
-
-/* Perform some simplifications of complex multiplication when one or more
-   of the components are constants or zeros.  Return non-null if successful.  */
-
-tree
-fold_complex_mult_parts (tree type, tree ar, tree ai, tree br, tree bi)
-{
-  tree rr, ri, inner_type, zero;
-  bool ar0, ai0, br0, bi0, bi1;
-
-  inner_type = TREE_TYPE (type);
-  zero = NULL;
-
-  if (SCALAR_FLOAT_TYPE_P (inner_type))
-    {
-      ar0 = ai0 = br0 = bi0 = bi1 = false;
-
-      /* We're only interested in +0.0 here, thus we don't use real_zerop.  */
-
-      if (TREE_CODE (ar) == REAL_CST
-         && REAL_VALUES_IDENTICAL (TREE_REAL_CST (ar), dconst0))
-       ar0 = true, zero = ar;
-
-      if (TREE_CODE (ai) == REAL_CST
-         && REAL_VALUES_IDENTICAL (TREE_REAL_CST (ai), dconst0))
-       ai0 = true, zero = ai;
-
-      if (TREE_CODE (br) == REAL_CST
-         && REAL_VALUES_IDENTICAL (TREE_REAL_CST (br), dconst0))
-       br0 = true, zero = br;
-
-      if (TREE_CODE (bi) == REAL_CST)
-       {
-         if (REAL_VALUES_IDENTICAL (TREE_REAL_CST (bi), dconst0))
-           bi0 = true, zero = bi;
-         else if (REAL_VALUES_IDENTICAL (TREE_REAL_CST (bi), dconst1))
-           bi1 = true;
-       }
-    }
-  else
-    {
-      ar0 = integer_zerop (ar);
-      if (ar0)
-       zero = ar;
-      ai0 = integer_zerop (ai);
-      if (ai0)
-       zero = ai;
-      br0 = integer_zerop (br);
-      if (br0)
-       zero = br;
-      bi0 = integer_zerop (bi);
-      if (bi0)
-       {
-         zero = bi;
-         bi1 = false;
-       }
-      else
-       bi1 = integer_onep (bi);
-    }
-
-  /* We won't optimize anything below unless something is zero.  */
-  if (zero == NULL)
-    return NULL;
-
-  if (ai0 && br0 && bi1)
-    {
-      rr = zero;
-      ri = ar;
-    }
-  else if (ai0 && bi0)
-    {
-      rr = fold_build2 (MULT_EXPR, inner_type, ar, br);
-      ri = zero;
-    }
-  else if (ai0 && br0)
-    {
-      rr = zero;
-      ri = fold_build2 (MULT_EXPR, inner_type, ar, bi);
-    }
-  else if (ar0 && bi0)
-    {
-      rr = zero;
-      ri = fold_build2 (MULT_EXPR, inner_type, ai, br);
-    }
-  else if (ar0 && br0)
-    {
-      rr = fold_build2 (MULT_EXPR, inner_type, ai, bi);
-      rr = fold_build1 (NEGATE_EXPR, inner_type, rr);
-      ri = zero;
-    }
-  else if (bi0)
-    {
-      rr = fold_build2 (MULT_EXPR, inner_type, ar, br);
-      ri = fold_build2 (MULT_EXPR, inner_type, ai, br);
-    }
-  else if (ai0)
-    {
-      rr = fold_build2 (MULT_EXPR, inner_type, ar, br);
-      ri = fold_build2 (MULT_EXPR, inner_type, ar, bi);
-    }
-  else if (br0)
-    {
-      rr = fold_build2 (MULT_EXPR, inner_type, ai, bi);
-      rr = fold_build1 (NEGATE_EXPR, inner_type, rr);
-      ri = fold_build2 (MULT_EXPR, inner_type, ar, bi);
-    }
-  else if (ar0)
-    {
-      rr = fold_build2 (MULT_EXPR, inner_type, ai, bi);
-      rr = fold_build1 (NEGATE_EXPR, inner_type, rr);
-      ri = fold_build2 (MULT_EXPR, inner_type, ai, br);
-    }
-  else
-    return NULL;
-
-  return fold_build2 (COMPLEX_EXPR, type, rr, ri);
-}
-
-static tree
-fold_complex_mult (tree type, tree ac, tree bc)
-{
-  tree ar, ai, br, bi;
-
-  if (TREE_CODE (ac) == COMPLEX_EXPR)
-    ar = TREE_OPERAND (ac, 0), ai = TREE_OPERAND (ac, 1);
-  else if (TREE_CODE (ac) == COMPLEX_CST)
-    ar = TREE_REALPART (ac), ai = TREE_IMAGPART (ac);
-  else
-    return NULL;
-
-  if (TREE_CODE (bc) == COMPLEX_EXPR)
-    br = TREE_OPERAND (bc, 0), bi = TREE_OPERAND (bc, 1);
-  else if (TREE_CODE (bc) == COMPLEX_CST)
-    br = TREE_REALPART (bc), bi = TREE_IMAGPART (bc);
-  else
-    return NULL;
-
-  return fold_complex_mult_parts (type, ar, ai, br, bi);
-}
-
-/* Perform some simplifications of complex division when one or more of
-   the components are constants or zeros.  Return non-null if successful.  */
-
-tree
-fold_complex_div_parts (tree type, tree ar, tree ai, tree br, tree bi,
-                       enum tree_code code)
-{
-  tree rr, ri, inner_type, zero;
-  bool ar0, ai0, br0, bi0, bi1;
-
-  inner_type = TREE_TYPE (type);
-  zero = NULL;
-
-  if (SCALAR_FLOAT_TYPE_P (inner_type))
-    {
-      ar0 = ai0 = br0 = bi0 = bi1 = false;
-
-      /* We're only interested in +0.0 here, thus we don't use real_zerop.  */
-
-      if (TREE_CODE (ar) == REAL_CST
-         && REAL_VALUES_IDENTICAL (TREE_REAL_CST (ar), dconst0))
-       ar0 = true, zero = ar;
-
-      if (TREE_CODE (ai) == REAL_CST
-         && REAL_VALUES_IDENTICAL (TREE_REAL_CST (ai), dconst0))
-       ai0 = true, zero = ai;
-
-      if (TREE_CODE (br) == REAL_CST
-         && REAL_VALUES_IDENTICAL (TREE_REAL_CST (br), dconst0))
-       br0 = true, zero = br;
-
-      if (TREE_CODE (bi) == REAL_CST)
-       {
-         if (REAL_VALUES_IDENTICAL (TREE_REAL_CST (bi), dconst0))
-           bi0 = true, zero = bi;
-         else if (REAL_VALUES_IDENTICAL (TREE_REAL_CST (bi), dconst1))
-           bi1 = true;
-       }
-    }
-  else
-    {
-      ar0 = integer_zerop (ar);
-      if (ar0)
-       zero = ar;
-      ai0 = integer_zerop (ai);
-      if (ai0)
-       zero = ai;
-      br0 = integer_zerop (br);
-      if (br0)
-       zero = br;
-      bi0 = integer_zerop (bi);
-      if (bi0)
-       {
-         zero = bi;
-         bi1 = false;
-       }
-      else
-       bi1 = integer_onep (bi);
-    }
-
-  /* We won't optimize anything below unless something is zero.  */
-  if (zero == NULL)
-    return NULL;
-
-  if (ai0 && bi0)
-    {
-      rr = fold_build2 (code, inner_type, ar, br);
-      ri = zero;
-    }
-  else if (ai0 && br0)
-    {
-      rr = zero;
-      ri = fold_build2 (code, inner_type, ar, bi);
-      ri = fold_build1 (NEGATE_EXPR, inner_type, ri);
-    }
-  else if (ar0 && bi0)
-    {
-      rr = zero;
-      ri = fold_build2 (code, inner_type, ai, br);
-    }
-  else if (ar0 && br0)
-    {
-      rr = fold_build2 (code, inner_type, ai, bi);
-      ri = zero;
-    }
-  else if (bi0)
-    {
-      rr = fold_build2 (code, inner_type, ar, br);
-      ri = fold_build2 (code, inner_type, ai, br);
-    }
-  else if (br0)
-    {
-      rr = fold_build2 (code, inner_type, ai, bi);
-      ri = fold_build2 (code, inner_type, ar, bi);
-      ri = fold_build1 (NEGATE_EXPR, inner_type, ri);
-    }
-  else
-    return NULL;
-
-  return fold_build2 (COMPLEX_EXPR, type, rr, ri);
-}
-
-static tree
-fold_complex_div (tree type, tree ac, tree bc, enum tree_code code)
-{
-  tree ar, ai, br, bi;
-
-  if (TREE_CODE (ac) == COMPLEX_EXPR)
-    ar = TREE_OPERAND (ac, 0), ai = TREE_OPERAND (ac, 1);
-  else if (TREE_CODE (ac) == COMPLEX_CST)
-    ar = TREE_REALPART (ac), ai = TREE_IMAGPART (ac);
-  else
-    return NULL;
-
-  if (TREE_CODE (bc) == COMPLEX_EXPR)
-    br = TREE_OPERAND (bc, 0), bi = TREE_OPERAND (bc, 1);
-  else if (TREE_CODE (bc) == COMPLEX_CST)
-    br = TREE_REALPART (bc), bi = TREE_IMAGPART (bc);
-  else
-    return NULL;
-
-  return fold_complex_div_parts (type, ar, ai, br, bi, code);
-}
-
 /* Fold a unary expression of code CODE and type TYPE with operand
    OP0.  Return the folded expression if folding is successful.
    Otherwise, return NULL_TREE.  */
@@ -6804,9 +6533,11 @@ fold_unary (enum tree_code code, tree type, tree op0)
   arg0 = op0;
   if (arg0)
     {
-      if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR)
+      if (code == NOP_EXPR || code == CONVERT_EXPR
+         || code == FLOAT_EXPR || code == ABS_EXPR)
        {
-         /* Don't use STRIP_NOPS, because signedness of argument type matters.  */
+         /* Don't use STRIP_NOPS, because signedness of argument type
+            matters.  */
          STRIP_SIGN_NOPS (arg0);
        }
       else
@@ -6989,6 +6720,29 @@ fold_unary (enum tree_code code, tree type, tree op0)
            return fold_build1 (code, type, TREE_OPERAND (op0, 0));
        }
 
+      /* Handle (T *)&A.B.C for A being of type T and B and C
+        living at offset zero.  This occurs frequently in
+        C++ upcasting and then accessing the base.  */
+      if (TREE_CODE (op0) == ADDR_EXPR
+         && POINTER_TYPE_P (type)
+         && handled_component_p (TREE_OPERAND (op0, 0)))
+        {
+         HOST_WIDE_INT bitsize, bitpos;
+         tree offset;
+         enum machine_mode mode;
+         int unsignedp, volatilep;
+          tree base = TREE_OPERAND (op0, 0);
+         base = get_inner_reference (base, &bitsize, &bitpos, &offset,
+                                     &mode, &unsignedp, &volatilep, false);
+         /* If the reference was to a (constant) zero offset, we can use
+            the address of the base if it has the same base type
+            as the result type.  */
+         if (! offset && bitpos == 0
+             && TYPE_MAIN_VARIANT (TREE_TYPE (type))
+                 == TYPE_MAIN_VARIANT (TREE_TYPE (base)))
+           return fold_convert (type, build_fold_addr_expr (base));
+        }
+
       if (TREE_CODE (op0) == MODIFY_EXPR
          && TREE_CONSTANT (TREE_OPERAND (op0, 1))
          /* Detect assigning a bitfield.  */
@@ -7106,7 +6860,8 @@ fold_unary (enum tree_code code, tree type, tree op0)
                                                    TREE_TYPE (targ0),
                                                    targ0));
        }
-      else if (tree_expr_nonnegative_p (arg0))
+      /* ABS_EXPR<ABS_EXPR<x>> = ABS_EXPR<x> even if flag_wrapv is on.  */
+      else if (tree_expr_nonnegative_p (arg0) || TREE_CODE (arg0) == ABS_EXPR)
        return arg0;
 
       /* Strip sign ops from argument.  */
@@ -7418,13 +7173,6 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && integer_onep (arg1))
        return fold_build1 (NEGATE_EXPR, type, TREE_OPERAND (arg0, 0));
 
-      if (TREE_CODE (type) == COMPLEX_TYPE)
-       {
-         tem = fold_complex_add (type, arg0, arg1, PLUS_EXPR);
-         if (tem)
-           return tem;
-       }
-
       if (! FLOAT_TYPE_P (type))
        {
          if (integer_zerop (arg1))
@@ -7557,13 +7305,13 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
            {
              tem = try_move_mult_to_index (PLUS_EXPR, arg0, arg1);
              if (tem)
-               return fold_convert (type, fold (tem));
+               return fold_convert (type, tem);
            }
          else if (TREE_CODE (arg1) == ADDR_EXPR)
            {
              tem = try_move_mult_to_index (PLUS_EXPR, arg1, arg0);
              if (tem)
-               return fold_convert (type, fold (tem));
+               return fold_convert (type, tem);
            }
        }
       else
@@ -7870,13 +7618,6 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && integer_all_onesp (arg0))
        return fold_build1 (BIT_NOT_EXPR, type, arg1);
 
-      if (TREE_CODE (type) == COMPLEX_TYPE)
-       {
-         tem = fold_complex_add (type, arg0, arg1, MINUS_EXPR);
-         if (tem)
-           return tem;
-       }
-
       if (! FLOAT_TYPE_P (type))
        {
          if (! wins && integer_zerop (arg0))
@@ -7989,7 +7730,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
        {
          tem = try_move_mult_to_index (MINUS_EXPR, arg0, arg1);
          if (tem)
-           return fold_convert (type, fold (tem));
+           return fold_convert (type, tem);
        }
 
       if (flag_unsafe_math_optimizations
@@ -8033,13 +7774,6 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                            negate_expr (arg0),
                            TREE_OPERAND (arg1, 0));
 
-      if (TREE_CODE (type) == COMPLEX_TYPE)
-       {
-         tem = fold_complex_mult (type, arg0, arg1);
-         if (tem)
-           return tem;
-       }
-
       if (! FLOAT_TYPE_P (type))
        {
          if (integer_zerop (arg1))
@@ -8359,6 +8093,54 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          goto bit_ior;
        }
 
+      /* (X | Y) ^ X -> Y & ~ X*/
+      if (TREE_CODE (arg0) == BIT_IOR_EXPR
+          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+        {
+         tree t2 = TREE_OPERAND (arg0, 1);
+         t1 = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg1),
+                           arg1);
+         t1 = fold_build2 (BIT_AND_EXPR, type, fold_convert (type, t2),
+                           fold_convert (type, t1));
+         return t1;
+       }
+
+      /* (Y | X) ^ X -> Y & ~ X*/
+      if (TREE_CODE (arg0) == BIT_IOR_EXPR
+          && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
+        {
+         tree t2 = TREE_OPERAND (arg0, 0);
+         t1 = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg1),
+                           arg1);
+         t1 = fold_build2 (BIT_AND_EXPR, type, fold_convert (type, t2),
+                           fold_convert (type, t1));
+         return t1;
+       }
+
+      /* X ^ (X | Y) -> Y & ~ X*/
+      if (TREE_CODE (arg1) == BIT_IOR_EXPR
+          && operand_equal_p (TREE_OPERAND (arg1, 0), arg0, 0))
+        {
+         tree t2 = TREE_OPERAND (arg1, 1);
+         t1 = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg0),
+                           arg0);
+         t1 = fold_build2 (BIT_AND_EXPR, type, fold_convert (type, t2),
+                           fold_convert (type, t1));
+         return t1;
+       }
+
+      /* X ^ (Y | X) -> Y & ~ X*/
+      if (TREE_CODE (arg1) == BIT_IOR_EXPR
+          && operand_equal_p (TREE_OPERAND (arg1, 1), arg0, 0))
+        {
+         tree t2 = TREE_OPERAND (arg1, 0);
+         t1 = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg0),
+                           arg0);
+         t1 = fold_build2 (BIT_AND_EXPR, type, fold_convert (type, t2),
+                           fold_convert (type, t1));
+         return t1;
+       }
+       
       /* Convert ~X ^ ~Y to X ^ Y.  */
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
          && TREE_CODE (arg1) == BIT_NOT_EXPR)
@@ -8501,13 +8283,6 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                                TREE_OPERAND (arg1, 0));
        }
 
-      if (TREE_CODE (type) == COMPLEX_TYPE)
-       {
-         tem = fold_complex_div (type, arg0, arg1, code);
-         if (tem)
-           return tem;
-       }
-
       if (flag_unsafe_math_optimizations)
        {
          enum built_in_function fcode = builtin_mathfn_code (arg1);
@@ -8631,12 +8406,6 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && 0 != (tem = extract_muldiv (op0, arg1, code, NULL_TREE)))
        return fold_convert (type, tem);
 
-      if (TREE_CODE (type) == COMPLEX_TYPE)
-       {
-         tem = fold_complex_div (type, arg0, arg1, code);
-         if (tem)
-           return tem;
-       }
       goto binary;
 
     case CEIL_MOD_EXPR:
@@ -8665,11 +8434,11 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && TREE_INT_CST_HIGH (arg1) == -1)
        return omit_one_operand (type, integer_zero_node, arg0);
 
-      /* Optimize unsigned TRUNC_MOD_EXPR by a power of two into a
-        BIT_AND_EXPR, i.e. "X % C" into "X & C2".  */
-      if (code == TRUNC_MOD_EXPR
-         && TYPE_UNSIGNED (type)
-         && integer_pow2p (arg1))
+      /* Optimize TRUNC_MOD_EXPR by a power of two into a BIT_AND_EXPR,
+         i.e. "X % C" into "X & C2", if X and C are positive.  */
+      if ((code == TRUNC_MOD_EXPR || code == FLOOR_MOD_EXPR)
+         && (TYPE_UNSIGNED (type) || tree_expr_nonnegative_p (arg0))
+         && integer_pow2p (arg1) && tree_int_cst_sgn (arg1) >= 0)
        {
          unsigned HOST_WIDE_INT high, low;
          tree mask;
@@ -8891,11 +8660,11 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && !TREE_SIDE_EFFECTS (arg1))
        {
          tem = fold_to_nonsharp_ineq_using_bound (arg0, arg1);
-         if (tem)
+         if (tem && !operand_equal_p (tem, arg0, 0))
            return fold_build2 (code, type, tem, arg1);
 
          tem = fold_to_nonsharp_ineq_using_bound (arg1, arg0);
-         if (tem)
+         if (tem && !operand_equal_p (tem, arg1, 0))
            return fold_build2 (code, type, arg0, tem);
        }
 
@@ -9052,7 +8821,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
         object against zero, then we know the result.  */
       if ((code == EQ_EXPR || code == NE_EXPR)
          && TREE_CODE (arg0) == ADDR_EXPR
-         && DECL_P (TREE_OPERAND (arg0, 0))
+         && VAR_OR_FUNCTION_DECL_P (TREE_OPERAND (arg0, 0))
          && ! DECL_WEAK (TREE_OPERAND (arg0, 0))
          && integer_zerop (arg1))
        return constant_boolean_node (code != EQ_EXPR, type);
@@ -9062,20 +8831,34 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
         have access to attributes for externs), then we know the result.  */
       if ((code == EQ_EXPR || code == NE_EXPR)
          && TREE_CODE (arg0) == ADDR_EXPR
-         && DECL_P (TREE_OPERAND (arg0, 0))
+         && VAR_OR_FUNCTION_DECL_P (TREE_OPERAND (arg0, 0))
          && ! DECL_WEAK (TREE_OPERAND (arg0, 0))
          && ! lookup_attribute ("alias",
                                 DECL_ATTRIBUTES (TREE_OPERAND (arg0, 0)))
          && ! DECL_EXTERNAL (TREE_OPERAND (arg0, 0))
          && TREE_CODE (arg1) == ADDR_EXPR
-         && DECL_P (TREE_OPERAND (arg1, 0))
+         && VAR_OR_FUNCTION_DECL_P (TREE_OPERAND (arg1, 0))
          && ! DECL_WEAK (TREE_OPERAND (arg1, 0))
          && ! lookup_attribute ("alias",
                                 DECL_ATTRIBUTES (TREE_OPERAND (arg1, 0)))
          && ! DECL_EXTERNAL (TREE_OPERAND (arg1, 0)))
-       return constant_boolean_node (operand_equal_p (arg0, arg1, 0)
-                                     ? code == EQ_EXPR : code != EQ_EXPR,
-                                     type);
+       {
+         /* We know that we're looking at the address of two
+            non-weak, unaliased, static _DECL nodes.
+
+            It is both wasteful and incorrect to call operand_equal_p
+            to compare the two ADDR_EXPR nodes.  It is wasteful in that
+            all we need to do is test pointer equality for the arguments
+            to the two ADDR_EXPR nodes.  It is incorrect to use
+            operand_equal_p as that function is NOT equivalent to a
+            C equality test.  It can in fact return false for two
+            objects which would test as equal using the C equality
+            operator.  */
+         bool equal = TREE_OPERAND (arg0, 0) == TREE_OPERAND (arg1, 0);
+         return constant_boolean_node (equal
+                                       ? code == EQ_EXPR : code != EQ_EXPR,
+                                       type);
+       }
 
       /* If this is a comparison of two exprs that look like an
         ARRAY_REF of the same object, then we can fold this to a
@@ -9181,6 +8964,30 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
            }
        }
 
+      /* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 +- C1.  */
+      if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
+         && (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
+             && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))
+             && !TYPE_UNSIGNED (TREE_TYPE (arg1))
+             && !(flag_wrapv || flag_trapv))
+         && (TREE_CODE (arg1) == INTEGER_CST
+             && !TREE_OVERFLOW (arg1)))
+       {
+         tree const1 = TREE_OPERAND (arg0, 1);
+         tree const2 = arg1;
+         tree variable = TREE_OPERAND (arg0, 0);
+         tree lhs;
+         int lhs_add;
+         lhs_add = TREE_CODE (arg0) != PLUS_EXPR;
+         
+         lhs = fold_build2 (lhs_add ? PLUS_EXPR : MINUS_EXPR,
+                            TREE_TYPE (arg1), const2, const1);
+         if (TREE_CODE (lhs) == TREE_CODE (arg1)
+             && (TREE_CODE (lhs) != INTEGER_CST
+                 || !TREE_OVERFLOW (lhs)))
+           return fold_build2 (code, type, variable, lhs);
+       }
+
       if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
        {
          tree targ0 = strip_float_extensions (arg0);
@@ -9478,7 +9285,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                  return omit_one_operand (type, integer_one_node, arg0);
 
                case GT_EXPR:
-                 return fold_build2 (NE_EXPR, type, arg0, arg1);
+                 return fold_build2 (NE_EXPR, type, op0, op1);
 
                default:
                  break;
@@ -9512,10 +9319,9 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                    tree st0, st1;
                    st0 = lang_hooks.types.signed_type (TREE_TYPE (arg0));
                    st1 = lang_hooks.types.signed_type (TREE_TYPE (arg1));
-                   return fold
-                     (build2 (code == LE_EXPR ? GE_EXPR: LT_EXPR,
-                              type, fold_convert (st0, arg0),
-                              fold_convert (st1, integer_zero_node)));
+                   return fold_build2 (code == LE_EXPR ? GE_EXPR: LT_EXPR,
+                                       type, fold_convert (st0, arg0),
+                                       build_int_cst (st1, 0));
                  }
              }
          }
@@ -9926,34 +9732,6 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
            }
        }
 
-      /* If this is a comparison of complex values and either or both sides
-        are a COMPLEX_EXPR or COMPLEX_CST, it is best to split up the
-        comparisons and join them with a TRUTH_ANDIF_EXPR or TRUTH_ORIF_EXPR.
-        This may prevent needless evaluations.  */
-      if ((code == EQ_EXPR || code == NE_EXPR)
-         && TREE_CODE (TREE_TYPE (arg0)) == COMPLEX_TYPE
-         && (TREE_CODE (arg0) == COMPLEX_EXPR
-             || TREE_CODE (arg1) == COMPLEX_EXPR
-             || TREE_CODE (arg0) == COMPLEX_CST
-             || TREE_CODE (arg1) == COMPLEX_CST))
-       {
-         tree subtype = TREE_TYPE (TREE_TYPE (arg0));
-         tree real0, imag0, real1, imag1;
-
-         arg0 = save_expr (arg0);
-         arg1 = save_expr (arg1);
-         real0 = fold_build1 (REALPART_EXPR, subtype, arg0);
-         imag0 = fold_build1 (IMAGPART_EXPR, subtype, arg0);
-         real1 = fold_build1 (REALPART_EXPR, subtype, arg1);
-         imag1 = fold_build1 (IMAGPART_EXPR, subtype, arg1);
-
-         return fold_build2 ((code == EQ_EXPR ? TRUTH_ANDIF_EXPR
-                              : TRUTH_ORIF_EXPR),
-                             type,
-                             fold_build2 (code, type, real0, real1),
-                             fold_build2 (code, type, imag0, imag1));
-       }
-
       /* Optimize comparisons of strlen vs zero to a compare of the
         first character of the string vs zero.  To wit,
                strlen(ptr) == 0   =>  *ptr == 0
@@ -9996,10 +9774,12 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
        }
 
       if ((code == EQ_EXPR || code == NE_EXPR)
-         && !TREE_SIDE_EFFECTS (arg0)
          && integer_zerop (arg1)
          && tree_expr_nonzero_p (arg0))
-       return constant_boolean_node (code==NE_EXPR, type);
+        {
+         tree res = constant_boolean_node (code==NE_EXPR, type);
+         return omit_one_operand (type, res, arg0);
+       }
 
       t1 = fold_relational_const (code, type, arg0, arg1);
       return t1 == NULL_TREE ? NULL_TREE : t1;
@@ -10164,9 +9944,11 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
       if (TREE_CODE (arg0) == CONSTRUCTOR
          && ! type_contains_placeholder_p (TREE_TYPE (arg0)))
        {
-         tree m = purpose_member (arg1, CONSTRUCTOR_ELTS (arg0));
-         if (m)
-           return TREE_VALUE (m);
+         unsigned HOST_WIDE_INT idx;
+         tree field, value;
+         FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (arg0), idx, field, value)
+           if (field == arg1)
+             return value;
        }
       return NULL_TREE;
 
@@ -10224,7 +10006,8 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
 
       /* If the second operand is simpler than the third, swap them
         since that produces better jump optimization results.  */
-      if (tree_swap_operands_p (op1, op2, false))
+      if (truth_value_p (TREE_CODE (arg0))
+         && tree_swap_operands_p (op1, op2, false))
        {
          /* See if this can be inverted.  If it can't, possibly because
             it was a floating-point inequality comparison, don't do
@@ -10333,13 +10116,7 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
       if (TREE_CODE (op0) == ADDR_EXPR
          && TREE_CODE (TREE_OPERAND (op0, 0)) == FUNCTION_DECL
          && DECL_BUILT_IN (TREE_OPERAND (op0, 0)))
-       {
-         tree fndecl = TREE_OPERAND (op0, 0);
-         tree arglist = op1;
-         tree tmp = fold_builtin (fndecl, arglist, false);
-         if (tmp)
-           return tmp;
-       }
+       return fold_builtin (TREE_OPERAND (op0, 0), op1, false);
       return NULL_TREE;
 
     case BIT_FIELD_REF:
@@ -10501,14 +10278,14 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
 {
   void **slot;
   enum tree_code code;
-  char buf[sizeof (struct tree_decl)];
+  char buf[sizeof (struct tree_function_decl)];
   int i, len;
   
 recursive_label:
 
   gcc_assert ((sizeof (struct tree_exp) + 5 * sizeof (tree)
-              <= sizeof (struct tree_decl))
-             && sizeof (struct tree_type) <= sizeof (struct tree_decl));
+              <= sizeof (struct tree_function_decl))
+             && sizeof (struct tree_type) <= sizeof (struct tree_function_decl));
   if (expr == NULL)
     return;
   slot = htab_find_slot (ht, expr, INSERT);
@@ -10599,13 +10376,18 @@ recursive_label:
       fold_checksum_tree (DECL_SIZE_UNIT (expr), ctx, ht);
       fold_checksum_tree (DECL_NAME (expr), ctx, ht);
       fold_checksum_tree (DECL_CONTEXT (expr), ctx, ht);
-      fold_checksum_tree (DECL_ARGUMENTS (expr), ctx, ht);
-      fold_checksum_tree (DECL_RESULT_FLD (expr), ctx, ht);
       fold_checksum_tree (DECL_INITIAL (expr), ctx, ht);
       fold_checksum_tree (DECL_ABSTRACT_ORIGIN (expr), ctx, ht);
-      fold_checksum_tree (DECL_SECTION_NAME (expr), ctx, ht);
       fold_checksum_tree (DECL_ATTRIBUTES (expr), ctx, ht);
-      fold_checksum_tree (DECL_VINDEX (expr), ctx, ht);
+      if (CODE_CONTAINS_STRUCT (TREE_CODE (expr), TS_DECL_WITH_VIS))
+       fold_checksum_tree (DECL_SECTION_NAME (expr), ctx, ht);
+         
+      if (CODE_CONTAINS_STRUCT (TREE_CODE (expr), TS_DECL_NON_COMMON))
+       {
+         fold_checksum_tree (DECL_VINDEX (expr), ctx, ht);
+         fold_checksum_tree (DECL_RESULT_FLD (expr), ctx, ht);
+         fold_checksum_tree (DECL_ARGUMENT_FLD (expr), ctx, ht);
+       }
       break;
     case tcc_type:
       if (TREE_CODE (expr) == ENUMERAL_TYPE)
@@ -10640,13 +10422,35 @@ recursive_label:
    operand OP0.  */
 
 tree
-fold_build1 (enum tree_code code, tree type, tree op0)
+fold_build1_stat (enum tree_code code, tree type, tree op0 MEM_STAT_DECL)
 {
-  tree tem = fold_unary (code, type, op0);
-  if (tem)
-    return tem;
+  tree tem;
+#ifdef ENABLE_FOLD_CHECKING
+  unsigned char checksum_before[16], checksum_after[16];
+  struct md5_ctx ctx;
+  htab_t ht;
+
+  ht = htab_create (32, htab_hash_pointer, htab_eq_pointer, NULL);
+  md5_init_ctx (&ctx);
+  fold_checksum_tree (op0, &ctx, ht);
+  md5_finish_ctx (&ctx, checksum_before);
+  htab_empty (ht);
+#endif
+  
+  tem = fold_unary (code, type, op0);
+  if (!tem)
+    tem = build1_stat (code, type, op0 PASS_MEM_STAT);
+  
+#ifdef ENABLE_FOLD_CHECKING
+  md5_init_ctx (&ctx);
+  fold_checksum_tree (op0, &ctx, ht);
+  md5_finish_ctx (&ctx, checksum_after);
+  htab_delete (ht);
 
-  return build1 (code, type, op0);
+  if (memcmp (checksum_before, checksum_after, 16))
+    fold_check_failed (op0, tem);
+#endif
+  return tem;
 }
 
 /* Fold a binary tree expression with code CODE of type TYPE with
@@ -10655,13 +10459,52 @@ fold_build1 (enum tree_code code, tree type, tree op0)
    with operands OP0 and OP1.  */
 
 tree
-fold_build2 (enum tree_code code, tree type, tree op0, tree op1)
+fold_build2_stat (enum tree_code code, tree type, tree op0, tree op1
+                 MEM_STAT_DECL)
 {
-  tree tem = fold_binary (code, type, op0, op1);
-  if (tem)
-    return tem;
+  tree tem;
+#ifdef ENABLE_FOLD_CHECKING
+  unsigned char checksum_before_op0[16],
+                checksum_before_op1[16],
+               checksum_after_op0[16],
+               checksum_after_op1[16];
+  struct md5_ctx ctx;
+  htab_t ht;
+
+  ht = htab_create (32, htab_hash_pointer, htab_eq_pointer, NULL);
+  md5_init_ctx (&ctx);
+  fold_checksum_tree (op0, &ctx, ht);
+  md5_finish_ctx (&ctx, checksum_before_op0);
+  htab_empty (ht);
+
+  md5_init_ctx (&ctx);
+  fold_checksum_tree (op1, &ctx, ht);
+  md5_finish_ctx (&ctx, checksum_before_op1);
+  htab_empty (ht);
+#endif
+
+  tem = fold_binary (code, type, op0, op1);
+  if (!tem)
+    tem = build2_stat (code, type, op0, op1 PASS_MEM_STAT);
+  
+#ifdef ENABLE_FOLD_CHECKING
+  md5_init_ctx (&ctx);
+  fold_checksum_tree (op0, &ctx, ht);
+  md5_finish_ctx (&ctx, checksum_after_op0);
+  htab_empty (ht);
+
+  if (memcmp (checksum_before_op0, checksum_after_op0, 16))
+    fold_check_failed (op0, tem);
+  
+  md5_init_ctx (&ctx);
+  fold_checksum_tree (op1, &ctx, ht);
+  md5_finish_ctx (&ctx, checksum_after_op1);
+  htab_delete (ht);
 
-  return build2 (code, type, op0, op1);
+  if (memcmp (checksum_before_op1, checksum_after_op1, 16))
+    fold_check_failed (op1, tem);
+#endif
+  return tem;
 }
 
 /* Fold a ternary tree expression with code CODE of type TYPE with
@@ -10670,43 +10513,129 @@ fold_build2 (enum tree_code code, tree type, tree op0, tree op1)
    type TYPE with operands OP0, OP1, and OP2.  */
 
 tree
-fold_build3 (enum tree_code code, tree type, tree op0, tree op1, tree op2)
+fold_build3_stat (enum tree_code code, tree type, tree op0, tree op1, tree op2
+            MEM_STAT_DECL)
 {
-  tree tem = fold_ternary (code, type, op0, op1, op2);
-  if (tem)
-    return tem;
+  tree tem;
+#ifdef ENABLE_FOLD_CHECKING
+  unsigned char checksum_before_op0[16],
+                checksum_before_op1[16],
+                checksum_before_op2[16],
+               checksum_after_op0[16],
+               checksum_after_op1[16],
+               checksum_after_op2[16];
+  struct md5_ctx ctx;
+  htab_t ht;
+
+  ht = htab_create (32, htab_hash_pointer, htab_eq_pointer, NULL);
+  md5_init_ctx (&ctx);
+  fold_checksum_tree (op0, &ctx, ht);
+  md5_finish_ctx (&ctx, checksum_before_op0);
+  htab_empty (ht);
+
+  md5_init_ctx (&ctx);
+  fold_checksum_tree (op1, &ctx, ht);
+  md5_finish_ctx (&ctx, checksum_before_op1);
+  htab_empty (ht);
+
+  md5_init_ctx (&ctx);
+  fold_checksum_tree (op2, &ctx, ht);
+  md5_finish_ctx (&ctx, checksum_before_op2);
+  htab_empty (ht);
+#endif
+  
+  tem = fold_ternary (code, type, op0, op1, op2);
+  if (!tem)
+    tem =  build3_stat (code, type, op0, op1, op2 PASS_MEM_STAT);
+      
+#ifdef ENABLE_FOLD_CHECKING
+  md5_init_ctx (&ctx);
+  fold_checksum_tree (op0, &ctx, ht);
+  md5_finish_ctx (&ctx, checksum_after_op0);
+  htab_empty (ht);
+
+  if (memcmp (checksum_before_op0, checksum_after_op0, 16))
+    fold_check_failed (op0, tem);
+  
+  md5_init_ctx (&ctx);
+  fold_checksum_tree (op1, &ctx, ht);
+  md5_finish_ctx (&ctx, checksum_after_op1);
+  htab_empty (ht);
+
+  if (memcmp (checksum_before_op1, checksum_after_op1, 16))
+    fold_check_failed (op1, tem);
+  
+  md5_init_ctx (&ctx);
+  fold_checksum_tree (op2, &ctx, ht);
+  md5_finish_ctx (&ctx, checksum_after_op2);
+  htab_delete (ht);
 
-  return build3 (code, type, op0, op1, op2);
+  if (memcmp (checksum_before_op2, checksum_after_op2, 16))
+    fold_check_failed (op2, tem);
+#endif
+  return tem;
 }
 
 /* Perform constant folding and related simplification of initializer
-   expression EXPR.  This behaves identically to "fold" but ignores
+   expression EXPR.  These behave identically to "fold_buildN" but ignore
    potential run-time traps and exceptions that fold must preserve.  */
 
+#define START_FOLD_INIT \
+  int saved_signaling_nans = flag_signaling_nans;\
+  int saved_trapping_math = flag_trapping_math;\
+  int saved_rounding_math = flag_rounding_math;\
+  int saved_trapv = flag_trapv;\
+  flag_signaling_nans = 0;\
+  flag_trapping_math = 0;\
+  flag_rounding_math = 0;\
+  flag_trapv = 0
+
+#define END_FOLD_INIT \
+  flag_signaling_nans = saved_signaling_nans;\
+  flag_trapping_math = saved_trapping_math;\
+  flag_rounding_math = saved_rounding_math;\
+  flag_trapv = saved_trapv
+
+tree
+fold_build1_initializer (enum tree_code code, tree type, tree op)
+{
+  tree result;
+  START_FOLD_INIT;
+
+  result = fold_build1 (code, type, op);
+
+  END_FOLD_INIT;
+  return result;
+}
+
 tree
-fold_initializer (tree expr)
+fold_build2_initializer (enum tree_code code, tree type, tree op0, tree op1)
 {
-  int saved_signaling_nans = flag_signaling_nans;
-  int saved_trapping_math = flag_trapping_math;
-  int saved_rounding_math = flag_rounding_math;
-  int saved_trapv = flag_trapv;
   tree result;
+  START_FOLD_INIT;
 
-  flag_signaling_nans = 0;
-  flag_trapping_math = 0;
-  flag_rounding_math = 0;
-  flag_trapv = 0;
+  result = fold_build2 (code, type, op0, op1);
 
-  result = fold (expr);
+  END_FOLD_INIT;
+  return result;
+}
 
-  flag_signaling_nans = saved_signaling_nans;
-  flag_trapping_math = saved_trapping_math;
-  flag_rounding_math = saved_rounding_math;
-  flag_trapv = saved_trapv;
+tree
+fold_build3_initializer (enum tree_code code, tree type, tree op0, tree op1,
+                        tree op2)
+{
+  tree result;
+  START_FOLD_INIT;
 
+  result = fold_build3 (code, type, op0, op1, op2);
+
+  END_FOLD_INIT;
   return result;
 }
 
+#undef START_FOLD_INIT
+#undef END_FOLD_INIT
+
 /* Determine if first argument is a multiple of second argument.  Return 0 if
    it is not, or we cannot easily determined it to be.
 
@@ -10825,10 +10754,17 @@ multiple_of_p (tree type, tree top, tree bottom)
 int
 tree_expr_nonnegative_p (tree t)
 {
+  if (TYPE_UNSIGNED (TREE_TYPE (t)))
+    return 1;
+
   switch (TREE_CODE (t))
     {
     case ABS_EXPR:
-      return 1;
+      /* We can't return 1 if flag_wrapv is set because
+        ABS_EXPR<INT_MIN> = INT_MIN.  */
+      if (!(flag_wrapv && INTEGRAL_TYPE_P (TREE_TYPE (t))))
+        return 1;
+      break;
 
     case INTEGER_CST:
       return tree_int_cst_sgn (t) >= 0;
@@ -10884,6 +10820,15 @@ tree_expr_nonnegative_p (tree t)
        }
       return 0;
 
+    case BIT_AND_EXPR:
+    case MAX_EXPR:
+      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
+            || tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+
+    case BIT_IOR_EXPR:
+    case BIT_XOR_EXPR:
+    case MIN_EXPR:
+    case RDIV_EXPR:
     case TRUNC_DIV_EXPR:
     case CEIL_DIV_EXPR:
     case FLOOR_DIV_EXPR:
@@ -10895,19 +10840,21 @@ tree_expr_nonnegative_p (tree t)
     case CEIL_MOD_EXPR:
     case FLOOR_MOD_EXPR:
     case ROUND_MOD_EXPR:
+    case SAVE_EXPR:
+    case NON_LVALUE_EXPR:
+    case FLOAT_EXPR:
       return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
 
-    case RDIV_EXPR:
-      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
-            && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+    case COMPOUND_EXPR:
+    case MODIFY_EXPR:
+      return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
 
-    case BIT_AND_EXPR:
+    case BIND_EXPR:
+      return tree_expr_nonnegative_p (expr_last (TREE_OPERAND (t, 1)));
+
+    case COND_EXPR:
       return tree_expr_nonnegative_p (TREE_OPERAND (t, 1))
-            || tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
-    case BIT_IOR_EXPR:
-    case BIT_XOR_EXPR:
-      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
-            && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+            && tree_expr_nonnegative_p (TREE_OPERAND (t, 2));
 
     case NOP_EXPR:
       {
@@ -10936,28 +10883,6 @@ tree_expr_nonnegative_p (tree t)
       }
       break;
 
-    case COND_EXPR:
-      return tree_expr_nonnegative_p (TREE_OPERAND (t, 1))
-       && tree_expr_nonnegative_p (TREE_OPERAND (t, 2));
-    case COMPOUND_EXPR:
-      return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
-    case MIN_EXPR:
-      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
-       && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
-    case MAX_EXPR:
-      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
-       || tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
-    case MODIFY_EXPR:
-      return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
-    case BIND_EXPR:
-      return tree_expr_nonnegative_p (expr_last (TREE_OPERAND (t, 1)));
-    case SAVE_EXPR:
-      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
-    case NON_LVALUE_EXPR:
-      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
-    case FLOAT_EXPR:
-      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
-
     case TARGET_EXPR:
       {
        tree temp = TARGET_EXPR_SLOT (t);
@@ -11011,7 +10936,6 @@ tree_expr_nonnegative_p (tree t)
            CASE_BUILTIN_F (BUILT_IN_EXP2)
            CASE_BUILTIN_F (BUILT_IN_FABS)
            CASE_BUILTIN_F (BUILT_IN_FDIM)
-           CASE_BUILTIN_F (BUILT_IN_FREXP)
            CASE_BUILTIN_F (BUILT_IN_HYPOT)
            CASE_BUILTIN_F (BUILT_IN_POW10)
            CASE_BUILTIN_I (BUILT_IN_FFS)
@@ -11035,6 +10959,7 @@ tree_expr_nonnegative_p (tree t)
            CASE_BUILTIN_F (BUILT_IN_EXPM1)
            CASE_BUILTIN_F (BUILT_IN_FLOOR)
            CASE_BUILTIN_F (BUILT_IN_FMOD)
+           CASE_BUILTIN_F (BUILT_IN_FREXP)
            CASE_BUILTIN_F (BUILT_IN_LCEIL)
            CASE_BUILTIN_F (BUILT_IN_LDEXP)
            CASE_BUILTIN_F (BUILT_IN_LFLOOR)
@@ -11093,7 +11018,7 @@ tree_expr_nonnegative_p (tree t)
    For floating point we further ensure that T is not denormal.
    Similar logic is present in nonzero_address in rtlanal.h.  */
 
-static bool
+bool
 tree_expr_nonzero_p (tree t)
 {
   tree type = TREE_TYPE (t);
@@ -11105,8 +11030,7 @@ tree_expr_nonzero_p (tree t)
   switch (TREE_CODE (t))
     {
     case ABS_EXPR:
-      if (!TYPE_UNSIGNED (type) && !flag_wrapv)
-       return tree_expr_nonzero_p (TREE_OPERAND (t, 0));
+      return tree_expr_nonzero_p (TREE_OPERAND (t, 0));
 
     case INTEGER_CST:
       /* We used to test for !integer_zerop here.  This does not work correctly
@@ -11154,7 +11078,7 @@ tree_expr_nonzero_p (tree t)
          return false;
 
        /* Weak declarations may link to NULL.  */
-       if (DECL_P (base))
+       if (VAR_OR_FUNCTION_DECL_P (base))
          return !DECL_WEAK (base);
 
        /* Constants are never weak.  */
@@ -11201,6 +11125,9 @@ tree_expr_nonzero_p (tree t)
       return tree_expr_nonzero_p (TREE_OPERAND (t, 1))
             || tree_expr_nonzero_p (TREE_OPERAND (t, 0));
 
+    case CALL_EXPR:
+      return alloca_call_p (t);
+
     default:
       break;
     }
@@ -11801,9 +11728,7 @@ split_address_to_core_and_offset (tree exp,
       core = get_inner_reference (TREE_OPERAND (exp, 0), &bitsize, pbitpos,
                                  poffset, &mode, &unsignedp, &volatilep,
                                  false);
-
-      if (TREE_CODE (core) == INDIRECT_REF)
-       core = TREE_OPERAND (core, 0);
+      core = build_fold_addr_expr (core);
     }
   else
     {
@@ -11840,10 +11765,10 @@ ptr_difference_const (tree e1, tree e2, HOST_WIDE_INT *diff)
        toffset2 = fold_convert (type, toffset2);
 
       tdiff = fold_build2 (MINUS_EXPR, type, toffset1, toffset2);
-      if (!host_integerp (tdiff, 0))
+      if (!cst_and_fits_in_hwi (tdiff))
        return false;
 
-      *diff = tree_low_cst (tdiff, 0);
+      *diff = int_cst_value (tdiff);
     }
   else if (toffset1 || toffset2)
     {