OSDN Git Service

2005-03-04 Andrew Pinski <pinskia@physics.uc.edu>
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index 0b225c0..517c45d 100644 (file)
@@ -1,6 +1,6 @@
 /* Fold a constant sub-tree into a single node for C-compiler
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -89,9 +89,6 @@ 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 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);
 static enum tree_code compcode_to_comparison (enum comparison_code);
@@ -124,8 +121,8 @@ 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 fold_binary_op_with_conditional_arg (enum tree_code, tree, tree,
-                                                tree, int);
+static tree fold_binary_op_with_conditional_arg (tree, enum tree_code, 
+                                                tree, tree, int);
 static bool fold_real_zero_addition_p (tree, tree, int);
 static tree fold_mathfn_compare (enum built_in_function, enum tree_code,
                                 tree, tree, tree);
@@ -192,25 +189,25 @@ decode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT *low,
    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 non-zero,
+       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 non-zero
+        CONST_OVERFLOWED is nonzero
        or we set TREE_OVERFLOWED.
   We return either the original T, or a copy.  */
 
 tree
-force_fit_type (tree t, int overflowable, bool overflowed, bool overflowed_const)
+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) != INTEGER_CST)
-    abort ();
-  
+  gcc_assert (TREE_CODE (t) == INTEGER_CST);
+
   low = TREE_INT_CST_LOW (t);
   high = TREE_INT_CST_HIGH (t);
 
@@ -226,7 +223,7 @@ force_fit_type (tree t, int overflowable, bool overflowed, bool overflowed_const
 
   /* First clear all bits that are beyond the type's precision.  */
 
-  if (prec == 2 * HOST_BITS_PER_WIDE_INT)
+  if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
     ;
   else if (prec > HOST_BITS_PER_WIDE_INT)
     high &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
@@ -239,7 +236,7 @@ force_fit_type (tree t, int overflowable, bool overflowed, bool overflowed_const
 
   if (!sign_extended_type)
     /* No sign extension */;
-  else if (prec == 2 * HOST_BITS_PER_WIDE_INT)
+  else if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
     /* Correct width already.  */;
   else if (prec > HOST_BITS_PER_WIDE_INT)
     {
@@ -267,20 +264,23 @@ force_fit_type (tree t, int overflowable, bool overflowed, bool overflowed_const
   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)
-       TREE_CONSTANT_OVERFLOW (t) = 1;
-      
-      TREE_INT_CST_LOW (t) = low;
-      TREE_INT_CST_HIGH (t) = high;
+       {
+         t = copy_node (t);
+         TREE_CONSTANT_OVERFLOW (t) = 1;
+       }
     }
-  
+
   return t;
 }
 \f
@@ -823,7 +823,7 @@ div_and_round_double (enum tree_code code, int uns,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   /* Compute true remainder:  rem = num - (quo * den)  */
@@ -861,14 +861,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)
@@ -884,19 +913,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:
@@ -1248,7 +1265,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));
     }
@@ -1405,33 +1430,26 @@ 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 (low, type);
-  else
-    {
-      t = build_int_2 (low, hi);
-      TREE_TYPE (t) = TREE_TYPE (arg1);
-    }
+  t = build_int_cst_wide (TREE_TYPE (arg1), low, hi);
 
   if (notrunc)
     {
       /* Propagate overflow flags ourselves.  */
       if (((!uns || is_sizetype) && overflow)
          | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2))
-       TREE_OVERFLOW (t) = 1;
-
-      if (TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1)
-         | TREE_CONSTANT_OVERFLOW (arg2))
-       TREE_CONSTANT_OVERFLOW (t) = 1;
+       {
+         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,
@@ -1439,7 +1457,7 @@ int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
                        | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2),
                        TREE_CONSTANT_OVERFLOW (arg1)
                        | TREE_CONSTANT_OVERFLOW (arg2));
-  
+
   return t;
 }
 
@@ -1464,6 +1482,8 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
       REAL_VALUE_TYPE d1;
       REAL_VALUE_TYPE d2;
       REAL_VALUE_TYPE value;
+      REAL_VALUE_TYPE result;
+      bool inexact;
       tree t, type;
 
       d1 = TREE_REAL_CST (arg1);
@@ -1492,9 +1512,21 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
       else if (REAL_VALUE_ISNAN (d2))
        return arg2;
 
-      REAL_ARITHMETIC (value, code, d1, d2);
+      inexact = real_arithmetic (&value, code, &d1, &d2);
+      real_convert (&result, mode, &value);
 
-      t = build_real (type, real_value_truncate (mode, value));
+      /* Don't constant fold this floating point operation if the
+        result may dependent upon the run-time rounding mode and
+        flag_rounding_math is set, or if GCC's software emulation
+        is unable to accurately represent the result.  */
+      
+      if ((flag_rounding_math
+          || (REAL_MODE_FORMAT_COMPOSITE_P (mode)
+              && !flag_unsafe_math_optimizations))
+         && (inexact || !real_identical (&result, &value)))
+       return NULL_TREE;
+
+      t = build_real (type, result);
 
       TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2);
       TREE_CONSTANT_OVERFLOW (t)
@@ -1575,108 +1607,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.  */
+/* Create a size type INT_CST node with NUMBER sign extended.  KIND
+   indicates which particular sizetype to create.  */
 
 tree
 size_int_kind (HOST_WIDE_INT number, enum size_type_kind kind)
 {
-  return size_int_type (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;
-
-tree
-size_int_type (HOST_WIDE_INT number, tree type)
-{
-  void **slot;
-  unsigned int prec;
-  HOST_WIDE_INT high;
-  unsigned HOST_WIDE_INT low;
-
-  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.  */
-  prec = TYPE_PRECISION (type);
-  TREE_TYPE (new_const) = type;
-  TREE_OVERFLOW (new_const) = TREE_CONSTANT_OVERFLOW (new_const) = 0;
-  low = number;
-  if (number >= 0)
-    high = 0;
-  else
-    {
-      /* Sizetype IS sign extended.  */
-      high = -1;
-      if (prec <= HOST_BITS_PER_WIDE_INT)
-       low |= (HOST_WIDE_INT)(-1) << (prec - 1);
-    }
-  TREE_INT_CST_LOW (new_const) = low;
-  TREE_INT_CST_HIGH (new_const) = high;
-
-  if (low != (unsigned HOST_WIDE_INT)number
-      || high != (number < 0 ? -1 : 0))
-    TREE_OVERFLOW (new_const) = TREE_CONSTANT_OVERFLOW (new_const) = 1;
-  
-  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.
@@ -1687,9 +1633,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)
@@ -1723,16 +1668,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
@@ -1755,166 +1698,185 @@ size_diffop (tree arg0, tree arg1)
                                                        arg1, arg0)));
 }
 \f
+/* A subroutine of fold_convert_const handling conversions of an
+   INTEGER_CST to another integer type.  */
 
-/* Attempt to fold type conversion operation CODE of expression ARG1 to
-   type TYPE.  If no simplification can be done return NULL_TREE.  */
+static tree
+fold_convert_const_int_from_int (tree type, tree arg1)
+{
+  tree t;
+
+  /* Given an integer constant, make new constant with new type,
+     appropriately sign-extended or truncated.  */
+  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;
+}
+
+/* A subroutine of fold_convert_const handling conversions a REAL_CST
+   to an integer type.  */
 
 static tree
-fold_convert_const (enum tree_code code, tree type, tree arg1)
+fold_convert_const_int_from_real (enum tree_code code, tree type, tree arg1)
 {
   int overflow = 0;
   tree t;
 
-  if (TREE_TYPE (arg1) == type)
-    return arg1;
+  /* The following code implements the floating point to integer
+     conversion rules required by the Java Language Specification,
+     that IEEE NaNs are mapped to zero and values that overflow
+     the target precision saturate, i.e. values greater than
+     INT_MAX are mapped to INT_MAX, and values less than INT_MIN
+     are mapped to INT_MIN.  These semantics are allowed by the
+     C and C++ standards that simply state that the behavior of
+     FP-to-integer conversion is unspecified upon overflow.  */
 
-  if (POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type))
+  HOST_WIDE_INT high, low;
+  REAL_VALUE_TYPE r;
+  REAL_VALUE_TYPE x = TREE_REAL_CST (arg1);
+
+  switch (code)
     {
-      if (TREE_CODE (arg1) == INTEGER_CST)
-       {
-         /* If we would build a constant wider than GCC supports,
-            leave the conversion unfolded.  */
-         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 (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;
-
-         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)
-       {
-         /* The following code implements the floating point to integer
-            conversion rules required by the Java Language Specification,
-            that IEEE NaNs are mapped to zero and values that overflow
-            the target precision saturate, i.e. values greater than
-            INT_MAX are mapped to INT_MAX, and values less than INT_MIN
-            are mapped to INT_MIN.  These semantics are allowed by the
-            C and C++ standards that simply state that the behavior of
-            FP-to-integer conversion is unspecified upon overflow.  */
+    case FIX_TRUNC_EXPR:
+      real_trunc (&r, VOIDmode, &x);
+      break;
 
-         HOST_WIDE_INT high, low;
-         REAL_VALUE_TYPE r;
-         REAL_VALUE_TYPE x = TREE_REAL_CST (arg1);
+    case FIX_CEIL_EXPR:
+      real_ceil (&r, VOIDmode, &x);
+      break;
 
-         switch (code)
-           {
-           case FIX_TRUNC_EXPR:
-             real_trunc (&r, VOIDmode, &x);
-             break;
+    case FIX_FLOOR_EXPR:
+      real_floor (&r, VOIDmode, &x);
+      break;
 
-           case FIX_CEIL_EXPR:
-             real_ceil (&r, VOIDmode, &x);
-             break;
+    case FIX_ROUND_EXPR:
+      real_round (&r, VOIDmode, &x);
+      break;
 
-           case FIX_FLOOR_EXPR:
-             real_floor (&r, VOIDmode, &x);
-             break;
+    default:
+      gcc_unreachable ();
+    }
 
-           case FIX_ROUND_EXPR:
-             real_round (&r, VOIDmode, &x);
-             break;
+  /* If R is NaN, return zero and show we have an overflow.  */
+  if (REAL_VALUE_ISNAN (r))
+    {
+      overflow = 1;
+      high = 0;
+      low = 0;
+    }
 
-           default:
-             abort ();
-           }
+  /* See if R is less than the lower bound or greater than the
+     upper bound.  */
+
+  if (! overflow)
+    {
+      tree lt = TYPE_MIN_VALUE (type);
+      REAL_VALUE_TYPE l = real_value_from_int_cst (NULL_TREE, lt);
+      if (REAL_VALUES_LESS (r, l))
+       {
+         overflow = 1;
+         high = TREE_INT_CST_HIGH (lt);
+         low = TREE_INT_CST_LOW (lt);
+       }
+    }
 
-         /* If R is NaN, return zero and show we have an overflow.  */
-         if (REAL_VALUE_ISNAN (r))
+  if (! overflow)
+    {
+      tree ut = TYPE_MAX_VALUE (type);
+      if (ut)
+       {
+         REAL_VALUE_TYPE u = real_value_from_int_cst (NULL_TREE, ut);
+         if (REAL_VALUES_LESS (u, r))
            {
              overflow = 1;
-             high = 0;
-             low = 0;
+             high = TREE_INT_CST_HIGH (ut);
+             low = TREE_INT_CST_LOW (ut);
            }
+       }
+    }
 
-         /* See if R is less than the lower bound or greater than the
-            upper bound.  */
+  if (! overflow)
+    REAL_VALUE_TO_INT (&low, &high, r);
 
-         if (! overflow)
-           {
-             tree lt = TYPE_MIN_VALUE (type);
-             REAL_VALUE_TYPE l = real_value_from_int_cst (NULL_TREE, lt);
-             if (REAL_VALUES_LESS (r, l))
-               {
-                 overflow = 1;
-                 high = TREE_INT_CST_HIGH (lt);
-                 low = TREE_INT_CST_LOW (lt);
-               }
-           }
+  t = build_int_cst_wide (type, low, high);
 
-         if (! overflow)
-           {
-             tree ut = TYPE_MAX_VALUE (type);
-             if (ut)
-               {
-                 REAL_VALUE_TYPE u = real_value_from_int_cst (NULL_TREE, ut);
-                 if (REAL_VALUES_LESS (u, r))
-                   {
-                     overflow = 1;
-                     high = TREE_INT_CST_HIGH (ut);
-                     low = TREE_INT_CST_LOW (ut);
-                   }
-               }
-           }
+  t = force_fit_type (t, -1, overflow | TREE_OVERFLOW (arg1),
+                     TREE_CONSTANT_OVERFLOW (arg1));
+  return t;
+}
 
-         if (! overflow)
-           REAL_VALUE_TO_INT (&low, &high, r);
+/* A subroutine of fold_convert_const handling conversions a REAL_CST
+   to another floating point type.  */
 
-         t = build_int_2 (low, high);
-         TREE_TYPE (t) = type;
+static tree
+fold_convert_const_real_from_real (tree type, tree arg1)
+{
+  REAL_VALUE_TYPE value;
+  tree t;
 
-         t = force_fit_type (t, -1, overflow | TREE_OVERFLOW (arg1),
-                             TREE_CONSTANT_OVERFLOW (arg1));
-         return t;
-       }
+  real_convert (&value, TYPE_MODE (type), &TREE_REAL_CST (arg1));
+  t = build_real (type, value);
+
+  TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1);
+  TREE_CONSTANT_OVERFLOW (t)
+    = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
+  return t;
+}
+
+/* Attempt to fold type conversion operation CODE of expression ARG1 to
+   type TYPE.  If no simplification can be done return NULL_TREE.  */
+
+static tree
+fold_convert_const (enum tree_code code, tree type, tree arg1)
+{
+  if (TREE_TYPE (arg1) == type)
+    return arg1;
+
+  if (POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type))
+    {
+      if (TREE_CODE (arg1) == INTEGER_CST)
+       return fold_convert_const_int_from_int (type, arg1);
+      else if (TREE_CODE (arg1) == REAL_CST)
+       return fold_convert_const_int_from_real (code, type, arg1);
     }
   else if (TREE_CODE (type) == REAL_TYPE)
     {
       if (TREE_CODE (arg1) == INTEGER_CST)
        return build_real_from_int_cst (type, arg1);
       if (TREE_CODE (arg1) == REAL_CST)
-       {
-         if (REAL_VALUE_ISNAN (TREE_REAL_CST (arg1)))
-           {
-             /* We make a copy of ARG1 so that we don't modify an
-                existing constant tree.  */
-             t = copy_node (arg1);
-             TREE_TYPE (t) = type;
-             return t;
-           }
-
-         t = build_real (type,
-                         real_value_truncate (TYPE_MODE (type),
-                                              TREE_REAL_CST (arg1)));
-
-         TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1);
-         TREE_CONSTANT_OVERFLOW (t)
-           = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
-         return t;
-       }
+       return fold_convert_const_real_from_real (type, arg1);
     }
   return NULL_TREE;
 }
 
