Makefile.in (tree-vn.o): New.
authorDiego Novillo <dnovillo@redhat.com>
Wed, 23 Jun 2004 20:12:44 +0000 (20:12 +0000)
committerDiego Novillo <dnovillo@gcc.gnu.org>
Wed, 23 Jun 2004 20:12:44 +0000 (16:12 -0400)
* Makefile.in (tree-vn.o): New.
(tree-ssa-pre.o): Don't depend on RTL_H.
* tree-dfa.c (find_referenced_vars): Don't call init_tree_ssa.
* tree-flow.h (struct var_ann_d): Remove field expr_set.
(add_to_value, expressions_equal_p, get_value_handle, vn_compute,
vn_lookup_or_add, vn_add, vn_lookup, vn_init, vn_delete): Declare.
* tree-optimize.c (execute_init_datastructures): New local function.
(pass_init_datastructures): New local variable.
(init_tree_optimization_passes): Sequence pass_init_datastructures.
* tree-pretty-print.c (MASK_POINTER): Remove.
(dump_generic_node): Handle VALUE_HANDLE.
* tree-ssa-pre.c: Move all value numbering routines to tree-vn.c.
Update callers to use new function names.
Use VALUE_HANDLE_ID and VALUE_HANDLE_EXPR_SET instead of
variable annotations.
* tree-ssa.c (init_tree_ssa): Call vn_init.
(delete_tree_ssa): Call vn_delete.
* tree-vn.c: New file.
* tree.c (tree_size): Handle VALUE_HANDLE.
(tree_node_structure): Likewise.
(iterative_hash_expr): Likewise.
* tree.def (VALUE_HANDLE): New code.
* tree.h (struct tree_value_handle): New.
(VALUE_HANDLE_ID): Define.
(VALUE_HANDLE_EXPR_SET): Define.
(enum tree_node_structure_enum): Add TS_VALUE_HANDLE.
(union tree_node): Add struct tree_value_handle.

From-SVN: r83564

12 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/tree-dfa.c
gcc/tree-flow.h
gcc/tree-optimize.c
gcc/tree-pretty-print.c
gcc/tree-ssa-pre.c
gcc/tree-ssa.c
gcc/tree-vn.c [new file with mode: 0644]
gcc/tree.c
gcc/tree.def
gcc/tree.h

index e2ca75138bc118fb0c92d9a15df8e725e24f274a..320edb0020e4baf2c12731d4fe005ebb0b9b7086 100644 (file)
@@ -1,3 +1,33 @@
+2004-06-23  Diego Novillo  <dnovillo@redhat.com>
+
+       * Makefile.in (tree-vn.o): New.
+       (tree-ssa-pre.o): Don't depend on RTL_H.
+       * tree-dfa.c (find_referenced_vars): Don't call init_tree_ssa.
+       * tree-flow.h (struct var_ann_d): Remove field expr_set.
+       (add_to_value, expressions_equal_p, get_value_handle, vn_compute,
+       vn_lookup_or_add, vn_add, vn_lookup, vn_init, vn_delete): Declare.
+       * tree-optimize.c (execute_init_datastructures): New local function.
+       (pass_init_datastructures): New local variable.
+       (init_tree_optimization_passes): Sequence pass_init_datastructures.
+       * tree-pretty-print.c (MASK_POINTER): Remove.
+       (dump_generic_node): Handle VALUE_HANDLE.
+       * tree-ssa-pre.c: Move all value numbering routines to tree-vn.c.
+       Update callers to use new function names.
+       Use VALUE_HANDLE_ID and VALUE_HANDLE_EXPR_SET instead of
+       variable annotations.
+       * tree-ssa.c (init_tree_ssa): Call vn_init.
+       (delete_tree_ssa): Call vn_delete.
+       * tree-vn.c: New file.
+       * tree.c (tree_size): Handle VALUE_HANDLE.
+       (tree_node_structure): Likewise.
+       (iterative_hash_expr): Likewise.
+       * tree.def (VALUE_HANDLE): New code.
+       * tree.h (struct tree_value_handle): New.
+       (VALUE_HANDLE_ID): Define.
+       (VALUE_HANDLE_EXPR_SET): Define.
+       (enum tree_node_structure_enum): Add TS_VALUE_HANDLE.
+       (union tree_node): Add struct tree_value_handle.
+
 2004-06-23  Andrew Pinski  <apinski@apple.com>
 
        * c-typeck.c (composite_type):
index 63c7ebc3d13b2e1cd7c1cade50f5e8b96f667889..81b5b7e51eb53299d4a0c478c2195196c1827a30 100644 (file)
@@ -887,7 +887,7 @@ C_OBJS = c-parse.o c-lang.o stub-objc.o $(C_AND_OBJC_OBJS)
 OBJS-common = \
  tree-cfg.o tree-dfa.o tree-eh.o tree-ssa.o tree-optimize.o tree-gimple.o  \
  tree-alias-type.o gimplify.o tree-pretty-print.o tree-into-ssa.o          \
- tree-outof-ssa.o tree-alias-common.o tree-ssa-ccp.o                      \
+ tree-outof-ssa.o tree-alias-common.o tree-ssa-ccp.o tree-vn.o             \
  @ANDER@ tree-ssa-dce.o  tree-ssa-copy.o tree-nrv.o tree-ssa-copyrename.o  \
  tree-ssa-pre.o tree-ssa-live.o tree-ssa-operands.o tree-ssa-alias.o       \
  tree-ssa-phiopt.o tree-ssa-forwprop.o tree-nested.o tree-ssa-dse.o       \
@@ -1640,9 +1640,12 @@ tree-ssa-copyrename.o : tree-ssa-copyrename.c $(TREE_FLOW_H) $(CONFIG_H) \
    diagnostic.h errors.h toplev.h function.h $(TIMEVAR_H) tree-pass.h \
    tree-alias-common.h $(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_SSA_LIVE_H)
 tree-ssa-pre.o : tree-ssa-pre.c $(TREE_FLOW_H) $(CONFIG_H) \
