This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH - remove 6 pointer fields from C's lang_identifier
- From: Per Bothner <per at bothner dot com>
- To: Gcc Patch List <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 06 Jan 2003 13:20:21 -0800
- Subject: PATCH - remove 6 pointer fields from C's lang_identifier
This patch removes 6 pointer fields from C's lang_identifier,
saving (ideally) 24 bytes per IDENTIFIER_NODE (on 32-bit systems).
These 6 fields were used for various properties (such as
IDENTIFIER_GLOBAL_VALUE), but most of the time at most one of
these properties is non-null. In that case, we store the
property in the unused 'chain' field, and specify which property
is stored in the 'value_kind' bit-field of struct cpp_hashnode.
If more than one property is non-null, we allocate an extension
TREE_VEC.
This patch is for C. I have a similar patch for C++ which depends
on this patch. (With the latter patch I ended up allocating 0
extension words for a large C++ pre-processed file.)
This is a follow-on this patch (which I got zero feedback on):
http://gcc.gnu.org/ml/gcc-patches/2002-12/msg00447.html
Now that it actually makes a difference, I hope I'll get some
response!
--
--Per Bothner
per@bothner.com http://www.bothner.com/per/
2003-01-06 Per Bothner <pbothner@apple.com>
* cpplib.h (struct cpp_hashnode): New bitfield value_kind.
* c-common.h (set_identifier_value): New declaration,
(IDENTIFIER_FIELD_KIND, IDENTIFIER_FIELD_DIRECT, IDENTIFIER_FIELD,
SET_IDENTIFIER_FIELD, IDENTIFIER_FIELD_INDIRECT): New macros.
* c-common.c (set_identifier_value): New function.
* c-tree.h (struct lang_identifier): Remove global_value, local_value,
label_value, implicit_decl, error_locus, limbo_value fields.
(IDENTIFIER_GLOBAL_INDEX, IDENTIFIER_LOCAL_INDEX,
IDENTIFIER_LABEL_INDEX, IDENTIFIER_IMPLICIT_INDEX,
IDENTIFIER_ERROR_INDEX, IDENTIFIER_LIMBO_INDEX,
IDENTIFIER_EXTENSION_INDEX): New macros.
(IDENTIFIER_GLOBAL_VALUE, IDENTIFIER_LOCAL_VALUE,
IDENTIFIER_LABEL_VALUE, IDENTIFIER_LIMBO_VALUE,
IDENTIFIER_IMPLICIT_DECL, IDENTIFIER_ERROR_LOCUS):
Redefine to use IDENTIFIER_FIELD.
(SET_IDENTIFIER_GLOBAL_VALUE, (SET_IDENTIFIER_LOCAL_VALUE,
(SET_IDENTIFIER_LABEL_VALUE, (SET_IDENTIFIER_LIMBO_VALUE,
(SET_IDENTIFIER_IMPLICIT_DECL, (SET_IDENTIFIER_ERROR_LOCUS):
New macros - use SET_IDENTIFIER_FIELD.
* c-decl (clear_limbo_values, poplevel, pop_label_level, pushdecl,
implicitly_declare, lookup_label, shadow_label, define_label,
store_parm_decls, c_pop_function_context): Use new macros.
* c-typeck.c (build_external_ref): Likewise.
* c-decl (pushdecl): Clear limbo_value *before* setting global_value,
so we have fewer non-zero properties at once.
Index: cpplib.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cpplib.h,v
retrieving revision 1.239
diff -u -p -r1.239 cpplib.h
--- cpplib.h 1 Jan 2003 12:26:48 -0000 1.239
+++ cpplib.h 6 Jan 2003 21:10:29 -0000
@@ -480,7 +480,8 @@ struct cpp_hashnode
then index into directive table.
Otherwise, a NODE_OPERATOR. */
unsigned char rid_code; /* Rid code - for front ends. */
- ENUM_BITFIELD(node_type) type : 8; /* CPP node type. */
+ unsigned int value_kind : 4; /* For front end. */
+ ENUM_BITFIELD(node_type) type : 4; /* CPP node type. */
unsigned char flags; /* CPP flags. */
union _cpp_hashnode_value
Index: c-common.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.h,v
retrieving revision 1.165
diff -u -p -r1.165 c-common.h
--- c-common.h 31 Dec 2002 17:34:17 -0000 1.165
+++ c-common.h 6 Jan 2003 21:10:30 -0000
@@ -315,6 +315,27 @@ extern tree gettags PARAMS ((void));
noreturn attribute. */
extern int (*lang_missing_noreturn_ok_p) PARAMS ((tree));
+/* Macros used to associate properties (such as IDENTIFIER_GLOBAL_VALUE)
+ with IDENTIFIER_NODEs. We assume that for most identifiers there will
+ zero or one property that is non-null. In that case, we store the
+ property directly in IDENTIFIER_FIELD_DIRECT, and IDENTIFIER_FIELD_KIND
+ is the number of the property. If we need more than one non-null property,
+ then we allocate a TREE_VEC store store the properties, and use
+ IDENTIFIER_FIELD_INDIRECT to access the property value. */
+#define IDENTIFIER_FIELD_KIND(NODE) \
+ (((struct c_common_identifier *) (NODE))->node.value_kind)
+#define IDENTIFIER_FIELD_DIRECT(NODE) ((NODE)->common.chain)
+#define IDENTIFIER_FIELD_INDIRECT(NODE, INDEX) \
+ TREE_VEC_ELT ((NODE)->common.chain, INDEX)
+#define IDENTIFIER_FIELD(NODE, INDEX) \
+ (IDENTIFIER_FIELD_KIND (NODE) == INDEX\
+ ? IDENTIFIER_FIELD_DIRECT (NODE) \
+ : IDENTIFIER_FIELD_KIND (NODE) == IDENTIFIER_EXTENSION_INDEX \
+ ? IDENTIFIER_FIELD_INDIRECT (NODE, INDEX) \
+ : NULL_TREE)
+#define SET_IDENTIFIER_FIELD(NODE, INDEX, VALUE) \
+ set_identifier_value (NODE, INDEX, IDENTIFIER_EXTENSION_INDEX, VALUE)
+extern void set_identifier_value PARAMS ((tree, int,int, tree));
extern int yyparse PARAMS ((void));
extern void free_parser_stacks PARAMS ((void));
Index: c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.395
diff -u -p -r1.395 c-common.c
--- c-common.c 3 Jan 2003 19:29:47 -0000 1.395
+++ c-common.c 6 Jan 2003 21:10:34 -0000
@@ -6632,4 +6632,40 @@ check_function_arguments_recurse (callba
(*callback) (ctx, param, param_num);
}
+/* Helper function used to implement the SET_IDENTIFIER_FIELD macro.
+ Set the property number VALUE_INDEX (out of max NUM_VALUES) in
+ the identifier ID to VALUE.
+ If there is only a single (non-null) property, it is stored directly
+ in IDENTIFIER_FIELD_DIRECT; otherwise, the latter points to a
+ TREE_VEC, and we store it in the element at index VALUE_INDEX.
+ The assumption is that we will only rarely need to do this. */
+
+void
+set_identifier_value (id, value_index, num_values, value)
+ tree id;
+ int value_index;
+ int num_values;
+ tree value;
+{
+ int cur_kind = IDENTIFIER_FIELD_KIND (id);
+ if (cur_kind == value_index)
+ IDENTIFIER_FIELD_DIRECT (id) = value;
+ else if (cur_kind == num_values)
+ IDENTIFIER_FIELD_INDIRECT (id, value_index) = value;
+ else if (IDENTIFIER_FIELD_DIRECT (id) == NULL_TREE)
+ {
+ IDENTIFIER_FIELD_KIND (id) = value_index;
+ IDENTIFIER_FIELD_DIRECT (id) = value;
+ }
+ else if (value != NULL_TREE)
+ {
+ tree tmp = IDENTIFIER_FIELD_DIRECT (id);
+ tree vec = make_tree_vec (num_values);
+ TREE_VEC_ELT (vec, cur_kind) = IDENTIFIER_FIELD_DIRECT (id);
+ TREE_VEC_ELT (vec, value_index) = value;
+ IDENTIFIER_FIELD_DIRECT (id) = vec;
+ IDENTIFIER_FIELD_KIND (id) = num_values;
+ }
+}
+
#include "gt-c-common.h"
Index: c-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-tree.h,v
retrieving revision 1.109
diff -u -p -r1.109 c-tree.h
--- c-tree.h 16 Sep 2002 18:33:18 -0000 1.109
+++ c-tree.h 6 Jan 2003 21:10:34 -0000
@@ -37,14 +37,16 @@ Software Foundation, 59 Temple Place - S
struct lang_identifier GTY(())
{
struct c_common_identifier common_id;
- tree global_value;
- tree local_value;
- tree label_value;
- tree implicit_decl;
- tree error_locus;
- tree limbo_value;
};
+#define IDENTIFIER_GLOBAL_INDEX 0
+#define IDENTIFIER_LOCAL_INDEX 1
+#define IDENTIFIER_LABEL_INDEX 2
+#define IDENTIFIER_IMPLICIT_INDEX 3
+#define IDENTIFIER_ERROR_INDEX 4
+#define IDENTIFIER_LIMBO_INDEX 5
+#define IDENTIFIER_EXTENSION_INDEX 6
+
/* The resulting tree type. */
union lang_tree_node
@@ -74,28 +76,40 @@ struct lang_decl GTY(())
/* This represents the value which the identifier has in the
file-scope namespace. */
#define IDENTIFIER_GLOBAL_VALUE(NODE) \
- (((struct lang_identifier *) (NODE))->global_value)
+ IDENTIFIER_FIELD (NODE, IDENTIFIER_GLOBAL_INDEX)
+#define SET_IDENTIFIER_GLOBAL_VALUE(NODE, VALUE) \
+ SET_IDENTIFIER_FIELD (NODE, IDENTIFIER_GLOBAL_INDEX, VALUE)
/* This represents the value which the identifier has in the current
scope. */
-#define IDENTIFIER_LOCAL_VALUE(NODE) \
- (((struct lang_identifier *) (NODE))->local_value)
+#define IDENTIFIER_LOCAL_VALUE(NODE) \
+ IDENTIFIER_FIELD (NODE, IDENTIFIER_LOCAL_INDEX)
+#define SET_IDENTIFIER_LOCAL_VALUE(NODE, VALUE) \
+ SET_IDENTIFIER_FIELD (NODE, IDENTIFIER_LOCAL_INDEX, VALUE)
/* This represents the value which the identifier has as a label in
the current label scope. */
#define IDENTIFIER_LABEL_VALUE(NODE) \
- (((struct lang_identifier *) (NODE))->label_value)
+ IDENTIFIER_FIELD (NODE, IDENTIFIER_LABEL_INDEX)
+#define SET_IDENTIFIER_LABEL_VALUE(NODE, VALUE) \
+ SET_IDENTIFIER_FIELD (NODE, IDENTIFIER_LABEL_INDEX, VALUE)
/* This records the extern decl of this identifier, if it has had one
at any point in this compilation. */
#define IDENTIFIER_LIMBO_VALUE(NODE) \
- (((struct lang_identifier *) (NODE))->limbo_value)
+ IDENTIFIER_FIELD (NODE, IDENTIFIER_LIMBO_INDEX)
+#define SET_IDENTIFIER_LIMBO_VALUE(NODE, VALUE) \
+ SET_IDENTIFIER_FIELD (NODE, IDENTIFIER_LIMBO_INDEX, VALUE)
/* This records the implicit function decl of this identifier, if it
has had one at any point in this compilation. */
#define IDENTIFIER_IMPLICIT_DECL(NODE) \
- (((struct lang_identifier *) (NODE))->implicit_decl)
+ IDENTIFIER_FIELD (NODE, IDENTIFIER_IMPLICIT_INDEX)
+#define SET_IDENTIFIER_IMPLICIT_DECL(NODE, VALUE) \
+ SET_IDENTIFIER_FIELD (NODE, IDENTIFIER_IMPLICIT_INDEX, VALUE)
/* This is the last function in which we printed an "undefined variable"
message for this identifier. Value is a FUNCTION_DECL or null. */
#define IDENTIFIER_ERROR_LOCUS(NODE) \
- (((struct lang_identifier *) (NODE))->error_locus)
-
+ IDENTIFIER_FIELD (NODE, IDENTIFIER_ERROR_INDEX)
+#define SET_IDENTIFIER_ERROR_LOCUS(NODE, VALUE) \
+ SET_IDENTIFIER_FIELD (NODE, IDENTIFIER_ERROR_INDEX, VALUE)
+
/* In identifiers, C uses the following fields in a special way:
TREE_PUBLIC to record that there was a previous local extern decl.
TREE_USED to record that such a decl was used.
Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.358
diff -u -p -r1.358 c-decl.c
--- c-decl.c 3 Jan 2003 19:29:47 -0000 1.358
+++ c-decl.c 6 Jan 2003 21:10:38 -0000
@@ -467,7 +467,7 @@ clear_limbo_values (block)
for (tem = BLOCK_VARS (block); tem; tem = TREE_CHAIN (tem))
if (DECL_NAME (tem) != 0)
- IDENTIFIER_LIMBO_VALUE (DECL_NAME (tem)) = 0;
+ SET_IDENTIFIER_LIMBO_VALUE (DECL_NAME (tem), NULL_TREE);
for (tem = BLOCK_SUBBLOCKS (block); tem; tem = TREE_CHAIN (tem))
clear_limbo_values (tem);
@@ -606,7 +606,7 @@ poplevel (keep, reverse, functionbody)
if (TREE_ADDRESSABLE (link))
TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
}
- IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
+ SET_IDENTIFIER_LOCAL_VALUE (DECL_NAME (link), NULL_TREE);
}
}
@@ -614,7 +614,7 @@ poplevel (keep, reverse, functionbody)
that were shadowed by this level. */
for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
- IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
+ SET_IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
/* If the level being exited is the top level of a function,
check over all the labels, and clear out the current
@@ -648,7 +648,7 @@ poplevel (keep, reverse, functionbody)
}
else if (warn_unused_label && !TREE_USED (label))
warning_with_decl (label, "label `%s' defined but not used");
- IDENTIFIER_LABEL_VALUE (DECL_NAME (label)) = 0;
+ SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), NULL_TREE);
/* Put the labels into the "variables" of the
top-level block, so debugger can see them. */
@@ -774,7 +774,7 @@ pop_label_level ()
else if (warn_unused_label && !TREE_USED (TREE_VALUE (link)))
warning_with_decl (TREE_VALUE (link),
"label `%s' defined but not used");
- IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link))) = 0;
+ SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)), NULL_TREE);
/* Delete this element from the list. */
link = TREE_CHAIN (link);
@@ -793,8 +793,8 @@ pop_label_level ()
/* Bring back all the labels that were shadowed. */
for (link = shadowed_labels; link; link = TREE_CHAIN (link))
if (DECL_NAME (TREE_VALUE (link)) != 0)
- IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
- = TREE_VALUE (link);
+ SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)),
+ TREE_VALUE (link));
named_labels = chainon (named_labels, level->names);
shadowed_labels = level->shadowed;
@@ -1838,10 +1838,10 @@ pushdecl (x)
if (IDENTIFIER_GLOBAL_VALUE (name) == 0 && TREE_PUBLIC (x))
TREE_PUBLIC (name) = 1;
- IDENTIFIER_GLOBAL_VALUE (name) = x;
-
/* We no longer care about any previous block level declarations. */
- IDENTIFIER_LIMBO_VALUE (name) = 0;
+ SET_IDENTIFIER_LIMBO_VALUE (name, NULL_TREE);
+
+ SET_IDENTIFIER_GLOBAL_VALUE (name, x);
/* Don't forget if the function was used via an implicit decl. */
if (IDENTIFIER_IMPLICIT_DECL (name)
@@ -1894,7 +1894,7 @@ pushdecl (x)
tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
tree oldglobal = IDENTIFIER_GLOBAL_VALUE (name);
- IDENTIFIER_LOCAL_VALUE (name) = x;
+ SET_IDENTIFIER_LOCAL_VALUE (name, x);
/* If this is an extern function declaration, see if we
have a global definition or declaration for the function. */
@@ -1972,7 +1972,7 @@ pushdecl (x)
will have been set when the inline function was parsed.
It also helps give slightly better warnings. */
if (IDENTIFIER_LIMBO_VALUE (name) == 0)
- IDENTIFIER_LIMBO_VALUE (name) = x;
+ SET_IDENTIFIER_LIMBO_VALUE (name, x);
}
warn_if_shadowing (x, oldlocal);
@@ -2057,7 +2057,7 @@ implicitly_declare (functionid)
TREE_PUBLIC (decl) = 1;
/* Record that we have an implicit decl and this is it. */
- IDENTIFIER_IMPLICIT_DECL (functionid) = decl;
+ SET_IDENTIFIER_IMPLICIT_DECL (functionid, decl);
/* ANSI standard says implicit declarations are in the innermost block.
So we record the decl in the standard fashion. */
@@ -2200,7 +2200,7 @@ lookup_label (id)
DECL_SOURCE_LINE (decl) = lineno;
DECL_SOURCE_FILE (decl) = input_filename;
- IDENTIFIER_LABEL_VALUE (id) = decl;
+ SET_IDENTIFIER_LABEL_VALUE (id, decl);
named_labels = tree_cons (NULL_TREE, decl, named_labels);
@@ -2239,7 +2239,8 @@ shadow_label (name)
}
shadowed_labels = tree_cons (NULL_TREE, decl, shadowed_labels);
- IDENTIFIER_LABEL_VALUE (name) = decl = 0;
+ decl = NULL_TREE;
+ SET_IDENTIFIER_LABEL_VALUE (name, NULL_TREE);
}
return lookup_label (name);
@@ -2261,7 +2262,7 @@ define_label (filename, line, name)
if (decl != 0 && DECL_CONTEXT (decl) != current_function_decl)
{
shadowed_labels = tree_cons (NULL_TREE, decl, shadowed_labels);
- IDENTIFIER_LABEL_VALUE (name) = 0;
+ SET_IDENTIFIER_LABEL_VALUE (name, NULL_TREE);
decl = lookup_label (name);
}
@@ -5960,10 +5961,11 @@ store_parm_decls ()
for (decl = current_binding_level->names;
decl; decl = TREE_CHAIN (decl))
if (DECL_NAME (decl))
- IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl)) = 0;
+ SET_IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl), NULL_TREE);
for (link = current_binding_level->shadowed;
link; link = TREE_CHAIN (link))
- IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
+ SET_IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link),
+ TREE_VALUE (link));
current_binding_level->names = 0;
current_binding_level->shadowed = 0;
}
@@ -6725,8 +6727,8 @@ c_pop_function_context (f)
/* Bring back all the labels that were shadowed. */
for (link = shadowed_labels; link; link = TREE_CHAIN (link))
if (DECL_NAME (TREE_VALUE (link)) != 0)
- IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
- = TREE_VALUE (link);
+ SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)),
+ TREE_VALUE (link));
if (DECL_SAVED_INSNS (current_function_decl) == 0
&& DECL_SAVED_TREE (current_function_decl) == NULL_TREE)
Index: c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.214
diff -u -p -r1.214 c-typeck.c
--- c-typeck.c 16 Dec 2002 18:19:05 -0000 1.214
+++ c-typeck.c 6 Jan 2003 21:10:42 -0000
@@ -1424,8 +1424,8 @@ build_external_ref (id, fun)
undeclared_variable_notice = 1;
}
}
- IDENTIFIER_GLOBAL_VALUE (id) = error_mark_node;
- IDENTIFIER_ERROR_LOCUS (id) = current_function_decl;
+ SET_IDENTIFIER_GLOBAL_VALUE (id, error_mark_node);
+ SET_IDENTIFIER_ERROR_LOCUS (id, current_function_decl);
}
return error_mark_node;
}
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.371
diff -u -p -r1.371 tree.h
--- tree.h 3 Jan 2003 16:41:23 -0000 1.371
+++ tree.h 6 Jan 2003 21:10:45 -0000
@@ -373,7 +373,8 @@ extern void tree_vec_elt_check_failed PA
of the scope.
Statement nodes for successive statements used to be chained together.
Often lists of things are represented by TREE_LIST nodes that
- are chained together. */
+ are chained together.
+ Don't use TREE_CHAIN for IDENTIFIER_NODEs. */
#define TREE_CHAIN(NODE) ((NODE)->common.chain)