+/* 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);
+}
+
 /* Convert expression ARG to type TYPE.  Used by the middle-end for
    simple conversions in preference to calling the front-end's convert.  */
 
@@ -1937,9 +1899,11 @@ fold_convert (tree type, tree arg)
                                        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);
@@ -1954,12 +1918,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
-         && tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (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);
@@ -1973,56 +1936,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))
-         && tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)))
-       return fold (build1 (NOP_EXPR, type, arg));
-      if (TREE_CODE (orig) == VECTOR_TYPE
-         && tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)))
-       return fold (build1 (NOP_EXPR, type, arg));
-    }
-  else if (VOID_TYPE_P (type))
-    return fold (build1 (CONVERT_EXPR, type, fold_ignored_result (arg)));
-  abort ();
 }
 \f
 /* Return an expr equal to X but certainly not valid as an lvalue.  */
@@ -2030,6 +2009,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))
   {
@@ -2042,6 +2026,8 @@ non_lvalue (tree x)
 
   case COMPONENT_REF:
   case INDIRECT_REF:
+  case ALIGN_INDIRECT_REF:
+  case MISALIGNED_INDIRECT_REF:
   case ARRAY_REF:
   case ARRAY_RANGE_REF:
   case BIT_FIELD_REF:
@@ -2080,7 +2066,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)
@@ -2131,7 +2117,7 @@ invert_tree_comparison (enum tree_code code, bool honor_nans)
     case UNORDERED_EXPR:
       return ORDERED_EXPR;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -2155,7 +2141,7 @@ swap_tree_comparison (enum tree_code code)
     case LE_EXPR:
       return GE_EXPR;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -2198,7 +2184,7 @@ comparison_to_compcode (enum tree_code code)
     case UNGE_EXPR:
       return COMPCODE_UNGE;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -2240,7 +2226,7 @@ compcode_to_comparison (enum comparison_code code)
     case COMPCODE_UNGE:
       return UNGE_EXPR;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -2333,7 +2319,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);
@@ -2368,17 +2354,8 @@ truth_value_p (enum tree_code code)
 int
 operand_equal_p (tree arg0, tree arg1, unsigned int flags)
 {
-  /* If one is specified and the other isn't, they aren't equal and if
-     neither is specified, they are.
-
-     ??? This is temporary and is meant only to handle the cases of the
-     optional operands for COMPONENT_REF and ARRAY_REF.  */
-  if ((arg0 && !arg1) || (!arg0 && arg1))
-    return 0;
-  else if (!arg0 && !arg1)
-    return 1;
   /* If either is ERROR_MARK, they aren't equal.  */
-  else if (TREE_CODE (arg0) == ERROR_MARK || TREE_CODE (arg1) == ERROR_MARK)
+  if (TREE_CODE (arg0) == ERROR_MARK || TREE_CODE (arg1) == ERROR_MARK)
     return 0;
 
   /* If both types don't have the same signedness, then we can't consider
@@ -2470,24 +2447,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 operand_equal_p (TREE_OPERAND (arg0, 0),
-                             TREE_OPERAND (arg1, 0), flags);
+      return OP_SAME (0);
 
-    case '<':
-    case '2':
-      if (operand_equal_p (TREE_OPERAND (arg0, 0),
-                          TREE_OPERAND (arg1, 0), flags)
-         && operand_equal_p (TREE_OPERAND (arg0, 1),
-                             TREE_OPERAND (arg1, 1), flags))
+
+    case tcc_comparison:
+    case tcc_binary:
+      if (OP_SAME (0) && OP_SAME (1))
        return 1;
 
       /* For commutative ops, allow the other order.  */
@@ -2497,7 +2493,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)
@@ -2507,75 +2503,58 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
       switch (TREE_CODE (arg0))
        {
        case INDIRECT_REF:
+       case ALIGN_INDIRECT_REF:
+       case MISALIGNED_INDIRECT_REF:
        case REALPART_EXPR:
        case IMAGPART_EXPR:
-         return operand_equal_p (TREE_OPERAND (arg0, 0),
-                                 TREE_OPERAND (arg1, 0), flags);
+         return OP_SAME (0);
 
        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)
-                 && operand_equal_p (TREE_OPERAND (arg0, 2),
-                                     TREE_OPERAND (arg1, 2), flags)
-                 && operand_equal_p (TREE_OPERAND (arg0, 3),
-                                     TREE_OPERAND (arg1, 3), 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:
-         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));
-
+         /* 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 operand_equal_p (TREE_OPERAND (arg0, 0),
-                                 TREE_OPERAND (arg1, 0), flags)
-                && operand_equal_p (TREE_OPERAND (arg0, 1),
-                                    TREE_OPERAND (arg1, 1), flags);
+         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;
+
+         /* Otherwise take into account this is a commutative operation.  */
          return (operand_equal_p (TREE_OPERAND (arg0, 0),
-                                  TREE_OPERAND (arg1, 0), flags)
+                                  TREE_OPERAND (arg1, 1), flags)
                  && operand_equal_p (TREE_OPERAND (arg0, 1),
-                                     TREE_OPERAND (arg1, 1), flags))
-                || (operand_equal_p (TREE_OPERAND (arg0, 0),
-                                     TREE_OPERAND (arg1, 1), flags)
-                    && operand_equal_p (TREE_OPERAND (arg0, 1),
-                                        TREE_OPERAND (arg1, 0), flags));
+                                     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;
 
          {
@@ -2611,7 +2590,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)
@@ -2621,6 +2600,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
@@ -2693,17 +2675,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
+  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
@@ -2711,24 +2693,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)
@@ -2738,7 +2720,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
@@ -2786,30 +2768,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:
@@ -2831,7 +2813,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);
@@ -2931,7 +2913,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)
@@ -2954,7 +2936,7 @@ invert_truthvalue (tree arg)
   switch (code)
     {
     case INTEGER_CST:
-      return fold_convert (type, build_int_2 (integer_zerop (arg), 0));
+      return constant_boolean_node (integer_zerop (arg), type);
 
     case TRUTH_AND_EXPR:
       return build2 (TRUTH_OR_EXPR, type,
@@ -3030,8 +3012,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);
 }
 
@@ -3094,8 +3075,20 @@ static tree
 make_bit_field_ref (tree inner, tree type, int bitsize, int bitpos,
                    int unsignedp)
 {
-  tree result = build3 (BIT_FIELD_REF, type, inner,
-                       size_int (bitsize), bitsize_int (bitpos));
+  tree result;
+
+  if (bitpos == 0)
+    {
+      tree size = TYPE_SIZE (TREE_TYPE (inner));
+      if ((INTEGRAL_TYPE_P (TREE_TYPE (inner))
+          || POINTER_TYPE_P (TREE_TYPE (inner)))
+         && host_integerp (size, 0) 
+         && tree_low_cst (size, 0) == bitsize)
+       return fold_convert (type, inner);
+    }
+
+  result = build3 (BIT_FIELD_REF, type, inner,
+                  size_int (bitsize), bitsize_int (bitpos));
 
   BIT_FIELD_REF_UNSIGNED (result) = unsignedp;
 
@@ -3143,7 +3136,7 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type,
      do anything if the inner expression is a PLACEHOLDER_EXPR since we
      then will no longer be able to replace it.  */
   linner = get_inner_reference (lhs, &lbitsize, &lbitpos, &offset, &lmode,
-                               &lunsignedp, &lvolatilep);
+                               &lunsignedp, &lvolatilep, false);
   if (linner == lhs || lbitsize == GET_MODE_BITSIZE (lmode) || lbitsize < 0
       || offset != 0 || TREE_CODE (linner) == PLACEHOLDER_EXPR)
     return 0;
@@ -3153,7 +3146,7 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type,
      /* If this is not a constant, we can only do something if bit positions,
        sizes, and signedness are the same.  */
      rinner = get_inner_reference (rhs, &rbitsize, &rbitpos, &offset, &rmode,
-                                  &runsignedp, &rvolatilep);
+                                  &runsignedp, &rvolatilep, false);
 
      if (rinner == rhs || lbitpos != rbitpos || lbitsize != rbitsize
         || lunsignedp != runsignedp || offset != 0
@@ -3189,8 +3182,7 @@ 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;
+  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);
@@ -3330,7 +3322,7 @@ decode_field_reference (tree exp, HOST_WIDE_INT *pbitsize,
     }
 
   inner = get_inner_reference (exp, pbitsize, pbitpos, &offset, pmode,
-                              punsignedp, pvolatilep);
+                              punsignedp, pvolatilep, false);
   if ((inner == exp && and_mask == 0)
       || *pbitsize < 0 || offset != 0
       || TREE_CODE (inner) == PLACEHOLDER_EXPR)
@@ -3346,10 +3338,9 @@ decode_field_reference (tree exp, HOST_WIDE_INT *pbitsize,
   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;
+  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);
 
@@ -3373,10 +3364,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);
+  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,
@@ -3451,13 +3441,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)
@@ -3528,7 +3515,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
@@ -3560,7 +3547,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);
@@ -3597,15 +3584,15 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
 
       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')
+         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) == '2'
-             || TREE_CODE_CLASS (code) == '<'
-             || (TREE_CODE_CLASS (code) == 'e'
+         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);
        }
@@ -3649,7 +3636,7 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
              in_p = ! in_p, low = 0, high = arg1;
              break;
            default:
-             abort ();
+             gcc_unreachable ();
            }
 
          /* If this is an unsigned comparison, we also know that EXP is
@@ -4206,10 +4193,17 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
     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)))
@@ -4217,6 +4211,10 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
                               (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)))
@@ -4225,7 +4223,8 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
        tem = fold (build1 (ABS_EXPR, TREE_TYPE (arg1), arg1));
        return negate_expr (fold_convert (type, tem));
       default:
-       abort ();
+       gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison);
+       break;
       }
 
   /* A != 0 ? A : 0 is simply A, unless A is -0.  Likewise
@@ -4289,6 +4288,8 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
          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
@@ -4297,31 +4298,37 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
            {
              comp_op0 = fold_convert (comp_type, comp_op0);
              comp_op1 = fold_convert (comp_type, comp_op1);
-             tem = fold (build2 (MIN_EXPR, comp_type,
-                                 (comp_code == LE_EXPR
-                                  ? comp_op0 : comp_op1),
-                                 (comp_code == LE_EXPR
-                                  ? comp_op1 : comp_op0)));
+             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 = fold (build2 (MAX_EXPR, comp_type,
-                                 (comp_code == GE_EXPR
-                                  ? comp_op0 : comp_op1),
-                                 (comp_code == GE_EXPR
-                                  ? comp_op1 : comp_op0)));
-             tem = fold (build2 (MAX_EXPR, comp_type, comp_op0, 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:
-         abort ();
+         gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison);
+         break;
        }
     }
 
@@ -4391,7 +4398,7 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
       case NE_EXPR:
        break;
       default:
-       abort ();
+       gcc_unreachable ();
       }
 
   return NULL_TREE;
@@ -4399,8 +4406,8 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
 
 
 \f
-#ifndef RANGE_TEST_NON_SHORT_CIRCUIT
-#define RANGE_TEST_NON_SHORT_CIRCUIT (BRANCH_COST >= 2)
+#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
@@ -4438,7 +4445,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)
@@ -4593,7 +4600,8 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
       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);
@@ -4659,7 +4667,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
@@ -4921,12 +4930,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);
        }
     }
@@ -5097,10 +5106,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
@@ -5118,10 +5127,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))
@@ -5152,7 +5161,21 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type)
        return t1;
       break;
 
-    case NEGATE_EXPR:  case ABS_EXPR:
+    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;
@@ -5358,18 +5381,61 @@ constant_boolean_node (int value, tree type)
     return value ? integer_one_node : integer_zero_node;
   else if (type == boolean_type_node)
     return value ? boolean_true_node : boolean_false_node;
-  else if (TREE_CODE (type) == BOOLEAN_TYPE)
-    return lang_hooks.truthvalue_conversion (value ? integer_one_node
-                                                  : integer_zero_node);
   else
-    {
-      tree t = build_int_2 (value, 0);
+    return build_int_cst (type, value);
+}
 
-      TREE_TYPE (t) = type;
-      return t;
+
+/* Return true if expr looks like an ARRAY_REF and set base and
+   offset to the appropriate trees.  If there is no offset,
+   offset is set to NULL_TREE.  */
+
+static bool
+extract_array_ref (tree expr, tree *base, tree *offset)
+{
+  /* We have to be careful with stripping nops as with the
+     base type the meaning of the offset can change.  */
+  tree inner_expr = expr;
+  STRIP_NOPS (inner_expr);
+  /* One canonical form is a PLUS_EXPR with the first
+     argument being an ADDR_EXPR with a possible NOP_EXPR
+     attached.  */
+  if (TREE_CODE (expr) == PLUS_EXPR)
+    {
+      tree op0 = TREE_OPERAND (expr, 0);
+      STRIP_NOPS (op0);
+      if (TREE_CODE (op0) == ADDR_EXPR)
+       {
+         *base = TREE_OPERAND (expr, 0);
+         *offset = TREE_OPERAND (expr, 1);
+         return true;
+       }
     }
+  /* Other canonical form is an ADDR_EXPR of an ARRAY_REF,
+     which we transform into an ADDR_EXPR with appropriate
+     offset.  For other arguments to the ADDR_EXPR we assume
+     zero offset and as such do not care about the ADDR_EXPR
+     type and strip possible nops from it.  */
+  else if (TREE_CODE (inner_expr) == ADDR_EXPR)
+    {
+      tree op0 = TREE_OPERAND (inner_expr, 0);
+      if (TREE_CODE (op0) == ARRAY_REF)
+       {
+         *base = build_fold_addr_expr (TREE_OPERAND (op0, 0));
+         *offset = TREE_OPERAND (op0, 1);
+       }
+      else
+       {
+         *base = inner_expr;
+         *offset = NULL_TREE;
+       }
+      return true;
+    }
+
+  return false;
 }
 
