OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index 5266b00..2fe0b7e 100644 (file)
@@ -39,8 +39,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    size_int takes an integer value, and creates a tree constant
    with type from `sizetype'.
 
-   force_fit_type takes a constant and prior overflow indicator, and
-   forces the value to fit the type.  It returns an overflow indicator.  */
+   force_fit_type takes a constant, an overflowable flag and prior
+   overflow indicators.  It forces the value to fit the type and sets
+   TREE_OVERFLOW and TREE_CONSTANT_OVERFLOW as appropriate.  */
 
 #include "config.h"
 #include "system.h"
@@ -88,8 +89,7 @@ static tree negate_expr (tree);
 static tree split_tree (tree, enum tree_code, tree *, tree *, tree *, int);
 static tree associate_trees (tree, tree, enum tree_code, tree);
 static tree const_binop (enum tree_code, tree, tree, int);
-static hashval_t size_htab_hash (const void *);
-static int size_htab_eq (const void *, const void *);
+static tree build_zero_vector (tree);
 static tree fold_convert_const (enum tree_code, tree, tree);
 static enum tree_code invert_tree_comparison (enum tree_code, bool);
 static enum comparison_code comparison_to_compcode (enum tree_code);
@@ -116,13 +116,13 @@ static tree build_range_check (tree, tree, int, tree, tree);
 static int merge_ranges (int *, tree *, tree *, int, tree, tree, int, tree,
                         tree);
 static tree fold_range_test (tree);
+static tree fold_cond_expr_with_comparison (tree, tree, tree, tree);
 static tree unextend (tree, int, int, tree);
 static tree fold_truthop (enum tree_code, tree, tree, tree);
 static tree optimize_minmax_comparison (tree);
 static tree extract_muldiv (tree, tree, enum tree_code, tree);
 static tree extract_muldiv_1 (tree, tree, enum tree_code, tree);
 static int multiple_of_p (tree, tree, tree);
-static tree constant_boolean_node (int, tree);
 static tree fold_binary_op_with_conditional_arg (enum tree_code, tree, tree,
                                                 tree, int);
 static bool fold_real_zero_addition_p (tree, tree, int);
@@ -136,6 +136,7 @@ static tree fold_not_const (tree, tree);
 static tree fold_relational_const (enum tree_code, tree, tree, tree);
 static tree fold_relational_hi_lo (enum tree_code *, const tree,
                                    tree *, tree *);
+static bool tree_expr_nonzero_p (tree);
 
 /* We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring
    overflow.  Suppose A, B and SUM have the same respective signs as A1, B1,
@@ -183,29 +184,31 @@ decode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT *low,
   *hi = words[2] + words[3] * BASE;
 }
 \f
-/* Make the integer constant T valid for its type by setting to 0 or 1 all
-   the bits in the constant that don't belong in the type.
+/* T is an INT_CST node.  OVERFLOWABLE indicates if we are interested
+   in overflow of the value, when >0 we are only interested in signed
+   overflow, for <0 we are interested in any overflow.  OVERFLOWED
+   indicates whether overflow has already occurred.  CONST_OVERFLOWED
+   indicates whether constant overflow has already occurred.  We force
+   T's value to be within range of T's type (by setting to 0 or 1 all
+   the bits outside the type's range).  We set TREE_OVERFLOWED if,
+       OVERFLOWED is nonzero,
+       or OVERFLOWABLE is >0 and signed overflow occurs
+       or OVERFLOWABLE is <0 and any overflow occurs
+   We set TREE_CONSTANT_OVERFLOWED if,
+        CONST_OVERFLOWED is nonzero
+       or we set TREE_OVERFLOWED.
+  We return either the original T, or a copy.  */
 
-   Return 1 if a signed overflow occurs, 0 otherwise.  If OVERFLOW is
-   nonzero, a signed overflow has already occurred in calculating T, so
-   propagate it.  */
-
-int
-force_fit_type (tree t, int overflow)
+tree
+force_fit_type (tree t, int overflowable,
+               bool overflowed, bool overflowed_const)
 {
   unsigned HOST_WIDE_INT low;
   HOST_WIDE_INT high;
   unsigned int prec;
+  int sign_extended_type;
 
-  if (TREE_CODE (t) == REAL_CST)
-    {
-      /* ??? Used to check for overflow here via CHECK_FLOAT_TYPE.
-        Consider doing it via real_convert now.  */
-      return overflow;
-    }
-
-  else if (TREE_CODE (t) != INTEGER_CST)
-    return overflow;
+  gcc_assert (TREE_CODE (t) == INTEGER_CST);
 
   low = TREE_INT_CST_LOW (t);
   high = TREE_INT_CST_HIGH (t);
@@ -215,54 +218,72 @@ force_fit_type (tree t, int overflow)
     prec = POINTER_SIZE;
   else
     prec = TYPE_PRECISION (TREE_TYPE (t));
+  /* Size types *are* sign extended.  */
+  sign_extended_type = (!TYPE_UNSIGNED (TREE_TYPE (t))
+                       || (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
+                           && TYPE_IS_SIZETYPE (TREE_TYPE (t))));
 
   /* First clear all bits that are beyond the type's precision.  */
 
   if (prec == 2 * HOST_BITS_PER_WIDE_INT)
     ;
   else if (prec > HOST_BITS_PER_WIDE_INT)
-    TREE_INT_CST_HIGH (t)
-      &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
+    high &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
   else
     {
-      TREE_INT_CST_HIGH (t) = 0;
+      high = 0;
       if (prec < HOST_BITS_PER_WIDE_INT)
-       TREE_INT_CST_LOW (t) &= ~((unsigned HOST_WIDE_INT) (-1) << prec);
-    }
-
-  /* Unsigned types do not suffer sign extension or overflow unless they
-     are a sizetype.  */
-  if (TYPE_UNSIGNED (TREE_TYPE (t))
-      && ! (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
-           && TYPE_IS_SIZETYPE (TREE_TYPE (t))))
-    return overflow;
-
-  /* If the value's sign bit is set, extend the sign.  */
-  if (prec != 2 * HOST_BITS_PER_WIDE_INT
-      && (prec > HOST_BITS_PER_WIDE_INT
-         ? 0 != (TREE_INT_CST_HIGH (t)
-                 & ((HOST_WIDE_INT) 1
-                    << (prec - HOST_BITS_PER_WIDE_INT - 1)))
-         : 0 != (TREE_INT_CST_LOW (t)
-                 & ((unsigned HOST_WIDE_INT) 1 << (prec - 1)))))
-    {
-      /* Value is negative:
-        set to 1 all the bits that are outside this type's precision.  */
-      if (prec > HOST_BITS_PER_WIDE_INT)
-       TREE_INT_CST_HIGH (t)
-         |= ((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
-      else
+       low &= ~((HOST_WIDE_INT) (-1) << prec);
+    }
+
+  if (!sign_extended_type)
+    /* No sign extension */;
+  else if (prec == 2 * HOST_BITS_PER_WIDE_INT)
+    /* Correct width already.  */;
+  else if (prec > HOST_BITS_PER_WIDE_INT)
+    {
+      /* Sign extend top half? */
+      if (high & ((unsigned HOST_WIDE_INT)1
+                 << (prec - HOST_BITS_PER_WIDE_INT - 1)))
+       high |= (HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT);
+    }
+  else if (prec == HOST_BITS_PER_WIDE_INT)
+    {
+      if ((HOST_WIDE_INT)low < 0)
+       high = -1;
+    }
+  else
+    {
+      /* Sign extend bottom half? */
+      if (low & ((unsigned HOST_WIDE_INT)1 << (prec - 1)))
        {
-         TREE_INT_CST_HIGH (t) = -1;
-         if (prec < HOST_BITS_PER_WIDE_INT)
-           TREE_INT_CST_LOW (t) |= ((unsigned HOST_WIDE_INT) (-1) << prec);
+         high = -1;
+         low |= (HOST_WIDE_INT)(-1) << prec;
        }
     }
 
-  /* Return nonzero if signed overflow occurred.  */
-  return
-    ((overflow | (low ^ TREE_INT_CST_LOW (t)) | (high ^ TREE_INT_CST_HIGH (t)))
-     != 0);
+  /* If the value changed, return a new node.  */
+  if (overflowed || overflowed_const
+      || low != TREE_INT_CST_LOW (t) || high != TREE_INT_CST_HIGH (t))
+    {
+      t = build_int_cst_wide (TREE_TYPE (t), low, high);
+
+      if (overflowed
+         || overflowable < 0
+         || (overflowable > 0 && sign_extended_type))
+       {
+         t = copy_node (t);
+         TREE_OVERFLOW (t) = 1;
+         TREE_CONSTANT_OVERFLOW (t) = 1;
+       }
+      else if (overflowed_const)
+       {
+         t = copy_node (t);
+         TREE_CONSTANT_OVERFLOW (t) = 1;
+       }
+    }
+
+  return t;
 }
 \f
 /* Add two doubleword integers with doubleword result.
@@ -804,7 +825,7 @@ div_and_round_double (enum tree_code code, int uns,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   /* Compute true remainder:  rem = num - (quo * den)  */
@@ -842,14 +863,43 @@ negate_mathfn_p (enum built_in_function code)
   return false;
 }
 
+/* Check whether we may negate an integer constant T without causing
+   overflow.  */
+
+bool
+may_negate_without_overflow_p (tree t)
+{
+  unsigned HOST_WIDE_INT val;
+  unsigned int prec;
+  tree type;
+
+  gcc_assert (TREE_CODE (t) == INTEGER_CST);
+
+  type = TREE_TYPE (t);
+  if (TYPE_UNSIGNED (type))
+    return false;
+
+  prec = TYPE_PRECISION (type);
+  if (prec > HOST_BITS_PER_WIDE_INT)
+    {
+      if (TREE_INT_CST_LOW (t) != 0)
+       return true;
+      prec -= HOST_BITS_PER_WIDE_INT;
+      val = TREE_INT_CST_HIGH (t);
+    }
+  else
+    val = TREE_INT_CST_LOW (t);
+  if (prec < HOST_BITS_PER_WIDE_INT)
+    val &= ((unsigned HOST_WIDE_INT) 1 << prec) - 1;
+  return val != ((unsigned HOST_WIDE_INT) 1 << (prec - 1));
+}
+
 /* Determine whether an expression T can be cheaply negated using
    the function negate_expr.  */
 
 static bool
 negate_expr_p (tree t)
 {
-  unsigned HOST_WIDE_INT val;
-  unsigned int prec;
   tree type;
 
   if (t == 0)
@@ -865,19 +915,7 @@ negate_expr_p (tree t)
        return true;
 
       /* Check that -CST will not overflow type.  */
-      prec = TYPE_PRECISION (type);
-      if (prec > HOST_BITS_PER_WIDE_INT)
-       {
-         if (TREE_INT_CST_LOW (t) != 0)
-           return true;
-         prec -= HOST_BITS_PER_WIDE_INT;
-         val = TREE_INT_CST_HIGH (t);
-       }
-      else
-       val = TREE_INT_CST_LOW (t);
-      if (prec < HOST_BITS_PER_WIDE_INT)
-       val &= ((unsigned HOST_WIDE_INT) 1 << prec) - 1;
-      return val != ((unsigned HOST_WIDE_INT) 1 << (prec - 1));
+      return may_negate_without_overflow_p (t);
 
     case REAL_CST:
     case NEGATE_EXPR:
@@ -1229,7 +1267,15 @@ associate_trees (tree t1, tree t2, enum tree_code code, tree type)
          else if (TREE_CODE (t2) == NEGATE_EXPR)
            return build2 (MINUS_EXPR, type, fold_convert (type, t1),
                           fold_convert (type, TREE_OPERAND (t2, 0)));
+         else if (integer_zerop (t2))
+           return fold_convert (type, t1);
        }
+      else if (code == MINUS_EXPR)
+       {
+         if (integer_zerop (t2))
+           return fold_convert (type, t1);
+       }
+
       return build2 (code, type, fold_convert (type, t1),
                     fold_convert (type, t2));
     }
@@ -1386,42 +1432,34 @@ int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
-  /* If this is for a sizetype, can be represented as one (signed)
-     HOST_WIDE_INT word, and doesn't overflow, use size_int since it caches
-     constants.  */
-  if (is_sizetype
-      && ((hi == 0 && (HOST_WIDE_INT) low >= 0)
-         || (hi == -1 && (HOST_WIDE_INT) low < 0))
-      && overflow == 0 && ! TREE_OVERFLOW (arg1) && ! TREE_OVERFLOW (arg2))
-    return size_int_type_wide (low, type);
-  else
+  t = build_int_cst_wide (TREE_TYPE (arg1), low, hi);
+
+  if (notrunc)
     {
-      t = build_int_2 (low, hi);
-      TREE_TYPE (t) = TREE_TYPE (arg1);
-    }
-
-  TREE_OVERFLOW (t)
-    = ((notrunc
-       ? (!uns || is_sizetype) && overflow
-       : (force_fit_type (t, (!uns || is_sizetype) && overflow)
-          && ! no_overflow))
-       | TREE_OVERFLOW (arg1)
-       | TREE_OVERFLOW (arg2));
-
-  /* If we're doing a size calculation, unsigned arithmetic does overflow.
-     So check if force_fit_type truncated the value.  */
-  if (is_sizetype
-      && ! TREE_OVERFLOW (t)
-      && (TREE_INT_CST_HIGH (t) != hi
-         || TREE_INT_CST_LOW (t) != low))
-    TREE_OVERFLOW (t) = 1;
-
-  TREE_CONSTANT_OVERFLOW (t) = (TREE_OVERFLOW (t)
-                               | TREE_CONSTANT_OVERFLOW (arg1)
-                               | TREE_CONSTANT_OVERFLOW (arg2));
+      /* Propagate overflow flags ourselves.  */
+      if (((!uns || is_sizetype) && overflow)
+         | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2))
+       {
+         t = copy_node (t);
+         TREE_OVERFLOW (t) = 1;
+         TREE_CONSTANT_OVERFLOW (t) = 1;
+       }
+      else if (TREE_CONSTANT_OVERFLOW (arg1) | TREE_CONSTANT_OVERFLOW (arg2))
+       {
+         t = copy_node (t);
+         TREE_CONSTANT_OVERFLOW (t) = 1;
+       }
+    }
+  else
+    t = force_fit_type (t, 1,
+                       ((!uns || is_sizetype) && overflow)
+                       | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2),
+                       TREE_CONSTANT_OVERFLOW (arg1)
+                       | TREE_CONSTANT_OVERFLOW (arg2));
+
   return t;
 }
 
@@ -1478,9 +1516,7 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
 
       t = build_real (type, real_value_truncate (mode, value));
 
-      TREE_OVERFLOW (t)
-       = (force_fit_type (t, 0)
-          | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2));
+      TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2);
       TREE_CONSTANT_OVERFLOW (t)
        = TREE_OVERFLOW (t)
          | TREE_CONSTANT_OVERFLOW (arg1)
@@ -1559,91 +1595,22 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
       return t;
     }
   return 0;
 }
 
-/* These are the hash table functions for the hash table of INTEGER_CST
-   nodes of a sizetype.  */
-
-/* Return the hash code code X, an INTEGER_CST.  */
-
-static hashval_t
-size_htab_hash (const void *x)
-{
-  tree t = (tree) x;
-
-  return (TREE_INT_CST_HIGH (t) ^ TREE_INT_CST_LOW (t)
-         ^ htab_hash_pointer (TREE_TYPE (t))
-         ^ (TREE_OVERFLOW (t) << 20));
-}
-
-/* Return nonzero if the value represented by *X (an INTEGER_CST tree node)
-   is the same as that given by *Y, which is the same.  */
-
-static int
-size_htab_eq (const void *x, const void *y)
-{
-  tree xt = (tree) x;
-  tree yt = (tree) y;
-
-  return (TREE_INT_CST_HIGH (xt) == TREE_INT_CST_HIGH (yt)
-         && TREE_INT_CST_LOW (xt) == TREE_INT_CST_LOW (yt)
-         && TREE_TYPE (xt) == TREE_TYPE (yt)
-         && TREE_OVERFLOW (xt) == TREE_OVERFLOW (yt));
-}
-\f
-/* Return an INTEGER_CST with value whose low-order HOST_BITS_PER_WIDE_INT
-   bits are given by NUMBER and of the sizetype represented by KIND.  */
-
-tree
-size_int_wide (HOST_WIDE_INT number, enum size_type_kind kind)
-{
-  return size_int_type_wide (number, sizetype_tab[(int) kind]);
-}
-
-/* Likewise, but the desired type is specified explicitly.  */
-
-static GTY (()) tree new_const;
-static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
-     htab_t size_htab;
+/* Create a size type INT_CST node with NUMBER sign extended.  KIND
+   indicates which particular sizetype to create.  */
 
 tree
-size_int_type_wide (HOST_WIDE_INT number, tree type)
+size_int_kind (HOST_WIDE_INT number, enum size_type_kind kind)
 {
-  void **slot;
-
-  if (size_htab == 0)
-    {
-      size_htab = htab_create_ggc (1024, size_htab_hash, size_htab_eq, NULL);
-      new_const = make_node (INTEGER_CST);
-    }
-
-  /* Adjust NEW_CONST to be the constant we want.  If it's already in the
-     hash table, we return the value from the hash table.  Otherwise, we
-     place that in the hash table and make a new node for the next time.  */
-  TREE_INT_CST_LOW (new_const) = number;
-  TREE_INT_CST_HIGH (new_const) = number < 0 ? -1 : 0;
-  TREE_TYPE (new_const) = type;
-  TREE_OVERFLOW (new_const) = TREE_CONSTANT_OVERFLOW (new_const)
-    = force_fit_type (new_const, 0);
-
-  slot = htab_find_slot (size_htab, new_const, INSERT);
-  if (*slot == 0)
-    {
-      tree t = new_const;
-
-      *slot = new_const;
-      new_const = make_node (INTEGER_CST);
-      return t;
-    }
-  else
-    return (tree) *slot;
+  return build_int_cst (sizetype_tab[(int) kind], number);
 }
-
+\f
 /* Combine operands OP1 and OP2 with arithmetic operation CODE.  CODE
    is a tree code.  The type of the result is taken from the operands.
    Both must be the same type integer type and it must be a size type.
@@ -1654,9 +1621,8 @@ size_binop (enum tree_code code, tree arg0, tree arg1)
 {
   tree type = TREE_TYPE (arg0);
 
-  if (TREE_CODE (type) != INTEGER_TYPE || ! TYPE_IS_SIZETYPE (type)
-      || type != TREE_TYPE (arg1))
-    abort ();
+  gcc_assert (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type)
+             && type == TREE_TYPE (arg1));
 
   /* Handle the special case of two integer constants faster.  */
   if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
@@ -1690,16 +1656,14 @@ size_diffop (tree arg0, tree arg1)
   tree type = TREE_TYPE (arg0);
   tree ctype;
 
-  if (TREE_CODE (type) != INTEGER_TYPE || ! TYPE_IS_SIZETYPE (type)
-      || type != TREE_TYPE (arg1))
-    abort ();
+  gcc_assert (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type)
+             && type == TREE_TYPE (arg1));
 
   /* If the type is already signed, just do the simple thing.  */
   if (!TYPE_UNSIGNED (type))
     return size_binop (MINUS_EXPR, arg0, arg1);
 
-  ctype = (type == bitsizetype || type == ubitsizetype
-          ? sbitsizetype : ssizetype);
+  ctype = type == bitsizetype ? sbitsizetype : ssizetype;
 
   /* If either operand is not a constant, do the conversions to the signed
      type and subtract.  The hardware will do the right thing with any
@@ -1722,6 +1686,23 @@ size_diffop (tree arg0, tree arg1)
                                                        arg1, arg0)));
 }
 \f
+/* Construct a vector of zero elements of vector type TYPE.  */
+
+static tree
+build_zero_vector (tree type)
+{
+  tree elem, list;
+  int i, units;
+
+  elem = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
+  units = TYPE_VECTOR_SUBPARTS (type);
+
+  list = NULL_TREE;
+  for (i = 0; i < units; i++)
+    list = tree_cons (NULL_TREE, elem, list);
+  return build_vector (type, list);
+}
+
 
 /* Attempt to fold type conversion operation CODE of expression ARG1 to
    type TYPE.  If no simplification can be done return NULL_TREE.  */
@@ -1744,32 +1725,20 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
          if (TYPE_PRECISION (type) > 2 * HOST_BITS_PER_WIDE_INT)
            return NULL_TREE;
 
-         /* If we are trying to make a sizetype for a small integer, use
-            size_int to pick up cached types to reduce duplicate nodes.  */
-         if (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type)
-             && !TREE_CONSTANT_OVERFLOW (arg1)
-             && compare_tree_int (arg1, 10000) < 0)
-           return size_int_type_wide (TREE_INT_CST_LOW (arg1), type);
-
          /* Given an integer constant, make new constant with new type,
             appropriately sign-extended or truncated.  */
-         t = build_int_2 (TREE_INT_CST_LOW (arg1),
-                          TREE_INT_CST_HIGH (arg1));
-         TREE_TYPE (t) = type;
-         /* Indicate an overflow if (1) ARG1 already overflowed,
-            or (2) force_fit_type indicates an overflow.
-            Tell force_fit_type that an overflow has already occurred
-            if ARG1 is a too-large unsigned value and T is signed.
-            But don't indicate an overflow if converting a pointer.  */
-         TREE_OVERFLOW (t)
-           = ((force_fit_type (t,
-                               (TREE_INT_CST_HIGH (arg1) < 0
-                                && (TYPE_UNSIGNED (type)
-                                   < TYPE_UNSIGNED (TREE_TYPE (arg1)))))
-               && ! POINTER_TYPE_P (TREE_TYPE (arg1)))
-              || TREE_OVERFLOW (arg1));
-         TREE_CONSTANT_OVERFLOW (t)
-           = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
+         t = build_int_cst_wide (type, TREE_INT_CST_LOW (arg1),
+                                 TREE_INT_CST_HIGH (arg1));
+
+         t = force_fit_type (t,
+                             /* Don't set the overflow when
+                                converting a pointer  */
+                             !POINTER_TYPE_P (TREE_TYPE (arg1)),
+                             (TREE_INT_CST_HIGH (arg1) < 0
+                              && (TYPE_UNSIGNED (type)
+                                  < TYPE_UNSIGNED (TREE_TYPE (arg1))))
+                             | TREE_OVERFLOW (arg1),
+                             TREE_CONSTANT_OVERFLOW (arg1));
          return t;
        }
       else if (TREE_CODE (arg1) == REAL_CST)
@@ -1784,7 +1753,6 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
             FP-to-integer conversion is unspecified upon overflow.  */
 
          HOST_WIDE_INT high, low;
-
          REAL_VALUE_TYPE r;
          REAL_VALUE_TYPE x = TREE_REAL_CST (arg1);
 
@@ -1807,7 +1775,7 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
              break;
 
            default:
-             abort ();
+             gcc_unreachable ();
            }
 
          /* If R is NaN, return zero and show we have an overflow.  */
@@ -1851,12 +1819,10 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
          if (! overflow)
            REAL_VALUE_TO_INT (&low, &high, r);
 
-         t = build_int_2 (low, high);
-         TREE_TYPE (t) = type;
-         TREE_OVERFLOW (t)
-           = TREE_OVERFLOW (arg1) | force_fit_type (t, overflow);
-         TREE_CONSTANT_OVERFLOW (t)
-           = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
+         t = build_int_cst_wide (type, low, high);
+
+         t = force_fit_type (t, -1, overflow | TREE_OVERFLOW (arg1),
+                             TREE_CONSTANT_OVERFLOW (arg1));
          return t;
        }
     }
@@ -1879,8 +1845,7 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
                          real_value_truncate (TYPE_MODE (type),
                                               TREE_REAL_CST (arg1)));
 
-         TREE_OVERFLOW (t)
-           = TREE_OVERFLOW (arg1) | force_fit_type (t, 0);
+         TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1);
          TREE_CONSTANT_OVERFLOW (t)
            = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
          return t;
@@ -1906,12 +1871,16 @@ fold_convert (tree type, tree arg)
       || TREE_CODE (orig) == ERROR_MARK)
     return error_mark_node;
 
-  if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (orig))
+  if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (orig)
+      || lang_hooks.types_compatible_p (TYPE_MAIN_VARIANT (type),
+                                       TYPE_MAIN_VARIANT (orig)))
     return fold (build1 (NOP_EXPR, type, arg));
 
-  if (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)
-      || TREE_CODE (type) == OFFSET_TYPE)
+  switch (TREE_CODE (type))
     {
+    case INTEGER_TYPE: case CHAR_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
+    case POINTER_TYPE: case REFERENCE_TYPE:
+    case OFFSET_TYPE:
       if (TREE_CODE (arg) == INTEGER_CST)
        {
          tem = fold_convert_const (NOP_EXPR, type, arg);
@@ -1926,13 +1895,11 @@ fold_convert (tree type, tree arg)
          tem = fold (build1 (REALPART_EXPR, TREE_TYPE (orig), arg));
          return fold_convert (type, tem);
        }
-      if (TREE_CODE (orig) == VECTOR_TYPE
-         && GET_MODE_SIZE (TYPE_MODE (type))
-            == GET_MODE_SIZE (TYPE_MODE (orig)))
-       return fold (build1 (NOP_EXPR, type, arg));
-    }
-  else if (TREE_CODE (type) == REAL_TYPE)
-    {
+      gcc_assert (TREE_CODE (orig) == VECTOR_TYPE
+                 && tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)));
+      return fold (build1 (NOP_EXPR, type, arg));
+
+    case REAL_TYPE:
       if (TREE_CODE (arg) == INTEGER_CST)
        {
          tem = fold_convert_const (FLOAT_EXPR, type, arg);
@@ -1946,58 +1913,72 @@ fold_convert (tree type, tree arg)
            return tem;
        }
 
-      if (INTEGRAL_TYPE_P (orig) || POINTER_TYPE_P (orig))
-        return fold (build1 (FLOAT_EXPR, type, arg));
-      if (TREE_CODE (orig) == REAL_TYPE)
-       return fold (build1 (flag_float_store ? CONVERT_EXPR : NOP_EXPR,
-                            type, arg));
-      if (TREE_CODE (orig) == COMPLEX_TYPE)
+      switch (TREE_CODE (orig))
        {
+       case INTEGER_TYPE: case CHAR_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));
+
+       case COMPLEX_TYPE:
          tem = fold (build1 (REALPART_EXPR, TREE_TYPE (orig), arg));
          return fold_convert (type, tem);
+
+       default:
+         gcc_unreachable ();
        }
-    }
-  else if (TREE_CODE (type) == COMPLEX_TYPE)
-    {
-      if (INTEGRAL_TYPE_P (orig)
-         || POINTER_TYPE_P (orig)
-         || TREE_CODE (orig) == REAL_TYPE)
-       return build2 (COMPLEX_EXPR, type,
-                      fold_convert (TREE_TYPE (type), arg),
-                      fold_convert (TREE_TYPE (type), integer_zero_node));
-      if (TREE_CODE (orig) == COMPLEX_TYPE)
+
+    case COMPLEX_TYPE:
+      switch (TREE_CODE (orig))
        {
-         tree rpart, ipart;
+       case INTEGER_TYPE: case CHAR_TYPE:
+       case BOOLEAN_TYPE: case ENUMERAL_TYPE:
+       case POINTER_TYPE: case REFERENCE_TYPE:
+       case REAL_TYPE:
+         return build2 (COMPLEX_EXPR, type,
+                        fold_convert (TREE_TYPE (type), arg),
+                        fold_convert (TREE_TYPE (type), integer_zero_node));
+       case COMPLEX_TYPE:
+         {
+           tree rpart, ipart;
 
-         if (TREE_CODE (arg) == COMPLEX_EXPR)
-           {
-             rpart = fold_convert (TREE_TYPE (type), TREE_OPERAND (arg, 0));
-             ipart = fold_convert (TREE_TYPE (type), TREE_OPERAND (arg, 1));
-             return fold (build2 (COMPLEX_EXPR, type, rpart, ipart));
-           }
+           if (TREE_CODE (arg) == COMPLEX_EXPR)
+             {
+               rpart = fold_convert (TREE_TYPE (type), TREE_OPERAND (arg, 0));
+               ipart = fold_convert (TREE_TYPE (type), TREE_OPERAND (arg, 1));
+               return fold (build2 (COMPLEX_EXPR, type, rpart, ipart));
+             }
 
-         arg = save_expr (arg);
-         rpart = fold (build1 (REALPART_EXPR, TREE_TYPE (orig), arg));
-         ipart = fold (build1 (IMAGPART_EXPR, TREE_TYPE (orig), arg));
-         rpart = fold_convert (TREE_TYPE (type), rpart);
-         ipart = fold_convert (TREE_TYPE (type), ipart);
-         return fold (build2 (COMPLEX_EXPR, type, rpart, ipart));
+           arg = save_expr (arg);
+           rpart = fold (build1 (REALPART_EXPR, TREE_TYPE (orig), arg));
+           ipart = fold (build1 (IMAGPART_EXPR, TREE_TYPE (orig), arg));
+           rpart = fold_convert (TREE_TYPE (type), rpart);
+           ipart = fold_convert (TREE_TYPE (type), ipart);
+           return fold (build2 (COMPLEX_EXPR, type, rpart, ipart));
+         }
+
+       default:
+         gcc_unreachable ();
        }
+
+    case VECTOR_TYPE:
+      if (integer_zerop (arg))
+       return build_zero_vector (type);
+      gcc_assert (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)));
+      gcc_assert (INTEGRAL_TYPE_P (orig) || POINTER_TYPE_P (orig)
+                 || TREE_CODE (orig) == VECTOR_TYPE);
+      return fold (build1 (NOP_EXPR, type, arg));
+
+    case VOID_TYPE:
+      return fold (build1 (CONVERT_EXPR, type, fold_ignored_result (arg)));
+
+    default:
+      gcc_unreachable ();
     }
-  else if (TREE_CODE (type) == VECTOR_TYPE)
-    {
-      if ((INTEGRAL_TYPE_P (orig) || POINTER_TYPE_P (orig))
-         && GET_MODE_SIZE (TYPE_MODE (type))
-            == GET_MODE_SIZE (TYPE_MODE (orig)))
-       return fold (build1 (NOP_EXPR, type, arg));
-      if (TREE_CODE (orig) == VECTOR_TYPE
-         && GET_MODE_SIZE (TYPE_MODE (type))
-            == GET_MODE_SIZE (TYPE_MODE (orig)))
-       return fold (build1 (NOP_EXPR, type, arg));
-    }
-  else if (VOID_TYPE_P (type))
-    return fold (build1 (CONVERT_EXPR, type, arg));
-  abort ();
 }
 \f
 /* Return an expr equal to X but certainly not valid as an lvalue.  */
@@ -2005,6 +1986,11 @@ fold_convert (tree type, tree arg)
 tree
 non_lvalue (tree x)
 {
+  /* While we are in GIMPLE, NON_LVALUE_EXPR doesn't mean anything to
+     us.  */
+  if (in_gimple_form)
+    return x;
+
   /* We only need to wrap lvalue tree codes.  */
   switch (TREE_CODE (x))
   {
@@ -2017,18 +2003,18 @@ non_lvalue (tree x)
 
   case COMPONENT_REF:
   case INDIRECT_REF:
+  case ALIGN_INDIRECT_REF:
+  case MISALIGNED_INDIRECT_REF:
   case ARRAY_REF:
-  case BIT_FIELD_REF:
-  case BUFFER_REF:
   case ARRAY_RANGE_REF:
-  case VTABLE_REF:
+  case BIT_FIELD_REF:
+  case OBJ_TYPE_REF:
 
   case REALPART_EXPR:
   case IMAGPART_EXPR:
   case PREINCREMENT_EXPR:
   case PREDECREMENT_EXPR:
   case SAVE_EXPR:
-  case UNSAVE_EXPR:
   case TRY_CATCH_EXPR:
   case WITH_CLEANUP_EXPR:
   case COMPOUND_EXPR:
@@ -2038,7 +2024,6 @@ non_lvalue (tree x)
   case BIND_EXPR:
   case MIN_EXPR:
   case MAX_EXPR:
-  case RTL_EXPR:
     break;
 
   default:
@@ -2058,7 +2043,7 @@ int pedantic_lvalues;
 /* When pedantic, return an expr equal to X but certainly not valid as a
    pedantic lvalue.  Otherwise, return X.  */
 
-tree
+static tree
 pedantic_non_lvalue (tree x)
 {
   if (pedantic_lvalues)
@@ -2109,7 +2094,7 @@ invert_tree_comparison (enum tree_code code, bool honor_nans)
     case UNORDERED_EXPR:
       return ORDERED_EXPR;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -2133,7 +2118,7 @@ swap_tree_comparison (enum tree_code code)
     case LE_EXPR:
       return GE_EXPR;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -2176,7 +2161,7 @@ comparison_to_compcode (enum tree_code code)
     case UNGE_EXPR:
       return COMPCODE_UNGE;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -2218,7 +2203,7 @@ compcode_to_comparison (enum comparison_code code)
     case COMPCODE_UNGE:
       return UNGE_EXPR;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -2264,7 +2249,7 @@ combine_comparisons (enum tree_code code, enum tree_code lcode,
     }
    else if (flag_trapping_math)
      {
-       /* Check that the original operation and the optimized ones will trap 
+       /* Check that the original operation and the optimized ones will trap
           under the same condition.  */
        bool ltrap = (lcompcode & COMPCODE_UNORD) == 0
                     && (lcompcode != COMPCODE_EQ)
@@ -2311,7 +2296,7 @@ combine_comparisons (enum tree_code code, enum tree_code lcode,
 static int
 truth_value_p (enum tree_code code)
 {
-  return (TREE_CODE_CLASS (code) == '<'
+  return (TREE_CODE_CLASS (code) == tcc_comparison
          || code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR
          || code == TRUTH_OR_EXPR || code == TRUTH_ORIF_EXPR
          || code == TRUTH_XOR_EXPR || code == TRUTH_NOT_EXPR);
@@ -2439,23 +2424,43 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
   if (flags & OEP_ONLY_CONST)
     return 0;
 
+/* Define macros to test an operand from arg0 and arg1 for equality and a
+   variant that allows null and views null as being different from any
+   non-null value.  In the latter case, if either is null, the both
+   must be; otherwise, do the normal comparison.  */
+#define OP_SAME(N) operand_equal_p (TREE_OPERAND (arg0, N),    \
+                                   TREE_OPERAND (arg1, N), flags)
+
+#define OP_SAME_WITH_NULL(N)                           \
+  ((!TREE_OPERAND (arg0, N) || !TREE_OPERAND (arg1, N))        \
+   ? TREE_OPERAND (arg0, N) == TREE_OPERAND (arg1, N) : OP_SAME (N))
+
   switch (TREE_CODE_CLASS (TREE_CODE (arg0)))
     {
-    case '1':
+    case tcc_unary:
       /* Two conversions are equal only if signedness and modes match.  */
-      if ((TREE_CODE (arg0) == NOP_EXPR || TREE_CODE (arg0) == CONVERT_EXPR)
-         && (TYPE_UNSIGNED (TREE_TYPE (arg0))
-             != TYPE_UNSIGNED (TREE_TYPE (arg1))))
-       return 0;
+      switch (TREE_CODE (arg0))
+        {
+        case NOP_EXPR:
+        case CONVERT_EXPR:
+        case FIX_CEIL_EXPR:
+        case FIX_TRUNC_EXPR:
+        case FIX_FLOOR_EXPR:
+        case FIX_ROUND_EXPR:
+         if (TYPE_UNSIGNED (TREE_TYPE (arg0))
+             != TYPE_UNSIGNED (TREE_TYPE (arg1)))
+           return 0;
+         break;
+       default:
+         break;
+       }
+
+      return OP_SAME (0);
 
-      return operand_equal_p (TREE_OPERAND (arg0, 0),
-                             TREE_OPERAND (arg1, 0), flags);
 
-    case '<':
-    case '2':
-      if (operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0), 0)
-         && operand_equal_p (TREE_OPERAND (arg0, 1), TREE_OPERAND (arg1, 1),
-                             0))
+    case tcc_comparison:
+    case tcc_binary:
+      if (OP_SAME (0) && OP_SAME (1))
        return 1;
 
       /* For commutative ops, allow the other order.  */
@@ -2465,7 +2470,7 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
              && operand_equal_p (TREE_OPERAND (arg0, 1),
                                  TREE_OPERAND (arg1, 0), flags));
 
-    case 'r':
+    case tcc_reference:
       /* If either of the pointer (or reference) expressions we are
         dereferencing contain a side effect, these cannot be equal.  */
       if (TREE_SIDE_EFFECTS (arg0)
@@ -2475,44 +2480,58 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
       switch (TREE_CODE (arg0))
        {
        case INDIRECT_REF:
-         return operand_equal_p (TREE_OPERAND (arg0, 0),
-                                 TREE_OPERAND (arg1, 0), flags);
+       case ALIGN_INDIRECT_REF:
+       case MISALIGNED_INDIRECT_REF:
+       case REALPART_EXPR:
+       case IMAGPART_EXPR:
+         return OP_SAME (0);
 
-       case COMPONENT_REF:
        case ARRAY_REF:
        case ARRAY_RANGE_REF:
-         return (operand_equal_p (TREE_OPERAND (arg0, 0),
-                                  TREE_OPERAND (arg1, 0), flags)
-                 && operand_equal_p (TREE_OPERAND (arg0, 1),
-                                     TREE_OPERAND (arg1, 1), flags));
+         /* Operands 2 and 3 may be null.  */
+         return (OP_SAME (0)
+                 && OP_SAME (1)
+                 && OP_SAME_WITH_NULL (2)
+                 && 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);
 
        case BIT_FIELD_REF:
-         return (operand_equal_p (TREE_OPERAND (arg0, 0),
-                                  TREE_OPERAND (arg1, 0), flags)
-                 && operand_equal_p (TREE_OPERAND (arg0, 1),
-                                     TREE_OPERAND (arg1, 1), flags)
-                 && operand_equal_p (TREE_OPERAND (arg0, 2),
-                                     TREE_OPERAND (arg1, 2), flags));
+         return OP_SAME (0) && OP_SAME (1) && OP_SAME (2);
+
        default:
          return 0;
        }
 
-    case 'e':
+    case tcc_expression:
       switch (TREE_CODE (arg0))
        {
        case ADDR_EXPR:
        case TRUTH_NOT_EXPR:
-         return operand_equal_p (TREE_OPERAND (arg0, 0),
-                                 TREE_OPERAND (arg1, 0), flags);
+         return OP_SAME (0);
+
+       case TRUTH_ANDIF_EXPR:
+       case TRUTH_ORIF_EXPR:
+         return OP_SAME (0) && OP_SAME (1);
+
+       case TRUTH_AND_EXPR:
+       case TRUTH_OR_EXPR:
+       case TRUTH_XOR_EXPR:
+         if (OP_SAME (0) && OP_SAME (1))
+           return 1;
 
-       case RTL_EXPR:
-         return rtx_equal_p (RTL_EXPR_RTL (arg0), RTL_EXPR_RTL (arg1));
+         /* Otherwise take into account this is a commutative operation.  */
+         return (operand_equal_p (TREE_OPERAND (arg0, 0),
+                                  TREE_OPERAND (arg1, 1), flags)
+                 && operand_equal_p (TREE_OPERAND (arg0, 1),
+                                     TREE_OPERAND (arg1, 0), flags));
 
        case CALL_EXPR:
          /* If the CALL_EXPRs call different functions, then they
             clearly can not be equal.  */
-         if (! operand_equal_p (TREE_OPERAND (arg0, 0),
-                                TREE_OPERAND (arg1, 0), flags))
+         if (!OP_SAME (0))
            return 0;
 
          {
@@ -2548,7 +2567,7 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
          return 0;
        }
 
-    case 'd':
+    case tcc_declaration:
       /* Consider __builtin_sqrt equal to sqrt.  */
       return (TREE_CODE (arg0) == FUNCTION_DECL
              && DECL_BUILT_IN (arg0) && DECL_BUILT_IN (arg1)
@@ -2558,6 +2577,9 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
     default:
       return 0;
     }
+
+#undef OP_SAME
+#undef OP_SAME_WITH_NULL
 }
 \f
 /* Similar to operand_equal_p, but see if ARG0 might have been made by
@@ -2630,17 +2652,17 @@ static int
 twoval_comparison_p (tree arg, tree *cval1, tree *cval2, int *save_p)
 {
   enum tree_code code = TREE_CODE (arg);
-  char class = TREE_CODE_CLASS (code);
+  enum tree_code_class class = TREE_CODE_CLASS (code);
 
-  /* We can handle some of the 'e' cases here.  */
-  if (class == 'e' && code == TRUTH_NOT_EXPR)
-    class = '1';
-  else if (class == 'e'
+  /* We can handle some of the tcc_expression cases here.  */
+  if (class == tcc_expression && code == TRUTH_NOT_EXPR)
+    class = tcc_unary;
+  else if (class == tcc_expression
           && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR
               || code == COMPOUND_EXPR))
-    class = '2';
+    class = tcc_binary;
 
-  else if (class == 'e' && code == SAVE_EXPR && SAVE_EXPR_RTL (arg) == 0
+  else if (class == tcc_expression && code == SAVE_EXPR
           && ! TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0)))
     {
       /* If we've already found a CVAL1 or CVAL2, this expression is
@@ -2648,24 +2670,24 @@ twoval_comparison_p (tree arg, tree *cval1, tree *cval2, int *save_p)
       if (*cval1 || *cval2)
        return 0;
 
-      class = '1';
+      class = tcc_unary;
       *save_p = 1;
     }
 
   switch (class)
     {
-    case '1':
+    case tcc_unary:
       return twoval_comparison_p (TREE_OPERAND (arg, 0), cval1, cval2, save_p);
 
-    case '2':
+    case tcc_binary:
       return (twoval_comparison_p (TREE_OPERAND (arg, 0), cval1, cval2, save_p)
              && twoval_comparison_p (TREE_OPERAND (arg, 1),
                                      cval1, cval2, save_p));
 
-    case 'c':
+    case tcc_constant:
       return 1;
 
-    case 'e':
+    case tcc_expression:
       if (code == COND_EXPR)
        return (twoval_comparison_p (TREE_OPERAND (arg, 0),
                                     cval1, cval2, save_p)
@@ -2675,7 +2697,7 @@ twoval_comparison_p (tree arg, tree *cval1, tree *cval2, int *save_p)
                                        cval1, cval2, save_p));
       return 0;
 
-    case '<':
+    case tcc_comparison:
       /* First see if we can handle the first operand, then the second.  For
         the second operand, we know *CVAL1 can't be zero.  It must be that
         one side of the comparison is each of the values; test for the
@@ -2723,30 +2745,30 @@ eval_subst (tree arg, tree old0, tree new0, tree old1, tree new1)
 {
   tree type = TREE_TYPE (arg);
   enum tree_code code = TREE_CODE (arg);
-  char class = TREE_CODE_CLASS (code);
+  enum tree_code_class class = TREE_CODE_CLASS (code);
 
-  /* We can handle some of the 'e' cases here.  */
-  if (class == 'e' && code == TRUTH_NOT_EXPR)
-    class = '1';
-  else if (class == 'e'
+  /* We can handle some of the tcc_expression cases here.  */
+  if (class == tcc_expression && code == TRUTH_NOT_EXPR)
+    class = tcc_unary;
+  else if (class == tcc_expression
           && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR))
-    class = '2';
+    class = tcc_binary;
 
   switch (class)
     {
-    case '1':
+    case tcc_unary:
       return fold (build1 (code, type,
                           eval_subst (TREE_OPERAND (arg, 0),
                                       old0, new0, old1, new1)));
 
-    case '2':
+    case tcc_binary:
       return fold (build2 (code, type,
                           eval_subst (TREE_OPERAND (arg, 0),
                                       old0, new0, old1, new1),
                           eval_subst (TREE_OPERAND (arg, 1),
                                       old0, new0, old1, new1)));
 
-    case 'e':
+    case tcc_expression:
       switch (code)
        {
        case SAVE_EXPR:
@@ -2768,7 +2790,7 @@ eval_subst (tree arg, tree old0, tree new0, tree old1, tree new1)
        }
       /* Fall through - ???  */
 
-    case '<':
+    case tcc_comparison:
       {
        tree arg0 = TREE_OPERAND (arg, 0);
        tree arg1 = TREE_OPERAND (arg, 1);
@@ -2808,7 +2830,7 @@ omit_one_operand (tree type, tree result, tree omitted)
   tree t = fold_convert (type, result);
 
   if (TREE_SIDE_EFFECTS (omitted))
-    return build2 (COMPOUND_EXPR, type, omitted, t);
+    return build2 (COMPOUND_EXPR, type, fold_ignored_result (omitted), t);
 
   return non_lvalue (t);
 }
@@ -2821,7 +2843,7 @@ pedantic_omit_one_operand (tree type, tree result, tree omitted)
   tree t = fold_convert (type, result);
 
   if (TREE_SIDE_EFFECTS (omitted))
-    return build2 (COMPOUND_EXPR, type, omitted, t);
+    return build2 (COMPOUND_EXPR, type, fold_ignored_result (omitted), t);
 
   return pedantic_non_lvalue (t);
 }
@@ -2868,7 +2890,7 @@ invert_truthvalue (tree arg)
      floating-point non-equality comparisons, in which case we just
      enclose a TRUTH_NOT_EXPR around what we have.  */
 
-  if (TREE_CODE_CLASS (code) == '<')
+  if (TREE_CODE_CLASS (code) == tcc_comparison)
     {
       tree op_type = TREE_TYPE (TREE_OPERAND (arg, 0));
       if (FLOAT_TYPE_P (op_type)
@@ -2891,7 +2913,8 @@ invert_truthvalue (tree arg)
   switch (code)
     {
     case INTEGER_CST:
-      return fold_convert (type, build_int_2 (integer_zerop (arg), 0));
+      return fold_convert (type,
+                          build_int_cst (NULL_TREE, integer_zerop (arg)));
 
     case TRUTH_AND_EXPR:
       return build2 (TRUTH_OR_EXPR, type,
@@ -2967,8 +2990,7 @@ invert_truthvalue (tree arg)
     default:
       break;
     }
-  if (TREE_CODE (TREE_TYPE (arg)) != BOOLEAN_TYPE)
-    abort ();
+  gcc_assert (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE);
   return build1 (TRUTH_NOT_EXPR, type, arg);
 }
 
@@ -3126,9 +3148,8 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type,
     lbitpos = nbitsize - lbitsize - lbitpos;
 
   /* Make the mask to be used against the extracted field.  */
-  mask = build_int_2 (~0, ~0);
-  TREE_TYPE (mask) = unsigned_type;
-  force_fit_type (mask, 0);
+  mask = build_int_cst (unsigned_type, -1);
+  mask = force_fit_type (mask, 0, false, false);
   mask = fold_convert (unsigned_type, mask);
   mask = const_binop (LSHIFT_EXPR, mask, size_int (nbitsize - lbitsize), 0);
   mask = const_binop (RSHIFT_EXPR, mask,
@@ -3276,16 +3297,16 @@ decode_field_reference (tree exp, HOST_WIDE_INT *pbitsize,
   /* If the number of bits in the reference is the same as the bitsize of
      the outer type, then the outer type gives the signedness. Otherwise
      (in case of a small bitfield) the signedness is unchanged.  */
-  if (outer_type && *pbitsize == tree_low_cst (TYPE_SIZE (outer_type), 1))
+  if (outer_type && *pbitsize == TYPE_PRECISION (outer_type))
     *punsignedp = TYPE_UNSIGNED (outer_type);
 
   /* Compute the mask to access the bitfield.  */
   unsigned_type = lang_hooks.types.type_for_size (*pbitsize, 1);
   precision = TYPE_PRECISION (unsigned_type);
 
-  mask = build_int_2 (~0, ~0);
-  TREE_TYPE (mask) = unsigned_type;
-  force_fit_type (mask, 0);
+  mask = build_int_cst (unsigned_type, -1);
+  mask = force_fit_type (mask, 0, false, false);
+
   mask = const_binop (LSHIFT_EXPR, mask, size_int (precision - *pbitsize), 0);
   mask = const_binop (RSHIFT_EXPR, mask, size_int (precision - *pbitsize), 0);
 
@@ -3309,9 +3330,9 @@ all_ones_mask_p (tree mask, int size)
   unsigned int precision = TYPE_PRECISION (type);
   tree tmask;
 
-  tmask = build_int_2 (~0, ~0);
-  TREE_TYPE (tmask) = lang_hooks.types.signed_type (type);
-  force_fit_type (tmask, 0);
+  tmask = build_int_cst (lang_hooks.types.signed_type (type), -1);
+  tmask = force_fit_type (tmask, 0, false, false);
+
   return
     tree_int_cst_equal (mask,
                        const_binop (RSHIFT_EXPR,
@@ -3386,13 +3407,10 @@ static int
 simple_operand_p (tree exp)
 {
   /* Strip any conversions that don't change the machine mode.  */
-  while ((TREE_CODE (exp) == NOP_EXPR
-         || TREE_CODE (exp) == CONVERT_EXPR)
-        && (TYPE_MODE (TREE_TYPE (exp))
-            == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
-    exp = TREE_OPERAND (exp, 0);
+  STRIP_NOPS (exp);
 
-  return (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c'
+  return (CONSTANT_CLASS_P (exp)
+         || TREE_CODE (exp) == SSA_NAME
          || (DECL_P (exp)
              && ! TREE_ADDRESSABLE (exp)
              && ! TREE_THIS_VOLATILE (exp)
@@ -3463,7 +3481,7 @@ range_binop (enum tree_code code, tree type, tree arg0, int upper0_p,
       return TREE_CODE (tem) == INTEGER_CST ? tem : 0;
     }
 
-  if (TREE_CODE_CLASS (code) != '<')
+  if (TREE_CODE_CLASS (code) != tcc_comparison)
     return 0;
 
   /* Set SGN[01] to -1 if ARG[01] is a lower bound, 1 for upper, and 0
@@ -3495,7 +3513,7 @@ range_binop (enum tree_code code, tree type, tree arg0, int upper0_p,
       result = sgn0 >= sgn1;
       break;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   return constant_boolean_node (result, type);
@@ -3511,8 +3529,8 @@ static tree
 make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
 {
   enum tree_code code;
-  tree arg0 = NULL_TREE, arg1 = NULL_TREE, type = NULL_TREE;
-  tree orig_type = NULL_TREE;
+  tree arg0 = NULL_TREE, arg1 = NULL_TREE;
+  tree exp_type = NULL_TREE, arg0_type = NULL_TREE;
   int in_p, n_in_p;
   tree low, high, n_low, n_high;
 
@@ -3528,27 +3546,23 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
   while (1)
     {
       code = TREE_CODE (exp);
+      exp_type = TREE_TYPE (exp);
 
       if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
        {
-         if (first_rtl_op (code) > 0)
+         if (TREE_CODE_LENGTH (code) > 0)
            arg0 = TREE_OPERAND (exp, 0);
-         if (TREE_CODE_CLASS (code) == '<'
-             || TREE_CODE_CLASS (code) == '1'
-             || TREE_CODE_CLASS (code) == '2')
-           type = TREE_TYPE (arg0);
-         if (TREE_CODE_CLASS (code) == '2'
-             || TREE_CODE_CLASS (code) == '<'
-             || (TREE_CODE_CLASS (code) == 'e'
+         if (TREE_CODE_CLASS (code) == tcc_comparison
+             || TREE_CODE_CLASS (code) == tcc_unary
+             || TREE_CODE_CLASS (code) == tcc_binary)
+           arg0_type = TREE_TYPE (arg0);
+         if (TREE_CODE_CLASS (code) == tcc_binary
+             || TREE_CODE_CLASS (code) == tcc_comparison
+             || (TREE_CODE_CLASS (code) == tcc_expression
                  && TREE_CODE_LENGTH (code) > 1))
            arg1 = TREE_OPERAND (exp, 1);
        }
 
-      /* Set ORIG_TYPE as soon as TYPE is non-null so that we do not
-        lose a cast by accident.  */
-      if (type != NULL_TREE && orig_type == NULL_TREE)
-       orig_type = type;
-
       switch (code)
        {
        case TRUTH_NOT_EXPR:
@@ -3588,19 +3602,19 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
              in_p = ! in_p, low = 0, high = arg1;
              break;
            default:
-             abort ();
+             gcc_unreachable ();
            }
 
-         exp = arg0;
-
          /* If this is an unsigned comparison, we also know that EXP is
             greater than or equal to zero.  We base the range tests we make
             on that fact, so we record it here so we can parse existing
-            range tests.  */
-         if (TYPE_UNSIGNED (type) && (low == 0 || high == 0))
+            range tests.  We test arg0_type since often the return type
+            of, e.g. EQ_EXPR, is boolean.  */
+         if (TYPE_UNSIGNED (arg0_type) && (low == 0 || high == 0))
            {
-             if (! merge_ranges (&n_in_p, &n_low, &n_high, in_p, low, high,
-                                 1, fold_convert (type, integer_zero_node),
+             if (! merge_ranges (&n_in_p, &n_low, &n_high,
+                                 in_p, low, high, 1,
+                                 fold_convert (arg0_type, integer_zero_node),
                                  NULL_TREE))
                break;
 
@@ -3614,18 +3628,20 @@ 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 (type, integer_zero_node);
+                 low = fold_convert (arg0_type, integer_zero_node);
                }
            }
+
+         exp = arg0;
          continue;
 
        case NEGATE_EXPR:
          /* (-x) IN [a,b] -> x in [-b, -a]  */
-         n_low = range_binop (MINUS_EXPR, type,
-                              fold_convert (type, integer_zero_node),
+         n_low = range_binop (MINUS_EXPR, exp_type,
+                              fold_convert (exp_type, integer_zero_node),
                               0, high, 1);
-         n_high = range_binop (MINUS_EXPR, type,
-                               fold_convert (type, integer_zero_node),
+         n_high = range_binop (MINUS_EXPR, exp_type,
+                               fold_convert (exp_type, integer_zero_node),
                                0, low, 0);
          low = n_low, high = n_high;
          exp = arg0;
@@ -3633,8 +3649,8 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
 
        case BIT_NOT_EXPR:
          /* ~ X -> -X - 1  */
-         exp = build2 (MINUS_EXPR, type, negate_expr (arg0),
-                       fold_convert (type, integer_one_node));
+         exp = build2 (MINUS_EXPR, exp_type, negate_expr (arg0),
+                       fold_convert (exp_type, integer_one_node));
          continue;
 
        case PLUS_EXPR:  case MINUS_EXPR:
@@ -3646,9 +3662,9 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
             the bounds don't overflow.  For unsigned, overflow is defined
             and this is exactly the right thing.  */
          n_low = range_binop (code == MINUS_EXPR ? PLUS_EXPR : MINUS_EXPR,
-                              type, low, 0, arg1, 0);
+                              arg0_type, low, 0, arg1, 0);
          n_high = range_binop (code == MINUS_EXPR ? PLUS_EXPR : MINUS_EXPR,
-                               type, high, 1, arg1, 0);
+                               arg0_type, high, 1, arg1, 0);
          if ((n_low != 0 && TREE_OVERFLOW (n_low))
              || (n_high != 0 && TREE_OVERFLOW (n_high)))
            break;
@@ -3657,9 +3673,9 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
             value thus making n_high < n_low, and normalize it.  */
          if (n_low && n_high && tree_int_cst_lt (n_high, n_low))
            {
-             low = range_binop (PLUS_EXPR, type, n_high, 0,
+             low = range_binop (PLUS_EXPR, arg0_type, n_high, 0,
                                 integer_one_node, 0);
-             high = range_binop (MINUS_EXPR, type, n_low, 0,
+             high = range_binop (MINUS_EXPR, arg0_type, n_low, 0,
                                  integer_one_node, 0);
 
              /* If the range is of the form +/- [ x+1, x ], we won't
@@ -3679,46 +3695,50 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
          continue;
 
        case NOP_EXPR:  case NON_LVALUE_EXPR:  case CONVERT_EXPR:
-         if (TYPE_PRECISION (type) > TYPE_PRECISION (orig_type))
+         if (TYPE_PRECISION (arg0_type) > TYPE_PRECISION (exp_type))
            break;
 
-         if (! INTEGRAL_TYPE_P (type)
-             || (low != 0 && ! int_fits_type_p (low, type))
-             || (high != 0 && ! int_fits_type_p (high, type)))
+         if (! INTEGRAL_TYPE_P (arg0_type)
+             || (low != 0 && ! int_fits_type_p (low, arg0_type))
+             || (high != 0 && ! int_fits_type_p (high, arg0_type)))
            break;
 
          n_low = low, n_high = high;
 
          if (n_low != 0)
-           n_low = fold_convert (type, n_low);
+           n_low = fold_convert (arg0_type, n_low);
 
          if (n_high != 0)
-           n_high = fold_convert (type, n_high);
+           n_high = fold_convert (arg0_type, n_high);
+
 
-         /* If we're converting from an unsigned to a signed type,
-            we will be doing the comparison as unsigned.  The tests above
-            have already verified that LOW and HIGH are both positive.
+         /* If we're converting arg0 from an unsigned type, to exp,
+            a signed type,  we will be doing the comparison as unsigned.
+            The tests above have already verified that LOW and HIGH
+            are both positive.
 
-            So we have to make sure that the original unsigned value will
-            be interpreted as positive.  */
-         if (TYPE_UNSIGNED (type) && ! TYPE_UNSIGNED (TREE_TYPE (exp)))
+            So we have to ensure that we will handle large unsigned
+            values the same way that the current signed bounds treat
+            negative values.  */
+
+         if (!TYPE_UNSIGNED (exp_type) && TYPE_UNSIGNED (arg0_type))
            {
-             tree equiv_type = lang_hooks.types.type_for_mode
-               (TYPE_MODE (type), 1);
              tree high_positive;
+             tree equiv_type = lang_hooks.types.type_for_mode
+               (TYPE_MODE (arg0_type), 1);
 
              /* A range without an upper bound is, naturally, unbounded.
                 Since convert would have cropped a very large value, use
                 the max value for the destination type.  */
              high_positive
                = TYPE_MAX_VALUE (equiv_type) ? TYPE_MAX_VALUE (equiv_type)
-                 : TYPE_MAX_VALUE (type);
+               : TYPE_MAX_VALUE (arg0_type);
 
-             if (TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (exp)))
-               high_positive = fold (build2 (RSHIFT_EXPR, type,
-                                             fold_convert (type,
+             if (TYPE_PRECISION (exp_type) == TYPE_PRECISION (arg0_type))
+               high_positive = fold (build2 (RSHIFT_EXPR, arg0_type,
+                                             fold_convert (arg0_type,
                                                            high_positive),
-                                             fold_convert (type,
+                                             fold_convert (arg0_type,
                                                            integer_one_node)));
 
              /* If the low bound is specified, "and" the range with the
@@ -3728,7 +3748,8 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
                {
                  if (! merge_ranges (&n_in_p, &n_low, &n_high,
                                      1, n_low, n_high, 1,
-                                     fold_convert (type, integer_zero_node),
+                                     fold_convert (arg0_type,
+                                                   integer_zero_node),
                                      high_positive))
                    break;
 
@@ -3740,7 +3761,8 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
                     that will be interpreted as negative.  */
                  if (! merge_ranges (&n_in_p, &n_low, &n_high,
                                      0, n_low, n_high, 1,
-                                     fold_convert (type, integer_zero_node),
+                                     fold_convert (arg0_type,
+                                                   integer_zero_node),
                                      high_positive))
                    break;
 
@@ -4089,8 +4111,269 @@ merge_ranges (int *pin_p, tree *plow, tree *phigh, int in0_p, tree low0,
   return 1;
 }
 \f
-#ifndef RANGE_TEST_NON_SHORT_CIRCUIT
-#define RANGE_TEST_NON_SHORT_CIRCUIT (BRANCH_COST >= 2)
+
+/* Subroutine of fold, looking inside expressions of the form
+   A op B ? A : C, where ARG0, ARG1 and ARG2 are the three operands
+   of the COND_EXPR.  This function is being used also to optimize
+   A op B ? C : A, by reversing the comparison first.
+
+   Return a folded expression whose code is not a COND_EXPR
+   anymore, or NULL_TREE if no folding opportunity is found.  */
+
+static tree
+fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
+{
+  enum tree_code comp_code = TREE_CODE (arg0);
+  tree arg00 = TREE_OPERAND (arg0, 0);
+  tree arg01 = TREE_OPERAND (arg0, 1);
+  tree arg1_type = TREE_TYPE (arg1);
+  tree tem;
+
+  STRIP_NOPS (arg1);
+  STRIP_NOPS (arg2);
+
+  /* If we have A op 0 ? A : -A, consider applying the following
+     transformations:
+
+     A == 0? A : -A    same as -A
+     A != 0? A : -A    same as A
+     A >= 0? A : -A    same as abs (A)
+     A > 0?  A : -A    same as abs (A)
+     A <= 0? A : -A    same as -abs (A)
+     A < 0?  A : -A    same as -abs (A)
+
+     None of these transformations work for modes with signed
+     zeros.  If A is +/-0, the first two transformations will
+     change the sign of the result (from +0 to -0, or vice
+     versa).  The last four will fix the sign of the result,
+     even though the original expressions could be positive or
+     negative, depending on the sign of A.
+
+     Note that all these transformations are correct if A is
+     NaN, since the two alternatives (A and -A) are also NaNs.  */
+  if ((FLOAT_TYPE_P (TREE_TYPE (arg01))
+       ? real_zerop (arg01)
+       : integer_zerop (arg01))
+      && TREE_CODE (arg2) == NEGATE_EXPR
+      && operand_equal_p (TREE_OPERAND (arg2, 0), arg1, 0))
+    switch (comp_code)
+      {
+      case EQ_EXPR:
+      case UNEQ_EXPR:
+       tem = fold_convert (arg1_type, arg1);
+       return pedantic_non_lvalue (fold_convert (type, negate_expr (tem)));
+      case NE_EXPR:
+      case LTGT_EXPR:
+       return pedantic_non_lvalue (fold_convert (type, arg1));
+      case UNGE_EXPR:
+      case UNGT_EXPR:
+       if (flag_trapping_math)
+         break;
+       /* Fall through.  */
+      case GE_EXPR:
+      case GT_EXPR:
+       if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
+         arg1 = fold_convert (lang_hooks.types.signed_type
+                              (TREE_TYPE (arg1)), arg1);
+       tem = fold (build1 (ABS_EXPR, TREE_TYPE (arg1), arg1));
+       return pedantic_non_lvalue (fold_convert (type, tem));
+      case UNLE_EXPR:
+      case UNLT_EXPR:
+       if (flag_trapping_math)
+         break;
+      case LE_EXPR:
+      case LT_EXPR:
+       if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
+         arg1 = fold_convert (lang_hooks.types.signed_type
+                              (TREE_TYPE (arg1)), arg1);
+       tem = fold (build1 (ABS_EXPR, TREE_TYPE (arg1), arg1));
+       return negate_expr (fold_convert (type, tem));
+      default:
+       gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison);
+       break;
+      }
+
+  /* A != 0 ? A : 0 is simply A, unless A is -0.  Likewise
+     A == 0 ? A : 0 is always 0 unless A is -0.  Note that
+     both transformations are correct when A is NaN: A != 0
+     is then true, and A == 0 is false.  */
+
+  if (integer_zerop (arg01) && integer_zerop (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);
+    }
+
+  /* Try some transformations of A op B ? A : B.
+
+     A == B? A : B    same as B
+     A != B? A : B    same as A
+     A >= B? A : B    same as max (A, B)
+     A > B?  A : B    same as max (B, A)
+     A <= B? A : B    same as min (A, B)
+     A < B?  A : B    same as min (B, A)
+
+     As above, these transformations don't work in the presence
+     of signed zeros.  For example, if A and B are zeros of
+     opposite sign, the first two transformations will change
+     the sign of the result.  In the last four, the original
+     expressions give different results for (A=+0, B=-0) and
+     (A=-0, B=+0), but the transformed expressions do not.
+
+     The first two transformations are correct if either A or B
+     is a NaN.  In the first transformation, the condition will
+     be false, and B will indeed be chosen.  In the case of the
+     second transformation, the condition A != B will be true,
+     and A will be chosen.
+
+     The conversions to max() and min() are not correct if B is
+     a number and A is not.  The conditions in the original
+     expressions will be false, so all four give B.  The min()
+     and max() versions would give a NaN instead.  */
+  if (operand_equal_for_comparison_p (arg01, arg2, arg00))
+    {
+      tree comp_op0 = arg00;
+      tree comp_op1 = arg01;
+      tree comp_type = TREE_TYPE (comp_op0);
+
+      /* Avoid adding NOP_EXPRs in case this is an lvalue.  */
+      if (TYPE_MAIN_VARIANT (comp_type) == TYPE_MAIN_VARIANT (type))
+       {
+         comp_type = type;
+         comp_op0 = arg1;
+         comp_op1 = arg2;
+       }
+
+      switch (comp_code)
+       {
+       case EQ_EXPR:
+         return pedantic_non_lvalue (fold_convert (type, arg2));
+       case NE_EXPR:
+         return pedantic_non_lvalue (fold_convert (type, arg1));
+       case LE_EXPR:
+       case LT_EXPR:
+       case UNLE_EXPR:
+       case UNLT_EXPR:
+         /* In C++ a ?: expression can be an lvalue, so put the
+            operand which will be used if they are equal first
+            so that we can convert this back to the
+            corresponding COND_EXPR.  */
+         if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
+           {
+             comp_op0 = fold_convert (comp_type, comp_op0);
+             comp_op1 = fold_convert (comp_type, comp_op1);
+             tem = (comp_code == LE_EXPR || comp_code == UNLE_EXPR)
+                   ? fold (build2 (MIN_EXPR, comp_type, comp_op0, comp_op1))
+                   : fold (build2 (MIN_EXPR, comp_type, comp_op1, comp_op0));
+             return pedantic_non_lvalue (fold_convert (type, tem));
+           }
+         break;
+       case GE_EXPR:
+       case GT_EXPR:
+       case UNGE_EXPR:
+       case UNGT_EXPR:
+         if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
+           {
+             comp_op0 = fold_convert (comp_type, comp_op0);
+             comp_op1 = fold_convert (comp_type, comp_op1);
+             tem = (comp_code == GE_EXPR || comp_code == UNGE_EXPR)
+                   ? fold (build2 (MAX_EXPR, comp_type, comp_op0, comp_op1))
+                   : fold (build2 (MAX_EXPR, comp_type, comp_op1, comp_op0));
+             return pedantic_non_lvalue (fold_convert (type, tem));
+           }
+         break;
+       case UNEQ_EXPR:
+         if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
+           return pedantic_non_lvalue (fold_convert (type, arg2));
+         break;
+       case LTGT_EXPR:
+         if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
+           return pedantic_non_lvalue (fold_convert (type, arg1));
+         break;
+       default:
+         gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison);
+         break;
+       }
+    }
+
+  /* If this is A op C1 ? A : C2 with C1 and C2 constant integers,
+     we might still be able to simplify this.  For example,
+     if C1 is one less or one more than C2, this might have started
+     out as a MIN or MAX and been transformed by this function.
+     Only good for INTEGER_TYPEs, because we need TYPE_MAX_VALUE.  */
+
+  if (INTEGRAL_TYPE_P (type)
+      && TREE_CODE (arg01) == INTEGER_CST
+      && TREE_CODE (arg2) == INTEGER_CST)
+    switch (comp_code)
+      {
+      case EQ_EXPR:
+       /* We can replace A with C1 in this case.  */
+       arg1 = fold_convert (type, arg01);
+       return fold (build3 (COND_EXPR, type, arg0, arg1, arg2));
+
+      case LT_EXPR:
+       /* If C1 is C2 + 1, this is min(A, C2).  */
+       if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type),
+                              OEP_ONLY_CONST)
+           && operand_equal_p (arg01,
+                               const_binop (PLUS_EXPR, arg2,
+                                            integer_one_node, 0),
+                               OEP_ONLY_CONST))
+         return pedantic_non_lvalue (fold (build2 (MIN_EXPR,
+                                                   type, arg1, arg2)));
+       break;
+
+      case LE_EXPR:
+       /* If C1 is C2 - 1, this is min(A, C2).  */
+       if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type),
+                              OEP_ONLY_CONST)
+           && operand_equal_p (arg01,
+                               const_binop (MINUS_EXPR, arg2,
+                                            integer_one_node, 0),
+                               OEP_ONLY_CONST))
+         return pedantic_non_lvalue (fold (build2 (MIN_EXPR,
+                                                   type, arg1, arg2)));
+       break;
+
+      case GT_EXPR:
+       /* If C1 is C2 - 1, this is max(A, C2).  */
+       if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type),
+                              OEP_ONLY_CONST)
+           && operand_equal_p (arg01,
+                               const_binop (MINUS_EXPR, arg2,
+                                            integer_one_node, 0),
+                               OEP_ONLY_CONST))
+         return pedantic_non_lvalue (fold (build2 (MAX_EXPR,
+                                                   type, arg1, arg2)));
+       break;
+
+      case GE_EXPR:
+       /* If C1 is C2 + 1, this is max(A, C2).  */
+       if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type),
+                              OEP_ONLY_CONST)
+           && operand_equal_p (arg01,
+                               const_binop (PLUS_EXPR, arg2,
+                                            integer_one_node, 0),
+                               OEP_ONLY_CONST))
+         return pedantic_non_lvalue (fold (build2 (MAX_EXPR,
+                                                   type, arg1, arg2)));
+       break;
+      case NE_EXPR:
+       break;
+      default:
+       gcc_unreachable ();
+      }
+
+  return NULL_TREE;
+}
+
+
+\f
+#ifndef LOGICAL_OP_NON_SHORT_CIRCUIT
+#define LOGICAL_OP_NON_SHORT_CIRCUIT (BRANCH_COST >= 2)
 #endif
 
 /* EXP is some logical combination of boolean tests.  See if we can
@@ -4128,7 +4411,7 @@ fold_range_test (tree exp)
   /* On machines where the branch cost is expensive, if this is a
      short-circuited branch and the underlying object on both sides
      is the same, make a non-short-circuit operation.  */
-  else if (RANGE_TEST_NON_SHORT_CIRCUIT
+  else if (LOGICAL_OP_NON_SHORT_CIRCUIT
           && lhs != 0 && rhs != 0
           && (TREE_CODE (exp) == TRUTH_ANDIF_EXPR
               || TREE_CODE (exp) == TRUTH_ORIF_EXPR)
@@ -4271,17 +4554,20 @@ 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, integer_zero_node);
+      lhs = build2 (NE_EXPR, truth_type, lhs,
+                   fold_convert (TREE_TYPE (lhs), integer_zero_node));
       lcode = NE_EXPR;
     }
 
   if (rcode == BIT_AND_EXPR && integer_onep (TREE_OPERAND (rhs, 1)))
     {
-      rhs = build2 (NE_EXPR, truth_type, rhs, integer_zero_node);
+      rhs = build2 (NE_EXPR, truth_type, rhs,
+                   fold_convert (TREE_TYPE (rhs), integer_zero_node));
       rcode = NE_EXPR;
     }
 
-  if (TREE_CODE_CLASS (lcode) != '<' || TREE_CODE_CLASS (rcode) != '<')
+  if (TREE_CODE_CLASS (lcode) != tcc_comparison
+      || TREE_CODE_CLASS (rcode) != tcc_comparison)
     return 0;
 
   ll_arg = TREE_OPERAND (lhs, 0);
@@ -4347,7 +4633,8 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
                               ll_arg, rl_arg),
                       fold_convert (TREE_TYPE (ll_arg), integer_zero_node));
 
-      return build2 (code, truth_type, lhs, rhs);
+      if (LOGICAL_OP_NON_SHORT_CIRCUIT)
+       return build2 (code, truth_type, lhs, rhs);
     }
 
   /* See if the comparisons can be merged.  Then get all the parameters for
@@ -4609,12 +4896,12 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
     {
       if (wanted_code == NE_EXPR)
        {
-         warning ("`or' of unmatched not-equal tests is always 1");
+         warning ("%<or%> of unmatched not-equal tests is always 1");
          return constant_boolean_node (true, truth_type);
        }
       else
        {
-         warning ("`and' of mutually exclusive equal-tests is always 0");
+         warning ("%<and%> of mutually exclusive equal-tests is always 0");
          return constant_boolean_node (false, truth_type);
        }
     }
