This is the mail archive of the gcc@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]

Re: Faster compilation speed


   From: Matt Austern <austern@apple.com>
   Date: Mon, 12 Aug 2002 12:47:30 -0700
   
   And yes, we're aware that many gains are possible only
   if we rewrite the parser or redesign the tree structure.  The
   only reason we haven't started on rewriting the parser is
   that someone else is already doing it.

So work on an attempt at RTL refcounting, the patch below is a place
to start.

Next you have to:

1) walk through the whole compiler and add all the
   proper {GET,PUT}_RTX calls.

2) find a solution for circular RTL

   I would suggest as a first pass (ie. to get some performance
   numbers), special case things like INSN_LISTs and just don't
   refcount for the references to INSNs they generate.  Likewise
   for INSN dependency lists generated by the scheduler et al.

3) bring it at least to the point where you can successfully
   get a successful build of some non-trivial source file.
   Perhaps gcc/reload.i.  Even if it requires some gross hacks
   to get it to pass through, post GC vs. refcounting performance
   numbers.

4) Almost certainly, in trying to refcount things correctly, you will
   spot real bugs in the compiler.  Please keep track of these so they
   can be fixed independant of whether the rtx refcounting is ever
   used or not.

5) If you are still bored at this point, add the machinery to use the
   RTX walking of the current garbage collector to verify the
   reference counts.  This will basically be required in order to
   make and sufficiently correctness check a final implementation.

   It would be enabled by default, so that if any refence counts
   go wrong they will be spotted with impunity.  This is part of the
   sociological aspect of these changes, namely getting people to
   think about proper resource tracking when working with RTL
   objects.  If the compiler explodes when they get it wrong, they
   will learn eventually :-)

Because if someone else doesn't do this, I will end up doing
so :-)

--- ./rtl.h.~1~	Sun Aug 11 19:04:35 2002
+++ ./rtl.h	Sun Aug 11 20:42:02 2002
@@ -130,6 +130,9 @@ struct rtx_def
   /* The kind of value the expression has.  */
   ENUM_BITFIELD(machine_mode) mode : 8;
 
+  /* Reference count.  */
+  unsigned int __count : 24;
+
   /* 1 in a MEM if we should keep the alias set for this mem unchanged
      when we access a component.
      1 in a CALL_INSN if it is a sibling call.
@@ -184,7 +187,7 @@ struct rtx_def
      1 in a REG means this reg refers to the return value
      of the current function.
      1 in a SYMBOL_REF if the symbol is weak.  */
-  unsigned integrated : 1;
+  unsigned int integrated : 1;
   /* 1 in an INSN or a SET if this rtx is related to the call frame,
      either changing how we compute the frame address or saving and
      restoring registers in the prologue and epilogue.
@@ -193,7 +196,7 @@ struct rtx_def
      1 in a REG if the register is a pointer.
      1 in a SYMBOL_REF if it addresses something in the per-function
      constant string pool.  */
-  unsigned frame_related : 1;
+  unsigned int frame_related : 1;
 
   /* The first element of the operands of this rtx.
      The number of operands and their types are controlled
@@ -211,12 +214,25 @@ struct rtx_def
 #define GET_MODE(RTX)	    ((enum machine_mode) (RTX)->mode)
 #define PUT_MODE(RTX, MODE) ((RTX)->mode = (ENUM_BITFIELD(machine_mode)) (MODE))
 
+/* Define macros to get/put references to RTL objects.  */
+
+#define GET_RTX(RTX)		(((RTX)->__count)++)
+#define PUT_RTX(RTX) \
+do \
+  { \
+    if (--((RTX)->__count) == 0) \
+      __put_rtx(RTX); \
+  } \
+while (0)
+
+
 /* RTL vector.  These appear inside RTX's when there is a need
    for a variable number of things.  The principle use is inside
    PARALLEL expressions.  */
 
 struct rtvec_def GTY(()) {
   int num_elem;		/* number of elements */
+  int __count;		/* reference count */
   rtx GTY ((length ("%h.num_elem"))) elem[1];
 };
 