+
 /* Transform `a + (b ? x : y)' into `b ? (a + x) : (a + y)'.
    Transform, `a + (x < y)' into `(x < y) ? (a + 1) : (a + 0)'.  Here
    CODE corresponds to the `+', COND to the `(b ? x : y)' or `(x < y)'
@@ -5380,15 +5446,20 @@ constant_boolean_node (int value, tree type)
    possible.  */
 
 static tree
-fold_binary_op_with_conditional_arg (enum tree_code code, tree type,
-                                    tree cond, tree arg, int cond_first_p)
+fold_binary_op_with_conditional_arg (tree t, enum tree_code code, tree cond,
+                                    tree arg, int cond_first_p)
 {
+  const tree type = TREE_TYPE (t);
+  tree cond_type = cond_first_p ? TREE_TYPE (TREE_OPERAND (t, 0)) 
+                               : TREE_TYPE (TREE_OPERAND (t, 1));
+  tree arg_type = cond_first_p ? TREE_TYPE (TREE_OPERAND (t, 1)) 
+                              : TREE_TYPE (TREE_OPERAND (t, 0));
   tree test, true_value, false_value;
   tree lhs = NULL_TREE;
   tree rhs = NULL_TREE;
 
   /* This transformation is only worthwhile if we don't have to wrap
-     arg in a SAVE_EXPR, and the operation can be simplified on atleast
+     arg in a SAVE_EXPR, and the operation can be simplified on at least
      one of the branches once its pushed inside the COND_EXPR.  */
   if (!TREE_CONSTANT (arg))
     return NULL_TREE;
@@ -5414,12 +5485,19 @@ fold_binary_op_with_conditional_arg (enum tree_code code, tree type,
       false_value = constant_boolean_node (false, testtype);
     }
 
+  arg = fold_convert (arg_type, arg);
   if (lhs == 0)
-    lhs = fold (cond_first_p ? build2 (code, type, true_value, arg)
+    {
+      true_value = fold_convert (cond_type, true_value);
+      lhs = fold (cond_first_p ? build2 (code, type, true_value, arg)
                             : build2 (code, type, arg, true_value));
+    }
   if (rhs == 0)
-    rhs = fold (cond_first_p ? build2 (code, type, false_value, arg)
+    {
+      false_value = fold_convert (cond_type, false_value);
+      rhs = fold (cond_first_p ? build2 (code, type, false_value, arg)
                             : build2 (code, type, arg, false_value));
+    }
 
   test = fold (build3 (COND_EXPR, type, test, lhs, rhs));
   return fold_convert (type, test);
@@ -5700,8 +5778,7 @@ 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);
+  prod = build_int_cst_wide (TREE_TYPE (arg00), lpart, hpart);
   prod = force_fit_type (prod, -1, overflow, false);
 
   if (TYPE_UNSIGNED (TREE_TYPE (arg0)))
@@ -5715,8 +5792,7 @@ 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);
+      hi = build_int_cst_wide (TREE_TYPE (arg00), lpart, hpart);
       hi = force_fit_type (hi, -1, overflow | TREE_OVERFLOW (prod),
                           TREE_CONSTANT_OVERFLOW (prod));
     }
@@ -5741,11 +5817,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))
        {
@@ -5765,7 +5844,7 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
 
@@ -5826,22 +5905,6 @@ tree
 fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
                      tree result_type)
 {
-  /* If this is a TRUTH_NOT_EXPR, it may have a single bit test inside
-     operand 0.  */
-  if (code == TRUTH_NOT_EXPR)
-    {
-      code = TREE_CODE (arg0);
-      if (code != NE_EXPR && code != EQ_EXPR)
-       return NULL_TREE;
-
-      /* Extract the arguments of the EQ/NE.  */
-      arg1 = TREE_OPERAND (arg0, 1);
-      arg0 = TREE_OPERAND (arg0, 0);
-
-      /* This requires us to invert the code.  */
-      code = (code == EQ_EXPR ? NE_EXPR : EQ_EXPR);
-    }
-
   /* If this is testing a single bit, we can optimize the test.  */
   if ((code == NE_EXPR || code == EQ_EXPR)
       && TREE_CODE (arg0) == BIT_AND_EXPR && integer_zerop (arg1)
@@ -5891,7 +5954,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
@@ -5928,7 +5992,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)
@@ -5978,15 +6042,6 @@ tree_swap_operands_p (tree arg0, tree arg1, bool reorder)
   if (DECL_P (arg0))
     return 1;
 
-  if (reorder && flag_evaluation_order
-      && (TREE_SIDE_EFFECTS (arg0) || TREE_SIDE_EFFECTS (arg1)))
-    return 0;
-
-  if (DECL_P (arg1))
-    return 0;
-  if (DECL_P (arg0))
-    return 1;
-
   /* It is preferable to swap two SSA_NAME to ensure a canonical form
      for commutative and comparison operators.  Ensuring a canonical
      form allows the optimizers to find additional redundancies without
@@ -5999,183 +6054,618 @@ tree_swap_operands_p (tree arg0, tree arg1, bool reorder)
   return 0;
 }
 
-/* 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.
-   NOP_EXPR conversions may be removed freely (as long as we
-   are careful not to change the type of the overall expression).
-   We cannot simplify through a CONVERT_EXPR, FIX_EXPR or FLOAT_EXPR,
-   but we can constant-fold them if they have constant operands.  */
+/* Fold comparison ARG0 CODE ARG1 (with result in TYPE), where
+   ARG0 is extended to a wider type.  */
 
-#ifdef ENABLE_FOLD_CHECKING
-# define fold(x) fold_1 (x)
-static tree fold_1 (tree);
-static
-#endif
-tree
-fold (tree expr)
+static tree
+fold_widened_comparison (enum tree_code code, tree type, tree arg0, tree arg1)
 {
-  const tree t = expr;
-  const tree type = TREE_TYPE (expr);
-  tree t1 = NULL_TREE;
-  tree tem;
-  tree arg0 = NULL_TREE, arg1 = NULL_TREE;
-  enum tree_code code = TREE_CODE (t);
-  int kind = TREE_CODE_CLASS (code);
+  tree arg0_unw = get_unwidened (arg0, NULL_TREE);
+  tree arg1_unw;
+  tree shorter_type, outer_type;
+  tree min, max;
+  bool above, below;
 
-  /* WINS will be nonzero when the switch is done
-     if all operands are constant.  */
-  int wins = 1;
+  if (arg0_unw == arg0)
+    return NULL_TREE;
+  shorter_type = TREE_TYPE (arg0_unw);
 
-  /* Return right away if a constant.  */
-  if (kind == 'c')
-    return t;
+  if (TYPE_PRECISION (TREE_TYPE (arg0)) <= TYPE_PRECISION (shorter_type))
+    return NULL_TREE;
 
-  if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR)
+  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)
     {
-      tree subop;
+    case EQ_EXPR:
+      if (above || below)
+       return omit_one_operand (type, integer_zero_node, arg0);
+      break;
 
-      /* Special case for conversion ops that can have fixed point args.  */
-      arg0 = TREE_OPERAND (t, 0);
+    case NE_EXPR:
+      if (above || below)
+       return omit_one_operand (type, integer_one_node, arg0);
+      break;
 
-      /* Don't use STRIP_NOPS, because signedness of argument type matters.  */
-      if (arg0 != 0)
-       STRIP_SIGN_NOPS (arg0);
+    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);
 
-      if (arg0 != 0 && TREE_CODE (arg0) == COMPLEX_CST)
-       subop = TREE_REALPART (arg0);
-      else
-       subop = 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);
 
-      if (subop != 0 && TREE_CODE (subop) != INTEGER_CST
-         && TREE_CODE (subop) != REAL_CST)
-       /* Note that TREE_CONSTANT isn't enough:
-          static var addresses are constant but we can't
-          do arithmetic on them.  */
-       wins = 0;
+    default:
+      break;
     }
-  else if (IS_EXPR_CODE_CLASS (kind))
-    {
-      int len = first_rtl_op (code);
-      int i;
-      for (i = 0; i < len; i++)
-       {
-         tree op = TREE_OPERAND (t, i);
-         tree subop;
 
-         if (op == 0)
-           continue;           /* Valid for CALL_EXPR, at least.  */
+  return NULL_TREE;
+}
 
-         /* Strip any conversions that don't change the mode.  This is
-            safe for every expression, except for a comparison expression
-            because its signedness is derived from its operands.  So, in
-            the latter case, only strip conversions that don't change the
-            signedness.
+/* Fold comparison ARG0 CODE ARG1 (with result in TYPE), where for
+   ARG0 just the signedness is changed.  */
 
-            Note that this is done as an internal manipulation within the
-            constant folder, in order to find the simplest representation
-            of the arguments so that their form can be studied.  In any
-            cases, the appropriate type conversions should be put back in
-            the tree that will get out of the constant folder.  */
-         if (kind == '<')
-           STRIP_SIGN_NOPS (op);
-         else
-           STRIP_NOPS (op);
+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 (op) == COMPLEX_CST)
-           subop = TREE_REALPART (op);
-         else
-           subop = op;
+  if (TREE_CODE (arg0) != NOP_EXPR)
+    return NULL_TREE;
 
-         if (TREE_CODE (subop) != INTEGER_CST
-             && TREE_CODE (subop) != REAL_CST)
-           /* Note that TREE_CONSTANT isn't enough:
-              static var addresses are constant but we can't
-              do arithmetic on them.  */
-           wins = 0;
+  outer_type = TREE_TYPE (arg0);
+  arg0_inner = TREE_OPERAND (arg0, 0);
+  inner_type = TREE_TYPE (arg0_inner);
 
-         if (i == 0)
-           arg0 = op;
-         else if (i == 1)
-           arg1 = op;
-       }
+  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);
 
-  /* If this is a commutative operation, and ARG0 is a constant, move it
-     to ARG1 to reduce the number of tests below.  */
-  if (commutative_tree_code (code)
-      && tree_swap_operands_p (arg0, arg1, true))
-    return fold (build2 (code, type, TREE_OPERAND (t, 1),
-                        TREE_OPERAND (t, 0)));
+  return fold (build (code, type, arg0_inner, arg1));
+}
 
-  /* Now WINS is set as described above,
-     ARG0 is the first operand of EXPR,
-     and ARG1 is the second operand (if it has more than one operand).
+/* Tries to replace &a[idx] CODE s * delta with &a[idx CODE delta], if s is
+   step of the array.  ADDR is the address. MULT is the multiplicative expression.
+   If the function succeeds, the new address expression is returned.  Otherwise
+   NULL_TREE is returned.  */
 
