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

C++ PATCH: Throttle inlining



This patch throttles tree-based inlining when the functions being
inlined get large.  This is analagous to the throttling done in the
RTL-inliner, and is in fact controlled by the same option, in order to
provide a simple interface for users.  On one test case provided by
Gerald, this reduces the space usage of the compiler from >500M (at
which point I ran out of memory) to around 75M.

I also found that we were sometimes trying to use both inliners, which
is silly, and very expensive.  I fixed this as well.

Bootstrapped and tested on i686-pc-linux-gnu, installed on the
mainline.  I will install this on the branch as soon as testing is
complete.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

2001-03-26  Mark Mitchell  <mark@codesourcery.com>

	* c-common.h (DECL_NUM_STMTS): New macro.
	* c-decl.c (duplicate_decls): Copy DECL_NUM_STMTS, not
	DECL_FRAME_SIZE.
	(pushdecl): Likewise.
	* c-semantics.c (add_stmt): Update DECL_NUM_STMTS.
	* integrate.c (expand_inline_function): Don't check
	DECL_FRAME_SIZE.
	* print-tree.c (print_node): Don't print it.
	* toplev.c (rest_of_compilation): Don't try to inline when
	flag_no_inline is on.
	* tree.h (DECL_FRAME_SIZE): Remove.
	(tree_decl): Adjust accordingly.
	
2001-03-26  Mark Mitchell  <mark@codesourcery.com>

	* Makefile.in (optimize.o): Depend on params.h.
	(duplicate_decls): Copy DECL_NUM_STMTS, not DECL_FRAME_SIZE.
	(init_decl_processing): Set flag_no_inline when doing
	inlining-on-trees.
	* optimize.c: Include params.h.
	(struct inline_data): Improve documentation of FNS.  Add
	FIRST_INLINED_FN, INLINED_STMTS, and CLONING_P.
	(INSNS_PER_STMT): New macro.
	(remap_block): Use CLONING_P.
	(inlinable_function_p): Don't inline big functions.
	(expand_call_inline): Keep track of how much inlining we've done.
	(optimize_function): Set FIRST_INLINED_FN.
	(maybe_clone_body): Set CLONING_P.
	* semantics.c (simplify_aggr_init_exprs_r): Fix typing problems in
	tree nodes.
	(genrtl_finish_function): Clear DECL_DEFER_OUTPUT before calling
	rest_of_compilation.  Clear DECL_RTL for local variables
	afterwards.
	(clear_decl_rtl): New function.
		
Mon Mar 26 18:13:30 2001  Mark Mitchell  <mark@codesourcery.com>

	* com.c (duplicate_decls): Don't copy DECL_FRAME_SIZE.

2001-03-26  Mark Mitchell  <mark@codesourcery.com>

	* parse.h (DECL_END_SOURCE_LINE): Don't rely on DECL_FRAME_SIZE.

Index: c-common.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-common.h,v
retrieving revision 1.64
diff -c -p -r1.64 c-common.h
*** c-common.h	2001/01/13 23:29:57	1.64
--- c-common.h	2001/03/27 02:00:58
*************** struct c_lang_decl {
*** 337,342 ****
--- 337,349 ----
    (((struct c_lang_decl *) DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE))) \
     ->saved_tree)
  
+ /* In a FUNCTION_DECL for which DECL_BUILT_IN does not hold, this is
+      the approximate number of statements in this function.  There is
+      no need for this number to be exact; it is only used in various
+      heuristics regarding optimization.  */
+ #define DECL_NUM_STMTS(NODE) \
+   (FUNCTION_DECL_CHECK (NODE)->decl.u1.i)
+ 
  extern void c_mark_lang_decl                    PARAMS ((struct c_lang_decl *));
  
  /* The variant of the C language being processed.  Each C language
Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-decl.c,v
retrieving revision 1.215
diff -c -p -r1.215 c-decl.c
*** c-decl.c	2001/03/19 23:49:50	1.215
--- c-decl.c	2001/03/27 02:01:02
*************** duplicate_decls (newdecl, olddecl, diffe
*** 2009,2015 ****
  	}
        /* Also preserve various other info from the definition.  */
        else if (! new_is_definition)
