OSDN Git Service

2004-05-13 Benjamin Kosnik <bkoz@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree.c
index 0b301e2..33c696e 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"
@@ -186,6 +191,22 @@ 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 EPHI_NODE:         return (sizeof (struct tree_ephi_node)
+                                       + (EPHI_ARG_CAPACITY (node) - 1) *
+                                       sizeof (struct ephi_arg_d));
+
+       case SSA_NAME:          return sizeof (struct tree_ssa_name);
+       case EUSE_NODE:         return sizeof (struct tree_euse_node);
+
+       case EKILL_NODE:
+       case EEXIT_NODE:        return sizeof (struct tree_eref_common);
+
+       case STATEMENT_LIST:    return sizeof (struct tree_statement_list);
+
        default:
          return lang_hooks.tree_size (code);
        }
@@ -212,9 +233,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, EPHI_NODE or STRING_CST
+     without knowing how many elements it will have.  */
+  if (code == TREE_VEC || code == PHI_NODE || code == EPHI_NODE)
     abort ();
 
   TREE_SET_CODE ((tree)&ttmp, code);
@@ -259,6 +280,10 @@ 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
        kind = x_kind;
       break;
@@ -311,6 +336,7 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
 
     case 'c':
       TREE_CONSTANT (t) = 1;
+      TREE_INVARIANT (t) = 1;
       break;
 
     case 'e':
@@ -348,12 +374,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 +489,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;
 }
@@ -1073,44 +1105,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,
@@ -1299,11 +1293,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;
@@ -1321,6 +1322,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)
@@ -1365,7 +1368,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)
@@ -1390,6 +1394,7 @@ save_expr (tree expr)
      eliminated as dead.  */
   TREE_SIDE_EFFECTS (t) = 1;
   TREE_READONLY (t) = 1;
+  TREE_INVARIANT (t) = 1;
   return t;
 }
 
@@ -1417,9 +1422,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;
@@ -1508,7 +1513,14 @@ 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 EPHI_NODE:            return TS_EPHI_NODE;
+    case EUSE_NODE:             return TS_EUSE_NODE;
+    case EKILL_NODE:            return TS_EREF_NODE;
+    case EEXIT_NODE:            return TS_EREF_NODE;
+    case SSA_NAME:             return TS_SSA_NAME;
     case PLACEHOLDER_EXPR:     return TS_COMMON;
+    case STATEMENT_LIST:       return TS_STATEMENT_LIST;
 
     default:
       abort ();
@@ -1551,57 +1563,6 @@ unsave_expr_1 (tree expr)
     }
 }
 
-/* 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.
@@ -1639,6 +1600,14 @@ unsafe_for_reeval (tree 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))
        {
@@ -2053,7 +2022,7 @@ tree
 substitute_placeholder_in_expr (tree exp, tree obj)
 {
   enum tree_code code = TREE_CODE (exp);
-  tree op0, op1, op2;
+  tree op0, op1, op2, op3;
 
   /* If this is a PLACEHOLDER_EXPR, see if we find a corresponding type
      in the chain of OBJ.  */
@@ -2151,6 +2120,19 @@ substitute_placeholder_in_expr (tree exp, tree obj)
            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 ();
          }
@@ -2277,7 +2259,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))
@@ -2330,12 +2312,50 @@ 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 and TREE_INVARIANT for an ADDR_EXPR.  */
+
+void
+recompute_tree_invarant_for_addr_expr (tree t)
+{
+  tree node = TREE_OPERAND (t, 0);
+  bool tc = false, ti = false;
+
+  /* Addresses of constants and static variables are constant;
+     all other decl addresses are invariant.  */
+  if (staticp (node))
+    tc = ti = true;
+  else
+    {
+      /* Step past constant offsets.  */
+      while (1)
+       {
+         if (TREE_CODE (node) == COMPONENT_REF
+             && TREE_CODE (TREE_OPERAND (node, 1)) == FIELD_DECL
+             && ! DECL_BIT_FIELD (TREE_OPERAND (node, 1)))
+           ;
+         else if (TREE_CODE (node) == ARRAY_REF
+                  && TREE_CONSTANT (TREE_OPERAND (node, 1)))
+           ;
+         else
+           break;
+         node = TREE_OPERAND (node, 0);
+       }
+      if (DECL_P (node))
+        ti = true;
+    }
+
+  TREE_CONSTANT (t) = tc;
+  TREE_INVARIANT (t) = ti;
+}
+
 /* 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.
@@ -2400,8 +2420,10 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
   TREE_SET_CODE (t, code);
 
   TREE_TYPE (t) = type;
+  SET_EXPR_LOCUS (t, NULL);
   TREE_COMPLEXITY (t) = 0;
   TREE_OPERAND (t, 0) = node;
+  TREE_BLOCK (t) = NULL_TREE;
   if (node && !TYPE_P (node) && first_rtl_op (code) != 0)
     {
       TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (node);
@@ -2435,6 +2457,8 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
     case ADDR_EXPR:
       if (node)
        {
+         recompute_tree_invarant_for_addr_expr (t);
+
          /* 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
@@ -2459,6 +2483,8 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
       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;
       break;
     }
 
@@ -2476,13 +2502,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;
 
@@ -2506,32 +2534,14 @@ 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;  
 
   return t;
@@ -2541,20 +2551,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 ();
@@ -2571,6 +2571,26 @@ 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;  
 
   return t;
@@ -2580,7 +2600,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;
 
@@ -2722,35 +2742,49 @@ 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).  */
+static GTY(()) tree last_annotated_node;
 
-tree
-build_expr_wfl (tree node, const char *file, int line, int col)
-{
-  static const char *last_file = 0;
-  static tree last_filenode = NULL_TREE;
-  tree wfl = make_node (EXPR_WITH_FILE_LOCATION);
+/* 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 && !TYPE_P (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);
 }
 \f
 /* Return a declaration like DDECL except that its DECL_ATTRIBUTES
@@ -3642,10 +3676,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));
@@ -3760,10 +3792,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;
@@ -3851,9 +3880,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))
        {
@@ -3882,6 +3919,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 ();
 
@@ -4842,6 +4884,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
@@ -5142,6 +5186,30 @@ 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 EPHI_NODE's
+   (dynamically sized) vector.  */
+
+void
+ephi_node_elt_check_failed (int idx, int len, const char *file, int line,
+                           const char *function)
+{
+  internal_error
+    ("tree check: accessed elt %d of ephi_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 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.  */
 
@@ -5182,6 +5250,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.  */
@@ -5224,17 +5313,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");
@@ -5411,44 +5502,94 @@ 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);
+}
+
+bool
+is_essa_node (tree t)
+{
+  if (TREE_CODE (t) == EPHI_NODE || TREE_CODE (t) == EUSE_NODE 
+      || TREE_CODE (t) == EEXIT_NODE || TREE_CODE (t) == EKILL_NODE)
+    return true;
+  return false;
+}
+
+
+/* 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"