OSDN Git Service

PR c++/15815
[pf3gnuchains/gcc-fork.git] / gcc / tree.c
index 6a62e71..410acdf 100644 (file)
@@ -45,6 +45,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "output.h"
 #include "target.h"
 #include "langhooks.h"
+#include "tree-iterator.h"
+#include "basic-block.h"
+#include "tree-flow.h"
+#include "opts.h"
 
 /* obstack.[ch] explicitly declined to prototype this.  */
 extern int _obstack_allocated_p (struct obstack *h, void *obj);
@@ -68,6 +72,9 @@ static const char * const tree_node_kind_names[] = {
   "perm_tree_lists",
   "temp_tree_lists",
   "vecs",
+  "binfos",
+  "phi_nodes",
+  "ssa names",
   "random kinds",
   "lang_decl kinds",
   "lang_type kinds"
@@ -88,6 +95,9 @@ struct type_hash GTY(())
   tree type;
 };
 
+/* Additional language-dependent binfo slots.  */
+unsigned binfo_lang_slots;
+
 /* Initial size of the hash table (rounded to next prime).  */
 #define TYPE_HASH_INITIAL_SIZE 1000
 
@@ -150,9 +160,6 @@ tree_size (tree node)
     case 't':  /* a type node */
       return sizeof (struct tree_type);
 
-    case 'b':  /* a lexical block node */
-      return sizeof (struct tree_block);
-
     case 'r':  /* a reference */
     case 'e':  /* an expression */
     case 's':  /* an expression with side effects */
@@ -186,6 +193,16 @@ tree_size (tree node)
        case ERROR_MARK:
        case PLACEHOLDER_EXPR:  return sizeof (struct tree_common);
 
+       case PHI_NODE:          return (sizeof (struct tree_phi_node)
+                                       + (PHI_ARG_CAPACITY (node) - 1) *
+                                       sizeof (struct phi_arg_d));
+
+       case SSA_NAME:          return sizeof (struct tree_ssa_name);
+
+       case STATEMENT_LIST:    return sizeof (struct tree_statement_list);
+       case BLOCK:             return sizeof (struct tree_block);
+       case VALUE_HANDLE:      return sizeof (struct tree_value_handle);
+
        default:
          return lang_hooks.tree_size (code);
        }
@@ -212,9 +229,9 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
 #endif
   struct tree_common ttmp;
 
-  /* We can't allocate a TREE_VEC without knowing how many elements
-     it will have.  */
-  if (code == TREE_VEC)
+  /* We can't allocate a TREE_VEC, PHI_NODE, or STRING_CST
+     without knowing how many elements it will have.  */
+  if (code == TREE_VEC || code == PHI_NODE)
     abort ();
 
   TREE_SET_CODE ((tree)&ttmp, code);
@@ -231,10 +248,6 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
       kind = t_kind;
       break;
 
-    case 'b':  /* a lexical block */
-      kind = b_kind;
-      break;
-
     case 's':  /* an expression with side effects */
       kind = s_kind;
       break;
@@ -259,6 +272,14 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
        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;
@@ -289,7 +310,10 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
       DECL_USER_ALIGN (t) = 0;
       DECL_IN_SYSTEM_HEADER (t) = in_system_header;
       DECL_SOURCE_LOCATION (t) = input_location;
-      DECL_UID (t) = next_decl_uid++;
+      if (code == TRANSLATION_UNIT_DECL)
+       DECL_UID (t) = cur_in_fname;
+      else
+       DECL_UID (t) = next_decl_uid++;
 
       /* We have not yet computed the alias set for this declaration.  */
       DECL_POINTER_ALIAS_SET (t) = -1;
@@ -303,7 +327,7 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
 
       /* Default to no attributes for type, but let target change that.  */
       TYPE_ATTRIBUTES (t) = NULL_TREE;
-      (*targetm.set_default_type_attributes) (t);
+      targetm.set_default_type_attributes (t);
 
       /* We have not yet computed the alias set for this type.  */
       TYPE_ALIAS_SET (t) = -1;
@@ -311,6 +335,7 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
 
     case 'c':
       TREE_CONSTANT (t) = 1;
+      TREE_INVARIANT (t) = 1;
       break;
 
     case 'e':
@@ -319,7 +344,6 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
        case INIT_EXPR:
        case MODIFY_EXPR:
        case VA_ARG_EXPR:
-       case RTL_EXPR:
        case PREDECREMENT_EXPR:
        case PREINCREMENT_EXPR:
        case POSTDECREMENT_EXPR:
@@ -348,14 +372,21 @@ copy_node_stat (tree node MEM_STAT_DECL)
   enum tree_code code = TREE_CODE (node);
   size_t length;
 
+#ifdef ENABLE_CHECKING
+  if (code == STATEMENT_LIST)
+    abort ();
+#endif
+
   length = tree_size (node);
   t = ggc_alloc_zone_stat (length, tree_zone PASS_MEM_STAT);
   memcpy (t, node, length);
 
   TREE_CHAIN (t) = 0;
   TREE_ASM_WRITTEN (t) = 0;
+  TREE_VISITED (t) = 0;
+  t->common.ann = 0;
 
-  if (TREE_CODE_CLASS (code) == 'd')
+  if (TREE_CODE_CLASS (code) == 'd' && code != TRANSLATION_UNIT_DECL)
     DECL_UID (t) = next_decl_uid++;
   else if (TREE_CODE_CLASS (code) == 't')
     {
@@ -456,9 +487,8 @@ build_constructor (tree type, tree vals)
       TREE_SIDE_EFFECTS (c) = TREE_SIDE_EFFECTS (vals);
       TREE_READONLY (c) = TREE_READONLY (vals);
       TREE_CONSTANT (c) = TREE_CONSTANT (vals);
+      TREE_INVARIANT (c) = TREE_INVARIANT (vals);
     }
-  else
-    TREE_CONSTANT (c) = 0;  /* safe side */
 
   return c;
 }
@@ -499,7 +529,7 @@ real_value_from_int_cst (tree type, tree i)
 
   real_from_integer (&d, type ? TYPE_MODE (type) : VOIDmode,
                     TREE_INT_CST_LOW (i), TREE_INT_CST_HIGH (i),
-                    TREE_UNSIGNED (TREE_TYPE (i)));
+                    TYPE_UNSIGNED (TREE_TYPE (i)));
   return d;
 }
 
@@ -553,6 +583,39 @@ build_complex (tree type, tree real, tree imag)
   return t;
 }
 
+/* Build a BINFO with LEN language slots.  */
+
+tree
+make_tree_binfo_stat (unsigned lang_slots MEM_STAT_DECL)
+{
+  tree t;
+  static unsigned length;
+  
+  if (!length)
+    {
+      length = (offsetof (struct tree_binfo, lang_slots)
+               + (sizeof (((struct tree_binfo *)0)->lang_slots[0])
+                  * lang_slots));
+      binfo_lang_slots = lang_slots;
+    }
+  else if (binfo_lang_slots != lang_slots)
+    abort ();
+  
+#ifdef GATHER_STATISTICS
+  tree_node_counts[(int) binfo_kind]++;
+  tree_node_sizes[(int) binfo_kind] += length;
+#endif
+
+  t = ggc_alloc_zone_stat (length, tree_zone PASS_MEM_STAT);
+
+  memset (t, 0, length);
+
+  TREE_SET_CODE (t, TREE_BINFO);
+
+  return t;
+}
+
+
 /* Build a newly constructed TREE_VEC node of length LEN.  */
 
 tree
@@ -630,7 +693,7 @@ integer_all_onesp (tree expr)
           || TREE_CONSTANT_OVERFLOW (expr))
     return 0;
 
-  uns = TREE_UNSIGNED (TREE_TYPE (expr));
+  uns = TYPE_UNSIGNED (TREE_TYPE (expr));
   if (!uns)
     return (TREE_INT_CST_LOW (expr) == ~(unsigned HOST_WIDE_INT) 0
            && TREE_INT_CST_HIGH (expr) == -1);
@@ -941,11 +1004,23 @@ chain_member (tree elem, tree chain)
 int
 list_length (tree t)
 {
-  tree tail;
+  tree p = t;
+#ifdef ENABLE_TREE_CHECKING
+  tree q = t;
+#endif
   int len = 0;
 
-  for (tail = t; tail; tail = TREE_CHAIN (tail))
-    len++;
+  while (p)
+    {
+      p = TREE_CHAIN (p);
+#ifdef ENABLE_TREE_CHECKING
+      if (len % 2)
+       q = TREE_CHAIN (q);
+      if (p == q)
+       abort ();
+#endif
+      len++;
+    }
 
   return len;
 }
@@ -1061,44 +1136,6 @@ tree_cons_stat (tree purpose, tree value, tree chain MEM_STAT_DECL)
   return node;
 }
 
-/* Return the first expression in a sequence of COMPOUND_EXPRs.  */
-
-tree
-expr_first (tree expr)
-{
-  if (expr == NULL_TREE)
-    return expr;
-  while (TREE_CODE (expr) == COMPOUND_EXPR)
-    expr = TREE_OPERAND (expr, 0);
-  return expr;
-}
-
-/* Return the last expression in a sequence of COMPOUND_EXPRs.  */
-
-tree
-expr_last (tree expr)
-{
-  if (expr == NULL_TREE)
-    return expr;
-  while (TREE_CODE (expr) == COMPOUND_EXPR)
-    expr = TREE_OPERAND (expr, 1);
-  return expr;
-}
-
-/* Return the number of subexpressions in a sequence of COMPOUND_EXPRs.  */
-
-int
-expr_length (tree expr)
-{
-  int len = 0;
-
-  if (expr == NULL_TREE)
-    return 0;
-  for (; TREE_CODE (expr) == COMPOUND_EXPR; expr = TREE_OPERAND (expr, 1))
-    len += expr_length (TREE_OPERAND (expr, 0));
-  ++len;
-  return len;
-}
 \f
 /* Return the size nominally occupied by an object of type TYPE
    when it resides in memory.  The value is measured in units of bytes,
@@ -1211,7 +1248,7 @@ expr_align (tree t)
 
     case SAVE_EXPR:         case COMPOUND_EXPR:       case MODIFY_EXPR:
     case INIT_EXPR:         case TARGET_EXPR:         case WITH_CLEANUP_EXPR:
-    case WITH_RECORD_EXPR:  case CLEANUP_POINT_EXPR:  case UNSAVE_EXPR:
+    case CLEANUP_POINT_EXPR:  case UNSAVE_EXPR:
       /* These don't change the alignment of an object.  */
       return expr_align (TREE_OPERAND (t, 0));
 
@@ -1258,7 +1295,7 @@ array_type_nelts (tree type)
 
   return (integer_zerop (min)
          ? max
-         : fold (build (MINUS_EXPR, TREE_TYPE (max), max, min)));
+         : fold (build2 (MINUS_EXPR, TREE_TYPE (max), max, min)));
 }
 \f
 /* Return nonzero if arg is static -- a reference to an object in
@@ -1287,11 +1324,18 @@ staticp (tree arg)
     case STRING_CST:
       return 1;
 
+    case COMPONENT_REF:
+      /* If the thing being referenced is not a field, then it is 
+        something language specific.  */
+      if (TREE_CODE (TREE_OPERAND (arg, 1)) != FIELD_DECL)
+       return (*lang_hooks.staticp) (arg);
+
       /* If we are referencing a bitfield, we can't evaluate an
         ADDR_EXPR at compile time and so it isn't a constant.  */
-    case COMPONENT_REF:
-      return (! DECL_BIT_FIELD (TREE_OPERAND (arg, 1))
-             && staticp (TREE_OPERAND (arg, 0)));
+      if (DECL_BIT_FIELD (TREE_OPERAND (arg, 1)))
+       return 0;
+
+      return staticp (TREE_OPERAND (arg, 0));
 
     case BIT_FIELD_REF:
       return 0;
@@ -1309,6 +1353,8 @@ staticp (tree arg)
       if (TREE_CODE (TYPE_SIZE (TREE_TYPE (arg))) == INTEGER_CST
          && TREE_CODE (TREE_OPERAND (arg, 1)) == INTEGER_CST)
        return staticp (TREE_OPERAND (arg, 0));