! 	DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
        if (! new_is_definition)
  	{
  	  DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
--- 2009,2015 ----
  	}
        /* Also preserve various other info from the definition.  */
        else if (! new_is_definition)
! 	DECL_NUM_STMTS (newdecl) = DECL_NUM_STMTS (olddecl);
        if (! new_is_definition)
  	{
  	  DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
*************** pushdecl (x)
*** 2372,2378 ****
  		      DECL_INITIAL (x) = (current_function_decl == oldglobal
  					  ? 0 : DECL_INITIAL (oldglobal));
  		      DECL_SAVED_INSNS (x) = DECL_SAVED_INSNS (oldglobal);
! 		      DECL_FRAME_SIZE (x) = DECL_FRAME_SIZE (oldglobal);
  		      DECL_ARGUMENTS (x) = DECL_ARGUMENTS (oldglobal);
  		      DECL_RESULT (x) = DECL_RESULT (oldglobal);
  		      TREE_ASM_WRITTEN (x) = TREE_ASM_WRITTEN (oldglobal);
--- 2372,2378 ----
  		      DECL_INITIAL (x) = (current_function_decl == oldglobal
  					  ? 0 : DECL_INITIAL (oldglobal));
  		      DECL_SAVED_INSNS (x) = DECL_SAVED_INSNS (oldglobal);
! 		      DECL_NUM_STMTS (x) = DECL_NUM_STMTS (oldglobal);
  		      DECL_ARGUMENTS (x) = DECL_ARGUMENTS (oldglobal);
  		      DECL_RESULT (x) = DECL_RESULT (oldglobal);
  		      TREE_ASM_WRITTEN (x) = TREE_ASM_WRITTEN (oldglobal);
Index: c-semantics.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-semantics.c,v
retrieving revision 1.21
diff -c -p -r1.21 c-semantics.c
*** c-semantics.c	2001/03/15 02:50:48	1.21
--- c-semantics.c	2001/03/27 02:01:03
*************** add_stmt (t)
*** 75,80 ****
--- 75,85 ----
    /* When we expand a statement-tree, we must know whether or not the
       statements are full-expresions.  We record that fact here.  */
    STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p ();
+ 
+   /* Keep track of the number of statements in this function.  */
+   if (current_function_decl)
+     ++DECL_NUM_STMTS (current_function_decl);
+ 
    return t;
  }
  
Index: integrate.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/integrate.c,v
retrieving revision 1.134
diff -c -p -r1.134 integrate.c
*** integrate.c	2001/03/22 18:48:30	1.134
--- integrate.c	2001/03/27 02:01:05
*************** expand_inline_function (fndecl, parms, t
*** 892,900 ****
  	     incoming arg rtx values are expanded now so that we can be
  	     sure we have enough slots in the const equiv map since the
  	     store_expr call can easily blow the size estimate.  */
- 	  if (DECL_FRAME_SIZE (fndecl) != 0)
- 	    copy_rtx_and_substitute (virtual_stack_vars_rtx, map, 0);
- 
  	  if (DECL_SAVED_INSNS (fndecl)->args_size != 0)
  	    copy_rtx_and_substitute (virtual_incoming_args_rtx, map, 0);
  	}
--- 892,897 ----
Index: print-tree.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/print-tree.c,v
retrieving revision 1.44
diff -c -p -r1.44 print-tree.c
*** print-tree.c	2001/03/17 16:52:05	1.44
--- print-tree.c	2001/03/27 02:01:05
*************** print_node (file, prefix, node, indent)
*** 402,412 ****
  		       DECL_OFFSET_ALIGN (node));
  	    }
  	}
-       else if (DECL_INLINE (node))
- 	{
- 	  fprintf (file, " frame_size ");
- 	  fprintf (file, HOST_WIDE_INT_PRINT_DEC, DECL_FRAME_SIZE (node));
- 	}
        else if (DECL_BUILT_IN (node))
  	{
  	  if (DECL_BUILT_IN_CLASS (node) == BUILT_IN_MD)
--- 402,407 ----
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/toplev.c,v
retrieving revision 1.440
diff -c -p -r1.440 toplev.c
*** toplev.c	2001/03/26 02:36:39	1.440
--- toplev.c	2001/03/27 02:01:08
*************** rest_of_compilation (decl)
*** 2775,2781 ****
  	  }
  
        /* If requested, consider whether to make this function inline.  */
