This is a first attempt to separate function RTL and make it default. This 
patch is enough for --disable-bootstrap --enable-languages=c to complete on 
Linux x64, but there still remains some RTL that is allocated on function 
obstack when it should be permanent instead.

The patch disables sharing of CONST_VECTOR rtxes. If that impacts memory usage 
too much, a new hash table can be introduced for storing them. That is for 
later, though.

Committed to gc-improv.

2011-03-29  Laurynas Biveinis  <laurynas.bivei...@gmail.com>

        * rtl.h (use_rtl_permanent_mem): New.
        (use_rtl_function_mem): New.
        (allocate_in_rtl_permanent_mem): New.
        (free_rtl_function_mem): New.
        (discard_rtx_lists): New.

        * rtl.c (obstack_nesting_level): New.
        (function_ob_first_obj): New.
        (init_rtl): Set function_ob_first_obj and obstack_nesting_level.
        (use_rtl_permanent_mem): New.
        (use_rtl_function_mem): New.
        (allocate_in_rtl_permanent_mem): New.
        (copy_rtx_to_permanent_mem): Use use_rtl_permanent_mem and
        use_rtl_function_mem.
        (strdup_to_permanent_mem): Likewise.
        (free_rtl_function_mem): New.
        (copy_rtx): Do not share CONST_VECTOR rtxes.

        * alias.c (init_alias_target): Allocate RTXes in permanent RTL
        memory.

        * cselib.c (cselib_init): Likewise.

        * config/i386/i386.c (ix86_init_machine_status): Likewise.
        (ix86_tls_get_addr): Likewise.
        (ix86_tls_module_base): Likewise.

        * cfgloopanal.c (init_set_costs): Likewise.

        * cfgexpand.c (expand_debug_expr): Likewise.

        * caller-save.c (init_caller_save): Likewise.

        * gcse.c (can_assign_to_reg_without_clobbers_p): Likewise.

        * tree-ssa-address.c (gen_addr_rtx): Likewise.
        (addr_for_mem_ref): Likewise.

        * reginfo.c (init_fake_stack_mems): Likewise.

        * varasm.c (make_decl_rtl): Likewise.
        (build_constant_desc): Likewise.
        (force_const_mem): Use RTL permanent memory for shared constant
        pool.

        * lists.c (discard_rtx_lists): New.

        * gengenrtl.c (special_rtx): Add "CONST" to specially handled
        rtxes.

        * function.h (struct function): New field spill_slot_decl.

        * function.c (free_after_compilation): Call free_rtl_function_mem
        and discard_rtx_lists.

        * emit-rtl.c (gen_rtx_CONST): New.
        (gen_rtx_CONST_INT): Perform the gen_rtx_raw_CONST_INT call using
        permanent RTL memory.
        (const_double_from_real_value): Allocate RTXes in permanent RTL
        memory.
        (immed_double_const): Likewise.
        (spill_slot_decl): Removed.
        (get_spill_slot_decl): Use cfun->spill_slot_decl.
        (init_emit_regs): Allocate RTXes in permanent RTL memory.
        (init_emit_once): Likewise..
        (gen_hard_reg_clobber): Likewise.

        * dwarf2out.c (add_AT_addr): Copy addr to permanent RTL memory.
        (mem_loc_descriptor): Copy rtl to permanent RTL memory.
        (loc_list_from_tree): Likewise.
        (gen_variable_die): Perform the plus_constant calls using
        permanent RTL memory.
Index: gengenrtl.c
===================================================================
--- gengenrtl.c	(revision 170593)
+++ gengenrtl.c	(working copy)
@@ -128,7 +128,8 @@
 	  || strcmp (defs[idx].enumname, "REG") == 0
 	  || strcmp (defs[idx].enumname, "SUBREG") == 0
 	  || strcmp (defs[idx].enumname, "MEM") == 0