-   $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) \
+   $(SYSTEM_H) $(TREE_H) $(TM_P_H) $(EXPR_H) \
    $(GGC_H) output.h diagnostic.h errors.h toplev.h $(TIMEVAR_H) \
    $(TM_H) coretypes.h $(TREE_DUMP_H) tree-pass.h $(FLAGS_H)
+tree-vn.o : tree-vn.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GGC_H) \
+   $(TREE_H) $(TREE_FLOW_H) $(HASHTAB_H) langhooks.h tree-pass.h \
+   $(TREE_DUMP_H) diagnostic.h
 tree-cfg.o : tree-cfg.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
    $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) $(FLAGS_H) output.h \
    diagnostic.h errors.h function.h $(TIMEVAR_H) $(TM_H) coretypes.h \
@@ -3068,6 +3071,7 @@ distclean: clean lang.distclean
        -rm -f fixinc/Makefile
 # Delete po/*.gmo only if we are not building in the source directory.
        -if [ ! -f po/exgettext ]; then rm -f po/*.gmo; fi
+       -rmdir ada cp f java objc fixinc intl po testsuite 2>/dev/null
 
 # Get rid of every file that's generated from some other file, except for `configure'.
 # Most of these files ARE PRESENT in the GCC distribution.
index 307086bedb776197fae5c04978cb95dfbc5293f2..bc1f8f5dd44581daf15cdcedd421fe7c8ff6fd91 100644 (file)
@@ -111,10 +111,6 @@ find_referenced_vars (void)
   struct walk_state walk_state;
   tree block;
 
-  /* This is the very first pass in preparation for building the SSA
-     form of the function, so initialize internal data structures now.  */
-  init_tree_ssa ();
-
   /* Walk the lexical blocks in the function looking for variables that may
      have been used to declare VLAs and for nested functions.  Both
      constructs create hidden uses of variables. 
index 6ddf72c2cfc12057a373cc4589a164e415da4a84..e18c1e4c48dd11a943992e9a988c5cfd425b9946 100644 (file)
@@ -167,11 +167,6 @@ struct var_ann_d GTY(())
      live at the same time and this can happen for each call to the
      dominator optimizer.  */
   tree current_def;
-
-  /* The set of expressions represented by this variable if it is a
-     value handle.  This is used by GVN-PRE.  */
-  PTR GTY ((skip)) expr_set;
-  
 };
 
 
@@ -576,12 +571,23 @@ extern bool tree_can_throw_internal (tree);
 extern bool tree_can_throw_external (tree);
 extern void add_stmt_to_eh_region (tree, int);
 
-/* In tree-ssa-pre.c */
-tree get_value_handle (tree);
-void set_value_handle (tree, tree);
+/* In tree-ssa-pre.c  */
+void add_to_value (tree, tree);
 void debug_value_expressions (tree);
 void print_value_expressions (FILE *, tree);
 
+
+/* In tree-vn.c  */
+bool expressions_equal_p (tree e1, tree e2);
+tree get_value_handle (tree);
+hashval_t vn_compute (tree, hashval_t);
+tree vn_lookup_or_add (tree);
+void vn_add (tree, tree);
+tree vn_lookup (tree);
+void vn_init (void);
+void vn_delete (void);
+
+
 /* In tree-sra.c  */
 void insert_edge_copies (tree stmt, basic_block bb);
 
index 30e1e7c25efd4679c66a9a1f98edc6ea3694c082..a9217b187c4201d4016a4906c2620a0782f66658 100644 (file)
@@ -153,6 +153,33 @@ static struct tree_opt_pass pass_free_datastructures =
   0                                    /* todo_flags_finish */
 };
 
+
+/* Do the actions required to initialize internal data structures used
+   in tree-ssa optimization passes.  */
+
+static void
+execute_init_datastructures (void)
+{
+  /* Allocate hash tables, arrays and other structures.  */
+  init_tree_ssa ();
+}
+
+static struct tree_opt_pass pass_init_datastructures =
+{
+  NULL,                                        /* name */
+  NULL,                                        /* gate */
+  execute_init_datastructures,         /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  0,                                   /* tv_id */
+  PROP_cfg,                            /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  0                                    /* todo_flags_finish */
+};
+
 /* Iterate over the pass tree allocating dump file numbers.  We want
    to do this depth first, and independent of whether the pass is
    enabled or not.  */
@@ -253,6 +280,7 @@ init_tree_optimization_passes (void)
   NEXT_PASS (pass_lower_eh);
   NEXT_PASS (pass_build_cfg);
   NEXT_PASS (pass_tree_profile);
+  NEXT_PASS (pass_init_datastructures);
   NEXT_PASS (pass_all_optimizations);
   NEXT_PASS (pass_mudflap_2);
   NEXT_PASS (pass_free_datastructures);
index 6ebf07564c7c0504b9b83e48008cb1901d41675a..fe115bc3ca8e644680cf2e507118c5d9057ae217 100644 (file)
@@ -55,8 +55,6 @@ static void dump_generic_bb_buff (pretty_printer *, basic_block, int, int);
    lang_hooks.decl_printable_name (TREE_OPERAND (NODE, 0), 1) : \
    lang_hooks.decl_printable_name (NODE, 1))
 
-#define MASK_POINTER(P)        ((unsigned)((unsigned long)(P) & 0xffff))
-
 static pretty_printer buffer;
 static int initialized = 0;
 static bool dumping_stmts;
@@ -1403,6 +1401,10 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
       pp_decimal_int (buffer, SSA_NAME_VERSION (node));
       break;
 
+    case VALUE_HANDLE:
+      pp_printf (buffer, "VH.%d", VALUE_HANDLE_ID (node));
+      break;
+
     default:
       NIY;
     }
index c8d8035f5ec263bcd59110fac9195a510c1a92f3..5c32bc2878775147e98d6a0b5c1ecea52ae91f28 100644 (file)
@@ -19,6 +19,7 @@ You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to
 the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
@@ -26,11 +27,6 @@ Boston, MA 02111-1307, USA.  */
 #include "errors.h"
 #include "ggc.h"
 #include "tree.h"
