This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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)
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]