-     First check for cases where an arithmetic operation is applied to a
-     compound, conditional, or comparison operation.  Push the arithmetic
-     operation inside the compound or conditional to see if any folding
-     can then be done.  Convert comparison to conditional for this purpose.
-     The also optimizes non-constant cases that used to be done in
-     expand_expr.
+static tree
+try_move_mult_to_index (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;
 
-     Before we do that, see if this is a BIT_AND_EXPR or a BIT_IOR_EXPR,
-     one of the operands is a comparison and the other is a comparison, a
-     BIT_AND_EXPR with the constant 1, or a truth value.  In that case, the
-     code below would make the expression more complex.  Change it to a
-     TRUTH_{AND,OR}_EXPR.  Likewise, convert a similar NE_EXPR to
-     TRUTH_XOR_EXPR and an EQ_EXPR to the inversion of a TRUTH_XOR_EXPR.  */
+  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;
 
-  if ((code == BIT_AND_EXPR || code == BIT_IOR_EXPR
-       || code == EQ_EXPR || code == NE_EXPR)
-      && ((truth_value_p (TREE_CODE (arg0))
-          && (truth_value_p (TREE_CODE (arg1))
-              || (TREE_CODE (arg1) == BIT_AND_EXPR
-                  && integer_onep (TREE_OPERAND (arg1, 1)))))
-         || (truth_value_p (TREE_CODE (arg1))
-             && (truth_value_p (TREE_CODE (arg0))
-                 || (TREE_CODE (arg0) == BIT_AND_EXPR
-                     && integer_onep (TREE_OPERAND (arg0, 1)))))))
+  for (;; ref = TREE_OPERAND (ref, 0))
     {
-      tem = fold (build2 (code == BIT_AND_EXPR ? TRUTH_AND_EXPR
-                         : code == BIT_IOR_EXPR ? TRUTH_OR_EXPR
-                         : TRUTH_XOR_EXPR,
-                         type, fold_convert (boolean_type_node, arg0),
-                         fold_convert (boolean_type_node, arg1)));
+      if (TREE_CODE (ref) == ARRAY_REF)
+       {
+         step = array_ref_element_size (ref);
 
-      if (code == EQ_EXPR)
-       tem = invert_truthvalue (tem);
+         if (TREE_CODE (step) != INTEGER_CST)
+           continue;
 
-      return tem;
+         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 (TREE_TYPE (s)))
+           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;
     }
 
-  if (TREE_CODE_CLASS (code) == '1')
+  /* 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)
     {
-      if (TREE_CODE (arg0) == COMPOUND_EXPR)
-       return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
-                      fold (build1 (code, type, TREE_OPERAND (arg0, 1))));
-      else if (TREE_CODE (arg0) == COND_EXPR)
-       {
-         tree arg01 = TREE_OPERAND (arg0, 1);
-         tree arg02 = TREE_OPERAND (arg0, 2);
-         if (! VOID_TYPE_P (TREE_TYPE (arg01)))
-           arg01 = fold (build1 (code, type, arg01));
-         if (! VOID_TYPE_P (TREE_TYPE (arg02)))
-           arg02 = fold (build1 (code, type, arg02));
-         tem = fold (build3 (COND_EXPR, type, TREE_OPERAND (arg0, 0),
-                             arg01, arg02));
+      pref = TREE_OPERAND (pref, 0);
+      TREE_OPERAND (pos, 0) = copy_node (pref);
+      pos = TREE_OPERAND (pos, 0);
+    }
 
-         /* If this was a conversion, and all we did was to move into
-            inside the COND_EXPR, bring it back out.  But leave it if
-            it is a conversion from integer to integer and the
-            result precision is no wider than a word since such a
-            conversion is cheap and may be optimized away by combine,
-            while it couldn't if it were outside the COND_EXPR.  Then return
-            so we don't get into an infinite recursion loop taking the
-            conversion out and then back in.  */
+  TREE_OPERAND (pos, 1) = fold (build2 (code, itype,
+                                       TREE_OPERAND (pos, 1),
+                                       delta));
 
-         if ((code == NOP_EXPR || code == CONVERT_EXPR
-              || code == NON_LVALUE_EXPR)
+  return build1 (ADDR_EXPR, TREE_TYPE (addr), 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));
+}
+
+/* Fold complex addition when both components are accessible by parts.
+   Return non-null if successful.  CODE should be PLUS_EXPR for addition,
+   or MINUS_EXPR for subtraction.  */
+
+static tree
+fold_complex_add (tree type, tree ac, tree bc, enum tree_code code)
+{
+  tree ar, ai, br, bi, rr, ri, inner_type;
+
+  if (TREE_CODE (ac) == COMPLEX_EXPR)
+    ar = TREE_OPERAND (ac, 0), ai = TREE_OPERAND (ac, 1);
+  else if (TREE_CODE (ac) == COMPLEX_CST)
+    ar = TREE_REALPART (ac), ai = TREE_IMAGPART (ac);
+  else
+    return NULL;
+
+  if (TREE_CODE (bc) == COMPLEX_EXPR)
+    br = TREE_OPERAND (bc, 0), bi = TREE_OPERAND (bc, 1);
+  else if (TREE_CODE (bc) == COMPLEX_CST)
+    br = TREE_REALPART (bc), bi = TREE_IMAGPART (bc);
+  else
+    return NULL;
+
+  inner_type = TREE_TYPE (type);
+
+  rr = fold (build2 (code, inner_type, ar, br));  
+  ri = fold (build2 (code, inner_type, ai, bi));  
+
+  return fold (build2 (COMPLEX_EXPR, type, rr, ri));
+}
+
+/* Perform some simplifications of complex multiplication when one or more
+   of the components are constants or zeros.  Return non-null if successful.  */
+
+tree
+fold_complex_mult_parts (tree type, tree ar, tree ai, tree br, tree bi)
+{
+  tree rr, ri, inner_type, zero;
+  bool ar0, ai0, br0, bi0, bi1;
+
+  inner_type = TREE_TYPE (type);
+  zero = NULL;
+
+  if (SCALAR_FLOAT_TYPE_P (inner_type))
+    {
+      ar0 = ai0 = br0 = bi0 = bi1 = false;
+
+      /* We're only interested in +0.0 here, thus we don't use real_zerop.  */
+
+      if (TREE_CODE (ar) == REAL_CST
+         && REAL_VALUES_IDENTICAL (TREE_REAL_CST (ar), dconst0))
+       ar0 = true, zero = ar;
+
+      if (TREE_CODE (ai) == REAL_CST
+         && REAL_VALUES_IDENTICAL (TREE_REAL_CST (ai), dconst0))
+       ai0 = true, zero = ai;
+
+      if (TREE_CODE (br) == REAL_CST
+         && REAL_VALUES_IDENTICAL (TREE_REAL_CST (br), dconst0))
+       br0 = true, zero = br;
+
+      if (TREE_CODE (bi) == REAL_CST)
+       {
+         if (REAL_VALUES_IDENTICAL (TREE_REAL_CST (bi), dconst0))
+           bi0 = true, zero = bi;
+         else if (REAL_VALUES_IDENTICAL (TREE_REAL_CST (bi), dconst1))
+           bi1 = true;
+       }
+    }
+  else
+    {
+      ar0 = integer_zerop (ar);
+      if (ar0)
+       zero = ar;
+      ai0 = integer_zerop (ai);
+      if (ai0)
+       zero = ai;
+      br0 = integer_zerop (br);
+      if (br0)
+       zero = br;
+      bi0 = integer_zerop (bi);
+      if (bi0)
+       {
+         zero = bi;
+         bi1 = false;
+       }
+      else
+       bi1 = integer_onep (bi);
+    }
+
+  /* We won't optimize anything below unless something is zero.  */
+  if (zero == NULL)
+    return NULL;
+
+  if (ai0 && br0 && bi1)
+    {
+      rr = zero;
+      ri = ar;
+    }
+  else if (ai0 && bi0)
+    {
+      rr = fold (build2 (MULT_EXPR, inner_type, ar, br));
+      ri = zero;
+    }
+  else if (ai0 && br0)
+    {
+      rr = zero;
+      ri = fold (build2 (MULT_EXPR, inner_type, ar, bi));
+    }
+  else if (ar0 && bi0)
+    {
+      rr = zero;
+      ri = fold (build2 (MULT_EXPR, inner_type, ai, br));
+    }
+  else if (ar0 && br0)
+    {
+      rr = fold (build2 (MULT_EXPR, inner_type, ai, bi));
+      rr = fold (build1 (NEGATE_EXPR, inner_type, rr));
+      ri = zero;
+    }
+  else if (bi0)
+    {
+      rr = fold (build2 (MULT_EXPR, inner_type, ar, br));
+      ri = fold (build2 (MULT_EXPR, inner_type, ai, br));
+    }
+  else if (ai0)
+    {
+      rr = fold (build2 (MULT_EXPR, inner_type, ar, br));
+      ri = fold (build2 (MULT_EXPR, inner_type, ar, bi));
+    }
+  else if (br0)
+    {
+      rr = fold (build2 (MULT_EXPR, inner_type, ai, bi));
+      rr = fold (build1 (NEGATE_EXPR, inner_type, rr));
+      ri = fold (build2 (MULT_EXPR, inner_type, ar, bi));
+    }
+  else if (ar0)
+    {
+      rr = fold (build2 (MULT_EXPR, inner_type, ai, bi));
+      rr = fold (build1 (NEGATE_EXPR, inner_type, rr));
+      ri = fold (build2 (MULT_EXPR, inner_type, ai, br));
+    }
+  else
+    return NULL;
+
+  return fold (build2 (COMPLEX_EXPR, type, rr, ri));
+}
+
+static tree
+fold_complex_mult (tree type, tree ac, tree bc)
+{
+  tree ar, ai, br, bi;
+
+  if (TREE_CODE (ac) == COMPLEX_EXPR)
+    ar = TREE_OPERAND (ac, 0), ai = TREE_OPERAND (ac, 1);
+  else if (TREE_CODE (ac) == COMPLEX_CST)
+    ar = TREE_REALPART (ac), ai = TREE_IMAGPART (ac);
+  else
+    return NULL;
+
+  if (TREE_CODE (bc) == COMPLEX_EXPR)
+    br = TREE_OPERAND (bc, 0), bi = TREE_OPERAND (bc, 1);
+  else if (TREE_CODE (bc) == COMPLEX_CST)
+    br = TREE_REALPART (bc), bi = TREE_IMAGPART (bc);
+  else
+    return NULL;
+
+  return fold_complex_mult_parts (type, ar, ai, br, bi);
+}
+
+/* Perform some simplifications of complex division when one or more of
+   the components are constants or zeros.  Return non-null if successful.  */
+
+tree
+fold_complex_div_parts (tree type, tree ar, tree ai, tree br, tree bi,
+                       enum tree_code code)
+{
+  tree rr, ri, inner_type, zero;
+  bool ar0, ai0, br0, bi0, bi1;
+
+  inner_type = TREE_TYPE (type);
+  zero = NULL;
+
+  if (SCALAR_FLOAT_TYPE_P (inner_type))
+    {
+      ar0 = ai0 = br0 = bi0 = bi1 = false;
+
+      /* We're only interested in +0.0 here, thus we don't use real_zerop.  */
+
+      if (TREE_CODE (ar) == REAL_CST
+         && REAL_VALUES_IDENTICAL (TREE_REAL_CST (ar), dconst0))
+       ar0 = true, zero = ar;
+
+      if (TREE_CODE (ai) == REAL_CST
+         && REAL_VALUES_IDENTICAL (TREE_REAL_CST (ai), dconst0))
+       ai0 = true, zero = ai;
+
+      if (TREE_CODE (br) == REAL_CST
+         && REAL_VALUES_IDENTICAL (TREE_REAL_CST (br), dconst0))
+       br0 = true, zero = br;
+
+      if (TREE_CODE (bi) == REAL_CST)
+       {
+         if (REAL_VALUES_IDENTICAL (TREE_REAL_CST (bi), dconst0))
+           bi0 = true, zero = bi;
+         else if (REAL_VALUES_IDENTICAL (TREE_REAL_CST (bi), dconst1))
+           bi1 = true;
+       }
+    }
+  else
+    {
+      ar0 = integer_zerop (ar);
+      if (ar0)
+       zero = ar;
+      ai0 = integer_zerop (ai);
+      if (ai0)
+       zero = ai;
+      br0 = integer_zerop (br);
+      if (br0)
+       zero = br;
+      bi0 = integer_zerop (bi);
+      if (bi0)
+       {
+         zero = bi;
+         bi1 = false;
+       }
+      else
+       bi1 = integer_onep (bi);
+    }
+
+  /* We won't optimize anything below unless something is zero.  */
+  if (zero == NULL)
+    return NULL;
+
+  if (ai0 && bi0)
+    {
+      rr = fold (build2 (code, inner_type, ar, br));
+      ri = zero;
+    }
+  else if (ai0 && br0)
+    {
+      rr = zero;
+      ri = fold (build2 (code, inner_type, ar, bi));
+      ri = fold (build1 (NEGATE_EXPR, inner_type, ri));
+    }
+  else if (ar0 && bi0)
+    {
+      rr = zero;
+      ri = fold (build2 (code, inner_type, ai, br));
+    }
+  else if (ar0 && br0)
+    {
+      rr = fold (build2 (code, inner_type, ai, bi));
+      ri = zero;
+    }
+  else if (bi0)
+    {
+      rr = fold (build2 (code, inner_type, ar, br));
+      ri = fold (build2 (code, inner_type, ai, br));
+    }
+  else if (br0)
+    {
+      rr = fold (build2 (code, inner_type, ai, bi));
+      ri = fold (build2 (code, inner_type, ar, bi));
+      ri = fold (build1 (NEGATE_EXPR, inner_type, ri));
+    }
+  else
+    return NULL;
+
+  return fold (build2 (COMPLEX_EXPR, type, rr, ri));
+}
+
+static tree
+fold_complex_div (tree type, tree ac, tree bc, enum tree_code code)
+{
+  tree ar, ai, br, bi;
+
+  if (TREE_CODE (ac) == COMPLEX_EXPR)
+    ar = TREE_OPERAND (ac, 0), ai = TREE_OPERAND (ac, 1);
+  else if (TREE_CODE (ac) == COMPLEX_CST)
+    ar = TREE_REALPART (ac), ai = TREE_IMAGPART (ac);
+  else
+    return NULL;
+
+  if (TREE_CODE (bc) == COMPLEX_EXPR)
+    br = TREE_OPERAND (bc, 0), bi = TREE_OPERAND (bc, 1);
+  else if (TREE_CODE (bc) == COMPLEX_CST)
+    br = TREE_REALPART (bc), bi = TREE_IMAGPART (bc);
+  else
+    return NULL;
+
+  return fold_complex_div_parts (type, ar, ai, br, bi, code);
+}
+
+/* Fold a unary expression EXPR.  Return the folded expression if
+   folding is successful.  Otherwise, return the original
+   expression.  */
+
+static tree
+fold_unary (tree expr)
+{
+  const tree t = expr;
+  const tree type = TREE_TYPE (expr);
+  tree tem;
+  tree op0, arg0;
+  enum tree_code code = TREE_CODE (t);
+  enum tree_code_class kind = TREE_CODE_CLASS (code);
+
+  gcc_assert (IS_EXPR_CODE_CLASS (kind)
+             && TREE_CODE_LENGTH (code) == 1);
+
+
+  arg0 = op0 = TREE_OPERAND (t, 0);
+  if (arg0)
+    {
+      if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR)
+       {
+         /* Don't use STRIP_NOPS, because signedness of argument type matters.  */
+         STRIP_SIGN_NOPS (arg0);
+       }
+      else
+       {
+         /* Strip any conversions that don't change the mode.  This
+            is safe for every expression, except for a comparison
+            expression because its signedness is derived from its
+            operands.
+
+            Note that this is done as an internal manipulation within
+            the constant folder, in order to find the simplest
+            representation of the arguments so that their form can be
+            studied.  In any cases, the appropriate type conversions
+            should be put back in the tree that will get out of the
+            constant folder.  */
+         STRIP_NOPS (arg0);
+       }
+    }
+
+  if (TREE_CODE_CLASS (code) == tcc_unary)
+    {
+      if (TREE_CODE (arg0) == COMPOUND_EXPR)
+       return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
+                      fold (build1 (code, type, TREE_OPERAND (arg0, 1))));
+      else if (TREE_CODE (arg0) == COND_EXPR)
+       {
+         tree arg01 = TREE_OPERAND (arg0, 1);
+         tree arg02 = TREE_OPERAND (arg0, 2);
+         if (! VOID_TYPE_P (TREE_TYPE (arg01)))
+           arg01 = fold (build1 (code, type, arg01));
+         if (! VOID_TYPE_P (TREE_TYPE (arg02)))
+           arg02 = fold (build1 (code, type, arg02));
+         tem = fold (build3 (COND_EXPR, type, TREE_OPERAND (arg0, 0),
+                             arg01, arg02));
+
+         /* If this was a conversion, and all we did was to move into
+            inside the COND_EXPR, bring it back out.  But leave it if
+            it is a conversion from integer to integer and the
+            result precision is no wider than a word since such a
+            conversion is cheap and may be optimized away by combine,
+            while it couldn't if it were outside the COND_EXPR.  Then return
+            so we don't get into an infinite recursion loop taking the
+            conversion out and then back in.  */
+
+         if ((code == NOP_EXPR || code == CONVERT_EXPR
+              || code == NON_LVALUE_EXPR)
              && TREE_CODE (tem) == COND_EXPR
              && TREE_CODE (TREE_OPERAND (tem, 1)) == code
              && TREE_CODE (TREE_OPERAND (tem, 2)) == code
@@ -6183,10 +6673,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
@@ -6196,7 +6687,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)
            {
@@ -6212,51 +6703,9 @@ fold (tree expr)
                                               integer_zero_node))));
        }
    }
