OSDN Git Service

PR middle-end/17055
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index 4bb42a4..10cdb69 100644 (file)
@@ -39,8 +39,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    size_int takes an integer value, and creates a tree constant
    with type from `sizetype'.
 
-   force_fit_type takes a constant and prior overflow indicator, and
-   forces the value to fit the type.  It returns an overflow indicator.  */
+   force_fit_type takes a constant, an overflowable flag and prior
+   overflow indicators.  It forces the value to fit the type and sets
+   TREE_OVERFLOW and TREE_CONSTANT_OVERFLOW as appropriate.  */
 
 #include "config.h"
 #include "system.h"
@@ -88,8 +89,7 @@ static tree negate_expr (tree);
 static tree split_tree (tree, enum tree_code, tree *, tree *, tree *, int);
 static tree associate_trees (tree, tree, enum tree_code, tree);
 static tree const_binop (enum tree_code, tree, tree, int);
-static hashval_t size_htab_hash (const void *);
-static int size_htab_eq (const void *, const void *);
+static tree build_zero_vector (tree);
 static tree fold_convert_const (enum tree_code, tree, tree);
 static enum tree_code invert_tree_comparison (enum tree_code, bool);
 static enum comparison_code comparison_to_compcode (enum tree_code);
@@ -123,7 +123,6 @@ static tree optimize_minmax_comparison (tree);
 static tree extract_muldiv (tree, tree, enum tree_code, tree);
 static tree extract_muldiv_1 (tree, tree, enum tree_code, tree);
 static int multiple_of_p (tree, tree, tree);
-static tree constant_boolean_node (int, tree);
 static tree fold_binary_op_with_conditional_arg (enum tree_code, tree, tree,
                                                 tree, int);
 static bool fold_real_zero_addition_p (tree, tree, int);
@@ -137,6 +136,7 @@ static tree fold_not_const (tree, tree);
 static tree fold_relational_const (enum tree_code, tree, tree, tree);
 static tree fold_relational_hi_lo (enum tree_code *, const tree,
                                    tree *, tree *);
+static bool tree_expr_nonzero_p (tree);
 
 /* We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring
    overflow.  Suppose A, B and SUM have the same respective signs as A1, B1,
@@ -184,30 +184,32 @@ decode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT *low,
   *hi = words[2] + words[3] * BASE;
 }
 \f
-/* Make the integer constant T valid for its type by setting to 0 or 1 all
-   the bits in the constant that don't belong in the type.
+/* T is an INT_CST node.  OVERFLOWABLE indicates if we are interested
+   in overflow of the value, when >0 we are only interested in signed
+   overflow, for <0 we are interested in any overflow.  OVERFLOWED
+   indicates whether overflow has already occurred.  CONST_OVERFLOWED
+   indicates whether constant overflow has already occurred.  We force
+   T's value to be within range of T's type (by setting to 0 or 1 all
+   the bits outside the type's range).  We set TREE_OVERFLOWED if,
+       OVERFLOWED is non-zero,
+       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
+       or we set TREE_OVERFLOWED.
+  We return either the original T, or a copy.  */
 
-   Return 1 if a signed overflow occurs, 0 otherwise.  If OVERFLOW is
-   nonzero, a signed overflow has already occurred in calculating T, so
-   propagate it.  */
-
-int
-force_fit_type (tree t, int overflow)
+tree
+force_fit_type (tree t, int overflowable,
+               bool overflowed, bool overflowed_const)
 {
   unsigned HOST_WIDE_INT low;
   HOST_WIDE_INT high;
   unsigned int prec;
+  int sign_extended_type;
 
-  if (TREE_CODE (t) == REAL_CST)
-    {
-      /* ??? Used to check for overflow here via CHECK_FLOAT_TYPE.
-        Consider doing it via real_convert now.  */
-      return overflow;
-    }
-
-  else if (TREE_CODE (t) != INTEGER_CST)
-    return overflow;
-
+  gcc_assert (TREE_CODE (t) == INTEGER_CST);
+  
   low = TREE_INT_CST_LOW (t);
   high = TREE_INT_CST_HIGH (t);
 
@@ -216,54 +218,72 @@ force_fit_type (tree t, int overflow)
     prec = POINTER_SIZE;
   else
     prec = TYPE_PRECISION (TREE_TYPE (t));
+  /* Size types *are* sign extended.  */
+  sign_extended_type = (!TYPE_UNSIGNED (TREE_TYPE (t))
+                       || (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
+                           && TYPE_IS_SIZETYPE (TREE_TYPE (t))));
 
   /* First clear all bits that are beyond the type's precision.  */
 
   if (prec == 2 * HOST_BITS_PER_WIDE_INT)
     ;
   else if (prec > HOST_BITS_PER_WIDE_INT)
-    TREE_INT_CST_HIGH (t)
-      &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
+    high &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
   else
     {
-      TREE_INT_CST_HIGH (t) = 0;
+      high = 0;
       if (prec < HOST_BITS_PER_WIDE_INT)
-       TREE_INT_CST_LOW (t) &= ~((unsigned HOST_WIDE_INT) (-1) << prec);
-    }
-
-  /* Unsigned types do not suffer sign extension or overflow unless they
-     are a sizetype.  */
-  if (TYPE_UNSIGNED (TREE_TYPE (t))
-      && ! (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
-           && TYPE_IS_SIZETYPE (TREE_TYPE (t))))
-    return overflow;
-
-  /* If the value's sign bit is set, extend the sign.  */
-  if (prec != 2 * HOST_BITS_PER_WIDE_INT
-      && (prec > HOST_BITS_PER_WIDE_INT
-         ? 0 != (TREE_INT_CST_HIGH (t)
-                 & ((HOST_WIDE_INT) 1
-                    << (prec - HOST_BITS_PER_WIDE_INT - 1)))
-         : 0 != (TREE_INT_CST_LOW (t)
-                 & ((unsigned HOST_WIDE_INT) 1 << (prec - 1)))))
-    {
-      /* Value is negative:
-        set to 1 all the bits that are outside this type's precision.  */
-      if (prec > HOST_BITS_PER_WIDE_INT)
-       TREE_INT_CST_HIGH (t)
-         |= ((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
-      else
+       low &= ~((HOST_WIDE_INT) (-1) << prec);
+    }
+
+  if (!sign_extended_type)
+    /* No sign extension */;
+  else if (prec == 2 * HOST_BITS_PER_WIDE_INT)
+    /* Correct width already.  */;
+  else if (prec > HOST_BITS_PER_WIDE_INT)
+    {
+      /* Sign extend top half? */
+      if (high & ((unsigned HOST_WIDE_INT)1
+                 << (prec - HOST_BITS_PER_WIDE_INT - 1)))
+       high |= (HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT);
+    }
+  else if (prec == HOST_BITS_PER_WIDE_INT)
+    {
+      if ((HOST_WIDE_INT)low < 0)
+       high = -1;
+    }
+  else
+    {
+      /* Sign extend bottom half? */
+      if (low & ((unsigned HOST_WIDE_INT)1 << (prec - 1)))
        {
-         TREE_INT_CST_HIGH (t) = -1;
-         if (prec < HOST_BITS_PER_WIDE_INT)
-           TREE_INT_CST_LOW (t) |= ((unsigned HOST_WIDE_INT) (-1) << prec);
+         high = -1;
+         low |= (HOST_WIDE_INT)(-1) << prec;
        }
     }
 
-  /* Return nonzero if signed overflow occurred.  */
-  return
-    ((overflow | (low ^ TREE_INT_CST_LOW (t)) | (high ^ TREE_INT_CST_HIGH (t)))
-     != 0);
+  /* If the value changed, return a new node.  */
+  if (overflowed || overflowed_const
+      || low != TREE_INT_CST_LOW (t) || high != TREE_INT_CST_HIGH (t))
+    {
+      t = build_int_cst_wide (TREE_TYPE (t), low, high);
+      
+      if (overflowed
+         || overflowable < 0
+         || (overflowable > 0 && sign_extended_type))
+       {
+         t = copy_node (t);
+         TREE_OVERFLOW (t) = 1;
+         TREE_CONSTANT_OVERFLOW (t) = 1;
+       }
+      else if (overflowed_const)
+       {
+         t = copy_node (t);
+         TREE_CONSTANT_OVERFLOW (t) = 1;
+       }
+    }
+  
+  return t;
 }
 \f
 /* Add two doubleword integers with doubleword result.
@@ -805,7 +825,7 @@ div_and_round_double (enum tree_code code, int uns,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   /* Compute true remainder:  rem = num - (quo * den)  */
@@ -843,14 +863,43 @@ negate_mathfn_p (enum built_in_function code)
   return false;
 }
 
+/* Check whether we may negate an integer constant T without causing
+   overflow.  */
+
+bool
+may_negate_without_overflow_p (tree t)
+{
+  unsigned HOST_WIDE_INT val;
+  unsigned int prec;
+  tree type;
+
+  gcc_assert (TREE_CODE (t) == INTEGER_CST);
+
+  type = TREE_TYPE (t);
+  if (TYPE_UNSIGNED (type))
+    return false;
+
+  prec = TYPE_PRECISION (type);
+  if (prec > HOST_BITS_PER_WIDE_INT)
+    {
+      if (TREE_INT_CST_LOW (t) != 0)
+       return true;
+      prec -= HOST_BITS_PER_WIDE_INT;
+      val = TREE_INT_CST_HIGH (t);
+    }
+  else
+    val = TREE_INT_CST_LOW (t);
+  if (prec < HOST_BITS_PER_WIDE_INT)
+    val &= ((unsigned HOST_WIDE_INT) 1 << prec) - 1;
+  return val != ((unsigned HOST_WIDE_INT) 1 << (prec - 1));
+}
+
 /* Determine whether an expression T can be cheaply negated using
    the function negate_expr.  */
 
 static bool
 negate_expr_p (tree t)
 {
-  unsigned HOST_WIDE_INT val;
-  unsigned int prec;
   tree type;
 
   if (t == 0)
@@ -866,19 +915,7 @@ negate_expr_p (tree t)
        return true;
 
       /* Check that -CST will not overflow type.  */
-      prec = TYPE_PRECISION (type);
-      if (prec > HOST_BITS_PER_WIDE_INT)
-       {
-         if (TREE_INT_CST_LOW (t) != 0)
-           return true;
-         prec -= HOST_BITS_PER_WIDE_INT;
-         val = TREE_INT_CST_HIGH (t);
-       }
-      else
-       val = TREE_INT_CST_LOW (t);
-      if (prec < HOST_BITS_PER_WIDE_INT)
-       val &= ((unsigned HOST_WIDE_INT) 1 << prec) - 1;
-      return val != ((unsigned HOST_WIDE_INT) 1 << (prec - 1));
+      return may_negate_without_overflow_p (t);
 
     case REAL_CST:
     case NEGATE_EXPR:
@@ -1387,42 +1424,34 @@ int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
-  /* If this is for a sizetype, can be represented as one (signed)
-     HOST_WIDE_INT word, and doesn't overflow, use size_int since it caches
-     constants.  */
-  if (is_sizetype
-      && ((hi == 0 && (HOST_WIDE_INT) low >= 0)
-         || (hi == -1 && (HOST_WIDE_INT) low < 0))
-      && overflow == 0 && ! TREE_OVERFLOW (arg1) && ! TREE_OVERFLOW (arg2))
-    return size_int_type_wide (low, type);
-  else
+  t = build_int_cst_wide (TREE_TYPE (arg1), low, hi);
+
+  if (notrunc)
     {
-      t = build_int_2 (low, hi);
-      TREE_TYPE (t) = TREE_TYPE (arg1);
-    }
-
-  TREE_OVERFLOW (t)
-    = ((notrunc
-       ? (!uns || is_sizetype) && overflow
-       : (force_fit_type (t, (!uns || is_sizetype) && overflow)
-          && ! no_overflow))
-       | TREE_OVERFLOW (arg1)
-       | TREE_OVERFLOW (arg2));
-
-  /* If we're doing a size calculation, unsigned arithmetic does overflow.
-     So check if force_fit_type truncated the value.  */
-  if (is_sizetype
-      && ! TREE_OVERFLOW (t)
-      && (TREE_INT_CST_HIGH (t) != hi
-         || TREE_INT_CST_LOW (t) != low))
-    TREE_OVERFLOW (t) = 1;
-
-  TREE_CONSTANT_OVERFLOW (t) = (TREE_OVERFLOW (t)
-                               | TREE_CONSTANT_OVERFLOW (arg1)
-                               | TREE_CONSTANT_OVERFLOW (arg2));
+      /* Propagate overflow flags ourselves.  */
+      if (((!uns || is_sizetype) && overflow)
+         | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2))
+       {
+         t = copy_node (t);
+         TREE_OVERFLOW (t) = 1;
+         TREE_CONSTANT_OVERFLOW (t) = 1;
+       }
+      else if (TREE_CONSTANT_OVERFLOW (arg1) | TREE_CONSTANT_OVERFLOW (arg2))
+       {
+         t = copy_node (t);
+         TREE_CONSTANT_OVERFLOW (t) = 1;
+       }
+    }
+  else
+    t = force_fit_type (t, 1,
+                       ((!uns || is_sizetype) && overflow)
+                       | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2),
+                       TREE_CONSTANT_OVERFLOW (arg1)
+                       | TREE_CONSTANT_OVERFLOW (arg2));
+  
   return t;
 }
 
@@ -1479,9 +1508,7 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
 
       t = build_real (type, real_value_truncate (mode, value));
 
-      TREE_OVERFLOW (t)
-       = (force_fit_type (t, 0)
-          | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2));
+      TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2);
       TREE_CONSTANT_OVERFLOW (t)
        = TREE_OVERFLOW (t)
          | TREE_CONSTANT_OVERFLOW (arg1)
@@ -1560,91 +1587,22 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
       return t;
     }
   return 0;
 }
 
-/* These are the hash table functions for the hash table of INTEGER_CST
-   nodes of a sizetype.  */
-
-/* Return the hash code code X, an INTEGER_CST.  */
-
-static hashval_t
-size_htab_hash (const void *x)
-{
-  tree t = (tree) x;
-
-  return (TREE_INT_CST_HIGH (t) ^ TREE_INT_CST_LOW (t)
-         ^ htab_hash_pointer (TREE_TYPE (t))
-         ^ (TREE_OVERFLOW (t) << 20));
-}
-
-/* Return nonzero if the value represented by *X (an INTEGER_CST tree node)
-   is the same as that given by *Y, which is the same.  */
-
-static int
-size_htab_eq (const void *x, const void *y)
-{
-  tree xt = (tree) x;
-  tree yt = (tree) y;
-
-  return (TREE_INT_CST_HIGH (xt) == TREE_INT_CST_HIGH (yt)
-         && TREE_INT_CST_LOW (xt) == TREE_INT_CST_LOW (yt)
-         && TREE_TYPE (xt) == TREE_TYPE (yt)
-         && TREE_OVERFLOW (xt) == TREE_OVERFLOW (yt));
-}
-\f
-/* Return an INTEGER_CST with value whose low-order HOST_BITS_PER_WIDE_INT
-   bits are given by NUMBER and of the sizetype represented by KIND.  */
-
-tree
-size_int_wide (HOST_WIDE_INT number, enum size_type_kind kind)
-{
-  return size_int_type_wide (number, sizetype_tab[(int) kind]);
-}
-
-/* Likewise, but the desired type is specified explicitly.  */
-
-static GTY (()) tree new_const;
-static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
-     htab_t size_htab;
+/* Create a size type INT_CST node with NUMBER sign extended.  KIND
+   indicates which particular sizetype to create.  */
 
 tree
-size_int_type_wide (HOST_WIDE_INT number, tree type)
+size_int_kind (HOST_WIDE_INT number, enum size_type_kind kind)
 {
-  void **slot;
-
-  if (size_htab == 0)
-    {
-      size_htab = htab_create_ggc (1024, size_htab_hash, size_htab_eq, NULL);
-      new_const = make_node (INTEGER_CST);
-    }
-
-  /* Adjust NEW_CONST to be the constant we want.  If it's already in the
-     hash table, we return the value from the hash table.  Otherwise, we
-     place that in the hash table and make a new node for the next time.  */
-  TREE_INT_CST_LOW (new_const) = number;
-  TREE_INT_CST_HIGH (new_const) = number < 0 ? -1 : 0;
-  TREE_TYPE (new_const) = type;
-  TREE_OVERFLOW (new_const) = TREE_CONSTANT_OVERFLOW (new_const)
-    = force_fit_type (new_const, 0);
-
-  slot = htab_find_slot (size_htab, new_const, INSERT);
-  if (*slot == 0)
-    {
-      tree t = new_const;
-
-      *slot = new_const;
-      new_const = make_node (INTEGER_CST);
-      return t;
-    }
-  else
-    return (tree) *slot;
+  return build_int_cst (sizetype_tab[(int) kind], number);
 }
-
+\f
 /* Combine operands OP1 and OP2 with arithmetic operation CODE.  CODE
    is a tree code.  The type of the result is taken from the operands.
    Both must be the same type integer type and it must be a size type.
@@ -1655,9 +1613,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)
@@ -1691,16 +1648,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
@@ -1723,6 +1678,23 @@ size_diffop (tree arg0, tree arg1)
                                                        arg1, arg0)));
 }
 \f
+/* Construct a vector of zero elements of vector type TYPE.  */
+
+static tree
+build_zero_vector (tree type)
+{
+  tree elem, list;
+  int i, units;
+
+  elem = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
+  units = TYPE_VECTOR_SUBPARTS (type);
+
+  list = NULL_TREE;
+  for (i = 0; i < units; i++)
+    list = tree_cons (NULL_TREE, elem, list);
+  return build_vector (type, list);
+}
+
 
 /* Attempt to fold type conversion operation CODE of expression ARG1 to
    type TYPE.  If no simplification can be done return NULL_TREE.  */
@@ -1745,32 +1717,20 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
          if (TYPE_PRECISION (type) > 2 * HOST_BITS_PER_WIDE_INT)
            return NULL_TREE;
 
-         /* If we are trying to make a sizetype for a small integer, use
-            size_int to pick up cached types to reduce duplicate nodes.  */
-         if (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type)
-             && !TREE_CONSTANT_OVERFLOW (arg1)
-             && compare_tree_int (arg1, 10000) < 0)
-           return size_int_type_wide (TREE_INT_CST_LOW (arg1), type);
-
          /* Given an integer constant, make new constant with new type,
             appropriately sign-extended or truncated.  */
-         t = build_int_2 (TREE_INT_CST_LOW (arg1),
-                          TREE_INT_CST_HIGH (arg1));
-         TREE_TYPE (t) = type;
-         /* Indicate an overflow if (1) ARG1 already overflowed,
-            or (2) force_fit_type indicates an overflow.
-            Tell force_fit_type that an overflow has already occurred
-            if ARG1 is a too-large unsigned value and T is signed.
-            But don't indicate an overflow if converting a pointer.  */
-         TREE_OVERFLOW (t)
-           = ((force_fit_type (t,
-                               (TREE_INT_CST_HIGH (arg1) < 0
-                                && (TYPE_UNSIGNED (type)
-                                   < TYPE_UNSIGNED (TREE_TYPE (arg1)))))
-               && ! POINTER_TYPE_P (TREE_TYPE (arg1)))
-              || TREE_OVERFLOW (arg1));
-         TREE_CONSTANT_OVERFLOW (t)
-           = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
+         t = build_int_cst_wide (type, TREE_INT_CST_LOW (arg1),
+                                 TREE_INT_CST_HIGH (arg1));
+
+         t = force_fit_type (t,
+                             /* Don't set the overflow when
+                                converting a pointer  */
+                             !POINTER_TYPE_P (TREE_TYPE (arg1)),
+                             (TREE_INT_CST_HIGH (arg1) < 0
+                              && (TYPE_UNSIGNED (type)
+                                  < TYPE_UNSIGNED (TREE_TYPE (arg1))))
+                             | TREE_OVERFLOW (arg1),
+                             TREE_CONSTANT_OVERFLOW (arg1));
          return t;
        }
       else if (TREE_CODE (arg1) == REAL_CST)
@@ -1785,7 +1745,6 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
             FP-to-integer conversion is unspecified upon overflow.  */
 
          HOST_WIDE_INT high, low;
-
          REAL_VALUE_TYPE r;
          REAL_VALUE_TYPE x = TREE_REAL_CST (arg1);
 
@@ -1808,7 +1767,7 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
              break;
 
            default:
-             abort ();
+             gcc_unreachable ();
            }
 
          /* If R is NaN, return zero and show we have an overflow.  */
@@ -1852,12 +1811,10 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
          if (! overflow)
            REAL_VALUE_TO_INT (&low, &high, r);
 
-         t = build_int_2 (low, high);
-         TREE_TYPE (t) = type;
-         TREE_OVERFLOW (t)
-           = TREE_OVERFLOW (arg1) | force_fit_type (t, overflow);
-         TREE_CONSTANT_OVERFLOW (t)
-           = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
+         t = build_int_cst_wide (type, low, high);
+
+         t = force_fit_type (t, -1, overflow | TREE_OVERFLOW (arg1),
+                             TREE_CONSTANT_OVERFLOW (arg1));
          return t;
        }
     }
@@ -1880,8 +1837,7 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
                          real_value_truncate (TYPE_MODE (type),
                                               TREE_REAL_CST (arg1)));
 
-         TREE_OVERFLOW (t)
-           = TREE_OVERFLOW (arg1) | force_fit_type (t, 0);
+         TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1);
          TREE_CONSTANT_OVERFLOW (t)
            = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
          return t;
@@ -1912,9 +1868,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);
@@ -1929,13 +1887,11 @@ fold_convert (tree type, tree arg)
          tem = fold (build1 (REALPART_EXPR, TREE_TYPE (orig), arg));
          return fold_convert (type, tem);
        }
-      if (TREE_CODE (orig) == VECTOR_TYPE
-         && GET_MODE_SIZE (TYPE_MODE (type))
-            == GET_MODE_SIZE (TYPE_MODE (orig)))
-       return fold (build1 (NOP_EXPR, type, arg));
-    }
-  else if (TREE_CODE (type) == REAL_TYPE)
-    {
+      gcc_assert (TREE_CODE (orig) == VECTOR_TYPE
+                 && tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)));
+      return fold (build1 (NOP_EXPR, type, arg));
+      
+    case REAL_TYPE:
       if (TREE_CODE (arg) == INTEGER_CST)
        {
          tem = fold_convert_const (FLOAT_EXPR, type, arg);
@@ -1949,58 +1905,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 ();
+       }
+      
+    case COMPLEX_TYPE:
+      switch (TREE_CODE (orig))
+       {
+       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));
+             }
+           
+           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 ();
        }
-    }
-  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)
-       {
-         tree rpart, ipart;
+      
+    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));
 
-         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));
-           }
+    case VOID_TYPE:
+      return fold (build1 (CONVERT_EXPR, type, fold_ignored_result (arg)));
 
-         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));
-       }
-    }
-  else if (TREE_CODE (type) == VECTOR_TYPE)
-    {
-      if ((INTEGRAL_TYPE_P (orig) || POINTER_TYPE_P (orig))
-         && GET_MODE_SIZE (TYPE_MODE (type))
-            == GET_MODE_SIZE (TYPE_MODE (orig)))
-       return fold (build1 (NOP_EXPR, type, arg));
-      if (TREE_CODE (orig) == VECTOR_TYPE
-         && GET_MODE_SIZE (TYPE_MODE (type))
-            == GET_MODE_SIZE (TYPE_MODE (orig)))
-       return fold (build1 (NOP_EXPR, type, arg));
+    default:
+      gcc_unreachable ();
     }
-  else if (VOID_TYPE_P (type))
-    return fold (build1 (CONVERT_EXPR, type, arg));
-  abort ();
 }
 \f
 /* Return an expr equal to X but certainly not valid as an lvalue.  */
@@ -2023,7 +1993,6 @@ non_lvalue (tree x)
   case ARRAY_REF:
   case ARRAY_RANGE_REF:
   case BIT_FIELD_REF:
-  case BUFFER_REF:
   case OBJ_TYPE_REF:
 
   case REALPART_EXPR:
@@ -2031,7 +2000,6 @@ non_lvalue (tree x)
   case PREINCREMENT_EXPR:
   case PREDECREMENT_EXPR:
   case SAVE_EXPR:
-  case UNSAVE_EXPR:
   case TRY_CATCH_EXPR:
   case WITH_CLEANUP_EXPR:
   case COMPOUND_EXPR:
@@ -2041,7 +2009,6 @@ non_lvalue (tree x)
   case BIND_EXPR:
   case MIN_EXPR:
   case MAX_EXPR:
-  case RTL_EXPR:
     break;
 
   default:
@@ -2112,7 +2079,7 @@ invert_tree_comparison (enum tree_code code, bool honor_nans)
     case UNORDERED_EXPR:
       return ORDERED_EXPR;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -2136,7 +2103,7 @@ swap_tree_comparison (enum tree_code code)
     case LE_EXPR:
       return GE_EXPR;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -2179,7 +2146,7 @@ comparison_to_compcode (enum tree_code code)
     case UNGE_EXPR:
       return COMPCODE_UNGE;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -2221,7 +2188,7 @@ compcode_to_comparison (enum comparison_code code)
     case COMPCODE_UNGE:
       return UNGE_EXPR;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -2349,8 +2316,17 @@ 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.  */
-  if (TREE_CODE (arg0) == ERROR_MARK || TREE_CODE (arg1) == ERROR_MARK)
+  else 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
@@ -2446,10 +2422,21 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
     {
     case '1':
       /* 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);
@@ -2479,16 +2466,31 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
       switch (TREE_CODE (arg0))
        {
        case INDIRECT_REF:
+       case REALPART_EXPR:
+       case IMAGPART_EXPR:
          return operand_equal_p (TREE_OPERAND (arg0, 0),
                                  TREE_OPERAND (arg1, 0), flags);
 
-       case COMPONENT_REF:
        case ARRAY_REF:
        case ARRAY_RANGE_REF:
          return (operand_equal_p (TREE_OPERAND (arg0, 0),
                                   TREE_OPERAND (arg1, 0), flags)
                  && operand_equal_p (TREE_OPERAND (arg0, 1),
-                                     TREE_OPERAND (arg1, 1), flags));
+                                     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));
+
+
+       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));
+
 
        case BIT_FIELD_REF:
          return (operand_equal_p (TREE_OPERAND (arg0, 0),
@@ -2528,9 +2530,6 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
                     && operand_equal_p (TREE_OPERAND (arg0, 1),
                                         TREE_OPERAND (arg1, 0), flags));
 
-       case RTL_EXPR:
-         return rtx_equal_p (RTL_EXPR_RTL (arg0), RTL_EXPR_RTL (arg1));
-
        case CALL_EXPR:
          /* If the CALL_EXPRs call different functions, then they
             clearly can not be equal.  */
@@ -2663,7 +2662,7 @@ twoval_comparison_p (tree arg, tree *cval1, tree *cval2, int *save_p)
               || code == COMPOUND_EXPR))
     class = '2';
 
-  else if (class == 'e' && code == SAVE_EXPR && SAVE_EXPR_RTL (arg) == 0
+  else if (class == 'e' && code == SAVE_EXPR
           && ! TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0)))
     {
       /* If we've already found a CVAL1 or CVAL2, this expression is
@@ -2831,7 +2830,7 @@ omit_one_operand (tree type, tree result, tree omitted)
   tree t = fold_convert (type, result);
 
   if (TREE_SIDE_EFFECTS (omitted))
-    return build2 (COMPOUND_EXPR, type, omitted, t);
+    return build2 (COMPOUND_EXPR, type, fold_ignored_result (omitted), t);
 
   return non_lvalue (t);
 }
@@ -2844,7 +2843,7 @@ pedantic_omit_one_operand (tree type, tree result, tree omitted)
   tree t = fold_convert (type, result);
 
   if (TREE_SIDE_EFFECTS (omitted))
-    return build2 (COMPOUND_EXPR, type, omitted, t);
+    return build2 (COMPOUND_EXPR, type, fold_ignored_result (omitted), t);
 
   return pedantic_non_lvalue (t);
 }
@@ -2914,7 +2913,8 @@ invert_truthvalue (tree arg)
   switch (code)
     {
     case INTEGER_CST:
-      return fold_convert (type, build_int_2 (integer_zerop (arg), 0));
+      return fold_convert (type,
+                          build_int_cst (NULL_TREE, integer_zerop (arg)));
 
     case TRUTH_AND_EXPR:
       return build2 (TRUTH_OR_EXPR, type,
@@ -2990,8 +2990,7 @@ invert_truthvalue (tree arg)
     default:
       break;
     }
-  if (TREE_CODE (TREE_TYPE (arg)) != BOOLEAN_TYPE)
-    abort ();
+  gcc_assert (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE);
   return build1 (TRUTH_NOT_EXPR, type, arg);
 }
 
@@ -3149,9 +3148,8 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type,
     lbitpos = nbitsize - lbitsize - lbitpos;
 
   /* Make the mask to be used against the extracted field.  */
-  mask = build_int_2 (~0, ~0);
-  TREE_TYPE (mask) = unsigned_type;
-  force_fit_type (mask, 0);
+  mask = build_int_cst (unsigned_type, -1);
+  mask = force_fit_type (mask, 0, false, false);
   mask = fold_convert (unsigned_type, mask);
   mask = const_binop (LSHIFT_EXPR, mask, size_int (nbitsize - lbitsize), 0);
   mask = const_binop (RSHIFT_EXPR, mask,
@@ -3299,16 +3297,16 @@ decode_field_reference (tree exp, HOST_WIDE_INT *pbitsize,
   /* If the number of bits in the reference is the same as the bitsize of
      the outer type, then the outer type gives the signedness. Otherwise
      (in case of a small bitfield) the signedness is unchanged.  */
-  if (outer_type && *pbitsize == tree_low_cst (TYPE_SIZE (outer_type), 1))
+  if (outer_type && *pbitsize == TYPE_PRECISION (outer_type))
     *punsignedp = TYPE_UNSIGNED (outer_type);
 
   /* Compute the mask to access the bitfield.  */
   unsigned_type = lang_hooks.types.type_for_size (*pbitsize, 1);
   precision = TYPE_PRECISION (unsigned_type);
 
-  mask = build_int_2 (~0, ~0);
-  TREE_TYPE (mask) = unsigned_type;
-  force_fit_type (mask, 0);
+  mask = build_int_cst (unsigned_type, -1);
+  mask = force_fit_type (mask, 0, false, false);
+  
   mask = const_binop (LSHIFT_EXPR, mask, size_int (precision - *pbitsize), 0);
   mask = const_binop (RSHIFT_EXPR, mask, size_int (precision - *pbitsize), 0);
 
@@ -3332,9 +3330,9 @@ all_ones_mask_p (tree mask, int size)
   unsigned int precision = TYPE_PRECISION (type);
   tree tmask;
 
-  tmask = build_int_2 (~0, ~0);
-  TREE_TYPE (tmask) = lang_hooks.types.signed_type (type);
-  force_fit_type (tmask, 0);
+  tmask = build_int_cst (lang_hooks.types.signed_type (type), -1);
+  tmask = force_fit_type (tmask, 0, false, false);
+  
   return
     tree_int_cst_equal (mask,
                        const_binop (RSHIFT_EXPR,
@@ -3518,7 +3516,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);
@@ -3607,7 +3605,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
@@ -3617,8 +3615,9 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
             of, e.g. EQ_EXPR, is boolean.  */
          if (TYPE_UNSIGNED (arg0_type) && (low == 0 || high == 0))
            {
-             if (! merge_ranges (&n_in_p, &n_low, &n_high, in_p, low, high,
-                                 1, fold_convert (arg0_type, integer_zero_node),
+             if (! merge_ranges (&n_in_p, &n_low, &n_high,
+                                 in_p, low, high, 1,
+                                 fold_convert (arg0_type, integer_zero_node),
                                  NULL_TREE))
                break;
 
@@ -3752,7 +3751,8 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
                {
                  if (! merge_ranges (&n_in_p, &n_low, &n_high,
                                      1, n_low, n_high, 1,
-                                     fold_convert (arg0_type, integer_zero_node),
+                                     fold_convert (arg0_type,
+                                                   integer_zero_node),
                                      high_positive))
                    break;
 
@@ -3764,7 +3764,8 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
                     that will be interpreted as negative.  */
                  if (! merge_ranges (&n_in_p, &n_low, &n_high,
                                      0, n_low, n_high, 1,
-                                     fold_convert (arg0_type, integer_zero_node),
+                                     fold_convert (arg0_type,
+                                                   integer_zero_node),
                                      high_positive))
                    break;
 
@@ -4180,7 +4181,7 @@ 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_unreachable ();
       }
 
   /* A != 0 ? A : 0 is simply A, unless A is -0.  Likewise
@@ -4193,7 +4194,7 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
       if (comp_code == NE_EXPR)
        return pedantic_non_lvalue (fold_convert (type, arg1));
       else if (comp_code == EQ_EXPR)
-       return pedantic_non_lvalue (fold_convert (type, integer_zero_node));
+       return fold_convert (type, integer_zero_node);
     }
 
   /* Try some transformations of A op B ? A : B.
@@ -4249,25 +4250,34 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
             so that we can convert this back to the
             corresponding COND_EXPR.  */
          if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
-           return pedantic_non_lvalue (
-                    fold_convert (type, fold (build2 (MIN_EXPR, comp_type,
-                                        (comp_code == LE_EXPR
-                                         ? comp_op0 : comp_op1),
-                                        (comp_code == LE_EXPR
-                                         ? comp_op1 : comp_op0)))));
+           {
+             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)));
+             return pedantic_non_lvalue (fold_convert (type, tem));
+           }
          break;
        case GE_EXPR:
        case GT_EXPR:
          if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
-           return pedantic_non_lvalue (
-                    fold_convert (type, fold (build2 (MAX_EXPR, comp_type,
-                                        (comp_code == GE_EXPR
-                                         ? comp_op0 : comp_op1),
-                                        (comp_code == GE_EXPR
-                                         ? comp_op1 : comp_op0)))));
+           {
+             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));
+             return pedantic_non_lvalue (fold_convert (type, tem));
+           }
          break;
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
 
@@ -4337,7 +4347,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;
@@ -4527,13 +4537,15 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
 
   if (lcode == BIT_AND_EXPR && integer_onep (TREE_OPERAND (lhs, 1)))
     {
-      lhs = build2 (NE_EXPR, truth_type, lhs, integer_zero_node);
+      lhs = build2 (NE_EXPR, truth_type, lhs,
+                   fold_convert (TREE_TYPE (lhs), integer_zero_node));
       lcode = NE_EXPR;
     }
 
   if (rcode == BIT_AND_EXPR && integer_onep (TREE_OPERAND (rhs, 1)))
     {
-      rhs = build2 (NE_EXPR, truth_type, rhs, integer_zero_node);
+      rhs = build2 (NE_EXPR, truth_type, rhs,
+                   fold_convert (TREE_TYPE (rhs), integer_zero_node));
       rcode = NE_EXPR;
     }
 
@@ -5073,9 +5085,9 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type)
                     && TYPE_IS_SIZETYPE (TREE_TYPE (op0)))
               && (GET_MODE_SIZE (TYPE_MODE (ctype))
                   > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0)))))
-             /* ... or its type is larger than ctype,
-                then we cannot pass through this truncation.  */
-             || (GET_MODE_SIZE (TYPE_MODE (ctype))
+             /* ... or this is a truncation (t is narrower than op0),
+                then we cannot pass through this narrowing.  */
+             || (GET_MODE_SIZE (TYPE_MODE (type))
                  < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0))))
              /* ... or signedness changes for division or modulus,
                 then we cannot pass through this conversion.  */
@@ -5122,8 +5134,12 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type)
     case LSHIFT_EXPR:  case RSHIFT_EXPR:
       /* If the second operand is constant, this is a multiplication
         or floor division, by a power of two, so we can treat it that
-        way unless the multiplier or divisor overflows.  */
+        way unless the multiplier or divisor overflows.  Signed
+        left-shift overflow is implementation-defined rather than
+        undefined in C90, so do not convert signed left shift into
+        multiplication.  */
       if (TREE_CODE (op1) == INTEGER_CST
+         && (tcode == RSHIFT_EXPR || TYPE_UNSIGNED (TREE_TYPE (op0)))
          /* const_binop may not detect overflow correctly,
             so check for it explicitly here.  */
          && TYPE_PRECISION (TREE_TYPE (size_one_node)) > TREE_INT_CST_LOW (op1)
@@ -5291,7 +5307,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type)
 /* Return a node which has the indicated constant VALUE (either 0 or
    1), and is of the indicated TYPE.  */
 
-static tree
+tree
 constant_boolean_node (int value, tree type)
 {
   if (type == integer_type_node)
@@ -5302,12 +5318,7 @@ constant_boolean_node (int value, tree type)
     return lang_hooks.truthvalue_conversion (value ? integer_one_node
                                                   : integer_zero_node);
   else
-    {
-      tree t = build_int_2 (value, 0);
-
-      TREE_TYPE (t) = type;
-      return t;
-    }
+    return build_int_cst (type, value);
 }
 
 /* Transform `a + (b ? x : y)' into `b ? (a + x) : (a + y)'.
