OSDN Git Service

2006-03-09 Roger Sayle <roger@eyesopen.com>
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index 53f737d..be0c461 100644 (file)
@@ -1,6 +1,6 @@
 /* Fold a constant sub-tree into a single node for C-compiler
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -1345,7 +1345,8 @@ associate_trees (tree t1, tree t2, enum tree_code code, tree type)
 }
 \f
 /* Combine two integer constants ARG1 and ARG2 under operation CODE
-   to produce a new constant.
+   to produce a new constant.  Return NULL_TREE if we don't know how
+   to evaluate CODE at compile-time.
 
    If NOTRUNC is nonzero, do not truncate the result to fit the data type.  */
 
@@ -1434,6 +1435,8 @@ int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
       /* ... fall through ...  */
 
     case ROUND_DIV_EXPR:
+      if (int2h == 0 && int2l == 0)
+       return NULL_TREE;
       if (int2h == 0 && int2l == 1)
        {
          low = int1l, hi = int1h;
@@ -1466,6 +1469,8 @@ int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
       /* ... fall through ...  */
 
     case ROUND_MOD_EXPR:
+      if (int2h == 0 && int2l == 0)
+       return NULL_TREE;
       overflow = div_and_round_double (code, uns,
                                       int1l, int1h, int2l, int2h,
                                       &garbagel, &garbageh, &low, &hi);
@@ -1490,7 +1495,7 @@ int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
       break;
 
     default:
-      gcc_unreachable ();
+      return NULL_TREE;
     }
 
   t = build_int_cst_wide (TREE_TYPE (arg1), low, hi);
@@ -1546,6 +1551,21 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
       bool inexact;
       tree t, type;
 
+      /* The following codes are handled by real_arithmetic.  */
+      switch (code)
+       {
+       case PLUS_EXPR:
+       case MINUS_EXPR:
+       case MULT_EXPR:
+       case RDIV_EXPR:
+       case MIN_EXPR:
+       case MAX_EXPR:
+         break;
+
+       default:
+         return NULL_TREE;
+       }
+
       d1 = TREE_REAL_CST (arg1);
       d2 = TREE_REAL_CST (arg2);
 
@@ -1605,6 +1625,7 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
          | TREE_CONSTANT_OVERFLOW (arg2);
       return t;
     }
+
   if (TREE_CODE (arg1) == COMPLEX_CST)
     {
       tree type = TREE_TYPE (arg1);
@@ -1680,11 +1701,11 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
          break;
 
        default:
-         gcc_unreachable ();
+         return NULL_TREE;
        }
       return t;
     }
-  return 0;
+  return NULL_TREE;
 }
 
 /* Create a size type INT_CST node with NUMBER sign extended.  KIND
@@ -1762,11 +1783,11 @@ size_diffop (tree arg0, tree arg1)
      overflow) and negate (which can't either).  Special-case a result
      of zero while we're here.  */
   if (tree_int_cst_equal (arg0, arg1))
-    return fold_convert (ctype, integer_zero_node);
+    return build_int_cst (ctype, 0);
   else if (tree_int_cst_lt (arg1, arg0))
     return fold_convert (ctype, size_binop (MINUS_EXPR, arg0, arg1));
   else
-    return size_binop (MINUS_EXPR, fold_convert (ctype, integer_zero_node),
+    return size_binop (MINUS_EXPR, build_int_cst (ctype, 0),
                       fold_convert (ctype, size_binop (MINUS_EXPR,
                                                        arg1, arg0)));
 }
@@ -1974,7 +1995,7 @@ fold_convert (tree type, tree arg)
 
   switch (TREE_CODE (type))
     {
-    case INTEGER_TYPE: case CHAR_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
+    case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
     case POINTER_TYPE: case REFERENCE_TYPE:
     case OFFSET_TYPE:
       if (TREE_CODE (arg) == INTEGER_CST)
@@ -2011,14 +2032,13 @@ fold_convert (tree type, tree arg)
 
       switch (TREE_CODE (orig))
        {
-       case INTEGER_TYPE: case CHAR_TYPE:
+       case INTEGER_TYPE:
        case BOOLEAN_TYPE: case ENUMERAL_TYPE:
        case POINTER_TYPE: case REFERENCE_TYPE:
          return fold_build1 (FLOAT_EXPR, type, arg);
 
        case REAL_TYPE:
-         return fold_build1 (flag_float_store ? CONVERT_EXPR : NOP_EXPR,
-                             type, arg);
+         return fold_build1 (NOP_EXPR, type, arg);
 
        case COMPLEX_TYPE:
          tem = fold_build1 (REALPART_EXPR, TREE_TYPE (orig), arg);
@@ -2031,7 +2051,7 @@ fold_convert (tree type, tree arg)
     case COMPLEX_TYPE:
       switch (TREE_CODE (orig))
        {
-       case INTEGER_TYPE: case CHAR_TYPE:
+       case INTEGER_TYPE:
        case BOOLEAN_TYPE: case ENUMERAL_TYPE:
        case POINTER_TYPE: case REFERENCE_TYPE:
        case REAL_TYPE:
@@ -2070,7 +2090,7 @@ fold_convert (tree type, tree arg)
       return fold_build1 (VIEW_CONVERT_EXPR, type, arg);
 
     case VOID_TYPE:
-      return fold_build1 (CONVERT_EXPR, type, fold_ignored_result (arg));
+      return fold_build1 (NOP_EXPR, type, fold_ignored_result (arg));
 
     default:
       gcc_unreachable ();
@@ -2615,8 +2635,11 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
                  && OP_SAME_WITH_NULL (3));
 
        case COMPONENT_REF:
-         /* Handle operand 2 the same as for ARRAY_REF.  */
-         return OP_SAME (0) && OP_SAME (1) && OP_SAME_WITH_NULL (2);
+         /* Handle operand 2 the same as for ARRAY_REF.  Operand 0
+            may be NULL when we're called to compare MEM_EXPRs.  */
+         return OP_SAME_WITH_NULL (0)
+                && OP_SAME (1)
+                && OP_SAME_WITH_NULL (2);
 
        case BIT_FIELD_REF:
          return OP_SAME (0) && OP_SAME (1) && OP_SAME (2);
@@ -3106,7 +3129,7 @@ invert_truthvalue (tree arg)
       if (!integer_onep (TREE_OPERAND (arg, 1)))
        break;
       return build2 (EQ_EXPR, type, arg,
-                    fold_convert (type, integer_zero_node));
+                    build_int_cst (type, 0));
 
     case SAVE_EXPR:
       return build1 (TRUTH_NOT_EXPR, type, arg);
@@ -3384,7 +3407,7 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type,
   if (lbitsize == 1 && ! integer_zerop (rhs))
     {
       code = code == EQ_EXPR ? NE_EXPR : EQ_EXPR;
-      rhs = fold_convert (type, integer_zero_node);
+      rhs = build_int_cst (type, 0);
     }
 
   /* Make a new bitfield reference, shift the constant over the
@@ -3721,7 +3744,7 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
      the switch, which will "break" the while.  */
 
   in_p = 0;
-  low = high = fold_convert (TREE_TYPE (exp), integer_zero_node);
+  low = high = build_int_cst (TREE_TYPE (exp), 0);
 
   while (1)
     {
@@ -3794,7 +3817,7 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
            {
              if (! merge_ranges (&n_in_p, &n_low, &n_high,
                                  in_p, low, high, 1,
-                                 fold_convert (arg0_type, integer_zero_node),
+                                 build_int_cst (arg0_type, 0),
                                  NULL_TREE))
                break;
 
@@ -3808,7 +3831,7 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
                  in_p = ! in_p;
                  high = range_binop (MINUS_EXPR, NULL_TREE, low, 0,
                                      integer_one_node, 0);
-                 low = fold_convert (arg0_type, integer_zero_node);
+                 low = build_int_cst (arg0_type, 0);
                }
            }
 
@@ -3818,10 +3841,10 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
        case NEGATE_EXPR:
          /* (-x) IN [a,b] -> x in [-b, -a]  */
          n_low = range_binop (MINUS_EXPR, exp_type,
-                              fold_convert (exp_type, integer_zero_node),
+                              build_int_cst (exp_type, 0),
                               0, high, 1);
          n_high = range_binop (MINUS_EXPR, exp_type,
-                               fold_convert (exp_type, integer_zero_node),
+                               build_int_cst (exp_type, 0),
                                0, low, 0);
          low = n_low, high = n_high;
          exp = arg0;
@@ -3830,13 +3853,18 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
        case BIT_NOT_EXPR:
          /* ~ X -> -X - 1  */
          exp = build2 (MINUS_EXPR, exp_type, negate_expr (arg0),
-                       fold_convert (exp_type, integer_one_node));
+                       build_int_cst (exp_type, 1));
          continue;
 
        case PLUS_EXPR:  case MINUS_EXPR:
          if (TREE_CODE (arg1) != INTEGER_CST)
            break;
 
+         /* If flag_wrapv and ARG0_TYPE is signed, then we cannot
+            move a constant to the other side.  */
+         if (flag_wrapv && !TYPE_UNSIGNED (arg0_type))
+           break;
+
          /* If EXP is signed, any overflow in the computation is undefined,
             so we don't worry about it so long as our computations on
             the bounds don't overflow.  For unsigned, overflow is defined
@@ -4005,7 +4033,7 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high)
     }
 
   if (low == 0 && high == 0)
-    return fold_convert (type, integer_one_node);
+    return build_int_cst (type, 1);
 
   if (low == 0)
     return fold_build2 (LE_EXPR, type, exp,
@@ -4057,7 +4085,7 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high)
              exp = fold_convert (etype, exp);
            }
          return fold_build2 (GT_EXPR, type, exp,
-                             fold_convert (etype, integer_zero_node));
+                             build_int_cst (etype, 0));
        }
     }
 
@@ -4073,7 +4101,6 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high)
        {
        case INTEGER_TYPE:
        case ENUMERAL_TYPE:
-       case CHAR_TYPE:
          /* There is no requirement that LOW be within the range of ETYPE
             if the latter is a subtype.  It must, however, be within the base
             type of ETYPE.  So be sure we do the subtraction in that type.  */