-  else if (TREE_CODE_CLASS (code) == '<'
-          && 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) == '<'
-          && 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) == '<')
-    {
-      if (TREE_CODE (arg0) == COMPOUND_EXPR)
-       return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
-                      fold (build2 (code, type, TREE_OPERAND (arg0, 1),
-                                    arg1)));
-      if (TREE_CODE (arg1) == COMPOUND_EXPR
-         && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
-       return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
-                      fold (build2 (code, type,
-                                    arg0, TREE_OPERAND (arg1, 1))));
-
-      if (TREE_CODE (arg0) == COND_EXPR
-         || TREE_CODE_CLASS (TREE_CODE (arg0)) == '<')
-       {
-         tem = fold_binary_op_with_conditional_arg (code, type, arg0, arg1,
-                                                    /*cond_first_p=*/1);
-         if (tem != NULL_TREE)
-           return tem;
-       }
-
-      if (TREE_CODE (arg1) == COND_EXPR
-         || TREE_CODE_CLASS (TREE_CODE (arg1)) == '<')
-       {
-         tem = fold_binary_op_with_conditional_arg (code, type, arg1, arg0,
-                                                    /*cond_first_p=*/0);
-         if (tem != NULL_TREE)
-           return tem;
-       }
-    }
 
   switch (code)
     {
-    case CONST_DECL:
-      return fold (DECL_INITIAL (t));
-
     case NOP_EXPR:
     case FLOAT_EXPR:
     case CONVERT_EXPR:
@@ -6264,15 +6713,15 @@ fold (tree expr)
     case FIX_CEIL_EXPR:
     case FIX_FLOOR_EXPR:
     case FIX_ROUND_EXPR:
-      if (TREE_TYPE (TREE_OPERAND (t, 0)) == type)
-       return TREE_OPERAND (t, 0);
+      if (TREE_TYPE (op0) == type)
+       return op0;
 
       /* Handle cases of two conversions in a row.  */
-      if (TREE_CODE (TREE_OPERAND (t, 0)) == NOP_EXPR
-         || TREE_CODE (TREE_OPERAND (t, 0)) == CONVERT_EXPR)
+      if (TREE_CODE (op0) == NOP_EXPR
+         || TREE_CODE (op0) == CONVERT_EXPR)
        {
-         tree inside_type = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 0), 0));
-         tree inter_type = TREE_TYPE (TREE_OPERAND (t, 0));
+         tree inside_type = TREE_TYPE (TREE_OPERAND (op0, 0));
+         tree inter_type = TREE_TYPE (op0);
          int inside_int = INTEGRAL_TYPE_P (inside_type);
          int inside_ptr = POINTER_TYPE_P (inside_type);
          int inside_float = FLOAT_TYPE_P (inside_type);
@@ -6296,8 +6745,7 @@ fold (tree expr)
          if (TYPE_MAIN_VARIANT (inside_type) == TYPE_MAIN_VARIANT (type)
              && ((inter_int && final_int) || (inter_float && final_float))
              && inter_prec >= final_prec)
-           return fold (build1 (code, type,
-                                TREE_OPERAND (TREE_OPERAND (t, 0), 0)));
+           return fold (build1 (code, type, TREE_OPERAND (op0, 0)));
 
          /* Likewise, if the intermediate and final types are either both
             float or both integer, we don't need the middle conversion if
@@ -6312,16 +6760,14 @@ fold (tree expr)
              && ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (type))
                    && TYPE_MODE (type) == TYPE_MODE (inter_type))
              && ! final_ptr)
-           return fold (build1 (code, type,
-                                TREE_OPERAND (TREE_OPERAND (t, 0), 0)));
+           return fold (build1 (code, type, TREE_OPERAND (op0, 0)));
 
          /* If we have a sign-extension of a zero-extended value, we can
             replace that by a single zero-extension.  */
          if (inside_int && inter_int && final_int
              && inside_prec < inter_prec && inter_prec < final_prec
              && inside_unsignedp && !inter_unsignedp)
-           return fold (build1 (code, type,
-                                TREE_OPERAND (TREE_OPERAND (t, 0), 0)));
+           return fold (build1 (code, type, TREE_OPERAND (op0, 0)));
 
          /* Two conversions in a row are not needed unless:
             - some conversion is floating-point (overstrict for now), or
@@ -6345,23 +6791,21 @@ fold (tree expr)
              && ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (type))
                    && TYPE_MODE (type) == TYPE_MODE (inter_type))
              && ! final_ptr)
-           return fold (build1 (code, type,
-                                TREE_OPERAND (TREE_OPERAND (t, 0), 0)));
+           return fold (build1 (code, type, TREE_OPERAND (op0, 0)));
        }
 
-      if (TREE_CODE (TREE_OPERAND (t, 0)) == MODIFY_EXPR
-         && TREE_CONSTANT (TREE_OPERAND (TREE_OPERAND (t, 0), 1))
+      if (TREE_CODE (op0) == MODIFY_EXPR
+         && TREE_CONSTANT (TREE_OPERAND (op0, 1))
          /* Detect assigning a bitfield.  */
-         && !(TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 0)) == COMPONENT_REF
-              && DECL_BIT_FIELD (TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (t, 0), 0), 1))))
+         && !(TREE_CODE (TREE_OPERAND (op0, 0)) == COMPONENT_REF
+              && DECL_BIT_FIELD (TREE_OPERAND (TREE_OPERAND (op0, 0), 1))))
        {
          /* Don't leave an assignment inside a conversion
             unless assigning a bitfield.  */
-         tree prev = TREE_OPERAND (t, 0);
          tem = copy_node (t);
-         TREE_OPERAND (tem, 0) = TREE_OPERAND (prev, 1);
+         TREE_OPERAND (tem, 0) = TREE_OPERAND (op0, 1);
          /* First do the assignment, then return converted constant.  */
-         tem = build2 (COMPOUND_EXPR, TREE_TYPE (tem), prev, fold (tem));
+         tem = build2 (COMPOUND_EXPR, TREE_TYPE (tem), op0, fold (tem));
          TREE_NO_WARNING (tem) = 1;
          TREE_USED (tem) = 1;
          return tem;
@@ -6372,10 +6816,10 @@ fold (tree expr)
         in c).  This folds extension into the BIT_AND_EXPR.  */
       if (INTEGRAL_TYPE_P (type)
          && TREE_CODE (type) != BOOLEAN_TYPE
-         && TREE_CODE (TREE_OPERAND (t, 0)) == BIT_AND_EXPR
-         && TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 1)) == INTEGER_CST)
+         && TREE_CODE (op0) == BIT_AND_EXPR
+         && TREE_CODE (TREE_OPERAND (op0, 1)) == INTEGER_CST)
        {
-         tree and = TREE_OPERAND (t, 0);
+         tree and = op0;
          tree and0 = TREE_OPERAND (and, 0), and1 = TREE_OPERAND (and, 1);
          int change = 0;
 
@@ -6395,6 +6839,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))
                {
@@ -6405,20 +6850,25 @@ fold (tree expr)
 #endif
            }
          if (change)
-           return fold (build2 (BIT_AND_EXPR, type,
-                                fold_convert (type, and0),
-                                fold_convert (type, and1)));
+           {
+             tem = build_int_cst_wide (type, TREE_INT_CST_LOW (and1),
+                                       TREE_INT_CST_HIGH (and1));
+             tem = force_fit_type (tem, 0, TREE_OVERFLOW (and1),
+                                   TREE_CONSTANT_OVERFLOW (and1));
+             return fold (build2 (BIT_AND_EXPR, type,
+                                  fold_convert (type, and0), tem));
+           }
        }
 
       /* 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'
+      if (POINTER_TYPE_P (type)
+         && BINARY_CLASS_P (arg0)
          && TREE_CODE (TREE_OPERAND (arg0, 0)) == NOP_EXPR
          && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (arg0, 0))))
        {
          tree arg00 = TREE_OPERAND (arg0, 0);
-         tree t0 = TREE_TYPE (t);
+         tree t0 = type;
          tree t1 = TREE_TYPE (arg00);
          tree tt0 = TREE_TYPE (t0);
          tree tt1 = TREE_TYPE (t1);
@@ -6434,34 +6884,17 @@ fold (tree expr)
       return tem ? tem : t;
 
     case VIEW_CONVERT_EXPR:
-      if (TREE_CODE (TREE_OPERAND (t, 0)) == VIEW_CONVERT_EXPR)
-       return build1 (VIEW_CONVERT_EXPR, type,
-                      TREE_OPERAND (TREE_OPERAND (t, 0), 0));
-      return t;
-
-    case COMPONENT_REF:
-      if (TREE_CODE (arg0) == CONSTRUCTOR
-         && ! type_contains_placeholder_p (TREE_TYPE (arg0)))
-       {
-         tree m = purpose_member (arg1, CONSTRUCTOR_ELTS (arg0));
-         if (m)
-           return TREE_VALUE (m);
-       }
-      return t;
-
-    case RANGE_EXPR:
-      if (TREE_CONSTANT (t) != wins)
-       {
-         tem = copy_node (t);
-         TREE_CONSTANT (tem) = wins;
-         TREE_INVARIANT (tem) = wins;
-         return tem;
-       }
+      if (TREE_CODE (op0) == VIEW_CONVERT_EXPR)
+       return build1 (VIEW_CONVERT_EXPR, type, TREE_OPERAND (op0, 0));
       return t;
 
     case NEGATE_EXPR:
       if (negate_expr_p (arg0))
        return fold_convert (type, negate_expr (arg0));
+      /* Convert - (~A) to A + 1.  */
+      if (INTEGRAL_TYPE_P (type) && TREE_CODE (arg0) == BIT_NOT_EXPR)
+       return fold (build2 (PLUS_EXPR, type, TREE_OPERAND (arg0, 0),
+                            build_int_cst (type, 1)));
       return t;
 
     case ABS_EXPR:
@@ -6481,6 +6914,14 @@ fold (tree expr)
        }
       else if (tree_expr_nonnegative_p (arg0))
        return arg0;
+
+      /* Strip sign ops from argument.  */
+      if (TREE_CODE (type) == REAL_TYPE)
+       {
+         tem = fold_strip_sign_ops (arg0);
+         if (tem)
+           return fold (build1 (ABS_EXPR, type, fold_convert (type, tem)));
+       }
       return t;
 
     case CONJ_EXPR:
@@ -6508,16 +6949,519 @@ fold (tree expr)
         return fold_not_const (arg0, type);
       else if (TREE_CODE (arg0) == BIT_NOT_EXPR)
        return TREE_OPERAND (arg0, 0);
+      /* Convert ~ (-A) to A - 1.  */
+      else if (INTEGRAL_TYPE_P (type) && TREE_CODE (arg0) == NEGATE_EXPR)
+       return fold (build2 (MINUS_EXPR, type, TREE_OPERAND (arg0, 0),
+                            build_int_cst (type, 1)));
+      /* Convert ~ (A - 1) or ~ (A + -1) to -A.  */
+      else if (INTEGRAL_TYPE_P (type)
+              && ((TREE_CODE (arg0) == MINUS_EXPR
+                   && integer_onep (TREE_OPERAND (arg0, 1)))
+                  || (TREE_CODE (arg0) == PLUS_EXPR
+                      && integer_all_onesp (TREE_OPERAND (arg0, 1)))))
+       return fold (build1 (NEGATE_EXPR, type, TREE_OPERAND (arg0, 0)));
       return t;
 
