OSDN Git Service

* tree.c (tree_fold_gcd): Use FLOOR_MOD_EXPR instead of
[pf3gnuchains/gcc-fork.git] / gcc / tree.c
index 392d997..1af25cb 100644 (file)
@@ -50,6 +50,23 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tree-flow.h"
 #include "params.h"
 
+/* Each tree code class has an associated string representation.
+   These must correspond to the tree_code_class entries.  */
+
+const char *const tree_code_class_strings[] =
+{
+  "exceptional",
+  "constant",
+  "type",
+  "declaration",
+  "reference",
+  "comparison",
+  "unary",
+  "binary",
+  "statement",
+  "expression",
+};
+
 /* obstack.[ch] explicitly declined to prototype this.  */
 extern int _obstack_allocated_p (struct obstack *h, void *obj);
 
@@ -108,9 +125,16 @@ struct type_hash GTY(())
 static GTY ((if_marked ("type_hash_marked_p"), param_is (struct type_hash)))
      htab_t type_hash_table;
 
+/* Hash table and temporary node for larger integer const values.  */
+static GTY (()) tree int_cst_node;
+static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
+     htab_t int_cst_hash_table;
+
 static void set_type_quals (tree, int);
 static int type_hash_eq (const void *, const void *);
 static hashval_t type_hash_hash (const void *);
+static hashval_t int_cst_hash_hash (const void *);
+static int int_cst_hash_eq (const void *, const void *);
 static void print_type_hash_statistics (void);
 static tree make_vector_type (tree, int, enum machine_mode);
 static int type_hash_marked_p (const void *);
@@ -128,6 +152,9 @@ init_ttree (void)
   /* Initialize the hash table of types.  */
   type_hash_table = htab_create_ggc (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
                                     type_hash_eq, 0);
+  int_cst_hash_table = htab_create_ggc (1024, int_cst_hash_hash,
+                                       int_cst_hash_eq, NULL);
+  int_cst_node = make_node (INTEGER_CST);
 }
 
 \f
@@ -142,47 +169,42 @@ decl_assembler_name (tree decl)
   return DECL_CHECK (decl)->decl.assembler_name;
 }
 