-	  || strcmp (defs[idx].enumname, "CONST_VECTOR") == 0);
+	  || strcmp (defs[idx].enumname, "CONST_VECTOR") == 0
+	  || strcmp (defs[idx].enumname, "CONST") == 0);
 }
 
 /* Return nonzero if the RTL code given by index IDX is one that we should
Index: lists.c
===================================================================
--- lists.c	(revision 170593)
+++ lists.c	(working copy)
@@ -213,3 +213,11 @@
 
   return elem;
 }
+
+/* Discards the cache lists once the RTXes in them are freed.  */
+void
+discard_rtx_lists (void)
+{
+  unused_insn_list = NULL;
+  unused_expr_list = NULL;
+}
Index: cfgloopanal.c
===================================================================
--- cfgloopanal.c	(revision 170593)
+++ cfgloopanal.c	(working copy)
@@ -335,6 +335,8 @@
   rtx mem = validize_mem (gen_rtx_MEM (SImode, addr));
   unsigned i;
 
+  use_rtl_permanent_mem ();
+
   target_avail_regs = 0;
   target_clobbered_regs = 0;
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
@@ -373,7 +375,9 @@
       end_sequence ();
       target_spill_cost [speed] = seq_cost (seq, speed);
     }
+
   default_rtl_profile ();
