OSDN Git Service

* tree.c (type_hash_eq): Allow TYPE_MIN_VALUE which compares equal
[pf3gnuchains/gcc-fork.git] / gcc / tree.c
index 9710ed2..64d2dd5 100644 (file)
@@ -45,6 +45,9 @@ 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"
 
 /* obstack.[ch] explicitly declined to prototype this.  */
 extern int _obstack_allocated_p (struct obstack *h, void *obj);
@@ -68,6 +71,8 @@ static const char * const tree_node_kind_names[] = {
   "perm_tree_lists",
   "temp_tree_lists",
   "vecs",
+  "phi_nodes",
+  "ssa names",
   "random kinds",
   "lang_decl kinds",
   "lang_type kinds"
@@ -131,7 +136,7 @@ tree
 decl_assembler_name (tree decl)
 {
   if (!DECL_ASSEMBLER_NAME_SET_P (decl))
-    (*lang_hooks.set_decl_assembler_name) (decl);
+    lang_hooks.set_decl_assembler_name (decl);
   return DECL_CHECK (decl)->decl.assembler_name;
 }
 
@@ -150,9 +155,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 */
@@ -171,7 +173,7 @@ tree_size (tree node)
        case VECTOR_CST:        return sizeof (struct tree_vector);
        case STRING_CST:        return sizeof (struct tree_string);
        default:
-         return (*lang_hooks.tree_size) (code);
+         return lang_hooks.tree_size (code);
        }
 
     case 'x':  /* something random, like an identifier.  */
@@ -186,8 +188,18 @@ 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);
+         return lang_hooks.tree_size (code);
        }
 
     default:
@@ -212,9 +224,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 +243,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 +267,12 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
        kind = id_kind;
       else if (code == TREE_VEC)
        kind = vec_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;
@@ -303,7 +317,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 +325,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 +334,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,12 +362,19 @@ 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')
     DECL_UID (t) = next_decl_uid++;
@@ -456,9 +477,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 +519,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;
 }
 
@@ -630,7 +650,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 +961,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 +1093,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,
@@ -1119,7 +1113,7 @@ size_in_bytes (tree type)
 
   if (t == 0)
     {
-      (*lang_hooks.types.incomplete_type_error) (NULL_TREE, type);
+      lang_hooks.types.incomplete_type_error (NULL_TREE, type);
       return size_zero_node;
     }
 
@@ -1211,7 +1205,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 +1252,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 +1281,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,11 +1310,13 @@ 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)
          >= (unsigned int) LAST_AND_UNUSED_TREE_CODE)
-       return (*lang_hooks.staticp) (arg);
+       return lang_hooks.staticp (arg);
       else
        return 0;
     }
@@ -1353,7 +1356,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 +1375,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 +1410,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 +1424,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 +1450,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 +1470,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 +1488,12 @@ 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 VALUE_HANDLE:         return TS_VALUE_HANDLE;
 
     default:
       abort ();
@@ -1511,11 +1508,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 +1520,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 +1536,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 +1556,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))
        {
@@ -1653,7 +1592,7 @@ unsafe_for_reeval (tree expr)
       return exp ? unsafe_for_reeval (exp) : 0;
 
     default:
-      tmp = (*lang_hooks.unsafe_for_reeval) (expr);
+      tmp = lang_hooks.unsafe_for_reeval (expr);
       if (tmp >= 0)
        return tmp;
       break;
@@ -1665,7 +1604,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 +1632,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 +1664,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 +1711,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 +1730,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 +1822,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 +1868,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;
-
-         new = fold (build1 (code, TREE_TYPE (exp), op0));
-         break;
+         case 1:
+           op0 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 0), f, r);
+           if (op0 == TREE_OPERAND (exp, 0))
+             return exp;
 
-       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 +2130,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 +2143,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 +2160,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 +2201,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 +2209,6 @@ stabilize_reference_1 (tree e)
     case 'x':
     case 't':
     case 'd':
-    case 'b':
     case '<':
     case 's':
     case 'e':
