Minor performance tweaks (memory allocation)

Zack Weinberg zack@bitmover.com
Thu Nov 18 00:27:00 GMT 1999


This patch avoids clearing memory that will be completely initialized
in several places.  It's good for approximately 2% on my favorite test
case.

More improvements are possible in this area, but they would take major
code restructuring:

- If the RTL and tree flags were all in one variable instead of
separate bitfields, it would be possible to clear them without
touching the code, mode, etc.  which are usually set immediately
afterward.  (This may not be much of a win due to cache effects.)

- The tree.c allocation functions could be changed to clear only the
flags and possibly the chain, relying on the caller to clear
everything else.  Unfortunately, those functions are used all over the
place.

I have not bootstrapped this yet - it will run overnight.  However, I
suspect that if it works for one test case it will work for
everything.

zw

1999-11-18 00:17 -0800  Zack Weinberg  <zack@bitmover.com>

	* ggc-none.c, ggc-page.c, ggc-simple.c (ggc_alloc_obj): Kill
	ZERO argument.  Never zero allocated memory.
	* ggc.h: Change prototype to match.
	(ggc_alloc_rtx): ggc_alloc_obj takes only one argument.  Clear
	the common fields here.
	(ggc_alloc_rtvec, ggc_alloc_tree, ggc_alloc): ggc_alloc_obj
	takes only one argument.
	* ggc-common.c (ggc_alloc_string): ggc_alloc_obj takes only
	one argument.

	* emit-rtl.c (init_emit_once): Initialize CONST_DOUBLE_CHAIN
	of floating-point const_tiny_rtx entries.
	* gengenrtl.c (gendef): Clear '0' format slots.
	* rtl.c (rtvec_alloc): Always clear vector here.
	(rtx_alloc): Do not manipulate obstack guts directly.
	(copy_rtx): Allocate copy by hand, don't call rtx_alloc.
	* tree.c (make_node, make_tree_vec, tree_cons, build1): Always
	clear out the new node by hand.  Avoid clearing something
	we're about to initialize.


Index: emit-rtl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/emit-rtl.c,v
retrieving revision 1.97
diff -u -p -r1.97 emit-rtl.c
--- emit-rtl.c	1999/11/04 07:23:58	1.97
+++ emit-rtl.c	1999/11/18 08:17:47
@@ -3863,6 +3863,7 @@ init_emit_once (line_numbers)
 
 	  bcopy ((char *) &u, (char *) &CONST_DOUBLE_LOW (tem), sizeof u);
 	  CONST_DOUBLE_MEM (tem) = cc0_rtx;
+	  CONST_DOUBLE_CHAIN (tem) = NULL_RTX;
 	  PUT_MODE (tem, mode);
 
 	  const_tiny_rtx[i][(int) mode] = tem;
Index: gengenrtl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/gengenrtl.c,v
retrieving revision 1.28
diff -u -p -r1.28 gengenrtl.c
--- gengenrtl.c	1999/09/15 14:13:49	1.28
+++ gengenrtl.c	1999/11/18 08:17:47
@@ -315,6 +315,8 @@ gendef (format)
   for (p = format, i = j = 0; *p ; ++p, ++i)
     if (*p != '0')
       printf ("  %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++);
+    else
+      printf ("  X0EXP (rt, %d) = NULL_RTX;\n", i);
 
   printf ("\n  return rt;\n}\n\n");
 }
Index: ggc-common.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/ggc-common.c,v
retrieving revision 1.16
diff -u -p -r1.16 ggc-common.c
--- ggc-common.c	1999/11/16 04:55:19	1.16
+++ ggc-common.c	1999/11/18 08:17:47
@@ -512,7 +512,7 @@ ggc_alloc_string (contents, length)
       length = strlen (contents);
     }
 
-  string = (char *) ggc_alloc_obj (length + 1, 0);
+  string = (char *) ggc_alloc_obj (length + 1);
   if (contents != NULL)
     memcpy (string, contents, length);
   string[length] = 0;
Index: ggc-none.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/ggc-none.c,v
retrieving revision 1.7
diff -u -p -r1.7 ggc-none.c
--- ggc-none.c	1999/10/13 17:09:18	1.7
+++ ggc-none.c	1999/11/18 08:17:47
@@ -36,12 +36,9 @@
 int ggc_p = 0;
 
 void *
-ggc_alloc_obj (size, zero)
+ggc_alloc_obj (size)
      size_t size;
-     int zero;
 {
   void *p = xmalloc (size);
-  if (zero)
-    memset (p, 0, size);
   return p;
 }
Index: ggc-page.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/ggc-page.c,v
retrieving revision 1.16
diff -u -p -r1.16 ggc-page.c
--- ggc-page.c	1999/11/01 06:57:01	1.16
+++ ggc-page.c	1999/11/18 08:17:48
@@ -608,13 +608,12 @@ static unsigned char const size_lookup[2
   8
 };
 