@@ -4785,10 +5072,10 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type)
   if (integer_zerop (c))
     return NULL_TREE;
 
-  if (TREE_CODE_CLASS (tcode) == '1')
+  if (TREE_CODE_CLASS (tcode) == tcc_unary)
     op0 = TREE_OPERAND (t, 0);
 
-  if (TREE_CODE_CLASS (tcode) == '2')
+  if (TREE_CODE_CLASS (tcode) == tcc_binary)
     op0 = TREE_OPERAND (t, 0), op1 = TREE_OPERAND (t, 1);
 
   /* Note that we need not handle conditional operations here since fold
@@ -4806,10 +5093,10 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type)
 
     case CONVERT_EXPR:  case NON_LVALUE_EXPR:  case NOP_EXPR:
       /* If op0 is an expression ...  */
-      if ((TREE_CODE_CLASS (TREE_CODE (op0)) == '<'
-          || TREE_CODE_CLASS (TREE_CODE (op0)) == '1'
-          || TREE_CODE_CLASS (TREE_CODE (op0)) == '2'
-          || TREE_CODE_CLASS (TREE_CODE (op0)) == 'e')
+      if ((COMPARISON_CLASS_P (op0)
+          || UNARY_CLASS_P (op0)
+          || BINARY_CLASS_P (op0)
+          || EXPRESSION_CLASS_P (op0))
          /* ... and is unsigned, and its type is smaller than ctype,
             then we cannot pass through as widening.  */
          && ((TYPE_UNSIGNED (TREE_TYPE (op0))
@@ -4817,9 +5104,9 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type)
                     && TYPE_IS_SIZETYPE (TREE_TYPE (op0)))
               && (GET_MODE_SIZE (TYPE_MODE (ctype))
                   > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0)))))