@@ -225,6 +241,15 @@ struct rtvec_def GTY(()) {
 #define GET_NUM_ELEM(RTVEC)		((RTVEC)->num_elem)
 #define PUT_NUM_ELEM(RTVEC, NUM)	((RTVEC)->num_elem = (NUM))
 
+#define GET_RTVEC(RTVEC)	(((RTVEC)->__count)++)
+#define PUT_RTVEC(RTVEC) \
+do \
+  { \
+    if (--((RTVEC)->__count) == 0) \
+      __put_rtvec(RTVEC); \
+  } \
+while (0)
+
 /* Predicate yielding nonzero iff X is an rtl for a register.  */
 #define REG_P(X) (GET_CODE (X) == REG)
 
@@ -1347,6 +1372,8 @@ extern rtx emit_copy_of_insn_after	PARAM
 extern rtx rtx_alloc			PARAMS ((RTX_CODE));
 extern rtvec rtvec_alloc		PARAMS ((int));
 extern rtx copy_rtx			PARAMS ((rtx));
+extern void __put_rtx			PARAMS ((rtx));
+extern void __put_rtvec			PARAMS ((rtvec));
 
 /* In emit-rtl.c */
 extern rtx copy_rtx_if_shared		PARAMS ((rtx));
--- ./gengenrtl.c.~1~	Sun Aug 11 19:04:33 2002
+++ ./gengenrtl.c	Sun Aug 11 20:45:18 2002
@@ -278,11 +278,15 @@ gendef (format)
      the memory and initializes it.  */
   puts ("{");
   puts ("  rtx rt;");
-  printf ("  rt = ggc_alloc_rtx (%d);\n", (int) strlen (format));
+  puts ("  int n;");
+  printf ("  n = (sizeof (struct rtx_def) + ((%d - 1) * sizeof(rtunion)));\n",
+	  (int) strlen (format));
+  puts ("  rt = xmalloc (n);\n");
 
   puts ("  memset (rt, 0, sizeof (struct rtx_def) - sizeof (rtunion));\n");
   puts ("  PUT_CODE (rt, code);");
   puts ("  PUT_MODE (rt, mode);");
+  puts ("  rt->__count = 1;");
 
   for (p = format, i = j = 0; *p ; ++p, ++i)
     if (*p != '0')
--- ./rtl.c.~1~	Tue Jun  4 14:06:54 2002
+++ ./rtl.c	Sun Aug 11 20:53:11 2002
@@ -242,14 +242,34 @@ rtvec_alloc (n)
 {
   rtvec rt;
 
-  rt = ggc_alloc_rtvec (n);
+  n = (sizeof(struct rtvec_def)
+       + ((n - 1) * sizeof (rtx)));
+  rt = xmalloc (n);
+
+  PUT_NUM_ELEM (rt, n);
+  rt->__count = 1;
+
   /* clear out the vector */
   memset (&rt->elem[0], 0, n * sizeof (rtx));
 
-  PUT_NUM_ELEM (rt, n);
   return rt;
 }
 
+void
+__put_rtvec (rv)
+     rtvec rv;
+{
+  int i, len = GET_NUM_ELEM (rv);
+
+  for (i = 0; i < len; i++)
+    {
+      if (! rv->elem[i])
+	abort ();
+      PUT_RTX (rv->elem[i]);
+    }
+  xfree (rv);
+}
+
 /* Allocate an rtx of code CODE.  The CODE is stored in the rtx;
    all the rest is initialized to zero.  */
 
@@ -258,9 +278,11 @@ rtx_alloc (code)
   RTX_CODE code;
 {
   rtx rt;
-  int n = GET_RTX_LENGTH (code);
+  int n;
 
-  rt = ggc_alloc_rtx (n);
+  n = (sizeof (struct rtx_def)
+       + ((GET_RTX_LENGTH (code) - 1) * sizeof(rtunion)));
+  rt = xmalloc (n);
 
   /* 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 isn't very
@@ -268,7 +290,58 @@ rtx_alloc (code)
 
   memset (rt, 0, sizeof (struct rtx_def) - sizeof (rtunion));
   PUT_CODE (rt, code);
+  rt->__count = 1;
   return rt;
+}
+
+void
+__put_rtx(rt)
+     rtx rt;
+{
+  char *fmt;
+  int i, j, len;
+
+  fmt = GET_RTX_FORMAT (GET_CODE (rt));
+  len = GET_RTX_LENGTH (GET_CODE (rt));
+  for (i = 0; i < len; i++) {
+    switch (fmt[i]) {
+	case 'e':
+	  if (! XEXP (rt, i))
+	    abort ();
+	  PUT_RTX (XEXP (rt, i));
+	  break;
+
+	case 'E':
+	case 'V':
+	  /* XXX How to handle vectors... XXX */
+	  if (XVEC (rt, i) != NULL)
+	    {
+	      for (j = 0; j < XVECLEN (rt, i); j++)
+		{
+		  if (! XVECEXP (rt, i, j))
+		    abort ();
+		  PUT_RTX (XVECEXP (rt, i, j));
+		}
+	    }
+	  break;
+
+	case 't':
+	case 'w':
+	case 'i':
+	case 's':
+	case 'S':
+	case 'T':
+	case 'u':
+	case 'B':
+	case '0':
+	  break;
+
+	default:
+	  abort ();
+    };
+  }
+
+  xfree(rt);
 }
 
 


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