tree-inline.c revision 90075
190075Sobrien/* Control and data flow functions for trees. 290075Sobrien Copyright 2001, 2002 Free Software Foundation, Inc. 390075Sobrien Contributed by Alexandre Oliva <aoliva@redhat.com> 490075Sobrien 590075SobrienThis file is part of GNU CC. 690075Sobrien 790075SobrienGNU CC is free software; you can redistribute it and/or modify 890075Sobrienit under the terms of the GNU General Public License as published by 990075Sobrienthe Free Software Foundation; either version 2, or (at your option) 1090075Sobrienany later version. 1190075Sobrien 1290075SobrienGNU CC is distributed in the hope that it will be useful, 1390075Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of 1490075SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1590075SobrienGNU General Public License for more details. 1690075Sobrien 1790075SobrienYou should have received a copy of the GNU General Public License 1890075Sobrienalong with GNU CC; see the file COPYING. If not, write to 1990075Sobrienthe Free Software Foundation, 59 Temple Place - Suite 330, 2090075SobrienBoston, MA 02111-1307, USA. */ 2190075Sobrien 2290075Sobrien#include "config.h" 2390075Sobrien#include "system.h" 2490075Sobrien#include "toplev.h" 2590075Sobrien#include "tree.h" 2690075Sobrien#include "tree-inline.h" 2790075Sobrien#include "rtl.h" 2890075Sobrien#include "expr.h" 2990075Sobrien#include "flags.h" 3090075Sobrien#include "params.h" 3190075Sobrien#include "input.h" 3290075Sobrien#include "insn-config.h" 3390075Sobrien#include "integrate.h" 3490075Sobrien#include "varray.h" 3590075Sobrien#include "hashtab.h" 3690075Sobrien#include "splay-tree.h" 3790075Sobrien#include "langhooks.h" 3890075Sobrien 3990075Sobrien/* This should be eventually be generalized to other languages, but 4090075Sobrien this would require a shared function-as-trees infrastructure. */ 4190075Sobrien#include "c-common.h" 4290075Sobrien 4390075Sobrien/* 0 if we should not perform inlining. 4490075Sobrien 1 if we should expand functions calls inline at the tree level. 4590075Sobrien 2 if we should consider *all* functions to be inline 4690075Sobrien candidates. */ 4790075Sobrien 4890075Sobrienint flag_inline_trees = 0; 4990075Sobrien 5090075Sobrien/* To Do: 5190075Sobrien 5290075Sobrien o In order to make inlining-on-trees work, we pessimized 5390075Sobrien function-local static constants. In particular, they are now 5490075Sobrien always output, even when not addressed. Fix this by treating 5590075Sobrien function-local static constants just like global static 5690075Sobrien constants; the back-end already knows not to output them if they 5790075Sobrien are not needed. 5890075Sobrien 5990075Sobrien o Provide heuristics to clamp inlining of recursive template 6090075Sobrien calls? */ 6190075Sobrien 6290075Sobrien/* Data required for function inlining. */ 6390075Sobrien 6490075Sobrientypedef struct inline_data 6590075Sobrien{ 6690075Sobrien /* A stack of the functions we are inlining. For example, if we are 6790075Sobrien compiling `f', which calls `g', which calls `h', and we are 6890075Sobrien inlining the body of `h', the stack will contain, `h', followed 6990075Sobrien by `g', followed by `f'. The first few elements of the stack may 7090075Sobrien contain other functions that we know we should not recurse into, 7190075Sobrien even though they are not directly being inlined. */ 7290075Sobrien varray_type fns; 7390075Sobrien /* The index of the first element of FNS that really represents an 7490075Sobrien inlined function. */ 7590075Sobrien unsigned first_inlined_fn; 7690075Sobrien /* The label to jump to when a return statement is encountered. If 7790075Sobrien this value is NULL, then return statements will simply be 7890075Sobrien remapped as return statements, rather than as jumps. */ 7990075Sobrien tree ret_label; 8090075Sobrien /* The map from local declarations in the inlined function to 8190075Sobrien equivalents in the function into which it is being inlined. */ 8290075Sobrien splay_tree decl_map; 8390075Sobrien /* Nonzero if we are currently within the cleanup for a 8490075Sobrien TARGET_EXPR. */ 8590075Sobrien int in_target_cleanup_p; 8690075Sobrien /* A stack of the TARGET_EXPRs that we are currently processing. */ 8790075Sobrien varray_type target_exprs; 8890075Sobrien /* A list of the functions current function has inlined. */ 8990075Sobrien varray_type inlined_fns; 9090075Sobrien /* The approximate number of statements we have inlined in the 9190075Sobrien current call stack. */ 9290075Sobrien int inlined_stmts; 9390075Sobrien /* We use the same mechanism to build clones that we do to perform 9490075Sobrien inlining. However, there are a few places where we need to 9590075Sobrien distinguish between those two situations. This flag is true if 9690075Sobrien we are cloning, rather than inlining. */ 9790075Sobrien bool cloning_p; 9890075Sobrien /* Hash table used to prevent walk_tree from visiting the same node 9990075Sobrien umpteen million times. */ 10090075Sobrien htab_t tree_pruner; 10190075Sobrien} inline_data; 10290075Sobrien 10390075Sobrien/* Prototypes. */ 10490075Sobrien 10590075Sobrienstatic tree initialize_inlined_parameters PARAMS ((inline_data *, tree, tree)); 10690075Sobrienstatic tree declare_return_variable PARAMS ((inline_data *, tree *)); 10790075Sobrienstatic tree copy_body_r PARAMS ((tree *, int *, void *)); 10890075Sobrienstatic tree copy_body PARAMS ((inline_data *)); 10990075Sobrienstatic tree expand_call_inline PARAMS ((tree *, int *, void *)); 11090075Sobrienstatic void expand_calls_inline PARAMS ((tree *, inline_data *)); 11190075Sobrienstatic int inlinable_function_p PARAMS ((tree, inline_data *)); 11290075Sobrienstatic tree remap_decl PARAMS ((tree, inline_data *)); 11390075Sobrienstatic void remap_block PARAMS ((tree, tree, inline_data *)); 11490075Sobrienstatic void copy_scope_stmt PARAMS ((tree *, int *, inline_data *)); 11590075Sobrien 11690075Sobrien/* The approximate number of instructions per statement. This number 11790075Sobrien need not be particularly accurate; it is used only to make 11890075Sobrien decisions about when a function is too big to inline. */ 11990075Sobrien#define INSNS_PER_STMT (10) 12090075Sobrien 12190075Sobrien/* Remap DECL during the copying of the BLOCK tree for the function. */ 12290075Sobrien 12390075Sobrienstatic tree 12490075Sobrienremap_decl (decl, id) 12590075Sobrien tree decl; 12690075Sobrien inline_data *id; 12790075Sobrien{ 12890075Sobrien splay_tree_node n; 12990075Sobrien tree fn; 13090075Sobrien 13190075Sobrien /* We only remap local variables in the current function. */ 13290075Sobrien fn = VARRAY_TOP_TREE (id->fns); 13390075Sobrien if (! (*lang_hooks.tree_inlining.auto_var_in_fn_p) (decl, fn)) 13490075Sobrien return NULL_TREE; 13590075Sobrien 13690075Sobrien /* See if we have remapped this declaration. */ 13790075Sobrien n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl); 13890075Sobrien /* If we didn't already have an equivalent for this declaration, 13990075Sobrien create one now. */ 14090075Sobrien if (!n) 14190075Sobrien { 14290075Sobrien tree t; 14390075Sobrien 14490075Sobrien /* Make a copy of the variable or label. */ 14590075Sobrien t = copy_decl_for_inlining (decl, fn, 14690075Sobrien VARRAY_TREE (id->fns, 0)); 14790075Sobrien 14890075Sobrien /* The decl T could be a dynamic array or other variable size type, 14990075Sobrien in which case some fields need to be remapped because they may 15090075Sobrien contain SAVE_EXPRs. */ 15190075Sobrien if (TREE_TYPE (t) && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE 15290075Sobrien && TYPE_DOMAIN (TREE_TYPE (t))) 15390075Sobrien { 15490075Sobrien TREE_TYPE (t) = copy_node (TREE_TYPE (t)); 15590075Sobrien TYPE_DOMAIN (TREE_TYPE (t)) 15690075Sobrien = copy_node (TYPE_DOMAIN (TREE_TYPE (t))); 15790075Sobrien walk_tree (&TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (t))), 15890075Sobrien copy_body_r, id, NULL); 15990075Sobrien } 16090075Sobrien 16190075Sobrien if (! DECL_NAME (t) && TREE_TYPE (t) 16290075Sobrien && (*lang_hooks.tree_inlining.anon_aggr_type_p) (TREE_TYPE (t))) 16390075Sobrien { 16490075Sobrien /* For a VAR_DECL of anonymous type, we must also copy the 16590075Sobrien member VAR_DECLS here and rechain the 16690075Sobrien DECL_ANON_UNION_ELEMS. */ 16790075Sobrien tree members = NULL; 16890075Sobrien tree src; 16990075Sobrien 17090075Sobrien for (src = DECL_ANON_UNION_ELEMS (t); src; 17190075Sobrien src = TREE_CHAIN (src)) 17290075Sobrien { 17390075Sobrien tree member = remap_decl (TREE_VALUE (src), id); 17490075Sobrien 17590075Sobrien if (TREE_PURPOSE (src)) 17690075Sobrien abort (); 17790075Sobrien members = tree_cons (NULL, member, members); 17890075Sobrien } 17990075Sobrien DECL_ANON_UNION_ELEMS (t) = nreverse (members); 18090075Sobrien } 18190075Sobrien 18290075Sobrien /* Remember it, so that if we encounter this local entity 18390075Sobrien again we can reuse this copy. */ 18490075Sobrien n = splay_tree_insert (id->decl_map, 18590075Sobrien (splay_tree_key) decl, 18690075Sobrien (splay_tree_value) t); 18790075Sobrien } 18890075Sobrien 18990075Sobrien return (tree) n->value; 19090075Sobrien} 19190075Sobrien 19290075Sobrien/* Copy the SCOPE_STMT_BLOCK associated with SCOPE_STMT to contain 19390075Sobrien remapped versions of the variables therein. And hook the new block 19490075Sobrien into the block-tree. If non-NULL, the DECLS are declarations to 19590075Sobrien add to use instead of the BLOCK_VARS in the old block. */ 19690075Sobrien 19790075Sobrienstatic void 19890075Sobrienremap_block (scope_stmt, decls, id) 19990075Sobrien tree scope_stmt; 20090075Sobrien tree decls; 20190075Sobrien inline_data *id; 20290075Sobrien{ 20390075Sobrien /* We cannot do this in the cleanup for a TARGET_EXPR since we do 20490075Sobrien not know whether or not expand_expr will actually write out the 20590075Sobrien code we put there. If it does not, then we'll have more BLOCKs 20690075Sobrien than block-notes, and things will go awry. At some point, we 20790075Sobrien should make the back-end handle BLOCK notes in a tidier way, 20890075Sobrien without requiring a strict correspondence to the block-tree; then 20990075Sobrien this check can go. */ 21090075Sobrien if (id->in_target_cleanup_p) 21190075Sobrien { 21290075Sobrien SCOPE_STMT_BLOCK (scope_stmt) = NULL_TREE; 21390075Sobrien return; 21490075Sobrien } 21590075Sobrien 21690075Sobrien /* If this is the beginning of a scope, remap the associated BLOCK. */ 21790075Sobrien if (SCOPE_BEGIN_P (scope_stmt) && SCOPE_STMT_BLOCK (scope_stmt)) 21890075Sobrien { 21990075Sobrien tree old_block; 22090075Sobrien tree new_block; 22190075Sobrien tree old_var; 22290075Sobrien tree fn; 22390075Sobrien 22490075Sobrien /* Make the new block. */ 22590075Sobrien old_block = SCOPE_STMT_BLOCK (scope_stmt); 22690075Sobrien new_block = make_node (BLOCK); 22790075Sobrien TREE_USED (new_block) = TREE_USED (old_block); 22890075Sobrien BLOCK_ABSTRACT_ORIGIN (new_block) = old_block; 22990075Sobrien SCOPE_STMT_BLOCK (scope_stmt) = new_block; 23090075Sobrien 23190075Sobrien /* Remap its variables. */ 23290075Sobrien for (old_var = decls ? decls : BLOCK_VARS (old_block); 23390075Sobrien old_var; 23490075Sobrien old_var = TREE_CHAIN (old_var)) 23590075Sobrien { 23690075Sobrien tree new_var; 23790075Sobrien 23890075Sobrien /* Remap the variable. */ 23990075Sobrien new_var = remap_decl (old_var, id); 24090075Sobrien /* If we didn't remap this variable, so we can't mess with 24190075Sobrien its TREE_CHAIN. If we remapped this variable to 24290075Sobrien something other than a declaration (say, if we mapped it 24390075Sobrien to a constant), then we must similarly omit any mention 24490075Sobrien of it here. */ 24590075Sobrien if (!new_var || !DECL_P (new_var)) 24690075Sobrien ; 24790075Sobrien else 24890075Sobrien { 24990075Sobrien TREE_CHAIN (new_var) = BLOCK_VARS (new_block); 25090075Sobrien BLOCK_VARS (new_block) = new_var; 25190075Sobrien } 25290075Sobrien } 25390075Sobrien /* We put the BLOCK_VARS in reverse order; fix that now. */ 25490075Sobrien BLOCK_VARS (new_block) = nreverse (BLOCK_VARS (new_block)); 25590075Sobrien fn = VARRAY_TREE (id->fns, 0); 25690075Sobrien if (id->cloning_p) 25790075Sobrien /* We're building a clone; DECL_INITIAL is still 25890075Sobrien error_mark_node, and current_binding_level is the parm 25990075Sobrien binding level. */ 26090075Sobrien insert_block (new_block); 26190075Sobrien else 26290075Sobrien { 26390075Sobrien /* Attach this new block after the DECL_INITIAL block for the 26490075Sobrien function into which this block is being inlined. In 26590075Sobrien rest_of_compilation we will straighten out the BLOCK tree. */ 26690075Sobrien tree *first_block; 26790075Sobrien if (DECL_INITIAL (fn)) 26890075Sobrien first_block = &BLOCK_CHAIN (DECL_INITIAL (fn)); 26990075Sobrien else 27090075Sobrien first_block = &DECL_INITIAL (fn); 27190075Sobrien BLOCK_CHAIN (new_block) = *first_block; 27290075Sobrien *first_block = new_block; 27390075Sobrien } 27490075Sobrien /* Remember the remapped block. */ 27590075Sobrien splay_tree_insert (id->decl_map, 27690075Sobrien (splay_tree_key) old_block, 27790075Sobrien (splay_tree_value) new_block); 27890075Sobrien } 27990075Sobrien /* If this is the end of a scope, set the SCOPE_STMT_BLOCK to be the 28090075Sobrien remapped block. */ 28190075Sobrien else if (SCOPE_END_P (scope_stmt) && SCOPE_STMT_BLOCK (scope_stmt)) 28290075Sobrien { 28390075Sobrien splay_tree_node n; 28490075Sobrien 28590075Sobrien /* Find this block in the table of remapped things. */ 28690075Sobrien n = splay_tree_lookup (id->decl_map, 28790075Sobrien (splay_tree_key) SCOPE_STMT_BLOCK (scope_stmt)); 28890075Sobrien if (! n) 28990075Sobrien abort (); 29090075Sobrien SCOPE_STMT_BLOCK (scope_stmt) = (tree) n->value; 29190075Sobrien } 29290075Sobrien} 29390075Sobrien 29490075Sobrien/* Copy the SCOPE_STMT pointed to by TP. */ 29590075Sobrien 29690075Sobrienstatic void 29790075Sobriencopy_scope_stmt (tp, walk_subtrees, id) 29890075Sobrien tree *tp; 29990075Sobrien int *walk_subtrees; 30090075Sobrien inline_data *id; 30190075Sobrien{ 30290075Sobrien tree block; 30390075Sobrien 30490075Sobrien /* Remember whether or not this statement was nullified. When 30590075Sobrien making a copy, copy_tree_r always sets SCOPE_NULLIFIED_P (and 30690075Sobrien doesn't copy the SCOPE_STMT_BLOCK) to free callers from having to 30790075Sobrien deal with copying BLOCKs if they do not wish to do so. */ 30890075Sobrien block = SCOPE_STMT_BLOCK (*tp); 30990075Sobrien /* Copy (and replace) the statement. */ 31090075Sobrien copy_tree_r (tp, walk_subtrees, NULL); 31190075Sobrien /* Restore the SCOPE_STMT_BLOCK. */ 31290075Sobrien SCOPE_STMT_BLOCK (*tp) = block; 31390075Sobrien 31490075Sobrien /* Remap the associated block. */ 31590075Sobrien remap_block (*tp, NULL_TREE, id); 31690075Sobrien} 31790075Sobrien 31890075Sobrien/* Called from copy_body via walk_tree. DATA is really an 31990075Sobrien `inline_data *'. */ 32090075Sobrien 32190075Sobrienstatic tree 32290075Sobriencopy_body_r (tp, walk_subtrees, data) 32390075Sobrien tree *tp; 32490075Sobrien int *walk_subtrees; 32590075Sobrien void *data; 32690075Sobrien{ 32790075Sobrien inline_data* id; 32890075Sobrien tree fn; 32990075Sobrien 33090075Sobrien /* Set up. */ 33190075Sobrien id = (inline_data *) data; 33290075Sobrien fn = VARRAY_TOP_TREE (id->fns); 33390075Sobrien 33490075Sobrien#if 0 33590075Sobrien /* All automatic variables should have a DECL_CONTEXT indicating 33690075Sobrien what function they come from. */ 33790075Sobrien if ((TREE_CODE (*tp) == VAR_DECL || TREE_CODE (*tp) == LABEL_DECL) 33890075Sobrien && DECL_NAMESPACE_SCOPE_P (*tp)) 33990075Sobrien if (! DECL_EXTERNAL (*tp) && ! TREE_STATIC (*tp)) 34090075Sobrien abort (); 34190075Sobrien#endif 34290075Sobrien 34390075Sobrien /* If this is a RETURN_STMT, change it into an EXPR_STMT and a 34490075Sobrien GOTO_STMT with the RET_LABEL as its target. */ 34590075Sobrien if (TREE_CODE (*tp) == RETURN_STMT && id->ret_label) 34690075Sobrien { 34790075Sobrien tree return_stmt = *tp; 34890075Sobrien tree goto_stmt; 34990075Sobrien 35090075Sobrien /* Build the GOTO_STMT. */ 35190075Sobrien goto_stmt = build_stmt (GOTO_STMT, id->ret_label); 35290075Sobrien TREE_CHAIN (goto_stmt) = TREE_CHAIN (return_stmt); 35390075Sobrien GOTO_FAKE_P (goto_stmt) = 1; 35490075Sobrien 35590075Sobrien /* If we're returning something, just turn that into an 35690075Sobrien assignment into the equivalent of the original 35790075Sobrien RESULT_DECL. */ 35890075Sobrien if (RETURN_EXPR (return_stmt)) 35990075Sobrien { 36090075Sobrien *tp = build_stmt (EXPR_STMT, 36190075Sobrien RETURN_EXPR (return_stmt)); 36290075Sobrien STMT_IS_FULL_EXPR_P (*tp) = 1; 36390075Sobrien /* And then jump to the end of the function. */ 36490075Sobrien TREE_CHAIN (*tp) = goto_stmt; 36590075Sobrien } 36690075Sobrien /* If we're not returning anything just do the jump. */ 36790075Sobrien else 36890075Sobrien *tp = goto_stmt; 36990075Sobrien } 37090075Sobrien /* Local variables and labels need to be replaced by equivalent 37190075Sobrien variables. We don't want to copy static variables; there's only 37290075Sobrien one of those, no matter how many times we inline the containing 37390075Sobrien function. */ 37490075Sobrien else if ((*lang_hooks.tree_inlining.auto_var_in_fn_p) (*tp, fn)) 37590075Sobrien { 37690075Sobrien tree new_decl; 37790075Sobrien 37890075Sobrien /* Remap the declaration. */ 37990075Sobrien new_decl = remap_decl (*tp, id); 38090075Sobrien if (! new_decl) 38190075Sobrien abort (); 38290075Sobrien /* Replace this variable with the copy. */ 38390075Sobrien STRIP_TYPE_NOPS (new_decl); 38490075Sobrien *tp = new_decl; 38590075Sobrien } 38690075Sobrien#if 0 38790075Sobrien else if (nonstatic_local_decl_p (*tp) 38890075Sobrien && DECL_CONTEXT (*tp) != VARRAY_TREE (id->fns, 0)) 38990075Sobrien abort (); 39090075Sobrien#endif 39190075Sobrien else if (TREE_CODE (*tp) == SAVE_EXPR) 39290075Sobrien remap_save_expr (tp, id->decl_map, VARRAY_TREE (id->fns, 0), 39390075Sobrien walk_subtrees); 39490075Sobrien else if (TREE_CODE (*tp) == UNSAVE_EXPR) 39590075Sobrien /* UNSAVE_EXPRs should not be generated until expansion time. */ 39690075Sobrien abort (); 39790075Sobrien /* For a SCOPE_STMT, we must copy the associated block so that we 39890075Sobrien can write out debugging information for the inlined variables. */ 39990075Sobrien else if (TREE_CODE (*tp) == SCOPE_STMT && !id->in_target_cleanup_p) 40090075Sobrien copy_scope_stmt (tp, walk_subtrees, id); 40190075Sobrien /* Otherwise, just copy the node. Note that copy_tree_r already 40290075Sobrien knows not to copy VAR_DECLs, etc., so this is safe. */ 40390075Sobrien else 40490075Sobrien { 40590075Sobrien copy_tree_r (tp, walk_subtrees, NULL); 40690075Sobrien 40790075Sobrien /* The copied TARGET_EXPR has never been expanded, even if the 40890075Sobrien original node was expanded already. */ 40990075Sobrien if (TREE_CODE (*tp) == TARGET_EXPR && TREE_OPERAND (*tp, 3)) 41090075Sobrien { 41190075Sobrien TREE_OPERAND (*tp, 1) = TREE_OPERAND (*tp, 3); 41290075Sobrien TREE_OPERAND (*tp, 3) = NULL_TREE; 41390075Sobrien } 41490075Sobrien else if (TREE_CODE (*tp) == MODIFY_EXPR 41590075Sobrien && TREE_OPERAND (*tp, 0) == TREE_OPERAND (*tp, 1) 41690075Sobrien && ((*lang_hooks.tree_inlining.auto_var_in_fn_p) 41790075Sobrien (TREE_OPERAND (*tp, 0), fn))) 41890075Sobrien { 41990075Sobrien /* Some assignments VAR = VAR; don't generate any rtl code 42090075Sobrien and thus don't count as variable modification. Avoid 42190075Sobrien keeping bogosities like 0 = 0. */ 42290075Sobrien tree decl = TREE_OPERAND (*tp, 0), value; 42390075Sobrien splay_tree_node n; 42490075Sobrien 42590075Sobrien n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl); 42690075Sobrien if (n) 42790075Sobrien { 42890075Sobrien value = (tree) n->value; 42990075Sobrien STRIP_TYPE_NOPS (value); 43090075Sobrien if (TREE_CONSTANT (value) || TREE_READONLY_DECL_P (value)) 43190075Sobrien *tp = value; 43290075Sobrien } 43390075Sobrien } 43490075Sobrien } 43590075Sobrien 43690075Sobrien /* Keep iterating. */ 43790075Sobrien return NULL_TREE; 43890075Sobrien} 43990075Sobrien 44090075Sobrien/* Make a copy of the body of FN so that it can be inserted inline in 44190075Sobrien another function. */ 44290075Sobrien 44390075Sobrienstatic tree 44490075Sobriencopy_body (id) 44590075Sobrien inline_data *id; 44690075Sobrien{ 44790075Sobrien tree body; 44890075Sobrien 44990075Sobrien body = DECL_SAVED_TREE (VARRAY_TOP_TREE (id->fns)); 45090075Sobrien walk_tree (&body, copy_body_r, id, NULL); 45190075Sobrien 45290075Sobrien return body; 45390075Sobrien} 45490075Sobrien 45590075Sobrien/* Generate code to initialize the parameters of the function at the 45690075Sobrien top of the stack in ID from the ARGS (presented as a TREE_LIST). */ 45790075Sobrien 45890075Sobrienstatic tree 45990075Sobrieninitialize_inlined_parameters (id, args, fn) 46090075Sobrien inline_data *id; 46190075Sobrien tree args; 46290075Sobrien tree fn; 46390075Sobrien{ 46490075Sobrien tree init_stmts; 46590075Sobrien tree parms; 46690075Sobrien tree a; 46790075Sobrien tree p; 46890075Sobrien 46990075Sobrien /* Figure out what the parameters are. */ 47090075Sobrien parms = DECL_ARGUMENTS (fn); 47190075Sobrien 47290075Sobrien /* Start with no initializations whatsoever. */ 47390075Sobrien init_stmts = NULL_TREE; 47490075Sobrien 47590075Sobrien /* Loop through the parameter declarations, replacing each with an 47690075Sobrien equivalent VAR_DECL, appropriately initialized. */ 47790075Sobrien for (p = parms, a = args; p; 47890075Sobrien a = a ? TREE_CHAIN (a) : a, p = TREE_CHAIN (p)) 47990075Sobrien { 48090075Sobrien tree init_stmt; 48190075Sobrien tree var; 48290075Sobrien tree value; 48390075Sobrien 48490075Sobrien /* Find the initializer. */ 48590075Sobrien value = a ? TREE_VALUE (a) : NULL_TREE; 48690075Sobrien 48790075Sobrien /* If the parameter is never assigned to, we may not need to 48890075Sobrien create a new variable here at all. Instead, we may be able 48990075Sobrien to just use the argument value. */ 49090075Sobrien if (TREE_READONLY (p) 49190075Sobrien && !TREE_ADDRESSABLE (p) 49290075Sobrien && value && !TREE_SIDE_EFFECTS (value)) 49390075Sobrien { 49490075Sobrien /* Simplify the value, if possible. */ 49590075Sobrien value = fold (DECL_P (value) ? decl_constant_value (value) : value); 49690075Sobrien 49790075Sobrien /* We can't risk substituting complex expressions. They 49890075Sobrien might contain variables that will be assigned to later. 49990075Sobrien Theoretically, we could check the expression to see if 50090075Sobrien all of the variables that determine its value are 50190075Sobrien read-only, but we don't bother. */ 50290075Sobrien if (TREE_CONSTANT (value) || TREE_READONLY_DECL_P (value)) 50390075Sobrien { 50490075Sobrien /* If this is a declaration, wrap it a NOP_EXPR so that 50590075Sobrien we don't try to put the VALUE on the list of 50690075Sobrien BLOCK_VARS. */ 50790075Sobrien if (DECL_P (value)) 50890075Sobrien value = build1 (NOP_EXPR, TREE_TYPE (value), value); 50990075Sobrien 51090075Sobrien splay_tree_insert (id->decl_map, 51190075Sobrien (splay_tree_key) p, 51290075Sobrien (splay_tree_value) value); 51390075Sobrien continue; 51490075Sobrien } 51590075Sobrien } 51690075Sobrien 51790075Sobrien /* Make an equivalent VAR_DECL. */ 51890075Sobrien var = copy_decl_for_inlining (p, fn, VARRAY_TREE (id->fns, 0)); 51990075Sobrien /* Register the VAR_DECL as the equivalent for the PARM_DECL; 52090075Sobrien that way, when the PARM_DECL is encountered, it will be 52190075Sobrien automatically replaced by the VAR_DECL. */ 52290075Sobrien splay_tree_insert (id->decl_map, 52390075Sobrien (splay_tree_key) p, 52490075Sobrien (splay_tree_value) var); 52590075Sobrien 52690075Sobrien /* Declare this new variable. */ 52790075Sobrien init_stmt = build_stmt (DECL_STMT, var); 52890075Sobrien TREE_CHAIN (init_stmt) = init_stmts; 52990075Sobrien init_stmts = init_stmt; 53090075Sobrien 53190075Sobrien /* Initialize this VAR_DECL from the equivalent argument. If 53290075Sobrien the argument is an object, created via a constructor or copy, 53390075Sobrien this will not result in an extra copy: the TARGET_EXPR 53490075Sobrien representing the argument will be bound to VAR, and the 53590075Sobrien object will be constructed in VAR. */ 53690075Sobrien if (! TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (p))) 53790075Sobrien DECL_INITIAL (var) = value; 53890075Sobrien else 53990075Sobrien { 54090075Sobrien /* Even if P was TREE_READONLY, the new VAR should not be. 54190075Sobrien In the original code, we would have constructed a 54290075Sobrien temporary, and then the function body would have never 54390075Sobrien changed the value of P. However, now, we will be 54490075Sobrien constructing VAR directly. The constructor body may 54590075Sobrien change its value multiple times as it is being 54690075Sobrien constructed. Therefore, it must not be TREE_READONLY; 54790075Sobrien the back-end assumes that TREE_READONLY variable is 54890075Sobrien assigned to only once. */ 54990075Sobrien TREE_READONLY (var) = 0; 55090075Sobrien 55190075Sobrien /* Build a run-time initialization. */ 55290075Sobrien init_stmt = build_stmt (EXPR_STMT, 55390075Sobrien build (INIT_EXPR, TREE_TYPE (p), 55490075Sobrien var, value)); 55590075Sobrien /* Add this initialization to the list. Note that we want the 55690075Sobrien declaration *after* the initialization because we are going 55790075Sobrien to reverse all the initialization statements below. */ 55890075Sobrien TREE_CHAIN (init_stmt) = init_stmts; 55990075Sobrien init_stmts = init_stmt; 56090075Sobrien } 56190075Sobrien } 56290075Sobrien 56390075Sobrien /* Evaluate trailing arguments. */ 56490075Sobrien for (; a; a = TREE_CHAIN (a)) 56590075Sobrien { 56690075Sobrien tree init_stmt; 56790075Sobrien tree value; 56890075Sobrien 56990075Sobrien /* Find the initializer. */ 57090075Sobrien value = a ? TREE_VALUE (a) : NULL_TREE; 57190075Sobrien 57290075Sobrien if (! value || ! TREE_SIDE_EFFECTS (value)) 57390075Sobrien continue; 57490075Sobrien 57590075Sobrien init_stmt = build_stmt (EXPR_STMT, value); 57690075Sobrien TREE_CHAIN (init_stmt) = init_stmts; 57790075Sobrien init_stmts = init_stmt; 57890075Sobrien } 57990075Sobrien 58090075Sobrien /* The initialization statements have been built up in reverse 58190075Sobrien order. Straighten them out now. */ 58290075Sobrien return nreverse (init_stmts); 58390075Sobrien} 58490075Sobrien 58590075Sobrien/* Declare a return variable to replace the RESULT_DECL for the 58690075Sobrien function we are calling. An appropriate DECL_STMT is returned. 58790075Sobrien The USE_STMT is filled in to contain a use of the declaration to 58890075Sobrien indicate the return value of the function. */ 58990075Sobrien 59090075Sobrienstatic tree 59190075Sobriendeclare_return_variable (id, use_stmt) 59290075Sobrien struct inline_data *id; 59390075Sobrien tree *use_stmt; 59490075Sobrien{ 59590075Sobrien tree fn = VARRAY_TOP_TREE (id->fns); 59690075Sobrien tree result = DECL_RESULT (fn); 59790075Sobrien tree var; 59890075Sobrien int need_return_decl = 1; 59990075Sobrien 60090075Sobrien /* We don't need to do anything for functions that don't return 60190075Sobrien anything. */ 60290075Sobrien if (!result || VOID_TYPE_P (TREE_TYPE (result))) 60390075Sobrien { 60490075Sobrien *use_stmt = NULL_TREE; 60590075Sobrien return NULL_TREE; 60690075Sobrien } 60790075Sobrien 60890075Sobrien var = ((*lang_hooks.tree_inlining.copy_res_decl_for_inlining) 60990075Sobrien (result, fn, VARRAY_TREE (id->fns, 0), id->decl_map, 61090075Sobrien &need_return_decl, &id->target_exprs)); 61190075Sobrien 61290075Sobrien /* Register the VAR_DECL as the equivalent for the RESULT_DECL; that 61390075Sobrien way, when the RESULT_DECL is encountered, it will be 61490075Sobrien automatically replaced by the VAR_DECL. */ 61590075Sobrien splay_tree_insert (id->decl_map, 61690075Sobrien (splay_tree_key) result, 61790075Sobrien (splay_tree_value) var); 61890075Sobrien 61990075Sobrien /* Build the USE_STMT. If the return type of the function was 62090075Sobrien promoted, convert it back to the expected type. */ 62190075Sobrien if (TREE_TYPE (var) == TREE_TYPE (TREE_TYPE (fn))) 62290075Sobrien *use_stmt = build_stmt (EXPR_STMT, var); 62390075Sobrien else 62490075Sobrien *use_stmt = build_stmt (EXPR_STMT, 62590075Sobrien build1 (NOP_EXPR, TREE_TYPE (TREE_TYPE (fn)), 62690075Sobrien var)); 62790075Sobrien 62890075Sobrien TREE_ADDRESSABLE (*use_stmt) = 1; 62990075Sobrien 63090075Sobrien /* Build the declaration statement if FN does not return an 63190075Sobrien aggregate. */ 63290075Sobrien if (need_return_decl) 63390075Sobrien return build_stmt (DECL_STMT, var); 63490075Sobrien /* If FN does return an aggregate, there's no need to declare the 63590075Sobrien return variable; we're using a variable in our caller's frame. */ 63690075Sobrien else 63790075Sobrien return NULL_TREE; 63890075Sobrien} 63990075Sobrien 64090075Sobrien/* Returns non-zero if a function can be inlined as a tree. */ 64190075Sobrien 64290075Sobrienint 64390075Sobrientree_inlinable_function_p (fn) 64490075Sobrien tree fn; 64590075Sobrien{ 64690075Sobrien return inlinable_function_p (fn, NULL); 64790075Sobrien} 64890075Sobrien 64990075Sobrien/* Returns non-zero if FN is a function that can be inlined into the 65090075Sobrien inlining context ID_. If ID_ is NULL, check whether the function 65190075Sobrien can be inlined at all. */ 65290075Sobrien 65390075Sobrienstatic int 65490075Sobrieninlinable_function_p (fn, id) 65590075Sobrien tree fn; 65690075Sobrien inline_data *id; 65790075Sobrien{ 65890075Sobrien int inlinable; 65990075Sobrien 66090075Sobrien /* If we've already decided this function shouldn't be inlined, 66190075Sobrien there's no need to check again. */ 66290075Sobrien if (DECL_UNINLINABLE (fn)) 66390075Sobrien return 0; 66490075Sobrien 66590075Sobrien /* Assume it is not inlinable. */ 66690075Sobrien inlinable = 0; 66790075Sobrien 66890075Sobrien /* If we're not inlining things, then nothing is inlinable. */ 66990075Sobrien if (! flag_inline_trees) 67090075Sobrien ; 67190075Sobrien /* If we're not inlining all functions and the function was not 67290075Sobrien declared `inline', we don't inline it. Don't think of 67390075Sobrien disregarding DECL_INLINE when flag_inline_trees == 2; it's the 67490075Sobrien front-end that must set DECL_INLINE in this case, because 67590075Sobrien dwarf2out loses if a function is inlined that doesn't have 67690075Sobrien DECL_INLINE set. */ 67790075Sobrien else if (! DECL_INLINE (fn)) 67890075Sobrien ; 67990075Sobrien /* We can't inline functions that are too big. Only allow a single 68090075Sobrien function to eat up half of our budget. Make special allowance 68190075Sobrien for extern inline functions, though. */ 68290075Sobrien else if (! (*lang_hooks.tree_inlining.disregard_inline_limits) (fn) 68390075Sobrien && DECL_NUM_STMTS (fn) * INSNS_PER_STMT > MAX_INLINE_INSNS / 2) 68490075Sobrien ; 68590075Sobrien /* All is well. We can inline this function. Traditionally, GCC 68690075Sobrien has refused to inline functions using alloca, or functions whose 68790075Sobrien values are returned in a PARALLEL, and a few other such obscure 68890075Sobrien conditions. We are not equally constrained at the tree level. */ 68990075Sobrien else 69090075Sobrien inlinable = 1; 69190075Sobrien 69290075Sobrien /* Squirrel away the result so that we don't have to check again. */ 69390075Sobrien DECL_UNINLINABLE (fn) = ! inlinable; 69490075Sobrien 69590075Sobrien /* Even if this function is not itself too big to inline, it might 69690075Sobrien be that we've done so much inlining already that we don't want to 69790075Sobrien risk too much inlining any more and thus halve the acceptable 69890075Sobrien size. */ 69990075Sobrien if (! (*lang_hooks.tree_inlining.disregard_inline_limits) (fn) 70090075Sobrien && ((DECL_NUM_STMTS (fn) + (id ? id->inlined_stmts : 0)) * INSNS_PER_STMT 70190075Sobrien > MAX_INLINE_INSNS) 70290075Sobrien && DECL_NUM_STMTS (fn) * INSNS_PER_STMT > MAX_INLINE_INSNS / 4) 70390075Sobrien inlinable = 0; 70490075Sobrien 70590075Sobrien if (inlinable && (*lang_hooks.tree_inlining.cannot_inline_tree_fn) (&fn)) 70690075Sobrien inlinable = 0; 70790075Sobrien 70890075Sobrien /* If we don't have the function body available, we can't inline 70990075Sobrien it. */ 71090075Sobrien if (! DECL_SAVED_TREE (fn)) 71190075Sobrien inlinable = 0; 71290075Sobrien 71390075Sobrien /* Check again, language hooks may have modified it. */ 71490075Sobrien if (! inlinable || DECL_UNINLINABLE (fn)) 71590075Sobrien return 0; 71690075Sobrien 71790075Sobrien /* Don't do recursive inlining, either. We don't record this in 71890075Sobrien DECL_UNINLINABLE; we may be able to inline this function later. */ 71990075Sobrien if (id) 72090075Sobrien { 72190075Sobrien size_t i; 72290075Sobrien 72390075Sobrien for (i = 0; i < VARRAY_ACTIVE_SIZE (id->fns); ++i) 72490075Sobrien if (VARRAY_TREE (id->fns, i) == fn) 72590075Sobrien return 0; 72690075Sobrien 72790075Sobrien if (DECL_INLINED_FNS (fn)) 72890075Sobrien { 72990075Sobrien int j; 73090075Sobrien tree inlined_fns = DECL_INLINED_FNS (fn); 73190075Sobrien 73290075Sobrien for (j = 0; j < TREE_VEC_LENGTH (inlined_fns); ++j) 73390075Sobrien if (TREE_VEC_ELT (inlined_fns, j) == VARRAY_TREE (id->fns, 0)) 73490075Sobrien return 0; 73590075Sobrien } 73690075Sobrien } 73790075Sobrien 73890075Sobrien /* Return the result. */ 73990075Sobrien return inlinable; 74090075Sobrien} 74190075Sobrien 74290075Sobrien/* If *TP is a CALL_EXPR, replace it with its inline expansion. */ 74390075Sobrien 74490075Sobrienstatic tree 74590075Sobrienexpand_call_inline (tp, walk_subtrees, data) 74690075Sobrien tree *tp; 74790075Sobrien int *walk_subtrees; 74890075Sobrien void *data; 74990075Sobrien{ 75090075Sobrien inline_data *id; 75190075Sobrien tree t; 75290075Sobrien tree expr; 75390075Sobrien tree chain; 75490075Sobrien tree fn; 75590075Sobrien tree scope_stmt; 75690075Sobrien tree use_stmt; 75790075Sobrien tree arg_inits; 75890075Sobrien tree *inlined_body; 75990075Sobrien splay_tree st; 76090075Sobrien 76190075Sobrien /* See what we've got. */ 76290075Sobrien id = (inline_data *) data; 76390075Sobrien t = *tp; 76490075Sobrien 76590075Sobrien /* Recurse, but letting recursive invocations know that we are 76690075Sobrien inside the body of a TARGET_EXPR. */ 76790075Sobrien if (TREE_CODE (*tp) == TARGET_EXPR) 76890075Sobrien { 76990075Sobrien int i, len = first_rtl_op (TARGET_EXPR); 77090075Sobrien 77190075Sobrien /* We're walking our own subtrees. */ 77290075Sobrien *walk_subtrees = 0; 77390075Sobrien 77490075Sobrien /* Push *TP on the stack of pending TARGET_EXPRs. */ 77590075Sobrien VARRAY_PUSH_TREE (id->target_exprs, *tp); 77690075Sobrien 77790075Sobrien /* Actually walk over them. This loop is the body of 77890075Sobrien walk_trees, omitting the case where the TARGET_EXPR 77990075Sobrien itself is handled. */ 78090075Sobrien for (i = 0; i < len; ++i) 78190075Sobrien { 78290075Sobrien if (i == 2) 78390075Sobrien ++id->in_target_cleanup_p; 78490075Sobrien walk_tree (&TREE_OPERAND (*tp, i), expand_call_inline, data, 78590075Sobrien id->tree_pruner); 78690075Sobrien if (i == 2) 78790075Sobrien --id->in_target_cleanup_p; 78890075Sobrien } 78990075Sobrien 79090075Sobrien /* We're done with this TARGET_EXPR now. */ 79190075Sobrien VARRAY_POP (id->target_exprs); 79290075Sobrien 79390075Sobrien return NULL_TREE; 79490075Sobrien } 79590075Sobrien 79690075Sobrien if (TYPE_P (t)) 79790075Sobrien /* Because types were not copied in copy_body, CALL_EXPRs beneath 79890075Sobrien them should not be expanded. This can happen if the type is a 79990075Sobrien dynamic array type, for example. */ 80090075Sobrien *walk_subtrees = 0; 80190075Sobrien 80290075Sobrien /* From here on, we're only interested in CALL_EXPRs. */ 80390075Sobrien if (TREE_CODE (t) != CALL_EXPR) 80490075Sobrien return NULL_TREE; 80590075Sobrien 80690075Sobrien /* First, see if we can figure out what function is being called. 80790075Sobrien If we cannot, then there is no hope of inlining the function. */ 80890075Sobrien fn = get_callee_fndecl (t); 80990075Sobrien if (!fn) 81090075Sobrien return NULL_TREE; 81190075Sobrien 81290075Sobrien /* If fn is a declaration of a function in a nested scope that was 81390075Sobrien globally declared inline, we don't set its DECL_INITIAL. 81490075Sobrien However, we can't blindly follow DECL_ABSTRACT_ORIGIN because the 81590075Sobrien C++ front-end uses it for cdtors to refer to their internal 81690075Sobrien declarations, that are not real functions. Fortunately those 81790075Sobrien don't have trees to be saved, so we can tell by checking their 81890075Sobrien DECL_SAVED_TREE. */ 81990075Sobrien if (! DECL_INITIAL (fn) 82090075Sobrien && DECL_ABSTRACT_ORIGIN (fn) 82190075Sobrien && DECL_SAVED_TREE (DECL_ABSTRACT_ORIGIN (fn))) 82290075Sobrien fn = DECL_ABSTRACT_ORIGIN (fn); 82390075Sobrien 82490075Sobrien /* Don't try to inline functions that are not well-suited to 82590075Sobrien inlining. */ 82690075Sobrien if (!inlinable_function_p (fn, id)) 82790075Sobrien return NULL_TREE; 82890075Sobrien 82990075Sobrien if (! (*lang_hooks.tree_inlining.start_inlining) (fn)) 83090075Sobrien return NULL_TREE; 83190075Sobrien 83290075Sobrien /* Set the current filename and line number to the function we are 83390075Sobrien inlining so that when we create new _STMT nodes here they get 83490075Sobrien line numbers corresponding to the function we are calling. We 83590075Sobrien wrap the whole inlined body in an EXPR_WITH_FILE_AND_LINE as well 83690075Sobrien because individual statements don't record the filename. */ 83790075Sobrien push_srcloc (fn->decl.filename, fn->decl.linenum); 83890075Sobrien 83990075Sobrien /* Build a statement-expression containing code to initialize the 84090075Sobrien arguments, the actual inline expansion of the body, and a label 84190075Sobrien for the return statements within the function to jump to. The 84290075Sobrien type of the statement expression is the return type of the 84390075Sobrien function call. */ 84490075Sobrien expr = build1 (STMT_EXPR, TREE_TYPE (TREE_TYPE (fn)), NULL_TREE); 84590075Sobrien 84690075Sobrien /* Local declarations will be replaced by their equivalents in this 84790075Sobrien map. */ 84890075Sobrien st = id->decl_map; 84990075Sobrien id->decl_map = splay_tree_new (splay_tree_compare_pointers, 85090075Sobrien NULL, NULL); 85190075Sobrien 85290075Sobrien /* Initialize the parameters. */ 85390075Sobrien arg_inits = initialize_inlined_parameters (id, TREE_OPERAND (t, 1), fn); 85490075Sobrien /* Expand any inlined calls in the initializers. Do this before we 85590075Sobrien push FN on the stack of functions we are inlining; we want to 85690075Sobrien inline calls to FN that appear in the initializers for the 85790075Sobrien parameters. */ 85890075Sobrien expand_calls_inline (&arg_inits, id); 85990075Sobrien /* And add them to the tree. */ 86090075Sobrien STMT_EXPR_STMT (expr) = chainon (STMT_EXPR_STMT (expr), arg_inits); 86190075Sobrien 86290075Sobrien /* Record the function we are about to inline so that we can avoid 86390075Sobrien recursing into it. */ 86490075Sobrien VARRAY_PUSH_TREE (id->fns, fn); 86590075Sobrien 86690075Sobrien /* Record the function we are about to inline if optimize_function 86790075Sobrien has not been called on it yet and we don't have it in the list. */ 86890075Sobrien if (! DECL_INLINED_FNS (fn)) 86990075Sobrien { 87090075Sobrien int i; 87190075Sobrien 87290075Sobrien for (i = VARRAY_ACTIVE_SIZE (id->inlined_fns) - 1; i >= 0; i--) 87390075Sobrien if (VARRAY_TREE (id->inlined_fns, i) == fn) 87490075Sobrien break; 87590075Sobrien if (i < 0) 87690075Sobrien VARRAY_PUSH_TREE (id->inlined_fns, fn); 87790075Sobrien } 87890075Sobrien 87990075Sobrien /* Return statements in the function body will be replaced by jumps 88090075Sobrien to the RET_LABEL. */ 88190075Sobrien id->ret_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); 88290075Sobrien DECL_CONTEXT (id->ret_label) = VARRAY_TREE (id->fns, 0); 88390075Sobrien 88490075Sobrien if (! DECL_INITIAL (fn) 88590075Sobrien || TREE_CODE (DECL_INITIAL (fn)) != BLOCK) 88690075Sobrien abort (); 88790075Sobrien 88890075Sobrien /* Create a block to put the parameters in. We have to do this 88990075Sobrien after the parameters have been remapped because remapping 89090075Sobrien parameters is different from remapping ordinary variables. */ 89190075Sobrien scope_stmt = build_stmt (SCOPE_STMT, DECL_INITIAL (fn)); 89290075Sobrien SCOPE_BEGIN_P (scope_stmt) = 1; 89390075Sobrien SCOPE_NO_CLEANUPS_P (scope_stmt) = 1; 89490075Sobrien remap_block (scope_stmt, DECL_ARGUMENTS (fn), id); 89590075Sobrien TREE_CHAIN (scope_stmt) = STMT_EXPR_STMT (expr); 89690075Sobrien STMT_EXPR_STMT (expr) = scope_stmt; 89790075Sobrien 89890075Sobrien /* Tell the debugging backends that this block represents the 89990075Sobrien outermost scope of the inlined function. */ 90090075Sobrien if (SCOPE_STMT_BLOCK (scope_stmt)) 90190075Sobrien BLOCK_ABSTRACT_ORIGIN (SCOPE_STMT_BLOCK (scope_stmt)) = DECL_ORIGIN (fn); 90290075Sobrien 90390075Sobrien /* Declare the return variable for the function. */ 90490075Sobrien STMT_EXPR_STMT (expr) 90590075Sobrien = chainon (STMT_EXPR_STMT (expr), 90690075Sobrien declare_return_variable (id, &use_stmt)); 90790075Sobrien 90890075Sobrien /* After we've initialized the parameters, we insert the body of the 90990075Sobrien function itself. */ 91090075Sobrien inlined_body = &STMT_EXPR_STMT (expr); 91190075Sobrien while (*inlined_body) 91290075Sobrien inlined_body = &TREE_CHAIN (*inlined_body); 91390075Sobrien *inlined_body = copy_body (id); 91490075Sobrien 91590075Sobrien /* Close the block for the parameters. */ 91690075Sobrien scope_stmt = build_stmt (SCOPE_STMT, DECL_INITIAL (fn)); 91790075Sobrien SCOPE_NO_CLEANUPS_P (scope_stmt) = 1; 91890075Sobrien remap_block (scope_stmt, NULL_TREE, id); 91990075Sobrien STMT_EXPR_STMT (expr) 92090075Sobrien = chainon (STMT_EXPR_STMT (expr), scope_stmt); 92190075Sobrien 92290075Sobrien /* After the body of the function comes the RET_LABEL. This must come 92390075Sobrien before we evaluate the returned value below, because that evalulation 92490075Sobrien may cause RTL to be generated. */ 92590075Sobrien STMT_EXPR_STMT (expr) 92690075Sobrien = chainon (STMT_EXPR_STMT (expr), 92790075Sobrien build_stmt (LABEL_STMT, id->ret_label)); 92890075Sobrien 92990075Sobrien /* Finally, mention the returned value so that the value of the 93090075Sobrien statement-expression is the returned value of the function. */ 93190075Sobrien STMT_EXPR_STMT (expr) = chainon (STMT_EXPR_STMT (expr), use_stmt); 93290075Sobrien 93390075Sobrien /* Clean up. */ 93490075Sobrien splay_tree_delete (id->decl_map); 93590075Sobrien id->decl_map = st; 93690075Sobrien 93790075Sobrien /* The new expression has side-effects if the old one did. */ 93890075Sobrien TREE_SIDE_EFFECTS (expr) = TREE_SIDE_EFFECTS (t); 93990075Sobrien 94090075Sobrien /* Replace the call by the inlined body. Wrap it in an 94190075Sobrien EXPR_WITH_FILE_LOCATION so that we'll get debugging line notes 94290075Sobrien pointing to the right place. */ 94390075Sobrien chain = TREE_CHAIN (*tp); 94490075Sobrien *tp = build_expr_wfl (expr, DECL_SOURCE_FILE (fn), DECL_SOURCE_LINE (fn), 94590075Sobrien /*col=*/0); 94690075Sobrien EXPR_WFL_EMIT_LINE_NOTE (*tp) = 1; 94790075Sobrien TREE_CHAIN (*tp) = chain; 94890075Sobrien pop_srcloc (); 94990075Sobrien 95090075Sobrien /* If the value of the new expression is ignored, that's OK. We 95190075Sobrien don't warn about this for CALL_EXPRs, so we shouldn't warn about 95290075Sobrien the equivalent inlined version either. */ 95390075Sobrien TREE_USED (*tp) = 1; 95490075Sobrien 95590075Sobrien /* Our function now has more statements than it did before. */ 95690075Sobrien DECL_NUM_STMTS (VARRAY_TREE (id->fns, 0)) += DECL_NUM_STMTS (fn); 95790075Sobrien id->inlined_stmts += DECL_NUM_STMTS (fn); 95890075Sobrien 95990075Sobrien /* Recurse into the body of the just inlined function. */ 96090075Sobrien expand_calls_inline (inlined_body, id); 96190075Sobrien VARRAY_POP (id->fns); 96290075Sobrien 96390075Sobrien /* If we've returned to the top level, clear out the record of how 96490075Sobrien much inlining has been done. */ 96590075Sobrien if (VARRAY_ACTIVE_SIZE (id->fns) == id->first_inlined_fn) 96690075Sobrien id->inlined_stmts = 0; 96790075Sobrien 96890075Sobrien /* Don't walk into subtrees. We've already handled them above. */ 96990075Sobrien *walk_subtrees = 0; 97090075Sobrien 97190075Sobrien (*lang_hooks.tree_inlining.end_inlining) (fn); 97290075Sobrien 97390075Sobrien /* Keep iterating. */ 97490075Sobrien return NULL_TREE; 97590075Sobrien} 97690075Sobrien 97790075Sobrien/* Walk over the entire tree *TP, replacing CALL_EXPRs with inline 97890075Sobrien expansions as appropriate. */ 97990075Sobrien 98090075Sobrienstatic void 98190075Sobrienexpand_calls_inline (tp, id) 98290075Sobrien tree *tp; 98390075Sobrien inline_data *id; 98490075Sobrien{ 98590075Sobrien /* Search through *TP, replacing all calls to inline functions by 98690075Sobrien appropriate equivalents. Use walk_tree in no-duplicates mode 98790075Sobrien to avoid exponential time complexity. (We can't just use 98890075Sobrien walk_tree_without_duplicates, because of the special TARGET_EXPR 98990075Sobrien handling in expand_calls. The hash table is set up in 99090075Sobrien optimize_function. */ 99190075Sobrien walk_tree (tp, expand_call_inline, id, id->tree_pruner); 99290075Sobrien} 99390075Sobrien 99490075Sobrien/* Expand calls to inline functions in the body of FN. */ 99590075Sobrien 99690075Sobrienvoid 99790075Sobrienoptimize_inline_calls (fn) 99890075Sobrien tree fn; 99990075Sobrien{ 100090075Sobrien inline_data id; 100190075Sobrien tree prev_fn; 100290075Sobrien 100390075Sobrien /* Clear out ID. */ 100490075Sobrien memset (&id, 0, sizeof (id)); 100590075Sobrien 100690075Sobrien /* Don't allow recursion into FN. */ 100790075Sobrien VARRAY_TREE_INIT (id.fns, 32, "fns"); 100890075Sobrien VARRAY_PUSH_TREE (id.fns, fn); 100990075Sobrien /* Or any functions that aren't finished yet. */ 101090075Sobrien prev_fn = NULL_TREE; 101190075Sobrien if (current_function_decl) 101290075Sobrien { 101390075Sobrien VARRAY_PUSH_TREE (id.fns, current_function_decl); 101490075Sobrien prev_fn = current_function_decl; 101590075Sobrien } 101690075Sobrien 101790075Sobrien prev_fn = ((*lang_hooks.tree_inlining.add_pending_fn_decls) 101890075Sobrien (&id.fns, prev_fn)); 101990075Sobrien 102090075Sobrien /* Create the stack of TARGET_EXPRs. */ 102190075Sobrien VARRAY_TREE_INIT (id.target_exprs, 32, "target_exprs"); 102290075Sobrien 102390075Sobrien /* Create the list of functions this call will inline. */ 102490075Sobrien VARRAY_TREE_INIT (id.inlined_fns, 32, "inlined_fns"); 102590075Sobrien 102690075Sobrien /* Keep track of the low-water mark, i.e., the point where the first 102790075Sobrien real inlining is represented in ID.FNS. */ 102890075Sobrien id.first_inlined_fn = VARRAY_ACTIVE_SIZE (id.fns); 102990075Sobrien 103090075Sobrien /* Replace all calls to inline functions with the bodies of those 103190075Sobrien functions. */ 103290075Sobrien id.tree_pruner = htab_create (37, htab_hash_pointer, 103390075Sobrien htab_eq_pointer, NULL); 103490075Sobrien expand_calls_inline (&DECL_SAVED_TREE (fn), &id); 103590075Sobrien 103690075Sobrien /* Clean up. */ 103790075Sobrien htab_delete (id.tree_pruner); 103890075Sobrien VARRAY_FREE (id.fns); 103990075Sobrien VARRAY_FREE (id.target_exprs); 104090075Sobrien if (DECL_LANG_SPECIFIC (fn)) 104190075Sobrien { 104290075Sobrien tree ifn = make_tree_vec (VARRAY_ACTIVE_SIZE (id.inlined_fns)); 104390075Sobrien 104490075Sobrien memcpy (&TREE_VEC_ELT (ifn, 0), &VARRAY_TREE (id.inlined_fns, 0), 104590075Sobrien VARRAY_ACTIVE_SIZE (id.inlined_fns) * sizeof (tree)); 104690075Sobrien DECL_INLINED_FNS (fn) = ifn; 104790075Sobrien } 104890075Sobrien VARRAY_FREE (id.inlined_fns); 104990075Sobrien} 105090075Sobrien 105190075Sobrien/* FN is a function that has a complete body, and CLONE is a function 105290075Sobrien whose body is to be set to a copy of FN, mapping argument 105390075Sobrien declarations according to the ARG_MAP splay_tree. */ 105490075Sobrien 105590075Sobrienvoid 105690075Sobrienclone_body (clone, fn, arg_map) 105790075Sobrien tree clone, fn; 105890075Sobrien void *arg_map; 105990075Sobrien{ 106090075Sobrien inline_data id; 106190075Sobrien 106290075Sobrien /* Clone the body, as if we were making an inline call. But, remap 106390075Sobrien the parameters in the callee to the parameters of caller. If 106490075Sobrien there's an in-charge parameter, map it to an appropriate 106590075Sobrien constant. */ 106690075Sobrien memset (&id, 0, sizeof (id)); 106790075Sobrien VARRAY_TREE_INIT (id.fns, 2, "fns"); 106890075Sobrien VARRAY_PUSH_TREE (id.fns, clone); 106990075Sobrien VARRAY_PUSH_TREE (id.fns, fn); 107090075Sobrien id.decl_map = (splay_tree)arg_map; 107190075Sobrien 107290075Sobrien /* Cloning is treated slightly differently from inlining. Set 107390075Sobrien CLONING_P so that it's clear which operation we're performing. */ 107490075Sobrien id.cloning_p = true; 107590075Sobrien 107690075Sobrien /* Actually copy the body. */ 107790075Sobrien TREE_CHAIN (DECL_SAVED_TREE (clone)) = copy_body (&id); 107890075Sobrien 107990075Sobrien /* Clean up. */ 108090075Sobrien VARRAY_FREE (id.fns); 108190075Sobrien} 108290075Sobrien 108390075Sobrien/* Apply FUNC to all the sub-trees of TP in a pre-order traversal. 108490075Sobrien FUNC is called with the DATA and the address of each sub-tree. If 108590075Sobrien FUNC returns a non-NULL value, the traversal is aborted, and the 108690075Sobrien value returned by FUNC is returned. If HTAB is non-NULL it is used 108790075Sobrien to record the nodes visited, and to avoid visiting a node more than 108890075Sobrien once. */ 108990075Sobrien 109090075Sobrientree 109190075Sobrienwalk_tree (tp, func, data, htab_) 109290075Sobrien tree *tp; 109390075Sobrien walk_tree_fn func; 109490075Sobrien void *data; 109590075Sobrien void *htab_; 109690075Sobrien{ 109790075Sobrien htab_t htab = (htab_t) htab_; 109890075Sobrien enum tree_code code; 109990075Sobrien int walk_subtrees; 110090075Sobrien tree result; 110190075Sobrien 110290075Sobrien#define WALK_SUBTREE(NODE) \ 110390075Sobrien do \ 110490075Sobrien { \ 110590075Sobrien result = walk_tree (&(NODE), func, data, htab); \ 110690075Sobrien if (result) \ 110790075Sobrien return result; \ 110890075Sobrien } \ 110990075Sobrien while (0) 111090075Sobrien 111190075Sobrien#define WALK_SUBTREE_TAIL(NODE) \ 111290075Sobrien do \ 111390075Sobrien { \ 111490075Sobrien tp = & (NODE); \ 111590075Sobrien goto tail_recurse; \ 111690075Sobrien } \ 111790075Sobrien while (0) 111890075Sobrien 111990075Sobrien tail_recurse: 112090075Sobrien /* Skip empty subtrees. */ 112190075Sobrien if (!*tp) 112290075Sobrien return NULL_TREE; 112390075Sobrien 112490075Sobrien if (htab) 112590075Sobrien { 112690075Sobrien void **slot; 112790075Sobrien 112890075Sobrien /* Don't walk the same tree twice, if the user has requested 112990075Sobrien that we avoid doing so. */ 113090075Sobrien if (htab_find (htab, *tp)) 113190075Sobrien return NULL_TREE; 113290075Sobrien /* If we haven't already seen this node, add it to the table. */ 113390075Sobrien slot = htab_find_slot (htab, *tp, INSERT); 113490075Sobrien *slot = *tp; 113590075Sobrien } 113690075Sobrien 113790075Sobrien /* Call the function. */ 113890075Sobrien walk_subtrees = 1; 113990075Sobrien result = (*func) (tp, &walk_subtrees, data); 114090075Sobrien 114190075Sobrien /* If we found something, return it. */ 114290075Sobrien if (result) 114390075Sobrien return result; 114490075Sobrien 114590075Sobrien code = TREE_CODE (*tp); 114690075Sobrien 114790075Sobrien /* Even if we didn't, FUNC may have decided that there was nothing 114890075Sobrien interesting below this point in the tree. */ 114990075Sobrien if (!walk_subtrees) 115090075Sobrien { 115190075Sobrien if (statement_code_p (code) || code == TREE_LIST 115290075Sobrien || (*lang_hooks.tree_inlining.tree_chain_matters_p) (*tp)) 115390075Sobrien /* But we still need to check our siblings. */ 115490075Sobrien WALK_SUBTREE_TAIL (TREE_CHAIN (*tp)); 115590075Sobrien else 115690075Sobrien return NULL_TREE; 115790075Sobrien } 115890075Sobrien 115990075Sobrien /* Handle common cases up front. */ 116090075Sobrien if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)) 116190075Sobrien || TREE_CODE_CLASS (code) == 'r' 116290075Sobrien || TREE_CODE_CLASS (code) == 's') 116390075Sobrien { 116490075Sobrien int i, len; 116590075Sobrien 116690075Sobrien /* Set lineno here so we get the right instantiation context 116790075Sobrien if we call instantiate_decl from inlinable_function_p. */ 116890075Sobrien if (statement_code_p (code) && !STMT_LINENO_FOR_FN_P (*tp)) 116990075Sobrien lineno = STMT_LINENO (*tp); 117090075Sobrien 117190075Sobrien /* Walk over all the sub-trees of this operand. */ 117290075Sobrien len = first_rtl_op (code); 117390075Sobrien /* TARGET_EXPRs are peculiar: operands 1 and 3 can be the same. 117490075Sobrien But, we only want to walk once. */ 117590075Sobrien if (code == TARGET_EXPR 117690075Sobrien && TREE_OPERAND (*tp, 3) == TREE_OPERAND (*tp, 1)) 117790075Sobrien --len; 117890075Sobrien /* Go through the subtrees. We need to do this in forward order so 117990075Sobrien that the scope of a FOR_EXPR is handled properly. */ 118090075Sobrien for (i = 0; i < len; ++i) 118190075Sobrien WALK_SUBTREE (TREE_OPERAND (*tp, i)); 118290075Sobrien 118390075Sobrien /* For statements, we also walk the chain so that we cover the 118490075Sobrien entire statement tree. */ 118590075Sobrien if (statement_code_p (code)) 118690075Sobrien { 118790075Sobrien if (code == DECL_STMT 118890075Sobrien && DECL_STMT_DECL (*tp) 118990075Sobrien && DECL_P (DECL_STMT_DECL (*tp))) 119090075Sobrien { 119190075Sobrien /* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk 119290075Sobrien into declarations that are just mentioned, rather than 119390075Sobrien declared; they don't really belong to this part of the tree. 119490075Sobrien And, we can see cycles: the initializer for a declaration can 119590075Sobrien refer to the declaration itself. */ 119690075Sobrien WALK_SUBTREE (DECL_INITIAL (DECL_STMT_DECL (*tp))); 119790075Sobrien WALK_SUBTREE (DECL_SIZE (DECL_STMT_DECL (*tp))); 119890075Sobrien WALK_SUBTREE (DECL_SIZE_UNIT (DECL_STMT_DECL (*tp))); 119990075Sobrien } 120090075Sobrien 120190075Sobrien /* This can be tail-recursion optimized if we write it this way. */ 120290075Sobrien WALK_SUBTREE_TAIL (TREE_CHAIN (*tp)); 120390075Sobrien } 120490075Sobrien 120590075Sobrien /* We didn't find what we were looking for. */ 120690075Sobrien return NULL_TREE; 120790075Sobrien } 120890075Sobrien else if (TREE_CODE_CLASS (code) == 'd') 120990075Sobrien { 121090075Sobrien WALK_SUBTREE_TAIL (TREE_TYPE (*tp)); 121190075Sobrien } 121290075Sobrien 121390075Sobrien result = (*lang_hooks.tree_inlining.walk_subtrees) (tp, &walk_subtrees, func, 121490075Sobrien data, htab); 121590075Sobrien if (result || ! walk_subtrees) 121690075Sobrien return result; 121790075Sobrien 121890075Sobrien /* Not one of the easy cases. We must explicitly go through the 121990075Sobrien children. */ 122090075Sobrien switch (code) 122190075Sobrien { 122290075Sobrien case ERROR_MARK: 122390075Sobrien case IDENTIFIER_NODE: 122490075Sobrien case INTEGER_CST: 122590075Sobrien case REAL_CST: 122690075Sobrien case STRING_CST: 122790075Sobrien case REAL_TYPE: 122890075Sobrien case COMPLEX_TYPE: 122990075Sobrien case VECTOR_TYPE: 123090075Sobrien case VOID_TYPE: 123190075Sobrien case BOOLEAN_TYPE: 123290075Sobrien case UNION_TYPE: 123390075Sobrien case ENUMERAL_TYPE: 123490075Sobrien case BLOCK: 123590075Sobrien case RECORD_TYPE: 123690075Sobrien /* None of thse have subtrees other than those already walked 123790075Sobrien above. */ 123890075Sobrien break; 123990075Sobrien 124090075Sobrien case POINTER_TYPE: 124190075Sobrien case REFERENCE_TYPE: 124290075Sobrien WALK_SUBTREE_TAIL (TREE_TYPE (*tp)); 124390075Sobrien break; 124490075Sobrien 124590075Sobrien case TREE_LIST: 124690075Sobrien WALK_SUBTREE (TREE_VALUE (*tp)); 124790075Sobrien WALK_SUBTREE_TAIL (TREE_CHAIN (*tp)); 124890075Sobrien break; 124990075Sobrien 125090075Sobrien case TREE_VEC: 125190075Sobrien { 125290075Sobrien int len = TREE_VEC_LENGTH (*tp); 125390075Sobrien 125490075Sobrien if (len == 0) 125590075Sobrien break; 125690075Sobrien 125790075Sobrien /* Walk all elements but the first. */ 125890075Sobrien while (--len) 125990075Sobrien WALK_SUBTREE (TREE_VEC_ELT (*tp, len)); 126090075Sobrien 126190075Sobrien /* Now walk the first one as a tail call. */ 126290075Sobrien WALK_SUBTREE_TAIL (TREE_VEC_ELT (*tp, 0)); 126390075Sobrien } 126490075Sobrien 126590075Sobrien case COMPLEX_CST: 126690075Sobrien WALK_SUBTREE (TREE_REALPART (*tp)); 126790075Sobrien WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp)); 126890075Sobrien 126990075Sobrien case CONSTRUCTOR: 127090075Sobrien WALK_SUBTREE_TAIL (CONSTRUCTOR_ELTS (*tp)); 127190075Sobrien 127290075Sobrien case METHOD_TYPE: 127390075Sobrien WALK_SUBTREE (TYPE_METHOD_BASETYPE (*tp)); 127490075Sobrien /* Fall through. */ 127590075Sobrien 127690075Sobrien case FUNCTION_TYPE: 127790075Sobrien WALK_SUBTREE (TREE_TYPE (*tp)); 127890075Sobrien { 127990075Sobrien tree arg = TYPE_ARG_TYPES (*tp); 128090075Sobrien 128190075Sobrien /* We never want to walk into default arguments. */ 128290075Sobrien for (; arg; arg = TREE_CHAIN (arg)) 128390075Sobrien WALK_SUBTREE (TREE_VALUE (arg)); 128490075Sobrien } 128590075Sobrien break; 128690075Sobrien 128790075Sobrien case ARRAY_TYPE: 128890075Sobrien WALK_SUBTREE (TREE_TYPE (*tp)); 128990075Sobrien WALK_SUBTREE_TAIL (TYPE_DOMAIN (*tp)); 129090075Sobrien 129190075Sobrien case INTEGER_TYPE: 129290075Sobrien WALK_SUBTREE (TYPE_MIN_VALUE (*tp)); 129390075Sobrien WALK_SUBTREE_TAIL (TYPE_MAX_VALUE (*tp)); 129490075Sobrien 129590075Sobrien case OFFSET_TYPE: 129690075Sobrien WALK_SUBTREE (TREE_TYPE (*tp)); 129790075Sobrien WALK_SUBTREE_TAIL (TYPE_OFFSET_BASETYPE (*tp)); 129890075Sobrien 129990075Sobrien default: 130090075Sobrien abort (); 130190075Sobrien } 130290075Sobrien 130390075Sobrien /* We didn't find what we were looking for. */ 130490075Sobrien return NULL_TREE; 130590075Sobrien 130690075Sobrien#undef WALK_SUBTREE 130790075Sobrien} 130890075Sobrien 130990075Sobrien/* Like walk_tree, but does not walk duplicate nodes more than 131090075Sobrien once. */ 131190075Sobrien 131290075Sobrientree 131390075Sobrienwalk_tree_without_duplicates (tp, func, data) 131490075Sobrien tree *tp; 131590075Sobrien walk_tree_fn func; 131690075Sobrien void *data; 131790075Sobrien{ 131890075Sobrien tree result; 131990075Sobrien htab_t htab; 132090075Sobrien 132190075Sobrien htab = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL); 132290075Sobrien result = walk_tree (tp, func, data, htab); 132390075Sobrien htab_delete (htab); 132490075Sobrien return result; 132590075Sobrien} 132690075Sobrien 132790075Sobrien/* Passed to walk_tree. Copies the node pointed to, if appropriate. */ 132890075Sobrien 132990075Sobrientree 133090075Sobriencopy_tree_r (tp, walk_subtrees, data) 133190075Sobrien tree *tp; 133290075Sobrien int *walk_subtrees; 133390075Sobrien void *data ATTRIBUTE_UNUSED; 133490075Sobrien{ 133590075Sobrien enum tree_code code = TREE_CODE (*tp); 133690075Sobrien 133790075Sobrien /* We make copies of most nodes. */ 133890075Sobrien if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)) 133990075Sobrien || TREE_CODE_CLASS (code) == 'r' 134090075Sobrien || TREE_CODE_CLASS (code) == 'c' 134190075Sobrien || TREE_CODE_CLASS (code) == 's' 134290075Sobrien || code == TREE_LIST 134390075Sobrien || code == TREE_VEC 134490075Sobrien || (*lang_hooks.tree_inlining.tree_chain_matters_p) (*tp)) 134590075Sobrien { 134690075Sobrien /* Because the chain gets clobbered when we make a copy, we save it 134790075Sobrien here. */ 134890075Sobrien tree chain = TREE_CHAIN (*tp); 134990075Sobrien 135090075Sobrien /* Copy the node. */ 135190075Sobrien *tp = copy_node (*tp); 135290075Sobrien 135390075Sobrien /* Now, restore the chain, if appropriate. That will cause 135490075Sobrien walk_tree to walk into the chain as well. */ 135590075Sobrien if (code == PARM_DECL || code == TREE_LIST 135690075Sobrien || (*lang_hooks.tree_inlining.tree_chain_matters_p) (*tp) 135790075Sobrien || statement_code_p (code)) 135890075Sobrien TREE_CHAIN (*tp) = chain; 135990075Sobrien 136090075Sobrien /* For now, we don't update BLOCKs when we make copies. So, we 136190075Sobrien have to nullify all scope-statements. */ 136290075Sobrien if (TREE_CODE (*tp) == SCOPE_STMT) 136390075Sobrien SCOPE_STMT_BLOCK (*tp) = NULL_TREE; 136490075Sobrien } 136590075Sobrien else if (TREE_CODE_CLASS (code) == 't') 136690075Sobrien /* There's no need to copy types, or anything beneath them. */ 136790075Sobrien *walk_subtrees = 0; 136890075Sobrien 136990075Sobrien return NULL_TREE; 137090075Sobrien} 137190075Sobrien 137290075Sobrien/* The SAVE_EXPR pointed to by TP is being copied. If ST contains 137390075Sobrien information indicating to what new SAVE_EXPR this one should be 137490075Sobrien mapped, use that one. Otherwise, create a new node and enter it in 137590075Sobrien ST. FN is the function into which the copy will be placed. */ 137690075Sobrien 137790075Sobrienvoid 137890075Sobrienremap_save_expr (tp, st_, fn, walk_subtrees) 137990075Sobrien tree *tp; 138090075Sobrien void *st_; 138190075Sobrien tree fn; 138290075Sobrien int *walk_subtrees; 138390075Sobrien{ 138490075Sobrien splay_tree st = (splay_tree) st_; 138590075Sobrien splay_tree_node n; 138690075Sobrien 138790075Sobrien /* See if we already encountered this SAVE_EXPR. */ 138890075Sobrien n = splay_tree_lookup (st, (splay_tree_key) *tp); 138990075Sobrien 139090075Sobrien /* If we didn't already remap this SAVE_EXPR, do so now. */ 139190075Sobrien if (!n) 139290075Sobrien { 139390075Sobrien tree t = copy_node (*tp); 139490075Sobrien 139590075Sobrien /* The SAVE_EXPR is now part of the function into which we 139690075Sobrien are inlining this body. */ 139790075Sobrien SAVE_EXPR_CONTEXT (t) = fn; 139890075Sobrien /* And we haven't evaluated it yet. */ 139990075Sobrien SAVE_EXPR_RTL (t) = NULL_RTX; 140090075Sobrien /* Remember this SAVE_EXPR. */ 140190075Sobrien n = splay_tree_insert (st, 140290075Sobrien (splay_tree_key) *tp, 140390075Sobrien (splay_tree_value) t); 140490075Sobrien /* Make sure we don't remap an already-remapped SAVE_EXPR. */ 140590075Sobrien splay_tree_insert (st, (splay_tree_key) t, 140690075Sobrien (splay_tree_value) error_mark_node); 140790075Sobrien } 140890075Sobrien else 140990075Sobrien /* We've already walked into this SAVE_EXPR, so we needn't do it 141090075Sobrien again. */ 141190075Sobrien *walk_subtrees = 0; 141290075Sobrien 141390075Sobrien /* Replace this SAVE_EXPR with the copy. */ 141490075Sobrien *tp = (tree) n->value; 141590075Sobrien} 1416