+      else
+       return 0;
 
     default:
       if ((unsigned int) TREE_CODE (arg)
@@ -1353,7 +1399,8 @@ save_expr (tree expr)
      Since it is no problem to reevaluate literals, we just return the
      literal node.  */
   inner = skip_simple_arithmetic (t);
-  if (TREE_CONSTANT (inner)
+
+  if (TREE_INVARIANT (inner)
       || (TREE_READONLY (inner) && ! TREE_SIDE_EFFECTS (inner))
       || TREE_CODE (inner) == SAVE_EXPR
       || TREE_CODE (inner) == ERROR_MARK)
@@ -1371,13 +1418,14 @@ save_expr (tree expr)
   if (contains_placeholder_p (inner))
     return t;
 
-  t = build (SAVE_EXPR, TREE_TYPE (expr), t, current_function_decl, NULL_TREE);
+  t = build1 (SAVE_EXPR, TREE_TYPE (expr), t);
 
   /* This expression might be placed ahead of a jump to ensure that the
      value was computed on both sides of the jump.  So make sure it isn't
      eliminated as dead.  */
   TREE_SIDE_EFFECTS (t) = 1;
   TREE_READONLY (t) = 1;
+  TREE_INVARIANT (t) = 1;
   return t;
 }
 
@@ -1405,9 +1453,9 @@ skip_simple_arithmetic (tree expr)
        inner = TREE_OPERAND (inner, 0);
       else if (TREE_CODE_CLASS (TREE_CODE (inner)) == '2')
        {
-         if (TREE_CONSTANT (TREE_OPERAND (inner, 1)))
+         if (TREE_INVARIANT (TREE_OPERAND (inner, 1)))
            inner = TREE_OPERAND (inner, 0);
-         else if (TREE_CONSTANT (TREE_OPERAND (inner, 0)))
+         else if (TREE_INVARIANT (TREE_OPERAND (inner, 0)))
            inner = TREE_OPERAND (inner, 1);
          else
            break;
@@ -1419,15 +1467,6 @@ skip_simple_arithmetic (tree expr)
   return inner;
 }
 
-/* Return TRUE if EXPR is a SAVE_EXPR or wraps simple arithmetic around a
-   SAVE_EXPR.  Return FALSE otherwise.  */
-
-bool
-saved_expr_p (tree expr)
-{
-  return TREE_CODE (skip_simple_arithmetic (expr)) == SAVE_EXPR;
-}
-
 /* Arrange for an expression to be expanded multiple independent
    times.  This is useful for cleanup actions, as the backend can
    expand them multiple times in different places.  */
@@ -1454,10 +1493,7 @@ first_rtl_op (enum tree_code code)
 {
   switch (code)
     {
-    case SAVE_EXPR:
-      return 2;
     case GOTO_SUBROUTINE_EXPR:
-    case RTL_EXPR:
       return 0;
     case WITH_CLEANUP_EXPR:
       return 2;
@@ -1477,7 +1513,6 @@ tree_node_structure (tree t)
     {
     case 'd':  return TS_DECL;
     case 't':  return TS_TYPE;
-    case 'b':  return TS_BLOCK;
     case 'r': case '<': case '1': case '2': case 'e': case 's':
       return TS_EXP;
     default:  /* 'c' and 'x' */
@@ -1496,7 +1531,13 @@ tree_node_structure (tree t)
     case IDENTIFIER_NODE:      return TS_IDENTIFIER;
     case TREE_LIST:            return TS_LIST;
     case TREE_VEC:             return TS_VEC;
+    case PHI_NODE:             return TS_PHI_NODE;
+    case SSA_NAME:             return TS_SSA_NAME;
     case PLACEHOLDER_EXPR:     return TS_COMMON;
+    case STATEMENT_LIST:       return TS_STATEMENT_LIST;
+    case BLOCK:                        return TS_BLOCK;
+    case TREE_BINFO:           return TS_BINFO;
+    case VALUE_HANDLE:         return TS_VALUE_HANDLE;
 
     default:
       abort ();
@@ -1511,11 +1552,6 @@ unsave_expr_1 (tree expr)
 {
   switch (TREE_CODE (expr))
     {
-    case SAVE_EXPR:
-      if (! SAVE_EXPR_PERSISTENT_P (expr))
-       SAVE_EXPR_RTL (expr) = 0;
-      break;
-
     case TARGET_EXPR:
       /* Don't mess with a TARGET_EXPR that hasn't been expanded.
          It's OK for this to happen if it was part of a subtree that
@@ -1528,68 +1564,11 @@ unsave_expr_1 (tree expr)
       TREE_OPERAND (expr, 3) = NULL_TREE;
       break;
 
-    case RTL_EXPR:
-      /* I don't yet know how to emit a sequence multiple times.  */
-      if (RTL_EXPR_SEQUENCE (expr) != 0)
-       abort ();
-      break;
-
     default:
       break;
     }
 }
 
-/* Default lang hook for "unsave_expr_now".  */
-
-tree
-lhd_unsave_expr_now (tree expr)
-{
-  enum tree_code code;
-
-  /* There's nothing to do for NULL_TREE.  */
-  if (expr == 0)
-    return expr;
-
-  unsave_expr_1 (expr);
-
-  code = TREE_CODE (expr);
-  switch (TREE_CODE_CLASS (code))
-    {
-    case 'c':  /* a constant */
-    case 't':  /* a type node */
-    case 'd':  /* A decl node */
-    case 'b':  /* A block node */
-      break;
-
-    case 'x':  /* miscellaneous: e.g., identifier, TREE_LIST or ERROR_MARK.  */
-      if (code == TREE_LIST)
-       {
-         lhd_unsave_expr_now (TREE_VALUE (expr));
-         lhd_unsave_expr_now (TREE_CHAIN (expr));
-       }
-      break;
-
-    case 'e':  /* an expression */
-    case 'r':  /* a reference */
-    case 's':  /* an expression with side effects */
-    case '<':  /* a comparison expression */
-    case '2':  /* a binary arithmetic expression */
-    case '1':  /* a unary arithmetic expression */
-      {
-       int i;
-
-       for (i = first_rtl_op (code) - 1; i >= 0; i--)
-         lhd_unsave_expr_now (TREE_OPERAND (expr, i));
-      }
-      break;
-
-    default:
-      abort ();
-    }
-
-  return expr;
-}
-
 /* Return 0 if it is safe to evaluate EXPR multiple times,
    return 1 if it is safe if EXPR is unsaved afterward, or
    return 2 if it is completely unsafe.
@@ -1601,10 +1580,7 @@ lhd_unsave_expr_now (tree expr)
    SAVE_EXPRs basically *only* appear replicated in an expression tree,
    occasionally across the whole of a function.  It is therefore only
    safe to unsave a SAVE_EXPR if you know that all occurrences appear
-   below the UNSAVE_EXPR.
-
-   RTL_EXPRs consume their rtl during evaluation.  It is therefore
-   never possible to unsave them.  */
+   below the UNSAVE_EXPR.  */
 
 int
 unsafe_for_reeval (tree expr)
@@ -1624,9 +1600,16 @@ unsafe_for_reeval (tree expr)
   switch (code)
     {
     case SAVE_EXPR:
-    case RTL_EXPR:
       return 2;
 
+      /* A label can only be emitted once.  */
+    case LABEL_EXPR:
+      return 1;
+
+    case BIND_EXPR:
+      unsafeness = 1;
+      break;
+
     case TREE_LIST:
       for (exp = expr; exp != 0; exp = TREE_CHAIN (exp))
        {
@@ -1665,7 +1648,6 @@ unsafe_for_reeval (tree expr)
     case 't':  /* a type node */
     case 'x':  /* something random, like an identifier or an ERROR_MARK.  */
     case 'd':  /* A decl node */
-    case 'b':  /* A block node */
       return 0;
 
     case 'e':  /* an expression */
@@ -1694,17 +1676,12 @@ bool
 contains_placeholder_p (tree exp)
 {
   enum tree_code code;
-  int result;
 
   if (!exp)
     return 0;
 
-  /* If we have a WITH_RECORD_EXPR, it "cancels" any PLACEHOLDER_EXPR
-     in it since it is supplying a value for it.  */
   code = TREE_CODE (exp);
-  if (code == WITH_RECORD_EXPR)
-    return 0;
-  else if (code == PLACEHOLDER_EXPR)
+  if (code == PLACEHOLDER_EXPR)
     return 1;
 
   switch (TREE_CODE_CLASS (code))
@@ -1731,36 +1708,16 @@ contains_placeholder_p (tree exp)
          /* Ignoring the first operand isn't quite right, but works best.  */
          return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1));
 
-       case RTL_EXPR:
-       case CONSTRUCTOR:
-         return 0;
-
        case COND_EXPR:
          return (CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0))
                  || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1))
                  || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 2)));
 
-       case SAVE_EXPR:
-         /* If we already know this doesn't have a placeholder, don't
-            check again.  */
-         if (SAVE_EXPR_NOPLACEHOLDER (exp) || SAVE_EXPR_RTL (exp) != 0)
-           return 0;
-
-         SAVE_EXPR_NOPLACEHOLDER (exp) = 1;
-         result = CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0));
-         if (result)
-           SAVE_EXPR_NOPLACEHOLDER (exp) = 0;
-
-         return result;
-
-       case CALL_EXPR:
-         return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1));
-
        default:
          break;
        }
 
-      switch (TREE_CODE_LENGTH (code))
+      switch (first_rtl_op (code))
        {
        case 1:
          return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0));
@@ -1798,7 +1755,6 @@ type_contains_placeholder_p (tree type)
     {
     case VOID_TYPE:
     case COMPLEX_TYPE:
-    case VECTOR_TYPE:
     case ENUMERAL_TYPE:
     case BOOLEAN_TYPE:
     case CHAR_TYPE:
@@ -1818,6 +1774,7 @@ type_contains_placeholder_p (tree type)
 
     case ARRAY_TYPE:
     case SET_TYPE:
+    case VECTOR_TYPE:
       /* We're already checked the component type (TREE_TYPE), so just check
         the index type.  */
       return type_contains_placeholder_p (TYPE_DOMAIN (type));
@@ -1909,6 +1866,10 @@ has_cleanups (tree exp)
        }
       return 0;
 
+    case DECL_EXPR:
+      return (DECL_INITIAL (DECL_EXPR_DECL (exp))
+             && has_cleanups (DECL_INITIAL (DECL_EXPR_DECL (exp))));
+
     default:
       break;
     }
@@ -1951,168 +1912,226 @@ substitute_in_expr (tree exp, tree f, tree r)
   tree new;
   tree inner;
 
