diff options
author | mmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-03-27 02:17:48 +0000 |
---|---|---|
committer | mmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-03-27 02:17:48 +0000 |
commit | 1f1fa73c1ad0871e076e13f914a555fb91d09f19 (patch) | |
tree | 948316451d83b15b776dfaed5ddc3be0ef0528cf /gcc/cp | |
parent | 95ed21b8d3c6ada80e21893c08f8713621c589c3 (diff) | |
download | gcc-1f1fa73c1ad0871e076e13f914a555fb91d09f19.tar.gz |
* 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.
* 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.
* com.c (duplicate_decls): Don't copy DECL_FRAME_SIZE.
* parse.h (DECL_END_SOURCE_LINE): Don't rely on DECL_FRAME_SIZE.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@40859 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 22 | ||||
-rw-r--r-- | gcc/cp/Make-lang.in | 2 | ||||
-rw-r--r-- | gcc/cp/decl.c | 7 | ||||
-rw-r--r-- | gcc/cp/optimize.c | 55 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 57 |
5 files changed, 124 insertions, 19 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3b89a973e06..cdf1637c61d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,25 @@ +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. + 2001-03-26 Nathan Sidwell <nathan@codesourcery.com> Implement DR 209 diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index 67789446278..d9685335688 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -297,7 +297,7 @@ cp/semantics.o: cp/semantics.c $(CXX_TREE_H) cp/lex.h except.h toplev.h \ 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 + 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 \ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 03f94a35fa1..92ee8edb7ac 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3692,7 +3692,7 @@ duplicate_decls (newdecl, olddecl) SET_DECL_RTL (newdecl, DECL_RTL (olddecl)); } else - DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl); + DECL_NUM_STMTS (newdecl) = DECL_NUM_STMTS (olddecl); DECL_RESULT (newdecl) = DECL_RESULT (olddecl); if ((DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl))) @@ -6346,7 +6346,10 @@ init_decl_processing () if (! flag_permissive && ! pedantic) flag_pedantic_errors = 1; if (!flag_no_inline) - flag_inline_trees = 1; + { + flag_inline_trees = 1; + flag_no_inline = 1; + } /* Initially, C. */ current_lang_name = lang_name_c; diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index d350fdaaeed..f7f957509c2 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -30,6 +30,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "toplev.h" #include "varray.h" #include "ggc.h" +#include "params.h" /* To Do: @@ -50,8 +51,13 @@ typedef struct inline_data /* 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'. */ + 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. */ @@ -66,6 +72,14 @@ typedef struct inline_data 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. */ @@ -82,6 +96,11 @@ static void remap_block PARAMS ((tree, tree, inline_data *)); 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 *'. */ @@ -199,9 +218,10 @@ remap_block (scope_stmt, decls, id) /* 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. */ + 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 { @@ -583,6 +603,9 @@ inlinable_function_p (fn, id) /* 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 @@ -593,6 +616,13 @@ inlinable_function_p (fn, id) /* 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 @@ -830,10 +860,19 @@ expand_call_inline (tp, walk_subtrees, data) 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; @@ -904,6 +943,10 @@ optimize_function (fn) /* 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); @@ -1011,6 +1054,10 @@ maybe_clone_body (fn) 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, NULL, NULL); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index c99a0db4e70..5406b3e3bd0 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -59,6 +59,7 @@ static void genrtl_named_return_value PARAMS ((void)); 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. */ @@ -2241,7 +2242,6 @@ simplify_aggr_init_exprs_r (tp, walk_subtrees, data) tree args; tree slot; tree type; - tree call_type; int copy_from_buffer_p; aggr_init_expr = *tp; @@ -2264,17 +2264,20 @@ simplify_aggr_init_exprs_r (tp, walk_subtrees, data) 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), + args = tree_cons (NULL_TREE, + build1 (ADDR_EXPR, + build_pointer_type (TREE_TYPE (slot)), + slot), TREE_CHAIN (args)); } - call_expr = build (CALL_EXPR, call_type, fn, args, NULL_TREE); + 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 @@ -2681,6 +2684,10 @@ genrtl_finish_function (fn) 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); @@ -2721,28 +2728,54 @@ genrtl_finish_function (fn) --function_depth; - if (!DECL_SAVED_INSNS (fn) - && !(flag_inline_trees && DECL_INLINE (fn))) + /* 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; - /* 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; + /* 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. */ void |