OSDN Git Service

2004-10-23 Daniel Berlin <dberlin@dberlin.org>
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index e85ead8..1dba1fb 100644 (file)
@@ -89,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);
@@ -192,11 +191,11 @@ 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.  */
 
@@ -209,9 +208,8 @@ force_fit_type (tree t, int overflowable,
   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);
 
@@ -268,8 +266,8 @@ force_fit_type (tree t, int overflowable,
   if (overflowed || overflowed_const
       || low != TREE_INT_CST_LOW (t) || high != TREE_INT_CST_HIGH (t))
     {
-      t = build_int_cst (TREE_TYPE (t), low, high);
-      
+      t = build_int_cst_wide (TREE_TYPE (t), low, high);
+
       if (overflowed
          || overflowable < 0
          || (overflowable > 0 && sign_extended_type))
@@ -284,7 +282,7 @@ force_fit_type (tree t, int overflowable,
          TREE_CONSTANT_OVERFLOW (t) = 1;
        }
     }
-  
+
   return t;
 }
 \f
@@ -827,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)  */
@@ -865,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)
@@ -888,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:
@@ -1409,10 +1424,10 @@ int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
-  t = build_int_cst (TREE_TYPE (arg1), low, hi);
+  t = build_int_cst_wide (TREE_TYPE (arg1), low, hi);
 
   if (notrunc)
     {
@@ -1436,7 +1451,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;
 }
 
@@ -1572,108 +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.  */
+/* 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.
@@ -1684,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)
@@ -1720,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
@@ -1752,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.  */
@@ -1776,8 +1719,8 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
 
          /* Given an integer constant, make new constant with new type,
             appropriately sign-extended or truncated.  */
-         t = build_int_cst (type, TREE_INT_CST_LOW (arg1),
-                            TREE_INT_CST_HIGH (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
@@ -1824,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.  */
@@ -1868,7 +1811,7 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
          if (! overflow)
            REAL_VALUE_TO_INT (&low, &high, r);
 
-         t = build_int_cst (type, low, high);
+         t = build_int_cst_wide (type, low, high);
 
          t = force_fit_type (t, -1, overflow | TREE_OVERFLOW (arg1),
                              TREE_CONSTANT_OVERFLOW (arg1));
@@ -1925,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);
@@ -1942,12 +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
-         && 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);
@@ -1961,56 +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 ();
        }
-    }
-  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 +1990,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:
@@ -2119,7 +2081,7 @@ invert_tree_comparison (enum tree_code code, bool honor_nans)
     case UNORDERED_EXPR:
       return ORDERED_EXPR;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -2143,7 +2105,7 @@ swap_tree_comparison (enum tree_code code)
     case LE_EXPR:
       return GE_EXPR;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -2186,7 +2148,7 @@ comparison_to_compcode (enum tree_code code)
     case UNGE_EXPR:
       return COMPCODE_UNGE;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -2228,7 +2190,7 @@ compcode_to_comparison (enum comparison_code code)
     case COMPCODE_UNGE:
       return UNGE_EXPR;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -2321,7 +2283,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);
@@ -2460,18 +2422,29 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
 
   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);
 
-    case '<':
-    case '2':
+    case tcc_comparison:
+    case tcc_binary:
       if (operand_equal_p (TREE_OPERAND (arg0, 0),
                           TREE_OPERAND (arg1, 0), flags)
          && operand_equal_p (TREE_OPERAND (arg0, 1),
@@ -2485,7 +2458,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)
@@ -2495,6 +2468,8 @@ 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),
@@ -2532,7 +2507,7 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
          return 0;
        }
 
-    case 'e':
+    case tcc_expression:
       switch (TREE_CODE (arg0))
        {
        case ADDR_EXPR:
@@ -2599,7 +2574,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)
@@ -2681,17 +2656,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
@@ -2699,24 +2674,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)
@@ -2726,7 +2701,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
@@ -2774,30 +2749,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:
@@ -2819,7 +2794,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);
@@ -2919,7 +2894,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)
@@ -2943,7 +2918,7 @@ invert_truthvalue (tree arg)
     {
     case INTEGER_CST:
       return fold_convert (type,
-                          build_int_cst (NULL_TREE, integer_zerop (arg), 0));
+                          build_int_cst (NULL_TREE, integer_zerop (arg)));
 
     case TRUTH_AND_EXPR:
       return build2 (TRUTH_OR_EXPR, type,
@@ -3019,8 +2994,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);
 }
 