+  use_rtl_function_mem ();
 }
 
 /* Estimates cost of increased register pressure caused by making N_NEW new
Index: caller-save.c
===================================================================
--- caller-save.c	(revision 170594)
+++ caller-save.c	(working copy)
@@ -192,6 +192,8 @@
 
   caller_save_initialized_p = true;
 
+  use_rtl_permanent_mem ();
+
   CLEAR_HARD_REG_SET (no_caller_save_reg_set);
   /* First find all the registers that we need to deal with and all
      the modes that they can have.  If we can't find a mode to use,
@@ -280,6 +282,7 @@
 		SET_HARD_REG_BIT (no_caller_save_reg_set, i);
 	    }
 	}
+  use_rtl_function_mem ();
 }
 
 
Index: dwarf2out.c
===================================================================
--- dwarf2out.c	(revision 170594)
+++ dwarf2out.c	(working copy)
@@ -7650,7 +7650,7 @@
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_addr;
-  attr.dw_attr_val.v.val_addr = addr;
+  attr.dw_attr_val.v.val_addr = copy_rtx_to_permanent_mem (addr);
   add_dwarf_attr (die, &attr);
 }
 
@@ -13937,7 +13937,7 @@
 	  temp = new_loc_descr (DWARF2_ADDR_SIZE == 4
 				? DW_OP_const4u : DW_OP_const8u, 0, 0);
 	  temp->dw_loc_oprnd1.val_class = dw_val_class_addr;
-	  temp->dw_loc_oprnd1.v.val_addr = rtl;
+	  temp->dw_loc_oprnd1.v.val_addr = copy_rtx_to_permanent_mem (rtl);
 	  temp->dtprel = true;
 
 	  mem_loc_result = new_loc_descr (DW_OP_GNU_push_tls_address, 0, 0);
@@ -15520,7 +15520,7 @@
 
 	  ret = new_loc_descr (first_op, 0, 0);
 	  ret->dw_loc_oprnd1.val_class = dw_val_class_addr;
-	  ret->dw_loc_oprnd1.v.val_addr = rtl;
+	  ret->dw_loc_oprnd1.v.val_addr = copy_rtx_to_permanent_mem (rtl);
 	  ret->dtprel = dtprel;
 
 	  ret1 = new_loc_descr (second_op, 0, 0);
@@ -15571,7 +15571,7 @@
 	  {
 	    ret = new_loc_descr (DW_OP_addr, 0, 0);
 	    ret->dw_loc_oprnd1.val_class = dw_val_class_addr;
-	    ret->dw_loc_oprnd1.v.val_addr = rtl;
+	    ret->dw_loc_oprnd1.v.val_addr = copy_rtx_to_permanent_mem (rtl);
 	  }
 	else
 	  {
@@ -19542,8 +19542,13 @@
 			  && loc->expr->dw_loc_next == NULL
 			  && GET_CODE (loc->expr->dw_loc_oprnd1.v.val_addr)
 			     == SYMBOL_REF)
-			loc->expr->dw_loc_oprnd1.v.val_addr
-			  = plus_constant (loc->expr->dw_loc_oprnd1.v.val_addr, off);
+			{
+			  use_rtl_permanent_mem ();
+			  loc->expr->dw_loc_oprnd1.v.val_addr
+			    = plus_constant (loc->expr->dw_loc_oprnd1.v.val_addr,
+					     off);
+			  use_rtl_function_mem ();
+			}
 			else
 			  loc_list_plus_const (loc, off);
 		    }
@@ -19605,8 +19610,12 @@
 		  && loc->expr->dw_loc_opc == DW_OP_addr
 		  && loc->expr->dw_loc_next == NULL
 		  && GET_CODE (loc->expr->dw_loc_oprnd1.v.val_addr) == SYMBOL_REF)
-		loc->expr->dw_loc_oprnd1.v.val_addr
-		  = plus_constant (loc->expr->dw_loc_oprnd1.v.val_addr, off);
+		{
+		  use_rtl_permanent_mem ();
+		  loc->expr->dw_loc_oprnd1.v.val_addr
+		    = plus_constant (loc->expr->dw_loc_oprnd1.v.val_addr, off);
+		  use_rtl_function_mem ();
+		}
 	      else
 		loc_list_plus_const (loc, off);
 	    }
Index: tree-ssa-address.c
===================================================================
--- tree-ssa-address.c	(revision 170593)
+++ tree-ssa-address.c	(working copy)
@@ -114,6 +114,8 @@
   if (offset_p)
     *offset_p = NULL;
 
+  use_rtl_permanent_mem ();
+
   if (index)
     {
       act_elem = index;
@@ -175,6 +177,8 @@
 
   if (!*addr)
     *addr = const0_rtx;
+
+  use_rtl_function_mem ();
 }
 
 /* Returns address for TARGET_MEM_REF with parameters given by ADDR
@@ -218,6 +222,7 @@
       templ = VEC_index (mem_addr_template, mem_addr_template_list, templ_index);
       if (!templ->ref)
 	{
+	  use_rtl_permanent_mem ();
 	  sym = (addr->symbol ?
 		 gen_rtx_SYMBOL_REF (address_mode, ggc_strdup ("test_symbol"))
 		 : NULL_RTX);
@@ -234,6 +239,7 @@
 			&templ->ref,
 			&templ->step_p,
 			&templ->off_p);
+	  use_rtl_function_mem ();
 	}
 
       if (st)
Index: function.c
===================================================================
--- function.c	(revision 170593)
+++ function.c	(working copy)
@@ -226,6 +226,8 @@
   f->cfg = NULL;
 
   insn_locators_free ();
+  free_rtl_function_mem ();
+  discard_rtx_lists ();
 }
 
 /* Return size needed for stack frame based on slots so far allocated.
Index: function.h
===================================================================
--- function.h	(revision 170593)
+++ function.h	(working copy)
@@ -537,6 +537,9 @@
   /* Vector of various tree declarations.  */
   VEC(tree,gc) *debug_decls;
 
+  /* A fake decl that is used as the MEM_EXPR of spill slots.  */
+  tree spill_slot_decl;
+
   /* For md files.  */
 
   /* tm.h can use this to store whatever it likes.  */