@@ -4252,7 +4279,6 @@ merge_ranges (int *pin_p, tree *plow, tree *phigh, int in0_p, tree low0,
                      break;
                    /* FALLTHROUGH */
                  case INTEGER_TYPE:
-                 case CHAR_TYPE:
                    if (tree_int_cst_equal (low0,
                                            TYPE_MIN_VALUE (TREE_TYPE (low0))))
                      low0 = 0;
@@ -4276,7 +4302,6 @@ merge_ranges (int *pin_p, tree *plow, tree *phigh, int in0_p, tree low0,
                      break;
                    /* FALLTHROUGH */
                  case INTEGER_TYPE:
-                 case CHAR_TYPE:
                    if (tree_int_cst_equal (high1,
                                            TYPE_MAX_VALUE (TREE_TYPE (high1))))
                      high1 = 0;
@@ -4421,7 +4446,7 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
       if (comp_code == NE_EXPR)
        return pedantic_non_lvalue (fold_convert (type, arg1));
       else if (comp_code == EQ_EXPR)
-       return fold_convert (type, integer_zero_node);
+       return build_int_cst (type, 0);
     }
 
   /* Try some transformations of A op B ? A : B.
@@ -4778,14 +4803,14 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
   if (lcode == BIT_AND_EXPR && integer_onep (TREE_OPERAND (lhs, 1)))
     {
       lhs = build2 (NE_EXPR, truth_type, lhs,
-                   fold_convert (TREE_TYPE (lhs), integer_zero_node));
+                   build_int_cst (TREE_TYPE (lhs), 0));
       lcode = NE_EXPR;
     }
 
   if (rcode == BIT_AND_EXPR && integer_onep (TREE_OPERAND (rhs, 1)))
     {
       rhs = build2 (NE_EXPR, truth_type, rhs,
-                   fold_convert (TREE_TYPE (rhs), integer_zero_node));
+                   build_int_cst (TREE_TYPE (rhs), 0));
       rcode = NE_EXPR;
     }
 
@@ -4844,7 +4869,7 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
        return build2 (NE_EXPR, truth_type,
                       build2 (BIT_IOR_EXPR, TREE_TYPE (ll_arg),
                               ll_arg, rl_arg),
-                      fold_convert (TREE_TYPE (ll_arg), integer_zero_node));
+                      build_int_cst (TREE_TYPE (ll_arg), 0));
 
       /* Convert (a == 0) && (b == 0) into (a | b) == 0.  */
       if (code == TRUTH_AND_EXPR
@@ -4854,7 +4879,7 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
        return build2 (EQ_EXPR, truth_type,
                       build2 (BIT_IOR_EXPR, TREE_TYPE (ll_arg),
                               ll_arg, rl_arg),
-                      fold_convert (TREE_TYPE (ll_arg), integer_zero_node));
+                      build_int_cst (TREE_TYPE (ll_arg), 0));
 
       if (LOGICAL_OP_NON_SHORT_CIRCUIT)
        return build2 (code, truth_type, lhs, rhs);
@@ -5989,6 +6014,7 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
   tree arg01 = TREE_OPERAND (arg0, 1);
   unsigned HOST_WIDE_INT lpart;
   HOST_WIDE_INT hpart;
+  bool neg_overflow;
   int overflow;
 
   /* We have to do this the hard way to detect unsigned overflow.
@@ -5999,6 +6025,7 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
                         TREE_INT_CST_HIGH (arg1), &lpart, &hpart);
   prod = build_int_cst_wide (TREE_TYPE (arg00), lpart, hpart);
   prod = force_fit_type (prod, -1, overflow, false);
+  neg_overflow = false;
 
   if (TYPE_UNSIGNED (TREE_TYPE (arg0)))
     {
@@ -6021,6 +6048,7 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
       switch (tree_int_cst_sgn (arg1))
        {
        case -1:
+         neg_overflow = true;
          lo = int_const_binop (MINUS_EXPR, prod, tmp, 0);
          hi = prod;
          break;
@@ -6058,7 +6086,8 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
          break;
 
        case  1:
-          lo = int_const_binop (PLUS_EXPR, prod, tmp, 0);
+         neg_overflow = true;
+         lo = int_const_binop (PLUS_EXPR, prod, tmp, 0);
          hi = prod;
          break;
 
@@ -6089,22 +6118,34 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
 
     case LT_EXPR:
       if (TREE_OVERFLOW (lo))
-       return omit_one_operand (type, integer_zero_node, arg00);
+       {
+         tmp = neg_overflow ? integer_zero_node : integer_one_node;
+         return omit_one_operand (type, tmp, arg00);
+       }
       return fold_build2 (LT_EXPR, type, arg00, lo);
 
     case LE_EXPR:
       if (TREE_OVERFLOW (hi))
-       return omit_one_operand (type, integer_one_node, arg00);
+       {
+         tmp = neg_overflow ? integer_zero_node : integer_one_node;
+         return omit_one_operand (type, tmp, arg00);
+       }
       return fold_build2 (LE_EXPR, type, arg00, hi);
 
     case GT_EXPR:
       if (TREE_OVERFLOW (hi))
-       return omit_one_operand (type, integer_zero_node, arg00);
+       {
+         tmp = neg_overflow ? integer_one_node : integer_zero_node;
+         return omit_one_operand (type, tmp, arg00);
+       }
       return fold_build2 (GT_EXPR, type, arg00, hi);
 
     case GE_EXPR:
       if (TREE_OVERFLOW (lo))
-       return omit_one_operand (type, integer_one_node, arg00);
+       {
+         tmp = neg_overflow ? integer_one_node : integer_zero_node;
+         return omit_one_operand (type, tmp, arg00);
+       }
       return fold_build2 (GE_EXPR, type, arg00, lo);
 
     default:
@@ -6142,7 +6183,7 @@ fold_single_bit_test_into_sign_test (enum tree_code code, tree arg0, tree arg1,
          tree stype = lang_hooks.types.signed_type (TREE_TYPE (arg00));
          return fold_build2 (code == EQ_EXPR ? GE_EXPR : LT_EXPR,
                              result_type, fold_convert (stype, arg00),
-                             fold_convert (stype, integer_zero_node));
+                             build_int_cst (stype, 0));
        }
     }
 
@@ -6810,7 +6851,7 @@ fold_unary (enum tree_code code, tree type, tree op0)
       if (TREE_TYPE (op0) == type)
        return op0;
       
-      /* If we have (type) (a CMP b) and type is an integal type, return
+      /* If we have (type) (a CMP b) and type is an integral type, return
          new expression involving the new type.  */
       if (COMPARISON_CLASS_P (op0) && INTEGRAL_TYPE_P (type))
        return fold_build2 (TREE_CODE (op0), type, TREE_OPERAND (op0, 0),
@@ -7156,91 +7197,550 @@ fold_unary (enum tree_code code, tree type, tree op0)
 }
 
 /* Fold a binary expression of code CODE and type TYPE with operands
-   OP0 and OP1.  Return the folded expression if folding is
-   successful.  Otherwise, return NULL_TREE.  */
+   OP0 and OP1, containing either a MIN-MAX or a MAX-MIN combination.
+   Return the folded expression if folding is successful.  Otherwise,
+   return NULL_TREE.  */
 
-tree
-fold_binary (enum tree_code code, tree type, tree op0, tree op1)
+static tree
+fold_minmax (enum tree_code code, tree type, tree op0, tree op1)
 {
-  tree t1 = NULL_TREE;
-  tree tem;
-  tree arg0 = NULL_TREE, arg1 = NULL_TREE;
-  enum tree_code_class kind = TREE_CODE_CLASS (code);
+  enum tree_code compl_code;
+
+  if (code == MIN_EXPR)
+    compl_code = MAX_EXPR;
+  else if (code == MAX_EXPR)
+    compl_code = MIN_EXPR;
+  else
+    gcc_unreachable ();
+
+  /* MIN (MAX (a, b), b) == b. Â */
+  if (TREE_CODE (op0) == compl_code
+      && operand_equal_p (TREE_OPERAND (op0, 1), op1, 0))
+    return omit_one_operand (type, op1, TREE_OPERAND (op0, 0));
+
+  /* MIN (MAX (b, a), b) == b. Â */
+  if (TREE_CODE (op0) == compl_code
+      && operand_equal_p (TREE_OPERAND (op0, 0), op1, 0)
+      && reorder_operands_p (TREE_OPERAND (op0, 1), op1))
+    return omit_one_operand (type, op1, TREE_OPERAND (op0, 1));
+
+  /* MIN (a, MAX (a, b)) == a. Â */
+  if (TREE_CODE (op1) == compl_code
+      && operand_equal_p (op0, TREE_OPERAND (op1, 0), 0)
+      && reorder_operands_p (op0, TREE_OPERAND (op1, 1)))
+    return omit_one_operand (type, op0, TREE_OPERAND (op1, 1));
+
+  /* MIN (a, MAX (b, a)) == a. Â */
+  if (TREE_CODE (op1) == compl_code
+      && operand_equal_p (op0, TREE_OPERAND (op1, 1), 0)
+      && reorder_operands_p (op0, TREE_OPERAND (op1, 0)))
+    return omit_one_operand (type, op0, TREE_OPERAND (op1, 0));
 
-  /* WINS will be nonzero when the switch is done
-     if all operands are constant.  */
-  int wins = 1;
+  return NULL_TREE;
+}
 
-  gcc_assert (IS_EXPR_CODE_CLASS (kind)
-             && TREE_CODE_LENGTH (code) == 2);
+/* Subroutine of fold_binary.  This routine performs all of the
+   transformations that are common to the equality/inequality
+   operators (EQ_EXPR and NE_EXPR) and the ordering operators
+   (LT_EXPR, LE_EXPR, GE_EXPR and GT_EXPR).  Callers other than
+   fold_binary should call fold_binary.  Fold a comparison with
+   tree code CODE and type TYPE with operands OP0 and OP1.  Return
+   the folded comparison or NULL_TREE.  */
+
+static tree
+fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
+{
+  tree arg0, arg1, tem;
 
   arg0 = op0;
   arg1 = op1;
 
-  if (arg0)
+  STRIP_SIGN_NOPS (arg0);
+  STRIP_SIGN_NOPS (arg1);
+
+  tem = fold_relational_const (code, type, arg0, arg1);
+  if (tem != NULL_TREE)
+    return tem;
+
+  /* If one arg is a real or integer constant, put it last.  */
+  if (tree_swap_operands_p (arg0, arg1, true))
+    return fold_build2 (swap_tree_comparison (code), type, op1, op0);
+
+  /* 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
+     comparison of the two offsets.  */
+  {
+    tree base0, offset0, base1, offset1;
+
+    if (extract_array_ref (arg0, &base0, &offset0)
+       && extract_array_ref (arg1, &base1, &offset1)
+       && operand_equal_p (base0, base1, 0))
+      {
+       /* Handle no offsets on both sides specially.  */
+       if (offset0 == NULL_TREE && offset1 == NULL_TREE)
+         return fold_build2 (code, type, integer_zero_node,
+                             integer_zero_node);
+
+       if (!offset0 || !offset1
+           || TREE_TYPE (offset0) == TREE_TYPE (offset1))
+         {
+           if (offset0 == NULL_TREE)
+             offset0 = build_int_cst (TREE_TYPE (offset1), 0);
+           if (offset1 == NULL_TREE)
+             offset1 = build_int_cst (TREE_TYPE (offset0), 0);
+           return fold_build2 (code, type, offset0, offset1);
+         }
+      }
+  }
+
+  /* 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 subop;
-
-      /* Strip any conversions that don't change the mode.  This is
-        safe for every expression, except for a comparison expression
-        because its signedness is derived from its operands.  So, in
-        the latter case, only strip conversions that don't change the
-        signedness.
-
-        Note that this is done as an internal manipulation within the
-        constant folder, in order to find the simplest representation
-        of the arguments so that their form can be studied.  In any
-        cases, the appropriate type conversions should be put back in
-        the tree that will get out of the constant folder.  */
-      if (kind == tcc_comparison)
-       STRIP_SIGN_NOPS (arg0);
-      else
-       STRIP_NOPS (arg0);
+      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);
+      tree targ1 = strip_float_extensions (arg1);
+      tree newtype = TREE_TYPE (targ0);
+
+      if (TYPE_PRECISION (TREE_TYPE (targ1)) > TYPE_PRECISION (newtype))
+       newtype = TREE_TYPE (targ1);
+
+      /* Fold (double)float1 CMP (double)float2 into float1 CMP float2.  */
+      if (TYPE_PRECISION (newtype) < TYPE_PRECISION (TREE_TYPE (arg0)))
+       return fold_build2 (code, type, fold_convert (newtype, targ0),
+                           fold_convert (newtype, targ1));
+
+      /* (-a) CMP (-b) -> b CMP a  */
+      if (TREE_CODE (arg0) == NEGATE_EXPR
+         && TREE_CODE (arg1) == NEGATE_EXPR)
+       return fold_build2 (code, type, TREE_OPERAND (arg1, 0),
+                           TREE_OPERAND (arg0, 0));
+
+      if (TREE_CODE (arg1) == REAL_CST)
+       {
+         REAL_VALUE_TYPE cst;
+         cst = TREE_REAL_CST (arg1);
+
+         /* (-a) CMP CST -> a swap(CMP) (-CST)  */
+         if (TREE_CODE (arg0) == NEGATE_EXPR)
+           return fold_build2 (swap_tree_comparison (code), type,
+                               TREE_OPERAND (arg0, 0),
+                               build_real (TREE_TYPE (arg1),
+                                           REAL_VALUE_NEGATE (cst)));
+
+         /* IEEE doesn't distinguish +0 and -0 in comparisons.  */
+         /* a CMP (-0) -> a CMP 0  */
+         if (REAL_VALUE_MINUS_ZERO (cst))
+           return fold_build2 (code, type, arg0,
+                               build_real (TREE_TYPE (arg1), dconst0));
+
+         /* x != NaN is always true, other ops are always false.  */
+         if (REAL_VALUE_ISNAN (cst)
+             && ! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1))))
+           {
+             tem = (code == NE_EXPR) ? integer_one_node : integer_zero_node;
+             return omit_one_operand (type, tem, arg0);
+           }
+
+         /* Fold comparisons against infinity.  */
+         if (REAL_VALUE_ISINF (cst))
+           {
+             tem = fold_inf_compare (code, type, arg0, arg1);
+             if (tem != NULL_TREE)
+               return tem;
+           }
+       }
+
+      /* If this is a comparison of a real constant with a PLUS_EXPR
+        or a MINUS_EXPR of a real constant, we can convert it into a
+        comparison with a revised real constant as long as no overflow
+        occurs when unsafe_math_optimizations are enabled.  */
+      if (flag_unsafe_math_optimizations
+         && TREE_CODE (arg1) == REAL_CST
+         && (TREE_CODE (arg0) == PLUS_EXPR
+             || TREE_CODE (arg0) == MINUS_EXPR)
+         && TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
+         && 0 != (tem = const_binop (TREE_CODE (arg0) == PLUS_EXPR
+                                     ? MINUS_EXPR : PLUS_EXPR,
+                                     arg1, TREE_OPERAND (arg0, 1), 0))
+         && ! TREE_CONSTANT_OVERFLOW (tem))
+       return fold_build2 (code, type, TREE_OPERAND (arg0, 0), tem);
+
+      /* Likewise, we can simplify a comparison of a real constant with
+         a MINUS_EXPR whose first operand is also a real constant, i.e.
+         (c1 - x) < c2 becomes x > c1-c2.  */
+      if (flag_unsafe_math_optimizations
+         && TREE_CODE (arg1) == REAL_CST
+         && TREE_CODE (arg0) == MINUS_EXPR
+         && TREE_CODE (TREE_OPERAND (arg0, 0)) == REAL_CST
+         && 0 != (tem = const_binop (MINUS_EXPR, TREE_OPERAND (arg0, 0),
+                                     arg1, 0))
+         && ! TREE_CONSTANT_OVERFLOW (tem))
+       return fold_build2 (swap_tree_comparison (code), type,
+                           TREE_OPERAND (arg0, 1), tem);
+
+      /* Fold comparisons against built-in math functions.  */
+      if (TREE_CODE (arg1) == REAL_CST
+         && flag_unsafe_math_optimizations
+         && ! flag_errno_math)
+       {
+         enum built_in_function fcode = builtin_mathfn_code (arg0);
+
+         if (fcode != END_BUILTINS)
+           {
+             tem = fold_mathfn_compare (fcode, code, type, arg0, arg1);
+             if (tem != NULL_TREE)
+               return tem;
+           }
+       }
+    }
+
+  /* Convert foo++ == CONST into ++foo == CONST + INCR.  */
+  if (TREE_CONSTANT (arg1)
+      && (TREE_CODE (arg0) == POSTINCREMENT_EXPR
+         || TREE_CODE (arg0) == POSTDECREMENT_EXPR)
+      /* This optimization is invalid for ordered comparisons
+         if CONST+INCR overflows or if foo+incr might overflow.
+        This optimization is invalid for floating point due to rounding.
+        For pointer types we assume overflow doesn't happen.  */
+      && (POINTER_TYPE_P (TREE_TYPE (arg0))
+         || (INTEGRAL_TYPE_P (TREE_TYPE (arg0))
+             && (code == EQ_EXPR || code == NE_EXPR))))
+    {
+      tree varop, newconst;
 
-      if (TREE_CODE (arg0) == COMPLEX_CST)
-       subop = TREE_REALPART (arg0);
+      if (TREE_CODE (arg0) == POSTINCREMENT_EXPR)
+       {
+         newconst = fold_build2 (PLUS_EXPR, TREE_TYPE (arg0),
+                                 arg1, TREE_OPERAND (arg0, 1));
+         varop = build2 (PREINCREMENT_EXPR, TREE_TYPE (arg0),
+                         TREE_OPERAND (arg0, 0),
+                         TREE_OPERAND (arg0, 1));
+       }
       else
-       subop = arg0;
+       {
+         newconst = fold_build2 (MINUS_EXPR, TREE_TYPE (arg0),
+                                 arg1, TREE_OPERAND (arg0, 1));
+         varop = build2 (PREDECREMENT_EXPR, TREE_TYPE (arg0),
+                         TREE_OPERAND (arg0, 0),
+                         TREE_OPERAND (arg0, 1));
+       }
+
+
+      /* If VAROP is a reference to a bitfield, we must mask
+        the constant by the width of the field.  */
+      if (TREE_CODE (TREE_OPERAND (varop, 0)) == COMPONENT_REF
+         && DECL_BIT_FIELD (TREE_OPERAND (TREE_OPERAND (varop, 0), 1))
+         && host_integerp (DECL_SIZE (TREE_OPERAND
+                                        (TREE_OPERAND (varop, 0), 1)), 1))
+       {
+         tree fielddecl = TREE_OPERAND (TREE_OPERAND (varop, 0), 1);
+         HOST_WIDE_INT size = tree_low_cst (DECL_SIZE (fielddecl), 1);
+         tree folded_compare, shift;
 
-      if (TREE_CODE (subop) != INTEGER_CST
-         && TREE_CODE (subop) != REAL_CST)
-       /* Note that TREE_CONSTANT isn't enough:
-          static var addresses are constant but we can't
-          do arithmetic on them.  */
-       wins = 0;
+         /* First check whether the comparison would come out
+            always the same.  If we don't do that we would
+            change the meaning with the masking.  */
+         folded_compare = fold_build2 (code, type,
+                                       TREE_OPERAND (varop, 0), arg1);
+         if (TREE_CODE (folded_compare) == INTEGER_CST)
+           return omit_one_operand (type, folded_compare, varop);
+
+         shift = build_int_cst (NULL_TREE,
+                                TYPE_PRECISION (TREE_TYPE (varop)) - size);
+         shift = fold_convert (TREE_TYPE (varop), shift);
+         newconst = fold_build2 (LSHIFT_EXPR, TREE_TYPE (varop),
+                                 newconst, shift);
+         newconst = fold_build2 (RSHIFT_EXPR, TREE_TYPE (varop),
+                                 newconst, shift);
+       }
+
+      return fold_build2 (code, type, varop, newconst);
     }
 