@@ -3178,7 +3152,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_cst (unsigned_type, ~0, ~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);
@@ -3334,9 +3308,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_cst (unsigned_type, ~0, ~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);
 
@@ -3360,9 +3334,9 @@ all_ones_mask_p (tree mask, int size)
   unsigned int precision = TYPE_PRECISION (type);
   tree tmask;
 
-  tmask = build_int_cst (lang_hooks.types.signed_type (type), ~0, ~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,
@@ -3443,7 +3417,7 @@ simple_operand_p (tree exp)
             == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
     exp = TREE_OPERAND (exp, 0);
 
-  return (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c'
+  return (CONSTANT_CLASS_P (exp)
          || (DECL_P (exp)
              && ! TREE_ADDRESSABLE (exp)
              && ! TREE_THIS_VOLATILE (exp)
@@ -3514,7 +3488,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
@@ -3546,7 +3520,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);
@@ -3585,13 +3559,13 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
        {
          if (first_rtl_op (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);
        }
@@ -3635,7 +3609,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
@@ -4192,10 +4166,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)))
@@ -4203,6 +4184,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)))
@@ -4211,7 +4196,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
@@ -4275,6 +4261,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
@@ -4283,31 +4271,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;
        }
     }
 
@@ -4377,7 +4371,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;
@@ -4579,7 +4573,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);
@@ -4907,12 +4902,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);
        }
     }
@@ -5083,10 +5078,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
@@ -5104,10 +5099,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))
@@ -5348,7 +5343,7 @@ constant_boolean_node (int value, tree type)
     return lang_hooks.truthvalue_conversion (value ? integer_one_node
                                                   : integer_zero_node);
   else
-    return build_int_cst (type, value, 0);
+    return build_int_cst (type, value);
 }
 
 /* Transform `a + (b ? x : y)' into `b ? (a + x) : (a + y)'.
@@ -5681,7 +5676,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_cst (TREE_TYPE (arg00), lpart, hpart);
+  prod = build_int_cst_wide (TREE_TYPE (arg00), lpart, hpart);
   prod = force_fit_type (prod, -1, overflow, false);
 
   if (TYPE_UNSIGNED (TREE_TYPE (arg0)))
@@ -5695,7 +5690,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_cst (TREE_TYPE (arg00), lpart, hpart);
+      hi = build_int_cst_wide (TREE_TYPE (arg00), lpart, hpart);
       hi = force_fit_type (hi, -1, overflow | TREE_OVERFLOW (prod),
                           TREE_CONSTANT_OVERFLOW (prod));
     }
@@ -5720,11 +5715,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))
        {
@@ -5744,7 +5742,7 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
 
@@ -5907,7 +5905,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)
@@ -5957,15 +5955,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
@@ -6000,14 +5989,14 @@ fold (tree expr)
   tree tem;
   tree arg0 = NULL_TREE, arg1 = NULL_TREE;
   enum tree_code code = TREE_CODE (t);
-  int kind = TREE_CODE_CLASS (code);
+  enum tree_code_class kind = TREE_CODE_CLASS (code);
 
   /* WINS will be nonzero when the switch is done
      if all operands are constant.  */
   int wins = 1;
 
   /* Return right away if a constant.  */
-  if (kind == 'c')
+  if (kind == tcc_constant)
     return t;
 
   if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR)
@@ -6056,7 +6045,7 @@ fold (tree expr)
             of the arguments so that their form can be studied.  In any
             cases, the appropriate type conversions should be put back in
             the tree that will get out of the constant folder.  */
-         if (kind == '<')
+         if (kind == tcc_comparison)
            STRIP_SIGN_NOPS (op);
          else
            STRIP_NOPS (op);
@@ -6128,7 +6117,7 @@ fold (tree expr)
       return tem;
     }
 