-/* Compute the number of bytes occupied by a tree with code CODE.  This
-   function cannot be used for TREE_VEC or PHI_NODE codes, which are of
-   variable length.  */
+/* Compute the number of bytes occupied by a tree with code CODE.
+   This function cannot be used for TREE_VEC, PHI_NODE, or STRING_CST
+   codes, which are of variable length.  */
 size_t
 tree_code_size (enum tree_code code)
 {
-  /* We can't state the size of a TREE_VEC or PHI_NODE
-     without knowing how many elements it will have.  */
-  gcc_assert (code != TREE_VEC);
-  gcc_assert (code != PHI_NODE);
-
   switch (TREE_CODE_CLASS (code))
     {
-    case 'd':  /* A decl node */
+    case tcc_declaration:  /* A decl node */
       return sizeof (struct tree_decl);
 
-    case 't':  /* a type node */
+    case tcc_type:  /* a type node */
       return sizeof (struct tree_type);
 
-    case 'r':  /* a reference */
-    case 'e':  /* an expression */
-    case 's':  /* an expression with side effects */
-    case '<':  /* a comparison expression */
-    case '1':  /* a unary arithmetic expression */
-    case '2':  /* a binary arithmetic expression */
+    case tcc_reference:   /* a reference */
+    case tcc_expression:  /* an expression */
+    case tcc_statement:   /* an expression with side effects */
+    case tcc_comparison:  /* a comparison expression */
+    case tcc_unary:       /* a unary arithmetic expression */
+    case tcc_binary:      /* a binary arithmetic expression */
       return (sizeof (struct tree_exp)
              + (TREE_CODE_LENGTH (code) - 1) * sizeof (char *));
 
-    case 'c':  /* a constant */
+    case tcc_constant:  /* a constant */
       switch (code)
        {
        case INTEGER_CST:       return sizeof (struct tree_int_cst);
        case REAL_CST:          return sizeof (struct tree_real_cst);
        case COMPLEX_CST:       return sizeof (struct tree_complex);
        case VECTOR_CST:        return sizeof (struct tree_vector);
-       case STRING_CST:        return sizeof (struct tree_string);
+       case STRING_CST:        gcc_unreachable ();
        default:
          return lang_hooks.tree_size (code);
        }
 
-    case 'x':  /* something random, like an identifier.  */
+    case tcc_exceptional:  /* something random, like an identifier.  */
       switch (code)
        {
        case IDENTIFIER_NODE:   return lang_hooks.identifier_size;
@@ -191,7 +213,8 @@ tree_code_size (enum tree_code code)
        case ERROR_MARK:
        case PLACEHOLDER_EXPR:  return sizeof (struct tree_common);
 
-       case PHI_NODE:          
+       case TREE_VEC:
+       case PHI_NODE:          gcc_unreachable ();
 
        case SSA_NAME:          return sizeof (struct tree_ssa_name);
 
@@ -224,6 +247,9 @@ tree_size (tree node)
       return (sizeof (struct tree_vec)
              + (TREE_VEC_LENGTH (node) - 1) * sizeof(char *));
 
+    case STRING_CST:
+      return sizeof (struct tree_string) + TREE_STRING_LENGTH (node) - 1;
+
     default:
       return tree_code_size (code);
     }
@@ -240,57 +266,73 @@ tree
 make_node_stat (enum tree_code code MEM_STAT_DECL)
 {
   tree t;
-  int type = TREE_CODE_CLASS (code);
+  enum tree_code_class type = TREE_CODE_CLASS (code);
   size_t length = tree_code_size (code);
 #ifdef GATHER_STATISTICS
   tree_node_kind kind;
 
   switch (type)
     {
-    case 'd':  /* A decl node */
+    case tcc_declaration:  /* A decl node */
       kind = d_kind;
       break;
 
-    case 't':  /* a type node */
+    case tcc_type:  /* a type node */
       kind = t_kind;
       break;
 
-    case 's':  /* an expression with side effects */
+    case tcc_statement:  /* an expression with side effects */
       kind = s_kind;
       break;
 
-    case 'r':  /* a reference */
+    case tcc_reference:  /* a reference */
       kind = r_kind;
       break;
 
-    case 'e':  /* an expression */
-    case '<':  /* a comparison expression */
-    case '1':  /* a unary arithmetic expression */
-    case '2':  /* a binary arithmetic expression */
+    case tcc_expression:  /* an expression */
+    case tcc_comparison:  /* a comparison expression */
+    case tcc_unary:  /* a unary arithmetic expression */
+    case tcc_binary:  /* a binary arithmetic expression */
       kind = e_kind;
       break;
 
-    case 'c':  /* a constant */
+    case tcc_constant:  /* a constant */
       kind = c_kind;
       break;
 
-    case 'x':  /* something random, like an identifier.  */
-      if (code == IDENTIFIER_NODE)
-       kind = id_kind;
-      else if (code == TREE_VEC)
-       kind = vec_kind;
-      else if (code == TREE_BINFO)
-       kind = binfo_kind;
-      else if (code == PHI_NODE)
-       kind = phi_kind;
-      else if (code == SSA_NAME)
-       kind = ssa_name_kind;
-      else if (code == BLOCK)
-       kind = b_kind;
-      else
-       kind = x_kind;
-      break;
+    case tcc_exceptional:  /* something random, like an identifier.  */
+      switch (code)
+       {
+       case IDENTIFIER_NODE:
+         kind = id_kind;
+         break;
+
+       case TREE_VEC:;
+         kind = vec_kind;
+         break;
 
+       case TREE_BINFO:
+         kind = binfo_kind;
+         break;
+
+       case PHI_NODE:
+         kind = phi_kind;
+         break;
+
+       case SSA_NAME:
+         kind = ssa_name_kind;
+         break;
+
+       case BLOCK:
+         kind = b_kind;
+         break;
+
+       default:
+         kind = x_kind;
+         break;
+       }
+      break;
+      
     default:
       gcc_unreachable ();
     }
@@ -307,11 +349,11 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
 
   switch (type)
     {
-    case 's':
+    case tcc_statement:
       TREE_SIDE_EFFECTS (t) = 1;
       break;
 
-    case 'd':
+    case tcc_declaration:
       if (code != FUNCTION_DECL)
        DECL_ALIGN (t) = 1;
       DECL_USER_ALIGN (t) = 0;
@@ -323,7 +365,7 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
       DECL_POINTER_ALIAS_SET (t) = -1;
       break;
 
-    case 't':
+    case tcc_type:
       TYPE_UID (t) = next_type_uid++;
       TYPE_ALIGN (t) = char_type_node ? TYPE_ALIGN (char_type_node) : 0;
       TYPE_USER_ALIGN (t) = 0;
@@ -337,12 +379,12 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
       TYPE_ALIAS_SET (t) = -1;
       break;
 
-    case 'c':
+    case tcc_constant:
       TREE_CONSTANT (t) = 1;
       TREE_INVARIANT (t) = 1;
       break;
 
-    case 'e':
+    case tcc_expression:
       switch (code)
        {
        case INIT_EXPR:
@@ -361,6 +403,10 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
          break;
        }
       break;
+
+    default:
+      /* Other classes need no special treatment.  */
+      break;
     }
 
   return t;
@@ -387,9 +433,9 @@ copy_node_stat (tree node MEM_STAT_DECL)
   TREE_VISITED (t) = 0;
   t->common.ann = 0;
 
-  if (TREE_CODE_CLASS (code) == 'd')
+  if (TREE_CODE_CLASS (code) == tcc_declaration)
     DECL_UID (t) = next_decl_uid++;
-  else if (TREE_CODE_CLASS (code) == 't')
+  else if (TREE_CODE_CLASS (code) == tcc_type)
     {
       TYPE_UID (t) = next_type_uid++;
       /* The following is so that the debug code for
@@ -486,8 +532,38 @@ build_int_cst_type (tree type, HOST_WIDE_INT low)
   return ret;
 }
 
+/* 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
+int_cst_hash_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)));
+}
+
+/* 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
+int_cst_hash_eq (const void *x, const void *y)
+{
+  tree xt = (tree) x;
+  tree yt = (tree) y;
+
+  return (TREE_TYPE (xt) == TREE_TYPE (yt)
+         && TREE_INT_CST_HIGH (xt) == TREE_INT_CST_HIGH (yt)
+         && TREE_INT_CST_LOW (xt) == TREE_INT_CST_LOW (yt));
+}
+
 /* Create an INT_CST node of TYPE and value HI:LOW.  If TYPE is NULL,
-   integer_type_node is used.  */
+   integer_type_node is used.  The returned node is always shared.
+   For small integers we use a per-type vector cache, for larger ones
+   we use a single hash table.  */
 
 tree
 build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
@@ -544,6 +620,7 @@ build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
 
   if (ix >= 0)
     {
+      /* Look for it in the type's vector of small shared ints.  */
       if (!TYPE_CACHED_VALUES_P (type))
        {
          TYPE_CACHED_VALUES_P (type) = 1;
@@ -557,22 +634,77 @@ build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
          gcc_assert (TREE_TYPE (t) == type);
          gcc_assert (TREE_INT_CST_LOW (t) == low);
          gcc_assert (TREE_INT_CST_HIGH (t) == hi);
-         return t;
        }
-    }
+      else
+       {
+         /* Create a new shared int.  */
+         t = make_node (INTEGER_CST);
 
-  t = make_node (INTEGER_CST);
+         TREE_INT_CST_LOW (t) = low;
+         TREE_INT_CST_HIGH (t) = hi;
+         TREE_TYPE (t) = type;
+         
+         TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t;
+       }
+    }
+  else
+    {
+      /* Use the cache of larger shared ints.  */
+      void **slot;
 
-  TREE_INT_CST_LOW (t) = low;
-  TREE_INT_CST_HIGH (t) = hi;
-  TREE_TYPE (t) = type;
+      TREE_INT_CST_LOW (int_cst_node) = low;
+      TREE_INT_CST_HIGH (int_cst_node) = hi;
+      TREE_TYPE (int_cst_node) = type;
 
-  if (ix >= 0)
-    TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t;
+      slot = htab_find_slot (int_cst_hash_table, int_cst_node, INSERT);
+      t = *slot;
+      if (!t)
+       {
+         /* Insert this one into the hash table.  */
+         t = int_cst_node;
+         *slot = t;
+         /* Make a new node for next time round.  */
+         int_cst_node = make_node (INTEGER_CST);
+       }
+    }
 
   return t;
 }
 
+/* Builds an integer constant in TYPE such that lowest BITS bits are ones
+   and the rest are zeros.  */
+
+tree
+build_low_bits_mask (tree type, unsigned bits)
+{
+  unsigned HOST_WIDE_INT low;
+  HOST_WIDE_INT high;
+  unsigned HOST_WIDE_INT all_ones = ~(unsigned HOST_WIDE_INT) 0;
+
+  gcc_assert (bits <= TYPE_PRECISION (type));
+
+  if (bits == TYPE_PRECISION (type)
+      && !TYPE_UNSIGNED (type))
+    {
+      /* Sign extended all-ones mask.  */
+      low = all_ones;
+      high = -1;
+    }
+  else if (bits <= HOST_BITS_PER_WIDE_INT)
+    {
+      low = all_ones >> (HOST_BITS_PER_WIDE_INT - bits);
+      high = 0;
+    }
+  else
+    {
+      bits -= HOST_BITS_PER_WIDE_INT;
+      low = all_ones;
+      high = all_ones >> (HOST_BITS_PER_WIDE_INT - bits);
+    }
+
+  return build_int_cst_wide (type, low, high);
+}
+
 /* Checks that X is integer constant that can be expressed in (unsigned)
    HOST_WIDE_INT without loss of precision.  */
 
@@ -701,10 +833,23 @@ build_real_from_int_cst (tree type, tree i)
 tree
 build_string (int len, const char *str)
 {
-  tree s = make_node (STRING_CST);
+  tree s;
+  size_t length;
+  
+  length = len + sizeof (struct tree_string);
 
+#ifdef GATHER_STATISTICS
+  tree_node_counts[(int) c_kind]++;
+  tree_node_sizes[(int) c_kind] += length;
+#endif  
+
+  s = ggc_alloc_tree (length);
+
+  memset (s, 0, sizeof (struct tree_common));
+  TREE_SET_CODE (s, STRING_CST);
   TREE_STRING_LENGTH (s) = len;
-  TREE_STRING_POINTER (s) = ggc_alloc_string (str, len);
+  memcpy ((char *) TREE_STRING_POINTER (s), str, len);
+  ((char *) TREE_STRING_POINTER (s))[len] = '\0';
 
   return s;
 }
@@ -1440,6 +1585,10 @@ staticp (tree arg)
              && ! DECL_NON_ADDR_CONST_P (arg)
              ? arg : NULL);
 
+    case CONST_DECL:
+      return ((TREE_STATIC (arg) || DECL_EXTERNAL (arg))
+             ? arg : NULL);
+
     case CONSTRUCTOR:
       return TREE_STATIC (arg) ? arg : NULL;
 
@@ -1463,6 +1612,8 @@ staticp (tree arg)
     case BIT_FIELD_REF:
       return NULL;
 
+    case MISALIGNED_INDIRECT_REF:
+    case ALIGN_INDIRECT_REF:
     case INDIRECT_REF:
       return TREE_CONSTANT (TREE_OPERAND (arg, 0)) ? arg : NULL;
 
@@ -1566,9 +1717,9 @@ skip_simple_arithmetic (tree expr)
   inner = expr;
   while (1)
     {
-      if (TREE_CODE_CLASS (TREE_CODE (inner)) == '1')
+      if (UNARY_CLASS_P (inner))
        inner = TREE_OPERAND (inner, 0);
-      else if (TREE_CODE_CLASS (TREE_CODE (inner)) == '2')
+      else if (BINARY_CLASS_P (inner))
        {
          if (TREE_INVARIANT (TREE_OPERAND (inner, 1)))
            inner = TREE_OPERAND (inner, 0);
@@ -1606,22 +1757,29 @@ tree_node_structure (tree t)
 
   switch (TREE_CODE_CLASS (code))
     {
-    case 'd':  return TS_DECL;
-    case 't':  return TS_TYPE;
-    case 'r': case '<': case '1': case '2': case 'e': case 's':
+    case tcc_declaration:
+      return TS_DECL;
+    case tcc_type:
+      return TS_TYPE;
+    case tcc_reference:
+    case tcc_comparison:
+    case tcc_unary:
+    case tcc_binary:
+    case tcc_expression:
+    case tcc_statement:
       return TS_EXP;
-    default:  /* 'c' and 'x' */
+    default:  /* tcc_constant and tcc_exceptional */
       break;
     }
   switch (code)
     {
-      /* 'c' cases.  */
+      /* tcc_constant cases.  */
     case INTEGER_CST:          return TS_INT_CST;
     case REAL_CST:             return TS_REAL_CST;
     case COMPLEX_CST:          return TS_COMPLEX;
     case VECTOR_CST:           return TS_VECTOR;
     case STRING_CST:           return TS_STRING;
-      /* 'x' cases.  */
+      /* tcc_exceptional cases.  */
     case ERROR_MARK:           return TS_COMMON;
     case IDENTIFIER_NODE:      return TS_IDENTIFIER;
     case TREE_LIST:            return TS_LIST;
@@ -1656,22 +1814,23 @@ contains_placeholder_p (tree exp)
 
   switch (TREE_CODE_CLASS (code))
     {
-    case 'r':
+    case tcc_reference:
       /* Don't look at any PLACEHOLDER_EXPRs that might be in index or bit
         position computations since they will be converted into a
         WITH_RECORD_EXPR involving the reference, which will assume
         here will be valid.  */
       return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0));
 
-    case 'x':
+    case tcc_exceptional:
       if (code == TREE_LIST)
        return (CONTAINS_PLACEHOLDER_P (TREE_VALUE (exp))
                || CONTAINS_PLACEHOLDER_P (TREE_CHAIN (exp)));
       break;
 
-    case '1':
-    case '2':  case '<':
-    case 'e':
+    case tcc_unary:
+    case tcc_binary:
+    case tcc_comparison:
+    case tcc_expression:
       switch (code)
        {
        case COMPOUND_EXPR:
@@ -1823,7 +1982,7 @@ substitute_in_expr (tree exp, tree f, tree r)
      /* If this expression is getting a value from a PLACEHOLDER_EXPR
        and it is the right field, replace it with R.  */
      for (inner = TREE_OPERAND (exp, 0);
-         TREE_CODE_CLASS (TREE_CODE (inner)) == 'r';
+         REFERENCE_CLASS_P (inner);
          inner = TREE_OPERAND (inner, 0))
        ;
      if (TREE_CODE (inner) == PLACEHOLDER_EXPR
@@ -1844,16 +2003,16 @@ substitute_in_expr (tree exp, tree f, tree r)
   else
     switch (TREE_CODE_CLASS (code))
       {
-      case 'c':
-      case 'd':
+      case tcc_constant:
+      case tcc_declaration:
        return exp;
 
-      case 'x':
-      case '1':
-      case '2':
-      case '<':
-      case 'e':
-      case 'r':
+      case tcc_exceptional:
+      case tcc_unary:
+      case tcc_binary:
+      case tcc_comparison:
+      case tcc_expression:
+      case tcc_reference:
        switch (first_rtl_op (code))
          {
          case 0:
@@ -1922,10 +2081,10 @@ substitute_placeholder_in_expr (tree exp, tree obj)
           elt = ((TREE_CODE (elt) == COMPOUND_EXPR
                   || TREE_CODE (elt) == COND_EXPR)
                  ? TREE_OPERAND (elt, 1)
-                 : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
-                    || TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
-                    || TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
-                    || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
+                 : (REFERENCE_CLASS_P (elt)
+                    || UNARY_CLASS_P (elt)
+                    || BINARY_CLASS_P (elt)
+                    || EXPRESSION_CLASS_P (elt))
                  ? TREE_OPERAND (elt, 0) : 0))
        if (TYPE_MAIN_VARIANT (TREE_TYPE (elt)) == need_type)
          return elt;
@@ -1934,10 +2093,10 @@ substitute_placeholder_in_expr (tree exp, tree obj)
           elt = ((TREE_CODE (elt) == COMPOUND_EXPR
                   || TREE_CODE (elt) == COND_EXPR)
                  ? TREE_OPERAND (elt, 1)
-                 : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
-                    || TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
-                    || TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
-                    || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
+                 : (REFERENCE_CLASS_P (elt)
+                    || UNARY_CLASS_P (elt)
+                    || BINARY_CLASS_P (elt)
+                    || EXPRESSION_CLASS_P (elt))
                  ? TREE_OPERAND (elt, 0) : 0))
        if (POINTER_TYPE_P (TREE_TYPE (elt))
            && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (elt)))
@@ -1963,17 +2122,17 @@ substitute_placeholder_in_expr (tree exp, tree obj)
   else
     switch (TREE_CODE_CLASS (code))
       {
-      case 'c':
-      case 'd':
+      case tcc_constant:
+      case tcc_declaration:
        return exp;
 
-      case 'x':
-      case '1':
-      case '2':
-      case '<':
-      case 'e':
-      case 'r':
-      case 's':
+      case tcc_exceptional:
+      case tcc_unary:
+      case tcc_binary:
+      case tcc_comparison:
+      case tcc_expression:
+      case tcc_reference:
+      case tcc_statement:
        switch (first_rtl_op (code))
          {
          case 0:
@@ -2145,13 +2304,13 @@ stabilize_reference_1 (tree e)
 
   switch (TREE_CODE_CLASS (code))
     {
-    case 'x':
-    case 't':
-    case 'd':
-    case '<':
-    case 's':
-    case 'e':
-    case 'r':
+    case tcc_exceptional:
+    case tcc_type:
+    case tcc_declaration:
+    case tcc_comparison:
+    case tcc_statement:
+    case tcc_expression:
+    case tcc_reference:
       /* If the expression has side-effects, then encase it in a SAVE_EXPR
         so that it will only be evaluated once.  */
       /* The reference (r) and comparison (<) classes could be handled as
@@ -2160,12 +2319,12 @@ stabilize_reference_1 (tree e)
        return save_expr (e);
       return e;
 
-    case 'c':
+    case tcc_constant:
       /* Constants need no processing.  In fact, we should never reach
         here.  */
       return e;
 
-    case '2':
+    case tcc_binary:
       /* Division is slow and tends to be compiled with jumps,
         especially the division by powers of 2 that is often
         found inside of an array reference.  So do it just once.  */
@@ -2179,7 +2338,7 @@ stabilize_reference_1 (tree e)
                         stabilize_reference_1 (TREE_OPERAND (e, 1)));
       break;
 
-    case '1':
+    case tcc_unary:
       /* Recursively stabilize each operand.  */
       result = build_nt (code, stabilize_reference_1 (TREE_OPERAND (e, 0)));
       break;
@@ -2252,16 +2411,13 @@ do { tree _node = (NODE); \
     }
 
   /* Now see what's inside.  If it's an INDIRECT_REF, copy our properties from
-     it.  If it's a decl, it's invariant and constant if the decl is static.
-     It's also invariant if it's a decl in the current function.  (Taking the
-     address of a volatile variable is not volatile.)  If it's a constant,
-     the address is both invariant and constant.  Otherwise it's neither.  */
+     the address, since &(*a)->b is a form of addition.  If it's a decl, it's
+     invariant and constant if the decl is static.  It's also invariant if it's
+     a decl in the current function.  Taking the address of a volatile variable
+     is not volatile.  If it's a constant, the address is both invariant and
+     constant.  Otherwise it's neither.  */
   if (TREE_CODE (node) == INDIRECT_REF)
-    {
-      /* If this is &((T*)0)->field, then this is a form of addition.  */
-      if (TREE_CODE (TREE_OPERAND (node, 0)) != INTEGER_CST)
-       UPDATE_TITCSE (node);
-    }
+    UPDATE_TITCSE (TREE_OPERAND (node, 0));
   else if (DECL_P (node))
     {
       if (staticp (node))
@@ -2271,7 +2427,7 @@ do { tree _node = (NODE); \
       else
        ti = tc = false;
     }
-  else if (TREE_CODE_CLASS (TREE_CODE (node)) == 'c')
+  else if (CONSTANT_CLASS_P (node))
     ;
   else
     {
@@ -2319,10 +2475,10 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
 #ifdef GATHER_STATISTICS
   switch (TREE_CODE_CLASS (code))
     {
-    case 's':  /* an expression with side effects */
+    case tcc_statement:  /* an expression with side effects */
       kind = s_kind;
       break;
-    case 'r':  /* a reference */
+    case tcc_reference:  /* a reference */
       kind = r_kind;
       break;
     default:
@@ -2357,7 +2513,7 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
       TREE_READONLY (t) = TREE_READONLY (node);
     }
 
-  if (TREE_CODE_CLASS (code) == 's')
+  if (TREE_CODE_CLASS (code) == tcc_statement)
     TREE_SIDE_EFFECTS (t) = 1;
   else switch (code)
     {
@@ -2374,6 +2530,8 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
       TREE_READONLY (t) = 0;
       break;
 
+    case MISALIGNED_INDIRECT_REF:
+    case ALIGN_INDIRECT_REF:
     case INDIRECT_REF:
       /* Whether a dereference is readonly has nothing to do with whether
         its operand is readonly.  */
@@ -2386,12 +2544,15 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
       break;
 
     default:
-      if (TREE_CODE_CLASS (code) == '1' && node && !TYPE_P (node)
+      if (TREE_CODE_CLASS (code) == tcc_unary
+         && node && !TYPE_P (node)
          && TREE_CONSTANT (node))
        TREE_CONSTANT (t) = 1;
-      if (TREE_CODE_CLASS (code) == '1' && node && TREE_INVARIANT (node))
+      if (TREE_CODE_CLASS (code) == tcc_unary
+         && node && TREE_INVARIANT (node))
        TREE_INVARIANT (t) = 1;
-      if (TREE_CODE_CLASS (code) == 'r' && node && TREE_THIS_VOLATILE (node))
+      if (TREE_CODE_CLASS (code) == tcc_reference
+         && node && TREE_THIS_VOLATILE (node))
        TREE_THIS_VOLATILE (t) = 1;
       break;
     }
@@ -2435,8 +2596,8 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
 
   /* Expressions without side effects may be constant if their
      arguments are as well.  */
-  constant = (TREE_CODE_CLASS (code) == '<'
-             || TREE_CODE_CLASS (code) == '2');
+  constant = (TREE_CODE_CLASS (code) == tcc_comparison
+             || TREE_CODE_CLASS (code) == tcc_binary);
   read_only = 1;
   side_effects = TREE_SIDE_EFFECTS (t);
   invariant = constant;
@@ -2449,7 +2610,8 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
   TREE_INVARIANT (t) = invariant;
   TREE_SIDE_EFFECTS (t) = side_effects;
   TREE_THIS_VOLATILE (t)
-    = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0);
+    = (TREE_CODE_CLASS (code) == tcc_reference
+       && arg0 && TREE_THIS_VOLATILE (arg0));
 
   return t;
 }
@@ -2497,7 +2659,8 @@ build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
 
   TREE_SIDE_EFFECTS (t) = side_effects;
   TREE_THIS_VOLATILE (t)
-    = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0);
+    = (TREE_CODE_CLASS (code) == tcc_reference
+       && arg0 && TREE_THIS_VOLATILE (arg0));
 
   return t;
 }
@@ -2526,7 +2689,8 @@ build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
 
   TREE_SIDE_EFFECTS (t) = side_effects;
   TREE_THIS_VOLATILE (t)
-    = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0);
+    = (TREE_CODE_CLASS (code) == tcc_reference
+       && arg0 && TREE_THIS_VOLATILE (arg0));
 
   return t;
 }
@@ -3829,12 +3993,12 @@ simple_cst_equal (tree t1, tree t2)
 
   switch (TREE_CODE_CLASS (code1))
     {
-    case '1':
-    case '2':
-    case '<':
-    case 'e':
-    case 'r':
-    case 's':
+    case tcc_unary:
+    case tcc_binary:
+    case tcc_comparison:
+    case tcc_expression:
+    case tcc_reference:
+    case tcc_statement:
       cmp = 1;
       for (i = 0; i < TREE_CODE_LENGTH (code1); i++)
        {
@@ -3976,7 +4140,7 @@ iterative_hash_expr (tree t, hashval_t val)
     default:
       class = TREE_CODE_CLASS (code);
 
-      if (class == 'd')
+      if (class == tcc_declaration)
        {
          /* Decls we can just compare by pointer.  */
          val = iterative_hash_pointer (t, val);
@@ -4170,7 +4334,7 @@ build_index_type (tree maxval)
   TREE_TYPE (itype) = sizetype;
   TYPE_PRECISION (itype) = TYPE_PRECISION (sizetype);
   TYPE_MIN_VALUE (itype) = size_zero_node;
-  TYPE_MAX_VALUE (itype) = convert (sizetype, maxval);
+  TYPE_MAX_VALUE (itype) = fold_convert (sizetype, maxval);
   TYPE_MODE (itype) = TYPE_MODE (sizetype);
   TYPE_SIZE (itype) = TYPE_SIZE (sizetype);
   TYPE_SIZE_UNIT (itype) = TYPE_SIZE_UNIT (sizetype);
@@ -4265,9 +4429,12 @@ build_array_type (tree elt_type, tree index_type)
   t = make_node (ARRAY_TYPE);
   TREE_TYPE (t) = elt_type;
   TYPE_DOMAIN (t) = index_type;
-
+  
   if (index_type == 0)
-    return t;
+    {
+      layout_type (t);
+      return t;
+    }
 
   hashcode = iterative_hash_object (TYPE_HASH (elt_type), hashcode);
   hashcode = iterative_hash_object (TYPE_HASH (index_type), hashcode);
@@ -4774,7 +4941,8 @@ find_var_from_fn (tree *tp, int *walk_subtrees, void *data)
   if (TYPE_P (*tp))
     *walk_subtrees = 0;
 
-  else if (DECL_P (*tp) && lang_hooks.tree_inlining.auto_var_in_fn_p (*tp, fn))
+  else if (DECL_P (*tp)
+          && lang_hooks.tree_inlining.auto_var_in_fn_p (*tp, fn))
     return *tp;
 
   return NULL_TREE;
@@ -5312,12 +5480,13 @@ tree_not_check_failed (const tree node, const char *file,
    code, given in CL.  */
 
 void
-tree_class_check_failed (const tree node, int cl, const char *file,
-                        int line, const char *function)
+tree_class_check_failed (const tree node, const enum tree_code_class cl,
+                        const char *file, int line, const char *function)
 {
   internal_error
-    ("tree check: expected class %qc, have %qc (%s) in %s, at %s:%d",
-     cl, TREE_CODE_CLASS (TREE_CODE (node)),
+    ("tree check: expected class %qs, have %qs (%s) in %s, at %s:%d",
+     TREE_CODE_CLASS_STRING (cl),
+     TREE_CODE_CLASS_STRING (TREE_CODE_CLASS (TREE_CODE (node))),
      tree_code_name[TREE_CODE (node)], function, trim_filename (file), line);
 }
 
@@ -5592,10 +5761,15 @@ reconstruct_complex_type (tree type, tree bottom)
     }
   else if (TREE_CODE (type) == METHOD_TYPE)
     {
+      tree argtypes;
       inner = reconstruct_complex_type (TREE_TYPE (type), bottom);
+      /* The build_method_type_directly() routine prepends 'this' to argument list,
+         so we must compensate by getting rid of it.  */
+      argtypes = TYPE_ARG_TYPES (type);
       outer = build_method_type_directly (TYPE_METHOD_BASETYPE (type),
                                          inner,
                                          TYPE_ARG_TYPES (type));
+      TYPE_ARG_TYPES (outer) = argtypes;
     }
   else
     return bottom;
@@ -5855,7 +6029,7 @@ tree_fold_gcd (tree a, tree b)
 
   while (1)
     {
-      a_mod_b = fold (build2 (CEIL_MOD_EXPR, type, a, b));
+      a_mod_b = fold (build2 (FLOOR_MOD_EXPR, type, a, b));
 
       if (!TREE_INT_CST_LOW (a_mod_b)
          && !TREE_INT_CST_HIGH (a_mod_b))
@@ -5866,4 +6040,20 @@ tree_fold_gcd (tree a, tree b)
     }
 }
 
+/* Returns unsigned variant of TYPE.  */
+
+tree
+unsigned_type_for (tree type)
+{
+  return lang_hooks.types.unsigned_type (type);
+}
+
+/* Returns signed variant of TYPE.  */
+
+tree
+signed_type_for (tree type)
+{
+  return lang_hooks.types.signed_type (type);
+}
+
 #include "gt-tree.h"