-  if (arg1)
+  if (TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE
+      && (TREE_CODE (arg0) == NOP_EXPR
+         || TREE_CODE (arg0) == CONVERT_EXPR))
     {
-      tree subop;
+      /* If we are widening one operand of an integer comparison,
+        see if the other operand is similarly being widened.  Perhaps we
+        can do the comparison in the narrower type.  */
+      tem = fold_widened_comparison (code, type, arg0, arg1);
+      if (tem)
+       return tem;
+
+      /* Or if we are changing signedness.  */
+      tem = fold_sign_changed_comparison (code, type, arg0, arg1);
+      if (tem)
+       return tem;
+    }
 
-      /* Strip any conversions that don't change the mode.  This is
-        safe for every expression, except for a comparison expression
-        because its signedness is derived from its operands.  So, in
-        the latter case, only strip conversions that don't change the
-        signedness.
+  /* If this is comparing a constant with a MIN_EXPR or a MAX_EXPR of a
+     constant, we can simplify it.  */
+  if (TREE_CODE (arg1) == INTEGER_CST
+      && (TREE_CODE (arg0) == MIN_EXPR
+         || TREE_CODE (arg0) == MAX_EXPR)
+      && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
+    {
+      tem = optimize_minmax_comparison (code, type, op0, op1);
+      if (tem)
+       return tem;
+    }
 
-        Note that this is done as an internal manipulation within the
-        constant folder, in order to find the simplest representation
-        of the arguments so that their form can be studied.  In any
-        cases, the appropriate type conversions should be put back in
-        the tree that will get out of the constant folder.  */
-      if (kind == tcc_comparison)
-       STRIP_SIGN_NOPS (arg1);
-      else
-       STRIP_NOPS (arg1);
+  /* Simplify comparison of something with itself.  (For IEEE
+     floating-point, we can only do some of these simplifications.)  */
+  if (operand_equal_p (arg0, arg1, 0))
+    {
+      switch (code)
+       {
+       case EQ_EXPR:
+         if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
+             || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
+           return constant_boolean_node (1, type);
+         break;
+
+       case GE_EXPR:
+       case LE_EXPR:
+         if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
+             || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
+           return constant_boolean_node (1, type);
+         return fold_build2 (EQ_EXPR, type, arg0, arg1);
+
+       case NE_EXPR:
+         /* For NE, we can only do this simplification if integer
+            or we don't honor IEEE floating point NaNs.  */
+         if (FLOAT_TYPE_P (TREE_TYPE (arg0))
+             && HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
+           break;
+         /* ... fall through ...  */
+       case GT_EXPR:
+       case LT_EXPR:
+         return constant_boolean_node (0, type);
+       default:
+         gcc_unreachable ();
+       }
+    }
+
+  /* If we are comparing an expression that just has comparisons
+     of two integer values, arithmetic expressions of those comparisons,
+     and constants, we can simplify it.  There are only three cases
+     to check: the two values can either be equal, the first can be
+     greater, or the second can be greater.  Fold the expression for
+     those three values.  Since each value must be 0 or 1, we have
+     eight possibilities, each of which corresponds to the constant 0
+     or 1 or one of the six possible comparisons.
+
+     This handles common cases like (a > b) == 0 but also handles
+     expressions like  ((x > y) - (y > x)) > 0, which supposedly
+     occur in macroized code.  */
+
+  if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg0) != INTEGER_CST)
+    {
+      tree cval1 = 0, cval2 = 0;
+      int save_p = 0;
+
+      if (twoval_comparison_p (arg0, &cval1, &cval2, &save_p)
+         /* Don't handle degenerate cases here; they should already
+            have been handled anyway.  */
+         && cval1 != 0 && cval2 != 0
+         && ! (TREE_CONSTANT (cval1) && TREE_CONSTANT (cval2))
+         && TREE_TYPE (cval1) == TREE_TYPE (cval2)
+         && INTEGRAL_TYPE_P (TREE_TYPE (cval1))
+         && TYPE_MAX_VALUE (TREE_TYPE (cval1))
+         && TYPE_MAX_VALUE (TREE_TYPE (cval2))
+         && ! operand_equal_p (TYPE_MIN_VALUE (TREE_TYPE (cval1)),
+                               TYPE_MAX_VALUE (TREE_TYPE (cval2)), 0))
+       {
+         tree maxval = TYPE_MAX_VALUE (TREE_TYPE (cval1));
+         tree minval = TYPE_MIN_VALUE (TREE_TYPE (cval1));
+
+         /* We can't just pass T to eval_subst in case cval1 or cval2
+            was the same as ARG1.  */
+
+         tree high_result
+               = fold_build2 (code, type,
+                              eval_subst (arg0, cval1, maxval,
+                                          cval2, minval),
+                              arg1);
+         tree equal_result
+               = fold_build2 (code, type,
+                              eval_subst (arg0, cval1, maxval,
+                                          cval2, maxval),
+                              arg1);
+         tree low_result
+               = fold_build2 (code, type,
+                              eval_subst (arg0, cval1, minval,
+                                          cval2, maxval),
+                              arg1);
+
+         /* All three of these results should be 0 or 1.  Confirm they are.
+            Then use those values to select the proper code to use.  */
+
+         if (TREE_CODE (high_result) == INTEGER_CST
+             && TREE_CODE (equal_result) == INTEGER_CST
+             && TREE_CODE (low_result) == INTEGER_CST)
+           {
+             /* Make a 3-bit mask with the high-order bit being the
+                value for `>', the next for '=', and the low for '<'.  */
+             switch ((integer_onep (high_result) * 4)
+                     + (integer_onep (equal_result) * 2)
+                     + integer_onep (low_result))
+               {
+               case 0:
+                 /* Always false.  */
+                 return omit_one_operand (type, integer_zero_node, arg0);
+               case 1:
+                 code = LT_EXPR;
+                 break;
+               case 2:
+                 code = EQ_EXPR;
+                 break;
+               case 3:
+                 code = LE_EXPR;
+                 break;
+               case 4:
+                 code = GT_EXPR;
+                 break;
+               case 5:
+                 code = NE_EXPR;
+                 break;
+               case 6:
+                 code = GE_EXPR;
+                 break;
+               case 7:
+                 /* Always true.  */
+                 return omit_one_operand (type, integer_one_node, arg0);
+               }
+
+             if (save_p)
+               return save_expr (build2 (code, type, cval1, cval2));
+             return fold_build2 (code, type, cval1, cval2);
+           }
+       }
+    }
+
+  /* Fold a comparison of the address of COMPONENT_REFs with the same
+     type and component to a comparison of the address of the base
+     object.  In short, &x->a OP &y->a to x OP y and
+     &x->a OP &y.a to x OP &y  */
+  if (TREE_CODE (arg0) == ADDR_EXPR
+      && TREE_CODE (TREE_OPERAND (arg0, 0)) == COMPONENT_REF
+      && TREE_CODE (arg1) == ADDR_EXPR
+      && TREE_CODE (TREE_OPERAND (arg1, 0)) == COMPONENT_REF)
+    {
+      tree cref0 = TREE_OPERAND (arg0, 0);
+      tree cref1 = TREE_OPERAND (arg1, 0);
+      if (TREE_OPERAND (cref0, 1) == TREE_OPERAND (cref1, 1))
+       {
+         tree op0 = TREE_OPERAND (cref0, 0);
+         tree op1 = TREE_OPERAND (cref1, 0);
+         return fold_build2 (code, type,
+                             build_fold_addr_expr (op0),
+                             build_fold_addr_expr (op1));
+       }
+    }
+
+  /* We can fold X/C1 op C2 where C1 and C2 are integer constants
+     into a single range test.  */
+  if ((TREE_CODE (arg0) == TRUNC_DIV_EXPR
+       || TREE_CODE (arg0) == EXACT_DIV_EXPR)
+      && TREE_CODE (arg1) == INTEGER_CST
+      && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
+      && !integer_zerop (TREE_OPERAND (arg0, 1))
+      && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))
+      && !TREE_OVERFLOW (arg1))
+    {
+      tem = fold_div_compare (code, type, arg0, arg1);
+      if (tem != NULL_TREE)
+       return tem;
+    }
+
+  return NULL_TREE;
+}
+
+/* Fold a binary expression of code CODE and type TYPE with operands
+   OP0 and OP1.  Return the folded expression if folding is
+   successful.  Otherwise, return NULL_TREE.  */
+
+tree
+fold_binary (enum tree_code code, tree type, tree op0, tree op1)
+{
+  enum tree_code_class kind = TREE_CODE_CLASS (code);
+  tree arg0, arg1, tem;
+  tree t1 = NULL_TREE;
+
+  gcc_assert (IS_EXPR_CODE_CLASS (kind)
+             && TREE_CODE_LENGTH (code) == 2
+             && op0 != NULL_TREE
+             && op1 != NULL_TREE);
+
+  arg0 = op0;
+  arg1 = op1;
+
+  /* Strip any conversions that don't change the mode.  This is
+     safe for every expression, except for a comparison expression
+     because its signedness is derived from its operands.  So, in
+     the latter case, only strip conversions that don't change the
+     signedness.
+
+     Note that this is done as an internal manipulation within the
+     constant folder, in order to find the simplest representation
+     of the arguments so that their form can be studied.  In any
+     cases, the appropriate type conversions should be put back in
+     the tree that will get out of the constant folder.  */
+
+  if (kind == tcc_comparison)
+    {
+      STRIP_SIGN_NOPS (arg0);
+      STRIP_SIGN_NOPS (arg1);
+    }
+  else
+    {
+      STRIP_NOPS (arg0);
+      STRIP_NOPS (arg1);
+    }
 
-      if (TREE_CODE (arg1) == COMPLEX_CST)
-       subop = TREE_REALPART (arg1);
+  /* Note that TREE_CONSTANT isn't enough: static var addresses are
+     constant but we can't do arithmetic on them.  */
+  if ((TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
+      || (TREE_CODE (arg0) == REAL_CST && TREE_CODE (arg1) == REAL_CST)
+      || (TREE_CODE (arg0) == COMPLEX_CST && TREE_CODE (arg1) == COMPLEX_CST)
+      || (TREE_CODE (arg0) == VECTOR_CST && TREE_CODE (arg1) == VECTOR_CST))
+    {
+      if (kind == tcc_binary)
+       tem = const_binop (code, arg0, arg1, 0);
+      else if (kind == tcc_comparison)
+       tem = fold_relational_const (code, type, arg0, arg1);
       else
-       subop = arg1;
+       tem = NULL_TREE;
 
-      if (TREE_CODE (subop) != INTEGER_CST
-         && TREE_CODE (subop) != REAL_CST)
-       /* Note that TREE_CONSTANT isn't enough:
-          static var addresses are constant but we can't
-          do arithmetic on them.  */
-       wins = 0;
+      if (tem != NULL_TREE)
+       {
+         if (TREE_TYPE (tem) != type)
+           tem = fold_convert (type, tem);
+         return tem;
+       }
     }
 
   /* If this is a commutative operation, and ARG0 is a constant, move it
@@ -7249,9 +7749,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       && tree_swap_operands_p (arg0, arg1, true))
     return fold_build2 (code, type, op1, op0);
 
-  /* Now WINS is set as described above,
-     ARG0 is the first operand of EXPR,
-     and ARG1 is the second operand (if it has more than one operand).
+  /* ARG0 is the first operand of EXPR, and ARG1 is the second operand.
 
      First check for cases where an arithmetic operation is applied to a
      compound, conditional, or comparison operation.  Push the arithmetic
@@ -7573,8 +8071,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
         don't associate floats at all, unless the user has specified
         -funsafe-math-optimizations.  */
 
-      if (! wins
-         && (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations))
+      if (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
        {
          tree var0, con0, lit0, minus_lit0;
          tree var1, con1, lit1, minus_lit1;
@@ -7648,18 +8145,6 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
            }
        }
 
-    binary:
-      if (wins)
-       t1 = const_binop (code, arg0, arg1, 0);
-      if (t1 != NULL_TREE)
-       {
-         /* The return value should always have
-            the same type as the original expression.  */
-         if (TREE_TYPE (t1) != type)
-           t1 = fold_convert (type, t1);
-
-         return t1;
-       }
       return NULL_TREE;
 
     case MINUS_EXPR:
@@ -7687,7 +8172,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
 
       if (! FLOAT_TYPE_P (type))
        {
-         if (! wins && integer_zerop (arg0))
+         if (integer_zerop (arg0))
            return negate_expr (fold_convert (type, arg1));
          if (integer_zerop (arg1))
            return non_lvalue (fold_convert (type, arg0));
@@ -7735,7 +8220,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       /* (ARG0 - ARG1) is the same as (-ARG1 + ARG0).  So check whether
         ARG0 is zero and X + ARG0 reduces to X, since that would mean
         (-ARG1 + ARG0) reduces to -ARG1.  */
-      else if (!wins && fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0))
+      else if (fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0))
        return negate_expr (fold_convert (type, arg1));
 
       /* Fold &x - &x.  This can happen from &x.foo - &x.
@@ -7749,7 +8234,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
        return fold_convert (type, integer_zero_node);
 
       /* A - B -> A + (-B) if B is easily negatable.  */
-      if (!wins && negate_expr_p (arg1)
+      if (negate_expr_p (arg1)
          && ((FLOAT_TYPE_P (type)
                /* Avoid this transformation if B is a positive REAL_CST.  */
               && (TREE_CODE (arg1) != REAL_CST
@@ -8084,13 +8569,80 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          return omit_one_operand (type, t1, arg0);
        }
 
-      t1 = distribute_bit_expr (code, type, arg0, arg1);
-      if (t1 != NULL_TREE)
-       return t1;
+      /* Canonicalize (X & C1) | C2.  */
+      if (TREE_CODE (arg0) == BIT_AND_EXPR
+         && TREE_CODE (arg1) == INTEGER_CST
+         && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
+       {
+         unsigned HOST_WIDE_INT hi1, lo1, hi2, lo2, mlo, mhi;
+         int width = TYPE_PRECISION (type);
+         hi1 = TREE_INT_CST_HIGH (TREE_OPERAND (arg0, 1));
+         lo1 = TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1));
+         hi2 = TREE_INT_CST_HIGH (arg1);
+         lo2 = TREE_INT_CST_LOW (arg1);
 
-      /* Convert (or (not arg0) (not arg1)) to (not (and (arg0) (arg1))).
+         /* If (C1&C2) == C1, then (X&C1)|C2 becomes (X,C2).  */
+         if ((hi1 & hi2) == hi1 && (lo1 & lo2) == lo1)
+           return omit_one_operand (type, arg1, TREE_OPERAND (arg0, 0));
 
-        This results in more efficient code for machines without a NAND
+         if (width > HOST_BITS_PER_WIDE_INT)
+           {
+             mhi = (unsigned HOST_WIDE_INT) -1 
+                   >> (2 * HOST_BITS_PER_WIDE_INT - width);
+             mlo = -1;
+           }
+         else
+           {
+             mhi = 0;
+             mlo = (unsigned HOST_WIDE_INT) -1
+                   >> (HOST_BITS_PER_WIDE_INT - width);
+           }
+
+         /* If (C1|C2) == ~0 then (X&C1)|C2 becomes X|C2.  */
+         if ((~(hi1 | hi2) & mhi) == 0 && (~(lo1 | lo2) & mlo) == 0)
+           return fold_build2 (BIT_IOR_EXPR, type,
+                               TREE_OPERAND (arg0, 0), arg1);
+
+         /* Minimize the number of bits set in C1, i.e. C1 := C1 & ~C2.  */
+         hi1 &= mhi;
+         lo1 &= mlo;
+         if ((hi1 & ~hi2) != hi1 || (lo1 & ~lo2) != lo1)
+           return fold_build2 (BIT_IOR_EXPR, type,
+                               fold_build2 (BIT_AND_EXPR, type,
+                                            TREE_OPERAND (arg0, 0),
+                                            build_int_cst_wide (type,
+                                                                lo1 & ~lo2,
+                                                                hi1 & ~hi2)),
+                               arg1);
+       }
+
+      /* (X & Y) | Y is (X, Y).  */
+      if (TREE_CODE (arg0) == BIT_AND_EXPR
+         && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
+       return omit_one_operand (type, arg1, TREE_OPERAND (arg0, 0));
+      /* (X & Y) | X is (Y, X).  */
+      if (TREE_CODE (arg0) == BIT_AND_EXPR
+         && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
+         && reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
+       return omit_one_operand (type, arg1, TREE_OPERAND (arg0, 1));
+      /* X | (X & Y) is (Y, X).  */
+      if (TREE_CODE (arg1) == BIT_AND_EXPR
+         && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0)
+         && reorder_operands_p (arg0, TREE_OPERAND (arg1, 1)))
+       return omit_one_operand (type, arg0, TREE_OPERAND (arg1, 1));
+      /* X | (Y & X) is (Y, X).  */
+      if (TREE_CODE (arg1) == BIT_AND_EXPR
+         && operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0)
+         && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
+       return omit_one_operand (type, arg0, TREE_OPERAND (arg1, 0));
+
+      t1 = distribute_bit_expr (code, type, arg0, arg1);
+      if (t1 != NULL_TREE)
+       return t1;
+
+      /* Convert (or (not arg0) (not arg1)) to (not (and (arg0) (arg1))).
+
+        This results in more efficient code for machines without a NAND
         instruction.  Combine will canonicalize to the first form
         which will allow use of NAND instructions provided by the
         backend if they exist.  */
@@ -8204,6 +8756,13 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                            fold_convert (type, TREE_OPERAND (arg0, 0)),
                            fold_convert (type, TREE_OPERAND (arg1, 0)));
 
+      /* Fold (X & 1) ^ 1 as (X & 1) == 0.  */
+      if (TREE_CODE (arg0) == BIT_AND_EXPR
+         && integer_onep (TREE_OPERAND (arg0, 1))
+         && integer_onep (arg1))
+       return fold_build2 (EQ_EXPR, type, arg0,
+                           build_int_cst (TREE_TYPE (arg0), 0));
+
       /* See if this can be simplified into a rotate first.  If that
         is unsuccessful continue in the association code.  */
       goto bit_rotate;
@@ -8226,6 +8785,58 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
        return omit_one_operand (type, integer_zero_node, arg0);
 
+      /* Canonicalize (X | C1) & C2 as (X & C2) | (C1 & C2).  */
+      if (TREE_CODE (arg0) == BIT_IOR_EXPR
+         && TREE_CODE (arg1) == INTEGER_CST
+         && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
+       return fold_build2 (BIT_IOR_EXPR, type,
+                           fold_build2 (BIT_AND_EXPR, type,
+                                        TREE_OPERAND (arg0, 0), arg1),
+                           fold_build2 (BIT_AND_EXPR, type,
+                                        TREE_OPERAND (arg0, 1), arg1));
+
+      /* (X | Y) & Y is (X, Y).  */
+      if (TREE_CODE (arg0) == BIT_IOR_EXPR
+         && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
+       return omit_one_operand (type, arg1, TREE_OPERAND (arg0, 0));
+      /* (X | Y) & X is (Y, X).  */
+      if (TREE_CODE (arg0) == BIT_IOR_EXPR
+         && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
+         && reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
+       return omit_one_operand (type, arg1, TREE_OPERAND (arg0, 1));
+      /* X & (X | Y) is (Y, X).  */
+      if (TREE_CODE (arg1) == BIT_IOR_EXPR
+         && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0)
+         && reorder_operands_p (arg0, TREE_OPERAND (arg1, 1)))
+       return omit_one_operand (type, arg0, TREE_OPERAND (arg1, 1));
+      /* X & (Y | X) is (Y, X).  */
+      if (TREE_CODE (arg1) == BIT_IOR_EXPR
+         && operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0)
+         && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
+       return omit_one_operand (type, arg0, TREE_OPERAND (arg1, 0));
+
+      /* Fold (X ^ 1) & 1 as (X & 1) == 0.  */
+      if (TREE_CODE (arg0) == BIT_XOR_EXPR
+         && integer_onep (TREE_OPERAND (arg0, 1))
+         && integer_onep (arg1))
+       {
+         tem = TREE_OPERAND (arg0, 0);
+         return fold_build2 (EQ_EXPR, type,
+                             fold_build2 (BIT_AND_EXPR, TREE_TYPE (tem), tem,
+                                          build_int_cst (TREE_TYPE (tem), 1)),
+                             build_int_cst (TREE_TYPE (tem), 0));
+       }
+      /* Fold ~X & 1 as (X & 1) == 0.  */
+      if (TREE_CODE (arg0) == BIT_NOT_EXPR
+         && integer_onep (arg1))
+       {
+         tem = TREE_OPERAND (arg0, 0);
+         return fold_build2 (EQ_EXPR, type,
+                             fold_build2 (BIT_AND_EXPR, TREE_TYPE (tem), tem,
+                                          build_int_cst (TREE_TYPE (tem), 1)),
+                             build_int_cst (TREE_TYPE (tem), 0));
+       }
+
       t1 = distribute_bit_expr (code, type, arg0, arg1);
       if (t1 != NULL_TREE)
        return t1;
@@ -8409,7 +9020,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
            }
 
          /* Optimize tan(x)/sin(x) as 1.0/cos(x) if we don't care about
-            NaNs or Infintes.  */
+            NaNs or Infinities.  */
          if (((fcode0 == BUILT_IN_TAN && fcode1 == BUILT_IN_SIN)
               || (fcode0 == BUILT_IN_TANF && fcode1 == BUILT_IN_SINF)
               || (fcode0 == BUILT_IN_TANL && fcode1 == BUILT_IN_SINL)))
@@ -8427,9 +9038,9 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                    {
                      tree tmp = TREE_OPERAND (arg0, 1);
                      tmp = build_function_call_expr (cosfn, tmp);
-                     return fold (build (RDIV_EXPR, type,
+                     return fold_build2 (RDIV_EXPR, type,
                                          build_real (type, dconst1),
-                                         tmp));
+                                         tmp);
                    }
                }
            }
@@ -8484,7 +9095,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              return fold_build2 (MULT_EXPR, type, arg0, arg1);
            }
        }
-      goto binary;
+      return NULL_TREE;
 
     case TRUNC_DIV_EXPR:
     case ROUND_DIV_EXPR:
@@ -8529,7 +9140,7 @@ 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);
 