Index: gcse.c
===================================================================
--- gcse.c	(revision 170594)
+++ gcse.c	(working copy)
@@ -878,12 +878,14 @@
      our test insn if we haven't already.  */
   if (test_insn == 0)
     {
+      use_rtl_permanent_mem ();
       test_insn
 	= make_insn_raw (gen_rtx_SET (VOIDmode,
 				      gen_rtx_REG (word_mode,
 						   FIRST_PSEUDO_REGISTER * 2),
 				      const0_rtx));
       NEXT_INSN (test_insn) = PREV_INSN (test_insn) = 0;
+      use_rtl_function_mem ();
     }
 
   /* Now make an insn like the one we would make when GCSE'ing and see if
Index: alias.c
===================================================================
--- alias.c	(revision 170593)
+++ alias.c	(working copy)
@@ -208,7 +208,7 @@
 
 /* We preserve the copy of old array around to avoid amount of garbage
    produced.  About 8% of garbage produced were attributed to this
-   array.  */
+   array.  TODO gc-improv.  */
 static VEC(rtx,heap) *old_reg_base_value;
 
 #define static_reg_base_value \
@@ -2678,6 +2678,8 @@
 {
   int i;
 
+  use_rtl_permanent_mem ();
+
   memset (static_reg_base_value, 0, sizeof static_reg_base_value);
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
@@ -2699,6 +2701,8 @@
   static_reg_base_value[HARD_FRAME_POINTER_REGNUM]
     = gen_rtx_ADDRESS (Pmode, hard_frame_pointer_rtx);
 #endif
+
+  use_rtl_function_mem ();
 }
 
 /* Set MEMORY_MODIFIED when X modifies DATA (that is assumed
Index: ChangeLog.gc-improv
===================================================================
--- ChangeLog.gc-improv	(revision 170593)
+++ ChangeLog.gc-improv	(working copy)
@@ -1,3 +1,78 @@
+2011-03-29  Laurynas Biveinis  <laurynas.bivei...@gmail.com>
+
+	* rtl.h (use_rtl_permanent_mem): New.
+	(use_rtl_function_mem): New.
+	(allocate_in_rtl_permanent_mem): New.
+	(free_rtl_function_mem): New.
+	(discard_rtx_lists): New.
+
+	* rtl.c (obstack_nesting_level): New.
+	(function_ob_first_obj): New.
+	(init_rtl): Set function_ob_first_obj and obstack_nesting_level.
+	(use_rtl_permanent_mem): New.
+	(use_rtl_function_mem): New.
+	(allocate_in_rtl_permanent_mem): New.
+	(copy_rtx_to_permanent_mem): Use use_rtl_permanent_mem and
+	use_rtl_function_mem.
+	(strdup_to_permanent_mem): Likewise.
+	(free_rtl_function_mem): New.
+	(copy_rtx): Do not share CONST_VECTOR rtxes.
+
+	* alias.c (init_alias_target): Allocate RTXes in permanent RTL
+	memory.
+
+	* cselib.c (cselib_init): Likewise.
+
+	* config/i386/i386.c (ix86_init_machine_status): Likewise.
+	(ix86_tls_get_addr): Likewise.
+	(ix86_tls_module_base): Likewise.
+
+	* cfgloopanal.c (init_set_costs): Likewise.
+
+	* cfgexpand.c (expand_debug_expr): Likewise.
+
+	* caller-save.c (init_caller_save): Likewise.
+
+	* gcse.c (can_assign_to_reg_without_clobbers_p): Likewise.
+
+	* tree-ssa-address.c (gen_addr_rtx): Likewise.
+	(addr_for_mem_ref): Likewise.
+
+	* reginfo.c (init_fake_stack_mems): Likewise.
+
+	* varasm.c (make_decl_rtl): Likewise.
+	(build_constant_desc): Likewise.
+	(force_const_mem): Use RTL permanent memory for shared constant
+	pool.
+
+	* lists.c (discard_rtx_lists): New.
+
+	* gengenrtl.c (special_rtx): Add "CONST" to specially handled
+	rtxes.
+
+	* function.h (struct function): New field spill_slot_decl.
+
+	* function.c (free_after_compilation): Call free_rtl_function_mem
+	and discard_rtx_lists.
+
+	* emit-rtl.c (gen_rtx_CONST): New.
+	(gen_rtx_CONST_INT): Perform the gen_rtx_raw_CONST_INT call using
+	permanent RTL memory.
+	(const_double_from_real_value): Allocate RTXes in permanent RTL
+	memory.
+	(immed_double_const): Likewise.
+	(spill_slot_decl): Removed.
+	(get_spill_slot_decl): Use cfun->spill_slot_decl.
+	(init_emit_regs): Allocate RTXes in permanent RTL memory.
+	(init_emit_once): Likewise..
+	(gen_hard_reg_clobber): Likewise.
+
+	* dwarf2out.c (add_AT_addr): Copy addr to permanent RTL memory.
+	(mem_loc_descriptor): Copy rtl to permanent RTL memory.
+	(loc_list_from_tree): Likewise.
+	(gen_variable_die): Perform the plus_constant calls using
+	permanent RTL memory.
+
 2011-03-01  Laurynas Biveinis  <laurynas.bivei...@gmail.com>
 
 	* varpool.c (varpool_finalize_decl): Fix typo in comment.
Index: emit-rtl.c
===================================================================
--- emit-rtl.c	(revision 170594)
+++ emit-rtl.c	(working copy)
@@ -391,6 +391,26 @@
    special_rtx in gengenrtl.c as well.  */
 
 rtx