@@ -5640,12 +5651,8 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
                         TREE_INT_CST_HIGH (arg01),
                         TREE_INT_CST_LOW (arg1),
                         TREE_INT_CST_HIGH (arg1), &lpart, &hpart);
-  prod = build_int_2 (lpart, hpart);
-  TREE_TYPE (prod) = TREE_TYPE (arg00);
-  TREE_OVERFLOW (prod) = force_fit_type (prod, overflow)
-                        || TREE_INT_CST_HIGH (prod) != hpart
-                        || TREE_INT_CST_LOW (prod) != lpart;
-  TREE_CONSTANT_OVERFLOW (prod) = TREE_OVERFLOW (prod);
+  prod = build_int_cst_wide (TREE_TYPE (arg00), lpart, hpart);
+  prod = force_fit_type (prod, -1, overflow, false);
 
   if (TYPE_UNSIGNED (TREE_TYPE (arg0)))
     {
@@ -5658,13 +5665,9 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
                             TREE_INT_CST_LOW (tmp),
                             TREE_INT_CST_HIGH (tmp),
                             &lpart, &hpart);
-      hi = build_int_2 (lpart, hpart);
-      TREE_TYPE (hi) = TREE_TYPE (arg00);
-      TREE_OVERFLOW (hi) = force_fit_type (hi, overflow)
-                          || TREE_INT_CST_HIGH (hi) != hpart
-                          || TREE_INT_CST_LOW (hi) != lpart
-                          || TREE_OVERFLOW (prod);
-      TREE_CONSTANT_OVERFLOW (hi) = TREE_OVERFLOW (hi);
+      hi = build_int_cst_wide (TREE_TYPE (arg00), lpart, hpart);
+      hi = force_fit_type (hi, -1, overflow | TREE_OVERFLOW (prod),
+                          TREE_CONSTANT_OVERFLOW (prod));
     }
   else if (tree_int_cst_sgn (arg01) >= 0)
     {
@@ -5687,7 +5690,7 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
   else
@@ -5711,7 +5714,7 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
 
@@ -5852,8 +5855,8 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
                        inner, size_int (bitnum));
 
       if (code == EQ_EXPR)
