From d173e68599639b825a1e12884fa35c00a024bee4 Mon Sep 17 00:00:00 2001
From: Jan Hubicka <jh@suse.cz>
Date: Thu, 29 Jan 2004 01:34:09 +0100
Subject: [PATCH] re PR c++/12850 (memory consumption for heavy template
 instantiations tripled since 3.3)

	PR c++/12850
	* cgraph.c (cgraph_remove_node): Clear out saved/insns/arguments and
	initial pointers.
	* cgraphunit.c (cgraph_finalize_function): Clear out DECL_SAVED_INSNS
	for functions that will be only inlined.
	(cgraph_mark_function_to_output): Likewise.
	(cgraph_expand_function): Sanity check that DECL_DEFER_OUTPUT is clear;
	do not clear function body.
	* tree-optimize.c (clear_decl_rtl): Use decl_function_context.
	(tree_rest_of_compilation): Reorganize the logic releasing function
	body to use callgraph datastructure.

From-SVN: r76822
---
 gcc/ChangeLog       | 14 ++++++++++++++
 gcc/cgraph.c        |  3 +++
 gcc/cgraphunit.c    | 11 +++++++++--
 gcc/tree-optimize.c | 30 +++++++++++++++++-------------
 4 files changed, 43 insertions(+), 15 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6c0b66440b25..aa8954209754 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,17 @@
+2004-01-29  Jan Hubicka  <jh@suse.cz>
+
+	PR c++/12850
+	* cgraph.c (cgraph_remove_node): Clear out saved/insns/arguments and
+	initial pointers.
+	* cgraphunit.c (cgraph_finalize_function): Clear out DECL_SAVED_INSNS
+	for functions that will be only inlined.
+	(cgraph_mark_function_to_output): Likewise.
+	(cgraph_expand_function): Sanity check that DECL_DEFER_OUTPUT is clear;
+	do not clear function body.
+	* tree-optimize.c (clear_decl_rtl): Use decl_function_context.
+	(tree_rest_of_compilation): Reorganize the logic releasing function
+	body to use callgraph datastructure.
+
 2004-01-28  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
 
 	* pa.md: Change predicate of a peephole2 pattern from reg_or_0_operand
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 57d0844beae2..e9d0b243bc4c 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -235,6 +235,9 @@ cgraph_remove_node (struct cgraph_node *node)
   if (node->next)
     node->next->previous = node->previous;
   DECL_SAVED_TREE (node->decl) = NULL;
+  DECL_SAVED_INSNS (node->decl) = NULL;
+  DECL_ARGUMENTS (node->decl) = NULL;
+  DECL_INITIAL (node->decl) = error_mark_node;
   slot = 
     htab_find_slot_with_hash (cgraph_hash, DECL_ASSEMBLER_NAME (node->decl),
 			      IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 3a7dcb3a4dc7..f68bd2a34df5 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -228,6 +228,11 @@ cgraph_finalize_function (tree decl, bool nested)
   /* If we've not yet emitted decl, tell the debug info about it.  */
   if (!TREE_ASM_WRITTEN (decl))
     (*debug_hooks->deferred_inline_function) (decl);
+
+  /* We will never really output the function body, clear the SAVED_INSNS array
+     early then.  */
+  if (DECL_EXTERNAL (decl))
+    DECL_SAVED_INSNS (decl) = NULL;
 }
 
 /* Walk tree and record all calls.  Called via walk_tree.  */
@@ -476,6 +481,8 @@ cgraph_mark_functions_to_output (void)
 	  && !TREE_ASM_WRITTEN (decl) && !node->origin
 	  && !DECL_EXTERNAL (decl))
 	node->output = 1;
+      else
+        DECL_SAVED_INSNS (decl) = NULL;
     }
 }
 
@@ -525,9 +532,9 @@ cgraph_expand_function (struct cgraph_node *node)
   /* Generate RTL for the body of DECL.  Nested functions are expanded
      via lang_expand_decl_stmt.  */
   (*lang_hooks.callgraph.expand_function) (decl);
+  if (DECL_DEFER_OUTPUT (decl))
+    abort ();
 
-  if (!cgraph_function_possibly_inlined_p (decl))
-    DECL_SAVED_TREE (decl) = NULL;
   current_function_decl = NULL;
 }
 
diff --git a/gcc/tree-optimize.c b/gcc/tree-optimize.c
index f1957ab20e7c..e42fa06ef569 100644
--- a/gcc/tree-optimize.c
+++ b/gcc/tree-optimize.c
@@ -65,13 +65,13 @@ clear_decl_rtl (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
     {
     case VAR_DECL:
       nonstatic_p = !TREE_STATIC (t) && !DECL_EXTERNAL (t);
-      local_p = DECL_CONTEXT (t) == data;
+      local_p = decl_function_context (t) == data;
       break;
 
     case PARM_DECL:
     case LABEL_DECL:
       nonstatic_p = true;
-      local_p = DECL_CONTEXT (t) == data;
+      local_p = decl_function_context (t) == data;
       break;
 
     case RESULT_DECL:
@@ -205,18 +205,22 @@ tree_rest_of_compilation (tree fndecl, bool nested_p)
   walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
 				clear_decl_rtl,
 				fndecl);
-
-  if (DECL_SAVED_INSNS (fndecl) == 0 && !nested_p && !flag_inline_trees)
+  if (!cgraph_function_possibly_inlined_p (fndecl))
     {
-      /* Stop pointing to the local nodes about to be freed.
-	 But DECL_INITIAL must remain nonzero so we know this
-	 was an actual function definition.
-	 For a nested function, this is done in c_pop_function_context.
-	 If rest_of_compilation set this to 0, leave it 0.  */
-      if (DECL_INITIAL (fndecl) != 0)
-	DECL_INITIAL (fndecl) = error_mark_node;
-
-      DECL_ARGUMENTS (fndecl) = 0;
+      DECL_SAVED_TREE (fndecl) = NULL;
+      if (DECL_SAVED_INSNS (fndecl) == 0
+	  && !cgraph_node (fndecl)->origin)
+	{
+	  /* Stop pointing to the local nodes about to be freed.
+	     But DECL_INITIAL must remain nonzero so we know this
+	     was an actual function definition.
+	     For a nested function, this is done in c_pop_function_context.
+	     If rest_of_compilation set this to 0, leave it 0.  */
+	  if (DECL_INITIAL (fndecl) != 0)
+	    DECL_INITIAL (fndecl) = error_mark_node;
+
+	  DECL_ARGUMENTS (fndecl) = 0;
+	}
     }
 
   input_location = saved_loc;
-- 
GitLab