-    case PLUS_EXPR:
-      /* A + (-B) -> A - B */
-      if (TREE_CODE (arg1) == NEGATE_EXPR)
-       return fold (build2 (MINUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0)));
-      /* (-A) + B -> B - A */
-      if (TREE_CODE (arg0) == NEGATE_EXPR
+    case TRUTH_NOT_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,
+        but we don't handle values other than 1 correctly yet.)  */
+      tem = invert_truthvalue (arg0);
+      /* Avoid infinite recursion.  */
+      if (TREE_CODE (tem) == TRUTH_NOT_EXPR)
+       return t;
+      return fold_convert (type, tem);
+
+    case REALPART_EXPR:
+      if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
+       return t;
+      else if (TREE_CODE (arg0) == COMPLEX_EXPR)
+       return omit_one_operand (type, TREE_OPERAND (arg0, 0),
+                                TREE_OPERAND (arg0, 1));
+      else if (TREE_CODE (arg0) == COMPLEX_CST)
+       return TREE_REALPART (arg0);
+      else if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
+       return fold (build2 (TREE_CODE (arg0), type,
+                            fold (build1 (REALPART_EXPR, type,
+                                          TREE_OPERAND (arg0, 0))),
+                            fold (build1 (REALPART_EXPR, type,
+                                          TREE_OPERAND (arg0, 1)))));
+      return t;
+
+    case IMAGPART_EXPR:
+      if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
+       return fold_convert (type, integer_zero_node);
+      else if (TREE_CODE (arg0) == COMPLEX_EXPR)
+       return omit_one_operand (type, TREE_OPERAND (arg0, 1),
+                                TREE_OPERAND (arg0, 0));
+      else if (TREE_CODE (arg0) == COMPLEX_CST)
+       return TREE_IMAGPART (arg0);
+      else if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
+       return fold (build2 (TREE_CODE (arg0), type,
+                            fold (build1 (IMAGPART_EXPR, type,
+                                          TREE_OPERAND (arg0, 0))),
+                            fold (build1 (IMAGPART_EXPR, type,
+                                          TREE_OPERAND (arg0, 1)))));
+      return t;
+
+    default:
+      return t;
+    } /* switch (code) */
+}
+
+/* Fold a ternary expression EXPR.  Return the folded expression if
+   folding is successful.  Otherwise, return the original
+   expression.  */
+
+static tree
+fold_ternary (tree expr)
+{
+  const tree t = expr;
+  const tree type = TREE_TYPE (expr);
+  tree tem;
+  tree arg0 = NULL_TREE, arg1 = NULL_TREE;
+  enum tree_code code = TREE_CODE (t);
+  enum tree_code_class kind = TREE_CODE_CLASS (code);
+  int i;
+
+  gcc_assert (IS_EXPR_CODE_CLASS (kind)
+             && TREE_CODE_LENGTH (code) == 3);
+
+  /* For now, we iterate only twice even though we are handling
+     ternary expressions.  This is because we haven't defined arg2
+     yet.  */
+  for (i = 0; i < 2; i++)
+    {
+      tree op = TREE_OPERAND (t, i);
+
+      if (op == 0)
+       continue;               /* Valid for CALL_EXPR, at least.  */
+
+      /* Strip any conversions that don't change the mode.  This is
+        safe for every expression, except for a comparison expression
+        because its signedness is derived from its operands.  So, in
+        the latter case, only strip conversions that don't change the
+        signedness.
+
+        Note that this is done as an internal manipulation within the
+        constant folder, in order to find the simplest representation
+        of the arguments so that their form can be studied.  In any
+        cases, the appropriate type conversions should be put back in
+        the tree that will get out of the constant folder.  */
+      STRIP_NOPS (op);
+
+      if (i == 0)
+       arg0 = op;
+      else if (i == 1)
+       arg1 = op;
+    }
+
+  switch (code)
+    {
+    case COMPONENT_REF:
+      if (TREE_CODE (arg0) == CONSTRUCTOR
+         && ! type_contains_placeholder_p (TREE_TYPE (arg0)))
+       {
+         tree m = purpose_member (arg1, CONSTRUCTOR_ELTS (arg0));
+         if (m)
+           return TREE_VALUE (m);
+       }
+      return t;
+
+    case COND_EXPR:
+      /* Pedantic ANSI C says that a conditional expression is never an lvalue,
+        so all simple results must be passed through pedantic_non_lvalue.  */
+      if (TREE_CODE (arg0) == INTEGER_CST)
+       {
+         tem = TREE_OPERAND (t, (integer_zerop (arg0) ? 2 : 1));
+         /* Only optimize constant conditions when the selected branch
+            has the same type as the COND_EXPR.  This avoids optimizing
+            away "c ? x : throw", where the throw has a void type.  */
+         if (! VOID_TYPE_P (TREE_TYPE (tem))
+             || VOID_TYPE_P (type))
+           return pedantic_non_lvalue (tem);
+         return t;
+       }
+      if (operand_equal_p (arg1, TREE_OPERAND (t, 2), 0))
+       return pedantic_omit_one_operand (type, arg1, arg0);
+
+      /* 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.
+
+         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))))
+       {
+         tem = fold_cond_expr_with_comparison (type, arg0,
+                                               TREE_OPERAND (t, 1),
+                                               TREE_OPERAND (t, 2));
+         if (tem)
+           return tem;
+       }
+
+      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))
+           {
+             tem = fold_cond_expr_with_comparison (type, tem,
+                                                   TREE_OPERAND (t, 2),
+                                                   TREE_OPERAND (t, 1));
+             if (tem)
+               return tem;
+           }
+       }
+
+      /* If the second operand is simpler than the third, swap them
+        since that produces better jump optimization results.  */
+      if (tree_swap_operands_p (TREE_OPERAND (t, 1),
+                               TREE_OPERAND (t, 2), false))
+       {
+         /* See if this can be inverted.  If it can't, possibly because
+            it was a floating-point inequality comparison, don't do
+            anything.  */
+         tem = invert_truthvalue (arg0);
+
+         if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
+           return fold (build3 (code, type, tem,
+                                TREE_OPERAND (t, 2), TREE_OPERAND (t, 1)));
+       }
+
+      /* Convert A ? 1 : 0 to simply A.  */
+      if (integer_onep (TREE_OPERAND (t, 1))
+         && integer_zerop (TREE_OPERAND (t, 2))
+         /* If we try to convert TREE_OPERAND (t, 0) to our type, the
+            call to fold will try to move the conversion inside
+            a COND, which will recurse.  In that case, the COND_EXPR
+            is probably the best choice, so leave it alone.  */
+         && type == TREE_TYPE (arg0))
+       return pedantic_non_lvalue (arg0);
+
+      /* Convert A ? 0 : 1 to !A.  This prefers the use of NOT_EXPR
+        over COND_EXPR in cases such as floating point comparisons.  */
+      if (integer_zerop (TREE_OPERAND (t, 1))
+         && integer_onep (TREE_OPERAND (t, 2))
+         && truth_value_p (TREE_CODE (arg0)))
+       return pedantic_non_lvalue (fold_convert (type,
+                                                 invert_truthvalue (arg0)));
+
+      /* 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))
+         && integer_pow2p (arg1)
+         && TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_AND_EXPR
+         && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1),
+                             arg1, OEP_ONLY_CONST))
+       return pedantic_non_lvalue (fold_convert (type,
+                                                 TREE_OPERAND (arg0, 0)));
+
+      /* Convert A ? B : 0 into A && B if A and B are truth values.  */
+      if (integer_zerop (TREE_OPERAND (t, 2))
+         && truth_value_p (TREE_CODE (arg0))
+         && truth_value_p (TREE_CODE (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))
+         && truth_value_p (TREE_CODE (arg0))
+         && truth_value_p (TREE_CODE (arg1)))
+       {
+         /* Only perform transformation if ARG0 is easily inverted.  */
+         tem = invert_truthvalue (arg0);
+         if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
+           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 CALL_EXPR:
+      /* Check for a built-in function.  */
+      if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
+         && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 0))
+             == FUNCTION_DECL)
+         && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
+       {
+         tree tmp = fold_builtin (t, false);
+         if (tmp)
+           return tmp;
+       }
+      return t;
+
+    default:
+      return t;
+    } /* switch (code) */
+}
+
+/* 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.
+   NOP_EXPR conversions may be removed freely (as long as we
+   are careful not to change the type of the overall expression).
+   We cannot simplify through a CONVERT_EXPR, FIX_EXPR or FLOAT_EXPR,
+   but we can constant-fold them if they have constant operands.  */
+
+#ifdef ENABLE_FOLD_CHECKING
+# define fold(x) fold_1 (x)
+static tree fold_1 (tree);
+static
+#endif
+tree
+fold (tree expr)
+{
+  const tree t = expr;
+  const tree type = TREE_TYPE (expr);
+  tree t1 = NULL_TREE;
+  tree tem;
+  tree arg0 = NULL_TREE, arg1 = NULL_TREE;
+  enum tree_code code = TREE_CODE (t);
+  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;
+
+  /* Return right away if a constant.  */
+  if (kind == tcc_constant)
+    return t;
+
+  if (IS_EXPR_CODE_CLASS (kind))
+    {
+      switch (TREE_CODE_LENGTH (code))
+       {
+       case 1:
+         return fold_unary (expr);
+       case 3:
+         return fold_ternary (expr);
+       default:
+         break;
+       }
+    }
+
+  if (IS_EXPR_CODE_CLASS (kind))
+    {
+      int len = TREE_CODE_LENGTH (code);
+      int i;
+      for (i = 0; i < len; i++)
+       {
+         tree op = TREE_OPERAND (t, i);
+         tree subop;
+
+         if (op == 0)
+           continue;           /* Valid for CALL_EXPR, at least.  */
+
+         /* Strip any conversions that don't change the mode.  This is
+            safe for every expression, except for a comparison expression
+            because its signedness is derived from its operands.  So, in
+            the latter case, only strip conversions that don't change the
+            signedness.
+
+            Note that this is done as an internal manipulation within the
+            constant folder, in order to find the simplest representation
+            of the arguments so that their form can be studied.  In any
+            cases, the appropriate type conversions should be put back in
+            the tree that will get out of the constant folder.  */
+         if (kind == tcc_comparison)
+           STRIP_SIGN_NOPS (op);
+         else
+           STRIP_NOPS (op);
+
+         if (TREE_CODE (op) == COMPLEX_CST)
+           subop = TREE_REALPART (op);
+         else
+           subop = op;
+
+         if (TREE_CODE (subop) != INTEGER_CST
+             && TREE_CODE (subop) != REAL_CST)
+           /* Note that TREE_CONSTANT isn't enough:
+              static var addresses are constant but we can't
+              do arithmetic on them.  */
+           wins = 0;
+
+         if (i == 0)
+           arg0 = op;
+         else if (i == 1)
+           arg1 = op;
+       }
+    }
+
+  /* If this is a commutative operation, and ARG0 is a constant, move it
+     to ARG1 to reduce the number of tests below.  */
+  if (commutative_tree_code (code)
+      && tree_swap_operands_p (arg0, arg1, true))
+    return fold (build2 (code, type, TREE_OPERAND (t, 1),
+                        TREE_OPERAND (t, 0)));
+
+  /* Now WINS is set as described above,
+     ARG0 is the first operand of EXPR,
+     and ARG1 is the second operand (if it has more than one operand).
+
+     First check for cases where an arithmetic operation is applied to a
+     compound, conditional, or comparison operation.  Push the arithmetic
+     operation inside the compound or conditional to see if any folding
+     can then be done.  Convert comparison to conditional for this purpose.
+     The also optimizes non-constant cases that used to be done in
+     expand_expr.
+
+     Before we do that, see if this is a BIT_AND_EXPR or a BIT_IOR_EXPR,
+     one of the operands is a comparison and the other is a comparison, a
+     BIT_AND_EXPR with the constant 1, or a truth value.  In that case, the
+     code below would make the expression more complex.  Change it to a
+     TRUTH_{AND,OR}_EXPR.  Likewise, convert a similar NE_EXPR to
+     TRUTH_XOR_EXPR and an EQ_EXPR to the inversion of a TRUTH_XOR_EXPR.  */
+
+  if ((code == BIT_AND_EXPR || code == BIT_IOR_EXPR
+       || code == EQ_EXPR || code == NE_EXPR)
+      && ((truth_value_p (TREE_CODE (arg0))
+          && (truth_value_p (TREE_CODE (arg1))
+              || (TREE_CODE (arg1) == BIT_AND_EXPR
+                  && integer_onep (TREE_OPERAND (arg1, 1)))))
+         || (truth_value_p (TREE_CODE (arg1))
+             && (truth_value_p (TREE_CODE (arg0))
+                 || (TREE_CODE (arg0) == BIT_AND_EXPR
+                     && integer_onep (TREE_OPERAND (arg0, 1)))))))
+    {
+      tem = fold (build2 (code == BIT_AND_EXPR ? TRUTH_AND_EXPR
+                         : code == BIT_IOR_EXPR ? TRUTH_OR_EXPR
+                         : TRUTH_XOR_EXPR,
+                         type, fold_convert (boolean_type_node, arg0),
+                         fold_convert (boolean_type_node, arg1)));
+
+      if (code == EQ_EXPR)
+       tem = invert_truthvalue (tem);
+
+      return tem;
+    }
+
+  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) == 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) == tcc_binary
+          || TREE_CODE_CLASS (code) == tcc_comparison)
+    {
+      if (TREE_CODE (arg0) == COMPOUND_EXPR)
+       return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
+                      fold (build2 (code, type, TREE_OPERAND (arg0, 1),
+                                    arg1)));
+      if (TREE_CODE (arg1) == COMPOUND_EXPR
+         && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
+       return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
+                      fold (build2 (code, type,
+                                    arg0, TREE_OPERAND (arg1, 1))));
+
+      if (TREE_CODE (arg0) == COND_EXPR || COMPARISON_CLASS_P (arg0))
+       {
+         tem = fold_binary_op_with_conditional_arg (t, code, arg0, arg1, 
+                                                    /*cond_first_p=*/1);
+         if (tem != NULL_TREE)
+           return tem;
+       }
+
+      if (TREE_CODE (arg1) == COND_EXPR || COMPARISON_CLASS_P (arg1))
+       {
+         tem = fold_binary_op_with_conditional_arg (t, code, arg1, arg0, 
+                                                    /*cond_first_p=*/0);
+         if (tem != NULL_TREE)
+           return tem;
+       }
+    }
+
+  switch (code)
+    {
+    case CONST_DECL:
+      return fold (DECL_INITIAL (t));
+
+    case RANGE_EXPR:
+      if (TREE_CONSTANT (t) != wins)
+       {
+         tem = copy_node (t);
+         TREE_CONSTANT (tem) = wins;
+         TREE_INVARIANT (tem) = wins;
+         return tem;
+       }
+      return t;
+
+    case PLUS_EXPR:
+      /* A + (-B) -> A - B */
+      if (TREE_CODE (arg1) == NEGATE_EXPR)
+       return fold (build2 (MINUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0)));
+      /* (-A) + B -> B - A */
+      if (TREE_CODE (arg0) == NEGATE_EXPR
          && reorder_operands_p (TREE_OPERAND (arg0, 0), arg1))
        return fold (build2 (MINUS_EXPR, type, arg1, TREE_OPERAND (arg0, 0)));
+
+      if (TREE_CODE (type) == COMPLEX_TYPE)
+       {
+         tem = fold_complex_add (type, arg0, arg1, PLUS_EXPR);
+         if (tem)
+           return tem;
+       }
+
       if (! FLOAT_TYPE_P (type))
        {
          if (integer_zerop (arg1))
@@ -6542,17 +7486,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);
@@ -6560,7 +7508,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))),
@@ -6568,10 +7516,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)
@@ -6623,7 +7572,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;
                    }
@@ -6632,9 +7582,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 (PLUS_EXPR, arg0, arg1);
+             if (tem)
+               return fold_convert (type, fold (tem));
+           }
+         else if (TREE_CODE (arg1) == ADDR_EXPR
+                  && TREE_CODE (arg0) == MULT_EXPR)
+           {
+             tem = try_move_mult_to_index (PLUS_EXPR, arg1, arg0);
+             if (tem)
+               return fold_convert (type, fold (tem));
+           }
        }
       else
        {
@@ -6713,7 +7682,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)
@@ -6728,7 +7697,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)
@@ -6924,6 +7893,13 @@ fold (tree expr)
        return fold (build2 (MINUS_EXPR, type, negate_expr (arg1),
                             TREE_OPERAND (arg0, 0)));
 
+      if (TREE_CODE (type) == COMPLEX_TYPE)
+       {
+         tem = fold_complex_add (type, arg0, arg1, MINUS_EXPR);
+         if (tem)
+           return tem;
+       }
+
       if (! FLOAT_TYPE_P (type))
        {
          if (! wins && integer_zerop (arg0))
@@ -6996,9 +7972,30 @@ fold (tree expr)
              || (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 (MINUS_EXPR, arg0, arg1);
+         if (tem)
+           return fold_convert (type, 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),
@@ -7031,6 +8028,13 @@ fold (tree expr)
                             negate_expr (arg0),
                             TREE_OPERAND (arg1, 0)));
 
+      if (TREE_CODE (type) == COMPLEX_TYPE)
+       {
+         tem = fold_complex_mult (type, arg0, arg1);
+         if (tem)
+           return tem;
+       }
+
       if (! FLOAT_TYPE_P (type))
        {
          if (integer_zerop (arg1))
@@ -7088,6 +8092,17 @@ fold (tree expr)
                                     TREE_OPERAND (arg0, 1)));
            }
 