!       if (DECL_INLINE (decl) || flag_inline_functions)
  	{
  	  timevar_push (TV_INTEGRATION);
  	  lose = function_cannot_inline_p (decl);
--- 2775,2782 ----
  	  }
  
        /* If requested, consider whether to make this function inline.  */
!       if ((DECL_INLINE (decl) && !flag_no_inline) 
! 	  || flag_inline_functions)
  	{
  	  timevar_push (TV_INTEGRATION);
  	  lose = function_cannot_inline_p (decl);
Index: tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/tree.h,v
retrieving revision 1.232
diff -c -p -r1.232 tree.h
*** tree.h	2001/03/19 23:49:51	1.232
--- tree.h	2001/03/27 02:01:11
*************** struct tree_type
*** 1396,1404 ****
  #define DECL_INCOMING_RTL(NODE) (PARM_DECL_CHECK (NODE)->decl.u2.r)
  /* For FUNCTION_DECL, if it is inline, holds the saved insn chain.  */
  #define DECL_SAVED_INSNS(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.u2.f)
- /* For FUNCTION_DECL, if it is inline,
-    holds the size of the stack frame, as an integer.  */
- #define DECL_FRAME_SIZE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.u1.i)
  /* For FUNCTION_DECL, if it is built-in,
     this identifies which built-in operation it is.  */
  #define DECL_FUNCTION_CODE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.u1.f)
--- 1396,1401 ----
*************** struct tree_decl
*** 1691,1702 ****
    unsigned lang_flag_6 : 1;
    unsigned lang_flag_7 : 1;
  
-   /* For a FUNCTION_DECL, if inline, this is the size of frame needed.
-      If built-in, this is the code for which built-in function.
-      For other kinds of decls, this is DECL_ALIGN and DECL_OFFSET_ALIGN.  */
    union {
!     HOST_WIDE_INT i;
      enum built_in_function f;
      struct {unsigned int align : 24; unsigned int off_align : 8;} a;
    } u1;
  
--- 1688,1702 ----
    unsigned lang_flag_6 : 1;
    unsigned lang_flag_7 : 1;
  
    union {
!     /* In a FUNCTION_DECL for which DECL_BUILT_IN holds, this is
!        DECL_FUNCTION_CODE.  */
      enum built_in_function f;
+     /* In a FUNCITON_DECL for which DECL_BUILT_IN does not hold, this
+        is used by language-dependent code.  */
+     HOST_WIDE_INT i;
+     /* DECL_ALIGN and DECL_OFFSET_ALIGN.  (These are not used for
+        FUNCTION_DECLs).  */
      struct {unsigned int align : 24; unsigned int off_align : 8;} a;
    } u1;
  
Index: cp/Make-lang.in
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/Make-lang.in,v
retrieving revision 1.80
diff -c -p -r1.80 Make-lang.in
*** Make-lang.in	2001/03/22 18:47:21	1.80
--- Make-lang.in	2001/03/27 02:01:12
*************** cp/semantics.o: cp/semantics.c $(CXX_TRE
*** 297,303 ****
    flags.h $(GGC_H) output.h $(RTL_H) $(TIMEVAR_H)
  cp/dump.o: cp/dump.c $(CXX_TREE_H) c-dump.h
  cp/optimize.o: cp/optimize.c $(CXX_TREE_H) rtl.h integrate.h insn-config.h \
!   input.h
  cp/mangle.o: cp/mangle.c $(CXX_TREE_H) toplev.h
  
  cp/parse.o: cp/parse.c $(CXX_TREE_H) flags.h cp/lex.h except.h output.h \
--- 297,303 ----
    flags.h $(GGC_H) output.h $(RTL_H) $(TIMEVAR_H)
  cp/dump.o: cp/dump.c $(CXX_TREE_H) c-dump.h
  cp/optimize.o: cp/optimize.c $(CXX_TREE_H) rtl.h integrate.h insn-config.h \
!   input.h params.h
  cp/mangle.o: cp/mangle.c $(CXX_TREE_H) toplev.h
  
  cp/parse.o: cp/parse.c $(CXX_TREE_H) flags.h cp/lex.h except.h output.h \
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.764
diff -c -p -r1.764 decl.c
*** decl.c	2001/03/26 08:37:24	1.764
--- decl.c	2001/03/27 02:01:20
*************** duplicate_decls (newdecl, olddecl)
*** 3692,3698 ****
  	      SET_DECL_RTL (newdecl, DECL_RTL (olddecl));
  	    }
  	  else
! 	    DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
  
  	  DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
  	  if ((DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl)))
