This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH]: Move DECL_DEBUG_EXPR to a hashtable
- From: Daniel Berlin <dberlin at dberlin dot org>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 30 May 2005 20:35:19 -0400
- Subject: [PATCH]: Move DECL_DEBUG_EXPR to a hashtable
This will save 4/8 bytes in struct tree_var_decl, once we have it (I've
got it done in a tree already).
This field is only used for debug info generation, and even then, only
in certain cases.
The hashtable is generally very sparse, and this patch has absolutely no
time effect, even on large testcases with -O2 -g/-O3 -g/etc
We use the same technique as the type hash table to avoid keeping trees
alive unnecessarily.
I've also got a followup that moves DECL_VALUE_EXPR to a hashtable,
which will save us some more space in all RTL derived trees without
costing anything that i can measure. This is the reason the structure
is simply called tree_map, etc. It's usable by anything that wants to
map trees to trees and have the entries disappear when the key gets
otherwise garbage collected.
Bootstrapped and regtested on i686-pc-linux-gnu.
Okay for mainline?
2005-05-30 Daniel Berlin <dberlin@dberlin.org>
* c-objc-common.c (c_tree_printer): Check flag before hashtable.
Use GET_DECL_DEBUG_EXPR and SET_DECL_DEBUG_EXPR.
* dwarf2out.c (dwarf2out_var_location): Ditto.
* toplev.c (default_tree_printer): Ditto.
* tree-outof-ssa.c (create_temp): Ditto.
* tree-sra.c (instantiate_element): Ditto.
* var-tracking.c (track_expr_p): Ditto.
* tree.c (struct tree_map): New structure.
(debug_expr_for_decl): New.
(tree_map_eq): New function.
(tree_map_hash): Ditto.
(tree_map_marked_p): Ditto.
(print_debug_expr_statistics): Ditto.
(decl_debug_expr_lookup): Ditto.
(decl_debug_expr_insert): Ditto.
(dump_tree_statistics): Dump debug_expr hashtable stats.
* tree.h (DECL_DEBUG_EXPR): Remove.
(GET_DECL_DEBUG_EXPR): Add.
(SET_DECL_DEBUG_EXPR): Ditto.
Index: c-objc-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-objc-common.c,v
retrieving revision 1.65
diff -u -p -r1.65 c-objc-common.c
--- c-objc-common.c 25 Apr 2005 19:03:20 -0000 1.65
+++ c-objc-common.c 31 May 2005 00:23:03 -0000
@@ -171,9 +171,9 @@ c_tree_printer (pretty_printer *pp, text
switch (*text->format_spec)
{
case 'D':
- if (DECL_DEBUG_EXPR (t) && DECL_DEBUG_EXPR_IS_FROM (t))
+ if (DECL_DEBUG_EXPR_IS_FROM (t) && GET_DECL_DEBUG_EXPR (t))
{
- t = DECL_DEBUG_EXPR (t);
+ t = GET_DECL_DEBUG_EXPR (t);
if (!DECL_P (t))
{
pp_c_expression (cpp, t);
Index: dwarf2out.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/dwarf2out.c,v
retrieving revision 1.595
diff -u -p -r1.595 dwarf2out.c
--- dwarf2out.c 16 May 2005 21:36:55 -0000 1.595
+++ dwarf2out.c 31 May 2005 00:23:08 -0000
@@ -13283,9 +13283,9 @@ dwarf2out_var_location (rtx loc_note)
last_insn = loc_note;
last_label = newloc->label;
decl = NOTE_VAR_LOCATION_DECL (loc_note);
- if (DECL_DEBUG_EXPR (decl) && DECL_DEBUG_EXPR_IS_FROM (decl)
- && DECL_P (DECL_DEBUG_EXPR (decl)))
- decl = DECL_DEBUG_EXPR (decl);
+ if (DECL_DEBUG_EXPR_IS_FROM (decl) && GET_DECL_DEBUG_EXPR (decl)
+ && DECL_P (GET_DECL_DEBUG_EXPR (decl)))
+ decl = GET_DECL_DEBUG_EXPR (decl);
add_var_loc_to_decl (decl, newloc);
}
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.955
diff -u -p -r1.955 toplev.c
--- toplev.c 25 May 2005 03:58:58 -0000 1.955
+++ toplev.c 31 May 2005 00:23:08 -0000
@@ -1570,8 +1570,8 @@ default_tree_printer (pretty_printer * p
{
case 'D':
t = va_arg (*text->args_ptr, tree);
- if (DECL_DEBUG_EXPR (t) && DECL_DEBUG_EXPR_IS_FROM (t))
- t = DECL_DEBUG_EXPR (t);
+ if (DECL_DEBUG_EXPR_IS_FROM (t) && GET_DECL_DEBUG_EXPR (t))
+ t = GET_DECL_DEBUG_EXPR (t);
break;
case 'F':
Index: tree-outof-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-outof-ssa.c,v
retrieving revision 2.60
diff -u -p -r2.60 tree-outof-ssa.c
--- tree-outof-ssa.c 30 May 2005 02:12:42 -0000 2.60
+++ tree-outof-ssa.c 31 May 2005 00:23:09 -0000
@@ -158,14 +158,14 @@ create_temp (tree t)
name = "temp";
tmp = create_tmp_var (type, name);
- if (DECL_DEBUG_EXPR (t) && DECL_DEBUG_EXPR_IS_FROM (t))
+ if (DECL_DEBUG_EXPR_IS_FROM (t) && GET_DECL_DEBUG_EXPR (t))
{
- DECL_DEBUG_EXPR (tmp) = DECL_DEBUG_EXPR (t);
+ SET_DECL_DEBUG_EXPR (tmp, GET_DECL_DEBUG_EXPR (t));
DECL_DEBUG_EXPR_IS_FROM (tmp) = 1;
}
else if (!DECL_IGNORED_P (t))
{
- DECL_DEBUG_EXPR (tmp) = t;
+ SET_DECL_DEBUG_EXPR (tmp, t);
DECL_DEBUG_EXPR_IS_FROM (tmp) = 1;
}
DECL_ARTIFICIAL (tmp) = DECL_ARTIFICIAL (t);
Index: tree-sra.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-sra.c,v
retrieving revision 2.59
diff -u -p -r2.59 tree-sra.c
--- tree-sra.c 3 May 2005 12:19:41 -0000 2.59
+++ tree-sra.c 31 May 2005 00:23:09 -0000
@@ -1126,7 +1126,7 @@ instantiate_element (struct sra_elt *elt
DECL_NAME (var) = get_identifier (pretty_name);
obstack_free (&sra_obstack, pretty_name);
- DECL_DEBUG_EXPR (var) = generate_element_ref (elt);
+ SET_DECL_DEBUG_EXPR (var, generate_element_ref (elt));
DECL_DEBUG_EXPR_IS_FROM (var) = 1;
DECL_IGNORED_P (var) = 0;
Index: tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.c,v
retrieving revision 1.482
diff -u -p -r1.482 tree.c
--- tree.c 26 May 2005 18:14:51 -0000 1.482
+++ tree.c 31 May 2005 00:23:11 -0000
@@ -131,19 +131,36 @@ static GTY (()) tree int_cst_node;
static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
htab_t int_cst_hash_table;
+/* General tree->tree mapping structure for use in hash tables. */
+
+struct tree_map GTY(())
+{
+ hashval_t hash;
+ tree from;
+ tree to;
+};
+
+static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
+ htab_t debug_expr_for_decl;
+
static void set_type_quals (tree, int);
static int type_hash_eq (const void *, const void *);
static hashval_t type_hash_hash (const void *);
+static int tree_map_eq (const void *, const void *);
+static hashval_t tree_map_hash (const void *);
static hashval_t int_cst_hash_hash (const void *);
static int int_cst_hash_eq (const void *, const void *);
static void print_type_hash_statistics (void);
+static void print_debug_expr_statistics (void);
static tree make_vector_type (tree, int, enum machine_mode);
static int type_hash_marked_p (const void *);
+static int tree_map_marked_p (const void *);
static unsigned int type_hash_list (tree, hashval_t);
static unsigned int attribute_hash_list (tree, hashval_t);
tree global_trees[TI_MAX];
tree integer_types[itk_none];
+
/* Init tree.c. */
@@ -153,9 +170,15 @@ init_ttree (void)
/* Initialize the hash table of types. */
type_hash_table = htab_create_ggc (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
type_hash_eq, 0);
+
+ debug_expr_for_decl = htab_create_ggc (512, tree_map_hash,
+ tree_map_eq, 0);
+
int_cst_hash_table = htab_create_ggc (1024, int_cst_hash_hash,
int_cst_hash_eq, NULL);
+
int_cst_node = make_node (INTEGER_CST);
+
}
@@ -3430,6 +3453,76 @@ build_variant_type_copy (tree type)
return t;
}
+/* Return true if the from tree in both tree maps are equal. */
+
+static int
+tree_map_eq (const void *va, const void *vb)
+{
+ const struct tree_map *a = va, *b = vb;
+ return (a->from == b->from);
+}
+
+/* Hash a from tree in a tree_map. */
+
+static hashval_t
+tree_map_hash (const void *item)
+{
+ return (((const struct tree_map *) item)->hash);
+}
+
+/* Return true if this tree map structure is marked for garbage collection
+ purposes. We simply return true if the from tree is marked, so that this
+ structure goes away when the from tree goes away. */
+
+static int
+tree_map_marked_p (const void *p)
+{
+ tree from = ((struct tree_map *) p)->from;
+
+ return ggc_marked_p (from);
+}
+
+/* Print out the statistics for the DECL_DEBUG_EXPR hash table. */
+
+static void
+print_debug_expr_statistics (void)
+{
+ fprintf (stderr, "DECL_DEBUG_EXPR hash: size %ld, %ld elements, %f collisions\n",
+ (long) htab_size (debug_expr_for_decl),
+ (long) htab_elements (debug_expr_for_decl),
+ htab_collisions (debug_expr_for_decl));
+}
+
+/* Lookup a debug expression for FROM, and return it if we find one. */
+
+tree
+decl_debug_expr_lookup (tree from)
+{
+ struct tree_map *h, in;
+ in.from = from;
+
+ h = htab_find_with_hash (debug_expr_for_decl, &in, htab_hash_pointer (from));
+ if (h)
+ return h->to;
+ return NULL_TREE;
+}
+
+/* Insert a mapping FROM->TO in the debug expression hashtable. */
+
+void
+decl_debug_expr_insert (tree from, tree to)
+{
+ struct tree_map *h;
+ void **loc;
+
+ h = ggc_alloc (sizeof (struct tree_map));
+ h->hash = htab_hash_pointer (from);
+ h->from = from;
+ h->to = to;
+ loc = htab_find_slot_with_hash (debug_expr_for_decl, h, h->hash, INSERT);
+ *(struct tree_map **) loc = h;
+}
+
/* Hashing of types so that we don't make duplicates.
The entry point is `type_hash_canon'. */
@@ -5261,6 +5354,7 @@ dump_tree_statistics (void)
fprintf (stderr, "(No per-node statistics)\n");
#endif
print_type_hash_statistics ();
+ print_debug_expr_statistics ();
lang_hooks.print_statistics ();
}
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.730
diff -u -p -r1.730 tree.h
--- tree.h 27 May 2005 22:06:46 -0000 1.730
+++ tree.h 31 May 2005 00:23:12 -0000
@@ -2053,10 +2053,18 @@ struct tree_binfo GTY (())
writing debugging information about vfield and vbase decls for C++. */
#define DECL_FCONTEXT(NODE) (FIELD_DECL_CHECK (NODE)->decl.vindex)
+extern tree decl_debug_expr_lookup (tree);
+extern void decl_debug_expr_insert (tree, tree);
+
/* For VAR_DECL, this is set to either an expression that it was split
from (if DECL_DEBUG_EXPR_IS_FROM is true), otherwise a tree_list of
subexpressions that it was split into. */
-#define DECL_DEBUG_EXPR(NODE) (DECL_CHECK (NODE)->decl.vindex)
+#define GET_DECL_DEBUG_EXPR(NODE) \
+ (decl_debug_expr_lookup (VAR_DECL_CHECK (NODE)))
+
+#define SET_DECL_DEBUG_EXPR(NODE, VAL) \
+ (decl_debug_expr_insert (VAR_DECL_CHECK (NODE), VAL))
+
#define DECL_DEBUG_EXPR_IS_FROM(NODE) \
(DECL_CHECK (NODE)->decl.debug_expr_is_from)
Index: var-tracking.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/var-tracking.c,v
retrieving revision 2.27
diff -u -p -r2.27 var-tracking.c
--- var-tracking.c 10 Mar 2005 15:36:39 -0000 2.27
+++ var-tracking.c 31 May 2005 00:23:12 -0000
@@ -1441,10 +1441,9 @@ track_expr_p (tree expr)
don't need to track this expression if the ultimate declaration is
ignored. */
realdecl = expr;
- if (DECL_DEBUG_EXPR (realdecl)
- && DECL_DEBUG_EXPR_IS_FROM (realdecl))
+ if (DECL_DEBUG_EXPR_IS_FROM (realdecl) && GET_DECL_DEBUG_EXPR (realdecl))
{
- realdecl = DECL_DEBUG_EXPR (realdecl);
+ realdecl = GET_DECL_DEBUG_EXPR (realdecl);
/* ??? We don't yet know how to emit DW_OP_piece for variable
that has been SRA'ed. */
if (!DECL_P (realdecl))