-       inner = build2 (BIT_XOR_EXPR, intermediate_type,
-                       inner, integer_one_node);
+       inner = fold (build2 (BIT_XOR_EXPR, intermediate_type,
+                             inner, integer_one_node));
 
       /* Put the AND last so it can combine with more things.  */
       inner = build2 (BIT_AND_EXPR, intermediate_type,
@@ -5973,11 +5976,6 @@ fold (tree expr)
      if all operands are constant.  */
   int wins = 1;
 
-  /* Don't try to process an RTL_EXPR since its operands aren't trees.
-     Likewise for a SAVE_EXPR that's already been evaluated.  */
-  if (code == RTL_EXPR || (code == SAVE_EXPR && SAVE_EXPR_RTL (t) != 0))
-    return t;
-
   /* Return right away if a constant.  */
   if (kind == 'c')
     return t;
@@ -6574,7 +6572,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;
                    }
@@ -6597,6 +6596,17 @@ fold (tree expr)
          if (fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0))
            return non_lvalue (fold_convert (type, arg1));
 
+         /* Convert X + -C into X - C.  */
+         if (TREE_CODE (arg1) == REAL_CST
+             && REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1)))
+           {
+             tem = fold_negate_const (arg1, type);
+             if (!TREE_OVERFLOW (arg1) || !flag_trapping_math)
+               return fold (build2 (MINUS_EXPR, type,
+                                    fold_convert (type, arg0),
+                                    fold_convert (type, tem)));
+           }
+
          /* Convert x+x into x*2.0.  */
          if (operand_equal_p (arg0, arg1, 0)
              && SCALAR_FLOAT_TYPE_P (type))