+gen_rtx_CONST (enum machine_mode mode, rtx arg)
+{
+  rtx x;
+  /* CONST can be shared if it contains a SYMBOL_REF.  If it contains
+     a LABEL_REF, it isn't sharable.  */
+  bool shared = (GET_CODE (arg) == PLUS
+		 && GET_CODE (XEXP (arg, 0)) == SYMBOL_REF
+		 && CONST_INT_P (XEXP (arg, 1)));
+  if (shared)
+    {
+      use_rtl_permanent_mem ();
+      arg = copy_rtx (arg);
+    }
+  x = gen_rtx_raw_CONST (mode, arg);
+  if (shared)
+    use_rtl_function_mem ();
+  return x;
+}
+
+rtx
 gen_rtx_CONST_INT (enum machine_mode mode ATTRIBUTE_UNUSED, HOST_WIDE_INT arg)
 {
   void **slot;
@@ -407,7 +427,11 @@
   slot = htab_find_slot_with_hash (const_int_htab, &arg,
 				   (hashval_t) arg, INSERT);
   if (*slot == 0)
-    *slot = gen_rtx_raw_CONST_INT (VOIDmode, arg);
+    {
+      use_rtl_permanent_mem ();
+      *slot = gen_rtx_raw_CONST_INT (VOIDmode, arg);
+      use_rtl_function_mem ();
+    }
 
   return (rtx) *slot;
 }
@@ -440,11 +464,16 @@
 rtx
 const_double_from_real_value (REAL_VALUE_TYPE value, enum machine_mode mode)
 {
-  rtx real = rtx_alloc (CONST_DOUBLE);
+  rtx real;
+  use_rtl_permanent_mem ();
+
+  real = rtx_alloc (CONST_DOUBLE);
   PUT_MODE (real, mode);
 
   real->u.rv = value;
 
+  use_rtl_function_mem ();
+
   return lookup_const_double (real);
 }
 
@@ -546,7 +575,9 @@
     return GEN_INT (i0);
 
   /* We use VOIDmode for integers.  */
+  use_rtl_permanent_mem ();
   value = rtx_alloc (CONST_DOUBLE);
+  use_rtl_function_mem ();
   PUT_MODE (value, VOIDmode);
 
   CONST_DOUBLE_LOW (value) = i0;
@@ -2219,13 +2250,10 @@
   return new_rtx;
 }
 