-
-/* These RTL headers are needed for basic-block.h.  */
-#include "rtl.h"
-#include "tm_p.h"
-#include "hard-reg-set.h"
 #include "basic-block.h"
 #include "diagnostic.h"
 #include "tree-inline.h"
@@ -48,6 +44,7 @@ Boston, MA 02111-1307, USA.  */
 #include "splay-tree.h"
 #include "bitmap.h"
 #include "langhooks.h"
+
 /* TODO:
    
    1. Implement load value numbering.
@@ -279,10 +276,8 @@ static struct
 static tree find_leader (value_set_t, tree);
 static void value_insert_into_set (value_set_t, tree);
 static void insert_into_set (value_set_t, tree);
-static void add_to_value (tree, tree);
 static value_set_t set_new  (bool);
 static bool is_undefined_value (tree);
-static bool expressions_equal_p (tree, tree);
 static tree create_expression_by_pieces (basic_block, tree, tree);
 
 /* We can add and remove elements and entries to and from sets
@@ -293,117 +288,12 @@ static alloc_pool value_set_node_pool;
 static alloc_pool binary_node_pool;
 static alloc_pool unary_node_pool;
 
-/* The value table that maps expressions to values.  */
-
-static htab_t value_table;
 
 /* The phi_translate_table caches phi translations for a given
    expression and predecessor.  */
 
 static htab_t phi_translate_table;
 
-/* Compare two expressions E1 and E2 and return true if they are
-   equal.  */
-
-static bool
-expressions_equal_p (tree e1, tree e2)
-{
-  tree te1, te2;
-  
-  if (e1 == e2)
-    return true;
-  
-  te1 = TREE_TYPE (e1);
-  te2 = TREE_TYPE (e2);
-
-  if (TREE_CODE (e1) == TREE_CODE (e2) 
-      && (te1 == te2 || lang_hooks.types_compatible_p (te1, te2))
-      && operand_equal_p (e1, e2, 0))
-    return true;
-  return false;
-}
-
-/* Map expressions to values.  These are simple pairs of expressions
-   and the values they represent.  To find the value represented by
-   an expression, we use a hash table where the elements are {e,v}
-   pairs, and the expression is the key.  */
-
-typedef struct val_expr_pair_d
-{
-  tree v, e;
-  hashval_t hashcode;
-} *val_expr_pair_t;
-
-
-/* Hash a {v,e} pair that is pointed to by P.
-   The hashcode is cached in the val_expr_pair, so we just return
-   that.  */
-
-static hashval_t
-val_expr_pair_hash (const void *p)
-{
-  const val_expr_pair_t ve = (val_expr_pair_t) p;
-  return ve->hashcode;
-}
-
-
-/* Given two val_expr_pair_t's, return true if they represent the same
-   expression, false otherwise.
-   P1 and P2 should point to the val_expr_pair_t's to be compared.  */
-
-static int
-val_expr_pair_expr_eq (const void *p1, const void *p2)
-{
-  const val_expr_pair_t ve1 = (val_expr_pair_t) p1;
-  const val_expr_pair_t ve2 = (val_expr_pair_t) p2;
-
-  if (expressions_equal_p (ve1->e, ve2->e))
-    return true;
-  
-  return false;
-}
-
-
-/* Get the value handle of EXPR.  This is the only correct way to get
-   the value handle for a "thing". 
-   Returns NULL if the value handle does not exist.  */
-
-tree
-get_value_handle (tree expr)
-{
-  /* We should never see these.  */
-  if (DECL_P (expr))
-    abort ();
-  else if (TREE_CODE (expr) == SSA_NAME)
-    {
-      return SSA_NAME_VALUE (expr);
-    }
-  else if (TREE_CODE_CLASS (TREE_CODE (expr)) == 'c')
-    return expr;
-  else if (EXPR_P (expr))
-    {
-      tree_ann_t ann = tree_ann (expr);  
-      if (ann)
-       return ann->common.value_handle;
-      return NULL;
-    }
-  abort ();
-}
-
-
-/* Set the value handle for expression E to value V */
-   
-void
-set_value_handle (tree e, tree v)
-{
-  if (DECL_P (e))
-    abort ();
-  else if (TREE_CODE (e) == SSA_NAME)
-    SSA_NAME_VALUE (e) = v;
-  else if (EXPR_P (e))
-    get_tree_ann (e)->common.value_handle = v;
-}
-
 /* A three tuple {e, pred, v} used to cache phi translations in the
    phi_translate_table.  */
 
@@ -468,7 +358,7 @@ phi_trans_lookup (tree e, basic_block pred)
   struct expr_pred_trans_d ept;
   ept.e = e;
   ept.pred = pred;
-  ept.hashcode = iterative_hash_expr (e, (unsigned long) pred);
+  ept.hashcode = vn_compute (e, (unsigned long) pred);
   slot = htab_find_slot_with_hash (phi_translate_table, &ept, ept.hashcode,
                                   NO_INSERT);
   if (!slot)
@@ -489,7 +379,7 @@ phi_trans_add (tree e, tree v, basic_block pred)
   new_pair->e = e;
   new_pair->pred = pred;
   new_pair->v = v;
-  new_pair->hashcode = iterative_hash_expr (e, (unsigned long) pred);
+  new_pair->hashcode = vn_compute (e, (unsigned long) pred);
   slot = htab_find_slot_with_hash (phi_translate_table, new_pair,
                                   new_pair->hashcode, INSERT);
   if (*slot)
@@ -497,31 +387,11 @@ phi_trans_add (tree e, tree v, basic_block pred)
   *slot = (void *) new_pair;
 }
 
-/* Search in TABLE for an existing instance of expression E,
-   and return its value, or NULL if none has been set.  */
-
-static inline tree
-lookup (htab_t table, tree e)
-{
-  void **slot;
-  struct val_expr_pair_d vep = {NULL, NULL, 0};
-  if (TREE_CODE_CLASS (TREE_CODE (e)) == 'c')
-    return e;
-  vep.e = e;
-  vep.hashcode = iterative_hash_expr (e,0); 
-  slot = htab_find_slot_with_hash (table, &vep, vep.hashcode, NO_INSERT);
-  if (!slot)
-    return NULL_TREE;
-  else
-    return ((val_expr_pair_t) *slot)->v;
-}
-
 /* Add expression E to the expression set of value V.  */
 