@@ -6929,7 +6939,10 @@ fold (tree expr)
 
       /* A - B -> A + (-B) if B is easily negatable.  */
       if (!wins && negate_expr_p (arg1)
-         && (FLOAT_TYPE_P (type)
+         && ((FLOAT_TYPE_P (type)
+               /* Avoid this transformation if B is a positive REAL_CST.  */
+              && (TREE_CODE (arg1) != REAL_CST
+                  ||  REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1))))
              || (INTEGRAL_TYPE_P (type) && flag_wrapv && !flag_trapv)))
        return fold (build2 (PLUS_EXPR, type, arg0, negate_expr (arg1)));
 
@@ -7194,9 +7207,8 @@ 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;
-         force_fit_type (t1, 0);
+         t1 = build_int_cst (type, -1);
+         t1 = force_fit_type (t1, 0, false, false);
          return omit_one_operand (type, t1, arg1);
        }
 
@@ -7204,9 +7216,8 @@ 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;
-         force_fit_type (t1, 0);
+         t1 = build_int_cst (type, -1);
+         t1 = force_fit_type (t1, 0, false, false);
          return omit_one_operand (type, t1, arg0);
        }
 
@@ -7245,9 +7256,8 @@ 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;
-         force_fit_type (t1, 0);
+         t1 = build_int_cst (type, -1);
+         t1 = force_fit_type (t1, 0, false, false);
          return omit_one_operand (type, t1, arg1);
        }
 