-  switch (TREE_CODE_CLASS (code))
+  /* We handle TREE_LIST and COMPONENT_REF separately.  */
+  if (code == TREE_LIST)
     {
-    case 'c':
-    case 'd':
-      return exp;
-
-    case 'x':
-      if (code == PLACEHOLDER_EXPR)
+      op0 = SUBSTITUTE_IN_EXPR (TREE_CHAIN (exp), f, r);
+      op1 = SUBSTITUTE_IN_EXPR (TREE_VALUE (exp), f, r);
+      if (op0 == TREE_CHAIN (exp) && op1 == TREE_VALUE (exp))
        return exp;
-      else if (code == TREE_LIST)
-       {
-         op0 = (TREE_CHAIN (exp) == 0
-                ? 0 : substitute_in_expr (TREE_CHAIN (exp), f, r));
-         op1 = substitute_in_expr (TREE_VALUE (exp), f, r);
-         if (op0 == TREE_CHAIN (exp) && op1 == TREE_VALUE (exp))
-           return exp;
-
-         return tree_cons (TREE_PURPOSE (exp), op1, op0);
-       }
 
-      abort ();
+      return tree_cons (TREE_PURPOSE (exp), op1, op0);
+    }
+  else if (code == COMPONENT_REF)
+   {
+     /* 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';
+         inner = TREE_OPERAND (inner, 0))
+       ;
+     if (TREE_CODE (inner) == PLACEHOLDER_EXPR
+        && TREE_OPERAND (exp, 1) == f)
+       return r;
+
+     /* If this expression hasn't been completed let, leave it
+       alone.  */
+     if (TREE_CODE (inner) == PLACEHOLDER_EXPR && TREE_TYPE (inner) == 0)
+       return exp;
+
+     op0 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 0), f, r);
+     if (op0 == TREE_OPERAND (exp, 0))
+       return exp;
+
+     new = fold (build (code, TREE_TYPE (exp), op0, TREE_OPERAND (exp, 1),
+                       NULL_TREE));
+   }
+  else
+    switch (TREE_CODE_CLASS (code))
+      {
+      case 'c':
+      case 'd':
+       return exp;
 
-    case '1':
-    case '2':
-    case '<':
-    case 'e':
-      switch (TREE_CODE_LENGTH (code))
-       {
-       case 1:
-         op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
-         if (op0 == TREE_OPERAND (exp, 0))
+      case 'x':
+      case '1':
+      case '2':
+      case '<':
+      case 'e':
+      case 'r':
+       switch (first_rtl_op (code))
+         {
+         case 0:
            return exp;
 
-         if (code == NON_LVALUE_EXPR)
-           return op0;
+         case 1:
+           op0 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 0), f, r);
+           if (op0 == TREE_OPERAND (exp, 0))
+             return exp;
 
-         new = fold (build1 (code, TREE_TYPE (exp), op0));
-         break;
-
-       case 2:
-         /* An RTL_EXPR cannot contain a PLACEHOLDER_EXPR; a CONSTRUCTOR
-            could, but we don't support it.  */
-         if (code == RTL_EXPR)
-           return exp;
-         else if (code == CONSTRUCTOR)
-           abort ();
+           new = fold (build1 (code, TREE_TYPE (exp), op0));
+           break;
 
-         op0 = TREE_OPERAND (exp, 0);
-         op1 = TREE_OPERAND (exp, 1);
-         if (CONTAINS_PLACEHOLDER_P (op0))
-           op0 = substitute_in_expr (op0, f, r);
-         if (CONTAINS_PLACEHOLDER_P (op1))
-           op1 = substitute_in_expr (op1, f, r);
+         case 2:
+           op0 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 0), f, r);
+           op1 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 1), f, r);
 
-         if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1))
-           return exp;
+           if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1))
+             return exp;
 
-         new = fold (build (code, TREE_TYPE (exp), op0, op1));
-         break;
+           new = fold (build2 (code, TREE_TYPE (exp), op0, op1));
+           break;
 
-       case 3:
-         /* It cannot be that anything inside a SAVE_EXPR contains a
-            PLACEHOLDER_EXPR.  */
-         if (code == SAVE_EXPR)
-           return exp;
+         case 3:
+           op0 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 0), f, r);
+           op1 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 1), f, r);
+           op2 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 2), f, r);
 
-         else if (code == CALL_EXPR)
-           {
-             op1 = substitute_in_expr (TREE_OPERAND (exp, 1), f, r);
-             if (op1 == TREE_OPERAND (exp, 1))
-               return exp;
+           if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)
+               && op2 == TREE_OPERAND (exp, 2))
+             return exp;
 
-             return build (code, TREE_TYPE (exp),
-                           TREE_OPERAND (exp, 0), op1, NULL_TREE);
-           }
+           new = fold (build3 (code, TREE_TYPE (exp), op0, op1, op2));
+           break;
 
-         else if (code != COND_EXPR)
+         default:
            abort ();
+         }
+       break;
 
-         op0 = TREE_OPERAND (exp, 0);
-         op1 = TREE_OPERAND (exp, 1);
-         op2 = TREE_OPERAND (exp, 2);
-
-         if (CONTAINS_PLACEHOLDER_P (op0))
-           op0 = substitute_in_expr (op0, f, r);
-         if (CONTAINS_PLACEHOLDER_P (op1))
-           op1 = substitute_in_expr (op1, f, r);
-         if (CONTAINS_PLACEHOLDER_P (op2))
-           op2 = substitute_in_expr (op2, f, r);
-
-         if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)
-             && op2 == TREE_OPERAND (exp, 2))
-           return exp;
-
-         new = fold (build (code, TREE_TYPE (exp), op0, op1, op2));
-         break;
-
-       default:
-         abort ();
-       }
+      default:
+       abort ();
+      }
 
-      break;
+  TREE_READONLY (new) = TREE_READONLY (exp);
+  return new;
+}
 
-    case 'r':
-      switch (code)
-       {
-       case COMPONENT_REF:
-         /* 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';
-              inner = TREE_OPERAND (inner, 0))
-           ;
-         if (TREE_CODE (inner) == PLACEHOLDER_EXPR
-             && TREE_OPERAND (exp, 1) == f)
-           return r;
-
-         /* If this expression hasn't been completed let, leave it
-            alone.  */
-         if (TREE_CODE (inner) == PLACEHOLDER_EXPR
-             && TREE_TYPE (inner) == 0)
-           return exp;
+/* Similar, but look for a PLACEHOLDER_EXPR in EXP and find a replacement
+   for it within OBJ, a tree that is an object or a chain of references.  */
 
-         op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
-         if (op0 == TREE_OPERAND (exp, 0))
-           return exp;
+tree
+substitute_placeholder_in_expr (tree exp, tree obj)
+{
+  enum tree_code code = TREE_CODE (exp);
+  tree op0, op1, op2, op3;
 
-         new = fold (build (code, TREE_TYPE (exp), op0,
-                            TREE_OPERAND (exp, 1)));
-         break;
+  /* If this is a PLACEHOLDER_EXPR, see if we find a corresponding type
+     in the chain of OBJ.  */
+  if (code == PLACEHOLDER_EXPR)
+    {
+      tree need_type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
+      tree elt;
+
+      for (elt = obj; elt != 0;
+          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')
+                 ? TREE_OPERAND (elt, 0) : 0))
+       if (TYPE_MAIN_VARIANT (TREE_TYPE (elt)) == need_type)
+         return elt;
+
+      for (elt = obj; elt != 0;
+          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')
+                 ? TREE_OPERAND (elt, 0) : 0))
+       if (POINTER_TYPE_P (TREE_TYPE (elt))
+           && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (elt)))
+               == need_type))
+         return fold (build1 (INDIRECT_REF, need_type, elt));
+
+      /* If we didn't find it, return the original PLACEHOLDER_EXPR.  If it
+        survives until RTL generation, there will be an error.  */
+      return exp;
+    }
 
-       case BIT_FIELD_REF:
-         op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
-         op1 = substitute_in_expr (TREE_OPERAND (exp, 1), f, r);
-         op2 = substitute_in_expr (TREE_OPERAND (exp, 2), f, r);
-         if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)
-             && op2 == TREE_OPERAND (exp, 2))
-           return exp;
+  /* TREE_LIST is special because we need to look at TREE_VALUE
+     and TREE_CHAIN, not TREE_OPERANDS.  */
+  else if (code == TREE_LIST)
+    {
+      op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_CHAIN (exp), obj);
+      op1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_VALUE (exp), obj);
+      if (op0 == TREE_CHAIN (exp) && op1 == TREE_VALUE (exp))
+       return exp;
 
-         new = fold (build (code, TREE_TYPE (exp), op0, op1, op2));
-         break;
+      return tree_cons (TREE_PURPOSE (exp), op1, op0);
+    }
+  else
+    switch (TREE_CODE_CLASS (code))
+      {
+      case 'c':
+      case 'd':
+       return exp;
 
-       case INDIRECT_REF:
-       case BUFFER_REF:
-         op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
-         if (op0 == TREE_OPERAND (exp, 0))
+      case 'x':
+      case '1':
+      case '2':
+      case '<':
+      case 'e':
+      case 'r':
+      case 's':
+       switch (first_rtl_op (code))
+         {
+         case 0:
            return exp;
 
-         new = fold (build1 (code, TREE_TYPE (exp), op0));
-         break;
-
-       default:
-         abort ();
-       }
-      break;
-
-    default:
-      abort ();
-    }
+         case 1:
+           op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj);
+           if (op0 == TREE_OPERAND (exp, 0))
+             return exp;
+           else
+             return fold (build1 (code, TREE_TYPE (exp), op0));
+
+         case 2:
+           op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj);
+           op1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 1), obj);
+
+           if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1))
+             return exp;
+           else
+             return fold (build2 (code, TREE_TYPE (exp), op0, op1));
+
+         case 3:
+           op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj);
+           op1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 1), obj);
+           op2 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 2), obj);
+
+           if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)
+               && op2 == TREE_OPERAND (exp, 2))
+             return exp;
+           else
+             return fold (build3 (code, TREE_TYPE (exp), op0, op1, op2));
+
+         case 4:
+           op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj);
+           op1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 1), obj);
+           op2 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 2), obj);
+           op3 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 3), obj);
+
+           if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)
+               && op2 == TREE_OPERAND (exp, 2)
+               && op3 == TREE_OPERAND (exp, 3))
+             return exp;
+           else
+             return fold (build4 (code, TREE_TYPE (exp), op0, op1, op2, op3));
+
+         default:
+           abort ();
+         }
+       break;
 
-  TREE_READONLY (new) = TREE_READONLY (exp);
-  return new;
+      default:
+       abort ();
+      }
 }
 \f
 /* Stabilize a reference so that we can use it any number of times
@@ -2155,7 +2174,7 @@ stabilize_reference (tree ref)
     case COMPONENT_REF:
       result = build_nt (COMPONENT_REF,
                         stabilize_reference (TREE_OPERAND (ref, 0)),
-                        TREE_OPERAND (ref, 1));
+                        TREE_OPERAND (ref, 1), NULL_TREE);
       break;
 
     case BIT_FIELD_REF:
@@ -2168,13 +2187,15 @@ stabilize_reference (tree ref)
     case ARRAY_REF:
       result = build_nt (ARRAY_REF,
                         stabilize_reference (TREE_OPERAND (ref, 0)),
-                        stabilize_reference_1 (TREE_OPERAND (ref, 1)));
+                        stabilize_reference_1 (TREE_OPERAND (ref, 1)),
+                        TREE_OPERAND (ref, 2), TREE_OPERAND (ref, 3));
       break;
 
     case ARRAY_RANGE_REF:
       result = build_nt (ARRAY_RANGE_REF,
                         stabilize_reference (TREE_OPERAND (ref, 0)),
-                        stabilize_reference_1 (TREE_OPERAND (ref, 1)));
+                        stabilize_reference_1 (TREE_OPERAND (ref, 1)),
+                        TREE_OPERAND (ref, 2), TREE_OPERAND (ref, 3));
       break;
 
     case COMPOUND_EXPR:
@@ -2183,13 +2204,6 @@ stabilize_reference (tree ref)
         volatiles.  */
       return stabilize_reference_1 (ref);
 
-    case RTL_EXPR:
-      result = build1 (INDIRECT_REF, TREE_TYPE (ref),
-                      save_expr (build1 (ADDR_EXPR,
-                                         build_pointer_type (TREE_TYPE (ref)),
-                                         ref)));
-      break;
-
       /* If arg isn't a kind of lvalue we recognize, make no change.
         Caller should recognize the error for an invalid lvalue.  */
     default:
@@ -2231,7 +2245,7 @@ stabilize_reference_1 (tree e)
      ignore things that are actual constant or that already have been
      handled by this function.  */
 
-  if (TREE_CONSTANT (e) || code == SAVE_EXPR)
+  if (TREE_INVARIANT (e))
     return e;
 
   switch (TREE_CODE_CLASS (code))
@@ -2239,7 +2253,6 @@ stabilize_reference_1 (tree e)
     case 'x':
     case 't':
     case 'd':
-    case 'b':
     case '<':
     case 's':
     case 'e':
@@ -2284,12 +2297,90 @@ stabilize_reference_1 (tree e)
   TREE_READONLY (result) = TREE_READONLY (e);
   TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (e);
   TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (e);
+  TREE_INVARIANT (result) = 1;
 
   return result;
 }
 \f
 /* Low-level constructors for expressions.  */
 