-/* A fake decl that is used as the MEM_EXPR of spill slots.  */
-static GTY(()) tree spill_slot_decl;
-
 tree
 get_spill_slot_decl (bool force_build_p)
 {
-  tree d = spill_slot_decl;
+  tree d = cfun->spill_slot_decl;
   rtx rd;
 
   if (d || !force_build_p)
@@ -2236,7 +2264,7 @@
   DECL_ARTIFICIAL (d) = 1;
   DECL_IGNORED_P (d) = 1;
   TREE_USED (d) = 1;
-  spill_slot_decl = d;
+  cfun->spill_slot_decl = d;
 
   rd = gen_rtx_MEM (BLKmode, frame_pointer_rtx);
   MEM_NOTRAP_P (rd) = 1;
@@ -5641,6 +5669,8 @@
 {
   int i;
 
+  use_rtl_permanent_mem ();
+
   /* Reset register attributes */
   htab_empty (reg_attrs_htab);
 
@@ -5680,6 +5710,8 @@
     pic_offset_table_rtx = gen_raw_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
   else
     pic_offset_table_rtx = NULL_RTX;
+
+  use_rtl_function_mem ();
 }
 
 /* Create some permanent unique rtl objects shared between all functions.  */
@@ -5691,6 +5723,8 @@
   enum machine_mode mode;
   enum machine_mode double_mode;
 
+  use_rtl_permanent_mem ();
+
   /* Initialize the CONST_INT, CONST_DOUBLE, CONST_FIXED, and memory attribute
      hash tables.  */
   const_int_htab = htab_create (37, const_int_htab_hash, const_int_htab_eq,
@@ -5936,6 +5970,8 @@
   const_tiny_rtx[0][(int) BImode] = const0_rtx;
   if (STORE_FLAG_VALUE == 1)
     const_tiny_rtx[1][(int) BImode] = const1_rtx;
+
+  use_rtl_function_mem ();
 }
 
 /* Produce exact duplicate of insn INSN after AFTER.
@@ -6007,11 +6043,14 @@
 rtx
 gen_hard_reg_clobber (enum machine_mode mode, unsigned int regno)
 {
-  if (hard_reg_clobbers[mode][regno])
-    return hard_reg_clobbers[mode][regno];
-  else
-    return (hard_reg_clobbers[mode][regno] =
-	    gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (mode, regno)));
+  if (!hard_reg_clobbers[mode][regno])
+    {
+      use_rtl_permanent_mem ();
+      hard_reg_clobbers[mode][regno] =
+	    gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (mode, regno));
+      use_rtl_function_mem ();
+    }
+  return hard_reg_clobbers[mode][regno];
 }
 
 #include "gt-emit-rtl.h"
Index: cfgexpand.c
===================================================================
--- cfgexpand.c	(revision 170594)
+++ cfgexpand.c	(working copy)
@@ -2424,9 +2424,11 @@
       if (op0)
 	return op0;
 
+      use_rtl_permanent_mem ();
       op0 = gen_rtx_DEBUG_EXPR (mode);
       DEBUG_EXPR_TREE_DECL (op0) = exp;
       SET_DECL_RTL (exp, op0);
+      use_rtl_function_mem ();
 
       return op0;
 
Index: cselib.c
===================================================================
--- cselib.c	(revision 170594)
+++ cselib.c	(working copy)
@@ -2419,7 +2419,11 @@
   /* (mem:BLK (scratch)) is a special mechanism to conflict with everything,
      see canon_true_dependence.  This is only created once.  */
   if (! callmem)
-    callmem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode));
+    {
+      use_rtl_permanent_mem ();
+      callmem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode));
+      use_rtl_function_mem ();
+    }
 
   cselib_nregs = max_reg_num ();
 
Index: varasm.c
===================================================================
--- varasm.c	(revision 170594)
+++ varasm.c	(working copy)
@@ -1294,6 +1294,8 @@
   if (TREE_CODE (decl) == VAR_DECL && DECL_WEAK (decl))
     DECL_COMMON (decl) = 0;
 
+  use_rtl_permanent_mem ();
+
   if (use_object_blocks_p () && use_blocks_for_decl_p (decl))
     x = create_block_symbol (name, get_block_for_decl (decl), -1);
   else
@@ -1323,6 +1325,8 @@
   /* Make this function static known to the mudflap runtime.  */
   if (flag_mudflap && TREE_CODE (decl) == VAR_DECL)
     mudflap_enqueue_decl (decl);