-             /* ... or its type is larger than ctype,
-                then we cannot pass through this truncation.  */
-             || (GET_MODE_SIZE (TYPE_MODE (ctype))
+             /* ... or this is a truncation (t is narrower than op0),
+                then we cannot pass through this narrowing.  */
+             || (GET_MODE_SIZE (TYPE_MODE (type))
                  < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0))))
              /* ... or signedness changes for division or modulus,
                 then we cannot pass through this conversion.  */
@@ -4840,11 +5127,25 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type)
        return t1;
       break;
 
-    case NEGATE_EXPR:  case ABS_EXPR:
-      if ((t1 = extract_muldiv (op0, c, code, wide_type)) != 0)
-       return fold (build1 (tcode, ctype, fold_convert (ctype, t1)));
-      break;
-
+    case ABS_EXPR:
+      /* If widening the type changes it from signed to unsigned, then we
+         must avoid building ABS_EXPR itself as unsigned.  */
+      if (TYPE_UNSIGNED (ctype) && !TYPE_UNSIGNED (type))
+        {
+          tree cstype = (*lang_hooks.types.signed_type) (ctype);
+          if ((t1 = extract_muldiv (op0, c, code, cstype)) != 0)
+            {
+              t1 = fold (build1 (tcode, cstype, fold_convert (cstype, t1)));
+              return fold_convert (ctype, t1);
+            }
+          break;
+        }
+      /* FALLTHROUGH */
+    case NEGATE_EXPR:
+      if ((t1 = extract_muldiv (op0, c, code, wide_type)) != 0)
+       return fold (build1 (tcode, ctype, fold_convert (ctype, t1)));
+      break;
+
     case MIN_EXPR:  case MAX_EXPR:
       /* If widening the type changes the signedness, then we can't perform
         this optimization as that changes the result.  */