+          /* Strip sign operations from X in X*X, i.e. -Y*-Y -> Y*Y.  */
+         if (operand_equal_p (arg0, arg1, 0))
+           {
+             tree tem = fold_strip_sign_ops (arg0);
+             if (tem != NULL_TREE)
+               {
+                 tem = fold_convert (type, tem);
+                 return fold (build2 (MULT_EXPR, type, tem, tem));
+               }
+           }
+
          if (flag_unsafe_math_optimizations)
            {
              enum built_in_function fcode0 = builtin_mathfn_code (arg0);
@@ -7257,8 +8272,7 @@ fold (tree expr)
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
        {
-         t1 = build_int_2 (-1, -1);
-         TREE_TYPE (t1) = type;
+         t1 = build_int_cst (type, -1);
          t1 = force_fit_type (t1, 0, false, false);
          return omit_one_operand (type, t1, arg1);
        }
@@ -7267,8 +8281,7 @@ fold (tree expr)
       if (TREE_CODE (arg1) == BIT_NOT_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
        {
-         t1 = build_int_2 (-1, -1);
-         TREE_TYPE (t1) = type;
+         t1 = build_int_cst (type, -1);
          t1 = force_fit_type (t1, 0, false, false);
          return omit_one_operand (type, t1, arg0);
        }
@@ -7308,8 +8321,7 @@ fold (tree expr)
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
        {
-         t1 = build_int_2 (-1, -1);
-         TREE_TYPE (t1) = type;
+         t1 = build_int_cst (type, -1);
          t1 = force_fit_type (t1, 0, false, false);
          return omit_one_operand (type, t1, arg1);
        }
@@ -7318,8 +8330,7 @@ fold (tree expr)
       if (TREE_CODE (arg1) == BIT_NOT_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
        {
-         t1 = build_int_2 (-1, -1);
-         TREE_TYPE (t1) = type;
+         t1 = build_int_cst (type, -1);
          t1 = force_fit_type (t1, 0, false, false);
          return omit_one_operand (type, t1, arg0);
        }
@@ -7474,6 +8485,13 @@ fold (tree expr)
                                 TREE_OPERAND (arg1, 0)));
        }
 
+      if (TREE_CODE (type) == COMPLEX_TYPE)
+       {
+         tem = fold_complex_div (type, arg0, arg1, code);
+         if (tem)
+           return tem;
+       }
+
       if (flag_unsafe_math_optimizations)
        {
          enum built_in_function fcode = builtin_mathfn_code (arg1);
@@ -7598,17 +8616,33 @@ fold (tree expr)
                                         code, NULL_TREE)))
        return fold_convert (type, tem);
 
+      if (TREE_CODE (type) == COMPLEX_TYPE)
+       {
+         tem = fold_complex_div (type, arg0, arg1, code);
+         if (tem)
+           return tem;
+       }
       goto binary;
 
     case CEIL_MOD_EXPR:
     case FLOOR_MOD_EXPR:
     case ROUND_MOD_EXPR:
     case TRUNC_MOD_EXPR:
+      /* X % 1 is always zero, but be sure to preserve any side
+        effects in X.  */
       if (integer_onep (arg1))
        return omit_one_operand (type, integer_zero_node, arg0);
+
+      /* X % 0, return X % 0 unchanged so that we can get the
+        proper warnings and errors.  */
       if (integer_zerop (arg1))
        return t;
 
+      /* 0 % X is always zero, but be sure to preserve any side
+        effects in X.  Place this after checking for X == 0.  */
+      if (integer_zerop (arg0))
+       return omit_one_operand (type, integer_zero_node, arg1);
+
       /* X % -1 is zero.  */
       if (!TYPE_UNSIGNED (type)
          && TREE_CODE (arg1) == INTEGER_CST
@@ -7639,8 +8673,7 @@ fold (tree expr)
              low = ((unsigned HOST_WIDE_INT) 1 << l) - 1;
            }
 
-         mask = build_int_2 (low, high);
-         TREE_TYPE (mask) = type;
+         mask = build_int_cst_wide (type, low, high);
          return fold (build2 (BIT_AND_EXPR, type,
                               fold_convert (type, arg0), mask));
        }
@@ -7698,7 +8731,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));
@@ -7749,26 +8783,6 @@ fold (tree expr)
        return omit_one_operand (type, arg1, arg0);
       goto associate;
 
-    case TRUTH_NOT_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,
-        but we don't handle values other than 1 correctly yet.)  */
-      tem = invert_truthvalue (arg0);
-      /* Avoid infinite recursion.  */
-      if (TREE_CODE (tem) == TRUTH_NOT_EXPR)
-       {
-         tem = fold_single_bit_test (code, arg0, arg1, type);
-         if (tem)
-           return tem;
-         return t;
-       }
-      return fold_convert (type, tem);
-
     case TRUTH_ANDIF_EXPR:
       /* Note that the operands of this must be ints
         and their values must be 0 or 1.
@@ -7802,6 +8816,22 @@ fold (tree 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)
@@ -7963,6 +8993,33 @@ fold (tree expr)
                                      ? code == EQ_EXPR : code != EQ_EXPR,
                                      type);
 
+      /* If this is a comparison of two exprs that look like an
+        ARRAY_REF of the same object, then we can fold this to a
+        comparison of the two offsets.  */
+      if (COMPARISON_CLASS_P (t))
+       {
+         tree base0, offset0, base1, offset1;
+
+         if (extract_array_ref (arg0, &base0, &offset0)
+             && extract_array_ref (arg1, &base1, &offset1)
+             && operand_equal_p (base0, base1, 0))
+           {
+             if (offset0 == NULL_TREE
+                 && offset1 == NULL_TREE)
+               {
+                 offset0 = integer_zero_node;
+                 offset1 = integer_zero_node;
+               }
+             else if (offset0 == NULL_TREE)
+               offset0 = build_int_cst (TREE_TYPE (offset1), 0);
+             else if (offset1 == NULL_TREE)
+               offset1 = build_int_cst (TREE_TYPE (offset0), 0);
+
+             if (TREE_TYPE (offset0) == TREE_TYPE (offset1))
+               return fold (build2 (code, type, offset0, offset1));
+           }
+       }
+
       if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
        {
          tree targ0 = strip_float_extensions (arg0);
@@ -8115,8 +9172,8 @@ fold (tree expr)
                  || 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));
@@ -8152,36 +9209,64 @@ fold (tree expr)
       /* Comparisons with the highest or lowest possible integer of
         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)));
 
        if (TREE_CODE (arg1) == INTEGER_CST
            && ! TREE_CONSTANT_OVERFLOW (arg1)
-           && width <= HOST_BITS_PER_WIDE_INT
+           && width <= 2 * HOST_BITS_PER_WIDE_INT
            && (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
                || POINTER_TYPE_P (TREE_TYPE (arg1))))
          {
-           unsigned HOST_WIDE_INT signed_max;
-           unsigned HOST_WIDE_INT max, min;
+           HOST_WIDE_INT signed_max_hi;
+           unsigned HOST_WIDE_INT signed_max_lo;
+           unsigned HOST_WIDE_INT max_hi, max_lo, min_hi, min_lo;
 
-           signed_max = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1;
-
-           if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
+           if (width <= HOST_BITS_PER_WIDE_INT)
              {
-               max = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
-               min = 0;
+               signed_max_lo = ((unsigned HOST_WIDE_INT) 1 << (width - 1))
+                               - 1;
+               signed_max_hi = 0;
+               max_hi = 0;
+
+               if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
+                 {
+                   max_lo = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
+                   min_lo = 0;
+                   min_hi = 0;
+                 }
+               else
+                 {
+                   max_lo = signed_max_lo;
+                   min_lo = ((unsigned HOST_WIDE_INT) -1 << (width - 1));
+                   min_hi = -1;
+                 }
              }
            else
              {
-               max = signed_max;
-               min = ((unsigned HOST_WIDE_INT) -1 << (width - 1));
+               width -= HOST_BITS_PER_WIDE_INT;
+               signed_max_lo = -1;
+               signed_max_hi = ((unsigned HOST_WIDE_INT) 1 << (width - 1))
+                               - 1;
+               max_lo = -1;
+               min_lo = 0;
+
+               if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
+                 {
+                   max_hi = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
+                   min_hi = 0;
+                 }
+               else
+                 {
+                   max_hi = signed_max_hi;
+                   min_hi = ((unsigned HOST_WIDE_INT) -1 << (width - 1));
+                 }
              }
 
-           if (TREE_INT_CST_HIGH (arg1) == 0
-               && TREE_INT_CST_LOW (arg1) == max)
+           if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1) == max_hi
+               && TREE_INT_CST_LOW (arg1) == max_lo)
              switch (code)
                {
                case GT_EXPR:
@@ -8202,8 +9287,9 @@ fold (tree expr)
                default:
                  break;
                }
-           else if (TREE_INT_CST_HIGH (arg1) == 0
-                    && TREE_INT_CST_LOW (arg1) == max - 1)
+           else if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1)
+                    == max_hi
+                    && TREE_INT_CST_LOW (arg1) == max_lo - 1)
              switch (code)
                {
                case GT_EXPR:
@@ -8215,8 +9301,9 @@ fold (tree expr)
                default:
                  break;
                }
-           else if (TREE_INT_CST_HIGH (arg1) == (min ? -1 : 0)
-                    && TREE_INT_CST_LOW (arg1) == min)
+           else if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1)
+                    == min_hi
+                    && TREE_INT_CST_LOW (arg1) == min_lo)
              switch (code)
                {
                case LT_EXPR:
@@ -8234,8 +9321,9 @@ fold (tree expr)
                default:
                  break;
                }
-           else if (TREE_INT_CST_HIGH (arg1) == (min ? -1 : 0)
-                    && TREE_INT_CST_LOW (arg1) == min + 1)
+           else if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1)
+                    == min_hi
+                    && TREE_INT_CST_LOW (arg1) == min_lo + 1)
              switch (code)
                {
                case GE_EXPR:
@@ -8249,8 +9337,8 @@ fold (tree expr)
                }
 
            else if (!in_gimple_form
-                    && TREE_INT_CST_HIGH (arg1) == 0
-                    && TREE_INT_CST_LOW (arg1) == signed_max
+                    && TREE_INT_CST_HIGH (arg1) == signed_max_hi
+                    && TREE_INT_CST_LOW (arg1) == signed_max_lo
                     && TYPE_UNSIGNED (TREE_TYPE (arg1))
                     /* signed_type does not work on pointer types.  */
                     && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
@@ -8301,21 +9389,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.  */
@@ -8342,6 +9430,26 @@ fold (tree expr)
                             build2 (LE_EXPR, type,
                                     TREE_OPERAND (arg0, 0), arg1)));
 
+      /* Convert ABS_EXPR<x> >= 0 to true.  */
+      else if (code == GE_EXPR
+              && tree_expr_nonnegative_p (arg0)
+              && (integer_zerop (arg1)
+                  || (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))
+                       && real_zerop (arg1))))
+       return omit_one_operand (type, integer_one_node, arg0);
+
+      /* Convert ABS_EXPR<x> < 0 to false.  */
+      else if (code == LT_EXPR
+              && tree_expr_nonnegative_p (arg0)
+              && (integer_zerop (arg1) || real_zerop (arg1)))
+       return omit_one_operand (type, integer_zero_node, arg0);
+
+      /* Convert ABS_EXPR<x> == 0 or ABS_EXPR<x> != 0 to x == 0 or x != 0.  */
+      else if ((code == EQ_EXPR || code == NE_EXPR)
+              && TREE_CODE (arg0) == ABS_EXPR
+              && (integer_zerop (arg1) || real_zerop (arg1)))
+       return fold (build2 (code, type, TREE_OPERAND (arg0, 0), arg1));
+
       /* If this is an EQ or NE comparison with zero and ARG0 is
         (1 << foo) & bar, convert it to (bar >> foo) & 1.  Both require
         two operations, but the latter can be done in one less insn
@@ -8427,11 +9535,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);
@@ -8444,10 +9552,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);
@@ -8508,7 +9615,7 @@ fold (tree expr)
            case LT_EXPR:
              return constant_boolean_node (0, type);
            default:
-             abort ();
+             gcc_unreachable ();
            }
        }
 
@@ -8672,8 +9779,7 @@ fold (tree expr)
          tree arglist;
 
          if (fndecl
-             && DECL_BUILT_IN (fndecl)
-             && DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_MD
+             && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
              && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRLEN
              && (arglist = TREE_OPERAND (arg0, 1))
              && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE
@@ -8687,7 +9793,8 @@ fold (tree expr)
 
       /* We can fold X/C1 op C2 where C1 and C2 are integer constants
         into a single range test.  */