@@ -7255,9 +7265,8 @@ 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;
-         force_fit_type (t1, 0);
+         t1 = build_int_cst (type, -1);
+         t1 = force_fit_type (t1, 0, false, false);
          return omit_one_operand (type, t1, arg0);
        }
 
@@ -7545,6 +7554,7 @@ fold (tree expr)
        return omit_one_operand (type, integer_zero_node, arg0);
       if (integer_zerop (arg1))
        return t;
+
       /* X % -1 is zero.  */
       if (!TYPE_UNSIGNED (type)
          && TREE_CODE (arg1) == INTEGER_CST
@@ -7552,6 +7562,53 @@ fold (tree expr)
          && TREE_INT_CST_HIGH (arg1) == -1)
        return omit_one_operand (type, integer_zero_node, arg0);
 
+      /* Optimize unsigned TRUNC_MOD_EXPR by a power of two into a
+        BIT_AND_EXPR, i.e. "X % C" into "X & C2".  */
+      if (code == TRUNC_MOD_EXPR
+         && TYPE_UNSIGNED (type)
+         && integer_pow2p (arg1))
+       {
+         unsigned HOST_WIDE_INT high, low;
+         tree mask;
+         int l;
+
+         l = tree_log2 (arg1);
+         if (l >= HOST_BITS_PER_WIDE_INT)
+           {
+             high = ((unsigned HOST_WIDE_INT) 1
+                     << (l - HOST_BITS_PER_WIDE_INT)) - 1;
+             low = -1;
+           }
+         else
+           {
+             high = 0;
+             low = ((unsigned HOST_WIDE_INT) 1 << l) - 1;
+           }
+
+         mask = build_int_cst_wide (type, low, high);
+         return fold (build2 (BIT_AND_EXPR, type,
+                              fold_convert (type, arg0), mask));
+       }
+
+      /* X % -C is the same as X % C.  */
+      if (code == TRUNC_MOD_EXPR
+         && !TYPE_UNSIGNED (type)
+         && TREE_CODE (arg1) == INTEGER_CST
+         && TREE_INT_CST_HIGH (arg1) < 0
+         && !flag_trapv
+         /* Avoid this transformation if C is INT_MIN, i.e. C == -C.  */
+         && !sign_bit_p (arg1, arg1))
+       return fold (build2 (code, type, fold_convert (type, arg0),
+                            fold_convert (type, negate_expr (arg1))));
+
+      /* X % -Y is the same as X % Y.  */
+      if (code == TRUNC_MOD_EXPR
+         && !TYPE_UNSIGNED (type)
+         && TREE_CODE (arg1) == NEGATE_EXPR
+         && !flag_trapv)
+       return fold (build2 (code, type, fold_convert (type, arg0),
+                            fold_convert (type, TREE_OPERAND (arg1, 0))));
+
       if (TREE_CODE (arg1) == INTEGER_CST
          && 0 != (tem = extract_muldiv (TREE_OPERAND (t, 0), arg1,
                                         code, NULL_TREE)))