-      goto binary;
+      return NULL_TREE;
 
     case CEIL_MOD_EXPR:
     case FLOOR_MOD_EXPR:
@@ -8609,7 +9220,7 @@ 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);
 
-      goto binary;
+      return NULL_TREE;
 
     case LROTATE_EXPR:
     case RROTATE_EXPR:
@@ -8723,7 +9334,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              == (unsigned int) GET_MODE_BITSIZE (TYPE_MODE (type))))
        return TREE_OPERAND (arg0, 0);
 
-      goto binary;
+      return NULL_TREE;
 
     case MIN_EXPR:
       if (operand_equal_p (arg0, arg1, 0))
@@ -8731,6 +9342,9 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       if (INTEGRAL_TYPE_P (type)
          && operand_equal_p (arg1, TYPE_MIN_VALUE (type), OEP_ONLY_CONST))
        return omit_one_operand (type, arg1, arg0);
+      tem = fold_minmax (MIN_EXPR, type, arg0, arg1);
+      if (tem)
+       return tem;
       goto associate;
 
     case MAX_EXPR:
@@ -8740,6 +9354,9 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && TYPE_MAX_VALUE (type)
          && operand_equal_p (arg1, TYPE_MAX_VALUE (type), OEP_ONLY_CONST))
        return omit_one_operand (type, arg1, arg0);
+      tem = fold_minmax (MAX_EXPR, type, arg0, arg1);
+      if (tem)
+       return tem;
       goto associate;
 
     case TRUTH_ANDIF_EXPR:
@@ -8922,26 +9539,15 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
 
     case EQ_EXPR:
     case NE_EXPR:
-    case LT_EXPR:
-    case GT_EXPR:
-    case LE_EXPR:
-    case GE_EXPR:      
-      /* If one arg is a real or integer constant, put it last.  */
-      if (tree_swap_operands_p (arg0, arg1, true))
-       return fold_build2 (swap_tree_comparison (code), type, op1, op0);
+      tem = fold_comparison (code, type, op0, op1);
+      if (tem != NULL_TREE)
+       return tem;
 
-      /*  ~a != C becomes a != ~C where C is a constant.  Likewise for ==.  */
-      if (TREE_CODE (arg0) == BIT_NOT_EXPR && TREE_CODE (arg1) == INTEGER_CST
-         && (code == NE_EXPR || code == EQ_EXPR))
-       return fold_build2 (code, type, TREE_OPERAND (arg0, 0),
-                           fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg1), 
-                                        arg1));
-       
       /* bool_var != 0 becomes bool_var. */
       if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_zerop (arg1)
           && code == NE_EXPR)
         return non_lvalue (fold_convert (type, arg0));
-       
+
       /* bool_var == 1 becomes bool_var. */
       if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_onep (arg1)
           && code == EQ_EXPR)
@@ -8957,10 +9563,16 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
           && code == EQ_EXPR)
         return fold_build1 (TRUTH_NOT_EXPR, type, arg0);
 