@@ -4866,8 +5167,12 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type)
     case LSHIFT_EXPR:  case RSHIFT_EXPR:
       /* If the second operand is constant, this is a multiplication
         or floor division, by a power of two, so we can treat it that
-        way unless the multiplier or divisor overflows.  */
+        way unless the multiplier or divisor overflows.  Signed
+        left-shift overflow is implementation-defined rather than
+        undefined in C90, so do not convert signed left shift into
+        multiplication.  */
       if (TREE_CODE (op1) == INTEGER_CST
+         && (tcode == RSHIFT_EXPR || TYPE_UNSIGNED (TREE_TYPE (op0)))
          /* const_binop may not detect overflow correctly,
             so check for it explicitly here.  */
          && TYPE_PRECISION (TREE_TYPE (size_one_node)) > TREE_INT_CST_LOW (op1)
@@ -5035,7 +5340,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type)
 /* Return a node which has the indicated constant VALUE (either 0 or
    1), and is of the indicated TYPE.  */
 
-static tree
+tree
 constant_boolean_node (int value, tree type)
 {
   if (type == integer_type_node)
@@ -5046,12 +5351,7 @@ constant_boolean_node (int value, tree type)
     return lang_hooks.truthvalue_conversion (value ? integer_one_node
                                                   : integer_zero_node);
   else
-    {
-      tree t = build_int_2 (value, 0);
-
-      TREE_TYPE (t) = type;
-      return t;
-    }
+    return build_int_cst (type, value);
 }
 
 /* Transform `a + (b ? x : y)' into `b ? (a + x) : (a + y)'.
@@ -5345,7 +5645,7 @@ fold_inf_compare (enum tree_code code, tree type, tree arg0, tree arg1)
         not appropriate if we are in gimple form.  */
       if (in_gimple_form)
        return NULL_TREE;
-       
+
       temp = fold (build2 (neg ? LT_EXPR : GT_EXPR, type,
                           arg0, build_real (TREE_TYPE (arg0), max)));
       return fold (build1 (TRUTH_NOT_EXPR, type, temp));
@@ -5384,12 +5684,8 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
                         TREE_INT_CST_HIGH (arg01),
                         TREE_INT_CST_LOW (arg1),
                         TREE_INT_CST_HIGH (arg1), &lpart, &hpart);
-  prod = build_int_2 (lpart, hpart);
-  TREE_TYPE (prod) = TREE_TYPE (arg00);
-  TREE_OVERFLOW (prod) = force_fit_type (prod, overflow)
-                        || TREE_INT_CST_HIGH (prod) != hpart
-                        || TREE_INT_CST_LOW (prod) != lpart;
-  TREE_CONSTANT_OVERFLOW (prod) = TREE_OVERFLOW (prod);
+  prod = build_int_cst_wide (TREE_TYPE (arg00), lpart, hpart);
+  prod = force_fit_type (prod, -1, overflow, false);
 
   if (TYPE_UNSIGNED (TREE_TYPE (arg0)))
     {
@@ -5402,13 +5698,9 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
                             TREE_INT_CST_LOW (tmp),
                             TREE_INT_CST_HIGH (tmp),
                             &lpart, &hpart);
-      hi = build_int_2 (lpart, hpart);
-      TREE_TYPE (hi) = TREE_TYPE (arg00);
-      TREE_OVERFLOW (hi) = force_fit_type (hi, overflow)
-                          || TREE_INT_CST_HIGH (hi) != hpart
-                          || TREE_INT_CST_LOW (hi) != lpart
-                          || TREE_OVERFLOW (prod);
-      TREE_CONSTANT_OVERFLOW (hi) = TREE_OVERFLOW (hi);
+      hi = build_int_cst_wide (TREE_TYPE (arg00), lpart, hpart);
+      hi = force_fit_type (hi, -1, overflow | TREE_OVERFLOW (prod),
+                          TREE_CONSTANT_OVERFLOW (prod));
     }
   else if (tree_int_cst_sgn (arg01) >= 0)
     {
@@ -5431,11 +5723,14 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
   else
     {
+      /* A negative divisor reverses the relational operators.  */
+      code = swap_tree_comparison (code);
+
       tmp = int_const_binop (PLUS_EXPR, arg01, integer_one_node, 0);
       switch (tree_int_cst_sgn (arg1))
        {
@@ -5455,7 +5750,7 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
 
@@ -5511,7 +5806,7 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
    equality/inequality test, then return a simplified form of
    the test using shifts and logical operations.  Otherwise return
    NULL.  TYPE is the desired result type.  */
+
 tree
 fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
                      tree result_type)
@@ -5528,7 +5823,7 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
       arg1 = TREE_OPERAND (arg0, 1);
       arg0 = TREE_OPERAND (arg0, 0);
 
-      /* This requires us to invert the code.  */ 
+      /* This requires us to invert the code.  */
       code = (code == EQ_EXPR ? NE_EXPR : EQ_EXPR);
     }
 
@@ -5544,7 +5839,7 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
       int ops_unsigned;
       tree signed_type, unsigned_type, intermediate_type;
       tree arg00;
-  
+
       /* If we have (A & C) != 0 where C is the sign bit of A, convert
         this into A < 0.  Similarly for (A & C) == 0 into A >= 0.  */
       arg00 = sign_bit_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1));
@@ -5560,7 +5855,7 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
                               fold_convert (stype, integer_zero_node)));
        }
 
-      /* Otherwise we have (A & C) != 0 where C is a single bit, 
+      /* Otherwise we have (A & C) != 0 where C is a single bit,
         convert that into ((A >> C2) & 1).  Where C2 = log2(C).
         Similarly for (A & C) == 0.  */
 
@@ -5581,7 +5876,8 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
         operations as unsigned.  If we must use the AND, we have a choice.
         Normally unsigned is faster, but for some machines signed is.  */
 #ifdef LOAD_EXTEND_OP
-      ops_unsigned = (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND ? 0 : 1);
+      ops_unsigned = (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND 
+                     && !flag_syntax_only) ? 0 : 1;
 #else
       ops_unsigned = 1;
 #endif
@@ -5596,8 +5892,8 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
                        inner, size_int (bitnum));
 
       if (code == EQ_EXPR)