-  if (TREE_CODE_CLASS (code) == '1')
+  if (TREE_CODE_CLASS (code) == tcc_unary)
     {
       if (TREE_CODE (arg0) == COMPOUND_EXPR)
        return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
@@ -6175,7 +6164,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)
            {
@@ -6191,16 +6180,16 @@ fold (tree expr)
                                               integer_zero_node))));
        }
    }
-  else if (TREE_CODE_CLASS (code) == '<'
+  else if (TREE_CODE_CLASS (code) == tcc_comparison
           && TREE_CODE (arg0) == COMPOUND_EXPR)
     return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
                   fold (build2 (code, type, TREE_OPERAND (arg0, 1), arg1)));
-  else if (TREE_CODE_CLASS (code) == '<'
+  else if (TREE_CODE_CLASS (code) == tcc_comparison
           && TREE_CODE (arg1) == COMPOUND_EXPR)
     return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
                   fold (build2 (code, type, arg0, TREE_OPERAND (arg1, 1))));
-  else if (TREE_CODE_CLASS (code) == '2'
-          || TREE_CODE_CLASS (code) == '<')
+  else if (TREE_CODE_CLASS (code) == tcc_binary
+          || TREE_CODE_CLASS (code) == tcc_comparison)
     {
       if (TREE_CODE (arg0) == COMPOUND_EXPR)
        return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
@@ -6212,8 +6201,7 @@ fold (tree expr)
                       fold (build2 (code, type,
                                     arg0, TREE_OPERAND (arg1, 1))));
 
-      if (TREE_CODE (arg0) == COND_EXPR
-         || TREE_CODE_CLASS (TREE_CODE (arg0)) == '<')
+      if (TREE_CODE (arg0) == COND_EXPR || COMPARISON_CLASS_P (arg0))
        {
          tem = fold_binary_op_with_conditional_arg (code, type, arg0, arg1,
                                                     /*cond_first_p=*/1);
@@ -6221,8 +6209,7 @@ fold (tree expr)
            return tem;
        }
 
-      if (TREE_CODE (arg1) == COND_EXPR
-         || TREE_CODE_CLASS (TREE_CODE (arg1)) == '<')
+      if (TREE_CODE (arg1) == COND_EXPR || COMPARISON_CLASS_P (arg1))
        {
          tem = fold_binary_op_with_conditional_arg (code, type, arg1, arg0,
                                                     /*cond_first_p=*/0);
@@ -6392,7 +6379,7 @@ fold (tree expr)
       /* Convert (T1)((T2)X op Y) into (T1)X op Y, for pointer types T1 and
         T2 being pointers to types of the same size.  */
       if (POINTER_TYPE_P (TREE_TYPE (t))
-         && TREE_CODE_CLASS (TREE_CODE (arg0)) == '2'
+         && BINARY_CLASS_P (arg0)
          && TREE_CODE (TREE_OPERAND (arg0, 0)) == NOP_EXPR
          && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (arg0, 0))))
        {
@@ -6603,7 +6590,7 @@ fold (tree expr)
                    {
                      alt0 = fold (build2 (MULT_EXPR, type, arg00,
                                           build_int_cst (NULL_TREE,
-                                                         int01 / int11, 0)));
+                                                         int01 / int11)));
                      alt1 = arg10;
                      same = arg11;
                    }
@@ -6693,7 +6680,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)
@@ -6708,7 +6695,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)
@@ -6976,6 +6963,18 @@ 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 (TREE_OPERAND (arg0, 0),
+                                    TREE_OPERAND (arg1, 0),
+                                    &diff))
+         return build_int_cst_type (type, diff);
+      }
+
       if (TREE_CODE (arg0) == MULT_EXPR
          && TREE_CODE (arg1) == MULT_EXPR
          && (INTEGRAL_TYPE_P (type) || flag_unsafe_math_optimizations))
@@ -7237,7 +7236,7 @@ fold (tree expr)
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
        {
-         t1 = build_int_cst (type, -1, -1);
+         t1 = build_int_cst (type, -1);
          t1 = force_fit_type (t1, 0, false, false);
          return omit_one_operand (type, t1, arg1);
        }