-/* Allocate a chunk of memory of SIZE bytes.  If ZERO is non-zero, the
-   memory is zeroed; otherwise, its contents are undefined.  */
+/* Allocate a chunk of memory of SIZE bytes.  The contents of the
+   block are undefined.  */
 
 void *
-ggc_alloc_obj (size, zero)
+ggc_alloc_obj (size)
      size_t size;
-     int zero;
 {
   unsigned order, word, bit, object_offset;
   struct page_entry *entry;
@@ -704,13 +703,9 @@ ggc_alloc_obj (size, zero)
   result = entry->page + object_offset;
 
 #ifdef GGC_POISON
-  /* `Poison' the entire allocated object before zeroing the requested area,
-     so that bytes beyond the end, if any, will not necessarily be zero.  */
+  /* `Poison' the entire allocated object.  */
   memset (result, 0xaf, 1 << order);
 #endif
-
-  if (zero)
-    memset (result, 0, size);
 
   /* Keep track of how many bytes are being allocated.  This
      information is used in deciding when to collect.  */
Index: ggc-simple.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/ggc-simple.c,v
retrieving revision 1.26
diff -u -p -r1.26 ggc-simple.c
--- ggc-simple.c	1999/10/30 21:36:13	1.26
+++ ggc-simple.c	1999/11/18 08:17:48
@@ -182,12 +182,11 @@ tree_lookup (v)
   return 0;
 }
 
-/* Alloc SIZE bytes of GC'able memory.  If ZERO, clear the memory.  */
+/* Alloc SIZE bytes of GC'able memory.  */
 
 void *
-ggc_alloc_obj (size, zero)
+ggc_alloc (size)
      size_t size;