+/* A helper function for build1 and constant folders.  Set TREE_CONSTANT,
+   TREE_INVARIANT, and TREE_SIDE_EFFECTS for an ADDR_EXPR.  */
+
+void
+recompute_tree_invarant_for_addr_expr (tree t)
+{
+  tree node;
+  bool tc = true, ti = true, se = false;
+
+  /* We started out assuming this address is both invariant and constant, but
+     does not have side effects.  Now go down any handled components and see if
+     any of them involve offsets that are either non-constant or non-invariant.
+     Also check for side-effects.
+
+     ??? Note that this code makes no attempt to deal with the case where
+     taking the address of something causes a copy due to misalignment.  */
+
+#define UPDATE_TITCSE(NODE)  \
+do { tree _node = (NODE); \
+     if (_node && !TREE_INVARIANT (_node)) ti = false; \
+     if (_node && !TREE_CONSTANT (_node)) tc = false; \
+     if (_node && TREE_SIDE_EFFECTS (_node)) se = true; } while (0)
+
+  for (node = TREE_OPERAND (t, 0); handled_component_p (node);
+       node = TREE_OPERAND (node, 0))
+    {
+      /* If the first operand doesn't have an ARRAY_TYPE, this is a bogus
+        array reference (probably made temporarily by the G++ front end),
+        so ignore all the operands.  */
+      if ((TREE_CODE (node) == ARRAY_REF
+          || TREE_CODE (node) == ARRAY_RANGE_REF)
+         && TREE_CODE (TREE_TYPE (TREE_OPERAND (node, 0))) == ARRAY_TYPE)
+       {
+         UPDATE_TITCSE (TREE_OPERAND (node, 1));
+         UPDATE_TITCSE (array_ref_low_bound (node));
+         UPDATE_TITCSE (array_ref_element_size (node));
+       }
+      /* Likewise, just because this is a COMPONENT_REF doesn't mean we have a
+        FIELD_DECL, apparently.  The G++ front end can put something else
+        there, at least temporarily.  */
+      else if (TREE_CODE (node) == COMPONENT_REF
+              && TREE_CODE (TREE_OPERAND (node, 1)) == FIELD_DECL)
+       UPDATE_TITCSE (component_ref_field_offset (node));
+      else if (TREE_CODE (node) == BIT_FIELD_REF)
+       UPDATE_TITCSE (TREE_OPERAND (node, 2));
+    }
+             
+  /* 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.  */
+  if (TREE_CODE (node) == INDIRECT_REF)
+    UPDATE_TITCSE (node);
+  else if (DECL_P (node))
+    {
+      if (staticp (node))
+       ;
+      else if (decl_function_context (node) == current_function_decl)
+       tc = false;
+      else
+       ti = tc = false;
+    }
+  else if (TREE_CODE_CLASS (TREE_CODE (node)) == 'c')
+    ;
+  else
+    {
+      ti = tc = false;
+      se |= TREE_SIDE_EFFECTS (node);
+    }
+
+  TREE_CONSTANT (t) = tc;
+  TREE_INVARIANT (t) = ti;
+  TREE_SIDE_EFFECTS (t) = se;
+#undef UPDATE_TITCSE
+}
+
 /* Build an expression of code CODE, data type TYPE, and operands as
    specified.  Expressions and reference nodes can be created this way.
    Constants, decls, types and misc nodes cannot be.
@@ -2354,9 +2445,15 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
   TREE_SET_CODE (t, code);
 
   TREE_TYPE (t) = type;
+#ifdef USE_MAPPED_LOCATION
+  SET_EXPR_LOCATION (t, UNKNOWN_LOCATION);
+#else
+  SET_EXPR_LOCUS (t, NULL);
+#endif
   TREE_COMPLEXITY (t) = 0;
   TREE_OPERAND (t, 0) = node;
-  if (node && first_rtl_op (code) != 0)
+  TREE_BLOCK (t) = NULL_TREE;
+  if (node && !TYPE_P (node) && first_rtl_op (code) != 0)
     {
       TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (node);
       TREE_READONLY (t) = TREE_READONLY (node);
@@ -2369,7 +2466,6 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
     case INIT_EXPR:
     case MODIFY_EXPR:
     case VA_ARG_EXPR:
-    case RTL_EXPR:
     case PREDECREMENT_EXPR:
     case PREINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
@@ -2388,30 +2484,17 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
 
     case ADDR_EXPR:
       if (node)
-       {
-         /* The address of a volatile decl or reference does not have
-            side-effects.  But be careful not to ignore side-effects from
-            other sources deeper in the expression--if node is a _REF and
-            one of its operands has side-effects, so do we.  */
-         if (TREE_THIS_VOLATILE (node))
-           {
-             TREE_SIDE_EFFECTS (t) = 0;
-             if (!DECL_P (node))
-               {
-                 int i = first_rtl_op (TREE_CODE (node)) - 1;
-                 for (; i >= 0; --i)
-                   {
-                     if (TREE_SIDE_EFFECTS (TREE_OPERAND (node, i)))
-                       TREE_SIDE_EFFECTS (t) = 1;
-                   }
-               }
-           }
-       }
+       recompute_tree_invarant_for_addr_expr (t);
       break;
 
     default:
-      if (TREE_CODE_CLASS (code) == '1' && node && TREE_CONSTANT (node))
+      if (TREE_CODE_CLASS (code) == '1' && node && !TYPE_P (node)
+         && TREE_CONSTANT (node))
        TREE_CONSTANT (t) = 1;
+      if (TREE_CODE_CLASS (code) == '1' && node && TREE_INVARIANT (node))
+       TREE_INVARIANT (t) = 1;
+      if (TREE_CODE_CLASS (code) == 'r' && node && TREE_THIS_VOLATILE (node))
+       TREE_THIS_VOLATILE (t) = 1;
       break;
     }
 