@@ -7586,7 +7643,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));
@@ -8003,8 +8061,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));
@@ -8275,13 +8333,14 @@ fold (tree expr)
          && integer_pow2p (TREE_OPERAND (arg0, 1)))
        {
          tree newtype = lang_hooks.types.unsigned_type (TREE_TYPE (arg0));
-         tree newmod = build2 (TREE_CODE (arg0), newtype,
-                               fold_convert (newtype,
-                                             TREE_OPERAND (arg0, 0)),
-                               fold_convert (newtype,
-                                             TREE_OPERAND (arg0, 1)));
+         tree newmod = fold (build2 (TREE_CODE (arg0), newtype,
+                                     fold_convert (newtype,
+                                                   TREE_OPERAND (arg0, 0)),
+                                     fold_convert (newtype,
+                                                   TREE_OPERAND (arg0, 1))));
 
-         return build2 (code, type, newmod, fold_convert (newtype, arg1));
+         return fold (build2 (code, type, newmod,
+                              fold_convert (newtype, arg1)));
        }
 
       /* If this is an NE comparison of zero with an AND of one, remove the
@@ -8298,7 +8357,8 @@ fold (tree expr)
          && integer_pow2p (TREE_OPERAND (arg0, 1))
          && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
        return fold (build2 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
-                            arg0, integer_zero_node));
+                            arg0, fold_convert (TREE_TYPE (arg0),
+                                                integer_zero_node)));
 
       /* If we have (A & C) != 0 or (A & C) == 0 and C is a power of
         2, then fold the expression into shifts and logical operations.  */