-static inline void
+void
 add_to_value (tree v, tree e)
 {
-  var_ann_t va;
   /* For values representing non-CST nodes, but still function
      invariant things we mark TREE_CONSTANT as true and set the tree
      chain to the actual constant.  This is because unlike values
@@ -536,106 +406,40 @@ add_to_value (tree v, tree e)
       TREE_CHAIN (v) = e;
       return;
     }
-  va = var_ann (v);
-  if (va->expr_set == NULL)
-    va->expr_set = set_new (false);
-  insert_into_set (va->expr_set, e);
-}
-
-/* Insert E into TABLE with value V, and add expression E to the value
-   set for value V.  */
-
-static inline void
-add (htab_t table, tree e, tree v)
-{
-
-  void **slot;
-  val_expr_pair_t new_pair = xmalloc (sizeof (struct val_expr_pair_d));
-  new_pair->e = e;
-  new_pair->v = v;
-  new_pair->hashcode = iterative_hash_expr (e, 0);
-  slot = htab_find_slot_with_hash (table, new_pair, new_pair->hashcode,
-                                  INSERT);
-  if (*slot)
-    free (*slot);
-  *slot = (void *) new_pair;
-  set_value_handle (e, v);
-
-  add_to_value (v, e);
-}
-
-/* A unique counter that is incremented every time we create a new
-   value.  */
-static int pre_uid;
 
-/* Create a new value handle for expression EXPR.  */
-
-static tree
-create_new_value (tree expr)
-{
-  tree a = create_tmp_var_raw (TREE_TYPE (expr), "value");
-  create_var_ann (a);
-  var_ann (a)->uid = pre_uid++;
+  if (VALUE_HANDLE_EXPR_SET (v) == NULL)
+    VALUE_HANDLE_EXPR_SET (v) = set_new (false);
 
-  if (dump_file && (dump_flags & TDF_DETAILS))
-    {     
-      fprintf (dump_file, "Created value ");
-      print_generic_expr (dump_file, a, dump_flags);
-      fprintf (dump_file, " for ");
-      print_generic_expr (dump_file, expr, dump_flags);
-      fprintf (dump_file, "\n");
-    }
-  return a;
+  insert_into_set (VALUE_HANDLE_EXPR_SET (v), e);
 }
 
-/* Like lookup, but creates a new value for expression E if E doesn't
-   already have a value.
-   Return the existing/created value for E.  */
-
-static inline tree
-lookup_or_add (htab_t table, tree e)
-{
-  tree x = lookup (table, e);
-  if (x == NULL_TREE)
-    {
-      tree v;
-      v = create_new_value (e);
-      add (table, e, v);
-      x = v;
-    }
-  set_value_handle (e, x);
-  return x;
-}
 
-  
 /* Return true if value V exists in the bitmap for SET.  */
 
 static inline bool
 value_exists_in_set_bitmap (value_set_t set, tree v)
 {
-  if (TREE_CODE (v) != VAR_DECL)
-    abort ();
-
   if (!set->values)
     return false;
-  return bitmap_bit_p (set->values, get_var_ann (v)->uid);
+
+  return bitmap_bit_p (set->values, VALUE_HANDLE_ID (v));
 }
 
+
 /* Remove value V from the bitmap for SET.  */
 
 static void
 value_remove_from_set_bitmap (value_set_t set, tree v)
 {
-  if (TREE_CODE (v) != VAR_DECL)
-    abort ();
 #ifdef ENABLE_CHECKING
   if (!set->indexed)
     abort ();
 #endif
+
   if (!set->values)
     return;
-  bitmap_clear_bit (set->values, get_var_ann (v)->uid);
+
+  bitmap_clear_bit (set->values, VALUE_HANDLE_ID (v));
 }
 
 
@@ -645,20 +449,21 @@ value_remove_from_set_bitmap (value_set_t set, tree v)
 static inline void
 value_insert_into_set_bitmap (value_set_t set, tree v)
 {
-  if (TREE_CODE (v) != VAR_DECL)
-    abort ();  
 #ifdef ENABLE_CHECKING
   if (!set->indexed)
     abort ();
 #endif
+
   if (set->values == NULL)
     {
       set->values = BITMAP_GGC_ALLOC ();
       bitmap_clear (set->values);
     }
-  bitmap_set_bit (set->values, get_var_ann (v)->uid);
+
+  bitmap_set_bit (set->values, VALUE_HANDLE_ID (v));
 }
 
+
 /* Create a new set.  */
 
 static value_set_t
@@ -681,8 +486,6 @@ insert_into_set (value_set_t set, tree expr)
 {
   value_set_node_t newnode = pool_alloc (value_set_node_pool);
   tree val = get_value_handle (expr);
-  if (DECL_P (expr))
-    abort ();
   
   if (val == NULL)
     abort ();
@@ -873,7 +676,6 @@ value_insert_into_set (value_set_t set, tree expr)
 {
   tree val = get_value_handle (expr);
 
-
   /* Constant and invariant values exist everywhere, and thus,
      actually keeping them in the sets is pointless.  */
   if (TREE_CONSTANT (val))
@@ -913,13 +715,16 @@ print_value_set (FILE *outfile, value_set_t set,
 }
 
 /* Print out the expressions that have VAL to OUTFILE.  */
+
 void
 print_value_expressions (FILE *outfile, tree val)
 {
-  var_ann_t va = var_ann (val);
-  if (va && va->expr_set)
-    print_value_set (outfile, va->expr_set, 
-                    IDENTIFIER_POINTER (DECL_NAME (val)), 0);
+  if (VALUE_HANDLE_EXPR_SET (val))
+    {
+      char s[10];
+      sprintf (s, "VH.%04d", VALUE_HANDLE_ID (val));
+      print_value_set (outfile, VALUE_HANDLE_EXPR_SET (val), s, 0);
+    }
 }
 
 
@@ -983,7 +788,7 @@ phi_translate (tree expr, value_set_t set,  basic_block pred,
            create_tree_ann (newexpr);
            TREE_OPERAND (newexpr, 0) = newop1 == oldop1 ? oldop1 : get_value_handle (newop1);
            TREE_OPERAND (newexpr, 1) = newop2 == oldop2 ? oldop2 : get_value_handle (newop2);
-           lookup_or_add (value_table, newexpr);
+           vn_lookup_or_add (newexpr);
            expr = newexpr;
            phi_trans_add (oldexpr, newexpr, pred);         
          }
@@ -1010,7 +815,7 @@ phi_translate (tree expr, value_set_t set,  basic_block pred,
            memcpy (newexpr, expr, tree_size (expr));
            create_tree_ann (newexpr);   
            TREE_OPERAND (newexpr, 0) = get_value_handle (newop1);
-           lookup_or_add (value_table, newexpr);
+           vn_lookup_or_add (newexpr);
            expr = newexpr;
            phi_trans_add (oldexpr, newexpr, pred);
          }
@@ -1035,7 +840,7 @@ phi_translate (tree expr, value_set_t set,  basic_block pred,
              tree val;
              if (is_undefined_value (PHI_ARG_DEF (phi, i)))
                return NULL;
-             val = lookup_or_add (value_table, PHI_ARG_DEF (phi, i));
+             val = vn_lookup_or_add (PHI_ARG_DEF (phi, i));
              return PHI_ARG_DEF (phi, i);
            }
       }
@@ -1328,15 +1133,6 @@ compute_antic (void)
     fprintf (dump_file, "compute_antic required %d iterations\n", num_iterations);
 }
 
-/* Get the expressions represented by value VAL.  */
-
-static value_set_t
-get_expr_set (tree val)
-{
-  var_ann_t va = var_ann (val);
-  return va->expr_set;
-}
-
 
 /* Find a leader for an expression, or generate one using
    create_expression_by_pieces if it's ANTIC but
@@ -1364,7 +1160,7 @@ find_or_generate_expression (basic_block block, tree expr, tree stmts)
      not really .  */
   if (genop == NULL)
     {
-      genop = get_expr_set (expr)->head->expr;
+      genop = VALUE_HANDLE_EXPR_SET (expr)->head->expr;
       if (TREE_CODE_CLASS (TREE_CODE (genop)) != '1'
          && TREE_CODE_CLASS (TREE_CODE (genop)) != '2')
        abort ();
@@ -1445,7 +1241,7 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts)
       
     }
   v = get_value_handle (expr);