@@ -2421,7 +2504,7 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
 #define PROCESS_ARG(N)                 \
   do {                                 \
     TREE_OPERAND (t, N) = arg##N;      \
-    if (arg##N && fro > N)             \
+    if (arg##N &&!TYPE_P (arg##N) && fro > N) \
       {                                        \
         if (TREE_SIDE_EFFECTS (arg##N))        \
          side_effects = 1;             \
@@ -2429,13 +2512,15 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
          read_only = 0;                \
         if (!TREE_CONSTANT (arg##N))   \
          constant = 0;                 \
+       if (!TREE_INVARIANT (arg##N))   \
+         invariant = 0;                \
       }                                        \
   } while (0)
 
 tree
 build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
 {
-  bool constant, read_only, side_effects;
+  bool constant, read_only, side_effects, invariant;
   tree t;
   int fro;
 
@@ -2459,33 +2544,17 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
              || TREE_CODE_CLASS (code) == '2');
   read_only = 1;
   side_effects = TREE_SIDE_EFFECTS (t);
+  invariant = constant;
 
   PROCESS_ARG(0);
   PROCESS_ARG(1);
 
-  if (code == CALL_EXPR && !side_effects)
-    {
-      tree node;
-      int i;
-
-      /* Calls have side-effects, except those to const or
-        pure functions.  */
-      i = call_expr_flags (t);
-      if (!(i & (ECF_CONST | ECF_PURE)))
-       side_effects = 1;
-
-      /* And even those have side-effects if their arguments do.  */
-      else for (node = TREE_OPERAND (t, 1); node; node = TREE_CHAIN (node))
-       if (TREE_SIDE_EFFECTS (TREE_VALUE (node)))
-         {
-           side_effects = 1;
-           break;
-         }
-    }
-
   TREE_READONLY (t) = read_only;
   TREE_CONSTANT (t) = constant;
+  TREE_INVARIANT (t) = invariant;
   TREE_SIDE_EFFECTS (t) = side_effects;  
+  TREE_THIS_VOLATILE (t)
+    = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0);
 
   return t;
 }
@@ -2494,20 +2563,10 @@ tree
 build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
             tree arg2 MEM_STAT_DECL)
 {
-  bool constant, read_only, side_effects;
+  bool constant, read_only, side_effects, invariant;
   tree t;
   int fro;
 
-  /* ??? Quite a lot of existing code passes one too many arguments to
-     CALL_EXPR.  Not going to fix them, because CALL_EXPR is about to
-     grow a new argument, so it would just mean changing them back.  */
-  if (code == CALL_EXPR)
-    {
-      if (arg2 != NULL_TREE)
-       abort ();
-      return build2 (code, tt, arg0, arg1);
-    }
-
 #ifdef ENABLE_CHECKING
   if (TREE_CODE_LENGTH (code) != 3)
     abort ();
@@ -2524,7 +2583,29 @@ build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
   PROCESS_ARG(1);
   PROCESS_ARG(2);
 
+  if (code == CALL_EXPR && !side_effects)
+    {
+      tree node;
+      int i;
+
+      /* Calls have side-effects, except those to const or
+        pure functions.  */
+      i = call_expr_flags (t);
+      if (!(i & (ECF_CONST | ECF_PURE)))
+       side_effects = 1;
+
+      /* And even those have side-effects if their arguments do.  */
+      else for (node = arg1; node; node = TREE_CHAIN (node))
+       if (TREE_SIDE_EFFECTS (TREE_VALUE (node)))
+         {
+           side_effects = 1;
+           break;
+         }
+    }
+
   TREE_SIDE_EFFECTS (t) = side_effects;  
+  TREE_THIS_VOLATILE (t)
+    = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0);
 
   return t;
 }
@@ -2533,7 +2614,7 @@ tree
 build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
             tree arg2, tree arg3 MEM_STAT_DECL)
 {
-  bool constant, read_only, side_effects;
+  bool constant, read_only, side_effects, invariant;
   tree t;
   int fro;
 
@@ -2555,6 +2636,8 @@ build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
   PROCESS_ARG(3);
 
   TREE_SIDE_EFFECTS (t) = side_effects;  
+  TREE_THIS_VOLATILE (t)
+    = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0);
 
   return t;
 }
@@ -2675,35 +2758,72 @@ build_block (tree vars, tree tags ATTRIBUTE_UNUSED, tree subblocks,
   return block;
 }
 
-/* EXPR_WITH_FILE_LOCATION are used to keep track of the exact
-   location where an expression or an identifier were encountered. It
-   is necessary for languages where the frontend parser will handle
-   recursively more than one file (Java is one of them).  */
+#if 1 /* ! defined(USE_MAPPED_LOCATION) */
+/* ??? gengtype doesn't handle conditionals */
+static GTY(()) tree last_annotated_node;
+#endif
 
-tree
-build_expr_wfl (tree node, const char *file, int line, int col)
+#ifdef USE_MAPPED_LOCATION
+
+expanded_location
+expand_location (source_location loc)
 {
-  static const char *last_file = 0;
-  static tree last_filenode = NULL_TREE;
-  tree wfl = make_node (EXPR_WITH_FILE_LOCATION);
+  expanded_location xloc;
+  if (loc == 0) { xloc.file = NULL; xloc.line = 0; }
+  else
+    {
+      const struct line_map *map = linemap_lookup (&line_table, loc);
+      xloc.file = map->to_file;
+      xloc.line = SOURCE_LINE (map, loc);
+    };
+  return xloc;
+}
 
-  EXPR_WFL_NODE (wfl) = node;
-  EXPR_WFL_SET_LINECOL (wfl, line, col);
-  if (file != last_file)
+#else
+
+/* Record the exact location where an expression or an identifier were
+   encountered.  */
+
+void
+annotate_with_file_line (tree node, const char *file, int line)
+{
+  /* Roughly one percent of the calls to this function are to annotate
+     a node with the same information already attached to that node!
+     Just return instead of wasting memory.  */
+  if (EXPR_LOCUS (node)
+      && (EXPR_FILENAME (node) == file
+         || ! strcmp (EXPR_FILENAME (node), file))
+      && EXPR_LINENO (node) == line)
     {
-      last_file = file;
-      last_filenode = file ? get_identifier (file) : NULL_TREE;
+      last_annotated_node = node;
+      return;
     }
 
-  EXPR_WFL_FILENAME_NODE (wfl) = last_filenode;
-  if (node)
+  /* In heavily macroized code (such as GCC itself) this single
+     entry cache can reduce the number of allocations by more
+     than half.  */
+  if (last_annotated_node
+      && EXPR_LOCUS (last_annotated_node)
+      && (EXPR_FILENAME (last_annotated_node) == file
+         || ! strcmp (EXPR_FILENAME (last_annotated_node), file))
+      && EXPR_LINENO (last_annotated_node) == line)
     {
-      TREE_SIDE_EFFECTS (wfl) = TREE_SIDE_EFFECTS (node);
-      TREE_TYPE (wfl) = TREE_TYPE (node);
+      SET_EXPR_LOCUS (node, EXPR_LOCUS (last_annotated_node));
+      return;
     }
 
-  return wfl;
+  SET_EXPR_LOCUS (node, ggc_alloc (sizeof (location_t)));
+  EXPR_LINENO (node) = line;
+  EXPR_FILENAME (node) = file;
+  last_annotated_node = node;
 }
+
+void
+annotate_with_locus (tree node, location_t locus)
+{
+  annotate_with_file_line (node, locus.file, locus.line);
+}
+#endif
 \f
 /* Return a declaration like DDECL except that its DECL_ATTRIBUTES
    is ATTRIBUTE.  */
@@ -3080,34 +3200,95 @@ type_hash_list (tree list, hashval_t hashcode)
 
 /* These are the Hashtable callback functions.  */
 
-/* Returns true if the types are equal.  */
+/* Returns true iff the types are equivalent.  */
 
 static int
 type_hash_eq (const void *va, const void *vb)
 {
   const struct type_hash *a = va, *b = vb;
-  if (a->hash == b->hash
-      && TREE_CODE (a->type) == TREE_CODE (b->type)
-      && TREE_TYPE (a->type) == TREE_TYPE (b->type)
-      && attribute_list_equal (TYPE_ATTRIBUTES (a->type),
-                              TYPE_ATTRIBUTES (b->type))
-      && TYPE_ALIGN (a->type) == TYPE_ALIGN (b->type)
-      && (TYPE_MAX_VALUE (a->type) == TYPE_MAX_VALUE (b->type)
-         || tree_int_cst_equal (TYPE_MAX_VALUE (a->type),
-                                TYPE_MAX_VALUE (b->type)))
-      && (TYPE_MIN_VALUE (a->type) == TYPE_MIN_VALUE (b->type)
-         || tree_int_cst_equal (TYPE_MIN_VALUE (a->type),
-                                TYPE_MIN_VALUE (b->type)))
-      /* Note that TYPE_DOMAIN is TYPE_ARG_TYPES for FUNCTION_TYPE.  */
-      && (TYPE_DOMAIN (a->type) == TYPE_DOMAIN (b->type)
-         || (TYPE_DOMAIN (a->type)
-             && TREE_CODE (TYPE_DOMAIN (a->type)) == TREE_LIST
-             && TYPE_DOMAIN (b->type)
-             && TREE_CODE (TYPE_DOMAIN (b->type)) == TREE_LIST
-             && type_list_equal (TYPE_DOMAIN (a->type),
-                                 TYPE_DOMAIN (b->type)))))
-    return 1;
-  return 0;
+
+  /* First test the things that are the same for all types.  */
+  if (a->hash != b->hash
+      || TREE_CODE (a->type) != TREE_CODE (b->type)
+      || TREE_TYPE (a->type) != TREE_TYPE (b->type)
+      || !attribute_list_equal (TYPE_ATTRIBUTES (a->type),
+                                TYPE_ATTRIBUTES (b->type))
+      || TYPE_ALIGN (a->type) != TYPE_ALIGN (b->type)
+      || TYPE_MODE (a->type) != TYPE_MODE (b->type))
+    return 0;
+
+  switch (TREE_CODE (a->type))
+    {
+    case VOID_TYPE:
+    case COMPLEX_TYPE:
+    case VECTOR_TYPE:
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+      return 1;
+
+    case ENUMERAL_TYPE:
+      if (TYPE_VALUES (a->type) != TYPE_VALUES (b->type)
+         && !(TYPE_VALUES (a->type)
+              && TREE_CODE (TYPE_VALUES (a->type)) == TREE_LIST
+              && TYPE_VALUES (b->type)
+              && TREE_CODE (TYPE_VALUES (b->type)) == TREE_LIST
+              && type_list_equal (TYPE_VALUES (a->type),
+                                  TYPE_VALUES (b->type))))
+       return 0;
+
+      /* ... fall through ... */
+
+    case INTEGER_TYPE:
+    case REAL_TYPE:
+    case BOOLEAN_TYPE:
+    case CHAR_TYPE:
+      return ((TYPE_MAX_VALUE (a->type) == TYPE_MAX_VALUE (b->type)
+              || tree_int_cst_equal (TYPE_MAX_VALUE (a->type),
+                                     TYPE_MAX_VALUE (b->type)))
+             && (TYPE_MIN_VALUE (a->type) == TYPE_MIN_VALUE (b->type)
+                 || tree_int_cst_equal (TYPE_MIN_VALUE (a->type),
+                                        TYPE_MIN_VALUE (b->type))));
+
+    case OFFSET_TYPE:
+      return TYPE_OFFSET_BASETYPE (a->type) == TYPE_OFFSET_BASETYPE (b->type);
+
+    case METHOD_TYPE:
+      return (TYPE_METHOD_BASETYPE (a->type) == TYPE_METHOD_BASETYPE (b->type)
+             && (TYPE_ARG_TYPES (a->type) == TYPE_ARG_TYPES (b->type)
+                 || (TYPE_ARG_TYPES (a->type)
+                     && TREE_CODE (TYPE_ARG_TYPES (a->type)) == TREE_LIST
+                     && TYPE_ARG_TYPES (b->type)
+                     && TREE_CODE (TYPE_ARG_TYPES (b->type)) == TREE_LIST
+                     && type_list_equal (TYPE_ARG_TYPES (a->type),
+                                         TYPE_ARG_TYPES (b->type)))));
+                                                                     
+    case ARRAY_TYPE:
+    case SET_TYPE:
+      return TYPE_DOMAIN (a->type) == TYPE_DOMAIN (b->type);
+
+    case RECORD_TYPE:
+    case UNION_TYPE:
+    case QUAL_UNION_TYPE:
+      return (TYPE_FIELDS (a->type) == TYPE_FIELDS (b->type)
+             || (TYPE_FIELDS (a->type)
+                 && TREE_CODE (TYPE_FIELDS (a->type)) == TREE_LIST
+                 && TYPE_FIELDS (b->type)
+                 && TREE_CODE (TYPE_FIELDS (b->type)) == TREE_LIST
+                 && type_list_equal (TYPE_FIELDS (a->type),
+                                     TYPE_FIELDS (b->type))));
+
+    case FUNCTION_TYPE:
+      return (TYPE_ARG_TYPES (a->type) == TYPE_ARG_TYPES (b->type)
+             || (TYPE_ARG_TYPES (a->type)
+                 && TREE_CODE (TYPE_ARG_TYPES (a->type)) == TREE_LIST
+                 && TYPE_ARG_TYPES (b->type)
+                 && TREE_CODE (TYPE_ARG_TYPES (b->type)) == TREE_LIST
+                 && type_list_equal (TYPE_ARG_TYPES (a->type),
+                                     TYPE_ARG_TYPES (b->type))));
+
+    default:
+      return 0;
+    }
 }
 
 /* Return the cached hash value.  */
@@ -3157,24 +3338,24 @@ type_hash_add (hashval_t hashcode, tree type)
 
 /* Given TYPE, and HASHCODE its hash code, return the canonical
    object for an identical type if one already exists.
-   Otherwise, return TYPE, and record it as the canonical object
-   if it is a permanent object.
+   Otherwise, return TYPE, and record it as the canonical object.
 
    To use this function, first create a type of the sort you want.
    Then compute its hash code from the fields of the type that
    make it different from other similar types.
-   Then call this function and use the value.
-   This function frees the type you pass in if it is a duplicate.  */
-
-/* Set to 1 to debug without canonicalization.  Never set by program.  */
-int debug_no_type_hash = 0;
+   Then call this function and use the value.  */
 
 tree
 type_hash_canon (unsigned int hashcode, tree type)
 {
   tree t1;
 
-  if (debug_no_type_hash)
+  /* The hash table only contains main variants, so ensure that's what we're
+     being passed.  */
+  if (TYPE_MAIN_VARIANT (type) != type)
+    abort ();
+
+  if (!lang_hooks.types.hash_types)
     return type;
 
   /* See if the type is in the hash table already.  If so, return it.
@@ -3366,7 +3547,7 @@ tree_int_cst_lt (tree t1, tree t2)
   if (t1 == t2)
     return 0;
 
-  if (TREE_UNSIGNED (TREE_TYPE (t1)) != TREE_UNSIGNED (TREE_TYPE (t2)))
+  if (TYPE_UNSIGNED (TREE_TYPE (t1)) != TYPE_UNSIGNED (TREE_TYPE (t2)))
     {
       int t1_sgn = tree_int_cst_sgn (t1);
       int t2_sgn = tree_int_cst_sgn (t2);
@@ -3379,7 +3560,7 @@ tree_int_cst_lt (tree t1, tree t2)
         unsigned just in case one of them would overflow a signed
         type.  */
     }
-  else if (! TREE_UNSIGNED (TREE_TYPE (t1)))
+  else if (!TYPE_UNSIGNED (TREE_TYPE (t1)))
     return INT_CST_LT (t1, t2);
 
   return INT_CST_LT_UNSIGNED (t1, t2);
@@ -3412,7 +3593,7 @@ host_integerp (tree t, int pos)
               && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) >= 0)
              || (! pos && TREE_INT_CST_HIGH (t) == -1
                  && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0
-                 && ! TREE_UNSIGNED (TREE_TYPE (t)))
+                 && !TYPE_UNSIGNED (TREE_TYPE (t)))
              || (pos && TREE_INT_CST_HIGH (t) == 0)));
 }
 
@@ -3455,7 +3636,7 @@ tree_int_cst_sgn (tree t)
 {
   if (TREE_INT_CST_LOW (t) == 0 && TREE_INT_CST_HIGH (t) == 0)
     return 0;
-  else if (TREE_UNSIGNED (TREE_TYPE (t)))
+  else if (TYPE_UNSIGNED (TREE_TYPE (t)))
     return 1;
   else if (TREE_INT_CST_HIGH (t) < 0)
     return -1;
@@ -3533,10 +3714,8 @@ simple_cst_equal (tree t1, tree t2)
                         TREE_STRING_LENGTH (t1)));
 
     case CONSTRUCTOR:
-      if (CONSTRUCTOR_ELTS (t1) == CONSTRUCTOR_ELTS (t2))
-       return 1;
-      else
-       abort ();
+      return simple_cst_list_equal (CONSTRUCTOR_ELTS (t1), 
+                                   CONSTRUCTOR_ELTS (t2));
 
     case SAVE_EXPR:
       return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
@@ -3651,10 +3830,7 @@ associative_tree_code (enum tree_code code)
     case BIT_AND_EXPR:
     case BIT_XOR_EXPR:
     case PLUS_EXPR:
-    case MINUS_EXPR:
     case MULT_EXPR:
-    case LSHIFT_EXPR:
-    case RSHIFT_EXPR:
     case MIN_EXPR:
     case MAX_EXPR:
       return true;
@@ -3681,6 +3857,13 @@ commutative_tree_code (enum tree_code code)
     case BIT_AND_EXPR:
     case NE_EXPR:
     case EQ_EXPR:
+    case UNORDERED_EXPR:
+    case ORDERED_EXPR:
+    case UNEQ_EXPR:
+    case LTGT_EXPR:
+    case TRUTH_AND_EXPR:
+    case TRUTH_XOR_EXPR:
+    case TRUTH_OR_EXPR:
       return true;
 
     default:
@@ -3708,7 +3891,8 @@ iterative_hash_expr (tree t, hashval_t val)
   code = TREE_CODE (t);
   class = TREE_CODE_CLASS (code);
 
-  if (class == 'd')
+  if (class == 'd'
+      || TREE_CODE (t) == VALUE_HANDLE)
     {
       /* Decls we can just compare by pointer.  */
       val = iterative_hash_object (t, val);
@@ -3723,8 +3907,11 @@ iterative_hash_expr (tree t, hashval_t val)
          val = iterative_hash_object (TREE_INT_CST_HIGH (t), val);
        }
       else if (code == REAL_CST)