+      /*  ~a != C becomes a != ~C where C is a constant.  Likewise for ==.  */
+      if (TREE_CODE (arg0) == BIT_NOT_EXPR
+         && TREE_CODE (arg1) == INTEGER_CST)
+       return fold_build2 (code, type, TREE_OPERAND (arg0, 0),
+                           fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg1), 
+                                        arg1));
+
       /* If this is an equality comparison of the address of a non-weak
         object against zero, then we know the result.  */
-      if ((code == EQ_EXPR || code == NE_EXPR)
-         && TREE_CODE (arg0) == ADDR_EXPR
+      if (TREE_CODE (arg0) == ADDR_EXPR
          && VAR_OR_FUNCTION_DECL_P (TREE_OPERAND (arg0, 0))
          && ! DECL_WEAK (TREE_OPERAND (arg0, 0))
          && integer_zerop (arg1))
@@ -8969,8 +9581,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       /* If this is an equality comparison of the address of two non-weak,
         unaliased symbols neither of which are extern (since we do not
         have access to attributes for externs), then we know the result.  */
-      if ((code == EQ_EXPR || code == NE_EXPR)
-         && TREE_CODE (arg0) == ADDR_EXPR
+      if (TREE_CODE (arg0) == ADDR_EXPR
          && VAR_OR_FUNCTION_DECL_P (TREE_OPERAND (arg0, 0))
          && ! DECL_WEAK (TREE_OPERAND (arg0, 0))
          && ! lookup_attribute ("alias",
@@ -9000,38 +9611,341 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                                        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
-        comparison of the two offsets.  */
-      if (TREE_CODE_CLASS (code) == tcc_comparison)
+      /* If this is an EQ or NE comparison of a constant with a PLUS_EXPR or
+        a MINUS_EXPR of a constant, we can convert it into a comparison with
+        a revised constant as long as no overflow occurs.  */
+      if (TREE_CODE (arg1) == INTEGER_CST
+         && (TREE_CODE (arg0) == PLUS_EXPR
+             || TREE_CODE (arg0) == MINUS_EXPR)
+         && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
+         && 0 != (tem = const_binop (TREE_CODE (arg0) == PLUS_EXPR
+                                     ? MINUS_EXPR : PLUS_EXPR,
+                                     arg1, TREE_OPERAND (arg0, 1), 0))
+         && ! TREE_CONSTANT_OVERFLOW (tem))
+       return fold_build2 (code, type, TREE_OPERAND (arg0, 0), tem);
+
+      /* Similarly for a NEGATE_EXPR.  */
+      if (TREE_CODE (arg0) == NEGATE_EXPR
+         && TREE_CODE (arg1) == INTEGER_CST
+         && 0 != (tem = negate_expr (arg1))
+         && TREE_CODE (tem) == INTEGER_CST
+         && ! TREE_CONSTANT_OVERFLOW (tem))
+       return fold_build2 (code, type, TREE_OPERAND (arg0, 0), tem);
+
+      /* If we have X - Y == 0, we can convert that to X == Y and similarly
+        for !=.  Don't do this for ordered comparisons due to overflow.  */
+      if (TREE_CODE (arg0) == MINUS_EXPR
+         && integer_zerop (arg1))
+       return fold_build2 (code, type,
+                           TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1));
+
+      /* Convert ABS_EXPR<x> == 0 or ABS_EXPR<x> != 0 to x == 0 or x != 0.  */
+      if (TREE_CODE (arg0) == ABS_EXPR
+         && (integer_zerop (arg1) || real_zerop (arg1)))
+       return fold_build2 (code, type, TREE_OPERAND (arg0, 0), arg1);
+
+      /* If this is an EQ or NE comparison with zero and ARG0 is
+        (1 << foo) & bar, convert it to (bar >> foo) & 1.  Both require
+        two operations, but the latter can be done in one less insn
+        on machines that have only two-operand insns or on which a
+        constant cannot be the first operand.  */
+      if (TREE_CODE (arg0) == BIT_AND_EXPR
+         && integer_zerop (arg1))
+       {
+         tree arg00 = TREE_OPERAND (arg0, 0);
+         tree arg01 = TREE_OPERAND (arg0, 1);
+         if (TREE_CODE (arg00) == LSHIFT_EXPR
+             && integer_onep (TREE_OPERAND (arg00, 0)))
+           return
+             fold_build2 (code, type,
+                          build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
+                                  build2 (RSHIFT_EXPR, TREE_TYPE (arg00),
+                                          arg01, TREE_OPERAND (arg00, 1)),
+                                  fold_convert (TREE_TYPE (arg0),
+                                                integer_one_node)),
+                          arg1);
+         else if (TREE_CODE (TREE_OPERAND (arg0, 1)) == LSHIFT_EXPR
+                  && integer_onep (TREE_OPERAND (TREE_OPERAND (arg0, 1), 0)))
+           return
+             fold_build2 (code, type,
+                          build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
+                                  build2 (RSHIFT_EXPR, TREE_TYPE (arg01),
+                                          arg00, TREE_OPERAND (arg01, 1)),
+                                  fold_convert (TREE_TYPE (arg0),
+                                                integer_one_node)),
+                          arg1);
+       }
+
+      /* If this is an NE or EQ comparison of zero against the result of a
+        signed MOD operation whose second operand is a power of 2, make
+        the MOD operation unsigned since it is simpler and equivalent.  */
+      if (integer_zerop (arg1)
+         && !TYPE_UNSIGNED (TREE_TYPE (arg0))
+         && (TREE_CODE (arg0) == TRUNC_MOD_EXPR
+             || TREE_CODE (arg0) == CEIL_MOD_EXPR
+             || TREE_CODE (arg0) == FLOOR_MOD_EXPR
+             || TREE_CODE (arg0) == ROUND_MOD_EXPR)
+         && integer_pow2p (TREE_OPERAND (arg0, 1)))
+       {
+         tree newtype = lang_hooks.types.unsigned_type (TREE_TYPE (arg0));
+         tree newmod = fold_build2 (TREE_CODE (arg0), newtype,
+                                    fold_convert (newtype,
+                                                  TREE_OPERAND (arg0, 0)),
+                                    fold_convert (newtype,
+                                                  TREE_OPERAND (arg0, 1)));
+
+         return fold_build2 (code, type, newmod,
+                             fold_convert (newtype, arg1));
+       }
+
+      /* Fold ((X >> C1) & C2) == 0 and ((X >> C1) & C2) != 0 where
+        C1 is a valid shift constant, and C2 is a power of two, i.e.
+        a single bit.  */
+      if (TREE_CODE (arg0) == BIT_AND_EXPR
+         && TREE_CODE (TREE_OPERAND (arg0, 0)) == RSHIFT_EXPR
+         && TREE_CODE (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1))
+            == INTEGER_CST
+         && integer_pow2p (TREE_OPERAND (arg0, 1))
+         && integer_zerop (arg1))
        {
-         tree base0, offset0, base1, offset1;
+         tree itype = TREE_TYPE (arg0);
+         unsigned HOST_WIDE_INT prec = TYPE_PRECISION (itype);
+         tree arg001 = TREE_OPERAND (TREE_OPERAND (arg0, 0), 1);
 
-         if (extract_array_ref (arg0, &base0, &offset0)
-             && extract_array_ref (arg1, &base1, &offset1)
-             && operand_equal_p (base0, base1, 0))
+         /* Check for a valid shift count.  */
+         if (TREE_INT_CST_HIGH (arg001) == 0
+             && TREE_INT_CST_LOW (arg001) < prec)
            {
-             /* Handle no offsets on both sides specially.  */
-             if (offset0 == NULL_TREE
-                 && offset1 == NULL_TREE)
-               return fold_build2 (code, type, integer_zero_node,
-                                   integer_zero_node);
-
-             if (!offset0 || !offset1
-                 || TREE_TYPE (offset0) == TREE_TYPE (offset1))
+             tree arg01 = TREE_OPERAND (arg0, 1);
+             tree arg000 = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+             unsigned HOST_WIDE_INT log2 = tree_log2 (arg01);
+             /* If (C2 << C1) doesn't overflow, then ((X >> C1) & C2) != 0
+                can be rewritten as (X & (C2 << C1)) != 0.  */
+             if ((log2 + TREE_INT_CST_LOW (arg01)) < prec)
                {
-                 if (offset0 == NULL_TREE)
-                   offset0 = build_int_cst (TREE_TYPE (offset1), 0);
-                 if (offset1 == NULL_TREE)
-                   offset1 = build_int_cst (TREE_TYPE (offset0), 0);
-                 return fold_build2 (code, type, offset0, offset1);
+                 tem = fold_build2 (LSHIFT_EXPR, itype, arg01, arg001);
+                 tem = fold_build2 (BIT_AND_EXPR, itype, arg000, tem);
+                 return fold_build2 (code, type, tem, arg1);
                }
+             /* Otherwise, for signed (arithmetic) shifts,
+                ((X >> C1) & C2) != 0 is rewritten as X < 0, and
+                ((X >> C1) & C2) == 0 is rewritten as X >= 0.  */
+             else if (!TYPE_UNSIGNED (itype))
+               return fold_build2 (code == EQ_EXPR ? GE_EXPR : LT_EXPR, type,
+                                   arg000, build_int_cst (itype, 0));
+             /* Otherwise, of unsigned (logical) shifts,
+                ((X >> C1) & C2) != 0 is rewritten as (X,false), and
+                ((X >> C1) & C2) == 0 is rewritten as (X,true).  */
+             else
+               return omit_one_operand (type,
+                                        code == EQ_EXPR ? integer_one_node
+                                                        : integer_zero_node,
+                                        arg000);
            }
        }
 
+      /* If this is an NE comparison of zero with an AND of one, remove the
+        comparison since the AND will give the correct value.  */
+      if (code == NE_EXPR
+         && integer_zerop (arg1)
+         && TREE_CODE (arg0) == BIT_AND_EXPR
+         && integer_onep (TREE_OPERAND (arg0, 1)))
+       return fold_convert (type, arg0);
+
+      /* If we have (A & C) == C where C is a power of 2, convert this into
+        (A & C) != 0.  Similarly for NE_EXPR.  */
+      if (TREE_CODE (arg0) == BIT_AND_EXPR
+         && integer_pow2p (TREE_OPERAND (arg0, 1))
+         && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
+       return fold_build2 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
+                           arg0, fold_convert (TREE_TYPE (arg0),
+                                               integer_zero_node));
+
+      /* If we have (A & C) != 0 or (A & C) == 0 and C is the sign
+        bit, then fold the expression into A < 0 or A >= 0.  */
+      tem = fold_single_bit_test_into_sign_test (code, arg0, arg1, type);
+      if (tem)
+       return tem;
+
+      /* If we have (A & C) == D where D & ~C != 0, convert this into 0.
+        Similarly for NE_EXPR.  */
+      if (TREE_CODE (arg0) == BIT_AND_EXPR
+         && TREE_CODE (arg1) == INTEGER_CST
+         && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
+       {
+         tree notc = fold_build1 (BIT_NOT_EXPR,
+                                  TREE_TYPE (TREE_OPERAND (arg0, 1)),
+                                  TREE_OPERAND (arg0, 1));
+         tree dandnotc = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
+                                      arg1, notc);
+         tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
+         if (integer_nonzerop (dandnotc))
+           return omit_one_operand (type, rslt, arg0);
+       }
+
+      /* If we have (A | C) == D where C & ~D != 0, convert this into 0.
+        Similarly for NE_EXPR.  */
+      if (TREE_CODE (arg0) == BIT_IOR_EXPR
+         && TREE_CODE (arg1) == INTEGER_CST
+         && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
+       {
+         tree notd = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg1), arg1);
+         tree candnotd = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
+                                      TREE_OPERAND (arg0, 1), notd);
+         tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
+         if (integer_nonzerop (candnotd))
+           return omit_one_operand (type, rslt, arg0);
+       }
+
+      /* If this is a comparison of a field, we may be able to simplify it.  */
+      if (((TREE_CODE (arg0) == COMPONENT_REF
+           && lang_hooks.can_use_bit_fields_p ())
+          || TREE_CODE (arg0) == BIT_FIELD_REF)
+         /* Handle the constant case even without -O
+            to make sure the warnings are given.  */
+         && (optimize || TREE_CODE (arg1) == INTEGER_CST))
+       {
+         t1 = optimize_bit_field_compare (code, type, arg0, arg1);
+         if (t1)
+           return t1;
+       }
+
+      /* 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
+               strlen(ptr) != 0   =>  *ptr != 0
+        Other cases should reduce to one of these two (or a constant)
+        due to the return value of strlen being unsigned.  */
+      if (TREE_CODE (arg0) == CALL_EXPR
+         && integer_zerop (arg1))
+       {
+         tree fndecl = get_callee_fndecl (arg0);
+         tree arglist;
+
+         if (fndecl
+             && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
+             && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRLEN
+             && (arglist = TREE_OPERAND (arg0, 1))
+             && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE
+             && ! TREE_CHAIN (arglist))
+           {
+             tree iref = build_fold_indirect_ref (TREE_VALUE (arglist));
+             return fold_build2 (code, type, iref,
+                                 build_int_cst (TREE_TYPE (iref), 0));
+           }
+       }
+
+      /* Fold (X >> C) != 0 into X < 0 if C is one less than the width
+        of X.  Similarly fold (X >> C) == 0 into X >= 0.  */
+      if (TREE_CODE (arg0) == RSHIFT_EXPR
+         && integer_zerop (arg1)
+         && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
+       {
+         tree arg00 = TREE_OPERAND (arg0, 0);
+         tree arg01 = TREE_OPERAND (arg0, 1);
+         tree itype = TREE_TYPE (arg00);
+         if (TREE_INT_CST_HIGH (arg01) == 0
+             && TREE_INT_CST_LOW (arg01)
+                == (unsigned HOST_WIDE_INT) (TYPE_PRECISION (itype) - 1))
+           {
+             if (TYPE_UNSIGNED (itype))
+               {
+                 itype = lang_hooks.types.signed_type (itype);
+                 arg00 = fold_convert (itype, arg00);
+               }
+             return fold_build2 (code == EQ_EXPR ? GE_EXPR : LT_EXPR,
+                                 type, arg00, build_int_cst (itype, 0));
+           }
+       }
+
+      /* (X ^ Y) == 0 becomes X == Y, and (X ^ Y) != 0 becomes X != Y.  */
+      if (integer_zerop (arg1)
+         && TREE_CODE (arg0) == BIT_XOR_EXPR)
+       return fold_build2 (code, type, TREE_OPERAND (arg0, 0),
+                           TREE_OPERAND (arg0, 1));
+
+      /* (X ^ Y) == Y becomes X == 0.  We know that Y has no side-effects.  */
+      if (TREE_CODE (arg0) == BIT_XOR_EXPR
+         && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
+       return fold_build2 (code, type, TREE_OPERAND (arg0, 0),
+                           build_int_cst (TREE_TYPE (arg1), 0));
+      /* Likewise (X ^ Y) == X becomes Y == 0.  X has no side-effects.  */
+      if (TREE_CODE (arg0) == BIT_XOR_EXPR
+         && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
+         && reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
+       return fold_build2 (code, type, TREE_OPERAND (arg0, 1),
+                           build_int_cst (TREE_TYPE (arg1), 0));
+
+      /* (X ^ C1) op C2 can be rewritten as X op (C1 ^ C2).  */
+      if (TREE_CODE (arg0) == BIT_XOR_EXPR
+         && TREE_CODE (arg1) == INTEGER_CST
+         && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
+       return fold_build2 (code, type, TREE_OPERAND (arg0, 0),
+                           fold_build2 (BIT_XOR_EXPR, TREE_TYPE (arg1),
+                                        TREE_OPERAND (arg0, 1), arg1));
+
+      /* Fold (~X & C) == 0 into (X & C) != 0 and (~X & C) != 0 into
+        (X & C) == 0 when C is a single bit.  */
+      if (TREE_CODE (arg0) == BIT_AND_EXPR
+         && TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_NOT_EXPR
+         && integer_zerop (arg1)
+         && integer_pow2p (TREE_OPERAND (arg0, 1)))
+       {
+         tem = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
+                            TREE_OPERAND (TREE_OPERAND (arg0, 0), 0),
+                            TREE_OPERAND (arg0, 1));
+         return fold_build2 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR,
+                             type, tem, arg1);
+       }
+
+      /* Fold ((X & C) ^ C) eq/ne 0 into (X & C) ne/eq 0, when the
+        constant C is a power of two, i.e. a single bit.  */
+      if (TREE_CODE (arg0) == BIT_XOR_EXPR
+         && TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_AND_EXPR
+         && integer_zerop (arg1)
+         && integer_pow2p (TREE_OPERAND (arg0, 1))
+         && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1),
+                             TREE_OPERAND (arg0, 1), OEP_ONLY_CONST))
+       {
+         tree arg00 = TREE_OPERAND (arg0, 0);
+         return fold_build2 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
+                             arg00, build_int_cst (TREE_TYPE (arg00), 0));
+       }
+
+      /* Likewise, fold ((X ^ C) & C) eq/ne 0 into (X & C) ne/eq 0,
+        when is C is a power of two, i.e. a single bit.  */
+      if (TREE_CODE (arg0) == BIT_AND_EXPR
+         && TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_XOR_EXPR
+         && integer_zerop (arg1)
+         && integer_pow2p (TREE_OPERAND (arg0, 1))
+         && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1),
+                             TREE_OPERAND (arg0, 1), OEP_ONLY_CONST))
+       {
+         tree arg000 = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+         tem = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg000),
+                            arg000, TREE_OPERAND (arg0, 1));
+         return fold_build2 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
+                             tem, build_int_cst (TREE_TYPE (tem), 0));
+       }
+
+      if (integer_zerop (arg1)
+         && tree_expr_nonzero_p (arg0))
+        {
+         tree res = constant_boolean_node (code==NE_EXPR, type);
+         return omit_one_operand (type, res, arg0);
+       }
+      return NULL_TREE;
+
+    case LT_EXPR:
+    case GT_EXPR:
+    case LE_EXPR:
+    case GE_EXPR:
+      tem = fold_comparison (code, type, op0, op1);
+      if (tem != NULL_TREE)
+       return tem;
+
       /* Transform comparisons of the form X +- C CMP X.  */
