diff options
author | aoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-10-05 02:48:47 +0000 |
---|---|---|
committer | aoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-10-05 02:48:47 +0000 |
commit | 1e3b023ca8a1e3c71fbc30d4bb9b84cd1623903d (patch) | |
tree | 8512628500ca03ba513e5684fba6a6a044156017 /gcc/cp/optimize.c | |
parent | b632977bd166019a4589082e383c5519b5f31558 (diff) | |
download | gcc-1e3b023ca8a1e3c71fbc30d4bb9b84cd1623903d.tar.gz |
* Make-lang.in (cp/decl.o, cp/tree.o): Depend on tree-inline.h.
(cp/pt.o, cp/semantics.o, cp/optimize.o): Likewise.
* cp-tree.h (lang_decl): Moved inlined_fns to tree_decl.
(TREE_READONLY_DECL_P, DECL_INLINED_FNS): Moved to ../tree.h.
(flag_inline_trees): Moved declaration to ../tree-inline.h.
(walk_tree): Moved declaration to ../tree-inline.h.
(walk_tree_without_duplicates, copy_tree_r): Likewise.
(remap_save_expr): Likewise.
* decl.c: Include tree-inline.h.
(lang_mark_tree): Don't mark inlined_fns.
* decl2.c (flag_inline_trees): Moved defn to ../tree-inline.c.
* optimize.c: Include tree-inline.h.
(optimize_inline_calls): Move declaration to ../tree.h, as
non-static.
(remap_decl): Use language-independent constructs and hooks.
(remap_block, copy_body_r, declare_return_variable): Likewise.
(inlinable_function_p): Likewise. Don't test for
DECL_LANG_SPECIFIC before DECL_INLINED_FNS as inlined_fns is
no longer language-specific.
(optimize_inline_calls): Likewise. Make it non-static. Moved
call of dump_function to...
(optimize_function): Here...
(clone_body): New function, extracted from...
(maybe_clone_body): ... here. Build decl_map locally and pass
it on to clone_body.
* pt.c, semantics.c: Include tree-inline.h.
* tree.c: Likewise.
(cp_walk_subtrees): New language-specific hook for tree inlining.
(cp_cannot_inline_tree_fn, cp_add_pending_fn_decls,
cp_is_overload_p, cp_auto_var_in_fn_p,
cp_copy_res_decl_for_inlining): Likewise.
(walk_tree): Move language-specific constructs into...
(cp_walk_subtrees): this new function.
(copy_tree_r): Use language-independent constructs and hooks.
(init_tree): Initialize tree inlining hooks.
(remap_save_expr): Adjust prototype so that the declaration
does not require the definition of splay_tree.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@46020 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp/optimize.c')
-rw-r--r-- | gcc/cp/optimize.c | 213 |
1 files changed, 97 insertions, 116 deletions
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index 95d02b70c34..bbc555bf6a9 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -33,6 +33,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "params.h" #include "hashtab.h" #include "debug.h" +#include "tree-inline.h" /* To Do: @@ -99,7 +100,6 @@ static int inlinable_function_p PARAMS ((tree, inline_data *)); static tree remap_decl PARAMS ((tree, inline_data *)); static void remap_block PARAMS ((tree, tree, inline_data *)); static void copy_scope_stmt PARAMS ((tree *, int *, inline_data *)); -static void optimize_inline_calls PARAMS ((tree)); static tree calls_setjmp_r PARAMS ((tree *, int *, void *)); static void update_cloned_parm PARAMS ((tree, tree)); static void dump_function PARAMS ((enum tree_dump_index, tree)); @@ -121,7 +121,7 @@ remap_decl (decl, id) /* We only remap local variables in the current function. */ fn = VARRAY_TOP_TREE (id->fns); - if (!nonstatic_local_decl_p (decl) || DECL_CONTEXT (decl) != fn) + if (! LANG_AUTO_VAR_IN_FN_P (decl, fn)) return NULL_TREE; /* See if we have remapped this declaration. */ @@ -151,8 +151,8 @@ remap_decl (decl, id) copy_body_r, id, NULL); } - if (!DECL_NAME (t) && TREE_TYPE (t) - && ANON_AGGR_TYPE_P (TREE_TYPE ((t)))) + if (! DECL_NAME (t) && TREE_TYPE (t) + && LANG_ANON_AGGR_TYPE_P (TREE_TYPE (t))) { /* For a VAR_DECL of anonymous type, we must also copy the member VAR_DECLS here and rechain the @@ -165,7 +165,8 @@ remap_decl (decl, id) { tree member = remap_decl (TREE_VALUE (src), id); - my_friendly_assert (!TREE_PURPOSE (src), 20010529); + if (TREE_PURPOSE (src)) + abort (); members = tree_cons (NULL, member, members); } DECL_ANON_UNION_ELEMS (t) = nreverse (members); @@ -277,7 +278,8 @@ remap_block (scope_stmt, decls, id) /* Find this block in the table of remapped things. */ n = splay_tree_lookup (id->decl_map, (splay_tree_key) SCOPE_STMT_BLOCK (scope_stmt)); - my_friendly_assert (n != NULL, 19991203); + if (! n) + abort (); SCOPE_STMT_BLOCK (scope_stmt) = (tree) n->value; } } @@ -322,12 +324,14 @@ copy_body_r (tp, walk_subtrees, data) id = (inline_data *) data; fn = VARRAY_TOP_TREE (id->fns); +#if 0 /* All automatic variables should have a DECL_CONTEXT indicating what function they come from. */ if ((TREE_CODE (*tp) == VAR_DECL || TREE_CODE (*tp) == LABEL_DECL) && DECL_NAMESPACE_SCOPE_P (*tp)) - my_friendly_assert (DECL_EXTERNAL (*tp) || TREE_STATIC (*tp), - 19991113); + if (! DECL_EXTERNAL (*tp) && ! TREE_STATIC (*tp)) + abort (); +#endif /* If this is a RETURN_STMT, change it into an EXPR_STMT and a GOTO_STMT with the RET_LABEL as its target. */ @@ -359,26 +363,29 @@ copy_body_r (tp, walk_subtrees, data) variables. We don't want to copy static variables; there's only one of those, no matter how many times we inline the containing function. */ - else if (nonstatic_local_decl_p (*tp) && DECL_CONTEXT (*tp) == fn) + else if (LANG_AUTO_VAR_IN_FN_P (*tp, fn)) { tree new_decl; /* Remap the declaration. */ new_decl = remap_decl (*tp, id); - my_friendly_assert (new_decl != NULL_TREE, 19991203); + if (! new_decl) + abort (); /* Replace this variable with the copy. */ STRIP_TYPE_NOPS (new_decl); *tp = new_decl; } +#if 0 else if (nonstatic_local_decl_p (*tp) && DECL_CONTEXT (*tp) != VARRAY_TREE (id->fns, 0)) - my_friendly_abort (0); + abort (); +#endif else if (TREE_CODE (*tp) == SAVE_EXPR) remap_save_expr (tp, id->decl_map, VARRAY_TREE (id->fns, 0), walk_subtrees); else if (TREE_CODE (*tp) == UNSAVE_EXPR) /* UNSAVE_EXPRs should not be generated until expansion time. */ - my_friendly_abort (19991113); + abort (); /* For a SCOPE_STMT, we must copy the associated block so that we can write out debugging information for the inlined variables. */ else if (TREE_CODE (*tp) == SCOPE_STMT && !id->in_target_cleanup_p) @@ -398,8 +405,7 @@ copy_body_r (tp, walk_subtrees, data) } else if (TREE_CODE (*tp) == MODIFY_EXPR && TREE_OPERAND (*tp, 0) == TREE_OPERAND (*tp, 1) - && nonstatic_local_decl_p (TREE_OPERAND (*tp, 0)) - && DECL_CONTEXT (TREE_OPERAND (*tp, 0)) == fn) + && LANG_AUTO_VAR_IN_FN_P (TREE_OPERAND (*tp, 0), fn)) { /* Some assignments VAR = VAR; don't generate any rtl code and thus don't count as variable modification. Avoid @@ -561,7 +567,7 @@ declare_return_variable (id, use_stmt) tree fn = VARRAY_TOP_TREE (id->fns); tree result = DECL_RESULT (fn); tree var; - int aggregate_return_p; + int need_return_decl = 1; /* We don't need to do anything for functions that don't return anything. */ @@ -571,29 +577,9 @@ declare_return_variable (id, use_stmt) return NULL_TREE; } - /* Figure out whether or not FN returns an aggregate. */ - aggregate_return_p = IS_AGGR_TYPE (TREE_TYPE (result)); - - /* If FN returns an aggregate then the caller will always create the - temporary (using a TARGET_EXPR) and the call will be the - initializing expression for the TARGET_EXPR. If we were just to - create a new VAR_DECL here, then the result of this function - would be copied (bitwise) into the variable initialized by the - TARGET_EXPR. That's incorrect, so we must transform any - references to the RESULT into references to the target. */ - if (aggregate_return_p) - { - my_friendly_assert (VARRAY_ACTIVE_SIZE (id->target_exprs) != 0, - 20000430); - var = TREE_OPERAND (VARRAY_TOP_TREE (id->target_exprs), 0); - my_friendly_assert - (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (var), - TREE_TYPE (result)), - 20000430); - } - /* Otherwise, make an appropriate copy. */ - else - var = copy_decl_for_inlining (result, fn, VARRAY_TREE (id->fns, 0)); + var = LANG_COPY_RES_DECL_FOR_INLINING (result, fn, VARRAY_TREE (id->fns, 0), + id->decl_map, &need_return_decl, + &id->target_exprs); /* Register the VAR_DECL as the equivalent for the RESULT_DECL; that way, when the RESULT_DECL is encountered, it will be @@ -602,29 +588,12 @@ declare_return_variable (id, use_stmt) (splay_tree_key) result, (splay_tree_value) var); - if (DECL_SAVED_FUNCTION_DATA (fn)) - { - tree nrv = DECL_SAVED_FUNCTION_DATA (fn)->x_return_value; - if (nrv) - { - /* We have a named return value; copy the name and source - position so we can get reasonable debugging information, and - register the return variable as its equivalent. */ - DECL_NAME (var) = DECL_NAME (nrv); - DECL_SOURCE_FILE (var) = DECL_SOURCE_FILE (nrv); - DECL_SOURCE_LINE (var) = DECL_SOURCE_LINE (nrv); - splay_tree_insert (id->decl_map, - (splay_tree_key) nrv, - (splay_tree_value) var); - } - } - /* Build the USE_STMT. */ *use_stmt = build_stmt (EXPR_STMT, var); /* Build the declaration statement if FN does not return an aggregate. */ - if (!aggregate_return_p) + if (need_return_decl) return build_stmt (DECL_STMT, var); /* If FN does return an aggregate, there's no need to declare the return variable; we're using a variable in our caller's frame. */ @@ -656,12 +625,11 @@ inlinable_function_p (fn, id) it. */ else if (!DECL_INLINE (fn)) ; - /* We can't inline varargs functions. */ - else if (varargs_function_p (fn)) - ; - /* We can't inline functions that are too big. - * Only allow a single function to eat up half of our budget. */ - else if (DECL_NUM_STMTS (fn) * INSNS_PER_STMT > MAX_INLINE_INSNS / 2) + /* We can't inline functions that are too big. Only allow a single + function to eat up half of our budget. Make special allowance + for extern inline functions, though. */ + else if (! LANG_DISREGARD_INLINE_LIMITS (fn) + && DECL_NUM_STMTS (fn) * INSNS_PER_STMT > MAX_INLINE_INSNS / 2) ; /* All is well. We can inline this function. Traditionally, GCC has refused to inline functions using alloca, or functions whose @@ -675,27 +643,26 @@ inlinable_function_p (fn, id) /* 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 too much inlining any more and thus halve the acceptable size. */ - if ((DECL_NUM_STMTS (fn) + id->inlined_stmts) * INSNS_PER_STMT - > MAX_INLINE_INSNS + risk too much inlining any more and thus halve the acceptable + size. */ + if (! LANG_DISREGARD_INLINE_LIMITS (fn) + && ((DECL_NUM_STMTS (fn) + id->inlined_stmts) * INSNS_PER_STMT + > MAX_INLINE_INSNS) && DECL_NUM_STMTS (fn) * INSNS_PER_STMT > MAX_INLINE_INSNS / 4) inlinable = 0; - /* We can inline a template instantiation only if it's fully - instantiated. */ - if (inlinable - && DECL_TEMPLATE_INFO (fn) - && TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn))) - { - fn = instantiate_decl (fn, /*defer_ok=*/0); - inlinable = !TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn)); - } - + if (inlinable && LANG_CANNOT_INLINE_TREE_FN (&fn)) + inlinable = 0; + /* If we don't have the function body available, we can't inline it. */ if (!DECL_SAVED_TREE (fn)) inlinable = 0; + /* Check again, language hooks may have modified it. */ + if (! inlinable || DECL_UNINLINABLE (fn)) + return 0; + /* Don't do recursive inlining, either. We don't record this in DECL_UNINLINABLE; we may be able to inline this function later. */ if (inlinable) @@ -706,7 +673,7 @@ inlinable_function_p (fn, id) if (VARRAY_TREE (id->fns, i) == fn) return 0; - if (inlinable && DECL_LANG_SPECIFIC (fn) && DECL_INLINED_FNS (fn)) + if (inlinable && DECL_INLINED_FNS (fn)) { int j; tree inlined_fns = DECL_INLINED_FNS (fn); @@ -808,7 +775,7 @@ expand_call_inline (tp, walk_subtrees, data) for the return statements within the function to jump to. The type of the statement expression is the return type of the function call. */ - expr = build_min (STMT_EXPR, TREE_TYPE (TREE_TYPE (fn)), NULL_TREE); + expr = build1 (STMT_EXPR, TREE_TYPE (TREE_TYPE (fn)), NULL_TREE); /* Local declarations will be replaced by their equivalents in this map. */ @@ -832,7 +799,7 @@ expand_call_inline (tp, walk_subtrees, data) /* Record the function we are about to inline if optimize_function has not been called on it yet and we don't have it in the list. */ - if (DECL_LANG_SPECIFIC (fn) && !DECL_INLINED_FNS (fn)) + if (! DECL_INLINED_FNS (fn)) { int i; @@ -878,9 +845,9 @@ expand_call_inline (tp, walk_subtrees, data) /* Close the block for the parameters. */ scope_stmt = build_stmt (SCOPE_STMT, DECL_INITIAL (fn)); SCOPE_NO_CLEANUPS_P (scope_stmt) = 1; - my_friendly_assert (DECL_INITIAL (fn) - && TREE_CODE (DECL_INITIAL (fn)) == BLOCK, - 19991203); + if (! DECL_INITIAL (fn) + || TREE_CODE (DECL_INITIAL (fn)) != BLOCK) + abort (); remap_block (scope_stmt, NULL_TREE, id); STMT_EXPR_STMT (expr) = chainon (STMT_EXPR_STMT (expr), scope_stmt); @@ -957,13 +924,12 @@ expand_calls_inline (tp, id) /* Expand calls to inline functions in the body of FN. */ -static void +void optimize_inline_calls (fn) tree fn; { inline_data id; tree prev_fn; - struct saved_scope *s; /* Clear out ID. */ memset (&id, 0, sizeof (id)); @@ -978,12 +944,8 @@ optimize_inline_calls (fn) VARRAY_PUSH_TREE (id.fns, current_function_decl); prev_fn = current_function_decl; } - for (s = scope_chain; s; s = s->prev) - if (s->function_decl && s->function_decl != prev_fn) - { - VARRAY_PUSH_TREE (id.fns, s->function_decl); - prev_fn = s->function_decl; - } + + prev_fn = LANG_ADD_PENDING_FN_DECLS (&id.fns, prev_fn); /* Create the stack of TARGET_EXPRs. */ VARRAY_TREE_INIT (id.target_exprs, 32, "target_exprs"); @@ -1014,8 +976,6 @@ optimize_inline_calls (fn) DECL_INLINED_FNS (fn) = ifn; } VARRAY_FREE (id.inlined_fns); - - dump_function (TDI_inlined, fn); } /* Optimize the body of FN. */ @@ -1043,7 +1003,11 @@ optimize_function (fn) optimization, (c) virtual functions are rarely inlineable, and (d) ASM_OUTPUT_MI_THUNK is there to DTRT anyway. */ && !DECL_THUNK_P (fn)) - optimize_inline_calls (fn); + { + optimize_inline_calls (fn); + + dump_function (TDI_inlined, fn); + } /* Undo the call to ggc_push_context above. */ --function_depth; @@ -1106,6 +1070,38 @@ update_cloned_parm (parm, cloned_parm) DECL_SOURCE_LINE (cloned_parm) = DECL_SOURCE_LINE (parm); } +/* FN is a function that has a complete body, and CLONE is a function + whose body is to be set to a copy of FN, mapping argument + declarations according to the ARG_MAP splay_tree. */ + +void +clone_body (clone, fn, arg_map) + tree clone, fn; + void *arg_map; +{ + inline_data id; + + /* Clone the body, as if we were making an inline call. But, remap + the parameters in the callee to the parameters of caller. If + there's an in-charge parameter, map it to an appropriate + constant. */ + memset (&id, 0, sizeof (id)); + VARRAY_TREE_INIT (id.fns, 2, "fns"); + VARRAY_PUSH_TREE (id.fns, clone); + VARRAY_PUSH_TREE (id.fns, fn); + id.decl_map = (splay_tree)arg_map; + + /* Cloning is treated slightly differently from inlining. Set + CLONING_P so that it's clear which operation we're performing. */ + id.cloning_p = true; + + /* Actually copy the body. */ + TREE_CHAIN (DECL_SAVED_TREE (clone)) = copy_body (&id); + + /* Clean up. */ + VARRAY_FREE (id.fns); +} + /* FN is a function that has a complete body. Clone the body as necessary. Returns non-zero if there's no longer any need to process the main body. */ @@ -1114,7 +1110,6 @@ int maybe_clone_body (fn) tree fn; { - inline_data id; tree clone; int first = 1; @@ -1135,6 +1130,7 @@ maybe_clone_body (fn) tree parm; tree clone_parm; int parmno; + splay_tree decl_map; /* Update CLONE's source position information to match FN's. */ DECL_SOURCE_FILE (clone) = DECL_SOURCE_FILE (fn); @@ -1178,22 +1174,8 @@ maybe_clone_body (fn) push_to_top_level (); start_function (NULL_TREE, clone, NULL_TREE, SF_PRE_PARSED); - /* Just clone the body, as if we were making an inline call. - But, remap the parameters in the callee to the parameters of - caller. If there's an in-charge parameter, map it to an - appropriate constant. */ - memset (&id, 0, sizeof (id)); - 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, - NULL, NULL); + decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL); for (parmno = 0, parm = DECL_ARGUMENTS (fn), clone_parm = DECL_ARGUMENTS (clone); @@ -1206,7 +1188,7 @@ maybe_clone_body (fn) { tree in_charge; in_charge = in_charge_arg_for_name (DECL_NAME (clone)); - splay_tree_insert (id.decl_map, + splay_tree_insert (decl_map, (splay_tree_key) parm, (splay_tree_value) in_charge); } @@ -1219,7 +1201,7 @@ maybe_clone_body (fn) if (DECL_HAS_VTT_PARM_P (clone)) { DECL_ABSTRACT_ORIGIN (clone_parm) = parm; - splay_tree_insert (id.decl_map, + splay_tree_insert (decl_map, (splay_tree_key) parm, (splay_tree_value) clone_parm); clone_parm = TREE_CHAIN (clone_parm); @@ -1227,7 +1209,7 @@ maybe_clone_body (fn) /* Otherwise, map the VTT parameter to `NULL'. */ else { - splay_tree_insert (id.decl_map, + splay_tree_insert (decl_map, (splay_tree_key) parm, (splay_tree_value) null_pointer_node); } @@ -1236,23 +1218,22 @@ maybe_clone_body (fn) function. */ else { - splay_tree_insert (id.decl_map, + splay_tree_insert (decl_map, (splay_tree_key) parm, (splay_tree_value) clone_parm); clone_parm = TREE_CHAIN (clone_parm); } } - /* Actually copy the body. */ - TREE_CHAIN (DECL_SAVED_TREE (clone)) = copy_body (&id); + /* Clone the body. */ + clone_body (clone, fn, decl_map); /* There are as many statements in the clone as in the original. */ DECL_NUM_STMTS (clone) = DECL_NUM_STMTS (fn); /* Clean up. */ - splay_tree_delete (id.decl_map); - VARRAY_FREE (id.fns); + splay_tree_delete (decl_map); /* Now, expand this function into RTL, if appropriate. */ finish_function (0); |