This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: Throttle inlining
- To: gcc-patches at gcc dot gnu dot org
- Subject: C++ PATCH: Throttle inlining
- From: Mark Mitchell <mark at codesourcery dot com>
- Date: Mon, 26 Mar 2001 18:24:36 -0800
- Cc: Gerald Pfeifer <pfeifer at dbai dot tuwien dot ac dot at>
- Organization: CodeSourcery, LLC
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. */