-  add (value_table, name, v);
+  vn_add (name, v);
   insert_into_set (NEW_SETS (block), name);
   value_insert_into_set (AVAIL_OUT (block), name);
   if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1610,7 +1406,7 @@ insert_aux (basic_block block)
                          temp = create_tmp_var (type, "prephitmp");
                          add_referenced_tmp_var (temp);
                          temp = create_phi_node (temp, block);
-                         add (value_table, PHI_RESULT (temp), val);
+                         vn_add (PHI_RESULT (temp), val);
 
 #if 0
                          if (!set_contains_value (AVAIL_OUT (block), val))
@@ -1679,17 +1475,19 @@ insert (void)
     fprintf (dump_file, "insert required %d iterations\n", num_iterations);
 }
 
+
 /* Return true if EXPR has no defining statement in this procedure,
    *AND* isn't a live-on-entry parameter.  */
+
 static bool
 is_undefined_value (tree expr)
 {  
-  
 #ifdef ENABLE_CHECKING
   /* We should never be handed DECL's  */
   if (DECL_P (expr))
     abort ();
 #endif
+
   if (TREE_CODE (expr) == SSA_NAME)
     {
       /* XXX: Is this the correct test?  */
@@ -1698,6 +1496,7 @@ is_undefined_value (tree expr)
       if (IS_EMPTY_STMT (SSA_NAME_DEF_STMT (expr)))
        return true;
     }
+
   return false;
 }
 
@@ -1731,7 +1530,7 @@ compute_avail (basic_block block)
            {
              tree val;
              tree def = default_def (param);
-             val = lookup_or_add (value_table, def);
+             val = vn_lookup_or_add (def);
              insert_into_set (TMP_GEN (block), def);
              value_insert_into_set (AVAIL_OUT (block), def);
            }
@@ -1746,6 +1545,7 @@ compute_avail (basic_block block)
       dom = get_immediate_dominator (CDI_DOMINATORS, block);
       if (dom)
        set_copy (AVAIL_OUT (block), AVAIL_OUT (dom));