-      if (TREE_CODE (arg0) == TRUNC_DIV_EXPR
+      if ((TREE_CODE (arg0) == TRUNC_DIV_EXPR
+          || TREE_CODE (arg0) == EXACT_DIV_EXPR)
          && TREE_CODE (arg1) == INTEGER_CST
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
          && !integer_zerop (TREE_OPERAND (arg0, 1))
@@ -8764,171 +9871,10 @@ fold (tree expr)
        if (TYPE_PRECISION (TREE_TYPE (targ1)) > TYPE_PRECISION (newtype))
          newtype = TREE_TYPE (targ1);
 
-       if (TYPE_PRECISION (newtype) < TYPE_PRECISION (TREE_TYPE (arg0)))
-         return fold (build2 (code, type, fold_convert (newtype, targ0),
-                              fold_convert (newtype, targ1)));
-      }
-
-      return t;
-
-    case COND_EXPR:
-      /* Pedantic ANSI C says that a conditional expression is never an lvalue,
-        so all simple results must be passed through pedantic_non_lvalue.  */
-      if (TREE_CODE (arg0) == INTEGER_CST)
-       {
-         tem = TREE_OPERAND (t, (integer_zerop (arg0) ? 2 : 1));
-         /* Only optimize constant conditions when the selected branch
-            has the same type as the COND_EXPR.  This avoids optimizing
-            away "c ? x : throw", where the throw has a void type.  */
-         if (! VOID_TYPE_P (TREE_TYPE (tem))
-             || VOID_TYPE_P (type))
-           return pedantic_non_lvalue (tem);
-         return t;
-       }
-      if (operand_equal_p (arg1, TREE_OPERAND (t, 2), 0))
-       return pedantic_omit_one_operand (type, arg1, arg0);
-
-      /* 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.
-
-         Also try swapping the arguments and inverting the conditional.  */
-      if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
-         && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
-                                            arg1, TREE_OPERAND (arg0, 1))
-         && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
-       {
-         tem = fold_cond_expr_with_comparison (type, arg0,
-                                               TREE_OPERAND (t, 1),
-                                               TREE_OPERAND (t, 2));
-         if (tem)
-           return tem;
-       }
-
-      if (TREE_CODE_CLASS (TREE_CODE (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 (TREE_CODE_CLASS (TREE_CODE (tem)) == '<')
-           {
-             tem = fold_cond_expr_with_comparison (type, tem,
-                                                   TREE_OPERAND (t, 2),
-                                                   TREE_OPERAND (t, 1));
-             if (tem)
-               return tem;
-           }
-       }
-
-      /* If the second operand is simpler than the third, swap them
-        since that produces better jump optimization results.  */
-      if (tree_swap_operands_p (TREE_OPERAND (t, 1),
-                               TREE_OPERAND (t, 2), false))
-       {
-         /* See if this can be inverted.  If it can't, possibly because
-            it was a floating-point inequality comparison, don't do
-            anything.  */
-         tem = invert_truthvalue (arg0);
-
-         if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
-           return fold (build3 (code, type, tem,
-                                TREE_OPERAND (t, 2), TREE_OPERAND (t, 1)));
-       }
-
-      /* Convert A ? 1 : 0 to simply A.  */
-      if (integer_onep (TREE_OPERAND (t, 1))
-         && integer_zerop (TREE_OPERAND (t, 2))
-         /* If we try to convert TREE_OPERAND (t, 0) to our type, the
-            call to fold will try to move the conversion inside
-            a COND, which will recurse.  In that case, the COND_EXPR
-            is probably the best choice, so leave it alone.  */
-         && type == TREE_TYPE (arg0))
-       return pedantic_non_lvalue (arg0);
-
-      /* Convert A ? 0 : 1 to !A.  This prefers the use of NOT_EXPR
-        over COND_EXPR in cases such as floating point comparisons.  */
-      if (integer_zerop (TREE_OPERAND (t, 1))
-         && integer_onep (TREE_OPERAND (t, 2))
-         && truth_value_p (TREE_CODE (arg0)))
-       return pedantic_non_lvalue (fold_convert (type,
-                                                 invert_truthvalue (arg0)));
-
-      /* 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
-              && (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))
-         && integer_pow2p (arg1)
-         && TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_AND_EXPR
-         && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1),
-                             arg1, OEP_ONLY_CONST))
-       return pedantic_non_lvalue (fold_convert (type,
-                                                 TREE_OPERAND (arg0, 0)));
-
-      /* Convert A ? B : 0 into A && B if A and B are truth values.  */
-      if (integer_zerop (TREE_OPERAND (t, 2))
-         && truth_value_p (TREE_CODE (arg0))
-         && truth_value_p (TREE_CODE (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))
-         && truth_value_p (TREE_CODE (arg0))
-         && truth_value_p (TREE_CODE (arg1)))
-       {
-         /* Only perform transformation if ARG0 is easily inverted.  */
-         tem = invert_truthvalue (arg0);
-         if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
-           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)));
+       if (TYPE_PRECISION (newtype) < TYPE_PRECISION (TREE_TYPE (arg0)))
+         return fold (build2 (code, type, fold_convert (newtype, targ0),
+                              fold_convert (newtype, targ1)));
+      }
 
       return t;
 
@@ -8947,92 +9893,6 @@ fold (tree expr)
        return build_complex (type, arg0, arg1);
       return t;
 
-    case REALPART_EXPR:
-      if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
-       return t;
-      else if (TREE_CODE (arg0) == COMPLEX_EXPR)
-       return omit_one_operand (type, TREE_OPERAND (arg0, 0),
-                                TREE_OPERAND (arg0, 1));
-      else if (TREE_CODE (arg0) == COMPLEX_CST)
-       return TREE_REALPART (arg0);
-      else if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
-       return fold (build2 (TREE_CODE (arg0), type,
-                            fold (build1 (REALPART_EXPR, type,
-                                          TREE_OPERAND (arg0, 0))),
-                            fold (build1 (REALPART_EXPR, type,
-                                          TREE_OPERAND (arg0, 1)))));
-      return t;
-
-    case IMAGPART_EXPR:
-      if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
-       return fold_convert (type, integer_zero_node);
-      else if (TREE_CODE (arg0) == COMPLEX_EXPR)
-       return omit_one_operand (type, TREE_OPERAND (arg0, 1),
-                                TREE_OPERAND (arg0, 0));
-      else if (TREE_CODE (arg0) == COMPLEX_CST)
-       return TREE_IMAGPART (arg0);
-      else if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
-       return fold (build2 (TREE_CODE (arg0), type,
-                            fold (build1 (IMAGPART_EXPR, type,
-                                          TREE_OPERAND (arg0, 0))),
-                            fold (build1 (IMAGPART_EXPR, type,
-                                          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
-         && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 0))
-             == FUNCTION_DECL)
-         && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
-       {
-         tree tmp = fold_builtin (t, false);
-         if (tmp)
-           return tmp;
-       }
-      return t;
-
     default:
       return t;
     } /* switch (code) */
@@ -9107,10 +9967,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);
@@ -9118,29 +9977,34 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
     return;
   *slot = expr;
   code = TREE_CODE (expr);
-  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);
   switch (TREE_CODE_CLASS (code))
     {
-    case 'c':
+    case tcc_constant:
       switch (code)
        {
        case STRING_CST:
@@ -9158,7 +10022,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:
@@ -9173,17 +10037,17 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
          break;
        }
       break;
-    case 'e':
-    case 'r':
-    case '<':
-    case '1':
-    case '2':
-    case 's':
-      len = first_rtl_op (code);
+    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);
@@ -9196,7 +10060,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);
@@ -9210,7 +10074,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:
@@ -9229,17 +10096,20 @@ fold_initializer (tree expr)
 {
   int saved_signaling_nans = flag_signaling_nans;
   int saved_trapping_math = flag_trapping_math;
+  int saved_rounding_math = flag_rounding_math;
   int saved_trapv = flag_trapv;
   tree result;
 
   flag_signaling_nans = 0;
   flag_trapping_math = 0;
+  flag_rounding_math = 0;
   flag_trapv = 0;
 
   result = fold (expr);
 
   flag_signaling_nans = saved_signaling_nans;
   flag_trapping_math = saved_trapping_math;
+  flag_rounding_math = saved_rounding_math;
   flag_trapv = saved_trapv;
 
   return result;
@@ -9296,6 +10166,13 @@ multiple_of_p (tree type, tree top, tree bottom)
 
   switch (TREE_CODE (top))
     {
+    case BIT_AND_EXPR:
+      /* Bitwise and provides a power of two multiple.  If the mask is
+        a multiple of BOTTOM then TOP is a multiple of BOTTOM.  */
+      if (!integer_pow2p (bottom))
+       return 0;
+      /* FALLTHRU */
+
     case MULT_EXPR:
       return (multiple_of_p (type, TREE_OPERAND (top, 0), bottom)
              || multiple_of_p (type, TREE_OPERAND (top, 1), bottom));
@@ -9524,9 +10401,7 @@ tree_expr_nonnegative_p (tree t)
       {
        tree fndecl = get_callee_fndecl (t);
        tree arglist = TREE_OPERAND (t, 1);
-       if (fndecl
-           && DECL_BUILT_IN (fndecl)
-           && DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_MD)
+       if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
          switch (DECL_FUNCTION_CODE (fndecl))
            {
 #define CASE_BUILTIN_F(BUILT_IN_FN) \
@@ -9620,7 +10495,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)
@@ -9638,7 +10513,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)
@@ -9673,11 +10551,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))
@@ -9722,50 +10611,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.  */
@@ -9895,11 +10740,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
@@ -9930,8 +10774,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;
@@ -10225,8 +11068,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)
@@ -10336,8 +11178,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;
 }
@@ -10352,26 +11195,30 @@ 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;
-      t = force_fit_type (t, 1,
-                         (overflow | TREE_OVERFLOW (arg0))
-                         && !TYPE_UNSIGNED (type),
-                         TREE_CONSTANT_OVERFLOW (arg0));
-    }
-  else if (TREE_CODE (arg0) == REAL_CST)
-    t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
-#ifdef ENABLE_CHECKING
-  else
-    abort ();
-#endif
+    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 ();
+    }
 
   return t;
 }
@@ -10386,15 +11233,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
@@ -10404,24 +11252,22 @@ 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;
+         t = build_int_cst_wide (type, low, high);
          t = force_fit_type (t, -1, overflow | TREE_OVERFLOW (arg0),
                              TREE_CONSTANT_OVERFLOW (arg0));
-         return t;
        }
-    }
-  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;
 }
@@ -10434,18 +11280,13 @@ 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;
-      t = force_fit_type (t, 0, TREE_OVERFLOW (arg0),
-                         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;
 }
@@ -10499,7 +11340,7 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
              break;
 
            default:
-             abort ();
+             gcc_unreachable ();
            }
 
          return constant_boolean_node (result, type);
@@ -10554,13 +11395,49 @@ 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;
+
+  /* If the expression is a return, check to see if the expression inside the
+     return has no side effects or the right hand side of the modify expression
+     inside the return. If either don't have side effects set we don't need to
+     wrap the expression in a cleanup point expression.  Note we don't check the
+     left hand side of the modify because it should always be a return decl.  */
+  if (TREE_CODE (expr) == RETURN_EXPR)
+    {
+      tree op = TREE_OPERAND (expr, 0);
+      if (!op || !TREE_SIDE_EFFECTS (op))
+        return expr;
+      op = TREE_OPERAND (op, 1);
+      if (!TREE_SIDE_EFFECTS (op))
+        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)
@@ -10570,9 +11447,7 @@ build_fold_addr_expr_with_type (tree t, tree ptrtype)
     {
       tree base = t;
 
-      while (handled_component_p (base)
-            || TREE_CODE (base) == REALPART_EXPR
-            || TREE_CODE (base) == IMAGPART_EXPR)
+      while (handled_component_p (base))
        base = TREE_OPERAND (base, 0);
       if (DECL_P (base))
        TREE_ADDRESSABLE (base) = 1;
@@ -10589,17 +11464,21 @@ build_fold_addr_expr (tree t)
   return build_fold_addr_expr_with_type (t, build_pointer_type (TREE_TYPE (t)));
 }
 
-/* Builds an expression for an indirection through T, simplifying some
-   cases.  */
+/* Given a pointer value T, return a simplified version of an indirection
+   through T, or NULL_TREE if no simplification is possible.  */
 
-tree
-build_fold_indirect_ref (tree t)
+static tree
+fold_indirect_ref_1 (tree t)
 {
   tree type = TREE_TYPE (TREE_TYPE (t));
   tree sub = t;
   tree subtype;
 
   STRIP_NOPS (sub);
+  subtype = TREE_TYPE (sub);
+  if (!POINTER_TYPE_P (subtype))
+    return NULL_TREE;
+
   if (TREE_CODE (sub) == ADDR_EXPR)
     {
       tree op = TREE_OPERAND (sub, 0);
@@ -10610,19 +11489,56 @@ 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 build4 (ARRAY_REF, type, op, size_zero_node, NULL_TREE, NULL_TREE);
+       {
+         tree type_domain = TYPE_DOMAIN (optype);
+         tree min_val = size_zero_node;
+         if (type_domain && TYPE_MIN_VALUE (type_domain))
+           min_val = TYPE_MIN_VALUE (type_domain);
+         return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE);
+       }
     }
 
   /* *(foo *)fooarrptr => (*fooarrptr)[0] */
-  subtype = TREE_TYPE (sub);
   if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
       && lang_hooks.types_compatible_p (type, TREE_TYPE (TREE_TYPE (subtype))))
     {
+      tree type_domain;
+      tree min_val = size_zero_node;
       sub = build_fold_indirect_ref (sub);
-      return build4 (ARRAY_REF, type, sub, size_zero_node, NULL_TREE, NULL_TREE);
+      type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
+      if (type_domain && TYPE_MIN_VALUE (type_domain))
+       min_val = TYPE_MIN_VALUE (type_domain);
+      return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE);
     }
 
-  return build1 (INDIRECT_REF, type, t);
+  return NULL_TREE;
+}
+
+/* Builds an expression for an indirection through T, simplifying some
+   cases.  */
+
+tree
+build_fold_indirect_ref (tree t)
+{
+  tree sub = fold_indirect_ref_1 (t);
+
+  if (sub)
+    return sub;
+  else
+    return build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t);
+}
+
+/* Given an INDIRECT_REF T, return either T or a simplified version.  */
+
+tree
+fold_indirect_ref (tree t)
+{
+  tree sub = fold_indirect_ref_1 (TREE_OPERAND (t, 0));
+
+  if (sub)
+    return sub;
+  else
+    return t;
 }
 
 /* Strip non-trapping, non-side-effecting tree nodes from an expression
@@ -10638,12 +11554,12 @@ fold_ignored_result (tree t)
   for (;;)
     switch (TREE_CODE_CLASS (TREE_CODE (t)))
       {
-      case '1':
+      case tcc_unary:
        t = TREE_OPERAND (t, 0);
        break;
 
-      case '2':
-      case '<':
+      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)))
@@ -10652,7 +11568,7 @@ fold_ignored_result (tree t)
          return t;
        break;
 
-      case 'e':
+      case tcc_expression:
        switch (TREE_CODE (t))
          {
          case COMPOUND_EXPR:
@@ -10678,4 +11594,199 @@ fold_ignored_result (tree t)
       }
 }
 
-#include "gt-fold-const.h"
+/* 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,
+                                 false);
+
+      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;
+}
+
+/* Simplify the floating point expression EXP when the sign of the
+   result is not significant.  Return NULL_TREE if no simplification
+   is possible.  */
+
+tree
+fold_strip_sign_ops (tree exp)
+{
+  tree arg0, arg1;
+
+  switch (TREE_CODE (exp))
+    {
+    case ABS_EXPR:
+    case NEGATE_EXPR:
+      arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 0));
+      return arg0 ? arg0 : TREE_OPERAND (exp, 0);
+
+    case MULT_EXPR:
+    case RDIV_EXPR:
+      if (HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (TREE_TYPE (exp))))
+       return NULL_TREE;
+      arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 0));
+      arg1 = fold_strip_sign_ops (TREE_OPERAND (exp, 1));
+      if (arg0 != NULL_TREE || arg1 != NULL_TREE)
+       return fold (build2 (TREE_CODE (exp), TREE_TYPE (exp),
+                            arg0 ? arg0 : TREE_OPERAND (exp, 0),
+                            arg1 ? arg1 : TREE_OPERAND (exp, 1)));
+      break;
+
+    default:
+      break;
+    }
+  return NULL_TREE;
+}
+