+
+  use_rtl_function_mem ();
 }
 
 /* Like make_decl_rtl, but inhibit creation of new alias sets when
@@ -3105,6 +3109,8 @@
     align_variable (decl, 0);
   VEC_safe_push (tree, gc, saved_constant_decls, decl);
 
+  use_rtl_permanent_mem ();
+
   /* Now construct the SYMBOL_REF and the MEM.  */
   if (use_object_blocks_p ())
     {
@@ -3136,6 +3142,8 @@
 
   desc->rtl = rtl;
 
+  use_rtl_function_mem ();
+
   return desc;
 }
 
@@ -3530,6 +3538,9 @@
   if (desc)
     return copy_rtx (desc->mem);
 
+  if (pool == shared_constant_pool)
+    use_rtl_permanent_mem ();
+
   /* Otherwise, create a new descriptor.  */
   desc = XNEW (struct constant_descriptor_rtx);
   *slot = desc;
@@ -3592,7 +3603,10 @@
   if (GET_CODE (x) == LABEL_REF)
     LABEL_PRESERVE_P (XEXP (x, 0)) = 1;
 
-  return copy_rtx (def);
+  if (pool == shared_constant_pool)
+    use_rtl_function_mem ();
+
+  return def; // TODO: gc-improv: why copy_rtx?
 }
 
 /* Given a constant pool SYMBOL_REF, return the corresponding constant.  */
Index: rtl.c
===================================================================
--- rtl.c	(revision 170593)
+++ rtl.c	(working copy)
@@ -147,15 +147,36 @@
 static struct obstack function_obstack;
 static struct obstack permanent_obstack;
 struct obstack *rtl_obstack = &function_obstack;
+static unsigned int obstack_nesting_level;
+static void *function_ob_first_obj;
 
 /* Prepares for allocation of RTXes.  */
 void
 init_rtl (void)
 {
   gcc_obstack_init (&function_obstack);
+  function_ob_first_obj = obstack_alloc (&function_obstack, 0);
   gcc_obstack_init (&permanent_obstack);
+  obstack_nesting_level = 0;
 }
 
+void
+use_rtl_permanent_mem (void)
+{
+  if (obstack_nesting_level == 0)
+    rtl_obstack = &permanent_obstack;
+  obstack_nesting_level++;
+}
+
+void
+use_rtl_function_mem (void)
+{
+  gcc_assert (obstack_nesting_level > 0);
+  obstack_nesting_level--;
+  if (obstack_nesting_level == 0)
+    rtl_obstack = &function_obstack;
+}
+
 /* Allocates memory from the RTL heap with the current lifetime.  */
 void *
 allocate_in_rtl_mem (int size)
@@ -169,13 +190,19 @@
   return obstack_alloc (&function_obstack, size);
 }
 
+void *
+allocate_in_rtl_permanent_mem (int size)
+{
+  return obstack_alloc (&permanent_obstack, size);
+}
+
 rtx
 copy_rtx_to_permanent_mem (rtx x)
 {
   rtx copy;
-  rtl_obstack = &permanent_obstack;
+  use_rtl_permanent_mem ();
   copy = copy_rtx (x);
-  rtl_obstack = &function_obstack;
+  use_rtl_function_mem ();
   return copy;
 }
 
@@ -183,9 +210,9 @@
 strdup_to_permanent_mem (const char *s)
 {
   char *result;
-  rtl_obstack = &permanent_obstack;
+  use_rtl_permanent_mem ();
   result = strdup_to_rtl_mem (s);
-  rtl_obstack = &function_obstack;
+  use_rtl_function_mem ();
   return result;
 }
 
@@ -198,6 +225,13 @@
   return result;
 }
 
+/* Frees everything in the RTL memory of the current function.  */
+void
+free_rtl_function_mem (void)
+{
+  obstack_free (&function_obstack, function_ob_first_obj);
+}
+
 /* Allocate an rtx vector of N elements.
    Store the length, and initialize all elements to zero.  */
 