--- 3692,3698 ----
  	      SET_DECL_RTL (newdecl, DECL_RTL (olddecl));
  	    }
  	  else
! 	    DECL_NUM_STMTS (newdecl) = DECL_NUM_STMTS (olddecl);
  
  	  DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
  	  if ((DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl)))
*************** init_decl_processing ()
*** 6346,6352 ****
    if (! flag_permissive && ! pedantic)
      flag_pedantic_errors = 1;
    if (!flag_no_inline)
!     flag_inline_trees = 1;
  
    /* Initially, C.  */
    current_lang_name = lang_name_c;
--- 6346,6355 ----
    if (! flag_permissive && ! pedantic)
      flag_pedantic_errors = 1;
    if (!flag_no_inline)
!     {
!       flag_inline_trees = 1;
!       flag_no_inline = 1;
!     }
  
    /* Initially, C.  */
    current_lang_name = lang_name_c;
Index: cp/optimize.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/optimize.c,v
retrieving revision 1.60
diff -c -p -r1.60 optimize.c
*** optimize.c	2001/03/23 12:04:10	1.60
--- optimize.c	2001/03/27 02:01:21
*************** Software Foundation, 59 Temple Place - S
*** 30,35 ****
--- 30,36 ----
  #include "toplev.h"
  #include "varray.h"
  #include "ggc.h"
+ #include "params.h"
  
  /* To Do:
  
*************** typedef struct inline_data
*** 50,57 ****
    /* A stack of the functions we are inlining.  For example, if we are
       compiling `f', which calls `g', which calls `h', and we are
       inlining the body of `h', the stack will contain, `h', followed
!      by `g', followed by `f'.  */
    varray_type fns;
    /* The label to jump to when a return statement is encountered.  If
       this value is NULL, then return statements will simply be
       remapped as return statements, rather than as jumps.  */
--- 51,63 ----
    /* A stack of the functions we are inlining.  For example, if we are
       compiling `f', which calls `g', which calls `h', and we are
       inlining the body of `h', the stack will contain, `h', followed
!      by `g', followed by `f'.  The first few elements of the stack may
!      contain other functions that we know we should not recurse into,
!      even though they are not directly being inlined.  */
    varray_type fns;
+   /* The index of the first element of FNS that really represents an
+      inlined function.  */
+   unsigned first_inlined_fn;
    /* The label to jump to when a return statement is encountered.  If
       this value is NULL, then return statements will simply be
       remapped as return statements, rather than as jumps.  */
*************** typedef struct inline_data
*** 66,71 ****
--- 72,85 ----
    varray_type target_exprs;
    /* A list of the functions current function has inlined.  */
    varray_type inlined_fns;
+   /* The approximate number of statements we have inlined in the
+      current call stack.  */
+   int inlined_stmts;
+   /* We use the same mechanism to build clones that we do to perform
+      inlining.  However, there are a few places where we need to
+      distinguish between those two situations.  This flag is true nif
+      we are cloning, rather than inlining.  */
+   bool cloning_p;
  } inline_data;
  
  /* Prototypes.  */