@@ -7246,7 +7245,7 @@ fold (tree expr)
       if (TREE_CODE (arg1) == BIT_NOT_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
        {
-         t1 = build_int_cst (type, -1, -1);
+         t1 = build_int_cst (type, -1);
          t1 = force_fit_type (t1, 0, false, false);
          return omit_one_operand (type, t1, arg0);
        }
@@ -7286,7 +7285,7 @@ fold (tree expr)
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
        {
-         t1 = build_int_cst (type, -1, -1);
+         t1 = build_int_cst (type, -1);
          t1 = force_fit_type (t1, 0, false, false);
          return omit_one_operand (type, t1, arg1);
        }
@@ -7295,7 +7294,7 @@ fold (tree expr)
       if (TREE_CODE (arg1) == BIT_NOT_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
        {
-         t1 = build_int_cst (type, -1, -1);
+         t1 = build_int_cst (type, -1);
          t1 = force_fit_type (t1, 0, false, false);
          return omit_one_operand (type, t1, arg0);
        }
@@ -7615,7 +7614,7 @@ fold (tree expr)
              low = ((unsigned HOST_WIDE_INT) 1 << l) - 1;
            }
 
-         mask = build_int_cst (type, low, high);
+         mask = build_int_cst_wide (type, low, high);
          return fold (build2 (BIT_AND_EXPR, type,
                               fold_convert (type, arg0), mask));
        }
@@ -7674,7 +7673,7 @@ fold (tree expr)
       if (code == LROTATE_EXPR && TREE_CODE (arg1) == INTEGER_CST)
        {
          tree tem = build_int_cst (NULL_TREE,
-                                   GET_MODE_BITSIZE (TYPE_MODE (type)), 0);
+                                   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));
@@ -8092,8 +8091,7 @@ fold (tree expr)
                return omit_one_operand (type, folded_compare, varop);
 
              shift = build_int_cst (NULL_TREE,
-                                    TYPE_PRECISION (TREE_TYPE (varop)) - size,
-                                    0);
+                                    TYPE_PRECISION (TREE_TYPE (varop)) - size);
              shift = fold_convert (TREE_TYPE (varop), shift);
              newconst = fold (build2 (LSHIFT_EXPR, TREE_TYPE (varop),
                                       newconst, shift));
@@ -8290,6 +8288,7 @@ fold (tree expr)
               && (t1 = get_unwidened (arg1, TREE_TYPE (tem))) != 0
               && (TREE_TYPE (t1) == TREE_TYPE (tem)
                   || (TREE_CODE (t1) == INTEGER_CST
+                      && TREE_CODE (TREE_TYPE (tem)) == INTEGER_TYPE
                       && int_fits_type_p (t1, TREE_TYPE (tem)))))
        return fold (build2 (code, type, tem,
                             fold_convert (TREE_TYPE (tem), t1)));
@@ -8404,11 +8403,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);
@@ -8421,10 +8420,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);
@@ -8485,7 +8483,7 @@ fold (tree expr)
            case LT_EXPR:
              return constant_boolean_node (0, type);
            default:
-             abort ();
+             gcc_unreachable ();
            }
        }
 
@@ -8771,7 +8769,7 @@ fold (tree expr)
         for reasons given above each one.
 
          Also try swapping the arguments and inverting the conditional.  */
-      if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
+      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))))
@@ -8783,14 +8781,14 @@ fold (tree expr)
            return tem;
        }
 
-      if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
+      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 (TREE_CODE_CLASS (TREE_CODE (tem)) == '<')
+         if (COMPARISON_CLASS_P (tem))
            {
              tem = fold_cond_expr_with_comparison (type, tem,
                                                    TREE_OPERAND (t, 2),
@@ -8957,47 +8955,6 @@ fold (tree expr)
                                           TREE_OPERAND (arg0, 1)))));
       return t;
 