-       val = iterative_hash (TREE_REAL_CST_PTR (t),
-                             sizeof (REAL_VALUE_TYPE), val);
+       {
+         unsigned int val2 = real_hash (TREE_REAL_CST_PTR (t));
+
+         val = iterative_hash (&val2, sizeof (unsigned int), val);
+       }
       else if (code == STRING_CST)
        val = iterative_hash (TREE_STRING_POINTER (t),
                              TREE_STRING_LENGTH (t), val);
@@ -3742,9 +3929,17 @@ iterative_hash_expr (tree t, hashval_t val)
     {
       val = iterative_hash_object (code, val);
 
-      if (code == NOP_EXPR || code == CONVERT_EXPR
+      /* Don't hash the type, that can lead to having nodes which
+        compare equal according to operand_equal_p, but which
+        have different hash codes.  */
+      if (code == NOP_EXPR
+         || code == CONVERT_EXPR
          || code == NON_LVALUE_EXPR)
-       val = iterative_hash_object (TREE_TYPE (t), val);
+       {
+         /* Make sure to include signness in the hash computation.  */
+         val += TYPE_UNSIGNED (TREE_TYPE (t));
+         val = iterative_hash_expr (TREE_OPERAND (t, 0), val);
+       }
 
       if (commutative_tree_code (code))
        {
@@ -3773,6 +3968,11 @@ iterative_hash_expr (tree t, hashval_t val)
       for (; t; t = TREE_CHAIN (t))
        val = iterative_hash_expr (TREE_VALUE (t), val);
     }
+  else if (code == SSA_NAME)
+    {
+      val = iterative_hash_object (SSA_NAME_VERSION (t), val);
+      val = iterative_hash_expr (SSA_NAME_VAR (t), val);
+    }
   else
     abort ();
 
@@ -3783,29 +3983,42 @@ iterative_hash_expr (tree t, hashval_t val)
    (RECORD_TYPE, UNION_TYPE and ENUMERAL_TYPE nodes are
    constructed by language-dependent code, not here.)  */
 
-/* Construct, lay out and return the type of pointers to TO_TYPE
-   with mode MODE. If such a type has already been constructed,
-   reuse it.  */
+/* Construct, lay out and return the type of pointers to TO_TYPE with
+   mode MODE.  If CAN_ALIAS_ALL is TRUE, indicate this type can
+   reference all of memory. If such a type has already been
+   constructed, reuse it.  */
 
 tree
-build_pointer_type_for_mode (tree to_type, enum machine_mode mode)
+build_pointer_type_for_mode (tree to_type, enum machine_mode mode,
+                            bool can_alias_all)
 {
-  tree t = TYPE_POINTER_TO (to_type);
+  tree t;
+
+  /* In some cases, languages will have things that aren't a POINTER_TYPE
+     (such as a RECORD_TYPE for fat pointers in Ada) as TYPE_POINTER_TO.
+     In that case, return that type without regard to the rest of our
+     operands.
+
+     ??? This is a kludge, but consistent with the way this function has
+     always operated and there doesn't seem to be a good way to avoid this
+     at the moment.  */
+  if (TYPE_POINTER_TO (to_type) != 0
+      && TREE_CODE (TYPE_POINTER_TO (to_type)) != POINTER_TYPE)
+    return TYPE_POINTER_TO (to_type);
 
   /* First, if we already have a type for pointers to TO_TYPE and it's
      the proper mode, use it.  */
-  if (t != 0 && mode == ptr_mode)
-    return t;
+  for (t = TYPE_POINTER_TO (to_type); t; t = TYPE_NEXT_PTR_TO (t))
+    if (TYPE_MODE (t) == mode && TYPE_REF_CAN_ALIAS_ALL (t) == can_alias_all)
+      return t;
 
   t = make_node (POINTER_TYPE);
 
   TREE_TYPE (t) = to_type;
   TYPE_MODE (t) = mode;
-
-  /* We can only record one type as "the" pointer to TO_TYPE.  We choose to
-     record the pointer whose mode is ptr_mode.  */
-  if (mode == ptr_mode)
-    TYPE_POINTER_TO (to_type) = t;
+  TYPE_REF_CAN_ALIAS_ALL (t) = can_alias_all;
+  TYPE_NEXT_PTR_TO (t) = TYPE_POINTER_TO (to_type);
+  TYPE_POINTER_TO (to_type) = t;
 
   /* Lay out the type.  This function has many callers that are concerned
      with expression-construction, and this simplifies them all.  */
@@ -3819,29 +4032,41 @@ build_pointer_type_for_mode (tree to_type, enum machine_mode mode)
 tree
 build_pointer_type (tree to_type)
 {
-  return build_pointer_type_for_mode (to_type, ptr_mode);
+  return build_pointer_type_for_mode (to_type, ptr_mode, false);
 }
 
-/* Construct, lay out and return the type of references to TO_TYPE
-   with mode MODE. If such a type has already been constructed,
-   reuse it.  */
+/* Same as build_pointer_type_for_mode, but for REFERENCE_TYPE.  */
 
 tree
-build_reference_type_for_mode (tree to_type, enum machine_mode mode)
+build_reference_type_for_mode (tree to_type, enum machine_mode mode,
+                              bool can_alias_all)
 {
-  tree t = TYPE_REFERENCE_TO (to_type);
+  tree t;
 
-  /* First, if we already have a type for pointers to TO_TYPE, use it.  */
-  if (t != 0 && mode == ptr_mode)
-    return t;
+  /* In some cases, languages will have things that aren't a REFERENCE_TYPE
+     (such as a RECORD_TYPE for fat pointers in Ada) as TYPE_REFERENCE_TO.
+     In that case, return that type without regard to the rest of our
+     operands.
+
+     ??? This is a kludge, but consistent with the way this function has
+     always operated and there doesn't seem to be a good way to avoid this
+     at the moment.  */
+  if (TYPE_REFERENCE_TO (to_type) != 0
+      && TREE_CODE (TYPE_REFERENCE_TO (to_type)) != REFERENCE_TYPE)
+    return TYPE_REFERENCE_TO (to_type);
+
+  /* First, if we already have a type for pointers to TO_TYPE and it's
+     the proper mode, use it.  */
+  for (t = TYPE_REFERENCE_TO (to_type); t; t = TYPE_NEXT_REF_TO (t))
+    if (TYPE_MODE (t) == mode && TYPE_REF_CAN_ALIAS_ALL (t) == can_alias_all)
+      return t;
 
   t = make_node (REFERENCE_TYPE);
 
   TREE_TYPE (t) = to_type;
   TYPE_MODE (t) = mode;
-
-  /* Record this type as the pointer to TO_TYPE.  */
-  if (mode == ptr_mode)
+  TYPE_REF_CAN_ALIAS_ALL (t) = can_alias_all;
+  TYPE_NEXT_REF_TO (t) = TYPE_REFERENCE_TO (to_type);
   TYPE_REFERENCE_TO (to_type) = t;
 
   layout_type (t);
@@ -3856,7 +4081,7 @@ build_reference_type_for_mode (tree to_type, enum machine_mode mode)
 tree
 build_reference_type (tree to_type)
 {
-  return build_reference_type_for_mode (to_type, ptr_mode);
+  return build_reference_type_for_mode (to_type, ptr_mode, false);
 }
 
 /* Build a type that is compatible with t but has no cv quals anywhere
@@ -3870,9 +4095,14 @@ build_type_no_quals (tree t)
   switch (TREE_CODE (t))
     {
     case POINTER_TYPE:
-      return build_pointer_type (build_type_no_quals (TREE_TYPE (t)));
+      return build_pointer_type_for_mode (build_type_no_quals (TREE_TYPE (t)),
+                                         TYPE_MODE (t),
+                                         TYPE_REF_CAN_ALIAS_ALL (t));
     case REFERENCE_TYPE:
-      return build_reference_type (build_type_no_quals (TREE_TYPE (t)));
+      return
+       build_reference_type_for_mode (build_type_no_quals (TREE_TYPE (t)),
+                                      TYPE_MODE (t),
+                                      TYPE_REF_CAN_ALIAS_ALL (t));
     default:
       return TYPE_MAIN_VARIANT (t);
     }
@@ -3965,19 +4195,12 @@ build_array_type (tree elt_type, tree index_type)
       elt_type = integer_type_node;
     }
 
-  /* Make sure TYPE_POINTER_TO (elt_type) is filled in.  */
-  build_pointer_type (elt_type);
-
-  /* Allocate the array after the pointer type,
-     in case we free it in type_hash_canon.  */
   t = make_node (ARRAY_TYPE);
   TREE_TYPE (t) = elt_type;
   TYPE_DOMAIN (t) = index_type;
 
   if (index_type == 0)
-    {
-      return t;
-    }
+    return t;
 
   hashcode = iterative_hash_object (TYPE_HASH (elt_type), hashcode);
   hashcode = iterative_hash_object (TYPE_HASH (index_type), hashcode);
@@ -4026,7 +4249,7 @@ build_function_type (tree value_type, tree arg_types)
   TREE_TYPE (t) = value_type;
   TYPE_ARG_TYPES (t) = arg_types;
 
-  /* If we already have such a type, use the old one and free this one.  */
+  /* If we already have such a type, use the old one.  */
   hashcode = iterative_hash_object (TYPE_HASH (value_type), hashcode);
   hashcode = type_hash_list (arg_types, hashcode);
   t = type_hash_canon (hashcode, t);
@@ -4088,12 +4311,10 @@ build_method_type_directly (tree basetype,
   argtypes = tree_cons (NULL_TREE, ptype, argtypes);
   TYPE_ARG_TYPES (t) = argtypes;
 
-  /* If we already have such a type, use the old one and free this one.
-     Note that it also frees up the above cons cell if found.  */
+  /* If we already have such a type, use the old one.  */
   hashcode = iterative_hash_object (TYPE_HASH (basetype), hashcode);
   hashcode = iterative_hash_object (TYPE_HASH (rettype), hashcode);
   hashcode = type_hash_list (argtypes, hashcode);
-
   t = type_hash_canon (hashcode, t);
 
   if (!COMPLETE_TYPE_P (t))
@@ -4134,7 +4355,7 @@ build_offset_type (tree basetype, tree type)
   TYPE_OFFSET_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);
   TREE_TYPE (t) = type;
 
-  /* If we already have such a type, use the old one and free this one.  */
+  /* If we already have such a type, use the old one.  */
   hashcode = iterative_hash_object (TYPE_HASH (basetype), hashcode);
   hashcode = iterative_hash_object (TYPE_HASH (type), hashcode);
   t = type_hash_canon (hashcode, t);
@@ -4157,9 +4378,8 @@ build_complex_type (tree component_type)
   t = make_node (COMPLEX_TYPE);
 
   TREE_TYPE (t) = TYPE_MAIN_VARIANT (component_type);
-  set_type_quals (t, TYPE_QUALS (component_type));
 
-  /* If we already have such a type, use the old one and free this one.  */
+  /* If we already have such a type, use the old one.  */
   hashcode = iterative_hash_object (TYPE_HASH (component_type), 0);
   t = type_hash_canon (hashcode, t);
 
@@ -4201,7 +4421,7 @@ build_complex_type (tree component_type)
        TYPE_NAME (t) = get_identifier (name);
     }
 
-  return t;
+  return build_qualified_type (t, TYPE_QUALS (component_type));
 }
 \f
 /* Return OP, stripped of any conversions to wider types as much as is safe.
@@ -4237,7 +4457,7 @@ get_unwidened (tree op, tree for_type)
   int uns
     = (for_type != 0 && for_type != type
        && final_prec > TYPE_PRECISION (type)
-       && TREE_UNSIGNED (type));
+       && TYPE_UNSIGNED (type));
   tree win = op;
 
   while (TREE_CODE (op) == NOP_EXPR)
@@ -4267,11 +4487,11 @@ get_unwidened (tree op, tree for_type)
        {
          if (! uns || final_prec <= TYPE_PRECISION (TREE_TYPE (op)))
            win = op;
-         /* TREE_UNSIGNED says whether this is a zero-extension.
+         /* TYPE_UNSIGNED says whether this is a zero-extension.
             Let's avoid computing it if it does not affect WIN
             and if UNS will not be needed again.  */
          if ((uns || TREE_CODE (op) == NOP_EXPR)
-             && TREE_UNSIGNED (TREE_TYPE (op)))
+             && TYPE_UNSIGNED (TREE_TYPE (op)))
            {
              uns = 1;
              win = op;
@@ -4288,8 +4508,8 @@ get_unwidened (tree op, tree for_type)
     {
       unsigned int innerprec
        = tree_low_cst (DECL_SIZE (TREE_OPERAND (op, 1)), 1);
-      int unsignedp = (TREE_UNSIGNED (TREE_OPERAND (op, 1))
-                      || TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op, 1))));
+      int unsignedp = (DECL_UNSIGNED (TREE_OPERAND (op, 1))
+                      || TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op, 1))));
       type = lang_hooks.types.type_for_size (innerprec, unsignedp);
 
       /* We can get this structure field in the narrowest type it fits in.
@@ -4303,8 +4523,8 @@ get_unwidened (tree op, tree for_type)
          && (for_type || ! DECL_BIT_FIELD (TREE_OPERAND (op, 1)))
          && (! uns || final_prec <= innerprec || unsignedp))
        {
-         win = build (COMPONENT_REF, type, TREE_OPERAND (op, 0),
-                      TREE_OPERAND (op, 1));
+         win = build3 (COMPONENT_REF, type, TREE_OPERAND (op, 0),
+                       TREE_OPERAND (op, 1), NULL_TREE);
          TREE_SIDE_EFFECTS (win) = TREE_SIDE_EFFECTS (op);
          TREE_THIS_VOLATILE (win) = TREE_THIS_VOLATILE (op);
        }
@@ -4344,11 +4564,11 @@ get_narrower (tree op, int *unsignedp_ptr)
          /* An extension: the outermost one can be stripped,
             but remember whether it is zero or sign extension.  */
          if (first)