-     int zero;
 {
   struct ggc_mem *x;
 
@@ -198,11 +197,8 @@ ggc_alloc_obj (size, zero)
   x->context = G.context;
   x->size = size;
 
-  if (zero)
-    memset (&x->u, 0, size);
 #ifdef GGC_POISON
-  else
-    memset (&x->u, 0xaf, size);
+  memset (&x->u, 0xaf, size);
 #endif
 
   tree_insert (x);
Index: ggc.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/ggc.h,v
retrieving revision 1.18
diff -u -p -r1.18 ggc.h
--- ggc.h	1999/11/16 04:55:19	1.18
+++ ggc.h	1999/11/18 08:17:48
@@ -118,20 +118,27 @@ extern void ggc_pop_context PROTO ((void
 /* Allocation.  */
 
 /* The internal primitive.  */
-void *ggc_alloc_obj PROTO ((size_t, int));
+void *ggc_alloc_obj PROTO ((size_t));
 
-#define ggc_alloc_rtx(NSLOTS)						     \
-  ((struct rtx_def *) ggc_alloc_obj (sizeof (struct rtx_def)		     \
-				     + ((NSLOTS) - 1) * sizeof (rtunion), 1))
+/* Allocate an RTX object and clear its code, mode, and flags fields.
+   The slots are left uninitialized.
+   It is a little-known fact that memset returns its first argument.  */
+#define ggc_alloc_rtx(NSLOTS)						      \
+  ((struct rtx_def *) memset (ggc_alloc_obj (sizeof (struct rtx_def) +	      \
+					     ((NSLOTS)-1) * sizeof (rtunion)),\
+					     0, sizeof (struct rtx_def) -     \
+					     sizeof (rtunion)))
 
+/* Allocate an RTVEC object.  */
 #define ggc_alloc_rtvec(NELT)						  \
   ((struct rtvec_def *) ggc_alloc_obj (sizeof (struct rtvec_def)	  \
-				       + ((NELT) - 1) * sizeof (rtx), 1))
+				       + ((NELT) - 1) * sizeof (rtx)))
 
+/* Allocate a tree object.  */
 #define ggc_alloc_tree(LENGTH)				\
-  ((union tree_node *) ggc_alloc_obj ((LENGTH), 1))
+  ((union tree_node *) ggc_alloc_obj (LENGTH))
 
-#define ggc_alloc(SIZE)  ggc_alloc_obj((SIZE), 0)
+#define ggc_alloc(SIZE)  ggc_alloc_obj (SIZE)
 
 char *ggc_alloc_string PROTO ((const char *contents, int length));
 
Index: rtl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/rtl.c,v
retrieving revision 1.55
diff -u -p -r1.55 rtl.c
--- rtl.c	1999/11/10 17:57:20	1.55
+++ rtl.c	1999/11/18 08:17:48
@@ -275,21 +275,18 @@ rtvec_alloc (n)
      int n;
 {
   rtvec rt;
- 
+  int i;
+  
   if (ggc_p)
     rt = ggc_alloc_rtvec (n);
   else
-    {
-      int i;
-
-      rt = (rtvec) obstack_alloc (rtl_obstack,
+    rt = (rtvec) obstack_alloc (rtl_obstack,
 				  sizeof (struct rtvec_def)
-				  + (( n - 1) * sizeof (rtx)));
+				  + ((n - 1) * sizeof (rtx)));
 
-      /* clear out the vector */
-      for (i = 0; i < n; i++)
-	rt->elem[i] = 0;
-    }
+  /* clear out the vector */
+  for (i = 0; i < n; i++)
+    rt->elem[i] = 0;
 
   PUT_NUM_ELEM (rt, n);
   return rt;
@@ -303,31 +300,15 @@ rtx_alloc (code)
   RTX_CODE code;
 {
   rtx rt;
+  int len = GET_RTX_LENGTH (code);
 
   if (ggc_p)
-    rt = ggc_alloc_rtx (GET_RTX_LENGTH (code));
+    rt = ggc_alloc_rtx (len);
   else
     {
-      register struct obstack *ob = rtl_obstack;
-      register int nelts = GET_RTX_LENGTH (code);
-      register int length = sizeof (struct rtx_def)
-	+ (nelts - 1) * sizeof (rtunion);
-
-      /* This function is called more than any other in GCC, so we
-	 manipulate the obstack directly.
-       
-	 Even though rtx objects are word aligned, we may be sharing
-	 an obstack with tree nodes, which may have to be double-word
-	 aligned.  So align our length to the alignment mask in the
-	 obstack.  */
-
-      length = (length + ob->alignment_mask) & ~ ob->alignment_mask;
-
-      if (ob->chunk_limit - ob->next_free < length)
-	_obstack_newchunk (ob, length);
-      rt = (rtx)ob->object_base;
-      ob->next_free += length;
-      ob->object_base = ob->next_free;
+      rt = (rtx) obstack_alloc (rtl_obstack,
+				sizeof (struct rtx_def)
+				+ ((len - 1) * sizeof (rtunion)));
 
       /* We want to clear everything up to the FLD array.  Normally,
 	 this is one int, but we don't want to assume that and it
@@ -362,6 +343,7 @@ copy_rtx (orig)
   register int i, j;
   register RTX_CODE code;
   register const char *format_ptr;
+  size_t len;
 
   code = GET_CODE (orig);
 
@@ -398,7 +380,12 @@ copy_rtx (orig)
       break;
     }
 
-  copy = rtx_alloc (code);
+  len = (sizeof (struct rtx_def)
+	 + (GET_RTX_LENGTH (code) - 1) * sizeof(rtunion));
+  if (ggc_p)
+    copy = ggc_alloc (len);
+  else
+    copy = (rtx) obstack_alloc (rtl_obstack, len);
 
   /* Copy the various flags, and other information.  We assume that
      all fields need copying, and then clear the fields that should
Index: tree.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/tree.c,v
retrieving revision 1.104
diff -u -p -r1.104 tree.c
--- tree.c	1999/11/12 16:52:08	1.104
+++ tree.c	1999/11/18 08:17:54
@@ -1026,10 +1026,8 @@ make_node (code)
   if (ggc_p)
     t = ggc_alloc_tree (length);
   else
-    {
-      t = (tree) obstack_alloc (obstack, length);
-      memset ((PTR) t, 0, length);
-    }
+    t = (tree) obstack_alloc (obstack, length);
+  memset ((PTR) t, 0, length);
 
 #ifdef GATHER_STATISTICS
   tree_node_counts[(int)kind]++;
@@ -1581,10 +1579,8 @@ make_tree_vec (len)
   if (ggc_p)
     t = ggc_alloc_tree (length);
   else
-    {
-      t = (tree) obstack_alloc (obstack, length);
-      bzero ((PTR) t, length);
-    }
+    t = (tree) obstack_alloc (obstack, length);
+  memset ((PTR) t, 0, length);
 
   TREE_SET_CODE (t, TREE_VEC);
   TREE_VEC_LENGTH (t) = len;
@@ -2090,10 +2086,8 @@ tree_cons (purpose, value, chain)
   if (ggc_p)
     node = ggc_alloc_tree (sizeof (struct tree_list));
   else
-    {
-      node = (tree) obstack_alloc (current_obstack, sizeof (struct tree_list));
-      memset (node, 0, sizeof (struct tree_common));
-    }
+    node = (tree) obstack_alloc (current_obstack, sizeof (struct tree_list));
+  memset (node, 0, sizeof (struct tree_common));
 
 #ifdef GATHER_STATISTICS
   tree_node_counts[(int)x_kind]++;
@@ -3108,10 +3102,9 @@ build1 (code, type, node)
   if (ggc_p)
     t = ggc_alloc_tree (length);
   else
-    {
-      t = (tree) obstack_alloc (obstack, length);
-      memset ((PTR) t, 0, length);
-    }
+    t = (tree) obstack_alloc (obstack, length);
+
+  memset ((PTR) t, 0, sizeof (struct tree_common));
 
 #ifdef GATHER_STATISTICS
   tree_node_counts[(int)kind]++;
@@ -3125,6 +3118,7 @@ build1 (code, type, node)
     TREE_PERMANENT (t) = 1;
 
   TREE_OPERAND (t, 0) = node;
+  TREE_OPERAND (t, 1) = NULL_TREE;
   if (node && first_rtl_op (code) != 0)
     {
       if (TREE_SIDE_EFFECTS (node))




More information about the Gcc-patches mailing list