-      if ((code != EQ_EXPR && code != NE_EXPR)
-         && (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
+      if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
          && ((TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
               && !HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0))))
@@ -9100,194 +10014,6 @@ 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);
-         tree targ1 = strip_float_extensions (arg1);
-         tree newtype = TREE_TYPE (targ0);
-
-         if (TYPE_PRECISION (TREE_TYPE (targ1)) > TYPE_PRECISION (newtype))
-           newtype = TREE_TYPE (targ1);
-
-         /* Fold (double)float1 CMP (double)float2 into float1 CMP float2.  */
-         if (TYPE_PRECISION (newtype) < TYPE_PRECISION (TREE_TYPE (arg0)))
-           return fold_build2 (code, type, fold_convert (newtype, targ0),
-                               fold_convert (newtype, targ1));
-
-         /* (-a) CMP (-b) -> b CMP a  */
-         if (TREE_CODE (arg0) == NEGATE_EXPR
-             && TREE_CODE (arg1) == NEGATE_EXPR)
-           return fold_build2 (code, type, TREE_OPERAND (arg1, 0),
-                               TREE_OPERAND (arg0, 0));
-
-         if (TREE_CODE (arg1) == REAL_CST)
-         {
-           REAL_VALUE_TYPE cst;
-           cst = TREE_REAL_CST (arg1);
-
-           /* (-a) CMP CST -> a swap(CMP) (-CST)  */
-           if (TREE_CODE (arg0) == NEGATE_EXPR)
-             return
-               fold_build2 (swap_tree_comparison (code), type,
-                            TREE_OPERAND (arg0, 0),
-                            build_real (TREE_TYPE (arg1),
-                                        REAL_VALUE_NEGATE (cst)));
-
-           /* IEEE doesn't distinguish +0 and -0 in comparisons.  */
-           /* a CMP (-0) -> a CMP 0  */
-           if (REAL_VALUE_MINUS_ZERO (cst))
-             return fold_build2 (code, type, arg0,
-                                 build_real (TREE_TYPE (arg1), dconst0));
-
-           /* x != NaN is always true, other ops are always false.  */
-           if (REAL_VALUE_ISNAN (cst)
-               && ! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1))))
-             {
-               tem = (code == NE_EXPR) ? integer_one_node : integer_zero_node;
-               return omit_one_operand (type, tem, arg0);
-             }
-
-           /* Fold comparisons against infinity.  */
-           if (REAL_VALUE_ISINF (cst))
-             {
-               tem = fold_inf_compare (code, type, arg0, arg1);
-               if (tem != NULL_TREE)
-                 return tem;
-             }
-         }
-
-         /* If this is a comparison of a real constant with a PLUS_EXPR
-            or a MINUS_EXPR of a real constant, we can convert it into a
-            comparison with a revised real constant as long as no overflow
-            occurs when unsafe_math_optimizations are enabled.  */
-         if (flag_unsafe_math_optimizations
-             && TREE_CODE (arg1) == REAL_CST
-             && (TREE_CODE (arg0) == PLUS_EXPR
-                 || TREE_CODE (arg0) == MINUS_EXPR)
-             && TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
-             && 0 != (tem = const_binop (TREE_CODE (arg0) == PLUS_EXPR
-                                         ? MINUS_EXPR : PLUS_EXPR,
-                                         arg1, TREE_OPERAND (arg0, 1), 0))
-             && ! TREE_CONSTANT_OVERFLOW (tem))
-           return fold_build2 (code, type, TREE_OPERAND (arg0, 0), tem);
-
-         /* Likewise, we can simplify a comparison of a real constant with
-            a MINUS_EXPR whose first operand is also a real constant, i.e.
-            (c1 - x) < c2 becomes x > c1-c2.  */
-         if (flag_unsafe_math_optimizations
-             && TREE_CODE (arg1) == REAL_CST
-             && TREE_CODE (arg0) == MINUS_EXPR
-             && TREE_CODE (TREE_OPERAND (arg0, 0)) == REAL_CST
-             && 0 != (tem = const_binop (MINUS_EXPR, TREE_OPERAND (arg0, 0),
-                                         arg1, 0))
-             && ! TREE_CONSTANT_OVERFLOW (tem))
-           return fold_build2 (swap_tree_comparison (code), type,
-                               TREE_OPERAND (arg0, 1), tem);
-
-         /* Fold comparisons against built-in math functions.  */
-         if (TREE_CODE (arg1) == REAL_CST
-             && flag_unsafe_math_optimizations
-             && ! flag_errno_math)
-           {
-             enum built_in_function fcode = builtin_mathfn_code (arg0);
-
-             if (fcode != END_BUILTINS)
-               {
-                 tem = fold_mathfn_compare (fcode, code, type, arg0, arg1);
-                 if (tem != NULL_TREE)
-                   return tem;
-               }
-           }
-       }
-
-      /* Convert foo++ == CONST into ++foo == CONST + INCR.  */
-      if (TREE_CONSTANT (arg1)
-         && (TREE_CODE (arg0) == POSTINCREMENT_EXPR
-             || TREE_CODE (arg0) == POSTDECREMENT_EXPR)
-         /* This optimization is invalid for ordered comparisons
-            if CONST+INCR overflows or if foo+incr might overflow.
-            This optimization is invalid for floating point due to rounding.
-            For pointer types we assume overflow doesn't happen.  */
-         && (POINTER_TYPE_P (TREE_TYPE (arg0))
-             || (INTEGRAL_TYPE_P (TREE_TYPE (arg0))
-                 && (code == EQ_EXPR || code == NE_EXPR))))
-       {
-         tree varop, newconst;
-
-         if (TREE_CODE (arg0) == POSTINCREMENT_EXPR)
-           {
-             newconst = fold_build2 (PLUS_EXPR, TREE_TYPE (arg0),
-                                     arg1, TREE_OPERAND (arg0, 1));
-             varop = build2 (PREINCREMENT_EXPR, TREE_TYPE (arg0),
-                             TREE_OPERAND (arg0, 0),
-                             TREE_OPERAND (arg0, 1));
-           }
-         else
-           {
-             newconst = fold_build2 (MINUS_EXPR, TREE_TYPE (arg0),
-                                     arg1, TREE_OPERAND (arg0, 1));
-             varop = build2 (PREDECREMENT_EXPR, TREE_TYPE (arg0),
-                             TREE_OPERAND (arg0, 0),
-                             TREE_OPERAND (arg0, 1));
-           }
-
-
-         /* If VAROP is a reference to a bitfield, we must mask
-            the constant by the width of the field.  */
-         if (TREE_CODE (TREE_OPERAND (varop, 0)) == COMPONENT_REF
-             && DECL_BIT_FIELD (TREE_OPERAND (TREE_OPERAND (varop, 0), 1))
-             && host_integerp (DECL_SIZE (TREE_OPERAND
-                                          (TREE_OPERAND (varop, 0), 1)), 1))
-           {
-             tree fielddecl = TREE_OPERAND (TREE_OPERAND (varop, 0), 1);
-             HOST_WIDE_INT size = tree_low_cst (DECL_SIZE (fielddecl), 1);
-             tree folded_compare, shift;
-
-             /* First check whether the comparison would come out
-                always the same.  If we don't do that we would
-                change the meaning with the masking.  */
-             folded_compare = fold_build2 (code, type,
-                                           TREE_OPERAND (varop, 0), arg1);
-             if (integer_zerop (folded_compare)
-                 || integer_onep (folded_compare))
-               return omit_one_operand (type, folded_compare, varop);
-
-             shift = build_int_cst (NULL_TREE,
-                                    TYPE_PRECISION (TREE_TYPE (varop)) - size);
-             shift = fold_convert (TREE_TYPE (varop), shift);
-             newconst = fold_build2 (LSHIFT_EXPR, TREE_TYPE (varop),
-                                     newconst, shift);
-             newconst = fold_build2 (RSHIFT_EXPR, TREE_TYPE (varop),
-                                     newconst, shift);
-           }
-
-         return fold_build2 (code, type, varop, newconst);
-       }
-
       /* Change X >= C to X > (C - 1) and X < C to X <= (C - 1) if C > 0.
         This transformation affects the cases which are handled in later
         optimizations involving comparisons with non-negative constants.  */
@@ -9295,22 +10021,19 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && TREE_CODE (arg0) != INTEGER_CST
          && tree_int_cst_sgn (arg1) > 0)
        {
-         switch (code)
+         if (code == GE_EXPR)
            {
-           case GE_EXPR:
              arg1 = const_binop (MINUS_EXPR, arg1,
                                  build_int_cst (TREE_TYPE (arg1), 1), 0);
              return fold_build2 (GT_EXPR, type, arg0,
                                  fold_convert (TREE_TYPE (arg0), arg1));
-
-           case LT_EXPR:
+           }
+         if (code == LT_EXPR)
+           {
              arg1 = const_binop (MINUS_EXPR, arg1,
                                  build_int_cst (TREE_TYPE (arg1), 1), 0);
              return fold_build2 (LE_EXPR, type, arg0,
                                  fold_convert (TREE_TYPE (arg0), arg1));
-
-           default:
-             break;
            }
        }
 
@@ -9441,100 +10164,40 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                  break;
                }
 