+
       for (phi = phi_nodes (block); phi; phi = PHI_CHAIN (phi))
        {
          /* Ignore virtual PHIs until we can do PRE on expressions
@@ -1753,7 +1553,7 @@ compute_avail (basic_block block)
          if (!is_gimple_reg (SSA_NAME_VAR (PHI_RESULT (phi))))
            continue;
 
-         lookup_or_add (value_table, PHI_RESULT (phi));
+         vn_lookup_or_add (PHI_RESULT (phi));
          value_insert_into_set (AVAIL_OUT (block), PHI_RESULT (phi));
          insert_into_set (PHI_GEN (block), PHI_RESULT (phi));
        }
@@ -1773,7 +1573,7 @@ compute_avail (basic_block block)
              for (j = 0; j < NUM_DEFS (STMT_DEF_OPS (stmt)); j++)
                {
                  tree def = DEF_OP (STMT_DEF_OPS (stmt), j);
-                 lookup_or_add (value_table, def);
+                 vn_lookup_or_add (def);
                  insert_into_set (TMP_GEN (block), def);
                  value_insert_into_set (AVAIL_OUT (block), def);
                }
@@ -1782,7 +1582,7 @@ compute_avail (basic_block block)
                  tree use = USE_OP (STMT_USE_OPS (stmt), j);
                  if (TREE_CODE (use) == SSA_NAME)
                    {
-                     lookup_or_add (value_table, use);
+                     vn_lookup_or_add (use);
                      insert_into_set (TMP_GEN (block), use);
                      value_insert_into_set (AVAIL_OUT (block), use);
                    }
@@ -1801,7 +1601,7 @@ compute_avail (basic_block block)
              STRIP_USELESS_TYPE_CONVERSION (op1);
              if (is_gimple_min_invariant (op1))
                {
-                 add (value_table, op0, lookup_or_add (value_table, op1));
+                 vn_add (op0, vn_lookup_or_add (op1));
                  insert_into_set (TMP_GEN (block), op0);
                  value_insert_into_set (AVAIL_OUT (block), op0);
                }
@@ -1812,15 +1612,15 @@ compute_avail (basic_block block)
                  tree newt;
                  bop1 = TREE_OPERAND (op1, 0);
                  bop2 = TREE_OPERAND (op1, 1);
-                 val1 = lookup_or_add (value_table, bop1);
-                 val2 = lookup_or_add (value_table, bop2);
+                 val1 = vn_lookup_or_add (bop1);
+                 val2 = vn_lookup_or_add (bop2);
  
                  newt = pool_alloc (binary_node_pool);
                  memcpy (newt, op1, tree_size (op1));
                  TREE_OPERAND (newt, 0) = val1;
                  TREE_OPERAND (newt, 1) = val2;
-                 val = lookup_or_add (value_table, newt);
-                 add (value_table, op0, val);
+                 val = vn_lookup_or_add (newt);
+                 vn_add (op0, val);
                  if (!is_undefined_value (bop1))
                    value_insert_into_set (EXP_GEN (block), bop1);
                  if (!is_undefined_value (bop2))
@@ -1836,12 +1636,12 @@ compute_avail (basic_block block)
                  tree val, val1;
                  tree newt;
                  uop = TREE_OPERAND (op1, 0);
-                 val1 = lookup_or_add (value_table, uop);
+                 val1 = vn_lookup_or_add (uop);
                  newt = pool_alloc (unary_node_pool);
                  memcpy (newt, op1, tree_size (op1));
                  TREE_OPERAND (newt, 0) = val1;
-                 val = lookup_or_add (value_table, newt);
-                 add (value_table, op0, val);
+                 val = vn_lookup_or_add (newt);
+                 vn_add (op0, val);
                  if (!is_undefined_value (uop))
                    value_insert_into_set (EXP_GEN (block), uop);
                  value_insert_into_set (EXP_GEN (block), newt);
@@ -1850,8 +1650,8 @@ compute_avail (basic_block block)
                }
              else if (TREE_CODE (op1) == SSA_NAME)
                {
-                 tree val = lookup_or_add (value_table, op1);
-                 add (value_table, op0, val);
+                 tree val = vn_lookup_or_add (op1);
+                 vn_add (op0, val);
                  if (!is_undefined_value (op1))
                    value_insert_into_set (EXP_GEN (block), op1);
                  insert_into_set (TMP_GEN (block), op0);
@@ -1863,7 +1663,7 @@ compute_avail (basic_block block)
                  for (j = 0; j < NUM_DEFS (STMT_DEF_OPS (stmt)); j++)
                    {
                      tree def = DEF_OP (STMT_DEF_OPS (stmt), j);
-                     lookup_or_add (value_table, def);
+                     vn_lookup_or_add (def);
                      insert_into_set (TMP_GEN (block), def);
                      value_insert_into_set (AVAIL_OUT (block), def);
                      if (def != op0)
@@ -1874,7 +1674,7 @@ compute_avail (basic_block block)
                      tree use = USE_OP (STMT_USE_OPS (stmt), j);
                      if (TREE_CODE (use) == SSA_NAME)
                        {
-                         lookup_or_add (value_table, use);
+                         vn_lookup_or_add (use);
                          insert_into_set (TMP_GEN (block), use);
                          value_insert_into_set (AVAIL_OUT (block), use);
                        }
@@ -1887,7 +1687,7 @@ compute_avail (basic_block block)
              for (j = 0; j < NUM_DEFS (STMT_DEF_OPS (stmt)); j++)
                {
                  tree def = DEF_OP (STMT_DEF_OPS (stmt), j);
-                 lookup_or_add (value_table, def);
+                 vn_lookup_or_add (def);
                  insert_into_set (TMP_GEN (block), def);
                  value_insert_into_set (AVAIL_OUT (block), def);
                }
@@ -1896,7 +1696,7 @@ compute_avail (basic_block block)
                  tree use = USE_OP (STMT_USE_OPS (stmt), j);
                  if (TREE_CODE (use) == SSA_NAME)
                    {
-                     lookup_or_add (value_table, use);
+                     vn_lookup_or_add (use);
                      insert_into_set (TMP_GEN (block), use);
                      value_insert_into_set (AVAIL_OUT (block), use);
                    }
@@ -1904,13 +1704,14 @@ compute_avail (basic_block block)
            }
        }
     }
+
   for (son = first_dom_son (CDI_DOMINATORS, block);
        son;
        son = next_dom_son (CDI_DOMINATORS, son))
     compute_avail (son);
-
 }
 
+
 /* Eliminate fully redundant computations.  */
 
 static void
@@ -1931,6 +1732,7 @@ eliminate (void)
              || NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt))
              || stmt_ann (stmt)->has_volatile_ops)
             continue;
+
           /* Lookup the RHS of the expression, see if we have an
             available computation for it. If so, replace the RHS with
             the available computation.  */
@@ -1945,8 +1747,8 @@ eliminate (void)
                  || (TREE_CODE_CLASS (TREE_CODE (expr)) != '2' 
                   && TREE_CODE_CLASS (TREE_CODE (expr)) != '1'))
                continue;
-             sprime = find_leader (AVAIL_OUT (b),
-                                   lookup (value_table, t));
+
+             sprime = find_leader (AVAIL_OUT (b), vn_lookup (t));
               if (sprime 
                  && sprime != t 
                  && may_propagate_copy (sprime, TREE_OPERAND (stmt, 1)))
@@ -1965,11 +1767,11 @@ eliminate (void)
                   modify_stmt (stmt);
                 }
             }