-       inner = build2 (BIT_XOR_EXPR, intermediate_type,
-                       inner, integer_one_node);
+       inner = fold (build2 (BIT_XOR_EXPR, intermediate_type,
+                             inner, integer_one_node));
 
       /* Put the AND last so it can combine with more things.  */
       inner = build2 (BIT_AND_EXPR, intermediate_type,
@@ -5618,7 +5914,7 @@ static bool
 reorder_operands_p (tree arg0, tree arg1)
 {
   if (! flag_evaluation_order)
-    return true;
+      return true;
   if (TREE_CONSTANT (arg0) || TREE_CONSTANT (arg1))
     return true;
   return ! TREE_SIDE_EFFECTS (arg0)
@@ -5655,18 +5951,9 @@ tree_swap_operands_p (tree arg0, tree arg1, bool reorder)
     return 0;
   if (TREE_CONSTANT (arg0))
     return 1;
-    
-  if (optimize_size)
-    return 0;
-
-  if (reorder && flag_evaluation_order
-      && (TREE_SIDE_EFFECTS (arg0) || TREE_SIDE_EFFECTS (arg1)))
-    return 0;
 
-  if (DECL_P (arg1))
+  if (optimize_size)
     return 0;
-  if (DECL_P (arg0))
-    return 1;
 
   if (reorder && flag_evaluation_order
       && (TREE_SIDE_EFFECTS (arg0) || TREE_SIDE_EFFECTS (arg1)))
@@ -5689,6 +5976,251 @@ tree_swap_operands_p (tree arg0, tree arg1, bool reorder)
   return 0;
 }
 
+/* Fold comparison ARG0 CODE ARG1 (with result in TYPE), where
+   ARG0 is extended to a wider type.  */
+
+static tree
+fold_widened_comparison (enum tree_code code, tree type, tree arg0, tree arg1)
+{
+  tree arg0_unw = get_unwidened (arg0, NULL_TREE);
+  tree arg1_unw;
+  tree shorter_type, outer_type;
+  tree min, max;
+  bool above, below;
+
+  if (arg0_unw == arg0)
+    return NULL_TREE;
+  shorter_type = TREE_TYPE (arg0_unw);
+  
+  arg1_unw = get_unwidened (arg1, shorter_type);
+  if (!arg1_unw)
+    return NULL_TREE;
+
+  /* If possible, express the comparison in the shorter mode.  */
+  if ((code == EQ_EXPR || code == NE_EXPR
+       || TYPE_UNSIGNED (TREE_TYPE (arg0)) == TYPE_UNSIGNED (shorter_type))
+      && (TREE_TYPE (arg1_unw) == shorter_type
+         || (TREE_CODE (arg1_unw) == INTEGER_CST
+             && TREE_CODE (shorter_type) == INTEGER_TYPE
+             && int_fits_type_p (arg1_unw, shorter_type))))
+    return fold (build (code, type, arg0_unw,
+                       fold_convert (shorter_type, arg1_unw)));
+
+  if (TREE_CODE (arg1_unw) != INTEGER_CST)
+    return NULL_TREE;
+
+  /* If we are comparing with the integer that does not fit into the range
+     of the shorter type, the result is known.  */
+  outer_type = TREE_TYPE (arg1_unw);
+  min = lower_bound_in_type (outer_type, shorter_type);
+  max = upper_bound_in_type (outer_type, shorter_type);
+
+  above = integer_nonzerop (fold_relational_const (LT_EXPR, type,
+                                                  max, arg1_unw));
+  below = integer_nonzerop (fold_relational_const (LT_EXPR, type,
+                                                  arg1_unw, min));
+
+  switch (code)
+    {
+    case EQ_EXPR:
+      if (above || below)
+       return omit_one_operand (type, integer_zero_node, arg0);
+      break;
+
+    case NE_EXPR:
+      if (above || below)
+       return omit_one_operand (type, integer_one_node, arg0);
+      break;
+
+    case LT_EXPR:
+    case LE_EXPR:
+      if (above)
+       return omit_one_operand (type, integer_one_node, arg0);
+      else if (below)
+       return omit_one_operand (type, integer_zero_node, arg0);
+
+    case GT_EXPR:
+    case GE_EXPR:
+      if (above)
+       return omit_one_operand (type, integer_zero_node, arg0);
+      else if (below)
+       return omit_one_operand (type, integer_one_node, arg0);
+
+    default:
+      break;
+    }
+
+  return NULL_TREE;
+}
+
+/* Fold comparison ARG0 CODE ARG1 (with result in TYPE), where for
+   ARG0 just the signedness is changed.  */
+
+static tree
+fold_sign_changed_comparison (enum tree_code code, tree type,
+                             tree arg0, tree arg1)
+{
+  tree arg0_inner, tmp;
+  tree inner_type, outer_type;
+
+  if (TREE_CODE (arg0) != NOP_EXPR)
+    return NULL_TREE;
+
+  outer_type = TREE_TYPE (arg0);
+  arg0_inner = TREE_OPERAND (arg0, 0);
+  inner_type = TREE_TYPE (arg0_inner);
+
+  if (TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type))
+    return NULL_TREE;
+
+  if (TREE_CODE (arg1) != INTEGER_CST
+      && !(TREE_CODE (arg1) == NOP_EXPR
+          && TREE_TYPE (TREE_OPERAND (arg1, 0)) == inner_type))
+    return NULL_TREE;
+
+  if (TYPE_UNSIGNED (inner_type) != TYPE_UNSIGNED (outer_type)
+      && code != NE_EXPR
+      && code != EQ_EXPR)
+    return NULL_TREE;
+
+  if (TREE_CODE (arg1) == INTEGER_CST)
+    {
+      tmp = build_int_cst_wide (inner_type,
+                               TREE_INT_CST_LOW (arg1),
+                               TREE_INT_CST_HIGH (arg1));
+      arg1 = force_fit_type (tmp, 0,
+                            TREE_OVERFLOW (arg1),
+                            TREE_CONSTANT_OVERFLOW (arg1));
+    }
+  else
+    arg1 = fold_convert (inner_type, arg1);
+
+  return fold (build (code, type, arg0_inner, arg1));
+}
+
+/* Tries to replace &a[idx] CODE s * delta with &a[idx CODE delta], if s is
+   step of the array.  TYPE is the type of the expression.  ADDR is the address.
+   MULT is the multiplicative expression.  If the function succeeds, the new
+   address expression is returned.  Otherwise NULL_TREE is returned.  */
+
+static tree
+try_move_mult_to_index (tree type, enum tree_code code, tree addr, tree mult)
+{
+  tree s, delta, step;
+  tree arg0 = TREE_OPERAND (mult, 0), arg1 = TREE_OPERAND (mult, 1);
+  tree ref = TREE_OPERAND (addr, 0), pref;
+  tree ret, pos;
+  tree itype;
+
+  STRIP_NOPS (arg0);
+  STRIP_NOPS (arg1);
+  
+  if (TREE_CODE (arg0) == INTEGER_CST)
+    {
+      s = arg0;
+      delta = arg1;
+    }
+  else if (TREE_CODE (arg1) == INTEGER_CST)
+    {
+      s = arg1;
+      delta = arg0;
+    }
+  else
+    return NULL_TREE;
+
+  for (;; ref = TREE_OPERAND (ref, 0))
+    {
+      if (TREE_CODE (ref) == ARRAY_REF)
+       {
+         step = array_ref_element_size (ref);
+
+         if (TREE_CODE (step) != INTEGER_CST)
+           continue;
+
+         itype = TREE_TYPE (step);
+
+         /* If the type sizes do not match, we might run into problems
+            when one of them would overflow.  */
+         if (TYPE_PRECISION (itype) != TYPE_PRECISION (type))
+           continue;
+
+         if (!operand_equal_p (step, fold_convert (itype, s), 0))
+           continue;
+
+         delta = fold_convert (itype, delta);
+         break;
+       }
+
+      if (!handled_component_p (ref))
+       return NULL_TREE;
+    }
+
+  /* We found the suitable array reference.  So copy everything up to it,
+     and replace the index.  */
+
+  pref = TREE_OPERAND (addr, 0);
+  ret = copy_node (pref);
+  pos = ret;
+
+  while (pref != ref)
+    {
+      pref = TREE_OPERAND (pref, 0);
+      TREE_OPERAND (pos, 0) = copy_node (pref);
+      pos = TREE_OPERAND (pos, 0);
+    }
+
+  TREE_OPERAND (pos, 1) = fold (build2 (code, itype,
+                                       TREE_OPERAND (pos, 1),
+                                       delta));
+
+  return build1 (ADDR_EXPR, type, ret);
+}
+
+
+/* Fold A < X && A + 1 > Y to A < X && A >= Y.  Normally A + 1 > Y
+   means A >= Y && A != MAX, but in this case we know that
+   A < X <= MAX.  INEQ is A + 1 > Y, BOUND is A < X.  */
+
+static tree
+fold_to_nonsharp_ineq_using_bound (tree ineq, tree bound)
+{
+  tree a, typea, type = TREE_TYPE (ineq), a1, diff, y;
+
+  if (TREE_CODE (bound) == LT_EXPR)
+    a = TREE_OPERAND (bound, 0);
+  else if (TREE_CODE (bound) == GT_EXPR)
+    a = TREE_OPERAND (bound, 1);
+  else
+    return NULL_TREE;
+
+  typea = TREE_TYPE (a);
+  if (!INTEGRAL_TYPE_P (typea)
+      && !POINTER_TYPE_P (typea))
+    return NULL_TREE;
+
+  if (TREE_CODE (ineq) == LT_EXPR)
+    {
+      a1 = TREE_OPERAND (ineq, 1);
+      y = TREE_OPERAND (ineq, 0);
+    }
+  else if (TREE_CODE (ineq) == GT_EXPR)
+    {
+      a1 = TREE_OPERAND (ineq, 0);
+      y = TREE_OPERAND (ineq, 1);
+    }
+  else
+    return NULL_TREE;
+
+  if (TREE_TYPE (a1) != typea)
+    return NULL_TREE;
+
+  diff = fold (build2 (MINUS_EXPR, typea, a1, a));
+  if (!integer_onep (diff))
+    return NULL_TREE;
+
+  return fold (build2 (GE_EXPR, type, a, y));
+}
+
 /* Perform constant folding and related simplification of EXPR.
    The related simplifications include x*1 => x, x*0 => 0, etc.,
    and application of the associative law.
@@ -5711,19 +6243,14 @@ fold (tree expr)
   tree tem;
   tree arg0 = NULL_TREE, arg1 = NULL_TREE;
   enum tree_code code = TREE_CODE (t);
-  int kind = TREE_CODE_CLASS (code);
+  enum tree_code_class kind = TREE_CODE_CLASS (code);
 
   /* WINS will be nonzero when the switch is done
      if all operands are constant.  */
   int wins = 1;
 
-  /* Don't try to process an RTL_EXPR since its operands aren't trees.
-     Likewise for a SAVE_EXPR that's already been evaluated.  */
-  if (code == RTL_EXPR || (code == SAVE_EXPR && SAVE_EXPR_RTL (t) != 0))
-    return t;
-
   /* Return right away if a constant.  */
-  if (kind == 'c')
+  if (kind == tcc_constant)
     return t;
 
   if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR)
@@ -5751,7 +6278,7 @@ fold (tree expr)
     }
   else if (IS_EXPR_CODE_CLASS (kind))
     {
-      int len = first_rtl_op (code);
+      int len = TREE_CODE_LENGTH (code);
       int i;
       for (i = 0; i < len; i++)
        {
@@ -5772,7 +6299,7 @@ fold (tree expr)
             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 == '<')
+         if (kind == tcc_comparison)
            STRIP_SIGN_NOPS (op);
          else
            STRIP_NOPS (op);
@@ -5844,7 +6371,7 @@ fold (tree expr)
       return tem;
     }
 
-  if (TREE_CODE_CLASS (code) == '1')
+  if (TREE_CODE_CLASS (code) == tcc_unary)
     {
       if (TREE_CODE (arg0) == COMPOUND_EXPR)
        return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
@@ -5878,10 +6405,11 @@ fold (tree expr)
              && ! VOID_TYPE_P (TREE_OPERAND (tem, 2))
              && (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 1), 0))
                  == TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 2), 0)))
-             && ! (INTEGRAL_TYPE_P (TREE_TYPE (tem))
-                   && (INTEGRAL_TYPE_P
-                       (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 1), 0))))
-                   && TYPE_PRECISION (TREE_TYPE (tem)) <= BITS_PER_WORD))
+             && (! (INTEGRAL_TYPE_P (TREE_TYPE (tem))
+                    && (INTEGRAL_TYPE_P
+                        (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 1), 0))))
+                    && TYPE_PRECISION (TREE_TYPE (tem)) <= BITS_PER_WORD)
+                 || flag_syntax_only))
            tem = build1 (code, type,
                          build3 (COND_EXPR,
                                  TREE_TYPE (TREE_OPERAND
@@ -5891,7 +6419,7 @@ fold (tree expr)
                                  TREE_OPERAND (TREE_OPERAND (tem, 2), 0)));
          return tem;
        }
-      else if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<')
+      else if (COMPARISON_CLASS_P (arg0))
        {
          if (TREE_CODE (type) == BOOLEAN_TYPE)
            {
@@ -5907,16 +6435,16 @@ fold (tree expr)
                                               integer_zero_node))));
        }
    }
-  else if (TREE_CODE_CLASS (code) == '<'
+  else if (TREE_CODE_CLASS (code) == tcc_comparison
           && TREE_CODE (arg0) == COMPOUND_EXPR)
     return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
                   fold (build2 (code, type, TREE_OPERAND (arg0, 1), arg1)));
-  else if (TREE_CODE_CLASS (code) == '<'
+  else if (TREE_CODE_CLASS (code) == tcc_comparison
           && TREE_CODE (arg1) == COMPOUND_EXPR)
     return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
                   fold (build2 (code, type, arg0, TREE_OPERAND (arg1, 1))));
-  else if (TREE_CODE_CLASS (code) == '2'
-          || TREE_CODE_CLASS (code) == '<')
+  else if (TREE_CODE_CLASS (code) == tcc_binary
+          || TREE_CODE_CLASS (code) == tcc_comparison)
     {
       if (TREE_CODE (arg0) == COMPOUND_EXPR)
        return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
@@ -5928,8 +6456,7 @@ fold (tree expr)
                       fold (build2 (code, type,
                                     arg0, TREE_OPERAND (arg1, 1))));
 
-      if (TREE_CODE (arg0) == COND_EXPR
-         || TREE_CODE_CLASS (TREE_CODE (arg0)) == '<')
+      if (TREE_CODE (arg0) == COND_EXPR || COMPARISON_CLASS_P (arg0))
        {
          tem = fold_binary_op_with_conditional_arg (code, type, arg0, arg1,
                                                     /*cond_first_p=*/1);
@@ -5937,8 +6464,7 @@ fold (tree expr)
            return tem;
        }
 
-      if (TREE_CODE (arg1) == COND_EXPR
-         || TREE_CODE_CLASS (TREE_CODE (arg1)) == '<')
+      if (TREE_CODE (arg1) == COND_EXPR || COMPARISON_CLASS_P (arg1))
        {
          tem = fold_binary_op_with_conditional_arg (code, type, arg1, arg0,
                                                     /*cond_first_p=*/0);
@@ -6090,6 +6616,7 @@ fold (tree expr)
              change = (cst == 0);
 #ifdef LOAD_EXTEND_OP
              if (change
+                 && !flag_syntax_only
                  && (LOAD_EXTEND_OP (TYPE_MODE (TREE_TYPE (and0)))
                      == ZERO_EXTEND))
                {
@@ -6108,7 +6635,7 @@ fold (tree expr)
       /* Convert (T1)((T2)X op Y) into (T1)X op Y, for pointer types T1 and
         T2 being pointers to types of the same size.  */
       if (POINTER_TYPE_P (TREE_TYPE (t))
-         && TREE_CODE_CLASS (TREE_CODE (arg0)) == '2'
+         && BINARY_CLASS_P (arg0)
          && TREE_CODE (TREE_OPERAND (arg0, 0)) == NOP_EXPR
          && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (arg0, 0))))
        {
@@ -6237,17 +6764,21 @@ fold (tree expr)
          /* Reassociate (plus (plus (mult) (foo)) (mult)) as
             (plus (plus (mult) (mult)) (foo)) so that we can
             take advantage of the factoring cases below.  */
-         if ((TREE_CODE (arg0) == PLUS_EXPR
+         if (((TREE_CODE (arg0) == PLUS_EXPR
+               || TREE_CODE (arg0) == MINUS_EXPR)
               && TREE_CODE (arg1) == MULT_EXPR)
-             || (TREE_CODE (arg1) == PLUS_EXPR
+             || ((TREE_CODE (arg1) == PLUS_EXPR
+                  || TREE_CODE (arg1) == MINUS_EXPR)
                  && TREE_CODE (arg0) == MULT_EXPR))
            {
              tree parg0, parg1, parg, marg;
+             enum tree_code pcode;
 
-             if (TREE_CODE (arg0) == PLUS_EXPR)
+             if (TREE_CODE (arg1) == MULT_EXPR)
                parg = arg0, marg = arg1;
              else
                parg = arg1, marg = arg0;
+             pcode = TREE_CODE (parg);
              parg0 = TREE_OPERAND (parg, 0);
              parg1 = TREE_OPERAND (parg, 1);
              STRIP_NOPS (parg0);
@@ -6255,7 +6786,7 @@ fold (tree expr)
 
              if (TREE_CODE (parg0) == MULT_EXPR
                  && TREE_CODE (parg1) != MULT_EXPR)
-               return fold (build2 (PLUS_EXPR, type,
+               return fold (build2 (pcode, type,
                                     fold (build2 (PLUS_EXPR, type,
                                                   fold_convert (type, parg0),
                                                   fold_convert (type, marg))),
@@ -6263,10 +6794,11 @@ fold (tree expr)
              if (TREE_CODE (parg0) != MULT_EXPR
                  && TREE_CODE (parg1) == MULT_EXPR)
                return fold (build2 (PLUS_EXPR, type,
-                                    fold (build2 (PLUS_EXPR, type,
-                                                  fold_convert (type, parg1),
-                                                  fold_convert (type, marg))),
-                                    fold_convert (type, parg0)));
+                                    fold_convert (type, parg0),
+                                    fold (build2 (pcode, type,
+                                                  fold_convert (type, marg),
+                                                  fold_convert (type,
+                                                                parg1)))));
            }
 
          if (TREE_CODE (arg0) == MULT_EXPR && TREE_CODE (arg1) == MULT_EXPR)
@@ -6318,7 +6850,8 @@ fold (tree expr)
                  if (exact_log2 (int11) > 0 && int01 % int11 == 0)
                    {
                      alt0 = fold (build2 (MULT_EXPR, type, arg00,
-                                          build_int_2 (int01 / int11, 0)));
+                                          build_int_cst (NULL_TREE,
+                                                         int01 / int11)));
                      alt1 = arg10;
                      same = arg11;
                    }
@@ -6327,9 +6860,28 @@ fold (tree expr)
              if (same)
                return fold (build2 (MULT_EXPR, type,
                                     fold (build2 (PLUS_EXPR, type,
-                                                  alt0, alt1)),
+                                                  fold_convert (type, alt0),
+                                                  fold_convert (type, alt1))),
                                     same));
            }
+
+         /* Try replacing &a[i1] + c * i2 with &a[i1 + i2], if c is step
+            of the array.  Loop optimizer sometimes produce this type of
+            expressions.  */
+         if (TREE_CODE (arg0) == ADDR_EXPR
+             && TREE_CODE (arg1) == MULT_EXPR)
+           {
+             tem = try_move_mult_to_index (type, PLUS_EXPR, arg0, arg1);
+             if (tem)
+               return fold (tem);
+           }
+         else if (TREE_CODE (arg1) == ADDR_EXPR
+                  && TREE_CODE (arg0) == MULT_EXPR)
+           {
+             tem = try_move_mult_to_index (type, PLUS_EXPR, arg1, arg0);
+             if (tem)
+               return fold (tem);
+           }
        }
       else
        {
@@ -6341,6 +6893,17 @@ fold (tree expr)
          if (fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0))
            return non_lvalue (fold_convert (type, arg1));
 
+         /* Convert X + -C into X - C.  */
+         if (TREE_CODE (arg1) == REAL_CST
+             && REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1)))
+           {
+             tem = fold_negate_const (arg1, type);
+             if (!TREE_OVERFLOW (arg1) || !flag_trapping_math)
+               return fold (build2 (MINUS_EXPR, type,
+                                    fold_convert (type, arg0),
+                                    fold_convert (type, tem)));
+           }
+
          /* Convert x+x into x*2.0.  */
          if (operand_equal_p (arg0, arg1, 0)
              && SCALAR_FLOAT_TYPE_P (type))
@@ -6397,7 +6960,7 @@ fold (tree expr)
                                   TREE_OPERAND (arg0, 0),
                                   build_real (type, c1)));
            }
-          /* Convert a + (b*c + d*e) into (a + b*c) + d*e */
+          /* Convert a + (b*c + d*e) into (a + b*c) + d*e */
           if (flag_unsafe_math_optimizations
               && TREE_CODE (arg1) == PLUS_EXPR
               && TREE_CODE (arg0) != MULT_EXPR)
@@ -6412,7 +6975,7 @@ fold (tree expr)
                   return fold (build2 (PLUS_EXPR, type, tree0, tree11));
                 }
             }
-          /* Convert (b*c + d*e) + a into b*c + (d*e +a) */
+          /* Convert (b*c + d*e) + a into b*c + (d*e +a) */
           if (flag_unsafe_math_optimizations
               && TREE_CODE (arg0) == PLUS_EXPR
               && TREE_CODE (arg1) != MULT_EXPR)
@@ -6641,7 +7204,7 @@ fold (tree expr)
              tree mask0 = TREE_OPERAND (arg0, 1);
              tree mask1 = TREE_OPERAND (arg1, 1);
              tree tem = fold (build1 (BIT_NOT_EXPR, type, mask0));