@@ -254,6 +288,7 @@
 {
   int length = RTX_CODE_SIZE (code);
   rtx rt;
+  /* TODO gc-improv: do not manipulate obstack alignment directly.  */
   length = (length + rtl_obstack->alignment_mask)
     & ~rtl_obstack->alignment_mask;
   rt = (rtx) obstack_alloc (rtl_obstack, length);
@@ -311,7 +346,6 @@
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
-    case CONST_VECTOR:
     case SYMBOL_REF:
     case CODE_LABEL:
     case PC:
Index: rtl.h
===================================================================
--- rtl.h	(revision 170594)
+++ rtl.h	(working copy)
@@ -1609,12 +1609,19 @@
 
 /* In rtl.c */
 extern void init_rtl (void);
+
+extern void use_rtl_permanent_mem (void);
+extern void use_rtl_function_mem (void);
+
 extern void * allocate_in_rtl_mem (int);
 extern void * allocate_in_rtl_function_mem (int);
+extern void * allocate_in_rtl_permanent_mem (int);
 extern rtx copy_rtx_to_permanent_mem (rtx);
 extern char * strdup_to_permanent_mem (const char *);
 extern char * strdup_to_rtl_mem (const char *);
 
+extern void free_rtl_function_mem (void);
+
 extern rtx rtx_alloc_stat (RTX_CODE MEM_STAT_DECL);
 #define rtx_alloc(c) rtx_alloc_stat (c MEM_STAT_INFO)
 
@@ -1993,6 +2000,7 @@
 extern rtx remove_free_INSN_LIST_node (rtx *);
 extern rtx remove_free_EXPR_LIST_node (rtx *);
 
+extern void discard_rtx_lists (void);
 
 /* reginfo.c */
 
Index: reginfo.c
===================================================================
--- reginfo.c	(revision 170593)
+++ reginfo.c	(working copy)
@@ -614,8 +614,10 @@
 {
   int i;
 
+  use_rtl_permanent_mem ();
   for (i = 0; i < MAX_MACHINE_MODE; i++)
     top_of_stack[i] = gen_rtx_MEM ((enum machine_mode) i, stack_pointer_rtx);
+  use_rtl_function_mem ();
 }
 
 
Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c	(revision 170594)
+++ config/i386/i386.c	(working copy)
@@ -22016,8 +22016,10 @@
 static struct machine_function *
 ix86_init_machine_status (void)
 {
+  /* TODO gc-improv: workout lifetime of this.  It seems that it is live for
+     every function throughout the whole compilation.  */
   struct machine_function *f = (struct machine_function *)
-    allocate_in_rtl_function_mem (sizeof (struct machine_function));;
+    allocate_in_rtl_permanent_mem (sizeof (struct machine_function));;
   memset (f, 0, sizeof (*f));
 
   f->use_fast_prologue_epilogue_nregs = -1;
@@ -22067,11 +22069,13 @@
 
   if (!ix86_tls_symbol)
     {
+      use_rtl_permanent_mem ();
       ix86_tls_symbol = gen_rtx_SYMBOL_REF (Pmode,
 					    (TARGET_ANY_GNU_TLS
 					     && !TARGET_64BIT)
 					    ? "___tls_get_addr"
 					    : "__tls_get_addr");
+      use_rtl_function_mem ();
     }
 
   return ix86_tls_symbol;
@@ -22086,10 +22090,12 @@
 
   if (!ix86_tls_module_base_symbol)
     {
+      use_rtl_permanent_mem ();
       ix86_tls_module_base_symbol = gen_rtx_SYMBOL_REF (Pmode,
 							"_TLS_MODULE_BASE_");
       SYMBOL_REF_FLAGS (ix86_tls_module_base_symbol)
 	|= TLS_MODEL_GLOBAL_DYNAMIC << SYMBOL_FLAG_TLS_SHIFT;
+      use_rtl_function_mem ();
     }
 
   return ix86_tls_module_base_symbol;

Reply via email to