-
         }
     }
 }
 
+
 /* Main entry point to the SSA-PRE pass.
 
    PHASE indicates which dump file from the DUMP_FILES array to use when
@@ -1980,7 +1782,6 @@ execute_pre (void)
 {
   size_t tsize;
   basic_block bb;
-  pre_uid = num_referenced_vars;
   memset (&pre_stats, 0, sizeof (pre_stats));
   FOR_ALL_BB (bb)
     {
@@ -1989,8 +1790,6 @@ execute_pre (void)
   phi_translate_table = htab_create (511, expr_pred_trans_hash,
                                     expr_pred_trans_eq,
                                     free);
-  value_table = htab_create (511, val_expr_pair_hash,
-                            val_expr_pair_expr_eq, free);
   value_set_pool = create_alloc_pool ("Value sets",
                                      sizeof (struct value_set), 30);
   value_set_node_pool = create_alloc_pool ("Value set nodes",
@@ -2048,7 +1847,6 @@ execute_pre (void)
   free_alloc_pool (value_set_node_pool);
   free_alloc_pool (binary_node_pool);
   free_alloc_pool (unary_node_pool);
-  htab_delete (value_table);
   htab_delete (phi_translate_table);
   
   FOR_ALL_BB (bb)
index a931d9f7fef6c769919e568aff7f4adb37dedfba..91bfaf54cf8f4c73bb83b52eda0334338447514a 100644 (file)
@@ -497,6 +497,7 @@ init_tree_ssa (void)
   init_ssa_operands ();
   init_ssanames ();
   init_phinodes ();
+  vn_init ();
   global_var = NULL_TREE;
   aliases_computed_p = false;
 }
@@ -527,6 +528,7 @@ delete_tree_ssa (void)
   fini_ssanames ();
   fini_phinodes ();
   fini_ssa_operands ();
+  vn_delete ();
 
   global_var = NULL_TREE;
   BITMAP_XFREE (call_clobbered_vars);
diff --git a/gcc/tree-vn.c b/gcc/tree-vn.c
new file mode 100644 (file)
index 0000000..de4c361
--- /dev/null
@@ -0,0 +1,257 @@
+/* Value Numbering routines for tree expressions.
+   Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Contributed by Daniel Berlin <dan@dberlin.org>, Steven Bosscher
+   <stevenb@suse.de> and Diego Novillo <dnovillo@redhat.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "ggc.h"
+#include "tree.h"
+#include "tree-flow.h"
+#include "hashtab.h"
+#include "langhooks.h"
+#include "tree-pass.h"
+#include "tree-dump.h"
+#include "diagnostic.h"
+
+/* The value table that maps expressions to values.  */
+static htab_t value_table;
+
+/* Map expressions to values.  These are simple pairs of expressions
+   and the values they represent.  To find the value represented by
+   an expression, we use a hash table where the elements are {e,v}
+   pairs, and the expression is the key.  */
+typedef struct val_expr_pair_d
+{
+  tree v, e;
+  hashval_t hashcode;
+} *val_expr_pair_t;
+
+static void set_value_handle (tree e, tree v);
+
+
+/* Create and return a new value handle node of type TYPE.  */
+
+static tree
+make_value_handle (tree type)
+{
+  static unsigned int id = 0;
+  tree vh;
+
+  vh = build0 (VALUE_HANDLE, type);
+  VALUE_HANDLE_ID (vh) = id++;
+  return vh;
+}
+
+
+/* Given an expression or statement P, compute a hash value number using the
+   code of the expression and its real operands.  */
+
+hashval_t
+vn_compute (tree expr, hashval_t val)
+{
+  val = iterative_hash_expr (expr, val);
+  return val;
+}
+
+
+/* Compare two expressions E1 and E2 and return true if they are
+   equal.  */
+
+bool
+expressions_equal_p (tree e1, tree e2)
+{
+  tree te1, te2;
+  
+  if (e1 == e2)
+    return true;
+
+  te1 = TREE_TYPE (e1);
+  te2 = TREE_TYPE (e2);
+
+  if (TREE_CODE (e1) == TREE_CODE (e2) 
+      && (te1 == te2 || lang_hooks.types_compatible_p (te1, te2))
+      && operand_equal_p (e1, e2, 0))
+    return true;
+
+  return false;
+}
+
+
+/* Hash a {v,e} pair that is pointed to by P.
+   The hashcode is cached in the val_expr_pair, so we just return
+   that.  */
+
+static hashval_t
+val_expr_pair_hash (const void *p)
+{
+  const val_expr_pair_t ve = (val_expr_pair_t) p;
+  return ve->hashcode;
+}
+
+
+/* Given two val_expr_pair_t's, return true if they represent the same
+   expression, false otherwise.
+   P1 and P2 should point to the val_expr_pair_t's to be compared.  */
+
+static int
+val_expr_pair_expr_eq (const void *p1, const void *p2)
+{
+  const val_expr_pair_t ve1 = (val_expr_pair_t) p1;
+  const val_expr_pair_t ve2 = (val_expr_pair_t) p2;
+
+  if (expressions_equal_p (ve1->e, ve2->e))
+    return true;
+  
+  return false;
+}
+
+
+/* Set the value handle for expression E to value V */
+   
+static void
+set_value_handle (tree e, tree v)
+{
+  if (TREE_CODE (e) == SSA_NAME)
+    SSA_NAME_VALUE (e) = v;
+  else if (EXPR_P (e) || DECL_P (e))
+    get_tree_ann (e)->common.value_handle = v;
+  else if (TREE_CODE_CLASS (TREE_CODE (e)) == 'c')
+    /* Do nothing.  Constants are their own value handles.  */
+    ;
+  else
+    abort ();
+}
+
+
+/* Insert E into VALUE_TABLE with value V, and add expression E to the
+   value set for value V.  */
+
+void
+vn_add (tree e, tree v)
+{
+  void **slot;
+  val_expr_pair_t new_pair = xmalloc (sizeof (struct val_expr_pair_d));
+  new_pair->e = e;
+  new_pair->v = v;
+  new_pair->hashcode = vn_compute (e, 0);
+  slot = htab_find_slot_with_hash (value_table, new_pair, new_pair->hashcode,
+                                  INSERT);
+  if (*slot)
+    free (*slot);
+  *slot = (void *) new_pair;
+  set_value_handle (e, v);
+
+  add_to_value (v, e);
+}
+
+
+/* Search in VALUE_TABLE for an existing instance of expression E, and
+   return its value, or NULL if none has been set.  */
+
+tree
+vn_lookup (tree e)
+{
+  void **slot;
+  struct val_expr_pair_d vep = {NULL, NULL, 0};
+
+  if (TREE_CODE_CLASS (TREE_CODE (e)) == 'c')
+    return e;
+  vep.e = e;
+  vep.hashcode = vn_compute (e, 0); 
+  slot = htab_find_slot_with_hash (value_table, &vep, vep.hashcode, NO_INSERT);
+  if (!slot)
+    return NULL_TREE;
+  else
+    return ((val_expr_pair_t) *slot)->v;
+}
+
+
+/* Like vn_lookup, but creates a new value for expression E if E doesn't
+   already have a value.  Return the existing/created value for E.  */
+
+tree
+vn_lookup_or_add (tree e)
+{
+  tree x = vn_lookup (e);
+  if (x == NULL_TREE)
+    {
+      tree v = make_value_handle (TREE_TYPE (e));
+
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       {     
+         fprintf (dump_file, "Created value ");
+         print_generic_expr (dump_file, v, dump_flags);
+         fprintf (dump_file, " for ");
+         print_generic_expr (dump_file, e, dump_flags);
+         fprintf (dump_file, "\n");
+       }
+
+      vn_add (e, v);
+      x = v;
+    }
+
+  set_value_handle (e, x);
+
+  return x;
+}
+
+
+/* Get the value handle of EXPR.  This is the only correct way to get
+   the value handle for a "thing".  If EXPR does not have a value
+   handle associated, it generates and returns a new one.  */
+
+tree
+get_value_handle (tree expr)
+{
+  if (TREE_CODE (expr) == SSA_NAME)
+    return SSA_NAME_VALUE (expr);
+  else if (TREE_CODE_CLASS (TREE_CODE (expr)) == 'c')
+    return expr;
+  else if (EXPR_P (expr) || DECL_P (expr))
+    {
+      tree_ann_t ann = tree_ann (expr);
+      return ((ann) ? ann->common.value_handle : NULL_TREE);
+    }
+
+  abort ();
+}
+
+
+/* Initialize data structures used in value numbering.  */
+
+void
+vn_init (void)
+{
+  value_table = htab_create (511, val_expr_pair_hash,
+                            val_expr_pair_expr_eq, free);
+}
+
+
+/* Delete data used for value numbering.  */
+
+void
+vn_delete (void)
+{
+  htab_delete (value_table);
+  value_table = NULL;
+}
index 716bc35fa70cdf2ca48cbfb5d82f42e4571ecba8..25431d4495b66a1ef0a4d442d78d0e846839f3d6 100644 (file)
@@ -196,6 +196,7 @@ tree_size (tree node)
 
        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);