-           else if (!in_gimple_form
-                    && TREE_INT_CST_HIGH (arg1) == signed_max_hi
-                    && TREE_INT_CST_LOW (arg1) == signed_max_lo
-                    && TYPE_UNSIGNED (TREE_TYPE (arg1))
-                    /* signed_type does not work on pointer types.  */
-                    && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
-             {
-               /* The following case also applies to X < signed_max+1
-                  and X >= signed_max+1 because previous transformations.  */
-               if (code == LE_EXPR || code == GT_EXPR)
-                 {
-                   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),
-                                       build_int_cst (st1, 0));
-                 }
-             }
-         }
-      }
-
-      /* If this is an EQ or NE comparison of a constant with a PLUS_EXPR or
-        a MINUS_EXPR of a constant, we can convert it into a comparison with
-        a revised constant as long as no overflow occurs.  */
-      if ((code == EQ_EXPR || code == NE_EXPR)
-         && TREE_CODE (arg1) == INTEGER_CST
-         && (TREE_CODE (arg0) == PLUS_EXPR
-             || TREE_CODE (arg0) == MINUS_EXPR)
-         && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
-         && 0 != (tem = const_binop (TREE_CODE (arg0) == PLUS_EXPR
-                                     ? MINUS_EXPR : PLUS_EXPR,
-                                     arg1, TREE_OPERAND (arg0, 1), 0))
-         && ! TREE_CONSTANT_OVERFLOW (tem))
-       return fold_build2 (code, type, TREE_OPERAND (arg0, 0), tem);
-
-      /* Similarly for a NEGATE_EXPR.  */
-      else if ((code == EQ_EXPR || code == NE_EXPR)
-              && TREE_CODE (arg0) == NEGATE_EXPR
-              && TREE_CODE (arg1) == INTEGER_CST
-              && 0 != (tem = negate_expr (arg1))
-              && TREE_CODE (tem) == INTEGER_CST
-              && ! TREE_CONSTANT_OVERFLOW (tem))
-       return fold_build2 (code, type, TREE_OPERAND (arg0, 0), tem);
-
-      /* If we have X - Y == 0, we can convert that to X == Y and similarly
-        for !=.  Don't do this for ordered comparisons due to overflow.  */
-      else if ((code == NE_EXPR || code == EQ_EXPR)
-              && integer_zerop (arg1) && TREE_CODE (arg0) == MINUS_EXPR)
-       return fold_build2 (code, type,
-                           TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1));
-
-      else if (TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE
-              && (TREE_CODE (arg0) == NOP_EXPR
-                  || TREE_CODE (arg0) == CONVERT_EXPR))
-       {
-         /* If we are widening one operand of an integer comparison,
-            see if the other operand is similarly being widened.  Perhaps we
-            can do the comparison in the narrower type.  */
-         tem = fold_widened_comparison (code, type, arg0, arg1);
-         if (tem)
-           return tem;
-
-         /* Or if we are changing signedness.  */
-         tem = fold_sign_changed_comparison (code, type, arg0, arg1);
-         if (tem)
-           return tem;
-       }
-
-      /* If this is comparing a constant with a MIN_EXPR or a MAX_EXPR of a
-        constant, we can simplify it.  */
-      else if (TREE_CODE (arg1) == INTEGER_CST
-              && (TREE_CODE (arg0) == MIN_EXPR
-                  || TREE_CODE (arg0) == MAX_EXPR)
-              && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
-       {
-         tem = optimize_minmax_comparison (code, type, op0, op1);
-         if (tem)
-           return tem;
-
-         return NULL_TREE;
-       }
-
+           else if (!in_gimple_form
+                    && TREE_INT_CST_HIGH (arg1) == signed_max_hi
+                    && TREE_INT_CST_LOW (arg1) == signed_max_lo
+                    && TYPE_UNSIGNED (TREE_TYPE (arg1))
+                    /* signed_type does not work on pointer types.  */
+                    && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
+             {
+               /* The following case also applies to X < signed_max+1
+                  and X >= signed_max+1 because previous transformations.  */
+               if (code == LE_EXPR || code == GT_EXPR)
+                 {
+                   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),
+                                       build_int_cst (st1, 0));
+                 }
+             }
+         }
+      }
+
       /* If we are comparing an ABS_EXPR with a constant, we can
         convert all the cases into explicit comparisons, but they may
         well not be faster than doing the ABS and one comparison.
         But ABS (X) <= C is a range comparison, which becomes a subtraction
         and a comparison, and is probably faster.  */
-      else if (code == LE_EXPR && TREE_CODE (arg1) == INTEGER_CST
-              && TREE_CODE (arg0) == ABS_EXPR
-              && ! TREE_SIDE_EFFECTS (arg0)
-              && (0 != (tem = negate_expr (arg1)))
-              && TREE_CODE (tem) == INTEGER_CST
-              && ! TREE_CONSTANT_OVERFLOW (tem))
+      if (code == LE_EXPR
+         && TREE_CODE (arg1) == INTEGER_CST
+         && TREE_CODE (arg0) == ABS_EXPR
+         && ! TREE_SIDE_EFFECTS (arg0)
+         && (0 != (tem = negate_expr (arg1)))
+         && TREE_CODE (tem) == INTEGER_CST
+         && ! TREE_CONSTANT_OVERFLOW (tem))
        return fold_build2 (TRUTH_ANDIF_EXPR, type,
                            build2 (GE_EXPR, type,
                                    TREE_OPERAND (arg0, 0), tem),
@@ -9542,135 +10205,19 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                                    TREE_OPERAND (arg0, 0), arg1));
 
       /* Convert ABS_EXPR<x> >= 0 to true.  */
-      else if (code == GE_EXPR
-              && tree_expr_nonnegative_p (arg0)
-              && (integer_zerop (arg1)
-                  || (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))
-                       && real_zerop (arg1))))
+      if (code == GE_EXPR
+         && tree_expr_nonnegative_p (arg0)
+         && (integer_zerop (arg1)
+             || (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))
+                 && real_zerop (arg1))))
        return omit_one_operand (type, integer_one_node, arg0);
 
       /* Convert ABS_EXPR<x> < 0 to false.  */
-      else if (code == LT_EXPR
-              && tree_expr_nonnegative_p (arg0)
-              && (integer_zerop (arg1) || real_zerop (arg1)))
+      if (code == LT_EXPR
+         && tree_expr_nonnegative_p (arg0)
+         && (integer_zerop (arg1) || real_zerop (arg1)))
        return omit_one_operand (type, integer_zero_node, arg0);
 
-      /* Convert ABS_EXPR<x> == 0 or ABS_EXPR<x> != 0 to x == 0 or x != 0.  */
-      else if ((code == EQ_EXPR || code == NE_EXPR)
-              && TREE_CODE (arg0) == ABS_EXPR
-              && (integer_zerop (arg1) || real_zerop (arg1)))
-       return fold_build2 (code, type, TREE_OPERAND (arg0, 0), arg1);
-
-      /* If this is an EQ or NE comparison with zero and ARG0 is
-        (1 << foo) & bar, convert it to (bar >> foo) & 1.  Both require
-        two operations, but the latter can be done in one less insn
-        on machines that have only two-operand insns or on which a
-        constant cannot be the first operand.  */
-      if (integer_zerop (arg1) && (code == EQ_EXPR || code == NE_EXPR)
-         && TREE_CODE (arg0) == BIT_AND_EXPR)
-       {
-         tree arg00 = TREE_OPERAND (arg0, 0);
-         tree arg01 = TREE_OPERAND (arg0, 1);
-         if (TREE_CODE (arg00) == LSHIFT_EXPR
-             && integer_onep (TREE_OPERAND (arg00, 0)))
-           return
-             fold_build2 (code, type,
-                          build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
-                                  build2 (RSHIFT_EXPR, TREE_TYPE (arg00),
-                                          arg01, TREE_OPERAND (arg00, 1)),
-                                  fold_convert (TREE_TYPE (arg0),
-                                                integer_one_node)),
-                          arg1);
-         else if (TREE_CODE (TREE_OPERAND (arg0, 1)) == LSHIFT_EXPR
-                  && integer_onep (TREE_OPERAND (TREE_OPERAND (arg0, 1), 0)))
-           return
-             fold_build2 (code, type,
-                          build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
-                                  build2 (RSHIFT_EXPR, TREE_TYPE (arg01),
-                                          arg00, TREE_OPERAND (arg01, 1)),
-                                  fold_convert (TREE_TYPE (arg0),
-                                                integer_one_node)),
-                          arg1);
-       }
-
-      /* If this is an NE or EQ comparison of zero against the result of a
-        signed MOD operation whose second operand is a power of 2, make
-        the MOD operation unsigned since it is simpler and equivalent.  */
-      if ((code == NE_EXPR || code == EQ_EXPR)
-         && integer_zerop (arg1)
-         && !TYPE_UNSIGNED (TREE_TYPE (arg0))
-         && (TREE_CODE (arg0) == TRUNC_MOD_EXPR
-             || TREE_CODE (arg0) == CEIL_MOD_EXPR
-             || TREE_CODE (arg0) == FLOOR_MOD_EXPR
-             || TREE_CODE (arg0) == ROUND_MOD_EXPR)
-         && integer_pow2p (TREE_OPERAND (arg0, 1)))
-       {
-         tree newtype = lang_hooks.types.unsigned_type (TREE_TYPE (arg0));
-         tree newmod = fold_build2 (TREE_CODE (arg0), newtype,
-                                    fold_convert (newtype,
-                                                  TREE_OPERAND (arg0, 0)),
-                                    fold_convert (newtype,
-                                                  TREE_OPERAND (arg0, 1)));
-
-         return fold_build2 (code, type, newmod,
-                             fold_convert (newtype, arg1));
-       }
-
-      /* If this is an NE comparison of zero with an AND of one, remove the
-        comparison since the AND will give the correct value.  */
-      if (code == NE_EXPR && integer_zerop (arg1)
-         && TREE_CODE (arg0) == BIT_AND_EXPR
-         && integer_onep (TREE_OPERAND (arg0, 1)))
-       return fold_convert (type, arg0);
-
-      /* If we have (A & C) == C where C is a power of 2, convert this into
-        (A & C) != 0.  Similarly for NE_EXPR.  */
-      if ((code == EQ_EXPR || code == NE_EXPR)
-         && TREE_CODE (arg0) == BIT_AND_EXPR
-         && integer_pow2p (TREE_OPERAND (arg0, 1))
-         && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
-       return fold_build2 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
-                           arg0, fold_convert (TREE_TYPE (arg0),
-                                               integer_zero_node));
-
-      /* If we have (A & C) != 0 or (A & C) == 0 and C is the sign
-        bit, then fold the expression into A < 0 or A >= 0.  */
-      tem = fold_single_bit_test_into_sign_test (code, arg0, arg1, type);
-      if (tem)
-       return tem;
-
-      /* If we have (A & C) == D where D & ~C != 0, convert this into 0.
-        Similarly for NE_EXPR.  */
-      if ((code == EQ_EXPR || code == NE_EXPR)
-         && TREE_CODE (arg0) == BIT_AND_EXPR
-         && TREE_CODE (arg1) == INTEGER_CST
-         && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
-       {
-         tree notc = fold_build1 (BIT_NOT_EXPR,
-                                  TREE_TYPE (TREE_OPERAND (arg0, 1)),
-                                  TREE_OPERAND (arg0, 1));
-         tree dandnotc = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
-                                      arg1, notc);
-         tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
-         if (integer_nonzerop (dandnotc))
-           return omit_one_operand (type, rslt, arg0);
-       }
-
-      /* If we have (A | C) == D where C & ~D != 0, convert this into 0.
-        Similarly for NE_EXPR.  */
-      if ((code == EQ_EXPR || code == NE_EXPR)
-         && TREE_CODE (arg0) == BIT_IOR_EXPR
-         && TREE_CODE (arg1) == INTEGER_CST
-         && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
-       {
-         tree notd = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg1), arg1);
-         tree candnotd = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
-                                      TREE_OPERAND (arg0, 1), notd);
-         tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
-         if (integer_nonzerop (candnotd))
-           return omit_one_operand (type, rslt, arg0);
-       }
-
       /* If X is unsigned, convert X < (1 << Y) into X >> Y == 0
         and similarly for >= into !=.  */
       if ((code == LT_EXPR || code == GE_EXPR)
@@ -9680,245 +10227,23 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
        return build2 (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
                       build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
                               TREE_OPERAND (arg1, 1)),
-                      fold_convert (TREE_TYPE (arg0), integer_zero_node));
-
-      else if ((code == LT_EXPR || code == GE_EXPR)
-              && TYPE_UNSIGNED (TREE_TYPE (arg0))
-              && (TREE_CODE (arg1) == NOP_EXPR
-                  || TREE_CODE (arg1) == CONVERT_EXPR)
-              && TREE_CODE (TREE_OPERAND (arg1, 0)) == LSHIFT_EXPR
-              && integer_onep (TREE_OPERAND (TREE_OPERAND (arg1, 0), 0)))
+                      build_int_cst (TREE_TYPE (arg0), 0));
+
+      if ((code == LT_EXPR || code == GE_EXPR)
+         && TYPE_UNSIGNED (TREE_TYPE (arg0))
+         && (TREE_CODE (arg1) == NOP_EXPR
+             || TREE_CODE (arg1) == CONVERT_EXPR)
+         && TREE_CODE (TREE_OPERAND (arg1, 0)) == LSHIFT_EXPR
+         && integer_onep (TREE_OPERAND (TREE_OPERAND (arg1, 0), 0)))
        return
          build2 (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
                  fold_convert (TREE_TYPE (arg0),
                                build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
                                        TREE_OPERAND (TREE_OPERAND (arg1, 0),
                                                      1))),