-             
+
              if (operand_equal_p (tem, mask1, 0))
                {
                  tem = fold (build2 (BIT_XOR_EXPR, type,
@@ -6673,13 +7236,37 @@ fold (tree expr)
 
       /* A - B -> A + (-B) if B is easily negatable.  */
       if (!wins && negate_expr_p (arg1)
-         && (FLOAT_TYPE_P (type)
+         && ((FLOAT_TYPE_P (type)
+               /* Avoid this transformation if B is a positive REAL_CST.  */
+              && (TREE_CODE (arg1) != REAL_CST
+                  ||  REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1))))
              || (INTEGRAL_TYPE_P (type) && flag_wrapv && !flag_trapv)))
        return fold (build2 (PLUS_EXPR, type, arg0, negate_expr (arg1)));
 
+      /* Try folding difference of addresses.  */
+      {
+       HOST_WIDE_INT diff;
+
+       if ((TREE_CODE (arg0) == ADDR_EXPR
+            || TREE_CODE (arg1) == ADDR_EXPR)
+           && ptr_difference_const (arg0, arg1, &diff))
+         return build_int_cst_type (type, diff);
+      }
+         
+      /* Try replacing &a[i1] - c * i2 with &a[i1 - i2], if c is step
+        of the array.  Loop optimizer sometimes produce this type of
+        expressions.  */
+      if (TREE_CODE (arg0) == ADDR_EXPR
+         && TREE_CODE (arg1) == MULT_EXPR)
+       {
+         tem = try_move_mult_to_index (type, MINUS_EXPR, arg0, arg1);
+         if (tem)
+           return fold (tem);
+       }
+
       if (TREE_CODE (arg0) == MULT_EXPR
          && TREE_CODE (arg1) == MULT_EXPR
-         && (INTEGRAL_TYPE_P (type) || flag_unsafe_math_optimizations))
+         && (!FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations))
        {
           /* (A * C) - (B * C) -> (A-B) * C.  */
          if (operand_equal_p (TREE_OPERAND (arg0, 1),
@@ -6933,6 +7520,25 @@ fold (tree expr)
        return non_lvalue (fold_convert (type, arg0));
       if (operand_equal_p (arg0, arg1, 0))
        return non_lvalue (fold_convert (type, arg0));
+
+      /* ~X | X is -1.  */
+      if (TREE_CODE (arg0) == BIT_NOT_EXPR
+         && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+       {
+         t1 = build_int_cst (type, -1);
+         t1 = force_fit_type (t1, 0, false, false);
+         return omit_one_operand (type, t1, arg1);
+       }
+
+      /* X | ~X is -1.  */
+      if (TREE_CODE (arg1) == BIT_NOT_EXPR
+         && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+       {
+         t1 = build_int_cst (type, -1);
+         t1 = force_fit_type (t1, 0, false, false);
+         return omit_one_operand (type, t1, arg0);
+       }
+
       t1 = distribute_bit_expr (code, type, arg0, arg1);
       if (t1 != NULL_TREE)
        return t1;
@@ -6964,6 +7570,24 @@ fold (tree expr)
       if (operand_equal_p (arg0, arg1, 0))
        return omit_one_operand (type, integer_zero_node, arg0);
 
+      /* ~X ^ X is -1.  */
+      if (TREE_CODE (arg0) == BIT_NOT_EXPR
+         && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+       {
+         t1 = build_int_cst (type, -1);
+         t1 = force_fit_type (t1, 0, false, false);
+         return omit_one_operand (type, t1, arg1);
+       }
+
+      /* X ^ ~X is -1.  */
+      if (TREE_CODE (arg1) == BIT_NOT_EXPR
+         && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+       {
+         t1 = build_int_cst (type, -1);
+         t1 = force_fit_type (t1, 0, false, false);
+         return omit_one_operand (type, t1, arg0);
+       }
+
       /* If we are XORing two BIT_AND_EXPR's, both of which are and'ing
          with a constant, and the two constants have no bits in common,
         we should treat this as a BIT_IOR_EXPR since this may produce more
@@ -6991,6 +7615,17 @@ fold (tree expr)
        return omit_one_operand (type, arg1, arg0);
       if (operand_equal_p (arg0, arg1, 0))
        return non_lvalue (fold_convert (type, arg0));
+
+      /* ~X & X is always zero.  */
+      if (TREE_CODE (arg0) == BIT_NOT_EXPR
+         && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+       return omit_one_operand (type, integer_zero_node, arg1);
+
+      /* X & ~X is always zero.  */
+      if (TREE_CODE (arg1) == BIT_NOT_EXPR
+         && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+       return omit_one_operand (type, integer_zero_node, arg0);
+
       t1 = distribute_bit_expr (code, type, arg0, arg1);
       if (t1 != NULL_TREE)
        return t1;
@@ -7237,6 +7872,7 @@ fold (tree expr)
        return omit_one_operand (type, integer_zero_node, arg0);
       if (integer_zerop (arg1))
        return t;
+
       /* X % -1 is zero.  */
       if (!TYPE_UNSIGNED (type)
          && TREE_CODE (arg1) == INTEGER_CST
@@ -7244,6 +7880,53 @@ fold (tree expr)
          && TREE_INT_CST_HIGH (arg1) == -1)
        return omit_one_operand (type, integer_zero_node, arg0);
 
+      /* Optimize unsigned TRUNC_MOD_EXPR by a power of two into a
+        BIT_AND_EXPR, i.e. "X % C" into "X & C2".  */
+      if (code == TRUNC_MOD_EXPR
+         && TYPE_UNSIGNED (type)
+         && integer_pow2p (arg1))
+       {
+         unsigned HOST_WIDE_INT high, low;
+         tree mask;
+         int l;
+
+         l = tree_log2 (arg1);
+         if (l >= HOST_BITS_PER_WIDE_INT)
+           {
+             high = ((unsigned HOST_WIDE_INT) 1
+                     << (l - HOST_BITS_PER_WIDE_INT)) - 1;
+             low = -1;
+           }
+         else
+           {
+             high = 0;
+             low = ((unsigned HOST_WIDE_INT) 1 << l) - 1;
+           }
+
+         mask = build_int_cst_wide (type, low, high);
+         return fold (build2 (BIT_AND_EXPR, type,
+                              fold_convert (type, arg0), mask));
+       }
+
+      /* X % -C is the same as X % C.  */
+      if (code == TRUNC_MOD_EXPR
+         && !TYPE_UNSIGNED (type)
+         && TREE_CODE (arg1) == INTEGER_CST
+         && TREE_INT_CST_HIGH (arg1) < 0
+         && !flag_trapv
+         /* Avoid this transformation if C is INT_MIN, i.e. C == -C.  */
+         && !sign_bit_p (arg1, arg1))
+       return fold (build2 (code, type, fold_convert (type, arg0),
+                            fold_convert (type, negate_expr (arg1))));
+
+      /* X % -Y is the same as X % Y.  */
+      if (code == TRUNC_MOD_EXPR
+         && !TYPE_UNSIGNED (type)
+         && TREE_CODE (arg1) == NEGATE_EXPR
+         && !flag_trapv)
+       return fold (build2 (code, type, fold_convert (type, arg0),
+                            fold_convert (type, TREE_OPERAND (arg1, 0))));
+
       if (TREE_CODE (arg1) == INTEGER_CST
          && 0 != (tem = extract_muldiv (TREE_OPERAND (t, 0), arg1,
                                         code, NULL_TREE)))
@@ -7278,7 +7961,8 @@ fold (tree expr)
         RROTATE_EXPR by a new constant.  */
       if (code == LROTATE_EXPR && TREE_CODE (arg1) == INTEGER_CST)
        {
-         tree tem = build_int_2 (GET_MODE_BITSIZE (TYPE_MODE (type)), 0);
+         tree tem = build_int_cst (NULL_TREE,
+                                   GET_MODE_BITSIZE (TYPE_MODE (type)));
          tem = fold_convert (TREE_TYPE (arg1), tem);
          tem = const_binop (MINUS_EXPR, tem, arg1, 0);
          return fold (build2 (RROTATE_EXPR, type, arg0, tem));
@@ -7333,7 +8017,7 @@ fold (tree expr)
       /* The argument to invert_truthvalue must have Boolean type.  */
       if (TREE_CODE (TREE_TYPE (arg0)) != BOOLEAN_TYPE)
           arg0 = fold_convert (boolean_type_node, arg0);
-      
+
       /* Note that the operand of this must be an int
         and its values must be 0 or 1.
         ("true" is a fixed value perhaps depending on the language,
@@ -7373,6 +8057,31 @@ fold (tree expr)
       if (integer_zerop (arg0))
        return omit_one_operand (type, arg0, arg1);
 
+      /* !X && X is always false.  */
+      if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
+         && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+       return omit_one_operand (type, integer_zero_node, arg1);
+      /* X && !X is always false.  */
+      if (TREE_CODE (arg1) == TRUTH_NOT_EXPR
+         && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+       return omit_one_operand (type, integer_zero_node, arg0);
+
+      /* A < X && A + 1 > Y ==> A < X && A >= Y.  Normally A + 1 > Y
+        means A >= Y && A != MAX, but in this case we know that
+        A < X <= MAX.  */
+
+      if (!TREE_SIDE_EFFECTS (arg0)
+         && !TREE_SIDE_EFFECTS (arg1))
+       {
+         tem = fold_to_nonsharp_ineq_using_bound (arg0, arg1);
+         if (tem)
+           return fold (build2 (code, type, tem, arg1));
+
+         tem = fold_to_nonsharp_ineq_using_bound (arg1, arg0);
+         if (tem)
+           return fold (build2 (code, type, arg0, tem));
+       }
+
     truth_andor:
       /* We only do these simplifications if we are optimizing.  */
       if (!optimize)
@@ -7460,22 +8169,39 @@ fold (tree expr)
         TRUTH_OR_EXPR.  */
       if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0))
        return omit_one_operand (type, arg0, arg1);
+
+      /* !X || X is always true.  */
+      if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
+         && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+       return omit_one_operand (type, integer_one_node, arg1);
+      /* X || !X is always true.  */
+      if (TREE_CODE (arg1) == TRUTH_NOT_EXPR
+         && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+       return omit_one_operand (type, integer_one_node, arg0);
+
       goto truth_andor;
 
     case TRUTH_XOR_EXPR:
-      /* If either arg is constant zero, drop it.  */
-      if (integer_zerop (arg0))
-       return non_lvalue (fold_convert (type, arg1));
+      /* If the second arg is constant zero, drop it.  */
       if (integer_zerop (arg1))
        return non_lvalue (fold_convert (type, arg0));
-      /* If either arg is constant true, this is a logical inversion.  */
-      if (integer_onep (arg0))
-       return non_lvalue (fold_convert (type, invert_truthvalue (arg1)));
+      /* If the second arg is constant true, this is a logical inversion.  */
       if (integer_onep (arg1))
        return non_lvalue (fold_convert (type, invert_truthvalue (arg0)));
       /* Identical arguments cancel to zero.  */
       if (operand_equal_p (arg0, arg1, 0))
        return omit_one_operand (type, integer_zero_node, arg0);
+
+      /* !X ^ X is always true.  */
+      if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
+         && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+       return omit_one_operand (type, integer_one_node, arg1);
+
+      /* X ^ !X is always true.  */
+      if (TREE_CODE (arg1) == TRUTH_NOT_EXPR
+         && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+       return omit_one_operand (type, integer_one_node, arg0);
+
       return t;
 
     case EQ_EXPR:
@@ -7652,24 +8378,26 @@ fold (tree expr)
          /* 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)))
+             && 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);
-             int size = TREE_INT_CST_LOW (DECL_SIZE (fielddecl));
+             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));
+                                            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_2 (TYPE_PRECISION (TREE_TYPE (varop)) - size,
-                                  0);
+             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),
@@ -7702,11 +8430,10 @@ fold (tree expr)
        }
 
       /* Comparisons with the highest or lowest possible integer of
-        the specified size will have known values. 
+        the specified size will have known values.
 
-        This is quite similar to fold_relational_hi_lo; however, my
-        attempts to share the code have been nothing but trouble.
-        I give up for now.  */
+        This is quite similar to fold_relational_hi_lo, however,
+        attempts to share the code have been nothing but trouble.  */
       {
        int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg1)));
 
@@ -7853,21 +8580,21 @@ fold (tree expr)
        return fold (build2 (code, type,
                             TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1)));
 
-      /* 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.  */
       else if (TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE
-              && TREE_CODE (arg0) == NOP_EXPR
-              && (tem = get_unwidened (arg0, NULL_TREE)) != arg0
-              && (code == EQ_EXPR || code == NE_EXPR
-                  || TYPE_UNSIGNED (TREE_TYPE (arg0))
-                     == TYPE_UNSIGNED (TREE_TYPE (tem)))
-              && (t1 = get_unwidened (arg1, TREE_TYPE (tem))) != 0
-              && (TREE_TYPE (t1) == TREE_TYPE (tem)
-                  || (TREE_CODE (t1) == INTEGER_CST
-                      && int_fits_type_p (t1, TREE_TYPE (tem)))))
-       return fold (build2 (code, type, tem,
-                            fold_convert (TREE_TYPE (tem), t1)));
+              && TREE_CODE (arg0) == NOP_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.  */
@@ -7939,13 +8666,14 @@ fold (tree expr)
          && integer_pow2p (TREE_OPERAND (arg0, 1)))
        {
          tree newtype = lang_hooks.types.unsigned_type (TREE_TYPE (arg0));
-         tree newmod = build2 (TREE_CODE (arg0), newtype,
-                               fold_convert (newtype,
-                                             TREE_OPERAND (arg0, 0)),
-                               fold_convert (newtype,
-                                             TREE_OPERAND (arg0, 1)));
+         tree newmod = fold (build2 (TREE_CODE (arg0), newtype,
+                                     fold_convert (newtype,
+                                                   TREE_OPERAND (arg0, 0)),
+                                     fold_convert (newtype,
+                                                   TREE_OPERAND (arg0, 1))));
 
-         return build2 (code, type, newmod, fold_convert (newtype, arg1));
+         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
@@ -7962,7 +8690,8 @@ fold (tree 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, integer_zero_node));
+                            arg0, fold_convert (TREE_TYPE (arg0),
+                                                integer_zero_node)));
 
       /* If we have (A & C) != 0 or (A & C) == 0 and C is a power of
         2, then fold the expression into shifts and logical operations.  */
@@ -7977,11 +8706,11 @@ fold (tree expr)
          && TREE_CODE (arg1) == INTEGER_CST
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
        {
-         tree dandnotc
-           = fold (build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
-                           arg1, build1 (BIT_NOT_EXPR,
-                                         TREE_TYPE (TREE_OPERAND (arg0, 1)),
-                                         TREE_OPERAND (arg0, 1))));
+         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);
@@ -7994,10 +8723,9 @@ fold (tree expr)
          && TREE_CODE (arg1) == INTEGER_CST
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
        {
-         tree candnotd
-           = fold (build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
-                           TREE_OPERAND (arg0, 1),
-                           build1 (BIT_NOT_EXPR, TREE_TYPE (arg1), arg1)));
+         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);
@@ -8058,7 +8786,7 @@ fold (tree expr)
            case LT_EXPR:
              return constant_boolean_node (0, type);
            default:
-             abort ();
+             gcc_unreachable ();
            }
        }
 
@@ -8230,8 +8958,9 @@ fold (tree expr)
              && ! TREE_CHAIN (arglist))
            return fold (build2 (code, type,
                                 build1 (INDIRECT_REF, char_type_node,
-                                        TREE_VALUE(arglist)),
-                                integer_zero_node));
+                                        TREE_VALUE (arglist)),
+                                fold_convert (char_type_node,
+                                              integer_zero_node)));
        }
 
       /* We can fold X/C1 op C2 where C1 and C2 are integer constants
@@ -8248,9 +8977,14 @@ fold (tree expr)
            return t1;
        }
 
-      /* Both ARG0 and ARG1 are known to be constants at this point.  */
+      if ((code == EQ_EXPR || code == NE_EXPR)
+         && !TREE_SIDE_EFFECTS (arg0)
+         && integer_zerop (arg1)
+         && tree_expr_nonzero_p (arg0))
+       return constant_boolean_node (code==NE_EXPR, type);
+
       t1 = fold_relational_const (code, type, arg0, arg1);
-      return (t1 == NULL_TREE ? t : t1);
+      return t1 == NULL_TREE ? t : t1;
 
     case UNORDERED_EXPR:
     case ORDERED_EXPR:
@@ -8289,6 +9023,16 @@ fold (tree expr)
          return omit_one_operand (type, t1, arg0);
        }
 
+      /* Simplify unordered comparison of something with itself.  */
+      if ((code == UNLE_EXPR || code == UNGE_EXPR || code == UNEQ_EXPR)
+         && operand_equal_p (arg0, arg1, 0))
+       return constant_boolean_node (1, type);
+
+      if (code == LTGT_EXPR
+         && !flag_trapping_math
+         && operand_equal_p (arg0, arg1, 0))
+       return constant_boolean_node (0, type);
+
       /* Fold (double)float1 CMP (double)float2 into float1 CMP float2.  */
       {
        tree targ0 = strip_float_extensions (arg0);
@@ -8325,227 +9069,36 @@ fold (tree expr)
       /* If we have A op B ? A : C, we may be able to convert this to a
         simpler expression, depending on the operation and the values
         of B and C.  Signed zeros prevent all of these transformations,
-        for reasons given above each one.  */
+        for reasons given above each one.
 
-      if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
+         Also try swapping the arguments and inverting the conditional.  */
+      if (COMPARISON_CLASS_P (arg0)
          && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
                                             arg1, TREE_OPERAND (arg0, 1))
          && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
        {
-         tree arg2 = TREE_OPERAND (t, 2);
-         enum tree_code comp_code = TREE_CODE (arg0);
-
-         STRIP_NOPS (arg2);
-
-         /* If we have A op 0 ? A : -A, consider applying the following
-            transformations:
-
-            A == 0? A : -A    same as -A
-            A != 0? A : -A    same as A
-            A >= 0? A : -A    same as abs (A)
-            A > 0?  A : -A    same as abs (A)
-            A <= 0? A : -A    same as -abs (A)
-            A < 0?  A : -A    same as -abs (A)
-
-            None of these transformations work for modes with signed
-            zeros.  If A is +/-0, the first two transformations will
-            change the sign of the result (from +0 to -0, or vice
-            versa).  The last four will fix the sign of the result,
-            even though the original expressions could be positive or
-            negative, depending on the sign of A.
-
-            Note that all these transformations are correct if A is
-            NaN, since the two alternatives (A and -A) are also NaNs.  */
-         if ((FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (arg0, 1)))
-              ? real_zerop (TREE_OPERAND (arg0, 1))
-              : integer_zerop (TREE_OPERAND (arg0, 1)))
-             && TREE_CODE (arg2) == NEGATE_EXPR
-             && operand_equal_p (TREE_OPERAND (arg2, 0), arg1, 0))
-           switch (comp_code)
-             {
-             case EQ_EXPR:
-               tem = fold_convert (TREE_TYPE (TREE_OPERAND (t, 1)), arg1);
-               tem = fold_convert (type, negate_expr (tem));
-               return pedantic_non_lvalue (tem);
-             case NE_EXPR:
-               return pedantic_non_lvalue (fold_convert (type, arg1));
-             case GE_EXPR:
-             case GT_EXPR:
-               if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
-                 arg1 = fold_convert (lang_hooks.types.signed_type
-                                      (TREE_TYPE (arg1)), arg1);
-               arg1 = fold (build1 (ABS_EXPR, TREE_TYPE (arg1), arg1));
-               return pedantic_non_lvalue (fold_convert (type, arg1));
-             case LE_EXPR:
-             case LT_EXPR:
-               if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
-                 arg1 = fold_convert (lang_hooks.types.signed_type
-                                      (TREE_TYPE (arg1)), arg1);
-               arg1 = fold (build1 (ABS_EXPR, TREE_TYPE (arg1), arg1));
-               arg1 = negate_expr (fold_convert (type, arg1));
-               return pedantic_non_lvalue (arg1);
-             default:
-               abort ();
-             }
-
-         /* A != 0 ? A : 0 is simply A, unless A is -0.  Likewise
-            A == 0 ? A : 0 is always 0 unless A is -0.  Note that
-            both transformations are correct when A is NaN: A != 0
-            is then true, and A == 0 is false.  */
+         tem = fold_cond_expr_with_comparison (type, arg0,
+                                               TREE_OPERAND (t, 1),
+                                               TREE_OPERAND (t, 2));
+         if (tem)
+           return tem;
+       }
 