-      /* Pull arithmetic ops out of the CLEANUP_POINT_EXPR where
-         appropriate.  */
-    case CLEANUP_POINT_EXPR:
-      if (! has_cleanups (arg0))
-       return TREE_OPERAND (t, 0);
-
-      {
-       enum tree_code code0 = TREE_CODE (arg0);
-       int kind0 = TREE_CODE_CLASS (code0);
-       tree arg00 = TREE_OPERAND (arg0, 0);
-       tree arg01;
-
-       if (kind0 == '1' || code0 == TRUTH_NOT_EXPR)
-         return fold (build1 (code0, type,
-                              fold (build1 (CLEANUP_POINT_EXPR,
-                                            TREE_TYPE (arg00), arg00))));
-
-       if (kind0 == '<' || kind0 == '2'
-           || code0 == TRUTH_ANDIF_EXPR || code0 == TRUTH_ORIF_EXPR
-           || code0 == TRUTH_AND_EXPR   || code0 == TRUTH_OR_EXPR
-           || code0 == TRUTH_XOR_EXPR)
-         {
-           arg01 = TREE_OPERAND (arg0, 1);
-
-           if (TREE_CONSTANT (arg00)
-               || ((code0 == TRUTH_ANDIF_EXPR || code0 == TRUTH_ORIF_EXPR)
-                   && ! has_cleanups (arg00)))
-             return fold (build2 (code0, type, arg00,
-                                  fold (build1 (CLEANUP_POINT_EXPR,
-                                                TREE_TYPE (arg01), arg01))));
-
-           if (TREE_CONSTANT (arg01))
-             return fold (build2 (code0, type,
-                                  fold (build1 (CLEANUP_POINT_EXPR,
-                                                TREE_TYPE (arg00), arg00)),
-                                  arg01));
-         }
-
-       return t;
-      }
-
     case CALL_EXPR:
       /* Check for a built-in function.  */
       if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
@@ -9085,10 +9042,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);
@@ -9096,29 +9052,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:
@@ -9136,7 +9097,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:
@@ -9151,17 +9112,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':
+    case tcc_expression:
+    case tcc_reference:
+    case tcc_comparison:
+    case tcc_unary:
+    case tcc_binary:
+    case tcc_statement:
       len = first_rtl_op (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);
@@ -9174,7 +9135,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);
@@ -9188,7 +9149,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:
@@ -9598,7 +9562,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)
@@ -9616,7 +9580,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)
@@ -9651,11 +9618,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))
@@ -9700,50 +9678,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.  */
@@ -10316,7 +10250,7 @@ fold_read_from_constant_string (tree exp)
        return fold_convert (TREE_TYPE (exp),
                             build_int_cst (NULL_TREE,
                                            (TREE_STRING_POINTER (string)
-                                            [TREE_INT_CST_LOW (index)]), 0));
+                                            [TREE_INT_CST_LOW (index)])));
     }
   return NULL;
 }
@@ -10331,25 +10265,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_cst (type, low, high);
-      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;
 }
@@ -10364,15 +10303,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
@@ -10382,23 +10322,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_cst (type, low, high);
+         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;
 }
@@ -10411,18 +10350,13 @@ fold_not_const (tree arg0, tree type)
 {
   tree t = NULL_TREE;
 
-  if (TREE_CODE (arg0) == INTEGER_CST)
-    {
-      t = build_int_cst (type,
-                        ~ TREE_INT_CST_LOW (arg0),
-                        ~ TREE_INT_CST_HIGH (arg0));
-      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;
 }
@@ -10476,7 +10410,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);
@@ -10531,13 +10465,34 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
   return constant_boolean_node (result, type);
 }
 