@@ -8394,7 +8454,7 @@ fold (tree expr)
            case LT_EXPR:
              return constant_boolean_node (0, type);
            default:
-             abort ();
+             gcc_unreachable ();
            }
        }
 
@@ -8566,8 +8626,9 @@ fold (tree expr)
              && ! TREE_CHAIN (arglist))
            return fold (build2 (code, type,
                                 build1 (INDIRECT_REF, char_type_node,
-                                        TREE_VALUE(arglist)),
-                                integer_zero_node));
+                                        TREE_VALUE (arglist)),
+                                fold_convert (char_type_node,
+                                              integer_zero_node)));
        }
 
       /* We can fold X/C1 op C2 where C1 and C2 are integer constants
@@ -8584,9 +8645,14 @@ fold (tree expr)
            return t1;
        }
 
-      /* Both ARG0 and ARG1 are known to be constants at this point.  */
+      if ((code == EQ_EXPR || code == NE_EXPR)
+         && !TREE_SIDE_EFFECTS (arg0)
+         && integer_zerop (arg1)
+         && tree_expr_nonzero_p (arg0))
+       return constant_boolean_node (code==NE_EXPR, type);
+
       t1 = fold_relational_const (code, type, arg0, arg1);
-      return (t1 == NULL_TREE ? t : t1);
+      return t1 == NULL_TREE ? t : t1;
 
     case UNORDERED_EXPR:
     case ORDERED_EXPR:
@@ -8625,6 +8691,16 @@ fold (tree expr)
          return omit_one_operand (type, t1, arg0);
        }
 
+      /* Simplify unordered comparison of something with itself.  */
+      if ((code == UNLE_EXPR || code == UNGE_EXPR || code == UNEQ_EXPR)
+         && operand_equal_p (arg0, arg1, 0))
+       return constant_boolean_node (1, type);
+
+      if (code == LTGT_EXPR
+         && !flag_trapping_math
+         && operand_equal_p (arg0, arg1, 0))
+       return constant_boolean_node (0, type);
+
       /* Fold (double)float1 CMP (double)float2 into float1 CMP float2.  */
       {
        tree targ0 = strip_float_extensions (arg0);
@@ -8744,6 +8820,7 @@ fold (tree expr)
          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,
@@ -8897,7 +8974,7 @@ fold (tree expr)
              == FUNCTION_DECL)
          && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
        {
-         tree tmp = fold_builtin (t);
+         tree tmp = fold_builtin (t, false);
          if (tmp)
            return tmp;
        }
@@ -8977,10 +9054,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);
@@ -8988,14 +9064,7 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
     return;
   *slot = expr;
   code = TREE_CODE (expr);
-  if (code == SAVE_EXPR && SAVE_EXPR_NOPLACEHOLDER (expr))
-    {
-      /* Allow SAVE_EXPR_NOPLACEHOLDER flag to be modified.  */
-      memcpy (buf, expr, tree_size (expr));
-      expr = (tree) buf;
-      SAVE_EXPR_NOPLACEHOLDER (expr) = 0;
-    }
-  else if (TREE_CODE_CLASS (code) == 'd' && DECL_ASSEMBLER_NAME_SET_P (expr))
+  if (TREE_CODE_CLASS (code) == 'd' && DECL_ASSEMBLER_NAME_SET_P (expr))
     {
       /* Allow DECL_ASSEMBLER_NAME to be modified.  */
       memcpy (buf, expr, tree_size (expr));
@@ -9015,7 +9084,6 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
   fold_checksum_tree (TREE_TYPE (expr), ctx, ht);
   if (TREE_CODE_CLASS (code) != 't' && TREE_CODE_CLASS (code) != 'd')
     fold_checksum_tree (TREE_CHAIN (expr), ctx, ht);
-  len = TREE_CODE_LENGTH (code);
   switch (TREE_CODE_CLASS (code))
     {
     case 'c':
@@ -9052,20 +9120,12 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
        }
       break;
     case 'e':
-      switch (code)
-       {
-       case SAVE_EXPR: len = 2; break;
-       case GOTO_SUBROUTINE_EXPR: len = 0; break;
-       case RTL_EXPR: len = 0; break;
-       case WITH_CLEANUP_EXPR: len = 2; break;
-       default: break;
-       }
-      /* Fall through.  */
     case 'r':
     case '<':
     case '1':
     case '2':
     case 's':
+      len = first_rtl_op (code);
       for (i = 0; i < len; ++i)
        fold_checksum_tree (TREE_OPERAND (expr, i), ctx, ht);
       break;
@@ -9374,8 +9434,6 @@ tree_expr_nonnegative_p (tree t)
       return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
     case FLOAT_EXPR:
       return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
-    case RTL_EXPR:
-      return rtl_expr_nonnegative_p (RTL_EXPR_RTL (t));
 
     case TARGET_EXPR:
       {
@@ -9526,7 +9584,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)
@@ -9561,11 +9622,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 (TREE_CODE_CLASS (TREE_CODE (base)) == 'c')
+         return true;
+
+       return false;
+      }
 
     case COND_EXPR:
       return (tree_expr_nonzero_p (TREE_OPERAND (t, 1))
@@ -9610,50 +9682,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.  */
@@ -10224,8 +10252,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;
 }
@@ -10240,28 +10269,31 @@ fold_negate_const (tree arg0, tree type)
 {
   tree t = NULL_TREE;
 
-  if (TREE_CODE (arg0) == INTEGER_CST)
+  switch (TREE_CODE (arg0))
     {
-      unsigned HOST_WIDE_INT low;
-      HOST_WIDE_INT high;
-      int overflow = neg_double (TREE_INT_CST_LOW (arg0),
-                                TREE_INT_CST_HIGH (arg0),
-                                &low, &high);
-      t = build_int_2 (low, high);
-      TREE_TYPE (t) = type;
-      TREE_OVERFLOW (t)
-       = (TREE_OVERFLOW (arg0)
-          | force_fit_type (t, overflow && !TYPE_UNSIGNED (type)));
-      TREE_CONSTANT_OVERFLOW (t)
-       = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg0);
-    }
-  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;
 }
 
@@ -10275,15 +10307,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
@@ -10293,28 +10326,23 @@ fold_abs_const (tree arg0, tree type)
          int overflow = neg_double (TREE_INT_CST_LOW (arg0),
                                     TREE_INT_CST_HIGH (arg0),
                                     &low, &high);
-         t = build_int_2 (low, high);
-         TREE_TYPE (t) = type;
-         TREE_OVERFLOW (t)
-           = (TREE_OVERFLOW (arg0)
-              | force_fit_type (t, overflow));
-         TREE_CONSTANT_OVERFLOW (t)
-           = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg0);
-         return t;
+         t = build_int_cst_wide (type, low, high);
+         t = force_fit_type (t, -1, overflow | TREE_OVERFLOW (arg0),
+                             TREE_CONSTANT_OVERFLOW (arg0));
        }
-    }
-  else if (TREE_CODE (arg0) == REAL_CST)
-    {
+      break;
+      
+    case REAL_CST:
       if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg0)))
-       return build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
+       t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
       else
-       return arg0;
+       t =  arg0;
+      break;
+      
+    default:
+      gcc_unreachable ();
     }
-#ifdef ENABLE_CHECKING
-  else
-    abort ();
-#endif
-
+  
   return t;
 }
 