-         if (integer_zerop (TREE_OPERAND (arg0, 1)) && integer_zerop (arg2))
-           {
-             if (comp_code == NE_EXPR)
-               return pedantic_non_lvalue (fold_convert (type, arg1));
-             else if (comp_code == EQ_EXPR)
-               return pedantic_non_lvalue (fold_convert (type, integer_zero_node));
-           }
-
-         /* Try some transformations of A op B ? A : B.
-
-            A == B? A : B    same as B
-            A != B? A : B    same as A
-            A >= B? A : B    same as max (A, B)
-            A > B?  A : B    same as max (B, A)
-            A <= B? A : B    same as min (A, B)
-            A < B?  A : B    same as min (B, A)
-
-            As above, these transformations don't work in the presence
-            of signed zeros.  For example, if A and B are zeros of
-            opposite sign, the first two transformations will change
-            the sign of the result.  In the last four, the original
-            expressions give different results for (A=+0, B=-0) and
-            (A=-0, B=+0), but the transformed expressions do not.
-
-            The first two transformations are correct if either A or B
-            is a NaN.  In the first transformation, the condition will
-            be false, and B will indeed be chosen.  In the case of the
-            second transformation, the condition A != B will be true,
-            and A will be chosen.
-
-            The conversions to max() and min() are not correct if B is
-            a number and A is not.  The conditions in the original
-            expressions will be false, so all four give B.  The min()
-            and max() versions would give a NaN instead.  */
-         if (operand_equal_for_comparison_p (TREE_OPERAND (arg0, 1),
-                                             arg2, TREE_OPERAND (arg0, 0)))
+      if (COMPARISON_CLASS_P (arg0)
+         && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
+                                            TREE_OPERAND (t, 2),
+                                            TREE_OPERAND (arg0, 1))
+         && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 2)))))
+       {
+         tem = invert_truthvalue (arg0);
+         if (COMPARISON_CLASS_P (tem))
            {
-             tree comp_op0 = TREE_OPERAND (arg0, 0);
-             tree comp_op1 = TREE_OPERAND (arg0, 1);
-             tree comp_type = TREE_TYPE (comp_op0);
-
-             /* Avoid adding NOP_EXPRs in case this is an lvalue.  */
-             if (TYPE_MAIN_VARIANT (comp_type) == TYPE_MAIN_VARIANT (type))
-               {
-                 comp_type = type;
-                 comp_op0 = arg1;
-                 comp_op1 = arg2;
-               }
-
-             switch (comp_code)
-               {
-               case EQ_EXPR:
-                 return pedantic_non_lvalue (fold_convert (type, arg2));
-               case NE_EXPR:
-                 return pedantic_non_lvalue (fold_convert (type, arg1));
-               case LE_EXPR:
-               case LT_EXPR:
-                 /* In C++ a ?: expression can be an lvalue, so put the
-                    operand which will be used if they are equal first
-                    so that we can convert this back to the
-                    corresponding COND_EXPR.  */
-                 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
-                   return pedantic_non_lvalue (fold_convert
-                     (type, fold (build2 (MIN_EXPR, comp_type,
-                                          (comp_code == LE_EXPR
-                                           ? comp_op0 : comp_op1),
-                                          (comp_code == LE_EXPR
-                                           ? comp_op1 : comp_op0)))));
-                 break;
-               case GE_EXPR:
-               case GT_EXPR:
-                 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
-                   return pedantic_non_lvalue (fold_convert
-                     (type, fold (build2 (MAX_EXPR, comp_type,
-                                          (comp_code == GE_EXPR
-                                           ? comp_op0 : comp_op1),
-                                          (comp_code == GE_EXPR
-                                           ? comp_op1 : comp_op0)))));
-                 break;
-               default:
-                 abort ();
-               }
+             tem = fold_cond_expr_with_comparison (type, tem,
+                                                   TREE_OPERAND (t, 2),
+                                                   TREE_OPERAND (t, 1));
+             if (tem)
+               return tem;
            }
-
-         /* If this is A op C1 ? A : C2 with C1 and C2 constant integers,
-            we might still be able to simplify this.  For example,
-            if C1 is one less or one more than C2, this might have started
-            out as a MIN or MAX and been transformed by this function.
-            Only good for INTEGER_TYPEs, because we need TYPE_MAX_VALUE.  */
-
-         if (INTEGRAL_TYPE_P (type)
-             && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
-             && TREE_CODE (arg2) == INTEGER_CST)
-           switch (comp_code)
-             {
-             case EQ_EXPR:
-               /* We can replace A with C1 in this case.  */
-               arg1 = fold_convert (type, TREE_OPERAND (arg0, 1));
-               return fold (build3 (code, type, TREE_OPERAND (t, 0), arg1,
-                                    TREE_OPERAND (t, 2)));
-
-             case LT_EXPR:
-               /* If C1 is C2 + 1, this is min(A, C2).  */
-               if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type),
-                                      OEP_ONLY_CONST)
-                   && operand_equal_p (TREE_OPERAND (arg0, 1),
-                                       const_binop (PLUS_EXPR, arg2,
-                                                    integer_one_node, 0),
-                                       OEP_ONLY_CONST))
-                 return pedantic_non_lvalue
-                   (fold (build2 (MIN_EXPR, type, arg1, arg2)));
-               break;
-
-             case LE_EXPR:
-               /* If C1 is C2 - 1, this is min(A, C2).  */
-               if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type),
-                                      OEP_ONLY_CONST)
-                   && operand_equal_p (TREE_OPERAND (arg0, 1),
-                                       const_binop (MINUS_EXPR, arg2,
-                                                    integer_one_node, 0),
-                                       OEP_ONLY_CONST))
-                 return pedantic_non_lvalue
-                   (fold (build2 (MIN_EXPR, type, arg1, arg2)));
-               break;
-
-             case GT_EXPR:
-               /* If C1 is C2 - 1, this is max(A, C2).  */
-               if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type),
-                                      OEP_ONLY_CONST)
-                   && operand_equal_p (TREE_OPERAND (arg0, 1),
-                                       const_binop (MINUS_EXPR, arg2,
-                                                    integer_one_node, 0),
-                                       OEP_ONLY_CONST))
-                 return pedantic_non_lvalue
-                   (fold (build2 (MAX_EXPR, type, arg1, arg2)));
-               break;
-
-             case GE_EXPR:
-               /* If C1 is C2 + 1, this is max(A, C2).  */
-               if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type),
-                                      OEP_ONLY_CONST)
-                   && operand_equal_p (TREE_OPERAND (arg0, 1),
-                                       const_binop (PLUS_EXPR, arg2,
-                                                    integer_one_node, 0),
-                                       OEP_ONLY_CONST))
-                 return pedantic_non_lvalue
-                   (fold (build2 (MAX_EXPR, type, arg1, arg2)));
-               break;
-             case NE_EXPR:
-               break;
-             default:
-               abort ();
-             }
        }
 
       /* If the second operand is simpler than the third, swap them
@@ -8581,9 +9134,35 @@ fold (tree expr)
        return pedantic_non_lvalue (fold_convert (type,
                                                  invert_truthvalue (arg0)));
 
-      /* Look for expressions of the form A & 2 ? 2 : 0.  The result of this
-        operation is simply A & 2.  */
+      /* A < 0 ? <sign bit of A> : 0 is simply (A & <sign bit of A>).  */
+      if (TREE_CODE (arg0) == LT_EXPR
+          && integer_zerop (TREE_OPERAND (arg0, 1))
+          && integer_zerop (TREE_OPERAND (t, 2))
+          && (tem = sign_bit_p (TREE_OPERAND (arg0, 0), arg1)))
+        return fold_convert (type, fold (build2 (BIT_AND_EXPR,
+                                                TREE_TYPE (tem), tem, arg1)));
 
+      /* (A >> N) & 1 ? (1 << N) : 0 is simply A & (1 << N).  A & 1 was
+        already handled above.  */
+      if (TREE_CODE (arg0) == BIT_AND_EXPR
+         && integer_onep (TREE_OPERAND (arg0, 1))
+         && integer_zerop (TREE_OPERAND (t, 2))
+         && integer_pow2p (arg1))
+       {
+         tree tem = TREE_OPERAND (arg0, 0);
+         STRIP_NOPS (tem);
+         if (TREE_CODE (tem) == RSHIFT_EXPR
+              && TREE_CODE (TREE_OPERAND (tem, 1)) == INTEGER_CST
+              && (unsigned HOST_WIDE_INT) tree_log2 (arg1) ==
+                TREE_INT_CST_LOW (TREE_OPERAND (tem, 1)))
+           return fold (build2 (BIT_AND_EXPR, type,
+                                TREE_OPERAND (tem, 0), arg1));
+       }
+
+      /* A & N ? N : 0 is simply A & N if N is a power of two.  This
+        is probably obsolete because the first operand should be a
+        truth value (that's why we have the two cases above), but let's
+        leave it in until we can confirm this for all front-ends.  */
       if (integer_zerop (TREE_OPERAND (t, 2))
          && TREE_CODE (arg0) == NE_EXPR
          && integer_zerop (TREE_OPERAND (arg0, 1))
@@ -8598,8 +9177,7 @@ fold (tree expr)
       if (integer_zerop (TREE_OPERAND (t, 2))
          && truth_value_p (TREE_CODE (arg0))
          && truth_value_p (TREE_CODE (arg1)))
-       return pedantic_non_lvalue (fold (build2 (TRUTH_ANDIF_EXPR, type,
-                                                 arg0, arg1)));
+       return fold (build2 (TRUTH_ANDIF_EXPR, type, arg0, arg1));
 
       /* Convert A ? B : 1 into !A || B if A and B are truth values.  */
       if (integer_onep (TREE_OPERAND (t, 2))
@@ -8609,10 +9187,28 @@ fold (tree expr)
          /* Only perform transformation if ARG0 is easily inverted.  */
          tem = invert_truthvalue (arg0);
          if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
-           return pedantic_non_lvalue (fold (build2 (TRUTH_ORIF_EXPR, type,
-                                                     tem, arg1)));
+           return fold (build2 (TRUTH_ORIF_EXPR, type, tem, arg1));
        }
 
+      /* Convert A ? 0 : B into !A && B if A and B are truth values.  */
+      if (integer_zerop (arg1)
+         && truth_value_p (TREE_CODE (arg0))
+         && truth_value_p (TREE_CODE (TREE_OPERAND (t, 2))))
+       {
+         /* Only perform transformation if ARG0 is easily inverted.  */
+         tem = invert_truthvalue (arg0);
+         if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
+           return fold (build2 (TRUTH_ANDIF_EXPR, type, tem,
+                                TREE_OPERAND (t, 2)));
+       }
+
+      /* Convert A ? 1 : B into A || B if A and B are truth values.  */
+      if (integer_onep (arg1)
+         && truth_value_p (TREE_CODE (arg0))
+         && truth_value_p (TREE_CODE (TREE_OPERAND (t, 2))))
+       return fold (build2 (TRUTH_ORIF_EXPR, type, arg0,
+                            TREE_OPERAND (t, 2)));
+
       return t;
 
     case COMPOUND_EXPR:
@@ -8662,47 +9258,6 @@ fold (tree expr)
                                           TREE_OPERAND (arg0, 1)))));
       return t;
 
-      /* Pull arithmetic ops out of the CLEANUP_POINT_EXPR where
-         appropriate.  */
-    case CLEANUP_POINT_EXPR:
-      if (! has_cleanups (arg0))
-       return TREE_OPERAND (t, 0);
-
-      {
-       enum tree_code code0 = TREE_CODE (arg0);
-       int kind0 = TREE_CODE_CLASS (code0);
-       tree arg00 = TREE_OPERAND (arg0, 0);
-       tree arg01;
-
-       if (kind0 == '1' || code0 == TRUTH_NOT_EXPR)
-         return fold (build1 (code0, type,
-                              fold (build1 (CLEANUP_POINT_EXPR,
-                                            TREE_TYPE (arg00), arg00))));
-
-       if (kind0 == '<' || kind0 == '2'
-           || code0 == TRUTH_ANDIF_EXPR || code0 == TRUTH_ORIF_EXPR
-           || code0 == TRUTH_AND_EXPR   || code0 == TRUTH_OR_EXPR
-           || code0 == TRUTH_XOR_EXPR)
-         {
-           arg01 = TREE_OPERAND (arg0, 1);
-
-           if (TREE_CONSTANT (arg00)
-               || ((code0 == TRUTH_ANDIF_EXPR || code0 == TRUTH_ORIF_EXPR)
-                   && ! has_cleanups (arg00)))
-             return fold (build2 (code0, type, arg00,
-                                  fold (build1 (CLEANUP_POINT_EXPR,
-                                                TREE_TYPE (arg01), arg01))));
-
-           if (TREE_CONSTANT (arg01))
-             return fold (build2 (code0, type,
-                                  fold (build1 (CLEANUP_POINT_EXPR,
-                                                TREE_TYPE (arg00), arg00)),
-                                  arg01));
-         }
-
-       return t;
-      }
-
     case CALL_EXPR:
       /* Check for a built-in function.  */
       if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
@@ -8710,7 +9265,7 @@ fold (tree expr)
              == FUNCTION_DECL)
          && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
        {
-         tree tmp = fold_builtin (t);
+         tree tmp = fold_builtin (t, false);
          if (tmp)
            return tmp;
        }
@@ -8790,10 +9345,9 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
   char buf[sizeof (struct tree_decl)];
   int i, len;
 
-  if (sizeof (struct tree_exp) + 5 * sizeof (tree)
-      > sizeof (struct tree_decl)
-      || sizeof (struct tree_type) > sizeof (struct tree_decl))
-    abort ();
+  gcc_assert ((sizeof (struct tree_exp) + 5 * sizeof (tree)
+              <= sizeof (struct tree_decl))
+             && sizeof (struct tree_type) <= sizeof (struct tree_decl));
   if (expr == NULL)
     return;
   slot = htab_find_slot (ht, expr, INSERT);
@@ -8801,37 +9355,34 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
     return;
   *slot = expr;
   code = TREE_CODE (expr);
-  if (code == SAVE_EXPR && SAVE_EXPR_NOPLACEHOLDER (expr))
-    {
-      /* Allow SAVE_EXPR_NOPLACEHOLDER flag to be modified.  */
-      memcpy (buf, expr, tree_size (expr));
-      expr = (tree) buf;
-      SAVE_EXPR_NOPLACEHOLDER (expr) = 0;
-    }
-  else if (TREE_CODE_CLASS (code) == 'd' && DECL_ASSEMBLER_NAME_SET_P (expr))
+  if (TREE_CODE_CLASS (code) == tcc_declaration
+      && DECL_ASSEMBLER_NAME_SET_P (expr))
     {
       /* Allow DECL_ASSEMBLER_NAME to be modified.  */
       memcpy (buf, expr, tree_size (expr));
       expr = (tree) buf;
       SET_DECL_ASSEMBLER_NAME (expr, NULL);
     }
-  else if (TREE_CODE_CLASS (code) == 't'
-          && (TYPE_POINTER_TO (expr) || TYPE_REFERENCE_TO (expr)))
+  else if (TREE_CODE_CLASS (code) == tcc_type
+          && (TYPE_POINTER_TO (expr) || TYPE_REFERENCE_TO (expr)
+              || TYPE_CACHED_VALUES_P (expr)))
     {
-      /* Allow TYPE_POINTER_TO and TYPE_REFERENCE_TO to be modified.  */
+      /* Allow these fields to be modified.  */
       memcpy (buf, expr, tree_size (expr));
       expr = (tree) buf;
       TYPE_POINTER_TO (expr) = NULL;
       TYPE_REFERENCE_TO (expr) = NULL;
+      TYPE_CACHED_VALUES_P (expr) = 0;
+      TYPE_CACHED_VALUES (expr) = NULL;
     }
   md5_process_bytes (expr, tree_size (expr), ctx);
   fold_checksum_tree (TREE_TYPE (expr), ctx, ht);
-  if (TREE_CODE_CLASS (code) != 't' && TREE_CODE_CLASS (code) != 'd')
+  if (TREE_CODE_CLASS (code) != tcc_type
+      && TREE_CODE_CLASS (code) != tcc_declaration)
     fold_checksum_tree (TREE_CHAIN (expr), ctx, ht);
-  len = TREE_CODE_LENGTH (code);
   switch (TREE_CODE_CLASS (code))
     {
-    case 'c':
+    case tcc_constant:
       switch (code)
        {
        case STRING_CST:
@@ -8849,7 +9400,7 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
          break;
        }
       break;
-    case 'x':
+    case tcc_exceptional:
       switch (code)
        {
        case TREE_LIST:
@@ -8864,25 +9415,17 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
          break;
        }
       break;
-    case 'e':
-      switch (code)
-       {
-       case SAVE_EXPR: len = 2; break;
-       case GOTO_SUBROUTINE_EXPR: len = 0; break;
-       case RTL_EXPR: len = 0; break;
-       case WITH_CLEANUP_EXPR: len = 2; break;
-       default: break;
-       }
-      /* Fall through.  */
-    case 'r':
-    case '<':
-    case '1':
-    case '2':
-    case 's':
+    case tcc_expression:
+    case tcc_reference:
+    case tcc_comparison:
+    case tcc_unary:
+    case tcc_binary:
+    case tcc_statement:
+      len = TREE_CODE_LENGTH (code);
       for (i = 0; i < len; ++i)
        fold_checksum_tree (TREE_OPERAND (expr, i), ctx, ht);
       break;
-    case 'd':
+    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);
@@ -8895,7 +9438,7 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
       fold_checksum_tree (DECL_ATTRIBUTES (expr), ctx, ht);
       fold_checksum_tree (DECL_VINDEX (expr), ctx, ht);
       break;
-    case 't':
+    case tcc_type:
       if (TREE_CODE (expr) == ENUMERAL_TYPE)
         fold_checksum_tree (TYPE_VALUES (expr), ctx, ht);
       fold_checksum_tree (TYPE_SIZE (expr), ctx, ht);
@@ -8909,7 +9452,10 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
          fold_checksum_tree (TYPE_MAX_VALUE (expr), ctx, ht);
        }
       fold_checksum_tree (TYPE_MAIN_VARIANT (expr), ctx, ht);
-      fold_checksum_tree (TYPE_BINFO (expr), ctx, ht);
+      if (TREE_CODE (expr) == RECORD_TYPE
+         || TREE_CODE (expr) == UNION_TYPE
+         || TREE_CODE (expr) == QUAL_UNION_TYPE)
+       fold_checksum_tree (TYPE_BINFO (expr), ctx, ht);
       fold_checksum_tree (TYPE_CONTEXT (expr), ctx, ht);
       break;
     default:
@@ -9187,8 +9733,37 @@ tree_expr_nonnegative_p (tree t)
       return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
     case FLOAT_EXPR:
       return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