@@ -2284,12 +2253,86 @@ 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 definitely invariant and it's constant if the
+     decl is static.  (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))
+       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 +2397,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 +2418,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 +2436,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 +2456,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 +2464,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 +2496,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 +2515,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 +2535,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 +2566,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 +2588,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 +2710,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;
+}
+
+#else
+
+/* Record the exact location where an expression or an identifier were
+   encountered.  */
 
-  EXPR_WFL_NODE (wfl) = node;
-  EXPR_WFL_SET_LINECOL (wfl, line, col);
-  if (file != last_file)
+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 +3152,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 +3290,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 +3499,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 +3512,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 +3545,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 +3588,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 +3666,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 +3782,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 +3809,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 +3843,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 +3859,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 +3881,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 +3920,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,31 +3935,45 @@ 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;
 
-  /* 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 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.  */
+  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;
-
-  /* Record this type as the pointer to TO_TYPE.  */
-  if (mode == ptr_mode)
+  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.
-     Also, it guarantees the TYPE_SIZE is in the same obstack as the type.  */
+     with expression-construction, and this simplifies them all.  */
   layout_type (t);
 
   return t;
@@ -3818,29 +3984,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);
@@ -3855,7 +4033,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
@@ -3869,9 +4047,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);
     }
@@ -3964,19 +4147,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);
@@ -4025,7 +4201,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);
@@ -4087,12 +4263,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))
@@ -4133,7 +4307,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);
@@ -4156,9 +4330,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);
 
@@ -4200,7 +4373,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.
@@ -4236,7 +4409,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)
@@ -4266,11 +4439,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;
@@ -4287,9 +4460,9 @@ 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))));
-      type = (*lang_hooks.types.type_for_size) (innerprec, unsignedp);
+      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.
         If FOR_TYPE is 0, do this only for a field that matches the
@@ -4302,8 +4475,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);
        }
@@ -4343,11 +4516,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;
        }
@@ -4356,7 +4529,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);
        }
@@ -4368,13 +4541,14 @@ 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))));
-      tree type = (*lang_hooks.types.type_for_size) (innerprec, unsignedp);
+      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,
         but the resulting extension to its nominal type (a fullword type)
@@ -4386,13 +4560,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);
        }
@@ -4414,10 +4588,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
@@ -4499,38 +4673,62 @@ variably_modified_type_p (tree 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)))
+       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)))
+         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)))
          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;
+      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)
+         {
+           tree t1 = DECL_FIELD_OFFSET (t);
+
+           if (t1 && t1 != error_mark_node && TREE_CODE (t1) != INTEGER_CST)
+             return true;
+
+           t1 = DECL_SIZE (t);
+           if (t1 && t1 != error_mark_node && TREE_CODE (t1) != INTEGER_CST)
+             return true;
+         }
+       break;
 
     default:
       break;
@@ -4538,7 +4736,7 @@ 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);
 }
 
 /* Given a DECL or TYPE, return the scope in which it was declared, or
@@ -4561,9 +4759,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'.
@@ -4659,7 +4854,7 @@ get_callee_fndecl (tree call)
   
   /* We couldn't figure out what was being called.  Maybe the front
      end has some idea.  */
-  return (*lang_hooks.lang_get_callee_fndecl) (call);
+  return lang_hooks.lang_get_callee_fndecl (call);
 }
 
 /* Print debugging information about tree nodes generated during the compile,
@@ -4688,11 +4883,13 @@ 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
   print_type_hash_statistics ();
-  (*lang_hooks.print_statistics) ();
+  lang_hooks.print_statistics ();
 }
 \f
 #define FILE_FUNCTION_FORMAT "_GLOBAL__%s_%s"
@@ -4893,19 +5090,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
@@ -4930,6 +5190,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.  */
 
@@ -4970,6 +5242,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.  */
@@ -5012,17 +5305,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");
@@ -5064,6 +5359,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;
@@ -5102,7 +5398,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
@@ -5114,40 +5410,6 @@ build_common_tree_nodes_2 (int short_double)
 
     va_list_type_node = t;
   }