-           uns = TREE_UNSIGNED (TREE_TYPE (op));
+           uns = TYPE_UNSIGNED (TREE_TYPE (op));
          /* Otherwise, if a sign extension has been stripped,
             only sign extensions can now be stripped;
             if a zero extension has been stripped, only zero-extensions.  */
-         else if (uns != TREE_UNSIGNED (TREE_TYPE (op)))
+         else if (uns != TYPE_UNSIGNED (TREE_TYPE (op)))
            break;
          first = 0;
        }
@@ -4357,7 +4577,7 @@ get_narrower (tree op, int *unsignedp_ptr)
          /* A change in nominal type can always be stripped, but we must
             preserve the unsignedness.  */
          if (first)
-           uns = TREE_UNSIGNED (TREE_TYPE (op));
+           uns = TYPE_UNSIGNED (TREE_TYPE (op));
          first = 0;
          op = TREE_OPERAND (op, 0);
        }
@@ -4369,12 +4589,13 @@ get_narrower (tree op, int *unsignedp_ptr)
       /* Since type_for_size always gives an integer type.  */
       && TREE_CODE (TREE_TYPE (op)) != REAL_TYPE
       /* Ensure field is laid out already.  */
-      && DECL_SIZE (TREE_OPERAND (op, 1)) != 0)
+      && DECL_SIZE (TREE_OPERAND (op, 1)) != 0
+      && host_integerp (DECL_SIZE (TREE_OPERAND (op, 1)), 1))
     {
       unsigned HOST_WIDE_INT innerprec
        = tree_low_cst (DECL_SIZE (TREE_OPERAND (op, 1)), 1);
-      int unsignedp = (TREE_UNSIGNED (TREE_OPERAND (op, 1))
-                      || TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op, 1))));
+      int unsignedp = (DECL_UNSIGNED (TREE_OPERAND (op, 1))
+                      || TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op, 1))));
       tree type = lang_hooks.types.type_for_size (innerprec, unsignedp);
 
       /* We can get this structure field in a narrower type that fits it,
@@ -4387,13 +4608,13 @@ get_narrower (tree op, int *unsignedp_ptr)
 
       if (innerprec < TYPE_PRECISION (TREE_TYPE (op))
          && ! DECL_BIT_FIELD (TREE_OPERAND (op, 1))
-         && (first || uns == TREE_UNSIGNED (TREE_OPERAND (op, 1)))
+         && (first || uns == DECL_UNSIGNED (TREE_OPERAND (op, 1)))
          && type != 0)
        {
          if (first)
-           uns = TREE_UNSIGNED (TREE_OPERAND (op, 1));
-         win = build (COMPONENT_REF, type, TREE_OPERAND (op, 0),
-                      TREE_OPERAND (op, 1));
+           uns = DECL_UNSIGNED (TREE_OPERAND (op, 1));
+         win = build3 (COMPONENT_REF, type, TREE_OPERAND (op, 0),
+                       TREE_OPERAND (op, 1), NULL_TREE);
          TREE_SIDE_EFFECTS (win) = TREE_SIDE_EFFECTS (op);
          TREE_THIS_VOLATILE (win) = TREE_THIS_VOLATILE (op);
        }
@@ -4415,10 +4636,10 @@ int_fits_type_p (tree c, tree type)
   /* Perform some generic filtering first, which may allow making a decision
      even if the bounds are not constant.  First, negative integers never fit
      in unsigned types, */
-  if ((TREE_UNSIGNED (type) && tree_int_cst_sgn (c) < 0)
+  if ((TYPE_UNSIGNED (type) && tree_int_cst_sgn (c) < 0)
       /* Also, unsigned integers with top bit set never fit signed types.  */
-      || (! TREE_UNSIGNED (type)
-         && TREE_UNSIGNED (TREE_TYPE (c)) && tree_int_cst_msb (c)))
+      || (! TYPE_UNSIGNED (type)
+         && TYPE_UNSIGNED (TREE_TYPE (c)) && tree_int_cst_msb (c)))
     return 0;
 
   /* If at least one bound of the type is a constant integer, we can check
@@ -4468,21 +4689,50 @@ int_fits_type_p (tree c, tree type)
     }
 }
 
+/* Subprogram of following function.  Called by walk_tree.
+
+   Return *TP if it is an automatic variable or parameter of the
+   function passed in as DATA.  */
+
+static tree
+find_var_from_fn (tree *tp, int *walk_subtrees, void *data)
+{
+  tree fn = (tree) data;
+
+  if (TYPE_P (*tp))
+    *walk_subtrees = 0;
+
+  else if (DECL_P (*tp) && lang_hooks.tree_inlining.auto_var_in_fn_p (*tp, fn))
+    return *tp;
+
+  return NULL_TREE;
+}
+
 /* Returns true if T is, contains, or refers to a type with variable
-   size.  This concept is more general than that of C99 'variably
-   modified types': in C99, a struct type is never variably modified
-   because a VLA may not appear as a structure member.  However, in
-   GNU C code like:
+   size.  If FN is nonzero, only return true if a modifier of the type
+   or position of FN is a variable or parameter inside FN.
+
+   This concept is more general than that of C99 'variably modified types':
+   in C99, a struct type is never variably modified because a VLA may not
+   appear as a structure member.  However, in GNU C code like:
 
      struct S { int i[f()]; };
 
    is valid, and other languages may define similar constructs.  */
 
 bool
-variably_modified_type_p (tree type)
+variably_modified_type_p (tree type, tree fn)
 {
   tree t;
 
+/* Test if T is either variable (if FN is zero) or an expression containing
+   a variable in FN.  */
+#define RETURN_TRUE_IF_VAR(T)                                          \
+  do { tree _t = (T);                                                  \
+    if (_t && _t != error_mark_node && TREE_CODE (_t) != INTEGER_CST   \
+        && (!fn || walk_tree (&_t, find_var_from_fn, fn, NULL)))       \
+      return true;  } while (0)
+
   if (type == error_mark_node)
     return false;
 
@@ -4491,47 +4741,63 @@ variably_modified_type_p (tree type)
      We do not yet have a representation of the C99 '[*]' syntax.
      When a representation is chosen, this function should be modified
      to test for that case as well.  */
-  t = TYPE_SIZE (type);
-  if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
-    return true;
+  RETURN_TRUE_IF_VAR (TYPE_SIZE (type));
+  RETURN_TRUE_IF_VAR (TYPE_SIZE_UNIT(type));
 
   switch (TREE_CODE (type))
     {
     case POINTER_TYPE:
     case REFERENCE_TYPE:
     case ARRAY_TYPE:
-      /* If TYPE is a pointer or reference, it is variably modified if
-        the type pointed to is variably modified.  Similarly for arrays;
-        note that VLAs are handled by the TYPE_SIZE check above.  */
-      return variably_modified_type_p (TREE_TYPE (type));
+    case SET_TYPE:
+    case VECTOR_TYPE:
+      if (variably_modified_type_p (TREE_TYPE (type), fn))
+       return true;
+      break;
 
     case FUNCTION_TYPE:
     case METHOD_TYPE:
       /* If TYPE is a function type, it is variably modified if any of the
          parameters or the return type are variably modified.  */
-      {
-       tree parm;
+      if (variably_modified_type_p (TREE_TYPE (type), fn))
+         return true;
 
-       if (variably_modified_type_p (TREE_TYPE (type)))
+      for (t = TYPE_ARG_TYPES (type);
+          t && t != void_list_node;
+          t = TREE_CHAIN (t))
+       if (variably_modified_type_p (TREE_VALUE (t), fn))
          return true;
-       for (parm = TYPE_ARG_TYPES (type);
-            parm && parm != void_list_node;
-            parm = TREE_CHAIN (parm))
-         if (variably_modified_type_p (TREE_VALUE (parm)))
-           return true;
-      }
       break;
 
     case INTEGER_TYPE:
+    case REAL_TYPE:
+    case ENUMERAL_TYPE:
+    case BOOLEAN_TYPE:
+    case CHAR_TYPE:
       /* Scalar types are variably modified if their end points
         aren't constant.  */
-      t = TYPE_MIN_VALUE (type);
-      if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
-       return true;
-      t = TYPE_MAX_VALUE (type);
-      if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
-       return true;
-      return false;
+      RETURN_TRUE_IF_VAR (TYPE_MIN_VALUE (type));
+      RETURN_TRUE_IF_VAR (TYPE_MAX_VALUE (type));
+      break;
+
+    case RECORD_TYPE:
+    case UNION_TYPE:
+    case QUAL_UNION_TYPE:
+      /* We can't see if any of the field are variably-modified by the
+        definition we normally use, since that would produce infinite
+        recursion via pointers.  */
+      /* This is variably modified if some field's type is.  */
+      for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
+       if (TREE_CODE (t) == FIELD_DECL)
+         {
+           RETURN_TRUE_IF_VAR (DECL_FIELD_OFFSET (t));
+           RETURN_TRUE_IF_VAR (DECL_SIZE (t));
+           RETURN_TRUE_IF_VAR (DECL_SIZE_UNIT (t));
+
+           if (TREE_CODE (type) == QUAL_UNION_TYPE)
+             RETURN_TRUE_IF_VAR (DECL_QUALIFIER (t));
+         }
+       break;
 
     default:
       break;
@@ -4539,7 +4805,9 @@ variably_modified_type_p (tree type)
 
   /* The current language may have other cases to check, but in general,
      all other types are not variably modified.  */
-  return lang_hooks.tree_inlining.var_mod_type_p (type);
+  return lang_hooks.tree_inlining.var_mod_type_p (type, fn);
+
+#undef RETURN_TRUE_IF_VAR
 }
 
 /* Given a DECL or TYPE, return the scope in which it was declared, or
@@ -4562,9 +4830,6 @@ decl_function_context (tree decl)
   if (TREE_CODE (decl) == ERROR_MARK)
     return 0;
 
-  if (TREE_CODE (decl) == SAVE_EXPR)
-    context = SAVE_EXPR_CONTEXT (decl);
-
   /* C++ virtual functions use DECL_CONTEXT for the class of the vtable
      where we look up the function at runtime.  Such functions always take
      a first argument of type 'pointer to real context'.
@@ -4689,6 +4954,8 @@ dump_tree_statistics (void)
   fprintf (stderr, "---------------------------------------\n");
   fprintf (stderr, "%-20s %7d %10d\n", "Total", total_nodes, total_bytes);
   fprintf (stderr, "---------------------------------------\n");
+  ssanames_print_statistics ();
+  phinodes_print_statistics ();
 #else
   fprintf (stderr, "(No per-node statistics)\n");
 #endif
@@ -4894,19 +5161,82 @@ get_set_constructor_bytes (tree init, unsigned char *buffer, int wd_size)
 }
 \f
 #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
-/* Complain that the tree code of NODE does not match the expected CODE.
-   FILE, LINE, and FUNCTION are of the caller.  */
+
+/* Complain that the tree code of NODE does not match the expected 0
+   terminated list of trailing codes. FILE, LINE, and FUNCTION are of
+   the caller.  */
 
 void
-tree_check_failed (const tree node, enum tree_code code, const char *file,
-                  int line, const char *function)
-{
+tree_check_failed (const tree node, const char *file,
+                  int line, const char *function, ...)
+{
+  va_list args;
+  char *buffer;
+  unsigned length = 0;
+  int code;
+
+  va_start (args, function);
+  while ((code = va_arg (args, int)))
+    length += 4 + strlen (tree_code_name[code]);
+  va_end (args);
+  va_start (args, function);
+  buffer = alloca (length);
+  length = 0;
+  while ((code = va_arg (args, int)))
+    {
+      if (length)
+       {
+         strcpy (buffer + length, " or ");
+         length += 4;
+       }
+      strcpy (buffer + length, tree_code_name[code]);
+      length += strlen (tree_code_name[code]);
+    }
+  va_end (args);
+  
   internal_error ("tree check: expected %s, have %s in %s, at %s:%d",
-                 tree_code_name[code], tree_code_name[TREE_CODE (node)],
+                 buffer, tree_code_name[TREE_CODE (node)],
+                 function, trim_filename (file), line);
+}
+
+/* Complain that the tree code of NODE does match the expected 0
+   terminated list of trailing codes. FILE, LINE, and FUNCTION are of
+   the caller.  */
+
+void
+tree_not_check_failed (const tree node, const char *file,
+                      int line, const char *function, ...)
+{
+  va_list args;
+  char *buffer;
+  unsigned length = 0;
+  int code;
+
+  va_start (args, function);
+  while ((code = va_arg (args, int)))
+    length += 4 + strlen (tree_code_name[code]);
+  va_end (args);
+  va_start (args, function);
+  buffer = alloca (length);
+  length = 0;
+  while ((code = va_arg (args, int)))
+    {
+      if (length)
+       {
+         strcpy (buffer + length, " or ");
+         length += 4;
+       }
+      strcpy (buffer + length, tree_code_name[code]);
+      length += strlen (tree_code_name[code]);
+    }
+  va_end (args);
+  
+  internal_error ("tree check: expected none of %s, have %s in %s, at %s:%d",
+                 buffer, tree_code_name[TREE_CODE (node)],
                  function, trim_filename (file), line);
 }
 
-/* Similar to above, except that we check for a class of tree
+/* Similar to tree_check_failed, except that we check for a class of tree
    code, given in CL.  */
 
 void
@@ -4931,6 +5261,18 @@ tree_vec_elt_check_failed (int idx, int len, const char *file, int line,
      idx + 1, len, function, trim_filename (file), line);
 }
 
+/* Similar to above, except that the check is for the bounds of a PHI_NODE's
+   (dynamically sized) vector.  */
+
+void
+phi_node_elt_check_failed (int idx, int len, const char *file, int line,
+                           const char *function)
+{
+  internal_error
+    ("tree check: accessed elt %d of phi_node with %d elts in %s, at %s:%d",
+     idx + 1, len, function, trim_filename (file), line);
+}
+
 /* Similar to above, except that the check is for the bounds of the operand
    vector of an expression node.  */
 
@@ -4971,6 +5313,27 @@ finish_vector_type (tree t)
   }
 }
 