@@ -10326,20 +10354,14 @@ fold_not_const (tree arg0, tree type)
 {
   tree t = NULL_TREE;
 
-  if (TREE_CODE (arg0) == INTEGER_CST)
-    {
-      t = build_int_2 (~ TREE_INT_CST_LOW (arg0),
-                      ~ TREE_INT_CST_HIGH (arg0));
-      TREE_TYPE (t) = type;
-      force_fit_type (t, 0);
-      TREE_OVERFLOW (t) = TREE_OVERFLOW (arg0);
-      TREE_CONSTANT_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (arg0);
-    }
-#ifdef ENABLE_CHECKING
-  else
-    abort ();
-#endif
-
+  gcc_assert (TREE_CODE (arg0) == INTEGER_CST);
+  
+  t = build_int_cst_wide (type,
+                         ~ TREE_INT_CST_LOW (arg0),
+                         ~ TREE_INT_CST_HIGH (arg0));
+  t = force_fit_type (t, 0, TREE_OVERFLOW (arg0),
+                     TREE_CONSTANT_OVERFLOW (arg0));
+  
   return t;
 }
 
@@ -10358,9 +10380,11 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
 
   if (TREE_CODE (op0) == REAL_CST && TREE_CODE (op1) == REAL_CST)
     {
+      const REAL_VALUE_TYPE *c0 = TREE_REAL_CST_PTR (op0);
+      const REAL_VALUE_TYPE *c1 = TREE_REAL_CST_PTR (op1);
+
       /* Handle the cases where either operand is a NaN.  */
-      if (REAL_VALUE_ISNAN (TREE_REAL_CST (op0))
-          || REAL_VALUE_ISNAN (TREE_REAL_CST (op1)))
+      if (real_isnan (c0) || real_isnan (c1))
        {
          switch (code)
            {
@@ -10390,43 +10414,13 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
              break;
 
            default:
-             abort ();
+             gcc_unreachable ();
            }
 
          return constant_boolean_node (result, type);
        }
 
-      /* From here on we're sure there are no NaNs.  */
-      switch (code)
-       {
-       case ORDERED_EXPR:
-         return constant_boolean_node (true, type);
-
-       case UNORDERED_EXPR:
-         return constant_boolean_node (false, type);
-
-       case UNLT_EXPR:
-         code = LT_EXPR;
-         break;
-       case UNLE_EXPR:
-         code = LE_EXPR;
-         break;
-       case UNGT_EXPR:
-         code = GT_EXPR;
-         break;
-       case UNGE_EXPR:
-         code = GE_EXPR;
-         break;
-       case UNEQ_EXPR:
-         code = EQ_EXPR;
-         break;
-       case LTGT_EXPR:
-         code = NE_EXPR;
-         break;
-
-       default:
-         break;
-       }
+      return constant_boolean_node (real_compare (code, c0, c1), type);
     }
 
   /* From here on we only handle LT, LE, GT, GE, EQ and NE.
@@ -10467,21 +10461,6 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
       else
        result = INT_CST_LT (op0, op1);
     }
-
-  else if (code == EQ_EXPR && !TREE_SIDE_EFFECTS (op0)
-           && integer_zerop (op1) && tree_expr_nonzero_p (op0))
-    result = 0;
-
-  /* Two real constants can be compared explicitly.  */
-  else if (TREE_CODE (op0) == REAL_CST && TREE_CODE (op1) == REAL_CST)
-    {
-      if (code == EQ_EXPR)
-       result = REAL_VALUES_EQUAL (TREE_REAL_CST (op0),
-                                   TREE_REAL_CST (op1));
-      else
-       result = REAL_VALUES_LESS (TREE_REAL_CST (op0),
-                                  TREE_REAL_CST (op1));
-    }
   else
     return NULL_TREE;
 
@@ -10496,6 +10475,10 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
 tree
 build_fold_addr_expr_with_type (tree t, tree ptrtype)
 {
+  /* 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);
+
   if (TREE_CODE (t) == INDIRECT_REF)
     {
       t = TREE_OPERAND (t, 0);
@@ -10561,4 +10544,142 @@ build_fold_indirect_ref (tree t)
   return build1 (INDIRECT_REF, type, t);
 }
 
-#include "gt-fold-const.h"
+/* Strip non-trapping, non-side-effecting tree nodes from an expression
+   whose result is ignored.  The type of the returned tree need not be
+   the same as the original expression.  */
+
+tree
+fold_ignored_result (tree t)
+{
+  if (!TREE_SIDE_EFFECTS (t))
+    return integer_zero_node;
+
+  for (;;)
+    switch (TREE_CODE_CLASS (TREE_CODE (t)))
+      {
+      case '1':
+       t = TREE_OPERAND (t, 0);
+       break;
+
+      case '2':
+      case '<':
+       if (!TREE_SIDE_EFFECTS (TREE_OPERAND (t, 1)))
+         t = TREE_OPERAND (t, 0);
+       else if (!TREE_SIDE_EFFECTS (TREE_OPERAND (t, 0)))
+         t = TREE_OPERAND (t, 1);
+       else
+         return t;
+       break;
+
+      case 'e':
+       switch (TREE_CODE (t))
+         {
+         case COMPOUND_EXPR:
+           if (TREE_SIDE_EFFECTS (TREE_OPERAND (t, 1)))
+             return t;
+           t = TREE_OPERAND (t, 0);
+           break;
+
+         case COND_EXPR:
+           if (TREE_SIDE_EFFECTS (TREE_OPERAND (t, 1))
+               || TREE_SIDE_EFFECTS (TREE_OPERAND (t, 2)))
+             return t;
+           t = TREE_OPERAND (t, 0);
+           break;
+
+         default:
+           return t;
+         }
+       break;
+
+      default:
+       return t;
+      }
+}
+
+/* Return the value of VALUE, rounded up to a multiple of DIVISOR.
+   This can only be applied to objects of a sizetype.  */
+
+tree
+round_up (tree value, int divisor)
+{
+  tree div = NULL_TREE;
+
+  gcc_assert (divisor > 0);
+  if (divisor == 1)
+    return value;
+
+  /* See if VALUE is already a multiple of DIVISOR.  If so, we don't
+     have to do anything.  Only do this when we are not given a const,
+     because in that case, this check is more expensive than just
+     doing it.  */
+  if (TREE_CODE (value) != INTEGER_CST)
+    {
+      div = build_int_cst (TREE_TYPE (value), divisor);
+
+      if (multiple_of_p (TREE_TYPE (value), value, div))
+       return value;
+    }
+
+  /* If divisor is a power of two, simplify this to bit manipulation.  */
+  if (divisor == (divisor & -divisor))
+    {
+      tree t;
+      
+      t = build_int_cst (TREE_TYPE (value), divisor - 1);
+      value = size_binop (PLUS_EXPR, value, t);
+      t = build_int_cst (TREE_TYPE (value), -divisor);
+      value = size_binop (BIT_AND_EXPR, value, t);
+    }
+  else
+    {
+      if (!div)
+       div = build_int_cst (TREE_TYPE (value), divisor);
+      value = size_binop (CEIL_DIV_EXPR, value, div);
+      value = size_binop (MULT_EXPR, value, div);
+    }
+
+  return value;
+}
+
+/* Likewise, but round down.  */
+
+tree
+round_down (tree value, int divisor)
+{
+  tree div = NULL_TREE;
+
+  gcc_assert (divisor > 0);
+  if (divisor == 1)
+    return value;
+
+  /* See if VALUE is already a multiple of DIVISOR.  If so, we don't
+     have to do anything.  Only do this when we are not given a const,
+     because in that case, this check is more expensive than just
+     doing it.  */
+  if (TREE_CODE (value) != INTEGER_CST)
+    {
+      div = build_int_cst (TREE_TYPE (value), divisor);
+
+      if (multiple_of_p (TREE_TYPE (value), value, div))
+       return value;
+    }
+
+  /* If divisor is a power of two, simplify this to bit manipulation.  */
+  if (divisor == (divisor & -divisor))
+    {
+      tree t;
+      
+      t = build_int_cst (TREE_TYPE (value), -divisor);
+      value = size_binop (BIT_AND_EXPR, value, t);
+    }
+  else
+    {
+      if (!div)
+       div = build_int_cst (TREE_TYPE (value), divisor);
+      value = size_binop (FLOOR_DIV_EXPR, value, div);
+      value = size_binop (MULT_EXPR, value, div);
+    }
+
+  return value;
+}