-
-  unsigned_V4SI_type_node
-    = make_vector (V4SImode, unsigned_intSI_type_node, 1);
-  unsigned_V2HI_type_node
-    = make_vector (V2HImode, unsigned_intHI_type_node, 1);
-  unsigned_V2SI_type_node
-    = make_vector (V2SImode, unsigned_intSI_type_node, 1);
-  unsigned_V2DI_type_node
-    = make_vector (V2DImode, unsigned_intDI_type_node, 1);
-  unsigned_V4HI_type_node
-    = make_vector (V4HImode, unsigned_intHI_type_node, 1);
-  unsigned_V8QI_type_node
-    = make_vector (V8QImode, unsigned_intQI_type_node, 1);
-  unsigned_V8HI_type_node
-    = make_vector (V8HImode, unsigned_intHI_type_node, 1);
-  unsigned_V16QI_type_node
-    = make_vector (V16QImode, unsigned_intQI_type_node, 1);
-  unsigned_V1DI_type_node
-    = make_vector (V1DImode, unsigned_intDI_type_node, 1);
-
-  V16SF_type_node = make_vector (V16SFmode, float_type_node, 0);
-  V4SF_type_node = make_vector (V4SFmode, float_type_node, 0);
-  V4SI_type_node = make_vector (V4SImode, intSI_type_node, 0);
-  V2HI_type_node = make_vector (V2HImode, intHI_type_node, 0);
-  V2SI_type_node = make_vector (V2SImode, intSI_type_node, 0);
-  V2DI_type_node = make_vector (V2DImode, intDI_type_node, 0);
-  V4HI_type_node = make_vector (V4HImode, intHI_type_node, 0);
-  V8QI_type_node = make_vector (V8QImode, intQI_type_node, 0);
-  V8HI_type_node = make_vector (V8HImode, intHI_type_node, 0);
-  V2SF_type_node = make_vector (V2SFmode, float_type_node, 0);
-  V2DF_type_node = make_vector (V2DFmode, double_type_node, 0);
-  V16QI_type_node = make_vector (V16QImode, intQI_type_node, 0);
-  V1DI_type_node = make_vector (V1DImode, intDI_type_node, 0);
-  V4DF_type_node = make_vector (V4DFmode, double_type_node, 0);
 }
 
 /* HACK.  GROSS.  This is absolutely disgusting.  I wish there was a
@@ -5190,73 +5452,128 @@ 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;
 }
 
-/* Returns a vector tree node given a vector mode, the inner type, and
-   the signness.  */
-
+/* Returns a vector tree node given a vector mode and inner type.  */
 tree
-make_vector (enum machine_mode mode, tree innertype, int unsignedp)
+build_vector_type_for_mode (tree innertype, enum machine_mode mode)
 {
   tree t;
-
   t = make_node (VECTOR_TYPE);
   TREE_TYPE (t) = innertype;
   TYPE_MODE (t) = mode;
-  TREE_UNSIGNED (TREE_TYPE (t)) = unsignedp;
   finish_vector_type (t);
-
   return t;
 }
 
+/* Similarly, but takes inner type and units.  */
+
+tree
+build_vector_type (tree innertype, int nunits)
+{
+  enum machine_mode innermode = TYPE_MODE (innertype);
+  enum machine_mode mode;
+
+  if (GET_MODE_CLASS (innermode) == MODE_FLOAT)
+    mode = MIN_MODE_VECTOR_FLOAT;
+  else
+    mode = MIN_MODE_VECTOR_INT;
+
+  for (; mode != VOIDmode ; mode = GET_MODE_WIDER_MODE (mode))
+    if (GET_MODE_NUNITS (mode) == nunits && GET_MODE_INNER (mode) == innermode)
+      return build_vector_type_for_mode (innertype, mode);
+
+  return NULL_TREE;
+}
+
 /* Given an initializer INIT, return TRUE if INIT is zero or some
    aggregate of zeros.  Otherwise return FALSE.  */
-
 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"