+/* Build an expression for the a clean point containing EXPR with type TYPE.
+   Don't build a cleanup point expression for EXPR which don't have side
+   effects.  */
+
+tree
+fold_build_cleanup_point_expr (tree type, tree expr)
+{
+  /* If the expression does not have side effects then we don't have to wrap
+     it with a cleanup point expression.  */
+  if (!TREE_SIDE_EFFECTS (expr))
+    return expr;
+  
+  return build1 (CLEANUP_POINT_EXPR, type, expr);
+}
+
 /* Build an expression for the address of T.  Folds away INDIRECT_REF to
    avoid confusing the gimplify process.  */
 
 tree
 build_fold_addr_expr_with_type (tree t, tree ptrtype)
 {
-  if (TREE_CODE (t) == INDIRECT_REF)
+  /* The size of the object is not relevant when talking about its address.  */
+  if (TREE_CODE (t) == WITH_SIZE_EXPR)
+    t = TREE_OPERAND (t, 0);
+
+  /* Note: doesn't apply to ALIGN_INDIRECT_REF */
+  if (TREE_CODE (t) == INDIRECT_REF
+      || TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
     {
       t = TREE_OPERAND (t, 0);
       if (TREE_TYPE (t) != ptrtype)
@@ -10615,12 +10570,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)))
@@ -10629,7 +10584,7 @@ fold_ignored_result (tree t)
          return t;
        break;
 
-      case 'e':
+      case tcc_expression:
        switch (TREE_CODE (t))
          {
          case COMPOUND_EXPR:
@@ -10663,18 +10618,17 @@ round_up (tree value, int divisor)
 {
   tree div = NULL_TREE;
 
-  if (divisor <= 0)
-    abort ();
+  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. */
+     doing it.  */
   if (TREE_CODE (value) != INTEGER_CST)
     {
-      div = size_int_type (divisor, TREE_TYPE (value));
+      div = build_int_cst (TREE_TYPE (value), divisor);
 
       if (multiple_of_p (TREE_TYPE (value), value, div))
        return value;
@@ -10684,16 +10638,16 @@ round_up (tree value, int divisor)
   if (divisor == (divisor & -divisor))
     {
       tree t;
-      
-      t = build_int_cst (TREE_TYPE (value), divisor - 1, 0);
+
+      t = build_int_cst (TREE_TYPE (value), divisor - 1);
       value = size_binop (PLUS_EXPR, value, t);
-      t = build_int_cst (TREE_TYPE (value), -divisor, -1);
+      t = build_int_cst (TREE_TYPE (value), -divisor);
       value = size_binop (BIT_AND_EXPR, value, t);
     }
   else
     {
       if (!div)
-       div = size_int_type (divisor, TREE_TYPE (value));
+       div = build_int_cst (TREE_TYPE (value), divisor);
       value = size_binop (CEIL_DIV_EXPR, value, div);
       value = size_binop (MULT_EXPR, value, div);
     }
@@ -10708,20 +10662,17 @@ round_down (tree value, int divisor)
 {
   tree div = NULL_TREE;
 
-  if (divisor <= 0)
-    abort ();
+  gcc_assert (divisor > 0);
   if (divisor == 1)
     return value;
 
-  div = size_int_type (divisor, TREE_TYPE (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. */
+     doing it.  */
   if (TREE_CODE (value) != INTEGER_CST)
     {
-      div = size_int_type (divisor, TREE_TYPE (value));
+      div = build_int_cst (TREE_TYPE (value), divisor);
 
       if (multiple_of_p (TREE_TYPE (value), value, div))
        return value;
@@ -10731,18 +10682,65 @@ round_down (tree value, int divisor)
   if (divisor == (divisor & -divisor))
     {
       tree t;
-      
-      t = build_int_cst (TREE_TYPE (value), -divisor, -1);
+
+      t = build_int_cst (TREE_TYPE (value), -divisor);
       value = size_binop (BIT_AND_EXPR, value, t);
     }
   else
     {
       if (!div)
-       div = size_int_type (divisor, TREE_TYPE (value));
+       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;
 }
-#include "gt-fold-const.h"
+
+/* 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 bitsize1, bitsize2;
+  HOST_WIDE_INT bitpos1, bitpos2;
+  tree toffset1, toffset2, tdiff, type;
+  enum machine_mode mode1, mode2;
+  int unsignedp1, unsignedp2, volatilep1, volatilep2;
+
+  core1 = get_inner_reference (e1, &bitsize1, &bitpos1, &toffset1, &mode1,
+                              &unsignedp1, &volatilep1);
+  core2 = get_inner_reference (e2, &bitsize2, &bitpos2, &toffset2, &mode2,
+                              &unsignedp2, &volatilep2);
+
+  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;
+}