@@ -1497,6 +1498,7 @@ tree_node_structure (tree t)
     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 ();
@@ -3851,7 +3853,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);
index 57596a2b45827add95517ff7a3d8877a36d9481c..f7dabaf46c8643d21068423bb262b4e435d47d1d 100644 (file)
@@ -899,6 +899,12 @@ DEFTREECODE (EH_FILTER_EXPR, "eh_filter_expr", 's', 2)
    Use the interface in tree-iterator.h to access this node.  */
 DEFTREECODE (STATEMENT_LIST, "statement_list", 'x', 0)
 
+/* Value handles.  Artificial nodes to represent expressions in
+   partial redundancy elimination (tree-ssa-pre.c).  These nodes are
+   used for expression canonicalization.  If two expressions compute
+   the same value, they will be assigned the same value handle.  */
+DEFTREECODE (VALUE_HANDLE, "value_handle", 'x', 0)
+
 /*
 Local variables:
 mode:c
index c404b84d1bcd7be588703ebeabc3eec8e606cd9d..3d3c6f11baa2c8a914024d6f5bde40b9eed3eda9 100644 (file)
@@ -2234,6 +2234,28 @@ struct tree_statement_list
   struct tree_statement_list_node *head;
   struct tree_statement_list_node *tail;
 };
+
+#define VALUE_HANDLE_ID(NODE)          \
+  (VALUE_HANDLE_CHECK (NODE)->value_handle.id)
+
+#define VALUE_HANDLE_EXPR_SET(NODE)    \
+  (VALUE_HANDLE_CHECK (NODE)->value_handle.expr_set)
+
+/* Defined and used in tree-ssa-pre.c.  */
+struct value_set;
+
+struct tree_value_handle GTY(())
+{
+  struct tree_common common;
+
+  /* The set of expressions represented by this handle.  */
+  struct value_set * GTY ((skip)) expr_set;
+
+  /* Unique ID for this value handle.  IDs are handed out in a
+     conveniently dense form starting at 0, so that we can make
+     bitmaps of value handles. */
+  unsigned int id;
+};
 \f
 enum tree_node_structure_enum {
   TS_COMMON,
@@ -2252,6 +2274,7 @@ enum tree_node_structure_enum {
   TS_PHI_NODE,
   TS_BLOCK,
   TS_STATEMENT_LIST,
+  TS_VALUE_HANDLE,
   LAST_TS_ENUM
 };
 
@@ -2278,6 +2301,7 @@ union tree_node GTY ((ptr_alias (union lang_tree_node),
   struct tree_phi_node GTY ((tag ("TS_PHI_NODE"))) phi;
   struct tree_block GTY ((tag ("TS_BLOCK"))) block;
   struct tree_statement_list GTY ((tag ("TS_STATEMENT_LIST"))) stmt_list;
+  struct tree_value_handle GTY ((tag ("TS_VALUE_HANDLE"))) value_handle;
 };
 \f
 /* Standard named or nameless data types of the C compiler.  */