diff mbox

[DF] RFC: obstacks in DF

Message ID alpine.LNX.2.02.1208191207010.20463@localhost.localdomain
State New
Headers show

Commit Message

Dimitrios Apostolou Aug. 20, 2012, 2:54 p.m. UTC
Hi,

while I was happy using obstacks in other parts of the compiler I thought 
they would provide a handy solution for the XNEWVECs/XRESIZEVECs in 
df-scan.c, especially df_install_refs() which is the heaviest malloc() 
user after the rest of my patches.

In the process I realised that obstacks weren't exactly suitable (thanks 
matz for helping on IRC), nevertheless I have a patch which is stable, a 
bit faster and more memory friendly (don't know why, but RSS memory for 
common non-pathological compilations, was smaller). However after trying 
various incorrect changes I'm aware that there are leaks in there that 
can't be closed without dirty hacks, so I gave up.

I'm posting the simplest but stable version of my changes and would really 
like to hear ideas. There are "holes" in the obstack that should have been 
free'd, but in the end I didn't see memory increase. I don't know what 
would happen for huge functions that keep the obstack alive for long, I 
didn't have such testcase. Finally, I think my next try will involve 
converting the chains to pool_alloc'ed linked list, do you think that 
makes sense?


Thanks,
Dimitris

Comments

Steven Bosscher Aug. 20, 2012, 3:32 p.m. UTC | #1
On Mon, Aug 20, 2012 at 4:54 PM, Dimitrios Apostolou <jimis@gmx.net> wrote:
> In the process I realised that obstacks weren't exactly suitable (thanks
> matz for helping on IRC),

Right, alloc-pool would be a better choice here.

Ciao!
Steven
diff mbox

Patch

=== modified file 'gcc/df-scan.c'
--- gcc/df-scan.c	2012-07-16 11:32:42 +0000
+++ gcc/df-scan.c	2012-08-20 14:01:59 +0000
@@ -184,6 +184,17 @@  struct df_scan_problem_data
   bitmap_obstack insn_bitmaps;
 };
 
+/* Obstack for storing all of all of
+   insn_info->{defs,uses,eq_uses,mw_hardregs} and
+   bb_info->artificial_{defs,uses}.  */
+static struct obstack df_refs_obstack;
+
+/* Keep the obstack initialised (only 4k overhead) and use this pointer to
+   actually empty it fast.  */
+static void *df_first_refs_obj;
+static int df_refs_obstack_is_init;
+
+
 typedef struct df_scan_bb_info *df_scan_bb_info_t;
 
 
@@ -193,36 +204,13 @@  df_scan_free_internal (void)
 {
   struct df_scan_problem_data *problem_data
     = (struct df_scan_problem_data *) df_scan->problem_data;
-  unsigned int i;
-  basic_block bb;
 
-  /* The vectors that hold the refs are not pool allocated because
-     they come in many sizes.  This makes them impossible to delete
-     all at once.  */
-  for (i = 0; i < DF_INSN_SIZE(); i++)
-    {
-      struct df_insn_info *insn_info = DF_INSN_UID_GET(i);
-      /* Skip the insns that have no insn_info or have been
-	 deleted.  */
-      if (insn_info)
-	{
-	  df_scan_free_ref_vec (insn_info->defs);
-	  df_scan_free_ref_vec (insn_info->uses);
-	  df_scan_free_ref_vec (insn_info->eq_uses);
-	  df_scan_free_mws_vec (insn_info->mw_hardregs);
-	}
-    }
-
-  FOR_ALL_BB (bb)
-    {
-      unsigned int bb_index = bb->index;
-      struct df_scan_bb_info *bb_info = df_scan_get_bb_info (bb_index);
-      if (bb_info)
-	{
-	  df_scan_free_ref_vec (bb_info->artificial_defs);
-	  df_scan_free_ref_vec (bb_info->artificial_uses);
-	}
-    }
+  /* Delete at once all vectors that hold the refs (all of
+     insn_info->{defs,uses,eq_uses,mw_hardregs} and
+     bb_info->artificial_{defs,uses}) but keep the obstack initialised, so
+     that it's ready for more BBs.  */
+  obstack_free (&df_refs_obstack, df_first_refs_obj);
+  df_first_refs_obj = NULL;
 
   free (df->def_info.refs);
   free (df->def_info.begin);
@@ -364,6 +352,14 @@  df_scan_alloc (bitmap all_blocks ATTRIBU
       bb_info->artificial_uses = NULL;
     }
 
+  if (! df_refs_obstack_is_init)
+    {
+      obstack_init (&df_refs_obstack);
+      df_refs_obstack_is_init = 1;
+    }
+  gcc_assert (df_first_refs_obj == NULL);
+  df_first_refs_obj = XOBNEW (&df_refs_obstack, void *);
+
   bitmap_initialize (&df->hardware_regs_used, &problem_data->reg_bitmaps);
   bitmap_initialize (&df->regular_block_artificial_uses, &problem_data->reg_bitmaps);
   bitmap_initialize (&df->eh_block_artificial_uses, &problem_data->reg_bitmaps);
@@ -791,9 +787,15 @@  df_install_ref_incremental (df_ref ref)
     }
 
   ref_rec = *ref_rec_ptr;
+  /* fprintf (stderr, "count:%d ref_rec:%p\n", count, ref_rec); */
   if (count)
     {
-      ref_rec = XRESIZEVEC (df_ref, ref_rec, count+2);
+      /* Impossible to actually know if ref_rec was malloc'ed or obstack'ed
+	 thus we might have a leak here!  */
+      df_ref *ref_rec2 = XOBNEWVEC (&df_refs_obstack, df_ref, count+2);
+      memcpy (ref_rec2, ref_rec, count*sizeof(df_ref));
+      /* free (ref_rec); */
+      ref_rec = ref_rec2;
       *ref_rec_ptr = ref_rec;
       ref_rec[count] = ref;
       ref_rec[count+1] = NULL;
@@ -801,7 +803,7 @@  df_install_ref_incremental (df_ref ref)
     }
   else
     {
-      df_ref *ref_rec = XNEWVEC (df_ref, 2);
+      ref_rec = XOBNEWVEC (&df_refs_obstack, df_ref, 2);
       ref_rec[0] = ref;
       ref_rec[1] = NULL;
       *ref_rec_ptr = ref_rec;
@@ -1070,8 +1072,9 @@  df_ref_chain_delete (df_ref *ref_rec)
 
   /* If the list is empty, it has a special shared element that is not
      to be deleted.  */
-  if (*start)
-    free (start);
+  /* if (*start) */
+  /*   free (start); */
+  /* obstack_free'd alltogether in the end of df pass.  */
 }
 
 
@@ -2611,7 +2615,7 @@  df_install_refs (basic_block bb,
   count = VEC_length (df_ref, old_vec);
   if (count)
     {
-      df_ref *new_vec = XNEWVEC (df_ref, count + 1);
+      df_ref *new_vec = XOBNEWVEC (&df_refs_obstack, df_ref, count + 1);
       bool add_to_table;
       df_ref this_ref;
       unsigned int ix;