-    case RTL_EXPR:
-      return rtl_expr_nonnegative_p (RTL_EXPR_RTL (t));
+
+    case TARGET_EXPR:
+      {
+       tree temp = TARGET_EXPR_SLOT (t);
+       t = TARGET_EXPR_INITIAL (t);
+
+       /* If the initializer is non-void, then it's a normal expression
+          that will be assigned to the slot.  */
+       if (!VOID_TYPE_P (t))
+         return tree_expr_nonnegative_p (t);
+
+       /* Otherwise, the initializer sets the slot in some way.  One common
+          way is an assignment statement at the end of the initializer.  */
+       while (1)
+         {
+           if (TREE_CODE (t) == BIND_EXPR)
+             t = expr_last (BIND_EXPR_BODY (t));
+           else if (TREE_CODE (t) == TRY_FINALLY_EXPR
+                    || TREE_CODE (t) == TRY_CATCH_EXPR)
+             t = expr_last (TREE_OPERAND (t, 0));
+           else if (TREE_CODE (t) == STATEMENT_LIST)
+             t = expr_last (t);
+           else
+             break;
+         }
+       if (TREE_CODE (t) == MODIFY_EXPR
+           && TREE_OPERAND (t, 0) == temp)
+         return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+
+       return 0;
+      }
 
     case CALL_EXPR:
       {
@@ -9290,7 +9865,7 @@ tree_expr_nonnegative_p (tree t)
 
 /* Return true when T is an address and is known to be nonzero.
    For floating point we further ensure that T is not denormal.
-   Similar logic is present in nonzero_address in rtlanal.h  */
+   Similar logic is present in nonzero_address in rtlanal.h.  */
 
 static bool
 tree_expr_nonzero_p (tree t)
@@ -9308,7 +9883,10 @@ tree_expr_nonzero_p (tree t)
        return tree_expr_nonzero_p (TREE_OPERAND (t, 0));
 
     case INTEGER_CST:
-      return !integer_zerop (t);
+      /* We used to test for !integer_zerop here.  This does not work correctly
+        if TREE_CONSTANT_OVERFLOW (t).  */
+      return (TREE_INT_CST_LOW (t) != 0
+             || TREE_INT_CST_HIGH (t) != 0);
 
     case PLUS_EXPR:
       if (!TYPE_UNSIGNED (type) && !flag_wrapv)
@@ -9343,11 +9921,22 @@ tree_expr_nonzero_p (tree t)
       break;
 
    case ADDR_EXPR:
-      /* Weak declarations may link to NULL.  */
-      if (DECL_P (TREE_OPERAND (t, 0)))
-       return !DECL_WEAK (TREE_OPERAND (t, 0));
-      /* Constants and all other cases are never weak.  */
-      return true;
+      {
+       tree base = get_base_address (TREE_OPERAND (t, 0));
+
+       if (!base)
+         return false;
+
+       /* Weak declarations may link to NULL.  */
+       if (DECL_P (base))
+         return !DECL_WEAK (base);
+
+       /* Constants are never weak.  */
+       if (CONSTANT_CLASS_P (base))
+         return true;
+
+       return false;
+      }
 
     case COND_EXPR:
       return (tree_expr_nonzero_p (TREE_OPERAND (t, 1))
@@ -9392,50 +9981,6 @@ tree_expr_nonzero_p (tree t)
   return false;
 }
 
-/* Return true if `r' is known to be non-negative.
-   Only handles constants at the moment.  */
-
-int
-rtl_expr_nonnegative_p (rtx r)
-{
-  switch (GET_CODE (r))
-    {
-    case CONST_INT:
-      return INTVAL (r) >= 0;
-
-    case CONST_DOUBLE:
-      if (GET_MODE (r) == VOIDmode)
-       return CONST_DOUBLE_HIGH (r) >= 0;
-      return 0;
-
-    case CONST_VECTOR:
-      {
-       int units, i;
-       rtx elt;
-
-       units = CONST_VECTOR_NUNITS (r);
-
-       for (i = 0; i < units; ++i)
-         {
-           elt = CONST_VECTOR_ELT (r, i);
-           if (!rtl_expr_nonnegative_p (elt))
-             return 0;
-         }
-
-       return 1;
-      }
-
-    case SYMBOL_REF:
-    case LABEL_REF:
-      /* These are always nonnegative.  */
-      return 1;
-
-    default:
-      return 0;
-    }
-}
-
-
 /* See if we are applying CODE, a relational to the highest or lowest
    possible integer of TYPE.  If so, then the result is a compile
    time constant.  */
@@ -9565,11 +10110,10 @@ fold_relational_hi_lo (enum tree_code *code_p, const tree type, tree *op0_p,
                            fold_convert (st0, op0),
                            fold_convert (st1, integer_zero_node));
 
-             retval
-               = nondestructive_fold_binary_to_constant (TREE_CODE (exp),
-                                                         TREE_TYPE (exp),
-                                                         TREE_OPERAND (exp, 0),
-                                                         TREE_OPERAND (exp, 1));
+             retval = fold_binary_to_constant (TREE_CODE (exp),
+                                               TREE_TYPE (exp),
+                                               TREE_OPERAND (exp, 0),
+                                               TREE_OPERAND (exp, 1));
 
              /* If we are in gimple form, then returning EXP would create
                 non-gimple expressions.  Clearing it is safe and insures
@@ -9600,8 +10144,7 @@ fold_relational_hi_lo (enum tree_code *code_p, const tree type, tree *op0_p,
    simpler than the generic fold routine.  */
 
 tree
-nondestructive_fold_binary_to_constant (enum tree_code code, tree type,
-                                       tree op0, tree op1)
+fold_binary_to_constant (enum tree_code code, tree type, tree op0, tree op1)
 {
   int wins = 1;
   tree subop0;
@@ -9672,7 +10215,7 @@ nondestructive_fold_binary_to_constant (enum tree_code code, tree type,
          return tem;
        }
       return NULL_TREE;
-      
+
     case MINUS_EXPR:
       /* Fold &x - &x.  This can happen from &x.foo - &x.
          This is unsafe for certain floats even in non-IEEE formats.
@@ -9704,7 +10247,7 @@ nondestructive_fold_binary_to_constant (enum tree_code code, tree type,
        return omit_one_operand (type, op1, op0);
 
       goto binary;
-       
+
     case TRUNC_DIV_EXPR:
     case ROUND_DIV_EXPR:
     case FLOOR_DIV_EXPR:
@@ -9883,7 +10426,7 @@ nondestructive_fold_binary_to_constant (enum tree_code code, tree type,
 
 /* Given the components of a unary expression CODE, TYPE and OP0,
    attempt to fold the expression to a constant without modifying
-   TYPE or OP0. 
+   TYPE or OP0.
 
    If the expression could be simplified to a constant, then return
    the constant.  If the expression would not be simplified to a
@@ -9895,8 +10438,7 @@ nondestructive_fold_binary_to_constant (enum tree_code code, tree type,
    the generic fold routine.  */
 
 tree
-nondestructive_fold_unary_to_constant (enum tree_code code, tree type,
-                                      tree op0)
+fold_unary_to_constant (enum tree_code code, tree type, tree op0)
 {
   /* Make sure we have a suitable constant argument.  */
   if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR)
@@ -9978,15 +10520,12 @@ fold_read_from_constant_string (tree exp)
       tree string;
 
       if (TREE_CODE (exp) == INDIRECT_REF)
-       {
-         string = string_constant (exp1, &index);
-       }
+       string = string_constant (exp1, &index);
       else
        {
-         tree domain = TYPE_DOMAIN (TREE_TYPE (exp1));
-         tree low_bound = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node;
+         tree low_bound = array_ref_low_bound (exp);
          index = fold_convert (sizetype, TREE_OPERAND (exp, 1));
-         
+
          /* Optimize the special-case of a zero lower bound.
 
             We convert the low_bound to sizetype to avoid some problems
@@ -10001,6 +10540,7 @@ fold_read_from_constant_string (tree exp)
        }
 
       if (string
+         && TREE_TYPE (exp) == TREE_TYPE (TREE_TYPE (string))
          && TREE_CODE (string) == STRING_CST
          && TREE_CODE (index) == INTEGER_CST
          && compare_tree_int (index, TREE_STRING_LENGTH (string)) < 0
@@ -10008,8 +10548,9 @@ fold_read_from_constant_string (tree exp)
              == MODE_INT)
          && (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (string)))) == 1))
        return fold_convert (TREE_TYPE (exp),
-                            build_int_2 ((TREE_STRING_POINTER (string)
-                                         [TREE_INT_CST_LOW (index)]), 0));
+                            build_int_cst (NULL_TREE,
+                                           (TREE_STRING_POINTER (string)
+                                            [TREE_INT_CST_LOW (index)])));
     }
   return NULL;
 }
@@ -10024,28 +10565,31 @@ fold_negate_const (tree arg0, tree type)
 {
   tree t = NULL_TREE;
 
-  if (TREE_CODE (arg0) == INTEGER_CST)
+  switch (TREE_CODE (arg0))
     {
-      unsigned HOST_WIDE_INT low;
-      HOST_WIDE_INT high;
-      int overflow = neg_double (TREE_INT_CST_LOW (arg0),
-                                TREE_INT_CST_HIGH (arg0),
-                                &low, &high);
-      t = build_int_2 (low, high);
-      TREE_TYPE (t) = type;
-      TREE_OVERFLOW (t)
-       = (TREE_OVERFLOW (arg0)
-          | force_fit_type (t, overflow && !TYPE_UNSIGNED (type)));
-      TREE_CONSTANT_OVERFLOW (t)
-       = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg0);
+    case INTEGER_CST:
+      {
+       unsigned HOST_WIDE_INT low;
+       HOST_WIDE_INT high;
+       int overflow = neg_double (TREE_INT_CST_LOW (arg0),
+                                  TREE_INT_CST_HIGH (arg0),
+                                  &low, &high);
+       t = build_int_cst_wide (type, low, high);
+       t = force_fit_type (t, 1,
+                           (overflow | TREE_OVERFLOW (arg0))
+                           && !TYPE_UNSIGNED (type),
+                           TREE_CONSTANT_OVERFLOW (arg0));
+       break;
+      }
+
+    case REAL_CST:
+      t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
+      break;
+
+    default:
+      gcc_unreachable ();
     }
-  else if (TREE_CODE (arg0) == REAL_CST)
-    t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
-#ifdef ENABLE_CHECKING
-  else
-    abort ();
-#endif
-    
+
   return t;
 }
 
@@ -10059,15 +10603,16 @@ fold_abs_const (tree arg0, tree type)
 {
   tree t = NULL_TREE;
 
-  if (TREE_CODE (arg0) == INTEGER_CST)
+  switch (TREE_CODE (arg0))
     {
+    case INTEGER_CST:
       /* If the value is unsigned, then the absolute value is
         the same as the ordinary value.  */
       if (TYPE_UNSIGNED (type))
-       return arg0;
+       t = arg0;
       /* Similarly, if the value is non-negative.  */
       else if (INT_CST_LT (integer_minus_one_node, arg0))
-       return arg0;
+       t = arg0;
       /* If the value is negative, then the absolute value is
         its negation.  */
       else
@@ -10077,28 +10622,23 @@ fold_abs_const (tree arg0, tree type)
          int overflow = neg_double (TREE_INT_CST_LOW (arg0),
                                     TREE_INT_CST_HIGH (arg0),
                                     &low, &high);
-         t = build_int_2 (low, high);
-         TREE_TYPE (t) = type;
-         TREE_OVERFLOW (t)
-           = (TREE_OVERFLOW (arg0)
-              | force_fit_type (t, overflow));
-         TREE_CONSTANT_OVERFLOW (t)
-           = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg0);
-         return t;
+         t = build_int_cst_wide (type, low, high);
+         t = force_fit_type (t, -1, overflow | TREE_OVERFLOW (arg0),
+                             TREE_CONSTANT_OVERFLOW (arg0));
        }
-    }
-  else if (TREE_CODE (arg0) == REAL_CST)
-    {
+      break;
+
+    case REAL_CST:
       if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg0)))
-       return build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
+       t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
       else
-       return arg0;
+       t =  arg0;
+      break;
+
+    default:
+      gcc_unreachable ();
     }
-#ifdef ENABLE_CHECKING
-  else
-    abort ();
-#endif
-    
+
   return t;
 }
 
@@ -10110,20 +10650,14 @@ fold_not_const (tree arg0, tree type)
 {
   tree t = NULL_TREE;
 
-  if (TREE_CODE (arg0) == INTEGER_CST)
-    {
-      t = build_int_2 (~ TREE_INT_CST_LOW (arg0),
-                      ~ TREE_INT_CST_HIGH (arg0));
-      TREE_TYPE (t) = type;
-      force_fit_type (t, 0);
-      TREE_OVERFLOW (t) = TREE_OVERFLOW (arg0);
-      TREE_CONSTANT_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (arg0);
-    }
-#ifdef ENABLE_CHECKING
-  else
-    abort ();
-#endif
-    
+  gcc_assert (TREE_CODE (arg0) == INTEGER_CST);
+
+  t = build_int_cst_wide (type,
+                         ~ TREE_INT_CST_LOW (arg0),
+                         ~ TREE_INT_CST_HIGH (arg0));
+  t = force_fit_type (t, 0, TREE_OVERFLOW (arg0),
+                     TREE_CONSTANT_OVERFLOW (arg0));
+
   return t;
 }
 
@@ -10142,9 +10676,11 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
 
   if (TREE_CODE (op0) == REAL_CST && TREE_CODE (op1) == REAL_CST)
     {
+      const REAL_VALUE_TYPE *c0 = TREE_REAL_CST_PTR (op0);
+      const REAL_VALUE_TYPE *c1 = TREE_REAL_CST_PTR (op1);
+
       /* Handle the cases where either operand is a NaN.  */
-      if (REAL_VALUE_ISNAN (TREE_REAL_CST (op0))
-          || REAL_VALUE_ISNAN (TREE_REAL_CST (op1)))
+      if (real_isnan (c0) || real_isnan (c1))
        {
          switch (code)
            {
@@ -10174,43 +10710,13 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
              break;
 
            default:
-             abort ();
+             gcc_unreachable ();
            }
 
          return constant_boolean_node (result, type);
        }
 
-      /* From here on we're sure there are no NaNs.  */
-      switch (code)
-       {
-       case ORDERED_EXPR:
-         return constant_boolean_node (true, type);
-
-       case UNORDERED_EXPR:
-         return constant_boolean_node (false, type);
-
-       case UNLT_EXPR:
-         code = LT_EXPR;
-         break;
-       case UNLE_EXPR:
-         code = LE_EXPR;
-         break;
-       case UNGT_EXPR:
-         code = GT_EXPR;
-         break;
-       case UNGE_EXPR:
-         code = GE_EXPR;
-         break;
-       case UNEQ_EXPR:
-         code = EQ_EXPR;
-         break;
-       case LTGT_EXPR:
-         code = NE_EXPR;
-         break;
-
-       default:
-         break;
-       }
+      return constant_boolean_node (real_compare (code, c0, c1), type);
     }
 
   /* From here on we only handle LT, LE, GT, GE, EQ and NE.
@@ -10251,21 +10757,6 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
       else
        result = INT_CST_LT (op0, op1);
     }
-
-  else if (code == EQ_EXPR && !TREE_SIDE_EFFECTS (op0)
-           && integer_zerop (op1) && tree_expr_nonzero_p (op0))
-    result = 0;
-
-  /* Two real constants can be compared explicitly.  */
-  else if (TREE_CODE (op0) == REAL_CST && TREE_CODE (op1) == REAL_CST)
-    {
-      if (code == EQ_EXPR)
-       result = REAL_VALUES_EQUAL (TREE_REAL_CST (op0),
-                                   TREE_REAL_CST (op1));
-      else
-       result = REAL_VALUES_LESS (TREE_REAL_CST (op0),
-                                  TREE_REAL_CST (op1));
-    }
   else
     return NULL_TREE;
 
@@ -10274,13 +10765,34 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
   return constant_boolean_node (result, type);
 }
 
+/* Build an expression for the a clean point containing EXPR with type TYPE.
+   Don't build a cleanup point expression for EXPR which don't have side
+   effects.  */
+
+tree
+fold_build_cleanup_point_expr (tree type, tree expr)
+{
+  /* If the expression does not have side effects then we don't have to wrap
+     it with a cleanup point expression.  */
+  if (!TREE_SIDE_EFFECTS (expr))
+    return expr;
+  
+  return build1 (CLEANUP_POINT_EXPR, type, expr);
+}
+
 /* Build an expression for the address of T.  Folds away INDIRECT_REF to
    avoid confusing the gimplify process.  */
 
 tree
 build_fold_addr_expr_with_type (tree t, tree ptrtype)
 {
-  if (TREE_CODE (t) == INDIRECT_REF)
+  /* The size of the object is not relevant when talking about its address.  */
+  if (TREE_CODE (t) == WITH_SIZE_EXPR)
+    t = TREE_OPERAND (t, 0);
+
+  /* Note: doesn't apply to ALIGN_INDIRECT_REF */
+  if (TREE_CODE (t) == INDIRECT_REF
+      || TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
     {
       t = TREE_OPERAND (t, 0);
       if (TREE_TYPE (t) != ptrtype)
@@ -10289,8 +10801,8 @@ build_fold_addr_expr_with_type (tree t, tree ptrtype)
   else
     {
       tree base = t;
-      while (TREE_CODE (base) == COMPONENT_REF
-            || TREE_CODE (base) == ARRAY_REF)
+
+      while (handled_component_p (base))
        base = TREE_OPERAND (base, 0);
       if (DECL_P (base))
        TREE_ADDRESSABLE (base) = 1;
@@ -10328,7 +10840,7 @@ build_fold_indirect_ref (tree t)
       /* *(foo *)&fooarray => fooarray[0] */
       else if (TREE_CODE (optype) == ARRAY_TYPE
               && lang_hooks.types_compatible_p (type, TREE_TYPE (optype)))
-       return build2 (ARRAY_REF, type, op, size_zero_node);
+       return build4 (ARRAY_REF, type, op, size_zero_node, NULL_TREE, NULL_TREE);
     }
 
   /* *(foo *)fooarrptr => (*fooarrptr)[0] */
@@ -10337,10 +10849,222 @@ build_fold_indirect_ref (tree t)
       && lang_hooks.types_compatible_p (type, TREE_TYPE (TREE_TYPE (subtype))))
     {
       sub = build_fold_indirect_ref (sub);
-      return build2 (ARRAY_REF, type, sub, size_zero_node);
+      return build4 (ARRAY_REF, type, sub, size_zero_node, NULL_TREE, NULL_TREE);
     }
 
   return build1 (INDIRECT_REF, type, t);
 }
 
-#include "gt-fold-const.h"
+/* Strip non-trapping, non-side-effecting tree nodes from an expression
+   whose result is ignored.  The type of the returned tree need not be
+   the same as the original expression.  */
+
+tree
+fold_ignored_result (tree t)
+{
+  if (!TREE_SIDE_EFFECTS (t))
+    return integer_zero_node;
+
+  for (;;)
+    switch (TREE_CODE_CLASS (TREE_CODE (t)))
+      {
+      case tcc_unary:
+       t = TREE_OPERAND (t, 0);
+       break;
+
+      case tcc_binary:
+      case tcc_comparison:
+       if (!TREE_SIDE_EFFECTS (TREE_OPERAND (t, 1)))
+         t = TREE_OPERAND (t, 0);
+       else if (!TREE_SIDE_EFFECTS (TREE_OPERAND (t, 0)))
+         t = TREE_OPERAND (t, 1);
+       else
+         return t;
+       break;
+
+      case tcc_expression:
+       switch (TREE_CODE (t))
+         {
+         case COMPOUND_EXPR:
+           if (TREE_SIDE_EFFECTS (TREE_OPERAND (t, 1)))
+             return t;
+           t = TREE_OPERAND (t, 0);
+           break;
+
+         case COND_EXPR:
+           if (TREE_SIDE_EFFECTS (TREE_OPERAND (t, 1))
+               || TREE_SIDE_EFFECTS (TREE_OPERAND (t, 2)))
+             return t;
+           t = TREE_OPERAND (t, 0);
+           break;
+
+         default:
+           return t;
+         }
+       break;
+
+      default:
+       return t;
+      }
+}
+
+/* Return the value of VALUE, rounded up to a multiple of DIVISOR.
+   This can only be applied to objects of a sizetype.  */
+
+tree
+round_up (tree value, int divisor)
+{
+  tree div = NULL_TREE;
+
+  gcc_assert (divisor > 0);
+  if (divisor == 1)
+    return value;
+
+  /* See if VALUE is already a multiple of DIVISOR.  If so, we don't
+     have to do anything.  Only do this when we are not given a const,
+     because in that case, this check is more expensive than just
+     doing it.  */
+  if (TREE_CODE (value) != INTEGER_CST)
+    {
+      div = build_int_cst (TREE_TYPE (value), divisor);
+
+      if (multiple_of_p (TREE_TYPE (value), value, div))
+       return value;
+    }
+
+  /* If divisor is a power of two, simplify this to bit manipulation.  */
+  if (divisor == (divisor & -divisor))
+    {
+      tree t;
+
+      t = build_int_cst (TREE_TYPE (value), divisor - 1);
+      value = size_binop (PLUS_EXPR, value, t);
+      t = build_int_cst (TREE_TYPE (value), -divisor);
+      value = size_binop (BIT_AND_EXPR, value, t);
+    }
+  else
+    {
+      if (!div)
+       div = build_int_cst (TREE_TYPE (value), divisor);
+      value = size_binop (CEIL_DIV_EXPR, value, div);
+      value = size_binop (MULT_EXPR, value, div);
+    }
+
+  return value;
+}
+
+/* Likewise, but round down.  */
+
+tree
+round_down (tree value, int divisor)
+{
+  tree div = NULL_TREE;
+
+  gcc_assert (divisor > 0);
+  if (divisor == 1)
+    return value;
+
+  /* See if VALUE is already a multiple of DIVISOR.  If so, we don't
+     have to do anything.  Only do this when we are not given a const,
+     because in that case, this check is more expensive than just
+     doing it.  */
+  if (TREE_CODE (value) != INTEGER_CST)
+    {
+      div = build_int_cst (TREE_TYPE (value), divisor);
+
+      if (multiple_of_p (TREE_TYPE (value), value, div))
+       return value;
+    }
+
+  /* If divisor is a power of two, simplify this to bit manipulation.  */
+  if (divisor == (divisor & -divisor))
+    {
+      tree t;
+
+      t = build_int_cst (TREE_TYPE (value), -divisor);
+      value = size_binop (BIT_AND_EXPR, value, t);
+    }
+  else
+    {
+      if (!div)
+       div = build_int_cst (TREE_TYPE (value), divisor);
+      value = size_binop (FLOOR_DIV_EXPR, value, div);
+      value = size_binop (MULT_EXPR, value, div);
+    }
+
+  return value;
+}
+
+/* Returns the pointer to the base of the object addressed by EXP and
+   extracts the information about the offset of the access, storing it
+   to PBITPOS and POFFSET.  */
+
+static tree
+split_address_to_core_and_offset (tree exp,
+                                 HOST_WIDE_INT *pbitpos, tree *poffset)
+{
+  tree core;
+  enum machine_mode mode;
+  int unsignedp, volatilep;
+  HOST_WIDE_INT bitsize;
+
+  if (TREE_CODE (exp) == ADDR_EXPR)
+    {
+      core = get_inner_reference (TREE_OPERAND (exp, 0), &bitsize, pbitpos,
+                                 poffset, &mode, &unsignedp, &volatilep);
+
+      if (TREE_CODE (core) == INDIRECT_REF)
+       core = TREE_OPERAND (core, 0);
+    }
+  else
+    {
+      core = exp;
+      *pbitpos = 0;
+      *poffset = NULL_TREE;
+    }
+
+  return core;
+}
+
+/* Returns true if addresses of E1 and E2 differ by a constant, false
+   otherwise.  If they do, E1 - E2 is stored in *DIFF.  */
+
+bool
+ptr_difference_const (tree e1, tree e2, HOST_WIDE_INT *diff)
+{
+  tree core1, core2;
+  HOST_WIDE_INT bitpos1, bitpos2;
+  tree toffset1, toffset2, tdiff, type;
+
+  core1 = split_address_to_core_and_offset (e1, &bitpos1, &toffset1);
+  core2 = split_address_to_core_and_offset (e2, &bitpos2, &toffset2);
+
+  if (bitpos1 % BITS_PER_UNIT != 0
+      || bitpos2 % BITS_PER_UNIT != 0
+      || !operand_equal_p (core1, core2, 0))
+    return false;
+
+  if (toffset1 && toffset2)
+    {
+      type = TREE_TYPE (toffset1);
+      if (type != TREE_TYPE (toffset2))
+       toffset2 = fold_convert (type, toffset2);
+
+      tdiff = fold (build2 (MINUS_EXPR, type, toffset1, toffset2));
+      if (!host_integerp (tdiff, 0))
+       return false;
+
+      *diff = tree_low_cst (tdiff, 0);
+    }
+  else if (toffset1 || toffset2)
+    {
+      /* If only one of the offsets is non-constant, the difference cannot
+        be a constant.  */
+      return false;
+    }
+  else
+    *diff = 0;
+
+  *diff += (bitpos1 - bitpos2) / BITS_PER_UNIT;
+  return true;
+}