+static tree
+make_or_reuse_type (unsigned size, int unsignedp)
+{
+  if (size == INT_TYPE_SIZE)
+    return unsignedp ? unsigned_type_node : integer_type_node;
+  if (size == CHAR_TYPE_SIZE)
+    return unsignedp ? unsigned_char_type_node : signed_char_type_node;
+  if (size == SHORT_TYPE_SIZE)
+    return unsignedp ? short_unsigned_type_node : short_integer_type_node;
+  if (size == LONG_TYPE_SIZE)
+    return unsignedp ? long_unsigned_type_node : long_integer_type_node;
+  if (size == LONG_LONG_TYPE_SIZE)
+    return (unsignedp ? long_long_unsigned_type_node
+            : long_long_integer_type_node);
+
+  if (unsignedp)
+    return make_unsigned_type (size);
+  else
+    return make_signed_type (size);
+}
+
 /* Create nodes for all integer types (and error_mark_node) using the sizes
    of C datatypes.  The caller should call set_sizetype soon after calling
    this function to select one of the types as sizetype.  */
@@ -4978,6 +5341,14 @@ finish_vector_type (tree t)
 void
 build_common_tree_nodes (int signed_char)
 {
+  /* This function is called after command line parsing is complete,
+     but before any DECL nodes should have been created.  Therefore,
+     now is the appropriate time to adjust next_decl_uid so that the
+     range 0 .. num_in_fnames-1 is reserved for TRANSLATION_UNIT_DECLs.  */
+  if (next_decl_uid)
+    abort ();
+  next_decl_uid = num_in_fnames;
+
   error_mark_node = make_node (ERROR_MARK);
   TREE_TYPE (error_mark_node) = error_mark_node;
 
@@ -5013,17 +5384,19 @@ build_common_tree_nodes (int signed_char)
   TREE_TYPE (TYPE_MAX_VALUE (boolean_type_node)) = boolean_type_node;
   TYPE_PRECISION (boolean_type_node) = 1;
 
-  intQI_type_node = make_signed_type (GET_MODE_BITSIZE (QImode));
-  intHI_type_node = make_signed_type (GET_MODE_BITSIZE (HImode));
-  intSI_type_node = make_signed_type (GET_MODE_BITSIZE (SImode));
-  intDI_type_node = make_signed_type (GET_MODE_BITSIZE (DImode));
-  intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode));
-
-  unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode));
-  unsigned_intHI_type_node = make_unsigned_type (GET_MODE_BITSIZE (HImode));
-  unsigned_intSI_type_node = make_unsigned_type (GET_MODE_BITSIZE (SImode));
-  unsigned_intDI_type_node = make_unsigned_type (GET_MODE_BITSIZE (DImode));
-  unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode));
+  /* Fill in the rest of the sized types.  Reuse existing type nodes
+     when possible.  */
+  intQI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (QImode), 0);
+  intHI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (HImode), 0);
+  intSI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (SImode), 0);
+  intDI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (DImode), 0);
+  intTI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (TImode), 0);
+
+  unsigned_intQI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (QImode), 1);
+  unsigned_intHI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (HImode), 1);
+  unsigned_intSI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (SImode), 1);
+  unsigned_intDI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (DImode), 1);
+  unsigned_intTI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (TImode), 1);
   
   access_public_node = get_identifier ("public");
   access_protected_node = get_identifier ("protected");
@@ -5065,6 +5438,7 @@ build_common_tree_nodes_2 (int short_double)
   ptr_type_node = build_pointer_type (void_type_node);
   const_ptr_type_node
     = build_pointer_type (build_type_variant (void_type_node, 1, 0));
+  fileptr_type_node = ptr_type_node;
 
   float_type_node = make_node (REAL_TYPE);
   TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
@@ -5103,7 +5477,7 @@ build_common_tree_nodes_2 (int short_double)
   layout_type (complex_long_double_type_node);
 
   {
-    tree t = (*targetm.build_builtin_va_list) ();
+    tree t = targetm.build_builtin_va_list ();
 
     /* Many back-ends define record types without setting TYPE_NAME.
        If we copied the record type here, we'd keep the original
@@ -5157,8 +5531,8 @@ reconstruct_complex_type (tree type, tree bottom)
   else
     return bottom;
 
-  TREE_READONLY (outer) = TREE_READONLY (type);
-  TREE_THIS_VOLATILE (outer) = TREE_THIS_VOLATILE (type);
+  TYPE_READONLY (outer) = TYPE_READONLY (type);
+  TYPE_VOLATILE (outer) = TYPE_VOLATILE (type);
 
   return outer;
 }
@@ -5171,7 +5545,6 @@ build_vector_type_for_mode (tree innertype, enum machine_mode mode)
   t = make_node (VECTOR_TYPE);
   TREE_TYPE (t) = innertype;
   TYPE_MODE (t) = mode;
-  TREE_UNSIGNED (t) = TREE_UNSIGNED (innertype);
   finish_vector_type (t);
   return t;
 }
@@ -5201,44 +5574,85 @@ build_vector_type (tree innertype, int nunits)
 bool
 initializer_zerop (tree init)
 {
+  tree elt;
+
   STRIP_NOPS (init);
 
   switch (TREE_CODE (init))
     {
     case INTEGER_CST:
       return integer_zerop (init);
+
     case REAL_CST:
+      /* ??? Note that this is not correct for C4X float formats.  There,
+        a bit pattern of all zeros is 1.0; 0.0 is encoded with the most
+        negative exponent.  */
       return real_zerop (init)
        && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (init));
+
     case COMPLEX_CST:
       return integer_zerop (init)
        || (real_zerop (init)
            && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (TREE_REALPART (init)))
            && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (TREE_IMAGPART (init))));
-    case CONSTRUCTOR:
-      {
-       /* Set is empty if it has no elements.  */
-        if ((TREE_CODE (TREE_TYPE (init)) == SET_TYPE)
-             && CONSTRUCTOR_ELTS (init))
+
+    case VECTOR_CST:
+      for (elt = TREE_VECTOR_CST_ELTS (init); elt; elt = TREE_CHAIN (elt))
+       if (!initializer_zerop (TREE_VALUE (elt)))
          return false;
+      return true;
 
-       if (AGGREGATE_TYPE_P (TREE_TYPE (init)))
-         {
-           tree aggr_init = CONSTRUCTOR_ELTS (init);
-
-           while (aggr_init)
-             {
-               if (! initializer_zerop (TREE_VALUE (aggr_init)))
-                 return false;
-               aggr_init = TREE_CHAIN (aggr_init);
-             }
-           return true;
-         }
+    case CONSTRUCTOR:
+      elt = CONSTRUCTOR_ELTS (init);
+      if (elt == NULL_TREE)
+       return true;
+
+      /* A set is empty only if it has no elements.  */
+      if (TREE_CODE (TREE_TYPE (init)) == SET_TYPE)
        return false;
-      }
+
+      for (; elt ; elt = TREE_CHAIN (elt))
+       if (! initializer_zerop (TREE_VALUE (elt)))
+         return false;
+      return true;
+
     default:
       return false;
     }
 }
 
+void
+add_var_to_bind_expr (tree bind_expr, tree var)
+{
+  BIND_EXPR_VARS (bind_expr)
+    = chainon (BIND_EXPR_VARS (bind_expr), var);
+  if (BIND_EXPR_BLOCK (bind_expr))
+    BLOCK_VARS (BIND_EXPR_BLOCK (bind_expr))
+      = BIND_EXPR_VARS (bind_expr);
+}
+
+/* Build an empty statement.  */
+
+tree
+build_empty_stmt (void)
+{
+  return build1 (NOP_EXPR, void_type_node, size_zero_node);
+}
+
+
+/* Return true if T (assumed to be a DECL) must be assigned a memory
+   location.  */
+
+bool
+needs_to_live_in_memory (tree t)
+{
+  return (DECL_NEEDS_TO_LIVE_IN_MEMORY_INTERNAL (t)
+         || TREE_STATIC (t)
+          || DECL_EXTERNAL (t)
+         || DECL_NONLOCAL (t)
+         || (TREE_CODE (t) == RESULT_DECL
+             && aggregate_value_p (t, current_function_decl))
+         || decl_function_context (t) != current_function_decl);
+}
+
 #include "gt-tree.h"