*************** static void remap_block PARAMS ((tree, t
*** 82,87 ****
--- 96,106 ----
  static void copy_scope_stmt PARAMS ((tree *, int *, inline_data *));
  static tree calls_setjmp_r PARAMS ((tree *, int *, void *));
  
+ /* The approximate number of instructions per statement.  This number
+    need not be particularly accurate; it is used only to make
+    decisions about when a function is too big to inline.  */
+ #define INSNS_PER_STMT (10)
+ 
  /* Remap DECL during the copying of the BLOCK tree for the function.
     DATA is really an `inline_data *'.  */
  
*************** remap_block (scope_stmt, decls, id)
*** 199,207 ****
        /* We put the BLOCK_VARS in reverse order; fix that now.  */
        BLOCK_VARS (new_block) = nreverse (BLOCK_VARS (new_block));
        fn = VARRAY_TREE (id->fns, 0);
!       if (fn == current_function_decl)
! 	/* We're building a clone; DECL_INITIAL is still error_mark_node, and
! 	   current_binding_level is the parm binding level.  */
  	insert_block (new_block);
        else
  	{
--- 218,227 ----
        /* We put the BLOCK_VARS in reverse order; fix that now.  */
        BLOCK_VARS (new_block) = nreverse (BLOCK_VARS (new_block));
        fn = VARRAY_TREE (id->fns, 0);
!       if (id->cloning_p)
! 	/* We're building a clone; DECL_INITIAL is still
! 	   error_mark_node, and current_binding_level is the parm
! 	   binding level.  */
  	insert_block (new_block);
        else
  	{
*************** inlinable_function_p (fn, id)
*** 583,588 ****
--- 603,611 ----
    /* We can't inline varargs functions.  */
    else if (varargs_function_p (fn))
      ;
+   /* We can't inline functions that are too big.  */
+   else if (DECL_NUM_STMTS (fn) * INSNS_PER_STMT > MAX_INLINE_INSNS)
+     ;
    /* All is well.  We can inline this function.  Traditionally, GCC
       has refused to inline functions using alloca, or functions whose
       values are returned in a PARALLEL, and a few other such obscure
*************** inlinable_function_p (fn, id)
*** 593,598 ****
--- 616,628 ----
    /* Squirrel away the result so that we don't have to check again.  */
    DECL_UNINLINABLE (fn) = !inlinable;
  
+   /* Even if this function is not itself too big to inline, it might
+      be that we've done so much inlining already that we don't want to
+      risk inlining any more.  */
+   if ((DECL_NUM_STMTS (fn) + id->inlined_stmts) * INSNS_PER_STMT 
+       > MAX_INLINE_INSNS)
+     inlinable = 0;
+ 
    /* We can inline a template instantiation only if it's fully
       instantiated.  */
    if (inlinable
*************** expand_call_inline (tp, walk_subtrees, d
*** 830,839 ****
--- 860,878 ----
       the equivalent inlined version either.  */
    TREE_USED (*tp) = 1;
  
+   /* Our function now has more statements than it did before.  */
+   DECL_NUM_STMTS (VARRAY_TREE (id->fns, 0)) += DECL_NUM_STMTS (fn);
+   id->inlined_stmts += DECL_NUM_STMTS (VARRAY_TREE (id->fns, 0));
+ 
    /* Recurse into the body of the just inlined function.  */
    expand_calls_inline (inlined_body, id);
    VARRAY_POP (id->fns);
  
+   /* If we've returned to the top level, clear out the record of how
+      much inlining has been done.  */
+   if (VARRAY_ACTIVE_SIZE (id->fns) == id->first_inlined_fn)
+     id->inlined_stmts = 0;
+ 
    /* Don't walk into subtrees.  We've already handled them above.  */
    *walk_subtrees = 0;
  
*************** optimize_function (fn)
*** 904,909 ****
--- 943,952 ----
        /* Create the list of functions this call will inline.  */
        VARRAY_TREE_INIT (id.inlined_fns, 32, "inlined_fns");
  
+       /* Keep track of the low-water mark, i.e., the point where
+ 	 the first real inlining is represented in ID.FNS.  */
+       id.first_inlined_fn = VARRAY_ACTIVE_SIZE (id.fns);
+ 
        /* Replace all calls to inline functions with the bodies of those
  	 functions.  */
        expand_calls_inline (&DECL_SAVED_TREE (fn), &id);
*************** maybe_clone_body (fn)
*** 1010,1015 ****
--- 1053,1062 ----
        VARRAY_TREE_INIT (id.fns, 2, "fns");
        VARRAY_PUSH_TREE (id.fns, clone);
        VARRAY_PUSH_TREE (id.fns, fn);
+ 
+       /* Cloning is treated slightly differently from inlining.  Set
+ 	 CLONING_P so that its clear which operation we're performing.  */
+       id.cloning_p = true;
  
        /* Remap the parameters.  */
        id.decl_map = splay_tree_new (splay_tree_compare_pointers,
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/semantics.c,v
retrieving revision 1.195
diff -c -p -r1.195 semantics.c
*** semantics.c	2001/03/26 08:37:25	1.195
--- semantics.c	2001/03/27 02:01:23
*************** static void genrtl_named_return_value PA
*** 59,64 ****
--- 59,65 ----
  static void cp_expand_stmt PARAMS ((tree));
  static void genrtl_start_function PARAMS ((tree));
  static void genrtl_finish_function PARAMS ((tree));
+ static tree clear_decl_rtl PARAMS ((tree *, int *, void *));
  
  /* Finish processing the COND, the SUBSTMT condition for STMT.  */
  
*************** simplify_aggr_init_exprs_r (tp, walk_sub
*** 2241,2247 ****
    tree args;
    tree slot;
    tree type;
-   tree call_type;
    int copy_from_buffer_p;
  
    aggr_init_expr = *tp;
--- 2242,2247 ----
*************** simplify_aggr_init_exprs_r (tp, walk_sub
*** 2264,2280 ****
    args = TREE_OPERAND (aggr_init_expr, 1);
    slot = TREE_OPERAND (aggr_init_expr, 2);
    type = TREE_TYPE (aggr_init_expr);
-   call_type = type;
    if (AGGR_INIT_VIA_CTOR_P (aggr_init_expr))
      {
        /* Replace the first argument with the address of the third
  	 argument to the AGGR_INIT_EXPR.  */
-       call_type = build_pointer_type (type);
        mark_addressable (slot);
!       args = tree_cons (NULL_TREE, build1 (ADDR_EXPR, call_type, slot),
  			TREE_CHAIN (args));
      }
!   call_expr = build (CALL_EXPR, call_type, fn, args, NULL_TREE);
    TREE_SIDE_EFFECTS (call_expr) = 1;
  
    /* If we're using the non-reentrant PCC calling convention, then we
--- 2264,2283 ----
    args = TREE_OPERAND (aggr_init_expr, 1);
    slot = TREE_OPERAND (aggr_init_expr, 2);
    type = TREE_TYPE (aggr_init_expr);
    if (AGGR_INIT_VIA_CTOR_P (aggr_init_expr))
      {
        /* Replace the first argument with the address of the third
  	 argument to the AGGR_INIT_EXPR.  */
        mark_addressable (slot);
!       args = tree_cons (NULL_TREE, 
! 			build1 (ADDR_EXPR, 
! 				build_pointer_type (TREE_TYPE (slot)),
! 				slot),
  			TREE_CHAIN (args));
      }
!   call_expr = build (CALL_EXPR, 
! 		     TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))),
! 		     fn, args, NULL_TREE);
    TREE_SIDE_EFFECTS (call_expr) = 1;
  
    /* If we're using the non-reentrant PCC calling convention, then we
*************** genrtl_finish_function (fn)
*** 2681,2686 ****
--- 2684,2693 ----
    if (function_depth > 1)
      ggc_push_context ();
  
+   /* There's no need to defer outputting this function any more; we
+      know we want to output it.  */
+   DECL_DEFER_OUTPUT (fn) = 0;
+ 
    /* Run the optimizers and output the assembler code for this
       function.  */
    rest_of_compilation (fn);
*************** genrtl_finish_function (fn)
*** 2721,2746 ****
  
    --function_depth;
  
!   if (!DECL_SAVED_INSNS (fn)
!       && !(flag_inline_trees && DECL_INLINE (fn)))
      {
        tree t;
  
!       /* 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.  */
!       DECL_INITIAL (fn) = error_mark_node;
        for (t = DECL_ARGUMENTS (fn); t; t = TREE_CHAIN (t))
  	{
  	  SET_DECL_RTL (t, NULL_RTX);
  	  DECL_INCOMING_RTL (t) = NULL_RTX;
  	}
-     }
  
    /* Let the error reporting routines know that we're outside a
       function.  For a nested function, this value is used in
       pop_cp_function_context and then reset via pop_function_context.  */
    current_function_decl = NULL_TREE;
  }
  
  /* Perform initialization related to this module.  */
--- 2728,2779 ----
  
    --function_depth;
  
!   /* If we don't need the RTL for this function anymore, stop pointing
!      to it.  That's especially important for LABEL_DECLs, since you
!      can reach all the instructions in the function from the
!      CODE_LABEL stored in the DECL_RTL for the LABEL_DECL.  */
!   if (!DECL_SAVED_INSNS (fn))
      {
        tree t;
+ 
+       /* Walk the BLOCK-tree, clearing DECL_RTL for LABEL_DECLs and
+ 	 non-static local variables.  */
+       walk_tree_without_duplicates (&DECL_SAVED_TREE (fn),
+ 				    clear_decl_rtl,
+ 				    NULL);
  
!       /* Clear out the RTL for the arguments.  */
        for (t = DECL_ARGUMENTS (fn); t; t = TREE_CHAIN (t))
  	{
  	  SET_DECL_RTL (t, NULL_RTX);
  	  DECL_INCOMING_RTL (t) = NULL_RTX;
  	}
  
+       if (!(flag_inline_trees && DECL_INLINE (fn)))
+ 	/* DECL_INITIAL must remain nonzero so we know this was an
+ 	   actual function definition.  */
+ 	DECL_INITIAL (fn) = error_mark_node;
+     }
+   
    /* Let the error reporting routines know that we're outside a
       function.  For a nested function, this value is used in
       pop_cp_function_context and then reset via pop_function_context.  */
    current_function_decl = NULL_TREE;
+ }
+ 
+ /* Clear out the DECL_RTL for the non-static variables in BLOCK and
+    its sub-blocks.  */
+ 
+ static tree
+ clear_decl_rtl (tp, walk_subtrees, data)
+      tree *tp;
+      int *walk_subtrees ATTRIBUTE_UNUSED;
+      void *data ATTRIBUTE_UNUSED;
+ {
+   if (nonstatic_local_decl_p (*tp)) 
+     SET_DECL_RTL (*tp, NULL_RTX);
+     
+   return NULL_TREE;
  }
  
  /* Perform initialization related to this module.  */
Index: f/com.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/f/com.c,v
retrieving revision 1.116
diff -c -p -r1.116 com.c
*** com.c	2001/03/19 23:50:02	1.116
--- com.c	2001/03/27 02:01:30
*************** duplicate_decls (tree newdecl, tree oldd
*** 13743,13750 ****
  	  DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
  	  DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
  	}
-       else
- 	DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
  
        DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
        DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
--- 13743,13748 ----
Index: java/parse.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/parse.h,v
retrieving revision 1.67
diff -c -p -r1.67 parse.h
*** parse.h	2001/03/17 20:25:10	1.67
--- parse.h	2001/03/27 02:01:32
*************** typedef struct _jdeplist {
*** 720,726 ****
  #define CURRENT_OSB(C) (C)->osb_number [(C)->osb_depth]
  
  /* Macro for the xreferencer */
! #define DECL_END_SOURCE_LINE(DECL)       DECL_FRAME_SIZE (DECL)
  #define DECL_INHERITED_SOURCE_LINE(DECL) (DECL_CHECK (DECL)->decl.u2.i)
       
  /* Parser context data structure. */
--- 720,726 ----
  #define CURRENT_OSB(C) (C)->osb_number [(C)->osb_depth]
  
  /* Macro for the xreferencer */
! #define DECL_END_SOURCE_LINE(DECL)       (DECL_CHECK (DECL)->decl.u1.i)
  #define DECL_INHERITED_SOURCE_LINE(DECL) (DECL_CHECK (DECL)->decl.u2.i)
       
  /* Parser context data structure. */


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