-                 fold_convert (TREE_TYPE (arg0), integer_zero_node));
-
-      /* Simplify comparison of something with itself.  (For IEEE
-        floating-point, we can only do some of these simplifications.)  */
-      if (operand_equal_p (arg0, arg1, 0))
-       {
-         switch (code)
-           {
-           case EQ_EXPR:
-             if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
-                 || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
-               return constant_boolean_node (1, type);
-             break;
-
-           case GE_EXPR:
-           case LE_EXPR:
-             if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
-                 || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
-               return constant_boolean_node (1, type);
-             return fold_build2 (EQ_EXPR, type, arg0, arg1);
-
-           case NE_EXPR:
-             /* For NE, we can only do this simplification if integer
-                or we don't honor IEEE floating point NaNs.  */
-             if (FLOAT_TYPE_P (TREE_TYPE (arg0))
-                 && HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
-               break;
-             /* ... fall through ...  */
-           case GT_EXPR:
-           case LT_EXPR:
-             return constant_boolean_node (0, type);
-           default:
-             gcc_unreachable ();
-           }
-       }
-
-      /* If we are comparing an expression that just has comparisons
-        of two integer values, arithmetic expressions of those comparisons,
-        and constants, we can simplify it.  There are only three cases
-        to check: the two values can either be equal, the first can be
-        greater, or the second can be greater.  Fold the expression for
-        those three values.  Since each value must be 0 or 1, we have
-        eight possibilities, each of which corresponds to the constant 0
-        or 1 or one of the six possible comparisons.
-
-        This handles common cases like (a > b) == 0 but also handles
-        expressions like  ((x > y) - (y > x)) > 0, which supposedly
-        occur in macroized code.  */
-
-      if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg0) != INTEGER_CST)
-       {
-         tree cval1 = 0, cval2 = 0;
-         int save_p = 0;
-
-         if (twoval_comparison_p (arg0, &cval1, &cval2, &save_p)
-             /* Don't handle degenerate cases here; they should already
-                have been handled anyway.  */
-             && cval1 != 0 && cval2 != 0
-             && ! (TREE_CONSTANT (cval1) && TREE_CONSTANT (cval2))
-             && TREE_TYPE (cval1) == TREE_TYPE (cval2)
-             && INTEGRAL_TYPE_P (TREE_TYPE (cval1))
-             && TYPE_MAX_VALUE (TREE_TYPE (cval1))
-             && TYPE_MAX_VALUE (TREE_TYPE (cval2))
-             && ! operand_equal_p (TYPE_MIN_VALUE (TREE_TYPE (cval1)),
-                                   TYPE_MAX_VALUE (TREE_TYPE (cval2)), 0))
-           {
-             tree maxval = TYPE_MAX_VALUE (TREE_TYPE (cval1));
-             tree minval = TYPE_MIN_VALUE (TREE_TYPE (cval1));
-
-             /* We can't just pass T to eval_subst in case cval1 or cval2
-                was the same as ARG1.  */
-
-             tree high_result
-               = fold_build2 (code, type,
-                              eval_subst (arg0, cval1, maxval,
-                                          cval2, minval),
-                              arg1);
-             tree equal_result
-               = fold_build2 (code, type,
-                              eval_subst (arg0, cval1, maxval,
-                                          cval2, maxval),
-                              arg1);
-             tree low_result
-               = fold_build2 (code, type,
-                              eval_subst (arg0, cval1, minval,
-                                          cval2, maxval),
-                              arg1);
-
-             /* All three of these results should be 0 or 1.  Confirm they
-                are.  Then use those values to select the proper code
-                to use.  */
-
-             if ((integer_zerop (high_result)
-                  || integer_onep (high_result))
-                 && (integer_zerop (equal_result)
-                     || integer_onep (equal_result))
-                 && (integer_zerop (low_result)
-                     || integer_onep (low_result)))
-               {
-                 /* Make a 3-bit mask with the high-order bit being the
-                    value for `>', the next for '=', and the low for '<'.  */
-                 switch ((integer_onep (high_result) * 4)
-                         + (integer_onep (equal_result) * 2)
-                         + integer_onep (low_result))
-                   {
-                   case 0:
-                     /* Always false.  */
-                     return omit_one_operand (type, integer_zero_node, arg0);
-                   case 1:
-                     code = LT_EXPR;
-                     break;
-                   case 2:
-                     code = EQ_EXPR;
-                     break;
-                   case 3:
-                     code = LE_EXPR;
-                     break;
-                   case 4:
-                     code = GT_EXPR;
-                     break;
-                   case 5:
-                     code = NE_EXPR;
-                     break;
-                   case 6:
-                     code = GE_EXPR;
-                     break;
-                   case 7:
-                     /* Always true.  */
-                     return omit_one_operand (type, integer_one_node, arg0);
-                   }
-
-                 if (save_p)
-                   return save_expr (build2 (code, type, cval1, cval2));
-                 else
-                   return fold_build2 (code, type, cval1, cval2);
-               }
-           }
-       }
-
-      /* If this is a comparison of a field, we may be able to simplify it.  */
-      if (((TREE_CODE (arg0) == COMPONENT_REF
-           && lang_hooks.can_use_bit_fields_p ())
-          || TREE_CODE (arg0) == BIT_FIELD_REF)
-         && (code == EQ_EXPR || code == NE_EXPR)
-         /* Handle the constant case even without -O
-            to make sure the warnings are given.  */
-         && (optimize || TREE_CODE (arg1) == INTEGER_CST))
-       {
-         t1 = optimize_bit_field_compare (code, type, arg0, arg1);
-         if (t1)
-           return t1;
-       }
-
-      /* Fold a comparison of the address of COMPONENT_REFs with the same
-         type and component to a comparison of the address of the base
-        object.  In short, &x->a OP &y->a to x OP y and
-         &x->a OP &y.a to x OP &y  */
-      if (TREE_CODE (arg0) == ADDR_EXPR
-         && TREE_CODE (TREE_OPERAND (arg0, 0)) == COMPONENT_REF
-         && TREE_CODE (arg1) == ADDR_EXPR
-         && TREE_CODE (TREE_OPERAND (arg1, 0)) == COMPONENT_REF)
-        {
-         tree cref0 = TREE_OPERAND (arg0, 0);
-         tree cref1 = TREE_OPERAND (arg1, 0);
-         if (TREE_OPERAND (cref0, 1) == TREE_OPERAND (cref1, 1))
-           {
-             tree op0 = TREE_OPERAND (cref0, 0);
-             tree op1 = TREE_OPERAND (cref1, 0);
-             return fold_build2 (code, type,
-                                 build_fold_addr_expr (op0),
-                                 build_fold_addr_expr (op1));
-           }
-       }
-
-      /* 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
-               strlen(ptr) != 0   =>  *ptr != 0
-        Other cases should reduce to one of these two (or a constant)
-        due to the return value of strlen being unsigned.  */
-      if ((code == EQ_EXPR || code == NE_EXPR)
-         && integer_zerop (arg1)
-         && TREE_CODE (arg0) == CALL_EXPR)
-       {
-         tree fndecl = get_callee_fndecl (arg0);
-         tree arglist;
-
-         if (fndecl
-             && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
-             && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRLEN
-             && (arglist = TREE_OPERAND (arg0, 1))
-             && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE
-             && ! TREE_CHAIN (arglist))
-           {
-             tree iref = build_fold_indirect_ref (TREE_VALUE (arglist));
-             return fold_build2 (code, type, iref,
-                                 build_int_cst (TREE_TYPE (iref), 0));
-           }
-       }
-
-      /* We can fold X/C1 op C2 where C1 and C2 are integer constants
-        into a single range test.  */
-      if ((TREE_CODE (arg0) == TRUNC_DIV_EXPR
-          || TREE_CODE (arg0) == EXACT_DIV_EXPR)
-         && TREE_CODE (arg1) == INTEGER_CST
-         && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
-         && !integer_zerop (TREE_OPERAND (arg0, 1))
-         && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))
-         && !TREE_OVERFLOW (arg1))
-       {
-         t1 = fold_div_compare (code, type, arg0, arg1);
-         if (t1 != NULL_TREE)
-           return t1;
-       }
-
-      if ((code == EQ_EXPR || code == NE_EXPR)
-         && integer_zerop (arg1)
-         && tree_expr_nonzero_p (arg0))
-        {
-         tree res = constant_boolean_node (code==NE_EXPR, type);
-         return omit_one_operand (type, res, arg0);
-       }
+                 build_int_cst (TREE_TYPE (arg0), 0));
 
-      t1 = fold_relational_const (code, type, arg0, arg1);
-      return t1 == NULL_TREE ? NULL_TREE : t1;
+      return NULL_TREE;
 
     case UNORDERED_EXPR:
     case ORDERED_EXPR:
@@ -9994,7 +10319,10 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       return pedantic_non_lvalue (tem);
 
     case COMPLEX_EXPR:
-      if (wins)
+      if ((TREE_CODE (arg0) == REAL_CST
+          && TREE_CODE (arg1) == REAL_CST)
+         || (TREE_CODE (arg0) == INTEGER_CST
+             && TREE_CODE (arg1) == INTEGER_CST))
        return build_complex (type, arg0, arg1);
       return NULL_TREE;
 
@@ -10414,7 +10742,7 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
 {
   void **slot;
   enum tree_code code;
-  char buf[sizeof (struct tree_function_decl)];
+  struct tree_function_decl buf;
   int i, len;
   
 recursive_label:
@@ -10433,8 +10761,8 @@ recursive_label:
       && DECL_ASSEMBLER_NAME_SET_P (expr))
     {
       /* Allow DECL_ASSEMBLER_NAME to be modified.  */
-      memcpy (buf, expr, tree_size (expr));
-      expr = (tree) buf;
+      memcpy ((char *) &buf, expr, tree_size (expr));
+      expr = (tree) &buf;
       SET_DECL_ASSEMBLER_NAME (expr, NULL);
     }
   else if (TREE_CODE_CLASS (code) == tcc_type
@@ -10443,8 +10771,8 @@ recursive_label:
               || TYPE_CONTAINS_PLACEHOLDER_INTERNAL (expr)))
     {
       /* Allow these fields to be modified.  */
-      memcpy (buf, expr, tree_size (expr));
-      expr = (tree) buf;
+      memcpy ((char *) &buf, expr, tree_size (expr));
+      expr = (tree) &buf;
       TYPE_CONTAINS_PLACEHOLDER_INTERNAL (expr) = 0;
       TYPE_POINTER_TO (expr) = NULL;
       TYPE_REFERENCE_TO (expr) = NULL;
@@ -10508,13 +10836,16 @@ recursive_label:
        fold_checksum_tree (TREE_OPERAND (expr, i), ctx, ht);
       break;
     case tcc_declaration:
-      fold_checksum_tree (DECL_SIZE (expr), ctx, ht);
-      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_INITIAL (expr), ctx, ht);
-      fold_checksum_tree (DECL_ABSTRACT_ORIGIN (expr), ctx, ht);
-      fold_checksum_tree (DECL_ATTRIBUTES (expr), ctx, ht);
+      if (CODE_CONTAINS_STRUCT (TREE_CODE (expr), TS_DECL_COMMON))
+       {
+         fold_checksum_tree (DECL_SIZE (expr), ctx, ht);
+         fold_checksum_tree (DECL_SIZE_UNIT (expr), ctx, ht);
+         fold_checksum_tree (DECL_INITIAL (expr), ctx, ht);
+         fold_checksum_tree (DECL_ABSTRACT_ORIGIN (expr), ctx, ht);
+         fold_checksum_tree (DECL_ATTRIBUTES (expr), ctx, ht);
+       }
       if (CODE_CONTAINS_STRUCT (TREE_CODE (expr), TS_DECL_WITH_VIS))
        fold_checksum_tree (DECL_SECTION_NAME (expr), ctx, ht);
          
@@ -10895,6 +11226,11 @@ tree_expr_nonnegative_p (tree t)
 
   switch (TREE_CODE (t))
     {
+    case SSA_NAME:
+      /* Query VRP to see if it has recorded any information about
+        the range of this object.  */
+      return ssa_name_nonnegative_p (t);
+
     case ABS_EXPR:
       /* We can't return 1 if flag_wrapv is set because
         ABS_EXPR<INT_MIN> = INT_MIN.  */
@@ -11158,6 +11494,11 @@ tree_expr_nonzero_p (tree t)
 
   switch (TREE_CODE (t))
     {
+    case SSA_NAME:
+      /* Query VRP to see if it has recorded any information about
+        the range of this object.  */
+      return ssa_name_nonzero_p (t);
+
     case ABS_EXPR:
       return tree_expr_nonzero_p (TREE_OPERAND (t, 0));
 
@@ -11194,7 +11535,7 @@ tree_expr_nonzero_p (tree t)
        tree inner_type = TREE_TYPE (TREE_OPERAND (t, 0));
        tree outer_type = TREE_TYPE (t);
 
-       return (TYPE_PRECISION (inner_type) >= TYPE_PRECISION (outer_type)
+       return (TYPE_PRECISION (outer_type) >= TYPE_PRECISION (inner_type)
                && tree_expr_nonzero_p (TREE_OPERAND (t, 0)));
       }
       break;
@@ -11659,8 +12000,32 @@ fold_indirect_ref_1 (tree type, tree op0)
            min_val = TYPE_MIN_VALUE (type_domain);
          return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE);
        }
+      /* *(foo *)&complexfoo => __real__ complexfoo */
+      else if (TREE_CODE (optype) == COMPLEX_TYPE
+              && type == TREE_TYPE (optype))
+       return fold_build1 (REALPART_EXPR, type, op);
     }
 
+  /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
+  if (TREE_CODE (sub) == PLUS_EXPR
+      && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
+    {
+      tree op00 = TREE_OPERAND (sub, 0);
+      tree op01 = TREE_OPERAND (sub, 1);
+      tree op00type;
+
+      STRIP_NOPS (op00);
+      op00type = TREE_TYPE (op00);
+      if (TREE_CODE (op00) == ADDR_EXPR
+         && TREE_CODE (TREE_TYPE (op00type)) == COMPLEX_TYPE
+         && type == TREE_TYPE (TREE_TYPE (op00type)))
+       {
+         tree size = TYPE_SIZE_UNIT (type);
+         if (tree_int_cst_equal (size, op01))
+           return fold_build1 (IMAGPART_EXPR, type, TREE_OPERAND (op00, 0));
+       }
+    }
+  
   /* *(foo *)fooarrptr => (*fooarrptr)[0] */
   if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
       && type == TREE_TYPE (TREE_TYPE (subtype)))