138fd1498Szrj /* Tree inlining. 238fd1498Szrj Copyright (C) 2001-2018 Free Software Foundation, Inc. 338fd1498Szrj Contributed by Alexandre Oliva <aoliva@redhat.com> 438fd1498Szrj 538fd1498Szrj This file is part of GCC. 638fd1498Szrj 738fd1498Szrj GCC is free software; you can redistribute it and/or modify 838fd1498Szrj it under the terms of the GNU General Public License as published by 938fd1498Szrj the Free Software Foundation; either version 3, or (at your option) 1038fd1498Szrj any later version. 1138fd1498Szrj 1238fd1498Szrj GCC is distributed in the hope that it will be useful, 1338fd1498Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of 1438fd1498Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1538fd1498Szrj GNU General Public License for more details. 1638fd1498Szrj 1738fd1498Szrj You should have received a copy of the GNU General Public License 1838fd1498Szrj along with GCC; see the file COPYING3. If not see 1938fd1498Szrj <http://www.gnu.org/licenses/>. */ 2038fd1498Szrj 2138fd1498Szrj #include "config.h" 2238fd1498Szrj #include "system.h" 2338fd1498Szrj #include "coretypes.h" 2438fd1498Szrj #include "backend.h" 2538fd1498Szrj #include "target.h" 2638fd1498Szrj #include "rtl.h" 2738fd1498Szrj #include "tree.h" 2838fd1498Szrj #include "gimple.h" 2938fd1498Szrj #include "cfghooks.h" 3038fd1498Szrj #include "tree-pass.h" 3138fd1498Szrj #include "ssa.h" 3238fd1498Szrj #include "cgraph.h" 3338fd1498Szrj #include "tree-pretty-print.h" 3438fd1498Szrj #include "diagnostic-core.h" 3538fd1498Szrj #include "gimple-predict.h" 3638fd1498Szrj #include "fold-const.h" 3738fd1498Szrj #include "stor-layout.h" 3838fd1498Szrj #include "calls.h" 3938fd1498Szrj #include "tree-inline.h" 4038fd1498Szrj #include "langhooks.h" 4138fd1498Szrj #include "cfganal.h" 4238fd1498Szrj #include "tree-iterator.h" 4338fd1498Szrj #include "intl.h" 4438fd1498Szrj #include "gimple-fold.h" 4538fd1498Szrj #include "tree-eh.h" 4638fd1498Szrj #include "gimplify.h" 4738fd1498Szrj #include "gimple-iterator.h" 4838fd1498Szrj #include "gimplify-me.h" 4938fd1498Szrj #include "gimple-walk.h" 5038fd1498Szrj #include "tree-cfg.h" 5138fd1498Szrj #include "tree-into-ssa.h" 5238fd1498Szrj #include "tree-dfa.h" 5338fd1498Szrj #include "tree-ssa.h" 5438fd1498Szrj #include "except.h" 5538fd1498Szrj #include "debug.h" 5638fd1498Szrj #include "params.h" 5738fd1498Szrj #include "value-prof.h" 5838fd1498Szrj #include "cfgloop.h" 5938fd1498Szrj #include "builtins.h" 6038fd1498Szrj #include "tree-chkp.h" 6138fd1498Szrj #include "stringpool.h" 6238fd1498Szrj #include "attribs.h" 6338fd1498Szrj #include "sreal.h" 6438fd1498Szrj 6538fd1498Szrj /* I'm not real happy about this, but we need to handle gimple and 6638fd1498Szrj non-gimple trees. */ 6738fd1498Szrj 6838fd1498Szrj /* Inlining, Cloning, Versioning, Parallelization 6938fd1498Szrj 7038fd1498Szrj Inlining: a function body is duplicated, but the PARM_DECLs are 7138fd1498Szrj remapped into VAR_DECLs, and non-void RETURN_EXPRs become 7238fd1498Szrj MODIFY_EXPRs that store to a dedicated returned-value variable. 7338fd1498Szrj The duplicated eh_region info of the copy will later be appended 7438fd1498Szrj to the info for the caller; the eh_region info in copied throwing 7538fd1498Szrj statements and RESX statements are adjusted accordingly. 7638fd1498Szrj 7738fd1498Szrj Cloning: (only in C++) We have one body for a con/de/structor, and 7838fd1498Szrj multiple function decls, each with a unique parameter list. 7938fd1498Szrj Duplicate the body, using the given splay tree; some parameters 8038fd1498Szrj will become constants (like 0 or 1). 8138fd1498Szrj 8238fd1498Szrj Versioning: a function body is duplicated and the result is a new 8338fd1498Szrj function rather than into blocks of an existing function as with 8438fd1498Szrj inlining. Some parameters will become constants. 8538fd1498Szrj 8638fd1498Szrj Parallelization: a region of a function is duplicated resulting in 8738fd1498Szrj a new function. Variables may be replaced with complex expressions 8838fd1498Szrj to enable shared variable semantics. 8938fd1498Szrj 9038fd1498Szrj All of these will simultaneously lookup any callgraph edges. If 9138fd1498Szrj we're going to inline the duplicated function body, and the given 9238fd1498Szrj function has some cloned callgraph nodes (one for each place this 9338fd1498Szrj function will be inlined) those callgraph edges will be duplicated. 9438fd1498Szrj If we're cloning the body, those callgraph edges will be 9538fd1498Szrj updated to point into the new body. (Note that the original 9638fd1498Szrj callgraph node and edge list will not be altered.) 9738fd1498Szrj 9838fd1498Szrj See the CALL_EXPR handling case in copy_tree_body_r (). */ 9938fd1498Szrj 10038fd1498Szrj /* To Do: 10138fd1498Szrj 10238fd1498Szrj o In order to make inlining-on-trees work, we pessimized 10338fd1498Szrj function-local static constants. In particular, they are now 10438fd1498Szrj always output, even when not addressed. Fix this by treating 10538fd1498Szrj function-local static constants just like global static 10638fd1498Szrj constants; the back-end already knows not to output them if they 10738fd1498Szrj are not needed. 10838fd1498Szrj 10938fd1498Szrj o Provide heuristics to clamp inlining of recursive template 11038fd1498Szrj calls? */ 11138fd1498Szrj 11238fd1498Szrj 11338fd1498Szrj /* Weights that estimate_num_insns uses to estimate the size of the 11438fd1498Szrj produced code. */ 11538fd1498Szrj 11638fd1498Szrj eni_weights eni_size_weights; 11738fd1498Szrj 11838fd1498Szrj /* Weights that estimate_num_insns uses to estimate the time necessary 11938fd1498Szrj to execute the produced code. */ 12038fd1498Szrj 12138fd1498Szrj eni_weights eni_time_weights; 12238fd1498Szrj 12338fd1498Szrj /* Prototypes. */ 12438fd1498Szrj 12538fd1498Szrj static tree declare_return_variable (copy_body_data *, tree, tree, tree, 12638fd1498Szrj basic_block); 12738fd1498Szrj static void remap_block (tree *, copy_body_data *); 12838fd1498Szrj static void copy_bind_expr (tree *, int *, copy_body_data *); 12938fd1498Szrj static void declare_inline_vars (tree, tree); 13038fd1498Szrj static void remap_save_expr (tree *, hash_map<tree, tree> *, int *); 13138fd1498Szrj static void prepend_lexical_block (tree current_block, tree new_block); 13238fd1498Szrj static tree copy_decl_to_var (tree, copy_body_data *); 13338fd1498Szrj static tree copy_result_decl_to_var (tree, copy_body_data *); 13438fd1498Szrj static tree copy_decl_maybe_to_var (tree, copy_body_data *); 13538fd1498Szrj static gimple_seq remap_gimple_stmt (gimple *, copy_body_data *); 13638fd1498Szrj static bool delete_unreachable_blocks_update_callgraph (copy_body_data *id); 13738fd1498Szrj static void insert_init_stmt (copy_body_data *, basic_block, gimple *); 13838fd1498Szrj 13938fd1498Szrj /* Insert a tree->tree mapping for ID. Despite the name suggests 14038fd1498Szrj that the trees should be variables, it is used for more than that. */ 14138fd1498Szrj 14238fd1498Szrj void 14338fd1498Szrj insert_decl_map (copy_body_data *id, tree key, tree value) 14438fd1498Szrj { 14538fd1498Szrj id->decl_map->put (key, value); 14638fd1498Szrj 14738fd1498Szrj /* Always insert an identity map as well. If we see this same new 14838fd1498Szrj node again, we won't want to duplicate it a second time. */ 14938fd1498Szrj if (key != value) 15038fd1498Szrj id->decl_map->put (value, value); 15138fd1498Szrj } 15238fd1498Szrj 15338fd1498Szrj /* Insert a tree->tree mapping for ID. This is only used for 15438fd1498Szrj variables. */ 15538fd1498Szrj 15638fd1498Szrj static void 15738fd1498Szrj insert_debug_decl_map (copy_body_data *id, tree key, tree value) 15838fd1498Szrj { 15938fd1498Szrj if (!gimple_in_ssa_p (id->src_cfun)) 16038fd1498Szrj return; 16138fd1498Szrj 16238fd1498Szrj if (!opt_for_fn (id->dst_fn, flag_var_tracking_assignments)) 16338fd1498Szrj return; 16438fd1498Szrj 16538fd1498Szrj if (!target_for_debug_bind (key)) 16638fd1498Szrj return; 16738fd1498Szrj 16838fd1498Szrj gcc_assert (TREE_CODE (key) == PARM_DECL); 16938fd1498Szrj gcc_assert (VAR_P (value)); 17038fd1498Szrj 17138fd1498Szrj if (!id->debug_map) 17238fd1498Szrj id->debug_map = new hash_map<tree, tree>; 17338fd1498Szrj 17438fd1498Szrj id->debug_map->put (key, value); 17538fd1498Szrj } 17638fd1498Szrj 17738fd1498Szrj /* If nonzero, we're remapping the contents of inlined debug 17838fd1498Szrj statements. If negative, an error has occurred, such as a 17938fd1498Szrj reference to a variable that isn't available in the inlined 18038fd1498Szrj context. */ 18138fd1498Szrj static int processing_debug_stmt = 0; 18238fd1498Szrj 18338fd1498Szrj /* Construct new SSA name for old NAME. ID is the inline context. */ 18438fd1498Szrj 18538fd1498Szrj static tree 18638fd1498Szrj remap_ssa_name (tree name, copy_body_data *id) 18738fd1498Szrj { 18838fd1498Szrj tree new_tree, var; 18938fd1498Szrj tree *n; 19038fd1498Szrj 19138fd1498Szrj gcc_assert (TREE_CODE (name) == SSA_NAME); 19238fd1498Szrj 19338fd1498Szrj n = id->decl_map->get (name); 19438fd1498Szrj if (n) 19538fd1498Szrj return unshare_expr (*n); 19638fd1498Szrj 19738fd1498Szrj if (processing_debug_stmt) 19838fd1498Szrj { 19938fd1498Szrj if (SSA_NAME_IS_DEFAULT_DEF (name) 20038fd1498Szrj && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL 20138fd1498Szrj && id->entry_bb == NULL 20238fd1498Szrj && single_succ_p (ENTRY_BLOCK_PTR_FOR_FN (cfun))) 20338fd1498Szrj { 20438fd1498Szrj tree vexpr = make_node (DEBUG_EXPR_DECL); 20538fd1498Szrj gimple *def_temp; 20638fd1498Szrj gimple_stmt_iterator gsi; 20738fd1498Szrj tree val = SSA_NAME_VAR (name); 20838fd1498Szrj 20938fd1498Szrj n = id->decl_map->get (val); 21038fd1498Szrj if (n != NULL) 21138fd1498Szrj val = *n; 21238fd1498Szrj if (TREE_CODE (val) != PARM_DECL) 21338fd1498Szrj { 21438fd1498Szrj processing_debug_stmt = -1; 21538fd1498Szrj return name; 21638fd1498Szrj } 21738fd1498Szrj def_temp = gimple_build_debug_source_bind (vexpr, val, NULL); 21838fd1498Szrj DECL_ARTIFICIAL (vexpr) = 1; 21938fd1498Szrj TREE_TYPE (vexpr) = TREE_TYPE (name); 22038fd1498Szrj SET_DECL_MODE (vexpr, DECL_MODE (SSA_NAME_VAR (name))); 22138fd1498Szrj gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun))); 22238fd1498Szrj gsi_insert_before (&gsi, def_temp, GSI_SAME_STMT); 22338fd1498Szrj return vexpr; 22438fd1498Szrj } 22538fd1498Szrj 22638fd1498Szrj processing_debug_stmt = -1; 22738fd1498Szrj return name; 22838fd1498Szrj } 22938fd1498Szrj 23038fd1498Szrj /* Remap anonymous SSA names or SSA names of anonymous decls. */ 23138fd1498Szrj var = SSA_NAME_VAR (name); 23238fd1498Szrj if (!var 23338fd1498Szrj || (!SSA_NAME_IS_DEFAULT_DEF (name) 23438fd1498Szrj && VAR_P (var) 23538fd1498Szrj && !VAR_DECL_IS_VIRTUAL_OPERAND (var) 23638fd1498Szrj && DECL_ARTIFICIAL (var) 23738fd1498Szrj && DECL_IGNORED_P (var) 23838fd1498Szrj && !DECL_NAME (var))) 23938fd1498Szrj { 24038fd1498Szrj struct ptr_info_def *pi; 24138fd1498Szrj new_tree = make_ssa_name (remap_type (TREE_TYPE (name), id)); 24238fd1498Szrj if (!var && SSA_NAME_IDENTIFIER (name)) 24338fd1498Szrj SET_SSA_NAME_VAR_OR_IDENTIFIER (new_tree, SSA_NAME_IDENTIFIER (name)); 24438fd1498Szrj insert_decl_map (id, name, new_tree); 24538fd1498Szrj SSA_NAME_OCCURS_IN_ABNORMAL_PHI (new_tree) 24638fd1498Szrj = SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name); 24738fd1498Szrj /* At least IPA points-to info can be directly transferred. */ 24838fd1498Szrj if (id->src_cfun->gimple_df 24938fd1498Szrj && id->src_cfun->gimple_df->ipa_pta 25038fd1498Szrj && POINTER_TYPE_P (TREE_TYPE (name)) 25138fd1498Szrj && (pi = SSA_NAME_PTR_INFO (name)) 25238fd1498Szrj && !pi->pt.anything) 25338fd1498Szrj { 25438fd1498Szrj struct ptr_info_def *new_pi = get_ptr_info (new_tree); 25538fd1498Szrj new_pi->pt = pi->pt; 25638fd1498Szrj } 25738fd1498Szrj return new_tree; 25838fd1498Szrj } 25938fd1498Szrj 26038fd1498Szrj /* Do not set DEF_STMT yet as statement is not copied yet. We do that 26138fd1498Szrj in copy_bb. */ 26238fd1498Szrj new_tree = remap_decl (var, id); 26338fd1498Szrj 26438fd1498Szrj /* We might've substituted constant or another SSA_NAME for 26538fd1498Szrj the variable. 26638fd1498Szrj 26738fd1498Szrj Replace the SSA name representing RESULT_DECL by variable during 26838fd1498Szrj inlining: this saves us from need to introduce PHI node in a case 26938fd1498Szrj return value is just partly initialized. */ 27038fd1498Szrj if ((VAR_P (new_tree) || TREE_CODE (new_tree) == PARM_DECL) 27138fd1498Szrj && (!SSA_NAME_VAR (name) 27238fd1498Szrj || TREE_CODE (SSA_NAME_VAR (name)) != RESULT_DECL 27338fd1498Szrj || !id->transform_return_to_modify)) 27438fd1498Szrj { 27538fd1498Szrj struct ptr_info_def *pi; 27638fd1498Szrj new_tree = make_ssa_name (new_tree); 27738fd1498Szrj insert_decl_map (id, name, new_tree); 27838fd1498Szrj SSA_NAME_OCCURS_IN_ABNORMAL_PHI (new_tree) 27938fd1498Szrj = SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name); 28038fd1498Szrj /* At least IPA points-to info can be directly transferred. */ 28138fd1498Szrj if (id->src_cfun->gimple_df 28238fd1498Szrj && id->src_cfun->gimple_df->ipa_pta 28338fd1498Szrj && POINTER_TYPE_P (TREE_TYPE (name)) 28438fd1498Szrj && (pi = SSA_NAME_PTR_INFO (name)) 28538fd1498Szrj && !pi->pt.anything) 28638fd1498Szrj { 28738fd1498Szrj struct ptr_info_def *new_pi = get_ptr_info (new_tree); 28838fd1498Szrj new_pi->pt = pi->pt; 28938fd1498Szrj } 29038fd1498Szrj if (SSA_NAME_IS_DEFAULT_DEF (name)) 29138fd1498Szrj { 29238fd1498Szrj /* By inlining function having uninitialized variable, we might 29338fd1498Szrj extend the lifetime (variable might get reused). This cause 29438fd1498Szrj ICE in the case we end up extending lifetime of SSA name across 29538fd1498Szrj abnormal edge, but also increase register pressure. 29638fd1498Szrj 29738fd1498Szrj We simply initialize all uninitialized vars by 0 except 29838fd1498Szrj for case we are inlining to very first BB. We can avoid 29938fd1498Szrj this for all BBs that are not inside strongly connected 30038fd1498Szrj regions of the CFG, but this is expensive to test. */ 30138fd1498Szrj if (id->entry_bb 30238fd1498Szrj && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name) 30338fd1498Szrj && (!SSA_NAME_VAR (name) 30438fd1498Szrj || TREE_CODE (SSA_NAME_VAR (name)) != PARM_DECL) 30538fd1498Szrj && (id->entry_bb != EDGE_SUCC (ENTRY_BLOCK_PTR_FOR_FN (cfun), 30638fd1498Szrj 0)->dest 30738fd1498Szrj || EDGE_COUNT (id->entry_bb->preds) != 1)) 30838fd1498Szrj { 30938fd1498Szrj gimple_stmt_iterator gsi = gsi_last_bb (id->entry_bb); 31038fd1498Szrj gimple *init_stmt; 31138fd1498Szrj tree zero = build_zero_cst (TREE_TYPE (new_tree)); 31238fd1498Szrj 31338fd1498Szrj init_stmt = gimple_build_assign (new_tree, zero); 31438fd1498Szrj gsi_insert_after (&gsi, init_stmt, GSI_NEW_STMT); 31538fd1498Szrj SSA_NAME_IS_DEFAULT_DEF (new_tree) = 0; 31638fd1498Szrj } 31738fd1498Szrj else 31838fd1498Szrj { 31938fd1498Szrj SSA_NAME_DEF_STMT (new_tree) = gimple_build_nop (); 32038fd1498Szrj set_ssa_default_def (cfun, SSA_NAME_VAR (new_tree), new_tree); 32138fd1498Szrj } 32238fd1498Szrj } 32338fd1498Szrj } 32438fd1498Szrj else 32538fd1498Szrj insert_decl_map (id, name, new_tree); 32638fd1498Szrj return new_tree; 32738fd1498Szrj } 32838fd1498Szrj 32938fd1498Szrj /* Remap DECL during the copying of the BLOCK tree for the function. */ 33038fd1498Szrj 33138fd1498Szrj tree 33238fd1498Szrj remap_decl (tree decl, copy_body_data *id) 33338fd1498Szrj { 33438fd1498Szrj tree *n; 33538fd1498Szrj 33638fd1498Szrj /* We only remap local variables in the current function. */ 33738fd1498Szrj 33838fd1498Szrj /* See if we have remapped this declaration. */ 33938fd1498Szrj 34038fd1498Szrj n = id->decl_map->get (decl); 34138fd1498Szrj 34238fd1498Szrj if (!n && processing_debug_stmt) 34338fd1498Szrj { 34438fd1498Szrj processing_debug_stmt = -1; 34538fd1498Szrj return decl; 34638fd1498Szrj } 34738fd1498Szrj 34838fd1498Szrj /* When remapping a type within copy_gimple_seq_and_replace_locals, all 34938fd1498Szrj necessary DECLs have already been remapped and we do not want to duplicate 35038fd1498Szrj a decl coming from outside of the sequence we are copying. */ 35138fd1498Szrj if (!n 35238fd1498Szrj && id->prevent_decl_creation_for_types 35338fd1498Szrj && id->remapping_type_depth > 0 35438fd1498Szrj && (VAR_P (decl) || TREE_CODE (decl) == PARM_DECL)) 35538fd1498Szrj return decl; 35638fd1498Szrj 35738fd1498Szrj /* If we didn't already have an equivalent for this declaration, create one 35838fd1498Szrj now. */ 35938fd1498Szrj if (!n) 36038fd1498Szrj { 36138fd1498Szrj /* Make a copy of the variable or label. */ 36238fd1498Szrj tree t = id->copy_decl (decl, id); 36338fd1498Szrj 36438fd1498Szrj /* Remember it, so that if we encounter this local entity again 36538fd1498Szrj we can reuse this copy. Do this early because remap_type may 36638fd1498Szrj need this decl for TYPE_STUB_DECL. */ 36738fd1498Szrj insert_decl_map (id, decl, t); 36838fd1498Szrj 36938fd1498Szrj if (!DECL_P (t)) 37038fd1498Szrj return t; 37138fd1498Szrj 37238fd1498Szrj /* Remap types, if necessary. */ 37338fd1498Szrj TREE_TYPE (t) = remap_type (TREE_TYPE (t), id); 37438fd1498Szrj if (TREE_CODE (t) == TYPE_DECL) 37538fd1498Szrj { 37638fd1498Szrj DECL_ORIGINAL_TYPE (t) = remap_type (DECL_ORIGINAL_TYPE (t), id); 37738fd1498Szrj 37838fd1498Szrj /* Preserve the invariant that DECL_ORIGINAL_TYPE != TREE_TYPE, 37938fd1498Szrj which is enforced in gen_typedef_die when DECL_ABSTRACT_ORIGIN 38038fd1498Szrj is not set on the TYPE_DECL, for example in LTO mode. */ 38138fd1498Szrj if (DECL_ORIGINAL_TYPE (t) == TREE_TYPE (t)) 38238fd1498Szrj { 38338fd1498Szrj tree x = build_variant_type_copy (TREE_TYPE (t)); 38438fd1498Szrj TYPE_STUB_DECL (x) = TYPE_STUB_DECL (TREE_TYPE (t)); 38538fd1498Szrj TYPE_NAME (x) = TYPE_NAME (TREE_TYPE (t)); 38638fd1498Szrj DECL_ORIGINAL_TYPE (t) = x; 38738fd1498Szrj } 38838fd1498Szrj } 38938fd1498Szrj 39038fd1498Szrj /* Remap sizes as necessary. */ 39138fd1498Szrj walk_tree (&DECL_SIZE (t), copy_tree_body_r, id, NULL); 39238fd1498Szrj walk_tree (&DECL_SIZE_UNIT (t), copy_tree_body_r, id, NULL); 39338fd1498Szrj 39438fd1498Szrj /* If fields, do likewise for offset and qualifier. */ 39538fd1498Szrj if (TREE_CODE (t) == FIELD_DECL) 39638fd1498Szrj { 39738fd1498Szrj walk_tree (&DECL_FIELD_OFFSET (t), copy_tree_body_r, id, NULL); 39838fd1498Szrj if (TREE_CODE (DECL_CONTEXT (t)) == QUAL_UNION_TYPE) 39938fd1498Szrj walk_tree (&DECL_QUALIFIER (t), copy_tree_body_r, id, NULL); 40038fd1498Szrj } 40138fd1498Szrj 40238fd1498Szrj return t; 40338fd1498Szrj } 40438fd1498Szrj 40538fd1498Szrj if (id->do_not_unshare) 40638fd1498Szrj return *n; 40738fd1498Szrj else 40838fd1498Szrj return unshare_expr (*n); 40938fd1498Szrj } 41038fd1498Szrj 41138fd1498Szrj static tree 41238fd1498Szrj remap_type_1 (tree type, copy_body_data *id) 41338fd1498Szrj { 41438fd1498Szrj tree new_tree, t; 41538fd1498Szrj 41638fd1498Szrj /* We do need a copy. build and register it now. If this is a pointer or 41738fd1498Szrj reference type, remap the designated type and make a new pointer or 41838fd1498Szrj reference type. */ 41938fd1498Szrj if (TREE_CODE (type) == POINTER_TYPE) 42038fd1498Szrj { 42138fd1498Szrj new_tree = build_pointer_type_for_mode (remap_type (TREE_TYPE (type), id), 42238fd1498Szrj TYPE_MODE (type), 42338fd1498Szrj TYPE_REF_CAN_ALIAS_ALL (type)); 42438fd1498Szrj if (TYPE_ATTRIBUTES (type) || TYPE_QUALS (type)) 42538fd1498Szrj new_tree = build_type_attribute_qual_variant (new_tree, 42638fd1498Szrj TYPE_ATTRIBUTES (type), 42738fd1498Szrj TYPE_QUALS (type)); 42838fd1498Szrj insert_decl_map (id, type, new_tree); 42938fd1498Szrj return new_tree; 43038fd1498Szrj } 43138fd1498Szrj else if (TREE_CODE (type) == REFERENCE_TYPE) 43238fd1498Szrj { 43338fd1498Szrj new_tree = build_reference_type_for_mode (remap_type (TREE_TYPE (type), id), 43438fd1498Szrj TYPE_MODE (type), 43538fd1498Szrj TYPE_REF_CAN_ALIAS_ALL (type)); 43638fd1498Szrj if (TYPE_ATTRIBUTES (type) || TYPE_QUALS (type)) 43738fd1498Szrj new_tree = build_type_attribute_qual_variant (new_tree, 43838fd1498Szrj TYPE_ATTRIBUTES (type), 43938fd1498Szrj TYPE_QUALS (type)); 44038fd1498Szrj insert_decl_map (id, type, new_tree); 44138fd1498Szrj return new_tree; 44238fd1498Szrj } 44338fd1498Szrj else 44438fd1498Szrj new_tree = copy_node (type); 44538fd1498Szrj 44638fd1498Szrj insert_decl_map (id, type, new_tree); 44738fd1498Szrj 44838fd1498Szrj /* This is a new type, not a copy of an old type. Need to reassociate 44938fd1498Szrj variants. We can handle everything except the main variant lazily. */ 45038fd1498Szrj t = TYPE_MAIN_VARIANT (type); 45138fd1498Szrj if (type != t) 45238fd1498Szrj { 45338fd1498Szrj t = remap_type (t, id); 45438fd1498Szrj TYPE_MAIN_VARIANT (new_tree) = t; 45538fd1498Szrj TYPE_NEXT_VARIANT (new_tree) = TYPE_NEXT_VARIANT (t); 45638fd1498Szrj TYPE_NEXT_VARIANT (t) = new_tree; 45738fd1498Szrj } 45838fd1498Szrj else 45938fd1498Szrj { 46038fd1498Szrj TYPE_MAIN_VARIANT (new_tree) = new_tree; 46138fd1498Szrj TYPE_NEXT_VARIANT (new_tree) = NULL; 46238fd1498Szrj } 46338fd1498Szrj 46438fd1498Szrj if (TYPE_STUB_DECL (type)) 46538fd1498Szrj TYPE_STUB_DECL (new_tree) = remap_decl (TYPE_STUB_DECL (type), id); 46638fd1498Szrj 46738fd1498Szrj /* Lazily create pointer and reference types. */ 46838fd1498Szrj TYPE_POINTER_TO (new_tree) = NULL; 46938fd1498Szrj TYPE_REFERENCE_TO (new_tree) = NULL; 47038fd1498Szrj 47138fd1498Szrj /* Copy all types that may contain references to local variables; be sure to 47238fd1498Szrj preserve sharing in between type and its main variant when possible. */ 47338fd1498Szrj switch (TREE_CODE (new_tree)) 47438fd1498Szrj { 47538fd1498Szrj case INTEGER_TYPE: 47638fd1498Szrj case REAL_TYPE: 47738fd1498Szrj case FIXED_POINT_TYPE: 47838fd1498Szrj case ENUMERAL_TYPE: 47938fd1498Szrj case BOOLEAN_TYPE: 48038fd1498Szrj if (TYPE_MAIN_VARIANT (new_tree) != new_tree) 48138fd1498Szrj { 48238fd1498Szrj gcc_checking_assert (TYPE_MIN_VALUE (type) == TYPE_MIN_VALUE (TYPE_MAIN_VARIANT (type))); 48338fd1498Szrj gcc_checking_assert (TYPE_MAX_VALUE (type) == TYPE_MAX_VALUE (TYPE_MAIN_VARIANT (type))); 48438fd1498Szrj 48538fd1498Szrj TYPE_MIN_VALUE (new_tree) = TYPE_MIN_VALUE (TYPE_MAIN_VARIANT (new_tree)); 48638fd1498Szrj TYPE_MAX_VALUE (new_tree) = TYPE_MAX_VALUE (TYPE_MAIN_VARIANT (new_tree)); 48738fd1498Szrj } 48838fd1498Szrj else 48938fd1498Szrj { 49038fd1498Szrj t = TYPE_MIN_VALUE (new_tree); 49138fd1498Szrj if (t && TREE_CODE (t) != INTEGER_CST) 49238fd1498Szrj walk_tree (&TYPE_MIN_VALUE (new_tree), copy_tree_body_r, id, NULL); 49338fd1498Szrj 49438fd1498Szrj t = TYPE_MAX_VALUE (new_tree); 49538fd1498Szrj if (t && TREE_CODE (t) != INTEGER_CST) 49638fd1498Szrj walk_tree (&TYPE_MAX_VALUE (new_tree), copy_tree_body_r, id, NULL); 49738fd1498Szrj } 49838fd1498Szrj return new_tree; 49938fd1498Szrj 50038fd1498Szrj case FUNCTION_TYPE: 50138fd1498Szrj if (TYPE_MAIN_VARIANT (new_tree) != new_tree 50238fd1498Szrj && TREE_TYPE (type) == TREE_TYPE (TYPE_MAIN_VARIANT (type))) 50338fd1498Szrj TREE_TYPE (new_tree) = TREE_TYPE (TYPE_MAIN_VARIANT (new_tree)); 50438fd1498Szrj else 50538fd1498Szrj TREE_TYPE (new_tree) = remap_type (TREE_TYPE (new_tree), id); 50638fd1498Szrj if (TYPE_MAIN_VARIANT (new_tree) != new_tree 50738fd1498Szrj && TYPE_ARG_TYPES (type) == TYPE_ARG_TYPES (TYPE_MAIN_VARIANT (type))) 50838fd1498Szrj TYPE_ARG_TYPES (new_tree) = TYPE_ARG_TYPES (TYPE_MAIN_VARIANT (new_tree)); 50938fd1498Szrj else 51038fd1498Szrj walk_tree (&TYPE_ARG_TYPES (new_tree), copy_tree_body_r, id, NULL); 51138fd1498Szrj return new_tree; 51238fd1498Szrj 51338fd1498Szrj case ARRAY_TYPE: 51438fd1498Szrj if (TYPE_MAIN_VARIANT (new_tree) != new_tree 51538fd1498Szrj && TREE_TYPE (type) == TREE_TYPE (TYPE_MAIN_VARIANT (type))) 51638fd1498Szrj TREE_TYPE (new_tree) = TREE_TYPE (TYPE_MAIN_VARIANT (new_tree)); 51738fd1498Szrj else 51838fd1498Szrj TREE_TYPE (new_tree) = remap_type (TREE_TYPE (new_tree), id); 51938fd1498Szrj 52038fd1498Szrj if (TYPE_MAIN_VARIANT (new_tree) != new_tree) 52138fd1498Szrj { 52238fd1498Szrj gcc_checking_assert (TYPE_DOMAIN (type) == TYPE_DOMAIN (TYPE_MAIN_VARIANT (type))); 52338fd1498Szrj TYPE_DOMAIN (new_tree) = TYPE_DOMAIN (TYPE_MAIN_VARIANT (new_tree)); 52438fd1498Szrj } 52538fd1498Szrj else 52638fd1498Szrj TYPE_DOMAIN (new_tree) = remap_type (TYPE_DOMAIN (new_tree), id); 52738fd1498Szrj break; 52838fd1498Szrj 52938fd1498Szrj case RECORD_TYPE: 53038fd1498Szrj case UNION_TYPE: 53138fd1498Szrj case QUAL_UNION_TYPE: 53238fd1498Szrj if (TYPE_MAIN_VARIANT (type) != type 53338fd1498Szrj && TYPE_FIELDS (type) == TYPE_FIELDS (TYPE_MAIN_VARIANT (type))) 53438fd1498Szrj TYPE_FIELDS (new_tree) = TYPE_FIELDS (TYPE_MAIN_VARIANT (new_tree)); 53538fd1498Szrj else 53638fd1498Szrj { 53738fd1498Szrj tree f, nf = NULL; 53838fd1498Szrj 53938fd1498Szrj for (f = TYPE_FIELDS (new_tree); f ; f = DECL_CHAIN (f)) 54038fd1498Szrj { 54138fd1498Szrj t = remap_decl (f, id); 54238fd1498Szrj DECL_CONTEXT (t) = new_tree; 54338fd1498Szrj DECL_CHAIN (t) = nf; 54438fd1498Szrj nf = t; 54538fd1498Szrj } 54638fd1498Szrj TYPE_FIELDS (new_tree) = nreverse (nf); 54738fd1498Szrj } 54838fd1498Szrj break; 54938fd1498Szrj 55038fd1498Szrj case OFFSET_TYPE: 55138fd1498Szrj default: 55238fd1498Szrj /* Shouldn't have been thought variable sized. */ 55338fd1498Szrj gcc_unreachable (); 55438fd1498Szrj } 55538fd1498Szrj 55638fd1498Szrj /* All variants of type share the same size, so use the already remaped data. */ 55738fd1498Szrj if (TYPE_MAIN_VARIANT (new_tree) != new_tree) 55838fd1498Szrj { 55938fd1498Szrj tree s = TYPE_SIZE (type); 56038fd1498Szrj tree mvs = TYPE_SIZE (TYPE_MAIN_VARIANT (type)); 56138fd1498Szrj tree su = TYPE_SIZE_UNIT (type); 56238fd1498Szrj tree mvsu = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type)); 56338fd1498Szrj gcc_checking_assert ((TREE_CODE (s) == PLACEHOLDER_EXPR 56438fd1498Szrj && (TREE_CODE (mvs) == PLACEHOLDER_EXPR)) 56538fd1498Szrj || s == mvs); 56638fd1498Szrj gcc_checking_assert ((TREE_CODE (su) == PLACEHOLDER_EXPR 56738fd1498Szrj && (TREE_CODE (mvsu) == PLACEHOLDER_EXPR)) 56838fd1498Szrj || su == mvsu); 56938fd1498Szrj TYPE_SIZE (new_tree) = TYPE_SIZE (TYPE_MAIN_VARIANT (new_tree)); 57038fd1498Szrj TYPE_SIZE_UNIT (new_tree) = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (new_tree)); 57138fd1498Szrj } 57238fd1498Szrj else 57338fd1498Szrj { 57438fd1498Szrj walk_tree (&TYPE_SIZE (new_tree), copy_tree_body_r, id, NULL); 57538fd1498Szrj walk_tree (&TYPE_SIZE_UNIT (new_tree), copy_tree_body_r, id, NULL); 57638fd1498Szrj } 57738fd1498Szrj 57838fd1498Szrj return new_tree; 57938fd1498Szrj } 58038fd1498Szrj 58138fd1498Szrj tree 58238fd1498Szrj remap_type (tree type, copy_body_data *id) 58338fd1498Szrj { 58438fd1498Szrj tree *node; 58538fd1498Szrj tree tmp; 58638fd1498Szrj 58738fd1498Szrj if (type == NULL) 58838fd1498Szrj return type; 58938fd1498Szrj 59038fd1498Szrj /* See if we have remapped this type. */ 59138fd1498Szrj node = id->decl_map->get (type); 59238fd1498Szrj if (node) 59338fd1498Szrj return *node; 59438fd1498Szrj 59538fd1498Szrj /* The type only needs remapping if it's variably modified. */ 59638fd1498Szrj if (! variably_modified_type_p (type, id->src_fn)) 59738fd1498Szrj { 59838fd1498Szrj insert_decl_map (id, type, type); 59938fd1498Szrj return type; 60038fd1498Szrj } 60138fd1498Szrj 60238fd1498Szrj id->remapping_type_depth++; 60338fd1498Szrj tmp = remap_type_1 (type, id); 60438fd1498Szrj id->remapping_type_depth--; 60538fd1498Szrj 60638fd1498Szrj return tmp; 60738fd1498Szrj } 60838fd1498Szrj 60938fd1498Szrj /* Decide if DECL can be put into BLOCK_NONLOCAL_VARs. */ 61038fd1498Szrj 61138fd1498Szrj static bool 61238fd1498Szrj can_be_nonlocal (tree decl, copy_body_data *id) 61338fd1498Szrj { 61438fd1498Szrj /* We can not duplicate function decls. */ 61538fd1498Szrj if (TREE_CODE (decl) == FUNCTION_DECL) 61638fd1498Szrj return true; 61738fd1498Szrj 61838fd1498Szrj /* Local static vars must be non-local or we get multiple declaration 61938fd1498Szrj problems. */ 62038fd1498Szrj if (VAR_P (decl) && !auto_var_in_fn_p (decl, id->src_fn)) 62138fd1498Szrj return true; 62238fd1498Szrj 62338fd1498Szrj return false; 62438fd1498Szrj } 62538fd1498Szrj 62638fd1498Szrj static tree 62738fd1498Szrj remap_decls (tree decls, vec<tree, va_gc> **nonlocalized_list, 62838fd1498Szrj copy_body_data *id) 62938fd1498Szrj { 63038fd1498Szrj tree old_var; 63138fd1498Szrj tree new_decls = NULL_TREE; 63238fd1498Szrj 63338fd1498Szrj /* Remap its variables. */ 63438fd1498Szrj for (old_var = decls; old_var; old_var = DECL_CHAIN (old_var)) 63538fd1498Szrj { 63638fd1498Szrj tree new_var; 63738fd1498Szrj 63838fd1498Szrj if (can_be_nonlocal (old_var, id)) 63938fd1498Szrj { 64038fd1498Szrj /* We need to add this variable to the local decls as otherwise 64138fd1498Szrj nothing else will do so. */ 64238fd1498Szrj if (VAR_P (old_var) && ! DECL_EXTERNAL (old_var) && cfun) 64338fd1498Szrj add_local_decl (cfun, old_var); 64438fd1498Szrj if ((!optimize || debug_info_level > DINFO_LEVEL_TERSE) 64538fd1498Szrj && !DECL_IGNORED_P (old_var) 64638fd1498Szrj && nonlocalized_list) 64738fd1498Szrj vec_safe_push (*nonlocalized_list, old_var); 64838fd1498Szrj continue; 64938fd1498Szrj } 65038fd1498Szrj 65138fd1498Szrj /* Remap the variable. */ 65238fd1498Szrj new_var = remap_decl (old_var, id); 65338fd1498Szrj 65438fd1498Szrj /* If we didn't remap this variable, we can't mess with its 65538fd1498Szrj TREE_CHAIN. If we remapped this variable to the return slot, it's 65638fd1498Szrj already declared somewhere else, so don't declare it here. */ 65738fd1498Szrj 65838fd1498Szrj if (new_var == id->retvar) 65938fd1498Szrj ; 66038fd1498Szrj else if (!new_var) 66138fd1498Szrj { 66238fd1498Szrj if ((!optimize || debug_info_level > DINFO_LEVEL_TERSE) 66338fd1498Szrj && !DECL_IGNORED_P (old_var) 66438fd1498Szrj && nonlocalized_list) 66538fd1498Szrj vec_safe_push (*nonlocalized_list, old_var); 66638fd1498Szrj } 66738fd1498Szrj else 66838fd1498Szrj { 66938fd1498Szrj gcc_assert (DECL_P (new_var)); 67038fd1498Szrj DECL_CHAIN (new_var) = new_decls; 67138fd1498Szrj new_decls = new_var; 67238fd1498Szrj 67338fd1498Szrj /* Also copy value-expressions. */ 67438fd1498Szrj if (VAR_P (new_var) && DECL_HAS_VALUE_EXPR_P (new_var)) 67538fd1498Szrj { 67638fd1498Szrj tree tem = DECL_VALUE_EXPR (new_var); 67738fd1498Szrj bool old_regimplify = id->regimplify; 67838fd1498Szrj id->remapping_type_depth++; 67938fd1498Szrj walk_tree (&tem, copy_tree_body_r, id, NULL); 68038fd1498Szrj id->remapping_type_depth--; 68138fd1498Szrj id->regimplify = old_regimplify; 68238fd1498Szrj SET_DECL_VALUE_EXPR (new_var, tem); 68338fd1498Szrj } 68438fd1498Szrj } 68538fd1498Szrj } 68638fd1498Szrj 68738fd1498Szrj return nreverse (new_decls); 68838fd1498Szrj } 68938fd1498Szrj 69038fd1498Szrj /* Copy the BLOCK to contain remapped versions of the variables 69138fd1498Szrj therein. And hook the new block into the block-tree. */ 69238fd1498Szrj 69338fd1498Szrj static void 69438fd1498Szrj remap_block (tree *block, copy_body_data *id) 69538fd1498Szrj { 69638fd1498Szrj tree old_block; 69738fd1498Szrj tree new_block; 69838fd1498Szrj 69938fd1498Szrj /* Make the new block. */ 70038fd1498Szrj old_block = *block; 70138fd1498Szrj new_block = make_node (BLOCK); 70238fd1498Szrj TREE_USED (new_block) = TREE_USED (old_block); 70338fd1498Szrj BLOCK_ABSTRACT_ORIGIN (new_block) = old_block; 70438fd1498Szrj BLOCK_SOURCE_LOCATION (new_block) = BLOCK_SOURCE_LOCATION (old_block); 70538fd1498Szrj BLOCK_NONLOCALIZED_VARS (new_block) 70638fd1498Szrj = vec_safe_copy (BLOCK_NONLOCALIZED_VARS (old_block)); 70738fd1498Szrj *block = new_block; 70838fd1498Szrj 70938fd1498Szrj /* Remap its variables. */ 71038fd1498Szrj BLOCK_VARS (new_block) = remap_decls (BLOCK_VARS (old_block), 71138fd1498Szrj &BLOCK_NONLOCALIZED_VARS (new_block), 71238fd1498Szrj id); 71338fd1498Szrj 71438fd1498Szrj if (id->transform_lang_insert_block) 71538fd1498Szrj id->transform_lang_insert_block (new_block); 71638fd1498Szrj 71738fd1498Szrj /* Remember the remapped block. */ 71838fd1498Szrj insert_decl_map (id, old_block, new_block); 71938fd1498Szrj } 72038fd1498Szrj 72138fd1498Szrj /* Copy the whole block tree and root it in id->block. */ 72238fd1498Szrj static tree 72338fd1498Szrj remap_blocks (tree block, copy_body_data *id) 72438fd1498Szrj { 72538fd1498Szrj tree t; 72638fd1498Szrj tree new_tree = block; 72738fd1498Szrj 72838fd1498Szrj if (!block) 72938fd1498Szrj return NULL; 73038fd1498Szrj 73138fd1498Szrj remap_block (&new_tree, id); 73238fd1498Szrj gcc_assert (new_tree != block); 73338fd1498Szrj for (t = BLOCK_SUBBLOCKS (block); t ; t = BLOCK_CHAIN (t)) 73438fd1498Szrj prepend_lexical_block (new_tree, remap_blocks (t, id)); 73538fd1498Szrj /* Blocks are in arbitrary order, but make things slightly prettier and do 73638fd1498Szrj not swap order when producing a copy. */ 73738fd1498Szrj BLOCK_SUBBLOCKS (new_tree) = blocks_nreverse (BLOCK_SUBBLOCKS (new_tree)); 73838fd1498Szrj return new_tree; 73938fd1498Szrj } 74038fd1498Szrj 74138fd1498Szrj /* Remap the block tree rooted at BLOCK to nothing. */ 74238fd1498Szrj static void 74338fd1498Szrj remap_blocks_to_null (tree block, copy_body_data *id) 74438fd1498Szrj { 74538fd1498Szrj tree t; 74638fd1498Szrj insert_decl_map (id, block, NULL_TREE); 74738fd1498Szrj for (t = BLOCK_SUBBLOCKS (block); t ; t = BLOCK_CHAIN (t)) 74838fd1498Szrj remap_blocks_to_null (t, id); 74938fd1498Szrj } 75038fd1498Szrj 75138fd1498Szrj static void 75238fd1498Szrj copy_statement_list (tree *tp) 75338fd1498Szrj { 75438fd1498Szrj tree_stmt_iterator oi, ni; 75538fd1498Szrj tree new_tree; 75638fd1498Szrj 75738fd1498Szrj new_tree = alloc_stmt_list (); 75838fd1498Szrj ni = tsi_start (new_tree); 75938fd1498Szrj oi = tsi_start (*tp); 76038fd1498Szrj TREE_TYPE (new_tree) = TREE_TYPE (*tp); 76138fd1498Szrj *tp = new_tree; 76238fd1498Szrj 76338fd1498Szrj for (; !tsi_end_p (oi); tsi_next (&oi)) 76438fd1498Szrj { 76538fd1498Szrj tree stmt = tsi_stmt (oi); 76638fd1498Szrj if (TREE_CODE (stmt) == STATEMENT_LIST) 76738fd1498Szrj /* This copy is not redundant; tsi_link_after will smash this 76838fd1498Szrj STATEMENT_LIST into the end of the one we're building, and we 76938fd1498Szrj don't want to do that with the original. */ 77038fd1498Szrj copy_statement_list (&stmt); 77138fd1498Szrj tsi_link_after (&ni, stmt, TSI_CONTINUE_LINKING); 77238fd1498Szrj } 77338fd1498Szrj } 77438fd1498Szrj 77538fd1498Szrj static void 77638fd1498Szrj copy_bind_expr (tree *tp, int *walk_subtrees, copy_body_data *id) 77738fd1498Szrj { 77838fd1498Szrj tree block = BIND_EXPR_BLOCK (*tp); 77938fd1498Szrj /* Copy (and replace) the statement. */ 78038fd1498Szrj copy_tree_r (tp, walk_subtrees, NULL); 78138fd1498Szrj if (block) 78238fd1498Szrj { 78338fd1498Szrj remap_block (&block, id); 78438fd1498Szrj BIND_EXPR_BLOCK (*tp) = block; 78538fd1498Szrj } 78638fd1498Szrj 78738fd1498Szrj if (BIND_EXPR_VARS (*tp)) 78838fd1498Szrj /* This will remap a lot of the same decls again, but this should be 78938fd1498Szrj harmless. */ 79038fd1498Szrj BIND_EXPR_VARS (*tp) = remap_decls (BIND_EXPR_VARS (*tp), NULL, id); 79138fd1498Szrj } 79238fd1498Szrj 79338fd1498Szrj 79438fd1498Szrj /* Create a new gimple_seq by remapping all the statements in BODY 79538fd1498Szrj using the inlining information in ID. */ 79638fd1498Szrj 79738fd1498Szrj static gimple_seq 79838fd1498Szrj remap_gimple_seq (gimple_seq body, copy_body_data *id) 79938fd1498Szrj { 80038fd1498Szrj gimple_stmt_iterator si; 80138fd1498Szrj gimple_seq new_body = NULL; 80238fd1498Szrj 80338fd1498Szrj for (si = gsi_start (body); !gsi_end_p (si); gsi_next (&si)) 80438fd1498Szrj { 80538fd1498Szrj gimple_seq new_stmts = remap_gimple_stmt (gsi_stmt (si), id); 80638fd1498Szrj gimple_seq_add_seq (&new_body, new_stmts); 80738fd1498Szrj } 80838fd1498Szrj 80938fd1498Szrj return new_body; 81038fd1498Szrj } 81138fd1498Szrj 81238fd1498Szrj 81338fd1498Szrj /* Copy a GIMPLE_BIND statement STMT, remapping all the symbols in its 81438fd1498Szrj block using the mapping information in ID. */ 81538fd1498Szrj 81638fd1498Szrj static gimple * 81738fd1498Szrj copy_gimple_bind (gbind *stmt, copy_body_data *id) 81838fd1498Szrj { 81938fd1498Szrj gimple *new_bind; 82038fd1498Szrj tree new_block, new_vars; 82138fd1498Szrj gimple_seq body, new_body; 82238fd1498Szrj 82338fd1498Szrj /* Copy the statement. Note that we purposely don't use copy_stmt 82438fd1498Szrj here because we need to remap statements as we copy. */ 82538fd1498Szrj body = gimple_bind_body (stmt); 82638fd1498Szrj new_body = remap_gimple_seq (body, id); 82738fd1498Szrj 82838fd1498Szrj new_block = gimple_bind_block (stmt); 82938fd1498Szrj if (new_block) 83038fd1498Szrj remap_block (&new_block, id); 83138fd1498Szrj 83238fd1498Szrj /* This will remap a lot of the same decls again, but this should be 83338fd1498Szrj harmless. */ 83438fd1498Szrj new_vars = gimple_bind_vars (stmt); 83538fd1498Szrj if (new_vars) 83638fd1498Szrj new_vars = remap_decls (new_vars, NULL, id); 83738fd1498Szrj 83838fd1498Szrj new_bind = gimple_build_bind (new_vars, new_body, new_block); 83938fd1498Szrj 84038fd1498Szrj return new_bind; 84138fd1498Szrj } 84238fd1498Szrj 84338fd1498Szrj /* Return true if DECL is a parameter or a SSA_NAME for a parameter. */ 84438fd1498Szrj 84538fd1498Szrj static bool 84638fd1498Szrj is_parm (tree decl) 84738fd1498Szrj { 84838fd1498Szrj if (TREE_CODE (decl) == SSA_NAME) 84938fd1498Szrj { 85038fd1498Szrj decl = SSA_NAME_VAR (decl); 85138fd1498Szrj if (!decl) 85238fd1498Szrj return false; 85338fd1498Szrj } 85438fd1498Szrj 85538fd1498Szrj return (TREE_CODE (decl) == PARM_DECL); 85638fd1498Szrj } 85738fd1498Szrj 85838fd1498Szrj /* Remap the dependence CLIQUE from the source to the destination function 85938fd1498Szrj as specified in ID. */ 86038fd1498Szrj 86138fd1498Szrj static unsigned short 86238fd1498Szrj remap_dependence_clique (copy_body_data *id, unsigned short clique) 86338fd1498Szrj { 86438fd1498Szrj if (clique == 0 || processing_debug_stmt) 86538fd1498Szrj return 0; 86638fd1498Szrj if (!id->dependence_map) 86738fd1498Szrj id->dependence_map = new hash_map<dependence_hash, unsigned short>; 86838fd1498Szrj bool existed; 86938fd1498Szrj unsigned short &newc = id->dependence_map->get_or_insert (clique, &existed); 87038fd1498Szrj if (!existed) 87138fd1498Szrj newc = ++cfun->last_clique; 87238fd1498Szrj return newc; 87338fd1498Szrj } 87438fd1498Szrj 87538fd1498Szrj /* Remap the GIMPLE operand pointed to by *TP. DATA is really a 87638fd1498Szrj 'struct walk_stmt_info *'. DATA->INFO is a 'copy_body_data *'. 87738fd1498Szrj WALK_SUBTREES is used to indicate walk_gimple_op whether to keep 87838fd1498Szrj recursing into the children nodes of *TP. */ 87938fd1498Szrj 88038fd1498Szrj static tree 88138fd1498Szrj remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data) 88238fd1498Szrj { 88338fd1498Szrj struct walk_stmt_info *wi_p = (struct walk_stmt_info *) data; 88438fd1498Szrj copy_body_data *id = (copy_body_data *) wi_p->info; 88538fd1498Szrj tree fn = id->src_fn; 88638fd1498Szrj 88738fd1498Szrj /* For recursive invocations this is no longer the LHS itself. */ 88838fd1498Szrj bool is_lhs = wi_p->is_lhs; 88938fd1498Szrj wi_p->is_lhs = false; 89038fd1498Szrj 89138fd1498Szrj if (TREE_CODE (*tp) == SSA_NAME) 89238fd1498Szrj { 89338fd1498Szrj *tp = remap_ssa_name (*tp, id); 89438fd1498Szrj *walk_subtrees = 0; 89538fd1498Szrj if (is_lhs) 89638fd1498Szrj SSA_NAME_DEF_STMT (*tp) = wi_p->stmt; 89738fd1498Szrj return NULL; 89838fd1498Szrj } 89938fd1498Szrj else if (auto_var_in_fn_p (*tp, fn)) 90038fd1498Szrj { 90138fd1498Szrj /* Local variables and labels need to be replaced by equivalent 90238fd1498Szrj variables. We don't want to copy static variables; there's 90338fd1498Szrj only one of those, no matter how many times we inline the 90438fd1498Szrj containing function. Similarly for globals from an outer 90538fd1498Szrj function. */ 90638fd1498Szrj tree new_decl; 90738fd1498Szrj 90838fd1498Szrj /* Remap the declaration. */ 90938fd1498Szrj new_decl = remap_decl (*tp, id); 91038fd1498Szrj gcc_assert (new_decl); 91138fd1498Szrj /* Replace this variable with the copy. */ 91238fd1498Szrj STRIP_TYPE_NOPS (new_decl); 91338fd1498Szrj /* ??? The C++ frontend uses void * pointer zero to initialize 91438fd1498Szrj any other type. This confuses the middle-end type verification. 91538fd1498Szrj As cloned bodies do not go through gimplification again the fixup 91638fd1498Szrj there doesn't trigger. */ 91738fd1498Szrj if (TREE_CODE (new_decl) == INTEGER_CST 91838fd1498Szrj && !useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (new_decl))) 91938fd1498Szrj new_decl = fold_convert (TREE_TYPE (*tp), new_decl); 92038fd1498Szrj *tp = new_decl; 92138fd1498Szrj *walk_subtrees = 0; 92238fd1498Szrj } 92338fd1498Szrj else if (TREE_CODE (*tp) == STATEMENT_LIST) 92438fd1498Szrj gcc_unreachable (); 92538fd1498Szrj else if (TREE_CODE (*tp) == SAVE_EXPR) 92638fd1498Szrj gcc_unreachable (); 92738fd1498Szrj else if (TREE_CODE (*tp) == LABEL_DECL 92838fd1498Szrj && (!DECL_CONTEXT (*tp) 92938fd1498Szrj || decl_function_context (*tp) == id->src_fn)) 93038fd1498Szrj /* These may need to be remapped for EH handling. */ 93138fd1498Szrj *tp = remap_decl (*tp, id); 93238fd1498Szrj else if (TREE_CODE (*tp) == FIELD_DECL) 93338fd1498Szrj { 93438fd1498Szrj /* If the enclosing record type is variably_modified_type_p, the field 93538fd1498Szrj has already been remapped. Otherwise, it need not be. */ 93638fd1498Szrj tree *n = id->decl_map->get (*tp); 93738fd1498Szrj if (n) 93838fd1498Szrj *tp = *n; 93938fd1498Szrj *walk_subtrees = 0; 94038fd1498Szrj } 94138fd1498Szrj else if (TYPE_P (*tp)) 94238fd1498Szrj /* Types may need remapping as well. */ 94338fd1498Szrj *tp = remap_type (*tp, id); 94438fd1498Szrj else if (CONSTANT_CLASS_P (*tp)) 94538fd1498Szrj { 94638fd1498Szrj /* If this is a constant, we have to copy the node iff the type 94738fd1498Szrj will be remapped. copy_tree_r will not copy a constant. */ 94838fd1498Szrj tree new_type = remap_type (TREE_TYPE (*tp), id); 94938fd1498Szrj 95038fd1498Szrj if (new_type == TREE_TYPE (*tp)) 95138fd1498Szrj *walk_subtrees = 0; 95238fd1498Szrj 95338fd1498Szrj else if (TREE_CODE (*tp) == INTEGER_CST) 95438fd1498Szrj *tp = wide_int_to_tree (new_type, wi::to_wide (*tp)); 95538fd1498Szrj else 95638fd1498Szrj { 95738fd1498Szrj *tp = copy_node (*tp); 95838fd1498Szrj TREE_TYPE (*tp) = new_type; 95938fd1498Szrj } 96038fd1498Szrj } 96138fd1498Szrj else 96238fd1498Szrj { 96338fd1498Szrj /* Otherwise, just copy the node. Note that copy_tree_r already 96438fd1498Szrj knows not to copy VAR_DECLs, etc., so this is safe. */ 96538fd1498Szrj 96638fd1498Szrj if (TREE_CODE (*tp) == MEM_REF) 96738fd1498Szrj { 96838fd1498Szrj /* We need to re-canonicalize MEM_REFs from inline substitutions 96938fd1498Szrj that can happen when a pointer argument is an ADDR_EXPR. 97038fd1498Szrj Recurse here manually to allow that. */ 97138fd1498Szrj tree ptr = TREE_OPERAND (*tp, 0); 97238fd1498Szrj tree type = remap_type (TREE_TYPE (*tp), id); 97338fd1498Szrj tree old = *tp; 97438fd1498Szrj walk_tree (&ptr, remap_gimple_op_r, data, NULL); 97538fd1498Szrj *tp = fold_build2 (MEM_REF, type, ptr, TREE_OPERAND (*tp, 1)); 97638fd1498Szrj TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old); 97738fd1498Szrj TREE_SIDE_EFFECTS (*tp) = TREE_SIDE_EFFECTS (old); 97838fd1498Szrj TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old); 97938fd1498Szrj if (MR_DEPENDENCE_CLIQUE (old) != 0) 98038fd1498Szrj { 98138fd1498Szrj MR_DEPENDENCE_CLIQUE (*tp) 98238fd1498Szrj = remap_dependence_clique (id, MR_DEPENDENCE_CLIQUE (old)); 98338fd1498Szrj MR_DEPENDENCE_BASE (*tp) = MR_DEPENDENCE_BASE (old); 98438fd1498Szrj } 98538fd1498Szrj /* We cannot propagate the TREE_THIS_NOTRAP flag if we have 98638fd1498Szrj remapped a parameter as the property might be valid only 98738fd1498Szrj for the parameter itself. */ 98838fd1498Szrj if (TREE_THIS_NOTRAP (old) 98938fd1498Szrj && (!is_parm (TREE_OPERAND (old, 0)) 99038fd1498Szrj || (!id->transform_parameter && is_parm (ptr)))) 99138fd1498Szrj TREE_THIS_NOTRAP (*tp) = 1; 99238fd1498Szrj REF_REVERSE_STORAGE_ORDER (*tp) = REF_REVERSE_STORAGE_ORDER (old); 99338fd1498Szrj *walk_subtrees = 0; 99438fd1498Szrj return NULL; 99538fd1498Szrj } 99638fd1498Szrj 99738fd1498Szrj /* Here is the "usual case". Copy this tree node, and then 99838fd1498Szrj tweak some special cases. */ 99938fd1498Szrj copy_tree_r (tp, walk_subtrees, NULL); 100038fd1498Szrj 100138fd1498Szrj if (TREE_CODE (*tp) != OMP_CLAUSE) 100238fd1498Szrj TREE_TYPE (*tp) = remap_type (TREE_TYPE (*tp), id); 100338fd1498Szrj 100438fd1498Szrj if (TREE_CODE (*tp) == TARGET_EXPR && TREE_OPERAND (*tp, 3)) 100538fd1498Szrj { 100638fd1498Szrj /* The copied TARGET_EXPR has never been expanded, even if the 100738fd1498Szrj original node was expanded already. */ 100838fd1498Szrj TREE_OPERAND (*tp, 1) = TREE_OPERAND (*tp, 3); 100938fd1498Szrj TREE_OPERAND (*tp, 3) = NULL_TREE; 101038fd1498Szrj } 101138fd1498Szrj else if (TREE_CODE (*tp) == ADDR_EXPR) 101238fd1498Szrj { 101338fd1498Szrj /* Variable substitution need not be simple. In particular, 101438fd1498Szrj the MEM_REF substitution above. Make sure that 101538fd1498Szrj TREE_CONSTANT and friends are up-to-date. */ 101638fd1498Szrj int invariant = is_gimple_min_invariant (*tp); 101738fd1498Szrj walk_tree (&TREE_OPERAND (*tp, 0), remap_gimple_op_r, data, NULL); 101838fd1498Szrj recompute_tree_invariant_for_addr_expr (*tp); 101938fd1498Szrj 102038fd1498Szrj /* If this used to be invariant, but is not any longer, 102138fd1498Szrj then regimplification is probably needed. */ 102238fd1498Szrj if (invariant && !is_gimple_min_invariant (*tp)) 102338fd1498Szrj id->regimplify = true; 102438fd1498Szrj 102538fd1498Szrj *walk_subtrees = 0; 102638fd1498Szrj } 102738fd1498Szrj } 102838fd1498Szrj 102938fd1498Szrj /* Update the TREE_BLOCK for the cloned expr. */ 103038fd1498Szrj if (EXPR_P (*tp)) 103138fd1498Szrj { 103238fd1498Szrj tree new_block = id->remapping_type_depth == 0 ? id->block : NULL; 103338fd1498Szrj tree old_block = TREE_BLOCK (*tp); 103438fd1498Szrj if (old_block) 103538fd1498Szrj { 103638fd1498Szrj tree *n; 103738fd1498Szrj n = id->decl_map->get (TREE_BLOCK (*tp)); 103838fd1498Szrj if (n) 103938fd1498Szrj new_block = *n; 104038fd1498Szrj } 104138fd1498Szrj TREE_SET_BLOCK (*tp, new_block); 104238fd1498Szrj } 104338fd1498Szrj 104438fd1498Szrj /* Keep iterating. */ 104538fd1498Szrj return NULL_TREE; 104638fd1498Szrj } 104738fd1498Szrj 104838fd1498Szrj 104938fd1498Szrj /* Called from copy_body_id via walk_tree. DATA is really a 105038fd1498Szrj `copy_body_data *'. */ 105138fd1498Szrj 105238fd1498Szrj tree 105338fd1498Szrj copy_tree_body_r (tree *tp, int *walk_subtrees, void *data) 105438fd1498Szrj { 105538fd1498Szrj copy_body_data *id = (copy_body_data *) data; 105638fd1498Szrj tree fn = id->src_fn; 105738fd1498Szrj tree new_block; 105838fd1498Szrj 105938fd1498Szrj /* Begin by recognizing trees that we'll completely rewrite for the 106038fd1498Szrj inlining context. Our output for these trees is completely 106138fd1498Szrj different from out input (e.g. RETURN_EXPR is deleted, and morphs 106238fd1498Szrj into an edge). Further down, we'll handle trees that get 106338fd1498Szrj duplicated and/or tweaked. */ 106438fd1498Szrj 106538fd1498Szrj /* When requested, RETURN_EXPRs should be transformed to just the 106638fd1498Szrj contained MODIFY_EXPR. The branch semantics of the return will 106738fd1498Szrj be handled elsewhere by manipulating the CFG rather than a statement. */ 106838fd1498Szrj if (TREE_CODE (*tp) == RETURN_EXPR && id->transform_return_to_modify) 106938fd1498Szrj { 107038fd1498Szrj tree assignment = TREE_OPERAND (*tp, 0); 107138fd1498Szrj 107238fd1498Szrj /* If we're returning something, just turn that into an 107338fd1498Szrj assignment into the equivalent of the original RESULT_DECL. 107438fd1498Szrj If the "assignment" is just the result decl, the result 107538fd1498Szrj decl has already been set (e.g. a recent "foo (&result_decl, 107638fd1498Szrj ...)"); just toss the entire RETURN_EXPR. */ 107738fd1498Szrj if (assignment && TREE_CODE (assignment) == MODIFY_EXPR) 107838fd1498Szrj { 107938fd1498Szrj /* Replace the RETURN_EXPR with (a copy of) the 108038fd1498Szrj MODIFY_EXPR hanging underneath. */ 108138fd1498Szrj *tp = copy_node (assignment); 108238fd1498Szrj } 108338fd1498Szrj else /* Else the RETURN_EXPR returns no value. */ 108438fd1498Szrj { 108538fd1498Szrj *tp = NULL; 108638fd1498Szrj return (tree) (void *)1; 108738fd1498Szrj } 108838fd1498Szrj } 108938fd1498Szrj else if (TREE_CODE (*tp) == SSA_NAME) 109038fd1498Szrj { 109138fd1498Szrj *tp = remap_ssa_name (*tp, id); 109238fd1498Szrj *walk_subtrees = 0; 109338fd1498Szrj return NULL; 109438fd1498Szrj } 109538fd1498Szrj 109638fd1498Szrj /* Local variables and labels need to be replaced by equivalent 109738fd1498Szrj variables. We don't want to copy static variables; there's only 109838fd1498Szrj one of those, no matter how many times we inline the containing 109938fd1498Szrj function. Similarly for globals from an outer function. */ 110038fd1498Szrj else if (auto_var_in_fn_p (*tp, fn)) 110138fd1498Szrj { 110238fd1498Szrj tree new_decl; 110338fd1498Szrj 110438fd1498Szrj /* Remap the declaration. */ 110538fd1498Szrj new_decl = remap_decl (*tp, id); 110638fd1498Szrj gcc_assert (new_decl); 110738fd1498Szrj /* Replace this variable with the copy. */ 110838fd1498Szrj STRIP_TYPE_NOPS (new_decl); 110938fd1498Szrj *tp = new_decl; 111038fd1498Szrj *walk_subtrees = 0; 111138fd1498Szrj } 111238fd1498Szrj else if (TREE_CODE (*tp) == STATEMENT_LIST) 111338fd1498Szrj copy_statement_list (tp); 111438fd1498Szrj else if (TREE_CODE (*tp) == SAVE_EXPR 111538fd1498Szrj || TREE_CODE (*tp) == TARGET_EXPR) 111638fd1498Szrj remap_save_expr (tp, id->decl_map, walk_subtrees); 111738fd1498Szrj else if (TREE_CODE (*tp) == LABEL_DECL 111838fd1498Szrj && (! DECL_CONTEXT (*tp) 111938fd1498Szrj || decl_function_context (*tp) == id->src_fn)) 112038fd1498Szrj /* These may need to be remapped for EH handling. */ 112138fd1498Szrj *tp = remap_decl (*tp, id); 112238fd1498Szrj else if (TREE_CODE (*tp) == BIND_EXPR) 112338fd1498Szrj copy_bind_expr (tp, walk_subtrees, id); 112438fd1498Szrj /* Types may need remapping as well. */ 112538fd1498Szrj else if (TYPE_P (*tp)) 112638fd1498Szrj *tp = remap_type (*tp, id); 112738fd1498Szrj 112838fd1498Szrj /* If this is a constant, we have to copy the node iff the type will be 112938fd1498Szrj remapped. copy_tree_r will not copy a constant. */ 113038fd1498Szrj else if (CONSTANT_CLASS_P (*tp)) 113138fd1498Szrj { 113238fd1498Szrj tree new_type = remap_type (TREE_TYPE (*tp), id); 113338fd1498Szrj 113438fd1498Szrj if (new_type == TREE_TYPE (*tp)) 113538fd1498Szrj *walk_subtrees = 0; 113638fd1498Szrj 113738fd1498Szrj else if (TREE_CODE (*tp) == INTEGER_CST) 113838fd1498Szrj *tp = wide_int_to_tree (new_type, wi::to_wide (*tp)); 113938fd1498Szrj else 114038fd1498Szrj { 114138fd1498Szrj *tp = copy_node (*tp); 114238fd1498Szrj TREE_TYPE (*tp) = new_type; 114338fd1498Szrj } 114438fd1498Szrj } 114538fd1498Szrj 114638fd1498Szrj /* Otherwise, just copy the node. Note that copy_tree_r already 114738fd1498Szrj knows not to copy VAR_DECLs, etc., so this is safe. */ 114838fd1498Szrj else 114938fd1498Szrj { 115038fd1498Szrj /* Here we handle trees that are not completely rewritten. 115138fd1498Szrj First we detect some inlining-induced bogosities for 115238fd1498Szrj discarding. */ 115338fd1498Szrj if (TREE_CODE (*tp) == MODIFY_EXPR 115438fd1498Szrj && TREE_OPERAND (*tp, 0) == TREE_OPERAND (*tp, 1) 115538fd1498Szrj && (auto_var_in_fn_p (TREE_OPERAND (*tp, 0), fn))) 115638fd1498Szrj { 115738fd1498Szrj /* Some assignments VAR = VAR; don't generate any rtl code 115838fd1498Szrj and thus don't count as variable modification. Avoid 115938fd1498Szrj keeping bogosities like 0 = 0. */ 116038fd1498Szrj tree decl = TREE_OPERAND (*tp, 0), value; 116138fd1498Szrj tree *n; 116238fd1498Szrj 116338fd1498Szrj n = id->decl_map->get (decl); 116438fd1498Szrj if (n) 116538fd1498Szrj { 116638fd1498Szrj value = *n; 116738fd1498Szrj STRIP_TYPE_NOPS (value); 116838fd1498Szrj if (TREE_CONSTANT (value) || TREE_READONLY (value)) 116938fd1498Szrj { 117038fd1498Szrj *tp = build_empty_stmt (EXPR_LOCATION (*tp)); 117138fd1498Szrj return copy_tree_body_r (tp, walk_subtrees, data); 117238fd1498Szrj } 117338fd1498Szrj } 117438fd1498Szrj } 117538fd1498Szrj else if (TREE_CODE (*tp) == INDIRECT_REF) 117638fd1498Szrj { 117738fd1498Szrj /* Get rid of *& from inline substitutions that can happen when a 117838fd1498Szrj pointer argument is an ADDR_EXPR. */ 117938fd1498Szrj tree decl = TREE_OPERAND (*tp, 0); 118038fd1498Szrj tree *n = id->decl_map->get (decl); 118138fd1498Szrj if (n) 118238fd1498Szrj { 118338fd1498Szrj /* If we happen to get an ADDR_EXPR in n->value, strip 118438fd1498Szrj it manually here as we'll eventually get ADDR_EXPRs 118538fd1498Szrj which lie about their types pointed to. In this case 118638fd1498Szrj build_fold_indirect_ref wouldn't strip the INDIRECT_REF, 118738fd1498Szrj but we absolutely rely on that. As fold_indirect_ref 118838fd1498Szrj does other useful transformations, try that first, though. */ 118938fd1498Szrj tree type = TREE_TYPE (*tp); 119038fd1498Szrj tree ptr = id->do_not_unshare ? *n : unshare_expr (*n); 119138fd1498Szrj tree old = *tp; 119238fd1498Szrj *tp = gimple_fold_indirect_ref (ptr); 119338fd1498Szrj if (! *tp) 119438fd1498Szrj { 119538fd1498Szrj type = remap_type (type, id); 119638fd1498Szrj if (TREE_CODE (ptr) == ADDR_EXPR) 119738fd1498Szrj { 119838fd1498Szrj *tp 119938fd1498Szrj = fold_indirect_ref_1 (EXPR_LOCATION (ptr), type, ptr); 120038fd1498Szrj /* ??? We should either assert here or build 120138fd1498Szrj a VIEW_CONVERT_EXPR instead of blindly leaking 120238fd1498Szrj incompatible types to our IL. */ 120338fd1498Szrj if (! *tp) 120438fd1498Szrj *tp = TREE_OPERAND (ptr, 0); 120538fd1498Szrj } 120638fd1498Szrj else 120738fd1498Szrj { 120838fd1498Szrj *tp = build1 (INDIRECT_REF, type, ptr); 120938fd1498Szrj TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old); 121038fd1498Szrj TREE_SIDE_EFFECTS (*tp) = TREE_SIDE_EFFECTS (old); 121138fd1498Szrj TREE_READONLY (*tp) = TREE_READONLY (old); 121238fd1498Szrj /* We cannot propagate the TREE_THIS_NOTRAP flag if we 121338fd1498Szrj have remapped a parameter as the property might be 121438fd1498Szrj valid only for the parameter itself. */ 121538fd1498Szrj if (TREE_THIS_NOTRAP (old) 121638fd1498Szrj && (!is_parm (TREE_OPERAND (old, 0)) 121738fd1498Szrj || (!id->transform_parameter && is_parm (ptr)))) 121838fd1498Szrj TREE_THIS_NOTRAP (*tp) = 1; 121938fd1498Szrj } 122038fd1498Szrj } 122138fd1498Szrj *walk_subtrees = 0; 122238fd1498Szrj return NULL; 122338fd1498Szrj } 122438fd1498Szrj } 122538fd1498Szrj else if (TREE_CODE (*tp) == MEM_REF) 122638fd1498Szrj { 122738fd1498Szrj /* We need to re-canonicalize MEM_REFs from inline substitutions 122838fd1498Szrj that can happen when a pointer argument is an ADDR_EXPR. 122938fd1498Szrj Recurse here manually to allow that. */ 123038fd1498Szrj tree ptr = TREE_OPERAND (*tp, 0); 123138fd1498Szrj tree type = remap_type (TREE_TYPE (*tp), id); 123238fd1498Szrj tree old = *tp; 123338fd1498Szrj walk_tree (&ptr, copy_tree_body_r, data, NULL); 123438fd1498Szrj *tp = fold_build2 (MEM_REF, type, ptr, TREE_OPERAND (*tp, 1)); 123538fd1498Szrj TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old); 123638fd1498Szrj TREE_SIDE_EFFECTS (*tp) = TREE_SIDE_EFFECTS (old); 123738fd1498Szrj TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old); 123838fd1498Szrj if (MR_DEPENDENCE_CLIQUE (old) != 0) 123938fd1498Szrj { 124038fd1498Szrj MR_DEPENDENCE_CLIQUE (*tp) 124138fd1498Szrj = remap_dependence_clique (id, MR_DEPENDENCE_CLIQUE (old)); 124238fd1498Szrj MR_DEPENDENCE_BASE (*tp) = MR_DEPENDENCE_BASE (old); 124338fd1498Szrj } 124438fd1498Szrj /* We cannot propagate the TREE_THIS_NOTRAP flag if we have 124538fd1498Szrj remapped a parameter as the property might be valid only 124638fd1498Szrj for the parameter itself. */ 124738fd1498Szrj if (TREE_THIS_NOTRAP (old) 124838fd1498Szrj && (!is_parm (TREE_OPERAND (old, 0)) 124938fd1498Szrj || (!id->transform_parameter && is_parm (ptr)))) 125038fd1498Szrj TREE_THIS_NOTRAP (*tp) = 1; 125138fd1498Szrj REF_REVERSE_STORAGE_ORDER (*tp) = REF_REVERSE_STORAGE_ORDER (old); 125238fd1498Szrj *walk_subtrees = 0; 125338fd1498Szrj return NULL; 125438fd1498Szrj } 125538fd1498Szrj 125638fd1498Szrj /* Here is the "usual case". Copy this tree node, and then 125738fd1498Szrj tweak some special cases. */ 125838fd1498Szrj copy_tree_r (tp, walk_subtrees, NULL); 125938fd1498Szrj 126038fd1498Szrj /* If EXPR has block defined, map it to newly constructed block. 126138fd1498Szrj When inlining we want EXPRs without block appear in the block 126238fd1498Szrj of function call if we are not remapping a type. */ 126338fd1498Szrj if (EXPR_P (*tp)) 126438fd1498Szrj { 126538fd1498Szrj new_block = id->remapping_type_depth == 0 ? id->block : NULL; 126638fd1498Szrj if (TREE_BLOCK (*tp)) 126738fd1498Szrj { 126838fd1498Szrj tree *n; 126938fd1498Szrj n = id->decl_map->get (TREE_BLOCK (*tp)); 127038fd1498Szrj if (n) 127138fd1498Szrj new_block = *n; 127238fd1498Szrj } 127338fd1498Szrj TREE_SET_BLOCK (*tp, new_block); 127438fd1498Szrj } 127538fd1498Szrj 127638fd1498Szrj if (TREE_CODE (*tp) != OMP_CLAUSE) 127738fd1498Szrj TREE_TYPE (*tp) = remap_type (TREE_TYPE (*tp), id); 127838fd1498Szrj 127938fd1498Szrj /* The copied TARGET_EXPR has never been expanded, even if the 128038fd1498Szrj original node was expanded already. */ 128138fd1498Szrj if (TREE_CODE (*tp) == TARGET_EXPR && TREE_OPERAND (*tp, 3)) 128238fd1498Szrj { 128338fd1498Szrj TREE_OPERAND (*tp, 1) = TREE_OPERAND (*tp, 3); 128438fd1498Szrj TREE_OPERAND (*tp, 3) = NULL_TREE; 128538fd1498Szrj } 128638fd1498Szrj 128738fd1498Szrj /* Variable substitution need not be simple. In particular, the 128838fd1498Szrj INDIRECT_REF substitution above. Make sure that TREE_CONSTANT 128938fd1498Szrj and friends are up-to-date. */ 129038fd1498Szrj else if (TREE_CODE (*tp) == ADDR_EXPR) 129138fd1498Szrj { 129238fd1498Szrj int invariant = is_gimple_min_invariant (*tp); 129338fd1498Szrj walk_tree (&TREE_OPERAND (*tp, 0), copy_tree_body_r, id, NULL); 129438fd1498Szrj 129538fd1498Szrj /* Handle the case where we substituted an INDIRECT_REF 129638fd1498Szrj into the operand of the ADDR_EXPR. */ 129738fd1498Szrj if (TREE_CODE (TREE_OPERAND (*tp, 0)) == INDIRECT_REF) 129838fd1498Szrj { 129938fd1498Szrj tree t = TREE_OPERAND (TREE_OPERAND (*tp, 0), 0); 130038fd1498Szrj if (TREE_TYPE (t) != TREE_TYPE (*tp)) 130138fd1498Szrj t = fold_convert (remap_type (TREE_TYPE (*tp), id), t); 130238fd1498Szrj *tp = t; 130338fd1498Szrj } 130438fd1498Szrj else 130538fd1498Szrj recompute_tree_invariant_for_addr_expr (*tp); 130638fd1498Szrj 130738fd1498Szrj /* If this used to be invariant, but is not any longer, 130838fd1498Szrj then regimplification is probably needed. */ 130938fd1498Szrj if (invariant && !is_gimple_min_invariant (*tp)) 131038fd1498Szrj id->regimplify = true; 131138fd1498Szrj 131238fd1498Szrj *walk_subtrees = 0; 131338fd1498Szrj } 131438fd1498Szrj } 131538fd1498Szrj 131638fd1498Szrj /* Keep iterating. */ 131738fd1498Szrj return NULL_TREE; 131838fd1498Szrj } 131938fd1498Szrj 132038fd1498Szrj /* Helper for remap_gimple_stmt. Given an EH region number for the 132138fd1498Szrj source function, map that to the duplicate EH region number in 132238fd1498Szrj the destination function. */ 132338fd1498Szrj 132438fd1498Szrj static int 132538fd1498Szrj remap_eh_region_nr (int old_nr, copy_body_data *id) 132638fd1498Szrj { 132738fd1498Szrj eh_region old_r, new_r; 132838fd1498Szrj 132938fd1498Szrj old_r = get_eh_region_from_number_fn (id->src_cfun, old_nr); 133038fd1498Szrj new_r = static_cast<eh_region> (*id->eh_map->get (old_r)); 133138fd1498Szrj 133238fd1498Szrj return new_r->index; 133338fd1498Szrj } 133438fd1498Szrj 133538fd1498Szrj /* Similar, but operate on INTEGER_CSTs. */ 133638fd1498Szrj 133738fd1498Szrj static tree 133838fd1498Szrj remap_eh_region_tree_nr (tree old_t_nr, copy_body_data *id) 133938fd1498Szrj { 134038fd1498Szrj int old_nr, new_nr; 134138fd1498Szrj 134238fd1498Szrj old_nr = tree_to_shwi (old_t_nr); 134338fd1498Szrj new_nr = remap_eh_region_nr (old_nr, id); 134438fd1498Szrj 134538fd1498Szrj return build_int_cst (integer_type_node, new_nr); 134638fd1498Szrj } 134738fd1498Szrj 134838fd1498Szrj /* Helper for copy_bb. Remap statement STMT using the inlining 134938fd1498Szrj information in ID. Return the new statement copy. */ 135038fd1498Szrj 135138fd1498Szrj static gimple_seq 135238fd1498Szrj remap_gimple_stmt (gimple *stmt, copy_body_data *id) 135338fd1498Szrj { 135438fd1498Szrj gimple *copy = NULL; 135538fd1498Szrj struct walk_stmt_info wi; 135638fd1498Szrj bool skip_first = false; 135738fd1498Szrj gimple_seq stmts = NULL; 135838fd1498Szrj 135938fd1498Szrj if (is_gimple_debug (stmt) 136038fd1498Szrj && (gimple_debug_nonbind_marker_p (stmt) 136138fd1498Szrj ? !DECL_STRUCT_FUNCTION (id->dst_fn)->debug_nonbind_markers 136238fd1498Szrj : !opt_for_fn (id->dst_fn, flag_var_tracking_assignments))) 136338fd1498Szrj return stmts; 136438fd1498Szrj 136538fd1498Szrj /* Begin by recognizing trees that we'll completely rewrite for the 136638fd1498Szrj inlining context. Our output for these trees is completely 136738fd1498Szrj different from out input (e.g. RETURN_EXPR is deleted, and morphs 136838fd1498Szrj into an edge). Further down, we'll handle trees that get 136938fd1498Szrj duplicated and/or tweaked. */ 137038fd1498Szrj 137138fd1498Szrj /* When requested, GIMPLE_RETURNs should be transformed to just the 137238fd1498Szrj contained GIMPLE_ASSIGN. The branch semantics of the return will 137338fd1498Szrj be handled elsewhere by manipulating the CFG rather than the 137438fd1498Szrj statement. */ 137538fd1498Szrj if (gimple_code (stmt) == GIMPLE_RETURN && id->transform_return_to_modify) 137638fd1498Szrj { 137738fd1498Szrj tree retval = gimple_return_retval (as_a <greturn *> (stmt)); 137838fd1498Szrj tree retbnd = gimple_return_retbnd (stmt); 137938fd1498Szrj tree bndslot = id->retbnd; 138038fd1498Szrj 138138fd1498Szrj if (retbnd && bndslot) 138238fd1498Szrj { 138338fd1498Szrj gimple *bndcopy = gimple_build_assign (bndslot, retbnd); 138438fd1498Szrj memset (&wi, 0, sizeof (wi)); 138538fd1498Szrj wi.info = id; 138638fd1498Szrj walk_gimple_op (bndcopy, remap_gimple_op_r, &wi); 138738fd1498Szrj gimple_seq_add_stmt (&stmts, bndcopy); 138838fd1498Szrj } 138938fd1498Szrj 139038fd1498Szrj /* If we're returning something, just turn that into an 139138fd1498Szrj assignment into the equivalent of the original RESULT_DECL. 139238fd1498Szrj If RETVAL is just the result decl, the result decl has 139338fd1498Szrj already been set (e.g. a recent "foo (&result_decl, ...)"); 139438fd1498Szrj just toss the entire GIMPLE_RETURN. */ 139538fd1498Szrj if (retval 139638fd1498Szrj && (TREE_CODE (retval) != RESULT_DECL 139738fd1498Szrj && (TREE_CODE (retval) != SSA_NAME 139838fd1498Szrj || ! SSA_NAME_VAR (retval) 139938fd1498Szrj || TREE_CODE (SSA_NAME_VAR (retval)) != RESULT_DECL))) 140038fd1498Szrj { 140138fd1498Szrj copy = gimple_build_assign (id->do_not_unshare 140238fd1498Szrj ? id->retvar : unshare_expr (id->retvar), 140338fd1498Szrj retval); 140438fd1498Szrj /* id->retvar is already substituted. Skip it on later remapping. */ 140538fd1498Szrj skip_first = true; 140638fd1498Szrj 140738fd1498Szrj /* We need to copy bounds if return structure with pointers into 140838fd1498Szrj instrumented function. */ 140938fd1498Szrj if (chkp_function_instrumented_p (id->dst_fn) 141038fd1498Szrj && !bndslot 141138fd1498Szrj && !BOUNDED_P (id->retvar) 141238fd1498Szrj && chkp_type_has_pointer (TREE_TYPE (id->retvar))) 141338fd1498Szrj id->assign_stmts.safe_push (copy); 141438fd1498Szrj 141538fd1498Szrj } 141638fd1498Szrj else 141738fd1498Szrj return stmts; 141838fd1498Szrj } 141938fd1498Szrj else if (gimple_has_substatements (stmt)) 142038fd1498Szrj { 142138fd1498Szrj gimple_seq s1, s2; 142238fd1498Szrj 142338fd1498Szrj /* When cloning bodies from the C++ front end, we will be handed bodies 142438fd1498Szrj in High GIMPLE form. Handle here all the High GIMPLE statements that 142538fd1498Szrj have embedded statements. */ 142638fd1498Szrj switch (gimple_code (stmt)) 142738fd1498Szrj { 142838fd1498Szrj case GIMPLE_BIND: 142938fd1498Szrj copy = copy_gimple_bind (as_a <gbind *> (stmt), id); 143038fd1498Szrj break; 143138fd1498Szrj 143238fd1498Szrj case GIMPLE_CATCH: 143338fd1498Szrj { 143438fd1498Szrj gcatch *catch_stmt = as_a <gcatch *> (stmt); 143538fd1498Szrj s1 = remap_gimple_seq (gimple_catch_handler (catch_stmt), id); 143638fd1498Szrj copy = gimple_build_catch (gimple_catch_types (catch_stmt), s1); 143738fd1498Szrj } 143838fd1498Szrj break; 143938fd1498Szrj 144038fd1498Szrj case GIMPLE_EH_FILTER: 144138fd1498Szrj s1 = remap_gimple_seq (gimple_eh_filter_failure (stmt), id); 144238fd1498Szrj copy = gimple_build_eh_filter (gimple_eh_filter_types (stmt), s1); 144338fd1498Szrj break; 144438fd1498Szrj 144538fd1498Szrj case GIMPLE_TRY: 144638fd1498Szrj s1 = remap_gimple_seq (gimple_try_eval (stmt), id); 144738fd1498Szrj s2 = remap_gimple_seq (gimple_try_cleanup (stmt), id); 144838fd1498Szrj copy = gimple_build_try (s1, s2, gimple_try_kind (stmt)); 144938fd1498Szrj break; 145038fd1498Szrj 145138fd1498Szrj case GIMPLE_WITH_CLEANUP_EXPR: 145238fd1498Szrj s1 = remap_gimple_seq (gimple_wce_cleanup (stmt), id); 145338fd1498Szrj copy = gimple_build_wce (s1); 145438fd1498Szrj break; 145538fd1498Szrj 145638fd1498Szrj case GIMPLE_OMP_PARALLEL: 145738fd1498Szrj { 145838fd1498Szrj gomp_parallel *omp_par_stmt = as_a <gomp_parallel *> (stmt); 145938fd1498Szrj s1 = remap_gimple_seq (gimple_omp_body (omp_par_stmt), id); 146038fd1498Szrj copy = gimple_build_omp_parallel 146138fd1498Szrj (s1, 146238fd1498Szrj gimple_omp_parallel_clauses (omp_par_stmt), 146338fd1498Szrj gimple_omp_parallel_child_fn (omp_par_stmt), 146438fd1498Szrj gimple_omp_parallel_data_arg (omp_par_stmt)); 146538fd1498Szrj } 146638fd1498Szrj break; 146738fd1498Szrj 146838fd1498Szrj case GIMPLE_OMP_TASK: 146938fd1498Szrj s1 = remap_gimple_seq (gimple_omp_body (stmt), id); 147038fd1498Szrj copy = gimple_build_omp_task 147138fd1498Szrj (s1, 147238fd1498Szrj gimple_omp_task_clauses (stmt), 147338fd1498Szrj gimple_omp_task_child_fn (stmt), 147438fd1498Szrj gimple_omp_task_data_arg (stmt), 147538fd1498Szrj gimple_omp_task_copy_fn (stmt), 147638fd1498Szrj gimple_omp_task_arg_size (stmt), 147738fd1498Szrj gimple_omp_task_arg_align (stmt)); 147838fd1498Szrj break; 147938fd1498Szrj 148038fd1498Szrj case GIMPLE_OMP_FOR: 148138fd1498Szrj s1 = remap_gimple_seq (gimple_omp_body (stmt), id); 148238fd1498Szrj s2 = remap_gimple_seq (gimple_omp_for_pre_body (stmt), id); 148338fd1498Szrj copy = gimple_build_omp_for (s1, gimple_omp_for_kind (stmt), 148438fd1498Szrj gimple_omp_for_clauses (stmt), 148538fd1498Szrj gimple_omp_for_collapse (stmt), s2); 148638fd1498Szrj { 148738fd1498Szrj size_t i; 148838fd1498Szrj for (i = 0; i < gimple_omp_for_collapse (stmt); i++) 148938fd1498Szrj { 149038fd1498Szrj gimple_omp_for_set_index (copy, i, 149138fd1498Szrj gimple_omp_for_index (stmt, i)); 149238fd1498Szrj gimple_omp_for_set_initial (copy, i, 149338fd1498Szrj gimple_omp_for_initial (stmt, i)); 149438fd1498Szrj gimple_omp_for_set_final (copy, i, 149538fd1498Szrj gimple_omp_for_final (stmt, i)); 149638fd1498Szrj gimple_omp_for_set_incr (copy, i, 149738fd1498Szrj gimple_omp_for_incr (stmt, i)); 149838fd1498Szrj gimple_omp_for_set_cond (copy, i, 149938fd1498Szrj gimple_omp_for_cond (stmt, i)); 150038fd1498Szrj } 150138fd1498Szrj } 150238fd1498Szrj break; 150338fd1498Szrj 150438fd1498Szrj case GIMPLE_OMP_MASTER: 150538fd1498Szrj s1 = remap_gimple_seq (gimple_omp_body (stmt), id); 150638fd1498Szrj copy = gimple_build_omp_master (s1); 150738fd1498Szrj break; 150838fd1498Szrj 150938fd1498Szrj case GIMPLE_OMP_TASKGROUP: 151038fd1498Szrj s1 = remap_gimple_seq (gimple_omp_body (stmt), id); 151138fd1498Szrj copy = gimple_build_omp_taskgroup (s1); 151238fd1498Szrj break; 151338fd1498Szrj 151438fd1498Szrj case GIMPLE_OMP_ORDERED: 151538fd1498Szrj s1 = remap_gimple_seq (gimple_omp_body (stmt), id); 151638fd1498Szrj copy = gimple_build_omp_ordered 151738fd1498Szrj (s1, 151838fd1498Szrj gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt))); 151938fd1498Szrj break; 152038fd1498Szrj 152138fd1498Szrj case GIMPLE_OMP_SECTION: 152238fd1498Szrj s1 = remap_gimple_seq (gimple_omp_body (stmt), id); 152338fd1498Szrj copy = gimple_build_omp_section (s1); 152438fd1498Szrj break; 152538fd1498Szrj 152638fd1498Szrj case GIMPLE_OMP_SECTIONS: 152738fd1498Szrj s1 = remap_gimple_seq (gimple_omp_body (stmt), id); 152838fd1498Szrj copy = gimple_build_omp_sections 152938fd1498Szrj (s1, gimple_omp_sections_clauses (stmt)); 153038fd1498Szrj break; 153138fd1498Szrj 153238fd1498Szrj case GIMPLE_OMP_SINGLE: 153338fd1498Szrj s1 = remap_gimple_seq (gimple_omp_body (stmt), id); 153438fd1498Szrj copy = gimple_build_omp_single 153538fd1498Szrj (s1, gimple_omp_single_clauses (stmt)); 153638fd1498Szrj break; 153738fd1498Szrj 153838fd1498Szrj case GIMPLE_OMP_TARGET: 153938fd1498Szrj s1 = remap_gimple_seq (gimple_omp_body (stmt), id); 154038fd1498Szrj copy = gimple_build_omp_target 154138fd1498Szrj (s1, gimple_omp_target_kind (stmt), 154238fd1498Szrj gimple_omp_target_clauses (stmt)); 154338fd1498Szrj break; 154438fd1498Szrj 154538fd1498Szrj case GIMPLE_OMP_TEAMS: 154638fd1498Szrj s1 = remap_gimple_seq (gimple_omp_body (stmt), id); 154738fd1498Szrj copy = gimple_build_omp_teams 154838fd1498Szrj (s1, gimple_omp_teams_clauses (stmt)); 154938fd1498Szrj break; 155038fd1498Szrj 155138fd1498Szrj case GIMPLE_OMP_CRITICAL: 155238fd1498Szrj s1 = remap_gimple_seq (gimple_omp_body (stmt), id); 155338fd1498Szrj copy = gimple_build_omp_critical (s1, 155438fd1498Szrj gimple_omp_critical_name 155538fd1498Szrj (as_a <gomp_critical *> (stmt)), 155638fd1498Szrj gimple_omp_critical_clauses 155738fd1498Szrj (as_a <gomp_critical *> (stmt))); 155838fd1498Szrj break; 155938fd1498Szrj 156038fd1498Szrj case GIMPLE_TRANSACTION: 156138fd1498Szrj { 156238fd1498Szrj gtransaction *old_trans_stmt = as_a <gtransaction *> (stmt); 156338fd1498Szrj gtransaction *new_trans_stmt; 156438fd1498Szrj s1 = remap_gimple_seq (gimple_transaction_body (old_trans_stmt), 156538fd1498Szrj id); 156638fd1498Szrj copy = new_trans_stmt = gimple_build_transaction (s1); 156738fd1498Szrj gimple_transaction_set_subcode (new_trans_stmt, 156838fd1498Szrj gimple_transaction_subcode (old_trans_stmt)); 156938fd1498Szrj gimple_transaction_set_label_norm (new_trans_stmt, 157038fd1498Szrj gimple_transaction_label_norm (old_trans_stmt)); 157138fd1498Szrj gimple_transaction_set_label_uninst (new_trans_stmt, 157238fd1498Szrj gimple_transaction_label_uninst (old_trans_stmt)); 157338fd1498Szrj gimple_transaction_set_label_over (new_trans_stmt, 157438fd1498Szrj gimple_transaction_label_over (old_trans_stmt)); 157538fd1498Szrj } 157638fd1498Szrj break; 157738fd1498Szrj 157838fd1498Szrj default: 157938fd1498Szrj gcc_unreachable (); 158038fd1498Szrj } 158138fd1498Szrj } 158238fd1498Szrj else 158338fd1498Szrj { 158438fd1498Szrj if (gimple_assign_copy_p (stmt) 158538fd1498Szrj && gimple_assign_lhs (stmt) == gimple_assign_rhs1 (stmt) 158638fd1498Szrj && auto_var_in_fn_p (gimple_assign_lhs (stmt), id->src_fn)) 158738fd1498Szrj { 158838fd1498Szrj /* Here we handle statements that are not completely rewritten. 158938fd1498Szrj First we detect some inlining-induced bogosities for 159038fd1498Szrj discarding. */ 159138fd1498Szrj 159238fd1498Szrj /* Some assignments VAR = VAR; don't generate any rtl code 159338fd1498Szrj and thus don't count as variable modification. Avoid 159438fd1498Szrj keeping bogosities like 0 = 0. */ 159538fd1498Szrj tree decl = gimple_assign_lhs (stmt), value; 159638fd1498Szrj tree *n; 159738fd1498Szrj 159838fd1498Szrj n = id->decl_map->get (decl); 159938fd1498Szrj if (n) 160038fd1498Szrj { 160138fd1498Szrj value = *n; 160238fd1498Szrj STRIP_TYPE_NOPS (value); 160338fd1498Szrj if (TREE_CONSTANT (value) || TREE_READONLY (value)) 160438fd1498Szrj return NULL; 160538fd1498Szrj } 160638fd1498Szrj } 160738fd1498Szrj 160838fd1498Szrj /* For *ptr_N ={v} {CLOBBER}, if ptr_N is SSA_NAME defined 160938fd1498Szrj in a block that we aren't copying during tree_function_versioning, 161038fd1498Szrj just drop the clobber stmt. */ 161138fd1498Szrj if (id->blocks_to_copy && gimple_clobber_p (stmt)) 161238fd1498Szrj { 161338fd1498Szrj tree lhs = gimple_assign_lhs (stmt); 161438fd1498Szrj if (TREE_CODE (lhs) == MEM_REF 161538fd1498Szrj && TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME) 161638fd1498Szrj { 161738fd1498Szrj gimple *def_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (lhs, 0)); 161838fd1498Szrj if (gimple_bb (def_stmt) 161938fd1498Szrj && !bitmap_bit_p (id->blocks_to_copy, 162038fd1498Szrj gimple_bb (def_stmt)->index)) 162138fd1498Szrj return NULL; 162238fd1498Szrj } 162338fd1498Szrj } 162438fd1498Szrj 162538fd1498Szrj if (gimple_debug_bind_p (stmt)) 162638fd1498Szrj { 162738fd1498Szrj gdebug *copy 162838fd1498Szrj = gimple_build_debug_bind (gimple_debug_bind_get_var (stmt), 162938fd1498Szrj gimple_debug_bind_get_value (stmt), 163038fd1498Szrj stmt); 163138fd1498Szrj id->debug_stmts.safe_push (copy); 163238fd1498Szrj gimple_seq_add_stmt (&stmts, copy); 163338fd1498Szrj return stmts; 163438fd1498Szrj } 163538fd1498Szrj if (gimple_debug_source_bind_p (stmt)) 163638fd1498Szrj { 163738fd1498Szrj gdebug *copy = gimple_build_debug_source_bind 163838fd1498Szrj (gimple_debug_source_bind_get_var (stmt), 163938fd1498Szrj gimple_debug_source_bind_get_value (stmt), 164038fd1498Szrj stmt); 164138fd1498Szrj id->debug_stmts.safe_push (copy); 164238fd1498Szrj gimple_seq_add_stmt (&stmts, copy); 164338fd1498Szrj return stmts; 164438fd1498Szrj } 164538fd1498Szrj if (gimple_debug_nonbind_marker_p (stmt)) 164638fd1498Szrj { 164738fd1498Szrj /* If the inlined function has too many debug markers, 164838fd1498Szrj don't copy them. */ 164938fd1498Szrj if (id->src_cfun->debug_marker_count 165038fd1498Szrj > PARAM_VALUE (PARAM_MAX_DEBUG_MARKER_COUNT)) 165138fd1498Szrj return stmts; 165238fd1498Szrj 165338fd1498Szrj gdebug *copy = as_a <gdebug *> (gimple_copy (stmt)); 165438fd1498Szrj id->debug_stmts.safe_push (copy); 165538fd1498Szrj gimple_seq_add_stmt (&stmts, copy); 165638fd1498Szrj return stmts; 165738fd1498Szrj } 165838fd1498Szrj gcc_checking_assert (!is_gimple_debug (stmt)); 165938fd1498Szrj 166038fd1498Szrj /* Create a new deep copy of the statement. */ 166138fd1498Szrj copy = gimple_copy (stmt); 166238fd1498Szrj 166338fd1498Szrj /* Clear flags that need revisiting. */ 166438fd1498Szrj if (gcall *call_stmt = dyn_cast <gcall *> (copy)) 166538fd1498Szrj { 166638fd1498Szrj if (gimple_call_tail_p (call_stmt)) 166738fd1498Szrj gimple_call_set_tail (call_stmt, false); 166838fd1498Szrj if (gimple_call_from_thunk_p (call_stmt)) 166938fd1498Szrj gimple_call_set_from_thunk (call_stmt, false); 167038fd1498Szrj if (gimple_call_internal_p (call_stmt)) 167138fd1498Szrj switch (gimple_call_internal_fn (call_stmt)) 167238fd1498Szrj { 167338fd1498Szrj case IFN_GOMP_SIMD_LANE: 167438fd1498Szrj case IFN_GOMP_SIMD_VF: 167538fd1498Szrj case IFN_GOMP_SIMD_LAST_LANE: 167638fd1498Szrj case IFN_GOMP_SIMD_ORDERED_START: 167738fd1498Szrj case IFN_GOMP_SIMD_ORDERED_END: 167838fd1498Szrj DECL_STRUCT_FUNCTION (id->dst_fn)->has_simduid_loops = true; 167938fd1498Szrj break; 168038fd1498Szrj default: 168138fd1498Szrj break; 168238fd1498Szrj } 168338fd1498Szrj } 168438fd1498Szrj 168538fd1498Szrj /* Remap the region numbers for __builtin_eh_{pointer,filter}, 168638fd1498Szrj RESX and EH_DISPATCH. */ 168738fd1498Szrj if (id->eh_map) 168838fd1498Szrj switch (gimple_code (copy)) 168938fd1498Szrj { 169038fd1498Szrj case GIMPLE_CALL: 169138fd1498Szrj { 169238fd1498Szrj tree r, fndecl = gimple_call_fndecl (copy); 169338fd1498Szrj if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) 169438fd1498Szrj switch (DECL_FUNCTION_CODE (fndecl)) 169538fd1498Szrj { 169638fd1498Szrj case BUILT_IN_EH_COPY_VALUES: 169738fd1498Szrj r = gimple_call_arg (copy, 1); 169838fd1498Szrj r = remap_eh_region_tree_nr (r, id); 169938fd1498Szrj gimple_call_set_arg (copy, 1, r); 170038fd1498Szrj /* FALLTHRU */ 170138fd1498Szrj 170238fd1498Szrj case BUILT_IN_EH_POINTER: 170338fd1498Szrj case BUILT_IN_EH_FILTER: 170438fd1498Szrj r = gimple_call_arg (copy, 0); 170538fd1498Szrj r = remap_eh_region_tree_nr (r, id); 170638fd1498Szrj gimple_call_set_arg (copy, 0, r); 170738fd1498Szrj break; 170838fd1498Szrj 170938fd1498Szrj default: 171038fd1498Szrj break; 171138fd1498Szrj } 171238fd1498Szrj 171338fd1498Szrj /* Reset alias info if we didn't apply measures to 171438fd1498Szrj keep it valid over inlining by setting DECL_PT_UID. */ 171538fd1498Szrj if (!id->src_cfun->gimple_df 171638fd1498Szrj || !id->src_cfun->gimple_df->ipa_pta) 171738fd1498Szrj gimple_call_reset_alias_info (as_a <gcall *> (copy)); 171838fd1498Szrj } 171938fd1498Szrj break; 172038fd1498Szrj 172138fd1498Szrj case GIMPLE_RESX: 172238fd1498Szrj { 172338fd1498Szrj gresx *resx_stmt = as_a <gresx *> (copy); 172438fd1498Szrj int r = gimple_resx_region (resx_stmt); 172538fd1498Szrj r = remap_eh_region_nr (r, id); 172638fd1498Szrj gimple_resx_set_region (resx_stmt, r); 172738fd1498Szrj } 172838fd1498Szrj break; 172938fd1498Szrj 173038fd1498Szrj case GIMPLE_EH_DISPATCH: 173138fd1498Szrj { 173238fd1498Szrj geh_dispatch *eh_dispatch = as_a <geh_dispatch *> (copy); 173338fd1498Szrj int r = gimple_eh_dispatch_region (eh_dispatch); 173438fd1498Szrj r = remap_eh_region_nr (r, id); 173538fd1498Szrj gimple_eh_dispatch_set_region (eh_dispatch, r); 173638fd1498Szrj } 173738fd1498Szrj break; 173838fd1498Szrj 173938fd1498Szrj default: 174038fd1498Szrj break; 174138fd1498Szrj } 174238fd1498Szrj } 174338fd1498Szrj 174438fd1498Szrj /* If STMT has a block defined, map it to the newly constructed 174538fd1498Szrj block. */ 174638fd1498Szrj if (gimple_block (copy)) 174738fd1498Szrj { 174838fd1498Szrj tree *n; 174938fd1498Szrj n = id->decl_map->get (gimple_block (copy)); 175038fd1498Szrj gcc_assert (n); 175138fd1498Szrj gimple_set_block (copy, *n); 175238fd1498Szrj } 175338fd1498Szrj 175438fd1498Szrj if (gimple_debug_bind_p (copy) || gimple_debug_source_bind_p (copy) 175538fd1498Szrj || gimple_debug_nonbind_marker_p (copy)) 175638fd1498Szrj { 175738fd1498Szrj gimple_seq_add_stmt (&stmts, copy); 175838fd1498Szrj return stmts; 175938fd1498Szrj } 176038fd1498Szrj 176138fd1498Szrj /* Remap all the operands in COPY. */ 176238fd1498Szrj memset (&wi, 0, sizeof (wi)); 176338fd1498Szrj wi.info = id; 176438fd1498Szrj if (skip_first) 176538fd1498Szrj walk_tree (gimple_op_ptr (copy, 1), remap_gimple_op_r, &wi, NULL); 176638fd1498Szrj else 176738fd1498Szrj walk_gimple_op (copy, remap_gimple_op_r, &wi); 176838fd1498Szrj 176938fd1498Szrj /* Clear the copied virtual operands. We are not remapping them here 177038fd1498Szrj but are going to recreate them from scratch. */ 177138fd1498Szrj if (gimple_has_mem_ops (copy)) 177238fd1498Szrj { 177338fd1498Szrj gimple_set_vdef (copy, NULL_TREE); 177438fd1498Szrj gimple_set_vuse (copy, NULL_TREE); 177538fd1498Szrj } 177638fd1498Szrj 177738fd1498Szrj gimple_seq_add_stmt (&stmts, copy); 177838fd1498Szrj return stmts; 177938fd1498Szrj } 178038fd1498Szrj 178138fd1498Szrj 178238fd1498Szrj /* Copy basic block, scale profile accordingly. Edges will be taken care of 178338fd1498Szrj later */ 178438fd1498Szrj 178538fd1498Szrj static basic_block 178638fd1498Szrj copy_bb (copy_body_data *id, basic_block bb, 178738fd1498Szrj profile_count num, profile_count den) 178838fd1498Szrj { 178938fd1498Szrj gimple_stmt_iterator gsi, copy_gsi, seq_gsi; 179038fd1498Szrj basic_block copy_basic_block; 179138fd1498Szrj tree decl; 179238fd1498Szrj basic_block prev; 179338fd1498Szrj 179438fd1498Szrj profile_count::adjust_for_ipa_scaling (&num, &den); 179538fd1498Szrj 179638fd1498Szrj /* Search for previous copied basic block. */ 179738fd1498Szrj prev = bb->prev_bb; 179838fd1498Szrj while (!prev->aux) 179938fd1498Szrj prev = prev->prev_bb; 180038fd1498Szrj 180138fd1498Szrj /* create_basic_block() will append every new block to 180238fd1498Szrj basic_block_info automatically. */ 180338fd1498Szrj copy_basic_block = create_basic_block (NULL, (basic_block) prev->aux); 180438fd1498Szrj copy_basic_block->count = bb->count.apply_scale (num, den); 180538fd1498Szrj 180638fd1498Szrj copy_gsi = gsi_start_bb (copy_basic_block); 180738fd1498Szrj 180838fd1498Szrj for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) 180938fd1498Szrj { 181038fd1498Szrj gimple_seq stmts; 181138fd1498Szrj gimple *stmt = gsi_stmt (gsi); 181238fd1498Szrj gimple *orig_stmt = stmt; 181338fd1498Szrj gimple_stmt_iterator stmts_gsi; 181438fd1498Szrj bool stmt_added = false; 181538fd1498Szrj 181638fd1498Szrj id->regimplify = false; 181738fd1498Szrj stmts = remap_gimple_stmt (stmt, id); 181838fd1498Szrj 181938fd1498Szrj if (gimple_seq_empty_p (stmts)) 182038fd1498Szrj continue; 182138fd1498Szrj 182238fd1498Szrj seq_gsi = copy_gsi; 182338fd1498Szrj 182438fd1498Szrj for (stmts_gsi = gsi_start (stmts); 182538fd1498Szrj !gsi_end_p (stmts_gsi); ) 182638fd1498Szrj { 182738fd1498Szrj stmt = gsi_stmt (stmts_gsi); 182838fd1498Szrj 182938fd1498Szrj /* Advance iterator now before stmt is moved to seq_gsi. */ 183038fd1498Szrj gsi_next (&stmts_gsi); 183138fd1498Szrj 183238fd1498Szrj if (gimple_nop_p (stmt)) 183338fd1498Szrj continue; 183438fd1498Szrj 183538fd1498Szrj gimple_duplicate_stmt_histograms (cfun, stmt, id->src_cfun, 183638fd1498Szrj orig_stmt); 183738fd1498Szrj 183838fd1498Szrj /* With return slot optimization we can end up with 183938fd1498Szrj non-gimple (foo *)&this->m, fix that here. */ 184038fd1498Szrj if (is_gimple_assign (stmt) 184138fd1498Szrj && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt)) 184238fd1498Szrj && !is_gimple_val (gimple_assign_rhs1 (stmt))) 184338fd1498Szrj { 184438fd1498Szrj tree new_rhs; 184538fd1498Szrj new_rhs = force_gimple_operand_gsi (&seq_gsi, 184638fd1498Szrj gimple_assign_rhs1 (stmt), 184738fd1498Szrj true, NULL, false, 184838fd1498Szrj GSI_CONTINUE_LINKING); 184938fd1498Szrj gimple_assign_set_rhs1 (stmt, new_rhs); 185038fd1498Szrj id->regimplify = false; 185138fd1498Szrj } 185238fd1498Szrj 185338fd1498Szrj gsi_insert_after (&seq_gsi, stmt, GSI_NEW_STMT); 185438fd1498Szrj 185538fd1498Szrj if (id->regimplify) 185638fd1498Szrj gimple_regimplify_operands (stmt, &seq_gsi); 185738fd1498Szrj 185838fd1498Szrj stmt_added = true; 185938fd1498Szrj } 186038fd1498Szrj 186138fd1498Szrj if (!stmt_added) 186238fd1498Szrj continue; 186338fd1498Szrj 186438fd1498Szrj /* If copy_basic_block has been empty at the start of this iteration, 186538fd1498Szrj call gsi_start_bb again to get at the newly added statements. */ 186638fd1498Szrj if (gsi_end_p (copy_gsi)) 186738fd1498Szrj copy_gsi = gsi_start_bb (copy_basic_block); 186838fd1498Szrj else 186938fd1498Szrj gsi_next (©_gsi); 187038fd1498Szrj 187138fd1498Szrj /* Process the new statement. The call to gimple_regimplify_operands 187238fd1498Szrj possibly turned the statement into multiple statements, we 187338fd1498Szrj need to process all of them. */ 187438fd1498Szrj do 187538fd1498Szrj { 187638fd1498Szrj tree fn; 187738fd1498Szrj gcall *call_stmt; 187838fd1498Szrj 187938fd1498Szrj stmt = gsi_stmt (copy_gsi); 188038fd1498Szrj call_stmt = dyn_cast <gcall *> (stmt); 188138fd1498Szrj if (call_stmt 188238fd1498Szrj && gimple_call_va_arg_pack_p (call_stmt) 188338fd1498Szrj && id->call_stmt 188438fd1498Szrj && ! gimple_call_va_arg_pack_p (id->call_stmt)) 188538fd1498Szrj { 188638fd1498Szrj /* __builtin_va_arg_pack () should be replaced by 188738fd1498Szrj all arguments corresponding to ... in the caller. */ 188838fd1498Szrj tree p; 188938fd1498Szrj gcall *new_call; 189038fd1498Szrj vec<tree> argarray; 189138fd1498Szrj size_t nargs = gimple_call_num_args (id->call_stmt); 189238fd1498Szrj size_t n, i, nargs_to_copy; 189338fd1498Szrj bool remove_bounds = false; 189438fd1498Szrj 189538fd1498Szrj for (p = DECL_ARGUMENTS (id->src_fn); p; p = DECL_CHAIN (p)) 189638fd1498Szrj nargs--; 189738fd1498Szrj 189838fd1498Szrj /* Bounds should be removed from arg pack in case 189938fd1498Szrj we handle not instrumented call in instrumented 190038fd1498Szrj function. */ 190138fd1498Szrj nargs_to_copy = nargs; 190238fd1498Szrj if (gimple_call_with_bounds_p (id->call_stmt) 190338fd1498Szrj && !gimple_call_with_bounds_p (stmt)) 190438fd1498Szrj { 190538fd1498Szrj for (i = gimple_call_num_args (id->call_stmt) - nargs; 190638fd1498Szrj i < gimple_call_num_args (id->call_stmt); 190738fd1498Szrj i++) 190838fd1498Szrj if (POINTER_BOUNDS_P (gimple_call_arg (id->call_stmt, i))) 190938fd1498Szrj nargs_to_copy--; 191038fd1498Szrj remove_bounds = true; 191138fd1498Szrj } 191238fd1498Szrj 191338fd1498Szrj /* Create the new array of arguments. */ 191438fd1498Szrj n = nargs_to_copy + gimple_call_num_args (call_stmt); 191538fd1498Szrj argarray.create (n); 191638fd1498Szrj argarray.safe_grow_cleared (n); 191738fd1498Szrj 191838fd1498Szrj /* Copy all the arguments before '...' */ 191938fd1498Szrj memcpy (argarray.address (), 192038fd1498Szrj gimple_call_arg_ptr (call_stmt, 0), 192138fd1498Szrj gimple_call_num_args (call_stmt) * sizeof (tree)); 192238fd1498Szrj 192338fd1498Szrj if (remove_bounds) 192438fd1498Szrj { 192538fd1498Szrj /* Append the rest of arguments removing bounds. */ 192638fd1498Szrj unsigned cur = gimple_call_num_args (call_stmt); 192738fd1498Szrj i = gimple_call_num_args (id->call_stmt) - nargs; 192838fd1498Szrj for (i = gimple_call_num_args (id->call_stmt) - nargs; 192938fd1498Szrj i < gimple_call_num_args (id->call_stmt); 193038fd1498Szrj i++) 193138fd1498Szrj if (!POINTER_BOUNDS_P (gimple_call_arg (id->call_stmt, i))) 193238fd1498Szrj argarray[cur++] = gimple_call_arg (id->call_stmt, i); 193338fd1498Szrj gcc_assert (cur == n); 193438fd1498Szrj } 193538fd1498Szrj else 193638fd1498Szrj { 193738fd1498Szrj /* Append the arguments passed in '...' */ 193838fd1498Szrj memcpy (argarray.address () + gimple_call_num_args (call_stmt), 193938fd1498Szrj gimple_call_arg_ptr (id->call_stmt, 0) 194038fd1498Szrj + (gimple_call_num_args (id->call_stmt) - nargs), 194138fd1498Szrj nargs * sizeof (tree)); 194238fd1498Szrj } 194338fd1498Szrj 194438fd1498Szrj new_call = gimple_build_call_vec (gimple_call_fn (call_stmt), 194538fd1498Szrj argarray); 194638fd1498Szrj 194738fd1498Szrj argarray.release (); 194838fd1498Szrj 194938fd1498Szrj /* Copy all GIMPLE_CALL flags, location and block, except 195038fd1498Szrj GF_CALL_VA_ARG_PACK. */ 195138fd1498Szrj gimple_call_copy_flags (new_call, call_stmt); 195238fd1498Szrj gimple_call_set_va_arg_pack (new_call, false); 195338fd1498Szrj gimple_set_location (new_call, gimple_location (stmt)); 195438fd1498Szrj gimple_set_block (new_call, gimple_block (stmt)); 195538fd1498Szrj gimple_call_set_lhs (new_call, gimple_call_lhs (call_stmt)); 195638fd1498Szrj 195738fd1498Szrj gsi_replace (©_gsi, new_call, false); 195838fd1498Szrj stmt = new_call; 195938fd1498Szrj } 196038fd1498Szrj else if (call_stmt 196138fd1498Szrj && id->call_stmt 196238fd1498Szrj && (decl = gimple_call_fndecl (stmt)) 196338fd1498Szrj && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL 1964*58e805e6Szrj && DECL_FUNCTION_CODE (decl) == BUILT_IN_VA_ARG_PACK_LEN) 196538fd1498Szrj { 196638fd1498Szrj /* __builtin_va_arg_pack_len () should be replaced by 196738fd1498Szrj the number of anonymous arguments. */ 196838fd1498Szrj size_t nargs = gimple_call_num_args (id->call_stmt), i; 196938fd1498Szrj tree count, p; 197038fd1498Szrj gimple *new_stmt; 197138fd1498Szrj 197238fd1498Szrj for (p = DECL_ARGUMENTS (id->src_fn); p; p = DECL_CHAIN (p)) 197338fd1498Szrj nargs--; 197438fd1498Szrj 197538fd1498Szrj /* For instrumented calls we should ignore bounds. */ 197638fd1498Szrj for (i = gimple_call_num_args (id->call_stmt) - nargs; 197738fd1498Szrj i < gimple_call_num_args (id->call_stmt); 197838fd1498Szrj i++) 197938fd1498Szrj if (POINTER_BOUNDS_P (gimple_call_arg (id->call_stmt, i))) 198038fd1498Szrj nargs--; 198138fd1498Szrj 1982*58e805e6Szrj if (!gimple_call_lhs (stmt)) 1983*58e805e6Szrj { 1984*58e805e6Szrj /* Drop unused calls. */ 1985*58e805e6Szrj gsi_remove (©_gsi, false); 1986*58e805e6Szrj continue; 1987*58e805e6Szrj } 1988*58e805e6Szrj else if (!gimple_call_va_arg_pack_p (id->call_stmt)) 1989*58e805e6Szrj { 199038fd1498Szrj count = build_int_cst (integer_type_node, nargs); 199138fd1498Szrj new_stmt = gimple_build_assign (gimple_call_lhs (stmt), count); 199238fd1498Szrj gsi_replace (©_gsi, new_stmt, false); 199338fd1498Szrj stmt = new_stmt; 199438fd1498Szrj } 1995*58e805e6Szrj else if (nargs != 0) 1996*58e805e6Szrj { 1997*58e805e6Szrj tree newlhs = create_tmp_reg_or_ssa_name (integer_type_node); 1998*58e805e6Szrj count = build_int_cst (integer_type_node, nargs); 1999*58e805e6Szrj new_stmt = gimple_build_assign (gimple_call_lhs (stmt), 2000*58e805e6Szrj PLUS_EXPR, newlhs, count); 2001*58e805e6Szrj gimple_call_set_lhs (stmt, newlhs); 2002*58e805e6Szrj gsi_insert_after (©_gsi, new_stmt, GSI_NEW_STMT); 2003*58e805e6Szrj } 2004*58e805e6Szrj } 200538fd1498Szrj else if (call_stmt 200638fd1498Szrj && id->call_stmt 200738fd1498Szrj && gimple_call_internal_p (stmt) 200838fd1498Szrj && gimple_call_internal_fn (stmt) == IFN_TSAN_FUNC_EXIT) 200938fd1498Szrj { 201038fd1498Szrj /* Drop TSAN_FUNC_EXIT () internal calls during inlining. */ 201138fd1498Szrj gsi_remove (©_gsi, false); 201238fd1498Szrj continue; 201338fd1498Szrj } 201438fd1498Szrj 201538fd1498Szrj /* Statements produced by inlining can be unfolded, especially 201638fd1498Szrj when we constant propagated some operands. We can't fold 201738fd1498Szrj them right now for two reasons: 201838fd1498Szrj 1) folding require SSA_NAME_DEF_STMTs to be correct 201938fd1498Szrj 2) we can't change function calls to builtins. 202038fd1498Szrj So we just mark statement for later folding. We mark 202138fd1498Szrj all new statements, instead just statements that has changed 202238fd1498Szrj by some nontrivial substitution so even statements made 202338fd1498Szrj foldable indirectly are updated. If this turns out to be 202438fd1498Szrj expensive, copy_body can be told to watch for nontrivial 202538fd1498Szrj changes. */ 202638fd1498Szrj if (id->statements_to_fold) 202738fd1498Szrj id->statements_to_fold->add (stmt); 202838fd1498Szrj 202938fd1498Szrj /* We're duplicating a CALL_EXPR. Find any corresponding 203038fd1498Szrj callgraph edges and update or duplicate them. */ 203138fd1498Szrj if (gcall *call_stmt = dyn_cast <gcall *> (stmt)) 203238fd1498Szrj { 203338fd1498Szrj struct cgraph_edge *edge; 203438fd1498Szrj 203538fd1498Szrj switch (id->transform_call_graph_edges) 203638fd1498Szrj { 203738fd1498Szrj case CB_CGE_DUPLICATE: 203838fd1498Szrj edge = id->src_node->get_edge (orig_stmt); 203938fd1498Szrj if (edge) 204038fd1498Szrj { 204138fd1498Szrj struct cgraph_edge *old_edge = edge; 204238fd1498Szrj profile_count old_cnt = edge->count; 204338fd1498Szrj edge = edge->clone (id->dst_node, call_stmt, 204438fd1498Szrj gimple_uid (stmt), 204538fd1498Szrj num, den, 204638fd1498Szrj true); 204738fd1498Szrj 204838fd1498Szrj /* Speculative calls consist of two edges - direct and 204938fd1498Szrj indirect. Duplicate the whole thing and distribute 205038fd1498Szrj frequencies accordingly. */ 205138fd1498Szrj if (edge->speculative) 205238fd1498Szrj { 205338fd1498Szrj struct cgraph_edge *direct, *indirect; 205438fd1498Szrj struct ipa_ref *ref; 205538fd1498Szrj 205638fd1498Szrj gcc_assert (!edge->indirect_unknown_callee); 205738fd1498Szrj old_edge->speculative_call_info (direct, indirect, ref); 205838fd1498Szrj 205938fd1498Szrj profile_count indir_cnt = indirect->count; 206038fd1498Szrj indirect = indirect->clone (id->dst_node, call_stmt, 206138fd1498Szrj gimple_uid (stmt), 206238fd1498Szrj num, den, 206338fd1498Szrj true); 206438fd1498Szrj 206538fd1498Szrj profile_probability prob 206638fd1498Szrj = indir_cnt.probability_in (old_cnt + indir_cnt); 206738fd1498Szrj indirect->count 206838fd1498Szrj = copy_basic_block->count.apply_probability (prob); 206938fd1498Szrj edge->count = copy_basic_block->count - indirect->count; 207038fd1498Szrj id->dst_node->clone_reference (ref, stmt); 207138fd1498Szrj } 207238fd1498Szrj else 207338fd1498Szrj edge->count = copy_basic_block->count; 207438fd1498Szrj } 207538fd1498Szrj break; 207638fd1498Szrj 207738fd1498Szrj case CB_CGE_MOVE_CLONES: 207838fd1498Szrj id->dst_node->set_call_stmt_including_clones (orig_stmt, 207938fd1498Szrj call_stmt); 208038fd1498Szrj edge = id->dst_node->get_edge (stmt); 208138fd1498Szrj break; 208238fd1498Szrj 208338fd1498Szrj case CB_CGE_MOVE: 208438fd1498Szrj edge = id->dst_node->get_edge (orig_stmt); 208538fd1498Szrj if (edge) 208638fd1498Szrj edge->set_call_stmt (call_stmt); 208738fd1498Szrj break; 208838fd1498Szrj 208938fd1498Szrj default: 209038fd1498Szrj gcc_unreachable (); 209138fd1498Szrj } 209238fd1498Szrj 209338fd1498Szrj /* Constant propagation on argument done during inlining 209438fd1498Szrj may create new direct call. Produce an edge for it. */ 209538fd1498Szrj if ((!edge 209638fd1498Szrj || (edge->indirect_inlining_edge 209738fd1498Szrj && id->transform_call_graph_edges == CB_CGE_MOVE_CLONES)) 209838fd1498Szrj && id->dst_node->definition 209938fd1498Szrj && (fn = gimple_call_fndecl (stmt)) != NULL) 210038fd1498Szrj { 210138fd1498Szrj struct cgraph_node *dest = cgraph_node::get_create (fn); 210238fd1498Szrj 210338fd1498Szrj /* We have missing edge in the callgraph. This can happen 210438fd1498Szrj when previous inlining turned an indirect call into a 210538fd1498Szrj direct call by constant propagating arguments or we are 210638fd1498Szrj producing dead clone (for further cloning). In all 210738fd1498Szrj other cases we hit a bug (incorrect node sharing is the 210838fd1498Szrj most common reason for missing edges). */ 210938fd1498Szrj gcc_assert (!dest->definition 211038fd1498Szrj || dest->address_taken 211138fd1498Szrj || !id->src_node->definition 211238fd1498Szrj || !id->dst_node->definition); 211338fd1498Szrj if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES) 211438fd1498Szrj id->dst_node->create_edge_including_clones 211538fd1498Szrj (dest, orig_stmt, call_stmt, bb->count, 211638fd1498Szrj CIF_ORIGINALLY_INDIRECT_CALL); 211738fd1498Szrj else 211838fd1498Szrj id->dst_node->create_edge (dest, call_stmt, 211938fd1498Szrj bb->count)->inline_failed 212038fd1498Szrj = CIF_ORIGINALLY_INDIRECT_CALL; 212138fd1498Szrj if (dump_file) 212238fd1498Szrj { 212338fd1498Szrj fprintf (dump_file, "Created new direct edge to %s\n", 212438fd1498Szrj dest->name ()); 212538fd1498Szrj } 212638fd1498Szrj } 212738fd1498Szrj 212838fd1498Szrj notice_special_calls (as_a <gcall *> (stmt)); 212938fd1498Szrj } 213038fd1498Szrj 213138fd1498Szrj maybe_duplicate_eh_stmt_fn (cfun, stmt, id->src_cfun, orig_stmt, 213238fd1498Szrj id->eh_map, id->eh_lp_nr); 213338fd1498Szrj 213438fd1498Szrj gsi_next (©_gsi); 213538fd1498Szrj } 213638fd1498Szrj while (!gsi_end_p (copy_gsi)); 213738fd1498Szrj 213838fd1498Szrj copy_gsi = gsi_last_bb (copy_basic_block); 213938fd1498Szrj } 214038fd1498Szrj 214138fd1498Szrj return copy_basic_block; 214238fd1498Szrj } 214338fd1498Szrj 214438fd1498Szrj /* Inserting Single Entry Multiple Exit region in SSA form into code in SSA 214538fd1498Szrj form is quite easy, since dominator relationship for old basic blocks does 214638fd1498Szrj not change. 214738fd1498Szrj 214838fd1498Szrj There is however exception where inlining might change dominator relation 214938fd1498Szrj across EH edges from basic block within inlined functions destinating 215038fd1498Szrj to landing pads in function we inline into. 215138fd1498Szrj 215238fd1498Szrj The function fills in PHI_RESULTs of such PHI nodes if they refer 215338fd1498Szrj to gimple regs. Otherwise, the function mark PHI_RESULT of such 215438fd1498Szrj PHI nodes for renaming. For non-gimple regs, renaming is safe: the 215538fd1498Szrj EH edges are abnormal and SSA_NAME_OCCURS_IN_ABNORMAL_PHI must be 215638fd1498Szrj set, and this means that there will be no overlapping live ranges 215738fd1498Szrj for the underlying symbol. 215838fd1498Szrj 215938fd1498Szrj This might change in future if we allow redirecting of EH edges and 216038fd1498Szrj we might want to change way build CFG pre-inlining to include 216138fd1498Szrj all the possible edges then. */ 216238fd1498Szrj static void 216338fd1498Szrj update_ssa_across_abnormal_edges (basic_block bb, basic_block ret_bb, 216438fd1498Szrj bool can_throw, bool nonlocal_goto) 216538fd1498Szrj { 216638fd1498Szrj edge e; 216738fd1498Szrj edge_iterator ei; 216838fd1498Szrj 216938fd1498Szrj FOR_EACH_EDGE (e, ei, bb->succs) 217038fd1498Szrj if (!e->dest->aux 217138fd1498Szrj || ((basic_block)e->dest->aux)->index == ENTRY_BLOCK) 217238fd1498Szrj { 217338fd1498Szrj gphi *phi; 217438fd1498Szrj gphi_iterator si; 217538fd1498Szrj 217638fd1498Szrj if (!nonlocal_goto) 217738fd1498Szrj gcc_assert (e->flags & EDGE_EH); 217838fd1498Szrj 217938fd1498Szrj if (!can_throw) 218038fd1498Szrj gcc_assert (!(e->flags & EDGE_EH)); 218138fd1498Szrj 218238fd1498Szrj for (si = gsi_start_phis (e->dest); !gsi_end_p (si); gsi_next (&si)) 218338fd1498Szrj { 218438fd1498Szrj edge re; 218538fd1498Szrj 218638fd1498Szrj phi = si.phi (); 218738fd1498Szrj 218838fd1498Szrj /* For abnormal goto/call edges the receiver can be the 218938fd1498Szrj ENTRY_BLOCK. Do not assert this cannot happen. */ 219038fd1498Szrj 219138fd1498Szrj gcc_assert ((e->flags & EDGE_EH) 219238fd1498Szrj || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (phi))); 219338fd1498Szrj 219438fd1498Szrj re = find_edge (ret_bb, e->dest); 219538fd1498Szrj gcc_checking_assert (re); 219638fd1498Szrj gcc_assert ((re->flags & (EDGE_EH | EDGE_ABNORMAL)) 219738fd1498Szrj == (e->flags & (EDGE_EH | EDGE_ABNORMAL))); 219838fd1498Szrj 219938fd1498Szrj SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), 220038fd1498Szrj USE_FROM_PTR (PHI_ARG_DEF_PTR_FROM_EDGE (phi, re))); 220138fd1498Szrj } 220238fd1498Szrj } 220338fd1498Szrj } 220438fd1498Szrj 220538fd1498Szrj 220638fd1498Szrj /* Copy edges from BB into its copy constructed earlier, scale profile 220738fd1498Szrj accordingly. Edges will be taken care of later. Assume aux 220838fd1498Szrj pointers to point to the copies of each BB. Return true if any 220938fd1498Szrj debug stmts are left after a statement that must end the basic block. */ 221038fd1498Szrj 221138fd1498Szrj static bool 221238fd1498Szrj copy_edges_for_bb (basic_block bb, profile_count num, profile_count den, 221338fd1498Szrj basic_block ret_bb, basic_block abnormal_goto_dest) 221438fd1498Szrj { 221538fd1498Szrj basic_block new_bb = (basic_block) bb->aux; 221638fd1498Szrj edge_iterator ei; 221738fd1498Szrj edge old_edge; 221838fd1498Szrj gimple_stmt_iterator si; 221938fd1498Szrj int flags; 222038fd1498Szrj bool need_debug_cleanup = false; 222138fd1498Szrj 222238fd1498Szrj /* Use the indices from the original blocks to create edges for the 222338fd1498Szrj new ones. */ 222438fd1498Szrj FOR_EACH_EDGE (old_edge, ei, bb->succs) 222538fd1498Szrj if (!(old_edge->flags & EDGE_EH)) 222638fd1498Szrj { 222738fd1498Szrj edge new_edge; 222838fd1498Szrj 222938fd1498Szrj flags = old_edge->flags; 223038fd1498Szrj 223138fd1498Szrj /* Return edges do get a FALLTHRU flag when the get inlined. */ 223238fd1498Szrj if (old_edge->dest->index == EXIT_BLOCK 223338fd1498Szrj && !(old_edge->flags & (EDGE_TRUE_VALUE|EDGE_FALSE_VALUE|EDGE_FAKE)) 223438fd1498Szrj && old_edge->dest->aux != EXIT_BLOCK_PTR_FOR_FN (cfun)) 223538fd1498Szrj flags |= EDGE_FALLTHRU; 223638fd1498Szrj new_edge = make_edge (new_bb, (basic_block) old_edge->dest->aux, flags); 223738fd1498Szrj new_edge->probability = old_edge->probability; 223838fd1498Szrj } 223938fd1498Szrj 224038fd1498Szrj if (bb->index == ENTRY_BLOCK || bb->index == EXIT_BLOCK) 224138fd1498Szrj return false; 224238fd1498Szrj 224338fd1498Szrj /* When doing function splitting, we must decreate count of the return block 224438fd1498Szrj which was previously reachable by block we did not copy. */ 224538fd1498Szrj if (single_succ_p (bb) && single_succ_edge (bb)->dest->index == EXIT_BLOCK) 224638fd1498Szrj FOR_EACH_EDGE (old_edge, ei, bb->preds) 224738fd1498Szrj if (old_edge->src->index != ENTRY_BLOCK 224838fd1498Szrj && !old_edge->src->aux) 224938fd1498Szrj new_bb->count -= old_edge->count ().apply_scale (num, den); 225038fd1498Szrj 225138fd1498Szrj for (si = gsi_start_bb (new_bb); !gsi_end_p (si);) 225238fd1498Szrj { 225338fd1498Szrj gimple *copy_stmt; 225438fd1498Szrj bool can_throw, nonlocal_goto; 225538fd1498Szrj 225638fd1498Szrj copy_stmt = gsi_stmt (si); 225738fd1498Szrj if (!is_gimple_debug (copy_stmt)) 225838fd1498Szrj update_stmt (copy_stmt); 225938fd1498Szrj 226038fd1498Szrj /* Do this before the possible split_block. */ 226138fd1498Szrj gsi_next (&si); 226238fd1498Szrj 226338fd1498Szrj /* If this tree could throw an exception, there are two 226438fd1498Szrj cases where we need to add abnormal edge(s): the 226538fd1498Szrj tree wasn't in a region and there is a "current 226638fd1498Szrj region" in the caller; or the original tree had 226738fd1498Szrj EH edges. In both cases split the block after the tree, 226838fd1498Szrj and add abnormal edge(s) as needed; we need both 226938fd1498Szrj those from the callee and the caller. 227038fd1498Szrj We check whether the copy can throw, because the const 227138fd1498Szrj propagation can change an INDIRECT_REF which throws 227238fd1498Szrj into a COMPONENT_REF which doesn't. If the copy 227338fd1498Szrj can throw, the original could also throw. */ 227438fd1498Szrj can_throw = stmt_can_throw_internal (copy_stmt); 227538fd1498Szrj nonlocal_goto 227638fd1498Szrj = (stmt_can_make_abnormal_goto (copy_stmt) 227738fd1498Szrj && !computed_goto_p (copy_stmt)); 227838fd1498Szrj 227938fd1498Szrj if (can_throw || nonlocal_goto) 228038fd1498Szrj { 228138fd1498Szrj if (!gsi_end_p (si)) 228238fd1498Szrj { 228338fd1498Szrj while (!gsi_end_p (si) && is_gimple_debug (gsi_stmt (si))) 228438fd1498Szrj gsi_next (&si); 228538fd1498Szrj if (gsi_end_p (si)) 228638fd1498Szrj need_debug_cleanup = true; 228738fd1498Szrj } 228838fd1498Szrj if (!gsi_end_p (si)) 228938fd1498Szrj /* Note that bb's predecessor edges aren't necessarily 229038fd1498Szrj right at this point; split_block doesn't care. */ 229138fd1498Szrj { 229238fd1498Szrj edge e = split_block (new_bb, copy_stmt); 229338fd1498Szrj 229438fd1498Szrj new_bb = e->dest; 229538fd1498Szrj new_bb->aux = e->src->aux; 229638fd1498Szrj si = gsi_start_bb (new_bb); 229738fd1498Szrj } 229838fd1498Szrj } 229938fd1498Szrj 230038fd1498Szrj bool update_probs = false; 230138fd1498Szrj 230238fd1498Szrj if (gimple_code (copy_stmt) == GIMPLE_EH_DISPATCH) 230338fd1498Szrj { 230438fd1498Szrj make_eh_dispatch_edges (as_a <geh_dispatch *> (copy_stmt)); 230538fd1498Szrj update_probs = true; 230638fd1498Szrj } 230738fd1498Szrj else if (can_throw) 230838fd1498Szrj { 230938fd1498Szrj make_eh_edges (copy_stmt); 231038fd1498Szrj update_probs = true; 231138fd1498Szrj } 231238fd1498Szrj 231338fd1498Szrj /* EH edges may not match old edges. Copy as much as possible. */ 231438fd1498Szrj if (update_probs) 231538fd1498Szrj { 231638fd1498Szrj edge e; 231738fd1498Szrj edge_iterator ei; 231838fd1498Szrj basic_block copy_stmt_bb = gimple_bb (copy_stmt); 231938fd1498Szrj 232038fd1498Szrj FOR_EACH_EDGE (old_edge, ei, bb->succs) 232138fd1498Szrj if ((old_edge->flags & EDGE_EH) 232238fd1498Szrj && (e = find_edge (copy_stmt_bb, 232338fd1498Szrj (basic_block) old_edge->dest->aux)) 232438fd1498Szrj && (e->flags & EDGE_EH)) 232538fd1498Szrj e->probability = old_edge->probability; 232638fd1498Szrj 232738fd1498Szrj FOR_EACH_EDGE (e, ei, copy_stmt_bb->succs) 232838fd1498Szrj if ((e->flags & EDGE_EH) && !e->probability.initialized_p ()) 232938fd1498Szrj e->probability = profile_probability::never (); 233038fd1498Szrj } 233138fd1498Szrj 233238fd1498Szrj 233338fd1498Szrj /* If the call we inline cannot make abnormal goto do not add 233438fd1498Szrj additional abnormal edges but only retain those already present 233538fd1498Szrj in the original function body. */ 233638fd1498Szrj if (abnormal_goto_dest == NULL) 233738fd1498Szrj nonlocal_goto = false; 233838fd1498Szrj if (nonlocal_goto) 233938fd1498Szrj { 234038fd1498Szrj basic_block copy_stmt_bb = gimple_bb (copy_stmt); 234138fd1498Szrj 234238fd1498Szrj if (get_abnormal_succ_dispatcher (copy_stmt_bb)) 234338fd1498Szrj nonlocal_goto = false; 234438fd1498Szrj /* ABNORMAL_DISPATCHER (1) is for longjmp/setjmp or nonlocal gotos 234538fd1498Szrj in OpenMP regions which aren't allowed to be left abnormally. 234638fd1498Szrj So, no need to add abnormal edge in that case. */ 234738fd1498Szrj else if (is_gimple_call (copy_stmt) 234838fd1498Szrj && gimple_call_internal_p (copy_stmt) 234938fd1498Szrj && (gimple_call_internal_fn (copy_stmt) 235038fd1498Szrj == IFN_ABNORMAL_DISPATCHER) 235138fd1498Szrj && gimple_call_arg (copy_stmt, 0) == boolean_true_node) 235238fd1498Szrj nonlocal_goto = false; 235338fd1498Szrj else 235438fd1498Szrj make_single_succ_edge (copy_stmt_bb, abnormal_goto_dest, 235538fd1498Szrj EDGE_ABNORMAL); 235638fd1498Szrj } 235738fd1498Szrj 235838fd1498Szrj if ((can_throw || nonlocal_goto) 235938fd1498Szrj && gimple_in_ssa_p (cfun)) 236038fd1498Szrj update_ssa_across_abnormal_edges (gimple_bb (copy_stmt), ret_bb, 236138fd1498Szrj can_throw, nonlocal_goto); 236238fd1498Szrj } 236338fd1498Szrj return need_debug_cleanup; 236438fd1498Szrj } 236538fd1498Szrj 236638fd1498Szrj /* Copy the PHIs. All blocks and edges are copied, some blocks 236738fd1498Szrj was possibly split and new outgoing EH edges inserted. 236838fd1498Szrj BB points to the block of original function and AUX pointers links 236938fd1498Szrj the original and newly copied blocks. */ 237038fd1498Szrj 237138fd1498Szrj static void 237238fd1498Szrj copy_phis_for_bb (basic_block bb, copy_body_data *id) 237338fd1498Szrj { 237438fd1498Szrj basic_block const new_bb = (basic_block) bb->aux; 237538fd1498Szrj edge_iterator ei; 237638fd1498Szrj gphi *phi; 237738fd1498Szrj gphi_iterator si; 237838fd1498Szrj edge new_edge; 237938fd1498Szrj bool inserted = false; 238038fd1498Szrj 238138fd1498Szrj for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si)) 238238fd1498Szrj { 238338fd1498Szrj tree res, new_res; 238438fd1498Szrj gphi *new_phi; 238538fd1498Szrj 238638fd1498Szrj phi = si.phi (); 238738fd1498Szrj res = PHI_RESULT (phi); 238838fd1498Szrj new_res = res; 238938fd1498Szrj if (!virtual_operand_p (res)) 239038fd1498Szrj { 239138fd1498Szrj walk_tree (&new_res, copy_tree_body_r, id, NULL); 239238fd1498Szrj if (EDGE_COUNT (new_bb->preds) == 0) 239338fd1498Szrj { 239438fd1498Szrj /* Technically we'd want a SSA_DEFAULT_DEF here... */ 239538fd1498Szrj SSA_NAME_DEF_STMT (new_res) = gimple_build_nop (); 239638fd1498Szrj } 239738fd1498Szrj else 239838fd1498Szrj { 239938fd1498Szrj new_phi = create_phi_node (new_res, new_bb); 240038fd1498Szrj FOR_EACH_EDGE (new_edge, ei, new_bb->preds) 240138fd1498Szrj { 240238fd1498Szrj edge old_edge = find_edge ((basic_block) new_edge->src->aux, 240338fd1498Szrj bb); 240438fd1498Szrj tree arg; 240538fd1498Szrj tree new_arg; 240638fd1498Szrj edge_iterator ei2; 240738fd1498Szrj location_t locus; 240838fd1498Szrj 240938fd1498Szrj /* When doing partial cloning, we allow PHIs on the entry 241038fd1498Szrj block as long as all the arguments are the same. 241138fd1498Szrj Find any input edge to see argument to copy. */ 241238fd1498Szrj if (!old_edge) 241338fd1498Szrj FOR_EACH_EDGE (old_edge, ei2, bb->preds) 241438fd1498Szrj if (!old_edge->src->aux) 241538fd1498Szrj break; 241638fd1498Szrj 241738fd1498Szrj arg = PHI_ARG_DEF_FROM_EDGE (phi, old_edge); 241838fd1498Szrj new_arg = arg; 241938fd1498Szrj walk_tree (&new_arg, copy_tree_body_r, id, NULL); 242038fd1498Szrj gcc_assert (new_arg); 242138fd1498Szrj /* With return slot optimization we can end up with 242238fd1498Szrj non-gimple (foo *)&this->m, fix that here. */ 242338fd1498Szrj if (TREE_CODE (new_arg) != SSA_NAME 242438fd1498Szrj && TREE_CODE (new_arg) != FUNCTION_DECL 242538fd1498Szrj && !is_gimple_val (new_arg)) 242638fd1498Szrj { 242738fd1498Szrj gimple_seq stmts = NULL; 242838fd1498Szrj new_arg = force_gimple_operand (new_arg, &stmts, true, 242938fd1498Szrj NULL); 243038fd1498Szrj gsi_insert_seq_on_edge (new_edge, stmts); 243138fd1498Szrj inserted = true; 243238fd1498Szrj } 243338fd1498Szrj locus = gimple_phi_arg_location_from_edge (phi, old_edge); 243438fd1498Szrj if (LOCATION_BLOCK (locus)) 243538fd1498Szrj { 243638fd1498Szrj tree *n; 243738fd1498Szrj n = id->decl_map->get (LOCATION_BLOCK (locus)); 243838fd1498Szrj gcc_assert (n); 243938fd1498Szrj locus = set_block (locus, *n); 244038fd1498Szrj } 244138fd1498Szrj else 244238fd1498Szrj locus = LOCATION_LOCUS (locus); 244338fd1498Szrj 244438fd1498Szrj add_phi_arg (new_phi, new_arg, new_edge, locus); 244538fd1498Szrj } 244638fd1498Szrj } 244738fd1498Szrj } 244838fd1498Szrj } 244938fd1498Szrj 245038fd1498Szrj /* Commit the delayed edge insertions. */ 245138fd1498Szrj if (inserted) 245238fd1498Szrj FOR_EACH_EDGE (new_edge, ei, new_bb->preds) 245338fd1498Szrj gsi_commit_one_edge_insert (new_edge, NULL); 245438fd1498Szrj } 245538fd1498Szrj 245638fd1498Szrj 245738fd1498Szrj /* Wrapper for remap_decl so it can be used as a callback. */ 245838fd1498Szrj 245938fd1498Szrj static tree 246038fd1498Szrj remap_decl_1 (tree decl, void *data) 246138fd1498Szrj { 246238fd1498Szrj return remap_decl (decl, (copy_body_data *) data); 246338fd1498Szrj } 246438fd1498Szrj 246538fd1498Szrj /* Build struct function and associated datastructures for the new clone 246638fd1498Szrj NEW_FNDECL to be build. CALLEE_FNDECL is the original. Function changes 246738fd1498Szrj the cfun to the function of new_fndecl (and current_function_decl too). */ 246838fd1498Szrj 246938fd1498Szrj static void 247038fd1498Szrj initialize_cfun (tree new_fndecl, tree callee_fndecl, profile_count count) 247138fd1498Szrj { 247238fd1498Szrj struct function *src_cfun = DECL_STRUCT_FUNCTION (callee_fndecl); 247338fd1498Szrj 247438fd1498Szrj if (!DECL_ARGUMENTS (new_fndecl)) 247538fd1498Szrj DECL_ARGUMENTS (new_fndecl) = DECL_ARGUMENTS (callee_fndecl); 247638fd1498Szrj if (!DECL_RESULT (new_fndecl)) 247738fd1498Szrj DECL_RESULT (new_fndecl) = DECL_RESULT (callee_fndecl); 247838fd1498Szrj 247938fd1498Szrj /* Register specific tree functions. */ 248038fd1498Szrj gimple_register_cfg_hooks (); 248138fd1498Szrj 248238fd1498Szrj /* Get clean struct function. */ 248338fd1498Szrj push_struct_function (new_fndecl); 248438fd1498Szrj 248538fd1498Szrj /* We will rebuild these, so just sanity check that they are empty. */ 248638fd1498Szrj gcc_assert (VALUE_HISTOGRAMS (cfun) == NULL); 248738fd1498Szrj gcc_assert (cfun->local_decls == NULL); 248838fd1498Szrj gcc_assert (cfun->cfg == NULL); 248938fd1498Szrj gcc_assert (cfun->decl == new_fndecl); 249038fd1498Szrj 249138fd1498Szrj /* Copy items we preserve during cloning. */ 249238fd1498Szrj cfun->static_chain_decl = src_cfun->static_chain_decl; 249338fd1498Szrj cfun->nonlocal_goto_save_area = src_cfun->nonlocal_goto_save_area; 249438fd1498Szrj cfun->function_end_locus = src_cfun->function_end_locus; 249538fd1498Szrj cfun->curr_properties = src_cfun->curr_properties; 249638fd1498Szrj cfun->last_verified = src_cfun->last_verified; 249738fd1498Szrj cfun->va_list_gpr_size = src_cfun->va_list_gpr_size; 249838fd1498Szrj cfun->va_list_fpr_size = src_cfun->va_list_fpr_size; 249938fd1498Szrj cfun->has_nonlocal_label = src_cfun->has_nonlocal_label; 250038fd1498Szrj cfun->stdarg = src_cfun->stdarg; 250138fd1498Szrj cfun->after_inlining = src_cfun->after_inlining; 250238fd1498Szrj cfun->can_throw_non_call_exceptions 250338fd1498Szrj = src_cfun->can_throw_non_call_exceptions; 250438fd1498Szrj cfun->can_delete_dead_exceptions = src_cfun->can_delete_dead_exceptions; 250538fd1498Szrj cfun->returns_struct = src_cfun->returns_struct; 250638fd1498Szrj cfun->returns_pcc_struct = src_cfun->returns_pcc_struct; 250738fd1498Szrj 250838fd1498Szrj init_empty_tree_cfg (); 250938fd1498Szrj 251038fd1498Szrj profile_status_for_fn (cfun) = profile_status_for_fn (src_cfun); 251138fd1498Szrj 251238fd1498Szrj profile_count num = count; 251338fd1498Szrj profile_count den = ENTRY_BLOCK_PTR_FOR_FN (src_cfun)->count; 251438fd1498Szrj profile_count::adjust_for_ipa_scaling (&num, &den); 251538fd1498Szrj 251638fd1498Szrj ENTRY_BLOCK_PTR_FOR_FN (cfun)->count = 251738fd1498Szrj ENTRY_BLOCK_PTR_FOR_FN (src_cfun)->count.apply_scale (count, 251838fd1498Szrj ENTRY_BLOCK_PTR_FOR_FN (src_cfun)->count); 251938fd1498Szrj EXIT_BLOCK_PTR_FOR_FN (cfun)->count = 252038fd1498Szrj EXIT_BLOCK_PTR_FOR_FN (src_cfun)->count.apply_scale (count, 252138fd1498Szrj ENTRY_BLOCK_PTR_FOR_FN (src_cfun)->count); 252238fd1498Szrj if (src_cfun->eh) 252338fd1498Szrj init_eh_for_function (); 252438fd1498Szrj 252538fd1498Szrj if (src_cfun->gimple_df) 252638fd1498Szrj { 252738fd1498Szrj init_tree_ssa (cfun); 252838fd1498Szrj cfun->gimple_df->in_ssa_p = src_cfun->gimple_df->in_ssa_p; 252938fd1498Szrj if (cfun->gimple_df->in_ssa_p) 253038fd1498Szrj init_ssa_operands (cfun); 253138fd1498Szrj } 253238fd1498Szrj } 253338fd1498Szrj 253438fd1498Szrj /* Helper function for copy_cfg_body. Move debug stmts from the end 253538fd1498Szrj of NEW_BB to the beginning of successor basic blocks when needed. If the 253638fd1498Szrj successor has multiple predecessors, reset them, otherwise keep 253738fd1498Szrj their value. */ 253838fd1498Szrj 253938fd1498Szrj static void 254038fd1498Szrj maybe_move_debug_stmts_to_successors (copy_body_data *id, basic_block new_bb) 254138fd1498Szrj { 254238fd1498Szrj edge e; 254338fd1498Szrj edge_iterator ei; 254438fd1498Szrj gimple_stmt_iterator si = gsi_last_nondebug_bb (new_bb); 254538fd1498Szrj 254638fd1498Szrj if (gsi_end_p (si) 254738fd1498Szrj || gsi_one_before_end_p (si) 254838fd1498Szrj || !(stmt_can_throw_internal (gsi_stmt (si)) 254938fd1498Szrj || stmt_can_make_abnormal_goto (gsi_stmt (si)))) 255038fd1498Szrj return; 255138fd1498Szrj 255238fd1498Szrj FOR_EACH_EDGE (e, ei, new_bb->succs) 255338fd1498Szrj { 255438fd1498Szrj gimple_stmt_iterator ssi = gsi_last_bb (new_bb); 255538fd1498Szrj gimple_stmt_iterator dsi = gsi_after_labels (e->dest); 255638fd1498Szrj while (is_gimple_debug (gsi_stmt (ssi))) 255738fd1498Szrj { 255838fd1498Szrj gimple *stmt = gsi_stmt (ssi); 255938fd1498Szrj gdebug *new_stmt; 256038fd1498Szrj tree var; 256138fd1498Szrj tree value; 256238fd1498Szrj 256338fd1498Szrj /* For the last edge move the debug stmts instead of copying 256438fd1498Szrj them. */ 256538fd1498Szrj if (ei_one_before_end_p (ei)) 256638fd1498Szrj { 256738fd1498Szrj si = ssi; 256838fd1498Szrj gsi_prev (&ssi); 256938fd1498Szrj if (!single_pred_p (e->dest) && gimple_debug_bind_p (stmt)) 257038fd1498Szrj gimple_debug_bind_reset_value (stmt); 257138fd1498Szrj gsi_remove (&si, false); 257238fd1498Szrj gsi_insert_before (&dsi, stmt, GSI_SAME_STMT); 257338fd1498Szrj continue; 257438fd1498Szrj } 257538fd1498Szrj 257638fd1498Szrj if (gimple_debug_bind_p (stmt)) 257738fd1498Szrj { 257838fd1498Szrj var = gimple_debug_bind_get_var (stmt); 257938fd1498Szrj if (single_pred_p (e->dest)) 258038fd1498Szrj { 258138fd1498Szrj value = gimple_debug_bind_get_value (stmt); 258238fd1498Szrj value = unshare_expr (value); 258338fd1498Szrj } 258438fd1498Szrj else 258538fd1498Szrj value = NULL_TREE; 258638fd1498Szrj new_stmt = gimple_build_debug_bind (var, value, stmt); 258738fd1498Szrj } 258838fd1498Szrj else if (gimple_debug_source_bind_p (stmt)) 258938fd1498Szrj { 259038fd1498Szrj var = gimple_debug_source_bind_get_var (stmt); 259138fd1498Szrj value = gimple_debug_source_bind_get_value (stmt); 259238fd1498Szrj new_stmt = gimple_build_debug_source_bind (var, value, stmt); 259338fd1498Szrj } 259438fd1498Szrj else if (gimple_debug_nonbind_marker_p (stmt)) 259538fd1498Szrj new_stmt = as_a <gdebug *> (gimple_copy (stmt)); 259638fd1498Szrj else 259738fd1498Szrj gcc_unreachable (); 259838fd1498Szrj gsi_insert_before (&dsi, new_stmt, GSI_SAME_STMT); 259938fd1498Szrj id->debug_stmts.safe_push (new_stmt); 260038fd1498Szrj gsi_prev (&ssi); 260138fd1498Szrj } 260238fd1498Szrj } 260338fd1498Szrj } 260438fd1498Szrj 260538fd1498Szrj /* Make a copy of the sub-loops of SRC_PARENT and place them 260638fd1498Szrj as siblings of DEST_PARENT. */ 260738fd1498Szrj 260838fd1498Szrj static void 260938fd1498Szrj copy_loops (copy_body_data *id, 261038fd1498Szrj struct loop *dest_parent, struct loop *src_parent) 261138fd1498Szrj { 261238fd1498Szrj struct loop *src_loop = src_parent->inner; 261338fd1498Szrj while (src_loop) 261438fd1498Szrj { 261538fd1498Szrj if (!id->blocks_to_copy 261638fd1498Szrj || bitmap_bit_p (id->blocks_to_copy, src_loop->header->index)) 261738fd1498Szrj { 261838fd1498Szrj struct loop *dest_loop = alloc_loop (); 261938fd1498Szrj 262038fd1498Szrj /* Assign the new loop its header and latch and associate 262138fd1498Szrj those with the new loop. */ 262238fd1498Szrj dest_loop->header = (basic_block)src_loop->header->aux; 262338fd1498Szrj dest_loop->header->loop_father = dest_loop; 262438fd1498Szrj if (src_loop->latch != NULL) 262538fd1498Szrj { 262638fd1498Szrj dest_loop->latch = (basic_block)src_loop->latch->aux; 262738fd1498Szrj dest_loop->latch->loop_father = dest_loop; 262838fd1498Szrj } 262938fd1498Szrj 263038fd1498Szrj /* Copy loop meta-data. */ 263138fd1498Szrj copy_loop_info (src_loop, dest_loop); 263238fd1498Szrj 263338fd1498Szrj /* Finally place it into the loop array and the loop tree. */ 263438fd1498Szrj place_new_loop (cfun, dest_loop); 263538fd1498Szrj flow_loop_tree_node_add (dest_parent, dest_loop); 263638fd1498Szrj 263738fd1498Szrj dest_loop->safelen = src_loop->safelen; 263838fd1498Szrj if (src_loop->unroll) 263938fd1498Szrj { 264038fd1498Szrj dest_loop->unroll = src_loop->unroll; 264138fd1498Szrj cfun->has_unroll = true; 264238fd1498Szrj } 264338fd1498Szrj dest_loop->dont_vectorize = src_loop->dont_vectorize; 264438fd1498Szrj if (src_loop->force_vectorize) 264538fd1498Szrj { 264638fd1498Szrj dest_loop->force_vectorize = true; 264738fd1498Szrj cfun->has_force_vectorize_loops = true; 264838fd1498Szrj } 264938fd1498Szrj if (src_loop->simduid) 265038fd1498Szrj { 265138fd1498Szrj dest_loop->simduid = remap_decl (src_loop->simduid, id); 265238fd1498Szrj cfun->has_simduid_loops = true; 265338fd1498Szrj } 265438fd1498Szrj 265538fd1498Szrj /* Recurse. */ 265638fd1498Szrj copy_loops (id, dest_loop, src_loop); 265738fd1498Szrj } 265838fd1498Szrj src_loop = src_loop->next; 265938fd1498Szrj } 266038fd1498Szrj } 266138fd1498Szrj 266238fd1498Szrj /* Call cgraph_redirect_edge_call_stmt_to_callee on all calls in BB */ 266338fd1498Szrj 266438fd1498Szrj void 266538fd1498Szrj redirect_all_calls (copy_body_data * id, basic_block bb) 266638fd1498Szrj { 266738fd1498Szrj gimple_stmt_iterator si; 266838fd1498Szrj gimple *last = last_stmt (bb); 266938fd1498Szrj for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si)) 267038fd1498Szrj { 267138fd1498Szrj gimple *stmt = gsi_stmt (si); 267238fd1498Szrj if (is_gimple_call (stmt)) 267338fd1498Szrj { 267438fd1498Szrj struct cgraph_edge *edge = id->dst_node->get_edge (stmt); 267538fd1498Szrj if (edge) 267638fd1498Szrj { 267738fd1498Szrj edge->redirect_call_stmt_to_callee (); 267838fd1498Szrj if (stmt == last && id->call_stmt && maybe_clean_eh_stmt (stmt)) 267938fd1498Szrj gimple_purge_dead_eh_edges (bb); 268038fd1498Szrj } 268138fd1498Szrj } 268238fd1498Szrj } 268338fd1498Szrj } 268438fd1498Szrj 268538fd1498Szrj /* Make a copy of the body of FN so that it can be inserted inline in 268638fd1498Szrj another function. Walks FN via CFG, returns new fndecl. */ 268738fd1498Szrj 268838fd1498Szrj static tree 268938fd1498Szrj copy_cfg_body (copy_body_data * id, 269038fd1498Szrj basic_block entry_block_map, basic_block exit_block_map, 269138fd1498Szrj basic_block new_entry) 269238fd1498Szrj { 269338fd1498Szrj tree callee_fndecl = id->src_fn; 269438fd1498Szrj /* Original cfun for the callee, doesn't change. */ 269538fd1498Szrj struct function *src_cfun = DECL_STRUCT_FUNCTION (callee_fndecl); 269638fd1498Szrj struct function *cfun_to_copy; 269738fd1498Szrj basic_block bb; 269838fd1498Szrj tree new_fndecl = NULL; 269938fd1498Szrj bool need_debug_cleanup = false; 270038fd1498Szrj int last; 270138fd1498Szrj profile_count den = ENTRY_BLOCK_PTR_FOR_FN (src_cfun)->count; 270238fd1498Szrj profile_count num = entry_block_map->count; 270338fd1498Szrj 270438fd1498Szrj cfun_to_copy = id->src_cfun = DECL_STRUCT_FUNCTION (callee_fndecl); 270538fd1498Szrj 270638fd1498Szrj /* Register specific tree functions. */ 270738fd1498Szrj gimple_register_cfg_hooks (); 270838fd1498Szrj 270938fd1498Szrj /* If we are inlining just region of the function, make sure to connect 271038fd1498Szrj new entry to ENTRY_BLOCK_PTR_FOR_FN (cfun). Since new entry can be 271138fd1498Szrj part of loop, we must compute frequency and probability of 271238fd1498Szrj ENTRY_BLOCK_PTR_FOR_FN (cfun) based on the frequencies and 271338fd1498Szrj probabilities of edges incoming from nonduplicated region. */ 271438fd1498Szrj if (new_entry) 271538fd1498Szrj { 271638fd1498Szrj edge e; 271738fd1498Szrj edge_iterator ei; 271838fd1498Szrj den = profile_count::zero (); 271938fd1498Szrj 272038fd1498Szrj FOR_EACH_EDGE (e, ei, new_entry->preds) 272138fd1498Szrj if (!e->src->aux) 272238fd1498Szrj den += e->count (); 272338fd1498Szrj ENTRY_BLOCK_PTR_FOR_FN (cfun)->count = den; 272438fd1498Szrj } 272538fd1498Szrj 272638fd1498Szrj profile_count::adjust_for_ipa_scaling (&num, &den); 272738fd1498Szrj 272838fd1498Szrj /* Must have a CFG here at this point. */ 272938fd1498Szrj gcc_assert (ENTRY_BLOCK_PTR_FOR_FN 273038fd1498Szrj (DECL_STRUCT_FUNCTION (callee_fndecl))); 273138fd1498Szrj 273238fd1498Szrj 273338fd1498Szrj ENTRY_BLOCK_PTR_FOR_FN (cfun_to_copy)->aux = entry_block_map; 273438fd1498Szrj EXIT_BLOCK_PTR_FOR_FN (cfun_to_copy)->aux = exit_block_map; 273538fd1498Szrj entry_block_map->aux = ENTRY_BLOCK_PTR_FOR_FN (cfun_to_copy); 273638fd1498Szrj exit_block_map->aux = EXIT_BLOCK_PTR_FOR_FN (cfun_to_copy); 273738fd1498Szrj 273838fd1498Szrj /* Duplicate any exception-handling regions. */ 273938fd1498Szrj if (cfun->eh) 274038fd1498Szrj id->eh_map = duplicate_eh_regions (cfun_to_copy, NULL, id->eh_lp_nr, 274138fd1498Szrj remap_decl_1, id); 274238fd1498Szrj 274338fd1498Szrj /* Use aux pointers to map the original blocks to copy. */ 274438fd1498Szrj FOR_EACH_BB_FN (bb, cfun_to_copy) 274538fd1498Szrj if (!id->blocks_to_copy || bitmap_bit_p (id->blocks_to_copy, bb->index)) 274638fd1498Szrj { 274738fd1498Szrj basic_block new_bb = copy_bb (id, bb, num, den); 274838fd1498Szrj bb->aux = new_bb; 274938fd1498Szrj new_bb->aux = bb; 275038fd1498Szrj new_bb->loop_father = entry_block_map->loop_father; 275138fd1498Szrj } 275238fd1498Szrj 275338fd1498Szrj last = last_basic_block_for_fn (cfun); 275438fd1498Szrj 275538fd1498Szrj /* Now that we've duplicated the blocks, duplicate their edges. */ 275638fd1498Szrj basic_block abnormal_goto_dest = NULL; 275738fd1498Szrj if (id->call_stmt 275838fd1498Szrj && stmt_can_make_abnormal_goto (id->call_stmt)) 275938fd1498Szrj { 276038fd1498Szrj gimple_stmt_iterator gsi = gsi_for_stmt (id->call_stmt); 276138fd1498Szrj 276238fd1498Szrj bb = gimple_bb (id->call_stmt); 276338fd1498Szrj gsi_next (&gsi); 276438fd1498Szrj if (gsi_end_p (gsi)) 276538fd1498Szrj abnormal_goto_dest = get_abnormal_succ_dispatcher (bb); 276638fd1498Szrj } 276738fd1498Szrj FOR_ALL_BB_FN (bb, cfun_to_copy) 276838fd1498Szrj if (!id->blocks_to_copy 276938fd1498Szrj || (bb->index > 0 && bitmap_bit_p (id->blocks_to_copy, bb->index))) 277038fd1498Szrj need_debug_cleanup |= copy_edges_for_bb (bb, num, den, exit_block_map, 277138fd1498Szrj abnormal_goto_dest); 277238fd1498Szrj 277338fd1498Szrj if (new_entry) 277438fd1498Szrj { 277538fd1498Szrj edge e = make_edge (entry_block_map, (basic_block)new_entry->aux, 277638fd1498Szrj EDGE_FALLTHRU); 277738fd1498Szrj e->probability = profile_probability::always (); 277838fd1498Szrj } 277938fd1498Szrj 278038fd1498Szrj /* Duplicate the loop tree, if available and wanted. */ 278138fd1498Szrj if (loops_for_fn (src_cfun) != NULL 278238fd1498Szrj && current_loops != NULL) 278338fd1498Szrj { 278438fd1498Szrj copy_loops (id, entry_block_map->loop_father, 278538fd1498Szrj get_loop (src_cfun, 0)); 278638fd1498Szrj /* Defer to cfgcleanup to update loop-father fields of basic-blocks. */ 278738fd1498Szrj loops_state_set (LOOPS_NEED_FIXUP); 278838fd1498Szrj } 278938fd1498Szrj 279038fd1498Szrj /* If the loop tree in the source function needed fixup, mark the 279138fd1498Szrj destination loop tree for fixup, too. */ 279238fd1498Szrj if (loops_for_fn (src_cfun)->state & LOOPS_NEED_FIXUP) 279338fd1498Szrj loops_state_set (LOOPS_NEED_FIXUP); 279438fd1498Szrj 279538fd1498Szrj if (gimple_in_ssa_p (cfun)) 279638fd1498Szrj FOR_ALL_BB_FN (bb, cfun_to_copy) 279738fd1498Szrj if (!id->blocks_to_copy 279838fd1498Szrj || (bb->index > 0 && bitmap_bit_p (id->blocks_to_copy, bb->index))) 279938fd1498Szrj copy_phis_for_bb (bb, id); 280038fd1498Szrj 280138fd1498Szrj FOR_ALL_BB_FN (bb, cfun_to_copy) 280238fd1498Szrj if (bb->aux) 280338fd1498Szrj { 280438fd1498Szrj if (need_debug_cleanup 280538fd1498Szrj && bb->index != ENTRY_BLOCK 280638fd1498Szrj && bb->index != EXIT_BLOCK) 280738fd1498Szrj maybe_move_debug_stmts_to_successors (id, (basic_block) bb->aux); 280838fd1498Szrj /* Update call edge destinations. This can not be done before loop 280938fd1498Szrj info is updated, because we may split basic blocks. */ 281038fd1498Szrj if (id->transform_call_graph_edges == CB_CGE_DUPLICATE 281138fd1498Szrj && bb->index != ENTRY_BLOCK 281238fd1498Szrj && bb->index != EXIT_BLOCK) 281338fd1498Szrj redirect_all_calls (id, (basic_block)bb->aux); 281438fd1498Szrj ((basic_block)bb->aux)->aux = NULL; 281538fd1498Szrj bb->aux = NULL; 281638fd1498Szrj } 281738fd1498Szrj 281838fd1498Szrj /* Zero out AUX fields of newly created block during EH edge 281938fd1498Szrj insertion. */ 282038fd1498Szrj for (; last < last_basic_block_for_fn (cfun); last++) 282138fd1498Szrj { 282238fd1498Szrj if (need_debug_cleanup) 282338fd1498Szrj maybe_move_debug_stmts_to_successors (id, 282438fd1498Szrj BASIC_BLOCK_FOR_FN (cfun, last)); 282538fd1498Szrj BASIC_BLOCK_FOR_FN (cfun, last)->aux = NULL; 282638fd1498Szrj /* Update call edge destinations. This can not be done before loop 282738fd1498Szrj info is updated, because we may split basic blocks. */ 282838fd1498Szrj if (id->transform_call_graph_edges == CB_CGE_DUPLICATE) 282938fd1498Szrj redirect_all_calls (id, BASIC_BLOCK_FOR_FN (cfun, last)); 283038fd1498Szrj } 283138fd1498Szrj entry_block_map->aux = NULL; 283238fd1498Szrj exit_block_map->aux = NULL; 283338fd1498Szrj 283438fd1498Szrj if (id->eh_map) 283538fd1498Szrj { 283638fd1498Szrj delete id->eh_map; 283738fd1498Szrj id->eh_map = NULL; 283838fd1498Szrj } 283938fd1498Szrj if (id->dependence_map) 284038fd1498Szrj { 284138fd1498Szrj delete id->dependence_map; 284238fd1498Szrj id->dependence_map = NULL; 284338fd1498Szrj } 284438fd1498Szrj 284538fd1498Szrj return new_fndecl; 284638fd1498Szrj } 284738fd1498Szrj 284838fd1498Szrj /* Copy the debug STMT using ID. We deal with these statements in a 284938fd1498Szrj special way: if any variable in their VALUE expression wasn't 285038fd1498Szrj remapped yet, we won't remap it, because that would get decl uids 285138fd1498Szrj out of sync, causing codegen differences between -g and -g0. If 285238fd1498Szrj this arises, we drop the VALUE expression altogether. */ 285338fd1498Szrj 285438fd1498Szrj static void 285538fd1498Szrj copy_debug_stmt (gdebug *stmt, copy_body_data *id) 285638fd1498Szrj { 285738fd1498Szrj tree t, *n; 285838fd1498Szrj struct walk_stmt_info wi; 285938fd1498Szrj 286038fd1498Szrj if (gimple_block (stmt)) 286138fd1498Szrj { 286238fd1498Szrj n = id->decl_map->get (gimple_block (stmt)); 286338fd1498Szrj gimple_set_block (stmt, n ? *n : id->block); 286438fd1498Szrj } 286538fd1498Szrj 286638fd1498Szrj if (gimple_debug_nonbind_marker_p (stmt)) 286738fd1498Szrj return; 286838fd1498Szrj 286938fd1498Szrj /* Remap all the operands in COPY. */ 287038fd1498Szrj memset (&wi, 0, sizeof (wi)); 287138fd1498Szrj wi.info = id; 287238fd1498Szrj 287338fd1498Szrj processing_debug_stmt = 1; 287438fd1498Szrj 287538fd1498Szrj if (gimple_debug_source_bind_p (stmt)) 287638fd1498Szrj t = gimple_debug_source_bind_get_var (stmt); 287738fd1498Szrj else if (gimple_debug_bind_p (stmt)) 287838fd1498Szrj t = gimple_debug_bind_get_var (stmt); 287938fd1498Szrj else 288038fd1498Szrj gcc_unreachable (); 288138fd1498Szrj 288238fd1498Szrj if (TREE_CODE (t) == PARM_DECL && id->debug_map 288338fd1498Szrj && (n = id->debug_map->get (t))) 288438fd1498Szrj { 288538fd1498Szrj gcc_assert (VAR_P (*n)); 288638fd1498Szrj t = *n; 288738fd1498Szrj } 288838fd1498Szrj else if (VAR_P (t) && !is_global_var (t) && !id->decl_map->get (t)) 288938fd1498Szrj /* T is a non-localized variable. */; 289038fd1498Szrj else 289138fd1498Szrj walk_tree (&t, remap_gimple_op_r, &wi, NULL); 289238fd1498Szrj 289338fd1498Szrj if (gimple_debug_bind_p (stmt)) 289438fd1498Szrj { 289538fd1498Szrj gimple_debug_bind_set_var (stmt, t); 289638fd1498Szrj 289738fd1498Szrj if (gimple_debug_bind_has_value_p (stmt)) 289838fd1498Szrj walk_tree (gimple_debug_bind_get_value_ptr (stmt), 289938fd1498Szrj remap_gimple_op_r, &wi, NULL); 290038fd1498Szrj 290138fd1498Szrj /* Punt if any decl couldn't be remapped. */ 290238fd1498Szrj if (processing_debug_stmt < 0) 290338fd1498Szrj gimple_debug_bind_reset_value (stmt); 290438fd1498Szrj } 290538fd1498Szrj else if (gimple_debug_source_bind_p (stmt)) 290638fd1498Szrj { 290738fd1498Szrj gimple_debug_source_bind_set_var (stmt, t); 290838fd1498Szrj /* When inlining and source bind refers to one of the optimized 290938fd1498Szrj away parameters, change the source bind into normal debug bind 291038fd1498Szrj referring to the corresponding DEBUG_EXPR_DECL that should have 291138fd1498Szrj been bound before the call stmt. */ 291238fd1498Szrj t = gimple_debug_source_bind_get_value (stmt); 291338fd1498Szrj if (t != NULL_TREE 291438fd1498Szrj && TREE_CODE (t) == PARM_DECL 291538fd1498Szrj && id->call_stmt) 291638fd1498Szrj { 291738fd1498Szrj vec<tree, va_gc> **debug_args = decl_debug_args_lookup (id->src_fn); 291838fd1498Szrj unsigned int i; 291938fd1498Szrj if (debug_args != NULL) 292038fd1498Szrj { 292138fd1498Szrj for (i = 0; i < vec_safe_length (*debug_args); i += 2) 292238fd1498Szrj if ((**debug_args)[i] == DECL_ORIGIN (t) 292338fd1498Szrj && TREE_CODE ((**debug_args)[i + 1]) == DEBUG_EXPR_DECL) 292438fd1498Szrj { 292538fd1498Szrj t = (**debug_args)[i + 1]; 292638fd1498Szrj stmt->subcode = GIMPLE_DEBUG_BIND; 292738fd1498Szrj gimple_debug_bind_set_value (stmt, t); 292838fd1498Szrj break; 292938fd1498Szrj } 293038fd1498Szrj } 293138fd1498Szrj } 293238fd1498Szrj if (gimple_debug_source_bind_p (stmt)) 293338fd1498Szrj walk_tree (gimple_debug_source_bind_get_value_ptr (stmt), 293438fd1498Szrj remap_gimple_op_r, &wi, NULL); 293538fd1498Szrj } 293638fd1498Szrj 293738fd1498Szrj processing_debug_stmt = 0; 293838fd1498Szrj 293938fd1498Szrj update_stmt (stmt); 294038fd1498Szrj } 294138fd1498Szrj 294238fd1498Szrj /* Process deferred debug stmts. In order to give values better odds 294338fd1498Szrj of being successfully remapped, we delay the processing of debug 294438fd1498Szrj stmts until all other stmts that might require remapping are 294538fd1498Szrj processed. */ 294638fd1498Szrj 294738fd1498Szrj static void 294838fd1498Szrj copy_debug_stmts (copy_body_data *id) 294938fd1498Szrj { 295038fd1498Szrj size_t i; 295138fd1498Szrj gdebug *stmt; 295238fd1498Szrj 295338fd1498Szrj if (!id->debug_stmts.exists ()) 295438fd1498Szrj return; 295538fd1498Szrj 295638fd1498Szrj FOR_EACH_VEC_ELT (id->debug_stmts, i, stmt) 295738fd1498Szrj copy_debug_stmt (stmt, id); 295838fd1498Szrj 295938fd1498Szrj id->debug_stmts.release (); 296038fd1498Szrj } 296138fd1498Szrj 296238fd1498Szrj /* Make a copy of the body of SRC_FN so that it can be inserted inline in 296338fd1498Szrj another function. */ 296438fd1498Szrj 296538fd1498Szrj static tree 296638fd1498Szrj copy_tree_body (copy_body_data *id) 296738fd1498Szrj { 296838fd1498Szrj tree fndecl = id->src_fn; 296938fd1498Szrj tree body = DECL_SAVED_TREE (fndecl); 297038fd1498Szrj 297138fd1498Szrj walk_tree (&body, copy_tree_body_r, id, NULL); 297238fd1498Szrj 297338fd1498Szrj return body; 297438fd1498Szrj } 297538fd1498Szrj 297638fd1498Szrj /* Make a copy of the body of FN so that it can be inserted inline in 297738fd1498Szrj another function. */ 297838fd1498Szrj 297938fd1498Szrj static tree 298038fd1498Szrj copy_body (copy_body_data *id, 298138fd1498Szrj basic_block entry_block_map, basic_block exit_block_map, 298238fd1498Szrj basic_block new_entry) 298338fd1498Szrj { 298438fd1498Szrj tree fndecl = id->src_fn; 298538fd1498Szrj tree body; 298638fd1498Szrj 298738fd1498Szrj /* If this body has a CFG, walk CFG and copy. */ 298838fd1498Szrj gcc_assert (ENTRY_BLOCK_PTR_FOR_FN (DECL_STRUCT_FUNCTION (fndecl))); 298938fd1498Szrj body = copy_cfg_body (id, entry_block_map, exit_block_map, 299038fd1498Szrj new_entry); 299138fd1498Szrj copy_debug_stmts (id); 299238fd1498Szrj 299338fd1498Szrj return body; 299438fd1498Szrj } 299538fd1498Szrj 299638fd1498Szrj /* Return true if VALUE is an ADDR_EXPR of an automatic variable 299738fd1498Szrj defined in function FN, or of a data member thereof. */ 299838fd1498Szrj 299938fd1498Szrj static bool 300038fd1498Szrj self_inlining_addr_expr (tree value, tree fn) 300138fd1498Szrj { 300238fd1498Szrj tree var; 300338fd1498Szrj 300438fd1498Szrj if (TREE_CODE (value) != ADDR_EXPR) 300538fd1498Szrj return false; 300638fd1498Szrj 300738fd1498Szrj var = get_base_address (TREE_OPERAND (value, 0)); 300838fd1498Szrj 300938fd1498Szrj return var && auto_var_in_fn_p (var, fn); 301038fd1498Szrj } 301138fd1498Szrj 301238fd1498Szrj /* Append to BB a debug annotation that binds VAR to VALUE, inheriting 301338fd1498Szrj lexical block and line number information from base_stmt, if given, 301438fd1498Szrj or from the last stmt of the block otherwise. */ 301538fd1498Szrj 301638fd1498Szrj static gimple * 301738fd1498Szrj insert_init_debug_bind (copy_body_data *id, 301838fd1498Szrj basic_block bb, tree var, tree value, 301938fd1498Szrj gimple *base_stmt) 302038fd1498Szrj { 302138fd1498Szrj gimple *note; 302238fd1498Szrj gimple_stmt_iterator gsi; 302338fd1498Szrj tree tracked_var; 302438fd1498Szrj 302538fd1498Szrj if (!gimple_in_ssa_p (id->src_cfun)) 302638fd1498Szrj return NULL; 302738fd1498Szrj 302838fd1498Szrj if (!opt_for_fn (id->dst_fn, flag_var_tracking_assignments)) 302938fd1498Szrj return NULL; 303038fd1498Szrj 303138fd1498Szrj tracked_var = target_for_debug_bind (var); 303238fd1498Szrj if (!tracked_var) 303338fd1498Szrj return NULL; 303438fd1498Szrj 303538fd1498Szrj if (bb) 303638fd1498Szrj { 303738fd1498Szrj gsi = gsi_last_bb (bb); 303838fd1498Szrj if (!base_stmt && !gsi_end_p (gsi)) 303938fd1498Szrj base_stmt = gsi_stmt (gsi); 304038fd1498Szrj } 304138fd1498Szrj 304238fd1498Szrj note = gimple_build_debug_bind (tracked_var, unshare_expr (value), base_stmt); 304338fd1498Szrj 304438fd1498Szrj if (bb) 304538fd1498Szrj { 304638fd1498Szrj if (!gsi_end_p (gsi)) 304738fd1498Szrj gsi_insert_after (&gsi, note, GSI_SAME_STMT); 304838fd1498Szrj else 304938fd1498Szrj gsi_insert_before (&gsi, note, GSI_SAME_STMT); 305038fd1498Szrj } 305138fd1498Szrj 305238fd1498Szrj return note; 305338fd1498Szrj } 305438fd1498Szrj 305538fd1498Szrj static void 305638fd1498Szrj insert_init_stmt (copy_body_data *id, basic_block bb, gimple *init_stmt) 305738fd1498Szrj { 305838fd1498Szrj /* If VAR represents a zero-sized variable, it's possible that the 305938fd1498Szrj assignment statement may result in no gimple statements. */ 306038fd1498Szrj if (init_stmt) 306138fd1498Szrj { 306238fd1498Szrj gimple_stmt_iterator si = gsi_last_bb (bb); 306338fd1498Szrj 306438fd1498Szrj /* We can end up with init statements that store to a non-register 306538fd1498Szrj from a rhs with a conversion. Handle that here by forcing the 306638fd1498Szrj rhs into a temporary. gimple_regimplify_operands is not 306738fd1498Szrj prepared to do this for us. */ 306838fd1498Szrj if (!is_gimple_debug (init_stmt) 306938fd1498Szrj && !is_gimple_reg (gimple_assign_lhs (init_stmt)) 307038fd1498Szrj && is_gimple_reg_type (TREE_TYPE (gimple_assign_lhs (init_stmt))) 307138fd1498Szrj && gimple_assign_rhs_class (init_stmt) == GIMPLE_UNARY_RHS) 307238fd1498Szrj { 307338fd1498Szrj tree rhs = build1 (gimple_assign_rhs_code (init_stmt), 307438fd1498Szrj gimple_expr_type (init_stmt), 307538fd1498Szrj gimple_assign_rhs1 (init_stmt)); 307638fd1498Szrj rhs = force_gimple_operand_gsi (&si, rhs, true, NULL_TREE, false, 307738fd1498Szrj GSI_NEW_STMT); 307838fd1498Szrj gimple_assign_set_rhs_code (init_stmt, TREE_CODE (rhs)); 307938fd1498Szrj gimple_assign_set_rhs1 (init_stmt, rhs); 308038fd1498Szrj } 308138fd1498Szrj gsi_insert_after (&si, init_stmt, GSI_NEW_STMT); 308238fd1498Szrj gimple_regimplify_operands (init_stmt, &si); 308338fd1498Szrj 308438fd1498Szrj if (!is_gimple_debug (init_stmt)) 308538fd1498Szrj { 308638fd1498Szrj tree def = gimple_assign_lhs (init_stmt); 308738fd1498Szrj insert_init_debug_bind (id, bb, def, def, init_stmt); 308838fd1498Szrj } 308938fd1498Szrj } 309038fd1498Szrj } 309138fd1498Szrj 309238fd1498Szrj /* Initialize parameter P with VALUE. If needed, produce init statement 309338fd1498Szrj at the end of BB. When BB is NULL, we return init statement to be 309438fd1498Szrj output later. */ 309538fd1498Szrj static gimple * 309638fd1498Szrj setup_one_parameter (copy_body_data *id, tree p, tree value, tree fn, 309738fd1498Szrj basic_block bb, tree *vars) 309838fd1498Szrj { 309938fd1498Szrj gimple *init_stmt = NULL; 310038fd1498Szrj tree var; 310138fd1498Szrj tree rhs = value; 310238fd1498Szrj tree def = (gimple_in_ssa_p (cfun) 310338fd1498Szrj ? ssa_default_def (id->src_cfun, p) : NULL); 310438fd1498Szrj 310538fd1498Szrj if (value 310638fd1498Szrj && value != error_mark_node 310738fd1498Szrj && !useless_type_conversion_p (TREE_TYPE (p), TREE_TYPE (value))) 310838fd1498Szrj { 310938fd1498Szrj /* If we can match up types by promotion/demotion do so. */ 311038fd1498Szrj if (fold_convertible_p (TREE_TYPE (p), value)) 311138fd1498Szrj rhs = fold_convert (TREE_TYPE (p), value); 311238fd1498Szrj else 311338fd1498Szrj { 311438fd1498Szrj /* ??? For valid programs we should not end up here. 311538fd1498Szrj Still if we end up with truly mismatched types here, fall back 311638fd1498Szrj to using a VIEW_CONVERT_EXPR or a literal zero to not leak invalid 311738fd1498Szrj GIMPLE to the following passes. */ 311838fd1498Szrj if (!is_gimple_reg_type (TREE_TYPE (value)) 311938fd1498Szrj || TYPE_SIZE (TREE_TYPE (p)) == TYPE_SIZE (TREE_TYPE (value))) 312038fd1498Szrj rhs = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (p), value); 312138fd1498Szrj else 312238fd1498Szrj rhs = build_zero_cst (TREE_TYPE (p)); 312338fd1498Szrj } 312438fd1498Szrj } 312538fd1498Szrj 312638fd1498Szrj /* Make an equivalent VAR_DECL. Note that we must NOT remap the type 312738fd1498Szrj here since the type of this decl must be visible to the calling 312838fd1498Szrj function. */ 312938fd1498Szrj var = copy_decl_to_var (p, id); 313038fd1498Szrj 313138fd1498Szrj /* Declare this new variable. */ 313238fd1498Szrj DECL_CHAIN (var) = *vars; 313338fd1498Szrj *vars = var; 313438fd1498Szrj 313538fd1498Szrj /* Make gimplifier happy about this variable. */ 313638fd1498Szrj DECL_SEEN_IN_BIND_EXPR_P (var) = 1; 313738fd1498Szrj 313838fd1498Szrj /* If the parameter is never assigned to, has no SSA_NAMEs created, 313938fd1498Szrj we would not need to create a new variable here at all, if it 314038fd1498Szrj weren't for debug info. Still, we can just use the argument 314138fd1498Szrj value. */ 314238fd1498Szrj if (TREE_READONLY (p) 314338fd1498Szrj && !TREE_ADDRESSABLE (p) 314438fd1498Szrj && value && !TREE_SIDE_EFFECTS (value) 314538fd1498Szrj && !def) 314638fd1498Szrj { 314738fd1498Szrj /* We may produce non-gimple trees by adding NOPs or introduce 314838fd1498Szrj invalid sharing when operand is not really constant. 314938fd1498Szrj It is not big deal to prohibit constant propagation here as 315038fd1498Szrj we will constant propagate in DOM1 pass anyway. */ 315138fd1498Szrj if (is_gimple_min_invariant (value) 315238fd1498Szrj && useless_type_conversion_p (TREE_TYPE (p), 315338fd1498Szrj TREE_TYPE (value)) 315438fd1498Szrj /* We have to be very careful about ADDR_EXPR. Make sure 315538fd1498Szrj the base variable isn't a local variable of the inlined 315638fd1498Szrj function, e.g., when doing recursive inlining, direct or 315738fd1498Szrj mutually-recursive or whatever, which is why we don't 315838fd1498Szrj just test whether fn == current_function_decl. */ 315938fd1498Szrj && ! self_inlining_addr_expr (value, fn)) 316038fd1498Szrj { 316138fd1498Szrj insert_decl_map (id, p, value); 316238fd1498Szrj insert_debug_decl_map (id, p, var); 316338fd1498Szrj return insert_init_debug_bind (id, bb, var, value, NULL); 316438fd1498Szrj } 316538fd1498Szrj } 316638fd1498Szrj 316738fd1498Szrj /* Register the VAR_DECL as the equivalent for the PARM_DECL; 316838fd1498Szrj that way, when the PARM_DECL is encountered, it will be 316938fd1498Szrj automatically replaced by the VAR_DECL. */ 317038fd1498Szrj insert_decl_map (id, p, var); 317138fd1498Szrj 317238fd1498Szrj /* Even if P was TREE_READONLY, the new VAR should not be. 317338fd1498Szrj In the original code, we would have constructed a 317438fd1498Szrj temporary, and then the function body would have never 317538fd1498Szrj changed the value of P. However, now, we will be 317638fd1498Szrj constructing VAR directly. The constructor body may 317738fd1498Szrj change its value multiple times as it is being 317838fd1498Szrj constructed. Therefore, it must not be TREE_READONLY; 317938fd1498Szrj the back-end assumes that TREE_READONLY variable is 318038fd1498Szrj assigned to only once. */ 318138fd1498Szrj if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (p))) 318238fd1498Szrj TREE_READONLY (var) = 0; 318338fd1498Szrj 318438fd1498Szrj /* If there is no setup required and we are in SSA, take the easy route 318538fd1498Szrj replacing all SSA names representing the function parameter by the 318638fd1498Szrj SSA name passed to function. 318738fd1498Szrj 318838fd1498Szrj We need to construct map for the variable anyway as it might be used 318938fd1498Szrj in different SSA names when parameter is set in function. 319038fd1498Szrj 319138fd1498Szrj Do replacement at -O0 for const arguments replaced by constant. 319238fd1498Szrj This is important for builtin_constant_p and other construct requiring 319338fd1498Szrj constant argument to be visible in inlined function body. */ 319438fd1498Szrj if (gimple_in_ssa_p (cfun) && rhs && def && is_gimple_reg (p) 319538fd1498Szrj && (optimize 319638fd1498Szrj || (TREE_READONLY (p) 319738fd1498Szrj && is_gimple_min_invariant (rhs))) 319838fd1498Szrj && (TREE_CODE (rhs) == SSA_NAME 319938fd1498Szrj || is_gimple_min_invariant (rhs)) 320038fd1498Szrj && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (def)) 320138fd1498Szrj { 320238fd1498Szrj insert_decl_map (id, def, rhs); 320338fd1498Szrj return insert_init_debug_bind (id, bb, var, rhs, NULL); 320438fd1498Szrj } 320538fd1498Szrj 320638fd1498Szrj /* If the value of argument is never used, don't care about initializing 320738fd1498Szrj it. */ 320838fd1498Szrj if (optimize && gimple_in_ssa_p (cfun) && !def && is_gimple_reg (p)) 320938fd1498Szrj { 321038fd1498Szrj gcc_assert (!value || !TREE_SIDE_EFFECTS (value)); 321138fd1498Szrj return insert_init_debug_bind (id, bb, var, rhs, NULL); 321238fd1498Szrj } 321338fd1498Szrj 321438fd1498Szrj /* Initialize this VAR_DECL from the equivalent argument. Convert 321538fd1498Szrj the argument to the proper type in case it was promoted. */ 321638fd1498Szrj if (value) 321738fd1498Szrj { 321838fd1498Szrj if (rhs == error_mark_node) 321938fd1498Szrj { 322038fd1498Szrj insert_decl_map (id, p, var); 322138fd1498Szrj return insert_init_debug_bind (id, bb, var, rhs, NULL); 322238fd1498Szrj } 322338fd1498Szrj 322438fd1498Szrj STRIP_USELESS_TYPE_CONVERSION (rhs); 322538fd1498Szrj 322638fd1498Szrj /* If we are in SSA form properly remap the default definition 322738fd1498Szrj or assign to a dummy SSA name if the parameter is unused and 322838fd1498Szrj we are not optimizing. */ 322938fd1498Szrj if (gimple_in_ssa_p (cfun) && is_gimple_reg (p)) 323038fd1498Szrj { 323138fd1498Szrj if (def) 323238fd1498Szrj { 323338fd1498Szrj def = remap_ssa_name (def, id); 323438fd1498Szrj init_stmt = gimple_build_assign (def, rhs); 323538fd1498Szrj SSA_NAME_IS_DEFAULT_DEF (def) = 0; 323638fd1498Szrj set_ssa_default_def (cfun, var, NULL); 323738fd1498Szrj } 323838fd1498Szrj else if (!optimize) 323938fd1498Szrj { 324038fd1498Szrj def = make_ssa_name (var); 324138fd1498Szrj init_stmt = gimple_build_assign (def, rhs); 324238fd1498Szrj } 324338fd1498Szrj } 324438fd1498Szrj else 324538fd1498Szrj init_stmt = gimple_build_assign (var, rhs); 324638fd1498Szrj 324738fd1498Szrj if (bb && init_stmt) 324838fd1498Szrj insert_init_stmt (id, bb, init_stmt); 324938fd1498Szrj } 325038fd1498Szrj return init_stmt; 325138fd1498Szrj } 325238fd1498Szrj 325338fd1498Szrj /* Generate code to initialize the parameters of the function at the 325438fd1498Szrj top of the stack in ID from the GIMPLE_CALL STMT. */ 325538fd1498Szrj 325638fd1498Szrj static void 325738fd1498Szrj initialize_inlined_parameters (copy_body_data *id, gimple *stmt, 325838fd1498Szrj tree fn, basic_block bb) 325938fd1498Szrj { 326038fd1498Szrj tree parms; 326138fd1498Szrj size_t i; 326238fd1498Szrj tree p; 326338fd1498Szrj tree vars = NULL_TREE; 326438fd1498Szrj tree static_chain = gimple_call_chain (stmt); 326538fd1498Szrj 326638fd1498Szrj /* Figure out what the parameters are. */ 326738fd1498Szrj parms = DECL_ARGUMENTS (fn); 326838fd1498Szrj 326938fd1498Szrj /* Loop through the parameter declarations, replacing each with an 327038fd1498Szrj equivalent VAR_DECL, appropriately initialized. */ 327138fd1498Szrj for (p = parms, i = 0; p; p = DECL_CHAIN (p), i++) 327238fd1498Szrj { 327338fd1498Szrj tree val; 327438fd1498Szrj val = i < gimple_call_num_args (stmt) ? gimple_call_arg (stmt, i) : NULL; 327538fd1498Szrj setup_one_parameter (id, p, val, fn, bb, &vars); 327638fd1498Szrj } 327738fd1498Szrj /* After remapping parameters remap their types. This has to be done 327838fd1498Szrj in a second loop over all parameters to appropriately remap 327938fd1498Szrj variable sized arrays when the size is specified in a 328038fd1498Szrj parameter following the array. */ 328138fd1498Szrj for (p = parms, i = 0; p; p = DECL_CHAIN (p), i++) 328238fd1498Szrj { 328338fd1498Szrj tree *varp = id->decl_map->get (p); 328438fd1498Szrj if (varp && VAR_P (*varp)) 328538fd1498Szrj { 328638fd1498Szrj tree def = (gimple_in_ssa_p (cfun) && is_gimple_reg (p) 328738fd1498Szrj ? ssa_default_def (id->src_cfun, p) : NULL); 328838fd1498Szrj tree var = *varp; 328938fd1498Szrj TREE_TYPE (var) = remap_type (TREE_TYPE (var), id); 329038fd1498Szrj /* Also remap the default definition if it was remapped 329138fd1498Szrj to the default definition of the parameter replacement 329238fd1498Szrj by the parameter setup. */ 329338fd1498Szrj if (def) 329438fd1498Szrj { 329538fd1498Szrj tree *defp = id->decl_map->get (def); 329638fd1498Szrj if (defp 329738fd1498Szrj && TREE_CODE (*defp) == SSA_NAME 329838fd1498Szrj && SSA_NAME_VAR (*defp) == var) 329938fd1498Szrj TREE_TYPE (*defp) = TREE_TYPE (var); 330038fd1498Szrj } 330138fd1498Szrj } 330238fd1498Szrj } 330338fd1498Szrj 330438fd1498Szrj /* Initialize the static chain. */ 330538fd1498Szrj p = DECL_STRUCT_FUNCTION (fn)->static_chain_decl; 330638fd1498Szrj gcc_assert (fn != current_function_decl); 330738fd1498Szrj if (p) 330838fd1498Szrj { 330938fd1498Szrj /* No static chain? Seems like a bug in tree-nested.c. */ 331038fd1498Szrj gcc_assert (static_chain); 331138fd1498Szrj 331238fd1498Szrj setup_one_parameter (id, p, static_chain, fn, bb, &vars); 331338fd1498Szrj } 331438fd1498Szrj 331538fd1498Szrj declare_inline_vars (id->block, vars); 331638fd1498Szrj } 331738fd1498Szrj 331838fd1498Szrj 331938fd1498Szrj /* Declare a return variable to replace the RESULT_DECL for the 332038fd1498Szrj function we are calling. An appropriate DECL_STMT is returned. 332138fd1498Szrj The USE_STMT is filled to contain a use of the declaration to 332238fd1498Szrj indicate the return value of the function. 332338fd1498Szrj 332438fd1498Szrj RETURN_SLOT, if non-null is place where to store the result. It 332538fd1498Szrj is set only for CALL_EXPR_RETURN_SLOT_OPT. MODIFY_DEST, if non-null, 332638fd1498Szrj was the LHS of the MODIFY_EXPR to which this call is the RHS. 332738fd1498Szrj 332838fd1498Szrj RETURN_BOUNDS holds a destination for returned bounds. 332938fd1498Szrj 333038fd1498Szrj The return value is a (possibly null) value that holds the result 333138fd1498Szrj as seen by the caller. */ 333238fd1498Szrj 333338fd1498Szrj static tree 333438fd1498Szrj declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest, 333538fd1498Szrj tree return_bounds, basic_block entry_bb) 333638fd1498Szrj { 333738fd1498Szrj tree callee = id->src_fn; 333838fd1498Szrj tree result = DECL_RESULT (callee); 333938fd1498Szrj tree callee_type = TREE_TYPE (result); 334038fd1498Szrj tree caller_type; 334138fd1498Szrj tree var, use; 334238fd1498Szrj 334338fd1498Szrj /* Handle type-mismatches in the function declaration return type 334438fd1498Szrj vs. the call expression. */ 334538fd1498Szrj if (modify_dest) 334638fd1498Szrj caller_type = TREE_TYPE (modify_dest); 334738fd1498Szrj else 334838fd1498Szrj caller_type = TREE_TYPE (TREE_TYPE (callee)); 334938fd1498Szrj 335038fd1498Szrj /* We don't need to do anything for functions that don't return anything. */ 335138fd1498Szrj if (VOID_TYPE_P (callee_type)) 335238fd1498Szrj return NULL_TREE; 335338fd1498Szrj 335438fd1498Szrj /* If there was a return slot, then the return value is the 335538fd1498Szrj dereferenced address of that object. */ 335638fd1498Szrj if (return_slot) 335738fd1498Szrj { 335838fd1498Szrj /* The front end shouldn't have used both return_slot and 335938fd1498Szrj a modify expression. */ 336038fd1498Szrj gcc_assert (!modify_dest); 336138fd1498Szrj if (DECL_BY_REFERENCE (result)) 336238fd1498Szrj { 336338fd1498Szrj tree return_slot_addr = build_fold_addr_expr (return_slot); 336438fd1498Szrj STRIP_USELESS_TYPE_CONVERSION (return_slot_addr); 336538fd1498Szrj 336638fd1498Szrj /* We are going to construct *&return_slot and we can't do that 336738fd1498Szrj for variables believed to be not addressable. 336838fd1498Szrj 336938fd1498Szrj FIXME: This check possibly can match, because values returned 337038fd1498Szrj via return slot optimization are not believed to have address 337138fd1498Szrj taken by alias analysis. */ 337238fd1498Szrj gcc_assert (TREE_CODE (return_slot) != SSA_NAME); 337338fd1498Szrj var = return_slot_addr; 337438fd1498Szrj } 337538fd1498Szrj else 337638fd1498Szrj { 337738fd1498Szrj var = return_slot; 337838fd1498Szrj gcc_assert (TREE_CODE (var) != SSA_NAME); 337938fd1498Szrj if (TREE_ADDRESSABLE (result)) 338038fd1498Szrj mark_addressable (var); 338138fd1498Szrj } 338238fd1498Szrj if ((TREE_CODE (TREE_TYPE (result)) == COMPLEX_TYPE 338338fd1498Szrj || TREE_CODE (TREE_TYPE (result)) == VECTOR_TYPE) 338438fd1498Szrj && !DECL_GIMPLE_REG_P (result) 338538fd1498Szrj && DECL_P (var)) 338638fd1498Szrj DECL_GIMPLE_REG_P (var) = 0; 338738fd1498Szrj use = NULL; 338838fd1498Szrj goto done; 338938fd1498Szrj } 339038fd1498Szrj 339138fd1498Szrj /* All types requiring non-trivial constructors should have been handled. */ 339238fd1498Szrj gcc_assert (!TREE_ADDRESSABLE (callee_type)); 339338fd1498Szrj 339438fd1498Szrj /* Attempt to avoid creating a new temporary variable. */ 339538fd1498Szrj if (modify_dest 339638fd1498Szrj && TREE_CODE (modify_dest) != SSA_NAME) 339738fd1498Szrj { 339838fd1498Szrj bool use_it = false; 339938fd1498Szrj 340038fd1498Szrj /* We can't use MODIFY_DEST if there's type promotion involved. */ 340138fd1498Szrj if (!useless_type_conversion_p (callee_type, caller_type)) 340238fd1498Szrj use_it = false; 340338fd1498Szrj 340438fd1498Szrj /* ??? If we're assigning to a variable sized type, then we must 340538fd1498Szrj reuse the destination variable, because we've no good way to 340638fd1498Szrj create variable sized temporaries at this point. */ 340738fd1498Szrj else if (TREE_CODE (TYPE_SIZE_UNIT (caller_type)) != INTEGER_CST) 340838fd1498Szrj use_it = true; 340938fd1498Szrj 341038fd1498Szrj /* If the callee cannot possibly modify MODIFY_DEST, then we can 341138fd1498Szrj reuse it as the result of the call directly. Don't do this if 341238fd1498Szrj it would promote MODIFY_DEST to addressable. */ 341338fd1498Szrj else if (TREE_ADDRESSABLE (result)) 341438fd1498Szrj use_it = false; 341538fd1498Szrj else 341638fd1498Szrj { 341738fd1498Szrj tree base_m = get_base_address (modify_dest); 341838fd1498Szrj 341938fd1498Szrj /* If the base isn't a decl, then it's a pointer, and we don't 342038fd1498Szrj know where that's going to go. */ 342138fd1498Szrj if (!DECL_P (base_m)) 342238fd1498Szrj use_it = false; 342338fd1498Szrj else if (is_global_var (base_m)) 342438fd1498Szrj use_it = false; 342538fd1498Szrj else if ((TREE_CODE (TREE_TYPE (result)) == COMPLEX_TYPE 342638fd1498Szrj || TREE_CODE (TREE_TYPE (result)) == VECTOR_TYPE) 342738fd1498Szrj && !DECL_GIMPLE_REG_P (result) 342838fd1498Szrj && DECL_GIMPLE_REG_P (base_m)) 342938fd1498Szrj use_it = false; 343038fd1498Szrj else if (!TREE_ADDRESSABLE (base_m)) 343138fd1498Szrj use_it = true; 343238fd1498Szrj } 343338fd1498Szrj 343438fd1498Szrj if (use_it) 343538fd1498Szrj { 343638fd1498Szrj var = modify_dest; 343738fd1498Szrj use = NULL; 343838fd1498Szrj goto done; 343938fd1498Szrj } 344038fd1498Szrj } 344138fd1498Szrj 344238fd1498Szrj gcc_assert (TREE_CODE (TYPE_SIZE_UNIT (callee_type)) == INTEGER_CST); 344338fd1498Szrj 344438fd1498Szrj var = copy_result_decl_to_var (result, id); 344538fd1498Szrj DECL_SEEN_IN_BIND_EXPR_P (var) = 1; 344638fd1498Szrj 344738fd1498Szrj /* Do not have the rest of GCC warn about this variable as it should 344838fd1498Szrj not be visible to the user. */ 344938fd1498Szrj TREE_NO_WARNING (var) = 1; 345038fd1498Szrj 345138fd1498Szrj declare_inline_vars (id->block, var); 345238fd1498Szrj 345338fd1498Szrj /* Build the use expr. If the return type of the function was 345438fd1498Szrj promoted, convert it back to the expected type. */ 345538fd1498Szrj use = var; 345638fd1498Szrj if (!useless_type_conversion_p (caller_type, TREE_TYPE (var))) 345738fd1498Szrj { 345838fd1498Szrj /* If we can match up types by promotion/demotion do so. */ 345938fd1498Szrj if (fold_convertible_p (caller_type, var)) 346038fd1498Szrj use = fold_convert (caller_type, var); 346138fd1498Szrj else 346238fd1498Szrj { 346338fd1498Szrj /* ??? For valid programs we should not end up here. 346438fd1498Szrj Still if we end up with truly mismatched types here, fall back 346538fd1498Szrj to using a MEM_REF to not leak invalid GIMPLE to the following 346638fd1498Szrj passes. */ 346738fd1498Szrj /* Prevent var from being written into SSA form. */ 346838fd1498Szrj if (TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE 346938fd1498Szrj || TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE) 347038fd1498Szrj DECL_GIMPLE_REG_P (var) = false; 347138fd1498Szrj else if (is_gimple_reg_type (TREE_TYPE (var))) 347238fd1498Szrj TREE_ADDRESSABLE (var) = true; 347338fd1498Szrj use = fold_build2 (MEM_REF, caller_type, 347438fd1498Szrj build_fold_addr_expr (var), 347538fd1498Szrj build_int_cst (ptr_type_node, 0)); 347638fd1498Szrj } 347738fd1498Szrj } 347838fd1498Szrj 347938fd1498Szrj STRIP_USELESS_TYPE_CONVERSION (use); 348038fd1498Szrj 348138fd1498Szrj if (DECL_BY_REFERENCE (result)) 348238fd1498Szrj { 348338fd1498Szrj TREE_ADDRESSABLE (var) = 1; 348438fd1498Szrj var = build_fold_addr_expr (var); 348538fd1498Szrj } 348638fd1498Szrj 348738fd1498Szrj done: 348838fd1498Szrj /* Register the VAR_DECL as the equivalent for the RESULT_DECL; that 348938fd1498Szrj way, when the RESULT_DECL is encountered, it will be 349038fd1498Szrj automatically replaced by the VAR_DECL. 349138fd1498Szrj 349238fd1498Szrj When returning by reference, ensure that RESULT_DECL remaps to 349338fd1498Szrj gimple_val. */ 349438fd1498Szrj if (DECL_BY_REFERENCE (result) 349538fd1498Szrj && !is_gimple_val (var)) 349638fd1498Szrj { 349738fd1498Szrj tree temp = create_tmp_var (TREE_TYPE (result), "retvalptr"); 349838fd1498Szrj insert_decl_map (id, result, temp); 349938fd1498Szrj /* When RESULT_DECL is in SSA form, we need to remap and initialize 350038fd1498Szrj it's default_def SSA_NAME. */ 350138fd1498Szrj if (gimple_in_ssa_p (id->src_cfun) 350238fd1498Szrj && is_gimple_reg (result)) 350338fd1498Szrj { 350438fd1498Szrj temp = make_ssa_name (temp); 350538fd1498Szrj insert_decl_map (id, ssa_default_def (id->src_cfun, result), temp); 350638fd1498Szrj } 350738fd1498Szrj insert_init_stmt (id, entry_bb, gimple_build_assign (temp, var)); 350838fd1498Szrj } 350938fd1498Szrj else 351038fd1498Szrj insert_decl_map (id, result, var); 351138fd1498Szrj 351238fd1498Szrj /* Remember this so we can ignore it in remap_decls. */ 351338fd1498Szrj id->retvar = var; 351438fd1498Szrj 351538fd1498Szrj /* If returned bounds are used, then make var for them. */ 351638fd1498Szrj if (return_bounds) 351738fd1498Szrj { 351838fd1498Szrj tree bndtemp = create_tmp_var (pointer_bounds_type_node, "retbnd"); 351938fd1498Szrj DECL_SEEN_IN_BIND_EXPR_P (bndtemp) = 1; 352038fd1498Szrj TREE_NO_WARNING (bndtemp) = 1; 352138fd1498Szrj declare_inline_vars (id->block, bndtemp); 352238fd1498Szrj 352338fd1498Szrj id->retbnd = bndtemp; 352438fd1498Szrj insert_init_stmt (id, entry_bb, 352538fd1498Szrj gimple_build_assign (bndtemp, chkp_get_zero_bounds_var ())); 352638fd1498Szrj } 352738fd1498Szrj 352838fd1498Szrj return use; 352938fd1498Szrj } 353038fd1498Szrj 353138fd1498Szrj /* Determine if the function can be copied. If so return NULL. If 353238fd1498Szrj not return a string describng the reason for failure. */ 353338fd1498Szrj 353438fd1498Szrj const char * 353538fd1498Szrj copy_forbidden (struct function *fun) 353638fd1498Szrj { 353738fd1498Szrj const char *reason = fun->cannot_be_copied_reason; 353838fd1498Szrj 353938fd1498Szrj /* Only examine the function once. */ 354038fd1498Szrj if (fun->cannot_be_copied_set) 354138fd1498Szrj return reason; 354238fd1498Szrj 354338fd1498Szrj /* We cannot copy a function that receives a non-local goto 354438fd1498Szrj because we cannot remap the destination label used in the 354538fd1498Szrj function that is performing the non-local goto. */ 354638fd1498Szrj /* ??? Actually, this should be possible, if we work at it. 354738fd1498Szrj No doubt there's just a handful of places that simply 354838fd1498Szrj assume it doesn't happen and don't substitute properly. */ 354938fd1498Szrj if (fun->has_nonlocal_label) 355038fd1498Szrj { 355138fd1498Szrj reason = G_("function %q+F can never be copied " 355238fd1498Szrj "because it receives a non-local goto"); 355338fd1498Szrj goto fail; 355438fd1498Szrj } 355538fd1498Szrj 355638fd1498Szrj if (fun->has_forced_label_in_static) 355738fd1498Szrj { 355838fd1498Szrj reason = G_("function %q+F can never be copied because it saves " 355938fd1498Szrj "address of local label in a static variable"); 356038fd1498Szrj goto fail; 356138fd1498Szrj } 356238fd1498Szrj 356338fd1498Szrj fail: 356438fd1498Szrj fun->cannot_be_copied_reason = reason; 356538fd1498Szrj fun->cannot_be_copied_set = true; 356638fd1498Szrj return reason; 356738fd1498Szrj } 356838fd1498Szrj 356938fd1498Szrj 357038fd1498Szrj static const char *inline_forbidden_reason; 357138fd1498Szrj 357238fd1498Szrj /* A callback for walk_gimple_seq to handle statements. Returns non-null 357338fd1498Szrj iff a function can not be inlined. Also sets the reason why. */ 357438fd1498Szrj 357538fd1498Szrj static tree 357638fd1498Szrj inline_forbidden_p_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p, 357738fd1498Szrj struct walk_stmt_info *wip) 357838fd1498Szrj { 357938fd1498Szrj tree fn = (tree) wip->info; 358038fd1498Szrj tree t; 358138fd1498Szrj gimple *stmt = gsi_stmt (*gsi); 358238fd1498Szrj 358338fd1498Szrj switch (gimple_code (stmt)) 358438fd1498Szrj { 358538fd1498Szrj case GIMPLE_CALL: 358638fd1498Szrj /* Refuse to inline alloca call unless user explicitly forced so as 358738fd1498Szrj this may change program's memory overhead drastically when the 358838fd1498Szrj function using alloca is called in loop. In GCC present in 358938fd1498Szrj SPEC2000 inlining into schedule_block cause it to require 2GB of 359038fd1498Szrj RAM instead of 256MB. Don't do so for alloca calls emitted for 359138fd1498Szrj VLA objects as those can't cause unbounded growth (they're always 359238fd1498Szrj wrapped inside stack_save/stack_restore regions. */ 359338fd1498Szrj if (gimple_maybe_alloca_call_p (stmt) 359438fd1498Szrj && !gimple_call_alloca_for_var_p (as_a <gcall *> (stmt)) 359538fd1498Szrj && !lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn))) 359638fd1498Szrj { 359738fd1498Szrj inline_forbidden_reason 359838fd1498Szrj = G_("function %q+F can never be inlined because it uses " 359938fd1498Szrj "alloca (override using the always_inline attribute)"); 360038fd1498Szrj *handled_ops_p = true; 360138fd1498Szrj return fn; 360238fd1498Szrj } 360338fd1498Szrj 360438fd1498Szrj t = gimple_call_fndecl (stmt); 360538fd1498Szrj if (t == NULL_TREE) 360638fd1498Szrj break; 360738fd1498Szrj 360838fd1498Szrj /* We cannot inline functions that call setjmp. */ 360938fd1498Szrj if (setjmp_call_p (t)) 361038fd1498Szrj { 361138fd1498Szrj inline_forbidden_reason 361238fd1498Szrj = G_("function %q+F can never be inlined because it uses setjmp"); 361338fd1498Szrj *handled_ops_p = true; 361438fd1498Szrj return t; 361538fd1498Szrj } 361638fd1498Szrj 361738fd1498Szrj if (DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL) 361838fd1498Szrj switch (DECL_FUNCTION_CODE (t)) 361938fd1498Szrj { 362038fd1498Szrj /* We cannot inline functions that take a variable number of 362138fd1498Szrj arguments. */ 362238fd1498Szrj case BUILT_IN_VA_START: 362338fd1498Szrj case BUILT_IN_NEXT_ARG: 362438fd1498Szrj case BUILT_IN_VA_END: 362538fd1498Szrj inline_forbidden_reason 362638fd1498Szrj = G_("function %q+F can never be inlined because it " 362738fd1498Szrj "uses variable argument lists"); 362838fd1498Szrj *handled_ops_p = true; 362938fd1498Szrj return t; 363038fd1498Szrj 363138fd1498Szrj case BUILT_IN_LONGJMP: 363238fd1498Szrj /* We can't inline functions that call __builtin_longjmp at 363338fd1498Szrj all. The non-local goto machinery really requires the 363438fd1498Szrj destination be in a different function. If we allow the 363538fd1498Szrj function calling __builtin_longjmp to be inlined into the 363638fd1498Szrj function calling __builtin_setjmp, Things will Go Awry. */ 363738fd1498Szrj inline_forbidden_reason 363838fd1498Szrj = G_("function %q+F can never be inlined because " 363938fd1498Szrj "it uses setjmp-longjmp exception handling"); 364038fd1498Szrj *handled_ops_p = true; 364138fd1498Szrj return t; 364238fd1498Szrj 364338fd1498Szrj case BUILT_IN_NONLOCAL_GOTO: 364438fd1498Szrj /* Similarly. */ 364538fd1498Szrj inline_forbidden_reason 364638fd1498Szrj = G_("function %q+F can never be inlined because " 364738fd1498Szrj "it uses non-local goto"); 364838fd1498Szrj *handled_ops_p = true; 364938fd1498Szrj return t; 365038fd1498Szrj 365138fd1498Szrj case BUILT_IN_RETURN: 365238fd1498Szrj case BUILT_IN_APPLY_ARGS: 365338fd1498Szrj /* If a __builtin_apply_args caller would be inlined, 365438fd1498Szrj it would be saving arguments of the function it has 365538fd1498Szrj been inlined into. Similarly __builtin_return would 365638fd1498Szrj return from the function the inline has been inlined into. */ 365738fd1498Szrj inline_forbidden_reason 365838fd1498Szrj = G_("function %q+F can never be inlined because " 365938fd1498Szrj "it uses __builtin_return or __builtin_apply_args"); 366038fd1498Szrj *handled_ops_p = true; 366138fd1498Szrj return t; 366238fd1498Szrj 366338fd1498Szrj default: 366438fd1498Szrj break; 366538fd1498Szrj } 366638fd1498Szrj break; 366738fd1498Szrj 366838fd1498Szrj case GIMPLE_GOTO: 366938fd1498Szrj t = gimple_goto_dest (stmt); 367038fd1498Szrj 367138fd1498Szrj /* We will not inline a function which uses computed goto. The 367238fd1498Szrj addresses of its local labels, which may be tucked into 367338fd1498Szrj global storage, are of course not constant across 367438fd1498Szrj instantiations, which causes unexpected behavior. */ 367538fd1498Szrj if (TREE_CODE (t) != LABEL_DECL) 367638fd1498Szrj { 367738fd1498Szrj inline_forbidden_reason 367838fd1498Szrj = G_("function %q+F can never be inlined " 367938fd1498Szrj "because it contains a computed goto"); 368038fd1498Szrj *handled_ops_p = true; 368138fd1498Szrj return t; 368238fd1498Szrj } 368338fd1498Szrj break; 368438fd1498Szrj 368538fd1498Szrj default: 368638fd1498Szrj break; 368738fd1498Szrj } 368838fd1498Szrj 368938fd1498Szrj *handled_ops_p = false; 369038fd1498Szrj return NULL_TREE; 369138fd1498Szrj } 369238fd1498Szrj 369338fd1498Szrj /* Return true if FNDECL is a function that cannot be inlined into 369438fd1498Szrj another one. */ 369538fd1498Szrj 369638fd1498Szrj static bool 369738fd1498Szrj inline_forbidden_p (tree fndecl) 369838fd1498Szrj { 369938fd1498Szrj struct function *fun = DECL_STRUCT_FUNCTION (fndecl); 370038fd1498Szrj struct walk_stmt_info wi; 370138fd1498Szrj basic_block bb; 370238fd1498Szrj bool forbidden_p = false; 370338fd1498Szrj 370438fd1498Szrj /* First check for shared reasons not to copy the code. */ 370538fd1498Szrj inline_forbidden_reason = copy_forbidden (fun); 370638fd1498Szrj if (inline_forbidden_reason != NULL) 370738fd1498Szrj return true; 370838fd1498Szrj 370938fd1498Szrj /* Next, walk the statements of the function looking for 371038fd1498Szrj constraucts we can't handle, or are non-optimal for inlining. */ 371138fd1498Szrj hash_set<tree> visited_nodes; 371238fd1498Szrj memset (&wi, 0, sizeof (wi)); 371338fd1498Szrj wi.info = (void *) fndecl; 371438fd1498Szrj wi.pset = &visited_nodes; 371538fd1498Szrj 371638fd1498Szrj FOR_EACH_BB_FN (bb, fun) 371738fd1498Szrj { 371838fd1498Szrj gimple *ret; 371938fd1498Szrj gimple_seq seq = bb_seq (bb); 372038fd1498Szrj ret = walk_gimple_seq (seq, inline_forbidden_p_stmt, NULL, &wi); 372138fd1498Szrj forbidden_p = (ret != NULL); 372238fd1498Szrj if (forbidden_p) 372338fd1498Szrj break; 372438fd1498Szrj } 372538fd1498Szrj 372638fd1498Szrj return forbidden_p; 372738fd1498Szrj } 372838fd1498Szrj 372938fd1498Szrj /* Return false if the function FNDECL cannot be inlined on account of its 373038fd1498Szrj attributes, true otherwise. */ 373138fd1498Szrj static bool 373238fd1498Szrj function_attribute_inlinable_p (const_tree fndecl) 373338fd1498Szrj { 373438fd1498Szrj if (targetm.attribute_table) 373538fd1498Szrj { 373638fd1498Szrj const_tree a; 373738fd1498Szrj 373838fd1498Szrj for (a = DECL_ATTRIBUTES (fndecl); a; a = TREE_CHAIN (a)) 373938fd1498Szrj { 374038fd1498Szrj const_tree name = TREE_PURPOSE (a); 374138fd1498Szrj int i; 374238fd1498Szrj 374338fd1498Szrj for (i = 0; targetm.attribute_table[i].name != NULL; i++) 374438fd1498Szrj if (is_attribute_p (targetm.attribute_table[i].name, name)) 374538fd1498Szrj return targetm.function_attribute_inlinable_p (fndecl); 374638fd1498Szrj } 374738fd1498Szrj } 374838fd1498Szrj 374938fd1498Szrj return true; 375038fd1498Szrj } 375138fd1498Szrj 375238fd1498Szrj /* Returns nonzero if FN is a function that does not have any 375338fd1498Szrj fundamental inline blocking properties. */ 375438fd1498Szrj 375538fd1498Szrj bool 375638fd1498Szrj tree_inlinable_function_p (tree fn) 375738fd1498Szrj { 375838fd1498Szrj bool inlinable = true; 375938fd1498Szrj bool do_warning; 376038fd1498Szrj tree always_inline; 376138fd1498Szrj 376238fd1498Szrj /* If we've already decided this function shouldn't be inlined, 376338fd1498Szrj there's no need to check again. */ 376438fd1498Szrj if (DECL_UNINLINABLE (fn)) 376538fd1498Szrj return false; 376638fd1498Szrj 376738fd1498Szrj /* We only warn for functions declared `inline' by the user. */ 376838fd1498Szrj do_warning = (warn_inline 376938fd1498Szrj && DECL_DECLARED_INLINE_P (fn) 377038fd1498Szrj && !DECL_NO_INLINE_WARNING_P (fn) 377138fd1498Szrj && !DECL_IN_SYSTEM_HEADER (fn)); 377238fd1498Szrj 377338fd1498Szrj always_inline = lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)); 377438fd1498Szrj 377538fd1498Szrj if (flag_no_inline 377638fd1498Szrj && always_inline == NULL) 377738fd1498Szrj { 377838fd1498Szrj if (do_warning) 377938fd1498Szrj warning (OPT_Winline, "function %q+F can never be inlined because it " 378038fd1498Szrj "is suppressed using -fno-inline", fn); 378138fd1498Szrj inlinable = false; 378238fd1498Szrj } 378338fd1498Szrj 378438fd1498Szrj else if (!function_attribute_inlinable_p (fn)) 378538fd1498Szrj { 378638fd1498Szrj if (do_warning) 378738fd1498Szrj warning (OPT_Winline, "function %q+F can never be inlined because it " 378838fd1498Szrj "uses attributes conflicting with inlining", fn); 378938fd1498Szrj inlinable = false; 379038fd1498Szrj } 379138fd1498Szrj 379238fd1498Szrj else if (inline_forbidden_p (fn)) 379338fd1498Szrj { 379438fd1498Szrj /* See if we should warn about uninlinable functions. Previously, 379538fd1498Szrj some of these warnings would be issued while trying to expand 379638fd1498Szrj the function inline, but that would cause multiple warnings 379738fd1498Szrj about functions that would for example call alloca. But since 379838fd1498Szrj this a property of the function, just one warning is enough. 379938fd1498Szrj As a bonus we can now give more details about the reason why a 380038fd1498Szrj function is not inlinable. */ 380138fd1498Szrj if (always_inline) 380238fd1498Szrj error (inline_forbidden_reason, fn); 380338fd1498Szrj else if (do_warning) 380438fd1498Szrj warning (OPT_Winline, inline_forbidden_reason, fn); 380538fd1498Szrj 380638fd1498Szrj inlinable = false; 380738fd1498Szrj } 380838fd1498Szrj 380938fd1498Szrj /* Squirrel away the result so that we don't have to check again. */ 381038fd1498Szrj DECL_UNINLINABLE (fn) = !inlinable; 381138fd1498Szrj 381238fd1498Szrj return inlinable; 381338fd1498Szrj } 381438fd1498Szrj 381538fd1498Szrj /* Estimate the cost of a memory move of type TYPE. Use machine dependent 381638fd1498Szrj word size and take possible memcpy call into account and return 381738fd1498Szrj cost based on whether optimizing for size or speed according to SPEED_P. */ 381838fd1498Szrj 381938fd1498Szrj int 382038fd1498Szrj estimate_move_cost (tree type, bool ARG_UNUSED (speed_p)) 382138fd1498Szrj { 382238fd1498Szrj HOST_WIDE_INT size; 382338fd1498Szrj 382438fd1498Szrj gcc_assert (!VOID_TYPE_P (type)); 382538fd1498Szrj 382638fd1498Szrj if (TREE_CODE (type) == VECTOR_TYPE) 382738fd1498Szrj { 382838fd1498Szrj scalar_mode inner = SCALAR_TYPE_MODE (TREE_TYPE (type)); 382938fd1498Szrj machine_mode simd = targetm.vectorize.preferred_simd_mode (inner); 383038fd1498Szrj int orig_mode_size 383138fd1498Szrj = estimated_poly_value (GET_MODE_SIZE (TYPE_MODE (type))); 383238fd1498Szrj int simd_mode_size = estimated_poly_value (GET_MODE_SIZE (simd)); 383338fd1498Szrj return ((orig_mode_size + simd_mode_size - 1) 383438fd1498Szrj / simd_mode_size); 383538fd1498Szrj } 383638fd1498Szrj 383738fd1498Szrj size = int_size_in_bytes (type); 383838fd1498Szrj 383938fd1498Szrj if (size < 0 || size > MOVE_MAX_PIECES * MOVE_RATIO (speed_p)) 384038fd1498Szrj /* Cost of a memcpy call, 3 arguments and the call. */ 384138fd1498Szrj return 4; 384238fd1498Szrj else 384338fd1498Szrj return ((size + MOVE_MAX_PIECES - 1) / MOVE_MAX_PIECES); 384438fd1498Szrj } 384538fd1498Szrj 384638fd1498Szrj /* Returns cost of operation CODE, according to WEIGHTS */ 384738fd1498Szrj 384838fd1498Szrj static int 384938fd1498Szrj estimate_operator_cost (enum tree_code code, eni_weights *weights, 385038fd1498Szrj tree op1 ATTRIBUTE_UNUSED, tree op2) 385138fd1498Szrj { 385238fd1498Szrj switch (code) 385338fd1498Szrj { 385438fd1498Szrj /* These are "free" conversions, or their presumed cost 385538fd1498Szrj is folded into other operations. */ 385638fd1498Szrj case RANGE_EXPR: 385738fd1498Szrj CASE_CONVERT: 385838fd1498Szrj case COMPLEX_EXPR: 385938fd1498Szrj case PAREN_EXPR: 386038fd1498Szrj case VIEW_CONVERT_EXPR: 386138fd1498Szrj return 0; 386238fd1498Szrj 386338fd1498Szrj /* Assign cost of 1 to usual operations. 386438fd1498Szrj ??? We may consider mapping RTL costs to this. */ 386538fd1498Szrj case COND_EXPR: 386638fd1498Szrj case VEC_COND_EXPR: 386738fd1498Szrj case VEC_PERM_EXPR: 386838fd1498Szrj 386938fd1498Szrj case PLUS_EXPR: 387038fd1498Szrj case POINTER_PLUS_EXPR: 387138fd1498Szrj case POINTER_DIFF_EXPR: 387238fd1498Szrj case MINUS_EXPR: 387338fd1498Szrj case MULT_EXPR: 387438fd1498Szrj case MULT_HIGHPART_EXPR: 387538fd1498Szrj case FMA_EXPR: 387638fd1498Szrj 387738fd1498Szrj case ADDR_SPACE_CONVERT_EXPR: 387838fd1498Szrj case FIXED_CONVERT_EXPR: 387938fd1498Szrj case FIX_TRUNC_EXPR: 388038fd1498Szrj 388138fd1498Szrj case NEGATE_EXPR: 388238fd1498Szrj case FLOAT_EXPR: 388338fd1498Szrj case MIN_EXPR: 388438fd1498Szrj case MAX_EXPR: 388538fd1498Szrj case ABS_EXPR: 388638fd1498Szrj 388738fd1498Szrj case LSHIFT_EXPR: 388838fd1498Szrj case RSHIFT_EXPR: 388938fd1498Szrj case LROTATE_EXPR: 389038fd1498Szrj case RROTATE_EXPR: 389138fd1498Szrj 389238fd1498Szrj case BIT_IOR_EXPR: 389338fd1498Szrj case BIT_XOR_EXPR: 389438fd1498Szrj case BIT_AND_EXPR: 389538fd1498Szrj case BIT_NOT_EXPR: 389638fd1498Szrj 389738fd1498Szrj case TRUTH_ANDIF_EXPR: 389838fd1498Szrj case TRUTH_ORIF_EXPR: 389938fd1498Szrj case TRUTH_AND_EXPR: 390038fd1498Szrj case TRUTH_OR_EXPR: 390138fd1498Szrj case TRUTH_XOR_EXPR: 390238fd1498Szrj case TRUTH_NOT_EXPR: 390338fd1498Szrj 390438fd1498Szrj case LT_EXPR: 390538fd1498Szrj case LE_EXPR: 390638fd1498Szrj case GT_EXPR: 390738fd1498Szrj case GE_EXPR: 390838fd1498Szrj case EQ_EXPR: 390938fd1498Szrj case NE_EXPR: 391038fd1498Szrj case ORDERED_EXPR: 391138fd1498Szrj case UNORDERED_EXPR: 391238fd1498Szrj 391338fd1498Szrj case UNLT_EXPR: 391438fd1498Szrj case UNLE_EXPR: 391538fd1498Szrj case UNGT_EXPR: 391638fd1498Szrj case UNGE_EXPR: 391738fd1498Szrj case UNEQ_EXPR: 391838fd1498Szrj case LTGT_EXPR: 391938fd1498Szrj 392038fd1498Szrj case CONJ_EXPR: 392138fd1498Szrj 392238fd1498Szrj case PREDECREMENT_EXPR: 392338fd1498Szrj case PREINCREMENT_EXPR: 392438fd1498Szrj case POSTDECREMENT_EXPR: 392538fd1498Szrj case POSTINCREMENT_EXPR: 392638fd1498Szrj 392738fd1498Szrj case REALIGN_LOAD_EXPR: 392838fd1498Szrj 392938fd1498Szrj case WIDEN_SUM_EXPR: 393038fd1498Szrj case WIDEN_MULT_EXPR: 393138fd1498Szrj case DOT_PROD_EXPR: 393238fd1498Szrj case SAD_EXPR: 393338fd1498Szrj case WIDEN_MULT_PLUS_EXPR: 393438fd1498Szrj case WIDEN_MULT_MINUS_EXPR: 393538fd1498Szrj case WIDEN_LSHIFT_EXPR: 393638fd1498Szrj 393738fd1498Szrj case VEC_WIDEN_MULT_HI_EXPR: 393838fd1498Szrj case VEC_WIDEN_MULT_LO_EXPR: 393938fd1498Szrj case VEC_WIDEN_MULT_EVEN_EXPR: 394038fd1498Szrj case VEC_WIDEN_MULT_ODD_EXPR: 394138fd1498Szrj case VEC_UNPACK_HI_EXPR: 394238fd1498Szrj case VEC_UNPACK_LO_EXPR: 394338fd1498Szrj case VEC_UNPACK_FLOAT_HI_EXPR: 394438fd1498Szrj case VEC_UNPACK_FLOAT_LO_EXPR: 394538fd1498Szrj case VEC_PACK_TRUNC_EXPR: 394638fd1498Szrj case VEC_PACK_SAT_EXPR: 394738fd1498Szrj case VEC_PACK_FIX_TRUNC_EXPR: 394838fd1498Szrj case VEC_WIDEN_LSHIFT_HI_EXPR: 394938fd1498Szrj case VEC_WIDEN_LSHIFT_LO_EXPR: 395038fd1498Szrj case VEC_DUPLICATE_EXPR: 395138fd1498Szrj case VEC_SERIES_EXPR: 395238fd1498Szrj 395338fd1498Szrj return 1; 395438fd1498Szrj 395538fd1498Szrj /* Few special cases of expensive operations. This is useful 395638fd1498Szrj to avoid inlining on functions having too many of these. */ 395738fd1498Szrj case TRUNC_DIV_EXPR: 395838fd1498Szrj case CEIL_DIV_EXPR: 395938fd1498Szrj case FLOOR_DIV_EXPR: 396038fd1498Szrj case ROUND_DIV_EXPR: 396138fd1498Szrj case EXACT_DIV_EXPR: 396238fd1498Szrj case TRUNC_MOD_EXPR: 396338fd1498Szrj case CEIL_MOD_EXPR: 396438fd1498Szrj case FLOOR_MOD_EXPR: 396538fd1498Szrj case ROUND_MOD_EXPR: 396638fd1498Szrj case RDIV_EXPR: 396738fd1498Szrj if (TREE_CODE (op2) != INTEGER_CST) 396838fd1498Szrj return weights->div_mod_cost; 396938fd1498Szrj return 1; 397038fd1498Szrj 397138fd1498Szrj /* Bit-field insertion needs several shift and mask operations. */ 397238fd1498Szrj case BIT_INSERT_EXPR: 397338fd1498Szrj return 3; 397438fd1498Szrj 397538fd1498Szrj default: 397638fd1498Szrj /* We expect a copy assignment with no operator. */ 397738fd1498Szrj gcc_assert (get_gimple_rhs_class (code) == GIMPLE_SINGLE_RHS); 397838fd1498Szrj return 0; 397938fd1498Szrj } 398038fd1498Szrj } 398138fd1498Szrj 398238fd1498Szrj 398338fd1498Szrj /* Estimate number of instructions that will be created by expanding 398438fd1498Szrj the statements in the statement sequence STMTS. 398538fd1498Szrj WEIGHTS contains weights attributed to various constructs. */ 398638fd1498Szrj 398738fd1498Szrj int 398838fd1498Szrj estimate_num_insns_seq (gimple_seq stmts, eni_weights *weights) 398938fd1498Szrj { 399038fd1498Szrj int cost; 399138fd1498Szrj gimple_stmt_iterator gsi; 399238fd1498Szrj 399338fd1498Szrj cost = 0; 399438fd1498Szrj for (gsi = gsi_start (stmts); !gsi_end_p (gsi); gsi_next (&gsi)) 399538fd1498Szrj cost += estimate_num_insns (gsi_stmt (gsi), weights); 399638fd1498Szrj 399738fd1498Szrj return cost; 399838fd1498Szrj } 399938fd1498Szrj 400038fd1498Szrj 400138fd1498Szrj /* Estimate number of instructions that will be created by expanding STMT. 400238fd1498Szrj WEIGHTS contains weights attributed to various constructs. */ 400338fd1498Szrj 400438fd1498Szrj int 400538fd1498Szrj estimate_num_insns (gimple *stmt, eni_weights *weights) 400638fd1498Szrj { 400738fd1498Szrj unsigned cost, i; 400838fd1498Szrj enum gimple_code code = gimple_code (stmt); 400938fd1498Szrj tree lhs; 401038fd1498Szrj tree rhs; 401138fd1498Szrj 401238fd1498Szrj switch (code) 401338fd1498Szrj { 401438fd1498Szrj case GIMPLE_ASSIGN: 401538fd1498Szrj /* Try to estimate the cost of assignments. We have three cases to 401638fd1498Szrj deal with: 401738fd1498Szrj 1) Simple assignments to registers; 401838fd1498Szrj 2) Stores to things that must live in memory. This includes 401938fd1498Szrj "normal" stores to scalars, but also assignments of large 402038fd1498Szrj structures, or constructors of big arrays; 402138fd1498Szrj 402238fd1498Szrj Let us look at the first two cases, assuming we have "a = b + C": 402338fd1498Szrj <GIMPLE_ASSIGN <var_decl "a"> 402438fd1498Szrj <plus_expr <var_decl "b"> <constant C>> 402538fd1498Szrj If "a" is a GIMPLE register, the assignment to it is free on almost 402638fd1498Szrj any target, because "a" usually ends up in a real register. Hence 402738fd1498Szrj the only cost of this expression comes from the PLUS_EXPR, and we 402838fd1498Szrj can ignore the GIMPLE_ASSIGN. 402938fd1498Szrj If "a" is not a GIMPLE register, the assignment to "a" will most 403038fd1498Szrj likely be a real store, so the cost of the GIMPLE_ASSIGN is the cost 403138fd1498Szrj of moving something into "a", which we compute using the function 403238fd1498Szrj estimate_move_cost. */ 403338fd1498Szrj if (gimple_clobber_p (stmt)) 403438fd1498Szrj return 0; /* ={v} {CLOBBER} stmt expands to nothing. */ 403538fd1498Szrj 403638fd1498Szrj lhs = gimple_assign_lhs (stmt); 403738fd1498Szrj rhs = gimple_assign_rhs1 (stmt); 403838fd1498Szrj 403938fd1498Szrj cost = 0; 404038fd1498Szrj 404138fd1498Szrj /* Account for the cost of moving to / from memory. */ 404238fd1498Szrj if (gimple_store_p (stmt)) 404338fd1498Szrj cost += estimate_move_cost (TREE_TYPE (lhs), weights->time_based); 404438fd1498Szrj if (gimple_assign_load_p (stmt)) 404538fd1498Szrj cost += estimate_move_cost (TREE_TYPE (rhs), weights->time_based); 404638fd1498Szrj 404738fd1498Szrj cost += estimate_operator_cost (gimple_assign_rhs_code (stmt), weights, 404838fd1498Szrj gimple_assign_rhs1 (stmt), 404938fd1498Szrj get_gimple_rhs_class (gimple_assign_rhs_code (stmt)) 405038fd1498Szrj == GIMPLE_BINARY_RHS 405138fd1498Szrj ? gimple_assign_rhs2 (stmt) : NULL); 405238fd1498Szrj break; 405338fd1498Szrj 405438fd1498Szrj case GIMPLE_COND: 405538fd1498Szrj cost = 1 + estimate_operator_cost (gimple_cond_code (stmt), weights, 405638fd1498Szrj gimple_op (stmt, 0), 405738fd1498Szrj gimple_op (stmt, 1)); 405838fd1498Szrj break; 405938fd1498Szrj 406038fd1498Szrj case GIMPLE_SWITCH: 406138fd1498Szrj { 406238fd1498Szrj gswitch *switch_stmt = as_a <gswitch *> (stmt); 406338fd1498Szrj /* Take into account cost of the switch + guess 2 conditional jumps for 406438fd1498Szrj each case label. 406538fd1498Szrj 406638fd1498Szrj TODO: once the switch expansion logic is sufficiently separated, we can 406738fd1498Szrj do better job on estimating cost of the switch. */ 406838fd1498Szrj if (weights->time_based) 406938fd1498Szrj cost = floor_log2 (gimple_switch_num_labels (switch_stmt)) * 2; 407038fd1498Szrj else 407138fd1498Szrj cost = gimple_switch_num_labels (switch_stmt) * 2; 407238fd1498Szrj } 407338fd1498Szrj break; 407438fd1498Szrj 407538fd1498Szrj case GIMPLE_CALL: 407638fd1498Szrj { 407738fd1498Szrj tree decl; 407838fd1498Szrj 407938fd1498Szrj if (gimple_call_internal_p (stmt)) 408038fd1498Szrj return 0; 408138fd1498Szrj else if ((decl = gimple_call_fndecl (stmt)) 408238fd1498Szrj && DECL_BUILT_IN (decl)) 408338fd1498Szrj { 408438fd1498Szrj /* Do not special case builtins where we see the body. 408538fd1498Szrj This just confuse inliner. */ 408638fd1498Szrj struct cgraph_node *node; 408738fd1498Szrj if (!(node = cgraph_node::get (decl)) 408838fd1498Szrj || node->definition) 408938fd1498Szrj ; 409038fd1498Szrj /* For buitins that are likely expanded to nothing or 409138fd1498Szrj inlined do not account operand costs. */ 409238fd1498Szrj else if (is_simple_builtin (decl)) 409338fd1498Szrj return 0; 409438fd1498Szrj else if (is_inexpensive_builtin (decl)) 409538fd1498Szrj return weights->target_builtin_call_cost; 409638fd1498Szrj else if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)) 409738fd1498Szrj { 409838fd1498Szrj /* We canonicalize x * x to pow (x, 2.0) with -ffast-math, so 409938fd1498Szrj specialize the cheap expansion we do here. 410038fd1498Szrj ??? This asks for a more general solution. */ 410138fd1498Szrj switch (DECL_FUNCTION_CODE (decl)) 410238fd1498Szrj { 410338fd1498Szrj case BUILT_IN_POW: 410438fd1498Szrj case BUILT_IN_POWF: 410538fd1498Szrj case BUILT_IN_POWL: 410638fd1498Szrj if (TREE_CODE (gimple_call_arg (stmt, 1)) == REAL_CST 410738fd1498Szrj && (real_equal 410838fd1498Szrj (&TREE_REAL_CST (gimple_call_arg (stmt, 1)), 410938fd1498Szrj &dconst2))) 411038fd1498Szrj return estimate_operator_cost 411138fd1498Szrj (MULT_EXPR, weights, gimple_call_arg (stmt, 0), 411238fd1498Szrj gimple_call_arg (stmt, 0)); 411338fd1498Szrj break; 411438fd1498Szrj 411538fd1498Szrj default: 411638fd1498Szrj break; 411738fd1498Szrj } 411838fd1498Szrj } 411938fd1498Szrj } 412038fd1498Szrj 412138fd1498Szrj cost = decl ? weights->call_cost : weights->indirect_call_cost; 412238fd1498Szrj if (gimple_call_lhs (stmt)) 412338fd1498Szrj cost += estimate_move_cost (TREE_TYPE (gimple_call_lhs (stmt)), 412438fd1498Szrj weights->time_based); 412538fd1498Szrj for (i = 0; i < gimple_call_num_args (stmt); i++) 412638fd1498Szrj { 412738fd1498Szrj tree arg = gimple_call_arg (stmt, i); 412838fd1498Szrj cost += estimate_move_cost (TREE_TYPE (arg), 412938fd1498Szrj weights->time_based); 413038fd1498Szrj } 413138fd1498Szrj break; 413238fd1498Szrj } 413338fd1498Szrj 413438fd1498Szrj case GIMPLE_RETURN: 413538fd1498Szrj return weights->return_cost; 413638fd1498Szrj 413738fd1498Szrj case GIMPLE_GOTO: 413838fd1498Szrj case GIMPLE_LABEL: 413938fd1498Szrj case GIMPLE_NOP: 414038fd1498Szrj case GIMPLE_PHI: 414138fd1498Szrj case GIMPLE_PREDICT: 414238fd1498Szrj case GIMPLE_DEBUG: 414338fd1498Szrj return 0; 414438fd1498Szrj 414538fd1498Szrj case GIMPLE_ASM: 414638fd1498Szrj { 414738fd1498Szrj int count = asm_str_count (gimple_asm_string (as_a <gasm *> (stmt))); 414838fd1498Szrj /* 1000 means infinity. This avoids overflows later 414938fd1498Szrj with very long asm statements. */ 415038fd1498Szrj if (count > 1000) 415138fd1498Szrj count = 1000; 4152*58e805e6Szrj /* If this asm is asm inline, count anything as minimum size. */ 4153*58e805e6Szrj if (gimple_asm_inline_p (as_a <gasm *> (stmt))) 4154*58e805e6Szrj count = MIN (1, count); 415538fd1498Szrj return MAX (1, count); 415638fd1498Szrj } 415738fd1498Szrj 415838fd1498Szrj case GIMPLE_RESX: 415938fd1498Szrj /* This is either going to be an external function call with one 416038fd1498Szrj argument, or two register copy statements plus a goto. */ 416138fd1498Szrj return 2; 416238fd1498Szrj 416338fd1498Szrj case GIMPLE_EH_DISPATCH: 416438fd1498Szrj /* ??? This is going to turn into a switch statement. Ideally 416538fd1498Szrj we'd have a look at the eh region and estimate the number of 416638fd1498Szrj edges involved. */ 416738fd1498Szrj return 10; 416838fd1498Szrj 416938fd1498Szrj case GIMPLE_BIND: 417038fd1498Szrj return estimate_num_insns_seq ( 417138fd1498Szrj gimple_bind_body (as_a <gbind *> (stmt)), 417238fd1498Szrj weights); 417338fd1498Szrj 417438fd1498Szrj case GIMPLE_EH_FILTER: 417538fd1498Szrj return estimate_num_insns_seq (gimple_eh_filter_failure (stmt), weights); 417638fd1498Szrj 417738fd1498Szrj case GIMPLE_CATCH: 417838fd1498Szrj return estimate_num_insns_seq (gimple_catch_handler ( 417938fd1498Szrj as_a <gcatch *> (stmt)), 418038fd1498Szrj weights); 418138fd1498Szrj 418238fd1498Szrj case GIMPLE_TRY: 418338fd1498Szrj return (estimate_num_insns_seq (gimple_try_eval (stmt), weights) 418438fd1498Szrj + estimate_num_insns_seq (gimple_try_cleanup (stmt), weights)); 418538fd1498Szrj 418638fd1498Szrj /* OMP directives are generally very expensive. */ 418738fd1498Szrj 418838fd1498Szrj case GIMPLE_OMP_RETURN: 418938fd1498Szrj case GIMPLE_OMP_SECTIONS_SWITCH: 419038fd1498Szrj case GIMPLE_OMP_ATOMIC_STORE: 419138fd1498Szrj case GIMPLE_OMP_CONTINUE: 419238fd1498Szrj /* ...except these, which are cheap. */ 419338fd1498Szrj return 0; 419438fd1498Szrj 419538fd1498Szrj case GIMPLE_OMP_ATOMIC_LOAD: 419638fd1498Szrj return weights->omp_cost; 419738fd1498Szrj 419838fd1498Szrj case GIMPLE_OMP_FOR: 419938fd1498Szrj return (weights->omp_cost 420038fd1498Szrj + estimate_num_insns_seq (gimple_omp_body (stmt), weights) 420138fd1498Szrj + estimate_num_insns_seq (gimple_omp_for_pre_body (stmt), weights)); 420238fd1498Szrj 420338fd1498Szrj case GIMPLE_OMP_PARALLEL: 420438fd1498Szrj case GIMPLE_OMP_TASK: 420538fd1498Szrj case GIMPLE_OMP_CRITICAL: 420638fd1498Szrj case GIMPLE_OMP_MASTER: 420738fd1498Szrj case GIMPLE_OMP_TASKGROUP: 420838fd1498Szrj case GIMPLE_OMP_ORDERED: 420938fd1498Szrj case GIMPLE_OMP_SECTION: 421038fd1498Szrj case GIMPLE_OMP_SECTIONS: 421138fd1498Szrj case GIMPLE_OMP_SINGLE: 421238fd1498Szrj case GIMPLE_OMP_TARGET: 421338fd1498Szrj case GIMPLE_OMP_TEAMS: 421438fd1498Szrj return (weights->omp_cost 421538fd1498Szrj + estimate_num_insns_seq (gimple_omp_body (stmt), weights)); 421638fd1498Szrj 421738fd1498Szrj case GIMPLE_TRANSACTION: 421838fd1498Szrj return (weights->tm_cost 421938fd1498Szrj + estimate_num_insns_seq (gimple_transaction_body ( 422038fd1498Szrj as_a <gtransaction *> (stmt)), 422138fd1498Szrj weights)); 422238fd1498Szrj 422338fd1498Szrj default: 422438fd1498Szrj gcc_unreachable (); 422538fd1498Szrj } 422638fd1498Szrj 422738fd1498Szrj return cost; 422838fd1498Szrj } 422938fd1498Szrj 423038fd1498Szrj /* Estimate number of instructions that will be created by expanding 423138fd1498Szrj function FNDECL. WEIGHTS contains weights attributed to various 423238fd1498Szrj constructs. */ 423338fd1498Szrj 423438fd1498Szrj int 423538fd1498Szrj estimate_num_insns_fn (tree fndecl, eni_weights *weights) 423638fd1498Szrj { 423738fd1498Szrj struct function *my_function = DECL_STRUCT_FUNCTION (fndecl); 423838fd1498Szrj gimple_stmt_iterator bsi; 423938fd1498Szrj basic_block bb; 424038fd1498Szrj int n = 0; 424138fd1498Szrj 424238fd1498Szrj gcc_assert (my_function && my_function->cfg); 424338fd1498Szrj FOR_EACH_BB_FN (bb, my_function) 424438fd1498Szrj { 424538fd1498Szrj for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) 424638fd1498Szrj n += estimate_num_insns (gsi_stmt (bsi), weights); 424738fd1498Szrj } 424838fd1498Szrj 424938fd1498Szrj return n; 425038fd1498Szrj } 425138fd1498Szrj 425238fd1498Szrj 425338fd1498Szrj /* Initializes weights used by estimate_num_insns. */ 425438fd1498Szrj 425538fd1498Szrj void 425638fd1498Szrj init_inline_once (void) 425738fd1498Szrj { 425838fd1498Szrj eni_size_weights.call_cost = 1; 425938fd1498Szrj eni_size_weights.indirect_call_cost = 3; 426038fd1498Szrj eni_size_weights.target_builtin_call_cost = 1; 426138fd1498Szrj eni_size_weights.div_mod_cost = 1; 426238fd1498Szrj eni_size_weights.omp_cost = 40; 426338fd1498Szrj eni_size_weights.tm_cost = 10; 426438fd1498Szrj eni_size_weights.time_based = false; 426538fd1498Szrj eni_size_weights.return_cost = 1; 426638fd1498Szrj 426738fd1498Szrj /* Estimating time for call is difficult, since we have no idea what the 426838fd1498Szrj called function does. In the current uses of eni_time_weights, 426938fd1498Szrj underestimating the cost does less harm than overestimating it, so 427038fd1498Szrj we choose a rather small value here. */ 427138fd1498Szrj eni_time_weights.call_cost = 10; 427238fd1498Szrj eni_time_weights.indirect_call_cost = 15; 427338fd1498Szrj eni_time_weights.target_builtin_call_cost = 1; 427438fd1498Szrj eni_time_weights.div_mod_cost = 10; 427538fd1498Szrj eni_time_weights.omp_cost = 40; 427638fd1498Szrj eni_time_weights.tm_cost = 40; 427738fd1498Szrj eni_time_weights.time_based = true; 427838fd1498Szrj eni_time_weights.return_cost = 2; 427938fd1498Szrj } 428038fd1498Szrj 428138fd1498Szrj 428238fd1498Szrj /* Install new lexical TREE_BLOCK underneath 'current_block'. */ 428338fd1498Szrj 428438fd1498Szrj static void 428538fd1498Szrj prepend_lexical_block (tree current_block, tree new_block) 428638fd1498Szrj { 428738fd1498Szrj BLOCK_CHAIN (new_block) = BLOCK_SUBBLOCKS (current_block); 428838fd1498Szrj BLOCK_SUBBLOCKS (current_block) = new_block; 428938fd1498Szrj BLOCK_SUPERCONTEXT (new_block) = current_block; 429038fd1498Szrj } 429138fd1498Szrj 429238fd1498Szrj /* Add local variables from CALLEE to CALLER. */ 429338fd1498Szrj 429438fd1498Szrj static inline void 429538fd1498Szrj add_local_variables (struct function *callee, struct function *caller, 429638fd1498Szrj copy_body_data *id) 429738fd1498Szrj { 429838fd1498Szrj tree var; 429938fd1498Szrj unsigned ix; 430038fd1498Szrj 430138fd1498Szrj FOR_EACH_LOCAL_DECL (callee, ix, var) 430238fd1498Szrj if (!can_be_nonlocal (var, id)) 430338fd1498Szrj { 430438fd1498Szrj tree new_var = remap_decl (var, id); 430538fd1498Szrj 430638fd1498Szrj /* Remap debug-expressions. */ 430738fd1498Szrj if (VAR_P (new_var) 430838fd1498Szrj && DECL_HAS_DEBUG_EXPR_P (var) 430938fd1498Szrj && new_var != var) 431038fd1498Szrj { 431138fd1498Szrj tree tem = DECL_DEBUG_EXPR (var); 431238fd1498Szrj bool old_regimplify = id->regimplify; 431338fd1498Szrj id->remapping_type_depth++; 431438fd1498Szrj walk_tree (&tem, copy_tree_body_r, id, NULL); 431538fd1498Szrj id->remapping_type_depth--; 431638fd1498Szrj id->regimplify = old_regimplify; 431738fd1498Szrj SET_DECL_DEBUG_EXPR (new_var, tem); 431838fd1498Szrj DECL_HAS_DEBUG_EXPR_P (new_var) = 1; 431938fd1498Szrj } 432038fd1498Szrj add_local_decl (caller, new_var); 432138fd1498Szrj } 432238fd1498Szrj } 432338fd1498Szrj 432438fd1498Szrj /* Add to BINDINGS a debug stmt resetting SRCVAR if inlining might 432538fd1498Szrj have brought in or introduced any debug stmts for SRCVAR. */ 432638fd1498Szrj 432738fd1498Szrj static inline void 432838fd1498Szrj reset_debug_binding (copy_body_data *id, tree srcvar, gimple_seq *bindings) 432938fd1498Szrj { 433038fd1498Szrj tree *remappedvarp = id->decl_map->get (srcvar); 433138fd1498Szrj 433238fd1498Szrj if (!remappedvarp) 433338fd1498Szrj return; 433438fd1498Szrj 433538fd1498Szrj if (!VAR_P (*remappedvarp)) 433638fd1498Szrj return; 433738fd1498Szrj 433838fd1498Szrj if (*remappedvarp == id->retvar || *remappedvarp == id->retbnd) 433938fd1498Szrj return; 434038fd1498Szrj 434138fd1498Szrj tree tvar = target_for_debug_bind (*remappedvarp); 434238fd1498Szrj if (!tvar) 434338fd1498Szrj return; 434438fd1498Szrj 434538fd1498Szrj gdebug *stmt = gimple_build_debug_bind (tvar, NULL_TREE, 434638fd1498Szrj id->call_stmt); 434738fd1498Szrj gimple_seq_add_stmt (bindings, stmt); 434838fd1498Szrj } 434938fd1498Szrj 435038fd1498Szrj /* For each inlined variable for which we may have debug bind stmts, 435138fd1498Szrj add before GSI a final debug stmt resetting it, marking the end of 435238fd1498Szrj its life, so that var-tracking knows it doesn't have to compute 435338fd1498Szrj further locations for it. */ 435438fd1498Szrj 435538fd1498Szrj static inline void 435638fd1498Szrj reset_debug_bindings (copy_body_data *id, gimple_stmt_iterator gsi) 435738fd1498Szrj { 435838fd1498Szrj tree var; 435938fd1498Szrj unsigned ix; 436038fd1498Szrj gimple_seq bindings = NULL; 436138fd1498Szrj 436238fd1498Szrj if (!gimple_in_ssa_p (id->src_cfun)) 436338fd1498Szrj return; 436438fd1498Szrj 436538fd1498Szrj if (!opt_for_fn (id->dst_fn, flag_var_tracking_assignments)) 436638fd1498Szrj return; 436738fd1498Szrj 436838fd1498Szrj for (var = DECL_ARGUMENTS (id->src_fn); 436938fd1498Szrj var; var = DECL_CHAIN (var)) 437038fd1498Szrj reset_debug_binding (id, var, &bindings); 437138fd1498Szrj 437238fd1498Szrj FOR_EACH_LOCAL_DECL (id->src_cfun, ix, var) 437338fd1498Szrj reset_debug_binding (id, var, &bindings); 437438fd1498Szrj 437538fd1498Szrj gsi_insert_seq_before_without_update (&gsi, bindings, GSI_SAME_STMT); 437638fd1498Szrj } 437738fd1498Szrj 437838fd1498Szrj /* If STMT is a GIMPLE_CALL, replace it with its inline expansion. */ 437938fd1498Szrj 438038fd1498Szrj static bool 438138fd1498Szrj expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id) 438238fd1498Szrj { 438338fd1498Szrj tree use_retvar; 438438fd1498Szrj tree fn; 438538fd1498Szrj hash_map<tree, tree> *dst; 438638fd1498Szrj hash_map<tree, tree> *st = NULL; 438738fd1498Szrj tree return_slot; 438838fd1498Szrj tree modify_dest; 438938fd1498Szrj tree return_bounds = NULL; 439038fd1498Szrj struct cgraph_edge *cg_edge; 439138fd1498Szrj cgraph_inline_failed_t reason; 439238fd1498Szrj basic_block return_block; 439338fd1498Szrj edge e; 439438fd1498Szrj gimple_stmt_iterator gsi, stmt_gsi; 439538fd1498Szrj bool successfully_inlined = false; 439638fd1498Szrj bool purge_dead_abnormal_edges; 439738fd1498Szrj gcall *call_stmt; 439838fd1498Szrj unsigned int i; 439938fd1498Szrj unsigned int prop_mask, src_properties; 440038fd1498Szrj struct function *dst_cfun; 440138fd1498Szrj tree simduid; 440238fd1498Szrj use_operand_p use; 440338fd1498Szrj gimple *simtenter_stmt = NULL; 440438fd1498Szrj vec<tree> *simtvars_save; 440538fd1498Szrj 440638fd1498Szrj /* The gimplifier uses input_location in too many places, such as 440738fd1498Szrj internal_get_tmp_var (). */ 440838fd1498Szrj location_t saved_location = input_location; 440938fd1498Szrj input_location = gimple_location (stmt); 441038fd1498Szrj 441138fd1498Szrj /* From here on, we're only interested in CALL_EXPRs. */ 441238fd1498Szrj call_stmt = dyn_cast <gcall *> (stmt); 441338fd1498Szrj if (!call_stmt) 441438fd1498Szrj goto egress; 441538fd1498Szrj 441638fd1498Szrj cg_edge = id->dst_node->get_edge (stmt); 441738fd1498Szrj gcc_checking_assert (cg_edge); 441838fd1498Szrj /* First, see if we can figure out what function is being called. 441938fd1498Szrj If we cannot, then there is no hope of inlining the function. */ 442038fd1498Szrj if (cg_edge->indirect_unknown_callee) 442138fd1498Szrj goto egress; 442238fd1498Szrj fn = cg_edge->callee->decl; 442338fd1498Szrj gcc_checking_assert (fn); 442438fd1498Szrj 442538fd1498Szrj /* If FN is a declaration of a function in a nested scope that was 442638fd1498Szrj globally declared inline, we don't set its DECL_INITIAL. 442738fd1498Szrj However, we can't blindly follow DECL_ABSTRACT_ORIGIN because the 442838fd1498Szrj C++ front-end uses it for cdtors to refer to their internal 442938fd1498Szrj declarations, that are not real functions. Fortunately those 443038fd1498Szrj don't have trees to be saved, so we can tell by checking their 443138fd1498Szrj gimple_body. */ 443238fd1498Szrj if (!DECL_INITIAL (fn) 443338fd1498Szrj && DECL_ABSTRACT_ORIGIN (fn) 443438fd1498Szrj && gimple_has_body_p (DECL_ABSTRACT_ORIGIN (fn))) 443538fd1498Szrj fn = DECL_ABSTRACT_ORIGIN (fn); 443638fd1498Szrj 443738fd1498Szrj /* Don't try to inline functions that are not well-suited to inlining. */ 443838fd1498Szrj if (cg_edge->inline_failed) 443938fd1498Szrj { 444038fd1498Szrj reason = cg_edge->inline_failed; 444138fd1498Szrj /* If this call was originally indirect, we do not want to emit any 444238fd1498Szrj inlining related warnings or sorry messages because there are no 444338fd1498Szrj guarantees regarding those. */ 444438fd1498Szrj if (cg_edge->indirect_inlining_edge) 444538fd1498Szrj goto egress; 444638fd1498Szrj 444738fd1498Szrj if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) 444838fd1498Szrj /* For extern inline functions that get redefined we always 444938fd1498Szrj silently ignored always_inline flag. Better behavior would 445038fd1498Szrj be to be able to keep both bodies and use extern inline body 445138fd1498Szrj for inlining, but we can't do that because frontends overwrite 445238fd1498Szrj the body. */ 445338fd1498Szrj && !cg_edge->callee->local.redefined_extern_inline 445438fd1498Szrj /* During early inline pass, report only when optimization is 445538fd1498Szrj not turned on. */ 445638fd1498Szrj && (symtab->global_info_ready 445738fd1498Szrj || !optimize 445838fd1498Szrj || cgraph_inline_failed_type (reason) == CIF_FINAL_ERROR) 445938fd1498Szrj /* PR 20090218-1_0.c. Body can be provided by another module. */ 446038fd1498Szrj && (reason != CIF_BODY_NOT_AVAILABLE || !flag_generate_lto)) 446138fd1498Szrj { 446238fd1498Szrj error ("inlining failed in call to always_inline %q+F: %s", fn, 446338fd1498Szrj cgraph_inline_failed_string (reason)); 446438fd1498Szrj if (gimple_location (stmt) != UNKNOWN_LOCATION) 446538fd1498Szrj inform (gimple_location (stmt), "called from here"); 446638fd1498Szrj else if (DECL_SOURCE_LOCATION (cfun->decl) != UNKNOWN_LOCATION) 446738fd1498Szrj inform (DECL_SOURCE_LOCATION (cfun->decl), 446838fd1498Szrj "called from this function"); 446938fd1498Szrj } 447038fd1498Szrj else if (warn_inline 447138fd1498Szrj && DECL_DECLARED_INLINE_P (fn) 447238fd1498Szrj && !DECL_NO_INLINE_WARNING_P (fn) 447338fd1498Szrj && !DECL_IN_SYSTEM_HEADER (fn) 447438fd1498Szrj && reason != CIF_UNSPECIFIED 447538fd1498Szrj && !lookup_attribute ("noinline", DECL_ATTRIBUTES (fn)) 447638fd1498Szrj /* Do not warn about not inlined recursive calls. */ 447738fd1498Szrj && !cg_edge->recursive_p () 447838fd1498Szrj /* Avoid warnings during early inline pass. */ 447938fd1498Szrj && symtab->global_info_ready) 448038fd1498Szrj { 448138fd1498Szrj if (warning (OPT_Winline, "inlining failed in call to %q+F: %s", 448238fd1498Szrj fn, _(cgraph_inline_failed_string (reason)))) 448338fd1498Szrj { 448438fd1498Szrj if (gimple_location (stmt) != UNKNOWN_LOCATION) 448538fd1498Szrj inform (gimple_location (stmt), "called from here"); 448638fd1498Szrj else if (DECL_SOURCE_LOCATION (cfun->decl) != UNKNOWN_LOCATION) 448738fd1498Szrj inform (DECL_SOURCE_LOCATION (cfun->decl), 448838fd1498Szrj "called from this function"); 448938fd1498Szrj } 449038fd1498Szrj } 449138fd1498Szrj goto egress; 449238fd1498Szrj } 449338fd1498Szrj id->src_node = cg_edge->callee; 449438fd1498Szrj 449538fd1498Szrj /* If callee is thunk, all we need is to adjust the THIS pointer 449638fd1498Szrj and redirect to function being thunked. */ 449738fd1498Szrj if (id->src_node->thunk.thunk_p) 449838fd1498Szrj { 449938fd1498Szrj cgraph_edge *edge; 450038fd1498Szrj tree virtual_offset = NULL; 450138fd1498Szrj profile_count count = cg_edge->count; 450238fd1498Szrj tree op; 450338fd1498Szrj gimple_stmt_iterator iter = gsi_for_stmt (stmt); 450438fd1498Szrj 450538fd1498Szrj cg_edge->remove (); 450638fd1498Szrj edge = id->src_node->callees->clone (id->dst_node, call_stmt, 450738fd1498Szrj gimple_uid (stmt), 450838fd1498Szrj profile_count::one (), 450938fd1498Szrj profile_count::one (), 451038fd1498Szrj true); 451138fd1498Szrj edge->count = count; 451238fd1498Szrj if (id->src_node->thunk.virtual_offset_p) 451338fd1498Szrj virtual_offset = size_int (id->src_node->thunk.virtual_value); 451438fd1498Szrj op = create_tmp_reg_fn (cfun, TREE_TYPE (gimple_call_arg (stmt, 0)), 451538fd1498Szrj NULL); 451638fd1498Szrj gsi_insert_before (&iter, gimple_build_assign (op, 451738fd1498Szrj gimple_call_arg (stmt, 0)), 451838fd1498Szrj GSI_NEW_STMT); 451938fd1498Szrj gcc_assert (id->src_node->thunk.this_adjusting); 452038fd1498Szrj op = thunk_adjust (&iter, op, 1, id->src_node->thunk.fixed_offset, 452138fd1498Szrj virtual_offset); 452238fd1498Szrj 452338fd1498Szrj gimple_call_set_arg (stmt, 0, op); 452438fd1498Szrj gimple_call_set_fndecl (stmt, edge->callee->decl); 452538fd1498Szrj update_stmt (stmt); 452638fd1498Szrj id->src_node->remove (); 452738fd1498Szrj expand_call_inline (bb, stmt, id); 452838fd1498Szrj maybe_remove_unused_call_args (cfun, stmt); 452938fd1498Szrj return true; 453038fd1498Szrj } 453138fd1498Szrj fn = cg_edge->callee->decl; 453238fd1498Szrj cg_edge->callee->get_untransformed_body (); 453338fd1498Szrj 453438fd1498Szrj if (flag_checking && cg_edge->callee->decl != id->dst_node->decl) 453538fd1498Szrj cg_edge->callee->verify (); 453638fd1498Szrj 453738fd1498Szrj /* We will be inlining this callee. */ 453838fd1498Szrj id->eh_lp_nr = lookup_stmt_eh_lp (stmt); 453938fd1498Szrj id->assign_stmts.create (0); 454038fd1498Szrj 454138fd1498Szrj /* Update the callers EH personality. */ 454238fd1498Szrj if (DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl)) 454338fd1498Szrj DECL_FUNCTION_PERSONALITY (cg_edge->caller->decl) 454438fd1498Szrj = DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl); 454538fd1498Szrj 454638fd1498Szrj /* Split the block before the GIMPLE_CALL. */ 454738fd1498Szrj stmt_gsi = gsi_for_stmt (stmt); 454838fd1498Szrj gsi_prev (&stmt_gsi); 454938fd1498Szrj e = split_block (bb, gsi_end_p (stmt_gsi) ? NULL : gsi_stmt (stmt_gsi)); 455038fd1498Szrj bb = e->src; 455138fd1498Szrj return_block = e->dest; 455238fd1498Szrj remove_edge (e); 455338fd1498Szrj 455438fd1498Szrj /* If the GIMPLE_CALL was in the last statement of BB, it may have 455538fd1498Szrj been the source of abnormal edges. In this case, schedule 455638fd1498Szrj the removal of dead abnormal edges. */ 455738fd1498Szrj gsi = gsi_start_bb (return_block); 455838fd1498Szrj gsi_next (&gsi); 455938fd1498Szrj purge_dead_abnormal_edges = gsi_end_p (gsi); 456038fd1498Szrj 456138fd1498Szrj stmt_gsi = gsi_start_bb (return_block); 456238fd1498Szrj 456338fd1498Szrj /* Build a block containing code to initialize the arguments, the 456438fd1498Szrj actual inline expansion of the body, and a label for the return 456538fd1498Szrj statements within the function to jump to. The type of the 456638fd1498Szrj statement expression is the return type of the function call. 456738fd1498Szrj ??? If the call does not have an associated block then we will 456838fd1498Szrj remap all callee blocks to NULL, effectively dropping most of 456938fd1498Szrj its debug information. This should only happen for calls to 457038fd1498Szrj artificial decls inserted by the compiler itself. We need to 457138fd1498Szrj either link the inlined blocks into the caller block tree or 457238fd1498Szrj not refer to them in any way to not break GC for locations. */ 457338fd1498Szrj if (gimple_block (stmt)) 457438fd1498Szrj { 4575*58e805e6Szrj /* We do want to assign a not UNKNOWN_LOCATION BLOCK_SOURCE_LOCATION 4576*58e805e6Szrj to make inlined_function_outer_scope_p return true on this BLOCK. */ 4577*58e805e6Szrj location_t loc = LOCATION_LOCUS (gimple_location (stmt)); 4578*58e805e6Szrj if (loc == UNKNOWN_LOCATION) 4579*58e805e6Szrj loc = LOCATION_LOCUS (DECL_SOURCE_LOCATION (fn)); 4580*58e805e6Szrj if (loc == UNKNOWN_LOCATION) 4581*58e805e6Szrj loc = BUILTINS_LOCATION; 458238fd1498Szrj id->block = make_node (BLOCK); 458338fd1498Szrj BLOCK_ABSTRACT_ORIGIN (id->block) = fn; 4584*58e805e6Szrj BLOCK_SOURCE_LOCATION (id->block) = loc; 458538fd1498Szrj prepend_lexical_block (gimple_block (stmt), id->block); 458638fd1498Szrj } 458738fd1498Szrj 458838fd1498Szrj /* Local declarations will be replaced by their equivalents in this 458938fd1498Szrj map. */ 459038fd1498Szrj st = id->decl_map; 459138fd1498Szrj id->decl_map = new hash_map<tree, tree>; 459238fd1498Szrj dst = id->debug_map; 459338fd1498Szrj id->debug_map = NULL; 459438fd1498Szrj 459538fd1498Szrj /* Record the function we are about to inline. */ 459638fd1498Szrj id->src_fn = fn; 459738fd1498Szrj id->src_cfun = DECL_STRUCT_FUNCTION (fn); 459838fd1498Szrj id->call_stmt = call_stmt; 459938fd1498Szrj 460038fd1498Szrj /* When inlining into an OpenMP SIMD-on-SIMT loop, arrange for new automatic 460138fd1498Szrj variables to be added to IFN_GOMP_SIMT_ENTER argument list. */ 460238fd1498Szrj dst_cfun = DECL_STRUCT_FUNCTION (id->dst_fn); 460338fd1498Szrj simtvars_save = id->dst_simt_vars; 460438fd1498Szrj if (!(dst_cfun->curr_properties & PROP_gimple_lomp_dev) 460538fd1498Szrj && (simduid = bb->loop_father->simduid) != NULL_TREE 460638fd1498Szrj && (simduid = ssa_default_def (dst_cfun, simduid)) != NULL_TREE 460738fd1498Szrj && single_imm_use (simduid, &use, &simtenter_stmt) 460838fd1498Szrj && is_gimple_call (simtenter_stmt) 460938fd1498Szrj && gimple_call_internal_p (simtenter_stmt, IFN_GOMP_SIMT_ENTER)) 461038fd1498Szrj vec_alloc (id->dst_simt_vars, 0); 461138fd1498Szrj else 461238fd1498Szrj id->dst_simt_vars = NULL; 461338fd1498Szrj 461438fd1498Szrj if (profile_status_for_fn (id->src_cfun) == PROFILE_ABSENT) 461538fd1498Szrj profile_status_for_fn (dst_cfun) = PROFILE_ABSENT; 461638fd1498Szrj 461738fd1498Szrj /* If the src function contains an IFN_VA_ARG, then so will the dst 461838fd1498Szrj function after inlining. Likewise for IFN_GOMP_USE_SIMT. */ 461938fd1498Szrj prop_mask = PROP_gimple_lva | PROP_gimple_lomp_dev; 462038fd1498Szrj src_properties = id->src_cfun->curr_properties & prop_mask; 462138fd1498Szrj if (src_properties != prop_mask) 462238fd1498Szrj dst_cfun->curr_properties &= src_properties | ~prop_mask; 462338fd1498Szrj 462438fd1498Szrj gcc_assert (!id->src_cfun->after_inlining); 462538fd1498Szrj 462638fd1498Szrj id->entry_bb = bb; 462738fd1498Szrj if (lookup_attribute ("cold", DECL_ATTRIBUTES (fn))) 462838fd1498Szrj { 462938fd1498Szrj gimple_stmt_iterator si = gsi_last_bb (bb); 463038fd1498Szrj gsi_insert_after (&si, gimple_build_predict (PRED_COLD_FUNCTION, 463138fd1498Szrj NOT_TAKEN), 463238fd1498Szrj GSI_NEW_STMT); 463338fd1498Szrj } 463438fd1498Szrj initialize_inlined_parameters (id, stmt, fn, bb); 463538fd1498Szrj if (debug_nonbind_markers_p && debug_inline_points && id->block 463638fd1498Szrj && inlined_function_outer_scope_p (id->block)) 463738fd1498Szrj { 463838fd1498Szrj gimple_stmt_iterator si = gsi_last_bb (bb); 463938fd1498Szrj gsi_insert_after (&si, gimple_build_debug_inline_entry 464038fd1498Szrj (id->block, input_location), GSI_NEW_STMT); 464138fd1498Szrj } 464238fd1498Szrj 464338fd1498Szrj if (DECL_INITIAL (fn)) 464438fd1498Szrj { 464538fd1498Szrj if (gimple_block (stmt)) 464638fd1498Szrj { 464738fd1498Szrj tree *var; 464838fd1498Szrj 464938fd1498Szrj prepend_lexical_block (id->block, 465038fd1498Szrj remap_blocks (DECL_INITIAL (fn), id)); 465138fd1498Szrj gcc_checking_assert (BLOCK_SUBBLOCKS (id->block) 465238fd1498Szrj && (BLOCK_CHAIN (BLOCK_SUBBLOCKS (id->block)) 465338fd1498Szrj == NULL_TREE)); 465438fd1498Szrj /* Move vars for PARM_DECLs from DECL_INITIAL block to id->block, 465538fd1498Szrj otherwise for DWARF DW_TAG_formal_parameter will not be children of 465638fd1498Szrj DW_TAG_inlined_subroutine, but of a DW_TAG_lexical_block 465738fd1498Szrj under it. The parameters can be then evaluated in the debugger, 465838fd1498Szrj but don't show in backtraces. */ 465938fd1498Szrj for (var = &BLOCK_VARS (BLOCK_SUBBLOCKS (id->block)); *var; ) 466038fd1498Szrj if (TREE_CODE (DECL_ORIGIN (*var)) == PARM_DECL) 466138fd1498Szrj { 466238fd1498Szrj tree v = *var; 466338fd1498Szrj *var = TREE_CHAIN (v); 466438fd1498Szrj TREE_CHAIN (v) = BLOCK_VARS (id->block); 466538fd1498Szrj BLOCK_VARS (id->block) = v; 466638fd1498Szrj } 466738fd1498Szrj else 466838fd1498Szrj var = &TREE_CHAIN (*var); 466938fd1498Szrj } 467038fd1498Szrj else 467138fd1498Szrj remap_blocks_to_null (DECL_INITIAL (fn), id); 467238fd1498Szrj } 467338fd1498Szrj 467438fd1498Szrj /* Return statements in the function body will be replaced by jumps 467538fd1498Szrj to the RET_LABEL. */ 467638fd1498Szrj gcc_assert (DECL_INITIAL (fn)); 467738fd1498Szrj gcc_assert (TREE_CODE (DECL_INITIAL (fn)) == BLOCK); 467838fd1498Szrj 467938fd1498Szrj /* Find the LHS to which the result of this call is assigned. */ 468038fd1498Szrj return_slot = NULL; 468138fd1498Szrj if (gimple_call_lhs (stmt)) 468238fd1498Szrj { 468338fd1498Szrj modify_dest = gimple_call_lhs (stmt); 468438fd1498Szrj 468538fd1498Szrj /* Remember where to copy returned bounds. */ 468638fd1498Szrj if (gimple_call_with_bounds_p (stmt) 468738fd1498Szrj && TREE_CODE (modify_dest) == SSA_NAME) 468838fd1498Szrj { 468938fd1498Szrj gcall *retbnd = chkp_retbnd_call_by_val (modify_dest); 469038fd1498Szrj if (retbnd) 469138fd1498Szrj { 469238fd1498Szrj return_bounds = gimple_call_lhs (retbnd); 469338fd1498Szrj /* If returned bounds are not used then just 469438fd1498Szrj remove unused call. */ 469538fd1498Szrj if (!return_bounds) 469638fd1498Szrj { 469738fd1498Szrj gimple_stmt_iterator iter = gsi_for_stmt (retbnd); 469838fd1498Szrj gsi_remove (&iter, true); 469938fd1498Szrj } 470038fd1498Szrj } 470138fd1498Szrj } 470238fd1498Szrj 470338fd1498Szrj /* The function which we are inlining might not return a value, 470438fd1498Szrj in which case we should issue a warning that the function 470538fd1498Szrj does not return a value. In that case the optimizers will 470638fd1498Szrj see that the variable to which the value is assigned was not 470738fd1498Szrj initialized. We do not want to issue a warning about that 470838fd1498Szrj uninitialized variable. */ 470938fd1498Szrj if (DECL_P (modify_dest)) 471038fd1498Szrj TREE_NO_WARNING (modify_dest) = 1; 471138fd1498Szrj 471238fd1498Szrj if (gimple_call_return_slot_opt_p (call_stmt)) 471338fd1498Szrj { 471438fd1498Szrj return_slot = modify_dest; 471538fd1498Szrj modify_dest = NULL; 471638fd1498Szrj } 471738fd1498Szrj } 471838fd1498Szrj else 471938fd1498Szrj modify_dest = NULL; 472038fd1498Szrj 472138fd1498Szrj /* If we are inlining a call to the C++ operator new, we don't want 472238fd1498Szrj to use type based alias analysis on the return value. Otherwise 472338fd1498Szrj we may get confused if the compiler sees that the inlined new 472438fd1498Szrj function returns a pointer which was just deleted. See bug 472538fd1498Szrj 33407. */ 472638fd1498Szrj if (DECL_IS_OPERATOR_NEW (fn)) 472738fd1498Szrj { 472838fd1498Szrj return_slot = NULL; 472938fd1498Szrj modify_dest = NULL; 473038fd1498Szrj } 473138fd1498Szrj 473238fd1498Szrj /* Declare the return variable for the function. */ 473338fd1498Szrj use_retvar = declare_return_variable (id, return_slot, modify_dest, 473438fd1498Szrj return_bounds, bb); 473538fd1498Szrj 473638fd1498Szrj /* Add local vars in this inlined callee to caller. */ 473738fd1498Szrj add_local_variables (id->src_cfun, cfun, id); 473838fd1498Szrj 473938fd1498Szrj if (dump_file && (dump_flags & TDF_DETAILS)) 474038fd1498Szrj { 474138fd1498Szrj fprintf (dump_file, "Inlining %s to %s with frequency %4.2f\n", 474238fd1498Szrj id->src_node->dump_name (), 474338fd1498Szrj id->dst_node->dump_name (), 474438fd1498Szrj cg_edge->sreal_frequency ().to_double ()); 474538fd1498Szrj id->src_node->dump (dump_file); 474638fd1498Szrj id->dst_node->dump (dump_file); 474738fd1498Szrj } 474838fd1498Szrj 474938fd1498Szrj /* This is it. Duplicate the callee body. Assume callee is 475038fd1498Szrj pre-gimplified. Note that we must not alter the caller 475138fd1498Szrj function in any way before this point, as this CALL_EXPR may be 475238fd1498Szrj a self-referential call; if we're calling ourselves, we need to 475338fd1498Szrj duplicate our body before altering anything. */ 475438fd1498Szrj copy_body (id, bb, return_block, NULL); 475538fd1498Szrj 475638fd1498Szrj reset_debug_bindings (id, stmt_gsi); 475738fd1498Szrj 475838fd1498Szrj if (flag_stack_reuse != SR_NONE) 475938fd1498Szrj for (tree p = DECL_ARGUMENTS (id->src_fn); p; p = DECL_CHAIN (p)) 476038fd1498Szrj if (!TREE_THIS_VOLATILE (p)) 476138fd1498Szrj { 476238fd1498Szrj tree *varp = id->decl_map->get (p); 476338fd1498Szrj if (varp && VAR_P (*varp) && !is_gimple_reg (*varp)) 476438fd1498Szrj { 476538fd1498Szrj tree clobber = build_constructor (TREE_TYPE (*varp), NULL); 476638fd1498Szrj gimple *clobber_stmt; 476738fd1498Szrj TREE_THIS_VOLATILE (clobber) = 1; 476838fd1498Szrj clobber_stmt = gimple_build_assign (*varp, clobber); 476938fd1498Szrj gimple_set_location (clobber_stmt, gimple_location (stmt)); 477038fd1498Szrj gsi_insert_before (&stmt_gsi, clobber_stmt, GSI_SAME_STMT); 477138fd1498Szrj } 477238fd1498Szrj } 477338fd1498Szrj 477438fd1498Szrj /* Reset the escaped solution. */ 477538fd1498Szrj if (cfun->gimple_df) 477638fd1498Szrj pt_solution_reset (&cfun->gimple_df->escaped); 477738fd1498Szrj 477838fd1498Szrj /* Add new automatic variables to IFN_GOMP_SIMT_ENTER arguments. */ 477938fd1498Szrj if (id->dst_simt_vars && id->dst_simt_vars->length () > 0) 478038fd1498Szrj { 478138fd1498Szrj size_t nargs = gimple_call_num_args (simtenter_stmt); 478238fd1498Szrj vec<tree> *vars = id->dst_simt_vars; 478338fd1498Szrj auto_vec<tree> newargs (nargs + vars->length ()); 478438fd1498Szrj for (size_t i = 0; i < nargs; i++) 478538fd1498Szrj newargs.quick_push (gimple_call_arg (simtenter_stmt, i)); 478638fd1498Szrj for (tree *pvar = vars->begin (); pvar != vars->end (); pvar++) 478738fd1498Szrj { 478838fd1498Szrj tree ptrtype = build_pointer_type (TREE_TYPE (*pvar)); 478938fd1498Szrj newargs.quick_push (build1 (ADDR_EXPR, ptrtype, *pvar)); 479038fd1498Szrj } 479138fd1498Szrj gcall *g = gimple_build_call_internal_vec (IFN_GOMP_SIMT_ENTER, newargs); 479238fd1498Szrj gimple_call_set_lhs (g, gimple_call_lhs (simtenter_stmt)); 479338fd1498Szrj gimple_stmt_iterator gsi = gsi_for_stmt (simtenter_stmt); 479438fd1498Szrj gsi_replace (&gsi, g, false); 479538fd1498Szrj } 479638fd1498Szrj vec_free (id->dst_simt_vars); 479738fd1498Szrj id->dst_simt_vars = simtvars_save; 479838fd1498Szrj 479938fd1498Szrj /* Clean up. */ 480038fd1498Szrj if (id->debug_map) 480138fd1498Szrj { 480238fd1498Szrj delete id->debug_map; 480338fd1498Szrj id->debug_map = dst; 480438fd1498Szrj } 480538fd1498Szrj delete id->decl_map; 480638fd1498Szrj id->decl_map = st; 480738fd1498Szrj 480838fd1498Szrj /* Unlink the calls virtual operands before replacing it. */ 480938fd1498Szrj unlink_stmt_vdef (stmt); 481038fd1498Szrj if (gimple_vdef (stmt) 481138fd1498Szrj && TREE_CODE (gimple_vdef (stmt)) == SSA_NAME) 481238fd1498Szrj release_ssa_name (gimple_vdef (stmt)); 481338fd1498Szrj 481438fd1498Szrj /* If the inlined function returns a result that we care about, 481538fd1498Szrj substitute the GIMPLE_CALL with an assignment of the return 481638fd1498Szrj variable to the LHS of the call. That is, if STMT was 481738fd1498Szrj 'a = foo (...)', substitute the call with 'a = USE_RETVAR'. */ 481838fd1498Szrj if (use_retvar && gimple_call_lhs (stmt)) 481938fd1498Szrj { 482038fd1498Szrj gimple *old_stmt = stmt; 482138fd1498Szrj stmt = gimple_build_assign (gimple_call_lhs (stmt), use_retvar); 482238fd1498Szrj gsi_replace (&stmt_gsi, stmt, false); 482338fd1498Szrj maybe_clean_or_replace_eh_stmt (old_stmt, stmt); 482438fd1498Szrj /* Append a clobber for id->retvar if easily possible. */ 482538fd1498Szrj if (flag_stack_reuse != SR_NONE 482638fd1498Szrj && id->retvar 482738fd1498Szrj && VAR_P (id->retvar) 482838fd1498Szrj && id->retvar != return_slot 482938fd1498Szrj && id->retvar != modify_dest 483038fd1498Szrj && !TREE_THIS_VOLATILE (id->retvar) 483138fd1498Szrj && !is_gimple_reg (id->retvar) 483238fd1498Szrj && !stmt_ends_bb_p (stmt)) 483338fd1498Szrj { 483438fd1498Szrj tree clobber = build_constructor (TREE_TYPE (id->retvar), NULL); 483538fd1498Szrj gimple *clobber_stmt; 483638fd1498Szrj TREE_THIS_VOLATILE (clobber) = 1; 483738fd1498Szrj clobber_stmt = gimple_build_assign (id->retvar, clobber); 483838fd1498Szrj gimple_set_location (clobber_stmt, gimple_location (old_stmt)); 483938fd1498Szrj gsi_insert_after (&stmt_gsi, clobber_stmt, GSI_SAME_STMT); 484038fd1498Szrj } 484138fd1498Szrj 484238fd1498Szrj /* Copy bounds if we copy structure with bounds. */ 484338fd1498Szrj if (chkp_function_instrumented_p (id->dst_fn) 484438fd1498Szrj && !BOUNDED_P (use_retvar) 484538fd1498Szrj && chkp_type_has_pointer (TREE_TYPE (use_retvar))) 484638fd1498Szrj id->assign_stmts.safe_push (stmt); 484738fd1498Szrj } 484838fd1498Szrj else 484938fd1498Szrj { 485038fd1498Szrj /* Handle the case of inlining a function with no return 485138fd1498Szrj statement, which causes the return value to become undefined. */ 485238fd1498Szrj if (gimple_call_lhs (stmt) 485338fd1498Szrj && TREE_CODE (gimple_call_lhs (stmt)) == SSA_NAME) 485438fd1498Szrj { 485538fd1498Szrj tree name = gimple_call_lhs (stmt); 485638fd1498Szrj tree var = SSA_NAME_VAR (name); 485738fd1498Szrj tree def = var ? ssa_default_def (cfun, var) : NULL; 485838fd1498Szrj 485938fd1498Szrj if (def) 486038fd1498Szrj { 486138fd1498Szrj /* If the variable is used undefined, make this name 486238fd1498Szrj undefined via a move. */ 486338fd1498Szrj stmt = gimple_build_assign (gimple_call_lhs (stmt), def); 486438fd1498Szrj gsi_replace (&stmt_gsi, stmt, true); 486538fd1498Szrj } 486638fd1498Szrj else 486738fd1498Szrj { 486838fd1498Szrj if (!var) 486938fd1498Szrj { 487038fd1498Szrj var = create_tmp_reg_fn (cfun, TREE_TYPE (name), NULL); 487138fd1498Szrj SET_SSA_NAME_VAR_OR_IDENTIFIER (name, var); 487238fd1498Szrj } 487338fd1498Szrj /* Otherwise make this variable undefined. */ 487438fd1498Szrj gsi_remove (&stmt_gsi, true); 487538fd1498Szrj set_ssa_default_def (cfun, var, name); 487638fd1498Szrj SSA_NAME_DEF_STMT (name) = gimple_build_nop (); 487738fd1498Szrj } 487838fd1498Szrj } 487938fd1498Szrj /* Replace with a clobber for id->retvar. */ 488038fd1498Szrj else if (flag_stack_reuse != SR_NONE 488138fd1498Szrj && id->retvar 488238fd1498Szrj && VAR_P (id->retvar) 488338fd1498Szrj && id->retvar != return_slot 488438fd1498Szrj && id->retvar != modify_dest 488538fd1498Szrj && !TREE_THIS_VOLATILE (id->retvar) 488638fd1498Szrj && !is_gimple_reg (id->retvar)) 488738fd1498Szrj { 488838fd1498Szrj tree clobber = build_constructor (TREE_TYPE (id->retvar), NULL); 488938fd1498Szrj gimple *clobber_stmt; 489038fd1498Szrj TREE_THIS_VOLATILE (clobber) = 1; 489138fd1498Szrj clobber_stmt = gimple_build_assign (id->retvar, clobber); 489238fd1498Szrj gimple_set_location (clobber_stmt, gimple_location (stmt)); 489338fd1498Szrj gsi_replace (&stmt_gsi, clobber_stmt, false); 489438fd1498Szrj maybe_clean_or_replace_eh_stmt (stmt, clobber_stmt); 489538fd1498Szrj } 489638fd1498Szrj else 489738fd1498Szrj gsi_remove (&stmt_gsi, true); 489838fd1498Szrj } 489938fd1498Szrj 490038fd1498Szrj /* Put returned bounds into the correct place if required. */ 490138fd1498Szrj if (return_bounds) 490238fd1498Szrj { 490338fd1498Szrj gimple *old_stmt = SSA_NAME_DEF_STMT (return_bounds); 490438fd1498Szrj gimple *new_stmt = gimple_build_assign (return_bounds, id->retbnd); 490538fd1498Szrj gimple_stmt_iterator bnd_gsi = gsi_for_stmt (old_stmt); 490638fd1498Szrj unlink_stmt_vdef (old_stmt); 490738fd1498Szrj gsi_replace (&bnd_gsi, new_stmt, false); 490838fd1498Szrj maybe_clean_or_replace_eh_stmt (old_stmt, new_stmt); 490938fd1498Szrj cgraph_update_edges_for_call_stmt (old_stmt, 491038fd1498Szrj gimple_call_fndecl (old_stmt), 491138fd1498Szrj new_stmt); 491238fd1498Szrj } 491338fd1498Szrj 491438fd1498Szrj if (purge_dead_abnormal_edges) 491538fd1498Szrj { 491638fd1498Szrj gimple_purge_dead_eh_edges (return_block); 491738fd1498Szrj gimple_purge_dead_abnormal_call_edges (return_block); 491838fd1498Szrj } 491938fd1498Szrj 492038fd1498Szrj /* If the value of the new expression is ignored, that's OK. We 492138fd1498Szrj don't warn about this for CALL_EXPRs, so we shouldn't warn about 492238fd1498Szrj the equivalent inlined version either. */ 492338fd1498Szrj if (is_gimple_assign (stmt)) 492438fd1498Szrj { 492538fd1498Szrj gcc_assert (gimple_assign_single_p (stmt) 492638fd1498Szrj || CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt))); 492738fd1498Szrj TREE_USED (gimple_assign_rhs1 (stmt)) = 1; 492838fd1498Szrj } 492938fd1498Szrj 493038fd1498Szrj /* Copy bounds for all generated assigns that need it. */ 493138fd1498Szrj for (i = 0; i < id->assign_stmts.length (); i++) 493238fd1498Szrj chkp_copy_bounds_for_assign (id->assign_stmts[i], cg_edge); 493338fd1498Szrj id->assign_stmts.release (); 493438fd1498Szrj 493538fd1498Szrj /* Output the inlining info for this abstract function, since it has been 493638fd1498Szrj inlined. If we don't do this now, we can lose the information about the 493738fd1498Szrj variables in the function when the blocks get blown away as soon as we 493838fd1498Szrj remove the cgraph node. */ 493938fd1498Szrj if (gimple_block (stmt)) 494038fd1498Szrj (*debug_hooks->outlining_inline_function) (cg_edge->callee->decl); 494138fd1498Szrj 494238fd1498Szrj /* Update callgraph if needed. */ 494338fd1498Szrj cg_edge->callee->remove (); 494438fd1498Szrj 494538fd1498Szrj id->block = NULL_TREE; 494638fd1498Szrj id->retvar = NULL_TREE; 494738fd1498Szrj id->retbnd = NULL_TREE; 494838fd1498Szrj successfully_inlined = true; 494938fd1498Szrj 495038fd1498Szrj egress: 495138fd1498Szrj input_location = saved_location; 495238fd1498Szrj return successfully_inlined; 495338fd1498Szrj } 495438fd1498Szrj 495538fd1498Szrj /* Expand call statements reachable from STMT_P. 495638fd1498Szrj We can only have CALL_EXPRs as the "toplevel" tree code or nested 495738fd1498Szrj in a MODIFY_EXPR. */ 495838fd1498Szrj 495938fd1498Szrj static bool 496038fd1498Szrj gimple_expand_calls_inline (basic_block bb, copy_body_data *id) 496138fd1498Szrj { 496238fd1498Szrj gimple_stmt_iterator gsi; 496338fd1498Szrj bool inlined = false; 496438fd1498Szrj 496538fd1498Szrj for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi);) 496638fd1498Szrj { 496738fd1498Szrj gimple *stmt = gsi_stmt (gsi); 496838fd1498Szrj gsi_prev (&gsi); 496938fd1498Szrj 497038fd1498Szrj if (is_gimple_call (stmt) 497138fd1498Szrj && !gimple_call_internal_p (stmt)) 497238fd1498Szrj inlined |= expand_call_inline (bb, stmt, id); 497338fd1498Szrj } 497438fd1498Szrj 497538fd1498Szrj return inlined; 497638fd1498Szrj } 497738fd1498Szrj 497838fd1498Szrj 497938fd1498Szrj /* Walk all basic blocks created after FIRST and try to fold every statement 498038fd1498Szrj in the STATEMENTS pointer set. */ 498138fd1498Szrj 498238fd1498Szrj static void 498338fd1498Szrj fold_marked_statements (int first, hash_set<gimple *> *statements) 498438fd1498Szrj { 498538fd1498Szrj for (; first < n_basic_blocks_for_fn (cfun); first++) 498638fd1498Szrj if (BASIC_BLOCK_FOR_FN (cfun, first)) 498738fd1498Szrj { 498838fd1498Szrj gimple_stmt_iterator gsi; 498938fd1498Szrj 499038fd1498Szrj for (gsi = gsi_start_bb (BASIC_BLOCK_FOR_FN (cfun, first)); 499138fd1498Szrj !gsi_end_p (gsi); 499238fd1498Szrj gsi_next (&gsi)) 499338fd1498Szrj if (statements->contains (gsi_stmt (gsi))) 499438fd1498Szrj { 499538fd1498Szrj gimple *old_stmt = gsi_stmt (gsi); 499638fd1498Szrj tree old_decl = is_gimple_call (old_stmt) ? gimple_call_fndecl (old_stmt) : 0; 499738fd1498Szrj 499838fd1498Szrj if (old_decl && DECL_BUILT_IN (old_decl)) 499938fd1498Szrj { 500038fd1498Szrj /* Folding builtins can create multiple instructions, 500138fd1498Szrj we need to look at all of them. */ 500238fd1498Szrj gimple_stmt_iterator i2 = gsi; 500338fd1498Szrj gsi_prev (&i2); 500438fd1498Szrj if (fold_stmt (&gsi)) 500538fd1498Szrj { 500638fd1498Szrj gimple *new_stmt; 500738fd1498Szrj /* If a builtin at the end of a bb folded into nothing, 500838fd1498Szrj the following loop won't work. */ 500938fd1498Szrj if (gsi_end_p (gsi)) 501038fd1498Szrj { 501138fd1498Szrj cgraph_update_edges_for_call_stmt (old_stmt, 501238fd1498Szrj old_decl, NULL); 501338fd1498Szrj break; 501438fd1498Szrj } 501538fd1498Szrj if (gsi_end_p (i2)) 501638fd1498Szrj i2 = gsi_start_bb (BASIC_BLOCK_FOR_FN (cfun, first)); 501738fd1498Szrj else 501838fd1498Szrj gsi_next (&i2); 501938fd1498Szrj while (1) 502038fd1498Szrj { 502138fd1498Szrj new_stmt = gsi_stmt (i2); 502238fd1498Szrj update_stmt (new_stmt); 502338fd1498Szrj cgraph_update_edges_for_call_stmt (old_stmt, old_decl, 502438fd1498Szrj new_stmt); 502538fd1498Szrj 502638fd1498Szrj if (new_stmt == gsi_stmt (gsi)) 502738fd1498Szrj { 502838fd1498Szrj /* It is okay to check only for the very last 502938fd1498Szrj of these statements. If it is a throwing 503038fd1498Szrj statement nothing will change. If it isn't 503138fd1498Szrj this can remove EH edges. If that weren't 503238fd1498Szrj correct then because some intermediate stmts 503338fd1498Szrj throw, but not the last one. That would mean 503438fd1498Szrj we'd have to split the block, which we can't 503538fd1498Szrj here and we'd loose anyway. And as builtins 503638fd1498Szrj probably never throw, this all 503738fd1498Szrj is mood anyway. */ 503838fd1498Szrj if (maybe_clean_or_replace_eh_stmt (old_stmt, 503938fd1498Szrj new_stmt)) 504038fd1498Szrj gimple_purge_dead_eh_edges ( 504138fd1498Szrj BASIC_BLOCK_FOR_FN (cfun, first)); 504238fd1498Szrj break; 504338fd1498Szrj } 504438fd1498Szrj gsi_next (&i2); 504538fd1498Szrj } 504638fd1498Szrj } 504738fd1498Szrj } 504838fd1498Szrj else if (fold_stmt (&gsi)) 504938fd1498Szrj { 505038fd1498Szrj /* Re-read the statement from GSI as fold_stmt() may 505138fd1498Szrj have changed it. */ 505238fd1498Szrj gimple *new_stmt = gsi_stmt (gsi); 505338fd1498Szrj update_stmt (new_stmt); 505438fd1498Szrj 505538fd1498Szrj if (is_gimple_call (old_stmt) 505638fd1498Szrj || is_gimple_call (new_stmt)) 505738fd1498Szrj cgraph_update_edges_for_call_stmt (old_stmt, old_decl, 505838fd1498Szrj new_stmt); 505938fd1498Szrj 506038fd1498Szrj if (maybe_clean_or_replace_eh_stmt (old_stmt, new_stmt)) 506138fd1498Szrj gimple_purge_dead_eh_edges (BASIC_BLOCK_FOR_FN (cfun, 506238fd1498Szrj first)); 506338fd1498Szrj } 506438fd1498Szrj } 506538fd1498Szrj } 506638fd1498Szrj } 506738fd1498Szrj 506838fd1498Szrj /* Expand calls to inline functions in the body of FN. */ 506938fd1498Szrj 507038fd1498Szrj unsigned int 507138fd1498Szrj optimize_inline_calls (tree fn) 507238fd1498Szrj { 507338fd1498Szrj copy_body_data id; 507438fd1498Szrj basic_block bb; 507538fd1498Szrj int last = n_basic_blocks_for_fn (cfun); 507638fd1498Szrj bool inlined_p = false; 507738fd1498Szrj 507838fd1498Szrj /* Clear out ID. */ 507938fd1498Szrj memset (&id, 0, sizeof (id)); 508038fd1498Szrj 508138fd1498Szrj id.src_node = id.dst_node = cgraph_node::get (fn); 508238fd1498Szrj gcc_assert (id.dst_node->definition); 508338fd1498Szrj id.dst_fn = fn; 508438fd1498Szrj /* Or any functions that aren't finished yet. */ 508538fd1498Szrj if (current_function_decl) 508638fd1498Szrj id.dst_fn = current_function_decl; 508738fd1498Szrj 508838fd1498Szrj id.copy_decl = copy_decl_maybe_to_var; 508938fd1498Szrj id.transform_call_graph_edges = CB_CGE_DUPLICATE; 509038fd1498Szrj id.transform_new_cfg = false; 509138fd1498Szrj id.transform_return_to_modify = true; 509238fd1498Szrj id.transform_parameter = true; 509338fd1498Szrj id.transform_lang_insert_block = NULL; 509438fd1498Szrj id.statements_to_fold = new hash_set<gimple *>; 509538fd1498Szrj 509638fd1498Szrj push_gimplify_context (); 509738fd1498Szrj 509838fd1498Szrj /* We make no attempts to keep dominance info up-to-date. */ 509938fd1498Szrj free_dominance_info (CDI_DOMINATORS); 510038fd1498Szrj free_dominance_info (CDI_POST_DOMINATORS); 510138fd1498Szrj 510238fd1498Szrj /* Register specific gimple functions. */ 510338fd1498Szrj gimple_register_cfg_hooks (); 510438fd1498Szrj 510538fd1498Szrj /* Reach the trees by walking over the CFG, and note the 510638fd1498Szrj enclosing basic-blocks in the call edges. */ 510738fd1498Szrj /* We walk the blocks going forward, because inlined function bodies 510838fd1498Szrj will split id->current_basic_block, and the new blocks will 510938fd1498Szrj follow it; we'll trudge through them, processing their CALL_EXPRs 511038fd1498Szrj along the way. */ 511138fd1498Szrj FOR_EACH_BB_FN (bb, cfun) 511238fd1498Szrj inlined_p |= gimple_expand_calls_inline (bb, &id); 511338fd1498Szrj 511438fd1498Szrj pop_gimplify_context (NULL); 511538fd1498Szrj 511638fd1498Szrj if (flag_checking) 511738fd1498Szrj { 511838fd1498Szrj struct cgraph_edge *e; 511938fd1498Szrj 512038fd1498Szrj id.dst_node->verify (); 512138fd1498Szrj 512238fd1498Szrj /* Double check that we inlined everything we are supposed to inline. */ 512338fd1498Szrj for (e = id.dst_node->callees; e; e = e->next_callee) 512438fd1498Szrj gcc_assert (e->inline_failed); 512538fd1498Szrj } 512638fd1498Szrj 512738fd1498Szrj /* Fold queued statements. */ 512838fd1498Szrj update_max_bb_count (); 512938fd1498Szrj fold_marked_statements (last, id.statements_to_fold); 513038fd1498Szrj delete id.statements_to_fold; 513138fd1498Szrj 513238fd1498Szrj gcc_assert (!id.debug_stmts.exists ()); 513338fd1498Szrj 513438fd1498Szrj /* If we didn't inline into the function there is nothing to do. */ 513538fd1498Szrj if (!inlined_p) 513638fd1498Szrj return 0; 513738fd1498Szrj 513838fd1498Szrj /* Renumber the lexical scoping (non-code) blocks consecutively. */ 513938fd1498Szrj number_blocks (fn); 514038fd1498Szrj 514138fd1498Szrj delete_unreachable_blocks_update_callgraph (&id); 514238fd1498Szrj if (flag_checking) 514338fd1498Szrj id.dst_node->verify (); 514438fd1498Szrj 514538fd1498Szrj /* It would be nice to check SSA/CFG/statement consistency here, but it is 514638fd1498Szrj not possible yet - the IPA passes might make various functions to not 514738fd1498Szrj throw and they don't care to proactively update local EH info. This is 514838fd1498Szrj done later in fixup_cfg pass that also execute the verification. */ 514938fd1498Szrj return (TODO_update_ssa 515038fd1498Szrj | TODO_cleanup_cfg 515138fd1498Szrj | (gimple_in_ssa_p (cfun) ? TODO_remove_unused_locals : 0) 515238fd1498Szrj | (gimple_in_ssa_p (cfun) ? TODO_update_address_taken : 0) 515338fd1498Szrj | (profile_status_for_fn (cfun) != PROFILE_ABSENT 515438fd1498Szrj ? TODO_rebuild_frequencies : 0)); 515538fd1498Szrj } 515638fd1498Szrj 515738fd1498Szrj /* Passed to walk_tree. Copies the node pointed to, if appropriate. */ 515838fd1498Szrj 515938fd1498Szrj tree 516038fd1498Szrj copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) 516138fd1498Szrj { 516238fd1498Szrj enum tree_code code = TREE_CODE (*tp); 516338fd1498Szrj enum tree_code_class cl = TREE_CODE_CLASS (code); 516438fd1498Szrj 516538fd1498Szrj /* We make copies of most nodes. */ 516638fd1498Szrj if (IS_EXPR_CODE_CLASS (cl) 516738fd1498Szrj || code == TREE_LIST 516838fd1498Szrj || code == TREE_VEC 516938fd1498Szrj || code == TYPE_DECL 517038fd1498Szrj || code == OMP_CLAUSE) 517138fd1498Szrj { 517238fd1498Szrj /* Because the chain gets clobbered when we make a copy, we save it 517338fd1498Szrj here. */ 517438fd1498Szrj tree chain = NULL_TREE, new_tree; 517538fd1498Szrj 517638fd1498Szrj if (CODE_CONTAINS_STRUCT (code, TS_COMMON)) 517738fd1498Szrj chain = TREE_CHAIN (*tp); 517838fd1498Szrj 517938fd1498Szrj /* Copy the node. */ 518038fd1498Szrj new_tree = copy_node (*tp); 518138fd1498Szrj 518238fd1498Szrj *tp = new_tree; 518338fd1498Szrj 518438fd1498Szrj /* Now, restore the chain, if appropriate. That will cause 518538fd1498Szrj walk_tree to walk into the chain as well. */ 518638fd1498Szrj if (code == PARM_DECL 518738fd1498Szrj || code == TREE_LIST 518838fd1498Szrj || code == OMP_CLAUSE) 518938fd1498Szrj TREE_CHAIN (*tp) = chain; 519038fd1498Szrj 519138fd1498Szrj /* For now, we don't update BLOCKs when we make copies. So, we 519238fd1498Szrj have to nullify all BIND_EXPRs. */ 519338fd1498Szrj if (TREE_CODE (*tp) == BIND_EXPR) 519438fd1498Szrj BIND_EXPR_BLOCK (*tp) = NULL_TREE; 519538fd1498Szrj } 519638fd1498Szrj else if (code == CONSTRUCTOR) 519738fd1498Szrj { 519838fd1498Szrj /* CONSTRUCTOR nodes need special handling because 519938fd1498Szrj we need to duplicate the vector of elements. */ 520038fd1498Szrj tree new_tree; 520138fd1498Szrj 520238fd1498Szrj new_tree = copy_node (*tp); 520338fd1498Szrj CONSTRUCTOR_ELTS (new_tree) = vec_safe_copy (CONSTRUCTOR_ELTS (*tp)); 520438fd1498Szrj *tp = new_tree; 520538fd1498Szrj } 520638fd1498Szrj else if (code == STATEMENT_LIST) 520738fd1498Szrj /* We used to just abort on STATEMENT_LIST, but we can run into them 520838fd1498Szrj with statement-expressions (c++/40975). */ 520938fd1498Szrj copy_statement_list (tp); 521038fd1498Szrj else if (TREE_CODE_CLASS (code) == tcc_type) 521138fd1498Szrj *walk_subtrees = 0; 521238fd1498Szrj else if (TREE_CODE_CLASS (code) == tcc_declaration) 521338fd1498Szrj *walk_subtrees = 0; 521438fd1498Szrj else if (TREE_CODE_CLASS (code) == tcc_constant) 521538fd1498Szrj *walk_subtrees = 0; 521638fd1498Szrj return NULL_TREE; 521738fd1498Szrj } 521838fd1498Szrj 521938fd1498Szrj /* The SAVE_EXPR pointed to by TP is being copied. If ST contains 522038fd1498Szrj information indicating to what new SAVE_EXPR this one should be mapped, 522138fd1498Szrj use that one. Otherwise, create a new node and enter it in ST. FN is 522238fd1498Szrj the function into which the copy will be placed. */ 522338fd1498Szrj 522438fd1498Szrj static void 522538fd1498Szrj remap_save_expr (tree *tp, hash_map<tree, tree> *st, int *walk_subtrees) 522638fd1498Szrj { 522738fd1498Szrj tree *n; 522838fd1498Szrj tree t; 522938fd1498Szrj 523038fd1498Szrj /* See if we already encountered this SAVE_EXPR. */ 523138fd1498Szrj n = st->get (*tp); 523238fd1498Szrj 523338fd1498Szrj /* If we didn't already remap this SAVE_EXPR, do so now. */ 523438fd1498Szrj if (!n) 523538fd1498Szrj { 523638fd1498Szrj t = copy_node (*tp); 523738fd1498Szrj 523838fd1498Szrj /* Remember this SAVE_EXPR. */ 523938fd1498Szrj st->put (*tp, t); 524038fd1498Szrj /* Make sure we don't remap an already-remapped SAVE_EXPR. */ 524138fd1498Szrj st->put (t, t); 524238fd1498Szrj } 524338fd1498Szrj else 524438fd1498Szrj { 524538fd1498Szrj /* We've already walked into this SAVE_EXPR; don't do it again. */ 524638fd1498Szrj *walk_subtrees = 0; 524738fd1498Szrj t = *n; 524838fd1498Szrj } 524938fd1498Szrj 525038fd1498Szrj /* Replace this SAVE_EXPR with the copy. */ 525138fd1498Szrj *tp = t; 525238fd1498Szrj } 525338fd1498Szrj 525438fd1498Szrj /* Called via walk_gimple_seq. If *GSIP points to a GIMPLE_LABEL for a local 525538fd1498Szrj label, copies the declaration and enters it in the splay_tree in DATA (which 525638fd1498Szrj is really a 'copy_body_data *'. */ 525738fd1498Szrj 525838fd1498Szrj static tree 525938fd1498Szrj mark_local_labels_stmt (gimple_stmt_iterator *gsip, 526038fd1498Szrj bool *handled_ops_p ATTRIBUTE_UNUSED, 526138fd1498Szrj struct walk_stmt_info *wi) 526238fd1498Szrj { 526338fd1498Szrj copy_body_data *id = (copy_body_data *) wi->info; 526438fd1498Szrj glabel *stmt = dyn_cast <glabel *> (gsi_stmt (*gsip)); 526538fd1498Szrj 526638fd1498Szrj if (stmt) 526738fd1498Szrj { 526838fd1498Szrj tree decl = gimple_label_label (stmt); 526938fd1498Szrj 527038fd1498Szrj /* Copy the decl and remember the copy. */ 527138fd1498Szrj insert_decl_map (id, decl, id->copy_decl (decl, id)); 527238fd1498Szrj } 527338fd1498Szrj 527438fd1498Szrj return NULL_TREE; 527538fd1498Szrj } 527638fd1498Szrj 527738fd1498Szrj static gimple_seq duplicate_remap_omp_clause_seq (gimple_seq seq, 527838fd1498Szrj struct walk_stmt_info *wi); 527938fd1498Szrj 528038fd1498Szrj /* Called via walk_gimple_seq by copy_gimple_seq_and_replace_local. 528138fd1498Szrj Using the splay_tree pointed to by ST (which is really a `splay_tree'), 528238fd1498Szrj remaps all local declarations to appropriate replacements in gimple 528338fd1498Szrj operands. */ 528438fd1498Szrj 528538fd1498Szrj static tree 528638fd1498Szrj replace_locals_op (tree *tp, int *walk_subtrees, void *data) 528738fd1498Szrj { 528838fd1498Szrj struct walk_stmt_info *wi = (struct walk_stmt_info*) data; 528938fd1498Szrj copy_body_data *id = (copy_body_data *) wi->info; 529038fd1498Szrj hash_map<tree, tree> *st = id->decl_map; 529138fd1498Szrj tree *n; 529238fd1498Szrj tree expr = *tp; 529338fd1498Szrj 529438fd1498Szrj /* For recursive invocations this is no longer the LHS itself. */ 529538fd1498Szrj bool is_lhs = wi->is_lhs; 529638fd1498Szrj wi->is_lhs = false; 529738fd1498Szrj 529838fd1498Szrj if (TREE_CODE (expr) == SSA_NAME) 529938fd1498Szrj { 530038fd1498Szrj *tp = remap_ssa_name (*tp, id); 530138fd1498Szrj *walk_subtrees = 0; 530238fd1498Szrj if (is_lhs) 530338fd1498Szrj SSA_NAME_DEF_STMT (*tp) = gsi_stmt (wi->gsi); 530438fd1498Szrj } 530538fd1498Szrj /* Only a local declaration (variable or label). */ 530638fd1498Szrj else if ((VAR_P (expr) && !TREE_STATIC (expr)) 530738fd1498Szrj || TREE_CODE (expr) == LABEL_DECL) 530838fd1498Szrj { 530938fd1498Szrj /* Lookup the declaration. */ 531038fd1498Szrj n = st->get (expr); 531138fd1498Szrj 531238fd1498Szrj /* If it's there, remap it. */ 531338fd1498Szrj if (n) 531438fd1498Szrj *tp = *n; 531538fd1498Szrj *walk_subtrees = 0; 531638fd1498Szrj } 531738fd1498Szrj else if (TREE_CODE (expr) == STATEMENT_LIST 531838fd1498Szrj || TREE_CODE (expr) == BIND_EXPR 531938fd1498Szrj || TREE_CODE (expr) == SAVE_EXPR) 532038fd1498Szrj gcc_unreachable (); 532138fd1498Szrj else if (TREE_CODE (expr) == TARGET_EXPR) 532238fd1498Szrj { 532338fd1498Szrj /* Don't mess with a TARGET_EXPR that hasn't been expanded. 532438fd1498Szrj It's OK for this to happen if it was part of a subtree that 532538fd1498Szrj isn't immediately expanded, such as operand 2 of another 532638fd1498Szrj TARGET_EXPR. */ 532738fd1498Szrj if (!TREE_OPERAND (expr, 1)) 532838fd1498Szrj { 532938fd1498Szrj TREE_OPERAND (expr, 1) = TREE_OPERAND (expr, 3); 533038fd1498Szrj TREE_OPERAND (expr, 3) = NULL_TREE; 533138fd1498Szrj } 533238fd1498Szrj } 533338fd1498Szrj else if (TREE_CODE (expr) == OMP_CLAUSE) 533438fd1498Szrj { 533538fd1498Szrj /* Before the omplower pass completes, some OMP clauses can contain 533638fd1498Szrj sequences that are neither copied by gimple_seq_copy nor walked by 533738fd1498Szrj walk_gimple_seq. To make copy_gimple_seq_and_replace_locals work even 533838fd1498Szrj in those situations, we have to copy and process them explicitely. */ 533938fd1498Szrj 534038fd1498Szrj if (OMP_CLAUSE_CODE (expr) == OMP_CLAUSE_LASTPRIVATE) 534138fd1498Szrj { 534238fd1498Szrj gimple_seq seq = OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (expr); 534338fd1498Szrj seq = duplicate_remap_omp_clause_seq (seq, wi); 534438fd1498Szrj OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (expr) = seq; 534538fd1498Szrj } 534638fd1498Szrj else if (OMP_CLAUSE_CODE (expr) == OMP_CLAUSE_LINEAR) 534738fd1498Szrj { 534838fd1498Szrj gimple_seq seq = OMP_CLAUSE_LINEAR_GIMPLE_SEQ (expr); 534938fd1498Szrj seq = duplicate_remap_omp_clause_seq (seq, wi); 535038fd1498Szrj OMP_CLAUSE_LINEAR_GIMPLE_SEQ (expr) = seq; 535138fd1498Szrj } 535238fd1498Szrj else if (OMP_CLAUSE_CODE (expr) == OMP_CLAUSE_REDUCTION) 535338fd1498Szrj { 535438fd1498Szrj gimple_seq seq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (expr); 535538fd1498Szrj seq = duplicate_remap_omp_clause_seq (seq, wi); 535638fd1498Szrj OMP_CLAUSE_REDUCTION_GIMPLE_INIT (expr) = seq; 535738fd1498Szrj seq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (expr); 535838fd1498Szrj seq = duplicate_remap_omp_clause_seq (seq, wi); 535938fd1498Szrj OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (expr) = seq; 536038fd1498Szrj } 536138fd1498Szrj } 536238fd1498Szrj 536338fd1498Szrj /* Keep iterating. */ 536438fd1498Szrj return NULL_TREE; 536538fd1498Szrj } 536638fd1498Szrj 536738fd1498Szrj 536838fd1498Szrj /* Called via walk_gimple_seq by copy_gimple_seq_and_replace_local. 536938fd1498Szrj Using the splay_tree pointed to by ST (which is really a `splay_tree'), 537038fd1498Szrj remaps all local declarations to appropriate replacements in gimple 537138fd1498Szrj statements. */ 537238fd1498Szrj 537338fd1498Szrj static tree 537438fd1498Szrj replace_locals_stmt (gimple_stmt_iterator *gsip, 537538fd1498Szrj bool *handled_ops_p ATTRIBUTE_UNUSED, 537638fd1498Szrj struct walk_stmt_info *wi) 537738fd1498Szrj { 537838fd1498Szrj copy_body_data *id = (copy_body_data *) wi->info; 537938fd1498Szrj gimple *gs = gsi_stmt (*gsip); 538038fd1498Szrj 538138fd1498Szrj if (gbind *stmt = dyn_cast <gbind *> (gs)) 538238fd1498Szrj { 538338fd1498Szrj tree block = gimple_bind_block (stmt); 538438fd1498Szrj 538538fd1498Szrj if (block) 538638fd1498Szrj { 538738fd1498Szrj remap_block (&block, id); 538838fd1498Szrj gimple_bind_set_block (stmt, block); 538938fd1498Szrj } 539038fd1498Szrj 539138fd1498Szrj /* This will remap a lot of the same decls again, but this should be 539238fd1498Szrj harmless. */ 539338fd1498Szrj if (gimple_bind_vars (stmt)) 539438fd1498Szrj { 539538fd1498Szrj tree old_var, decls = gimple_bind_vars (stmt); 539638fd1498Szrj 539738fd1498Szrj for (old_var = decls; old_var; old_var = DECL_CHAIN (old_var)) 539838fd1498Szrj if (!can_be_nonlocal (old_var, id) 539938fd1498Szrj && ! variably_modified_type_p (TREE_TYPE (old_var), id->src_fn)) 540038fd1498Szrj remap_decl (old_var, id); 540138fd1498Szrj 540238fd1498Szrj gcc_checking_assert (!id->prevent_decl_creation_for_types); 540338fd1498Szrj id->prevent_decl_creation_for_types = true; 540438fd1498Szrj gimple_bind_set_vars (stmt, remap_decls (decls, NULL, id)); 540538fd1498Szrj id->prevent_decl_creation_for_types = false; 540638fd1498Szrj } 540738fd1498Szrj } 540838fd1498Szrj 540938fd1498Szrj /* Keep iterating. */ 541038fd1498Szrj return NULL_TREE; 541138fd1498Szrj } 541238fd1498Szrj 541338fd1498Szrj /* Create a copy of SEQ and remap all decls in it. */ 541438fd1498Szrj 541538fd1498Szrj static gimple_seq 541638fd1498Szrj duplicate_remap_omp_clause_seq (gimple_seq seq, struct walk_stmt_info *wi) 541738fd1498Szrj { 541838fd1498Szrj if (!seq) 541938fd1498Szrj return NULL; 542038fd1498Szrj 542138fd1498Szrj /* If there are any labels in OMP sequences, they can be only referred to in 542238fd1498Szrj the sequence itself and therefore we can do both here. */ 542338fd1498Szrj walk_gimple_seq (seq, mark_local_labels_stmt, NULL, wi); 542438fd1498Szrj gimple_seq copy = gimple_seq_copy (seq); 542538fd1498Szrj walk_gimple_seq (copy, replace_locals_stmt, replace_locals_op, wi); 542638fd1498Szrj return copy; 542738fd1498Szrj } 542838fd1498Szrj 542938fd1498Szrj /* Copies everything in SEQ and replaces variables and labels local to 543038fd1498Szrj current_function_decl. */ 543138fd1498Szrj 543238fd1498Szrj gimple_seq 543338fd1498Szrj copy_gimple_seq_and_replace_locals (gimple_seq seq) 543438fd1498Szrj { 543538fd1498Szrj copy_body_data id; 543638fd1498Szrj struct walk_stmt_info wi; 543738fd1498Szrj gimple_seq copy; 543838fd1498Szrj 543938fd1498Szrj /* There's nothing to do for NULL_TREE. */ 544038fd1498Szrj if (seq == NULL) 544138fd1498Szrj return seq; 544238fd1498Szrj 544338fd1498Szrj /* Set up ID. */ 544438fd1498Szrj memset (&id, 0, sizeof (id)); 544538fd1498Szrj id.src_fn = current_function_decl; 544638fd1498Szrj id.dst_fn = current_function_decl; 544738fd1498Szrj id.src_cfun = cfun; 544838fd1498Szrj id.decl_map = new hash_map<tree, tree>; 544938fd1498Szrj id.debug_map = NULL; 545038fd1498Szrj 545138fd1498Szrj id.copy_decl = copy_decl_no_change; 545238fd1498Szrj id.transform_call_graph_edges = CB_CGE_DUPLICATE; 545338fd1498Szrj id.transform_new_cfg = false; 545438fd1498Szrj id.transform_return_to_modify = false; 545538fd1498Szrj id.transform_parameter = false; 545638fd1498Szrj id.transform_lang_insert_block = NULL; 545738fd1498Szrj 545838fd1498Szrj /* Walk the tree once to find local labels. */ 545938fd1498Szrj memset (&wi, 0, sizeof (wi)); 546038fd1498Szrj hash_set<tree> visited; 546138fd1498Szrj wi.info = &id; 546238fd1498Szrj wi.pset = &visited; 546338fd1498Szrj walk_gimple_seq (seq, mark_local_labels_stmt, NULL, &wi); 546438fd1498Szrj 546538fd1498Szrj copy = gimple_seq_copy (seq); 546638fd1498Szrj 546738fd1498Szrj /* Walk the copy, remapping decls. */ 546838fd1498Szrj memset (&wi, 0, sizeof (wi)); 546938fd1498Szrj wi.info = &id; 547038fd1498Szrj walk_gimple_seq (copy, replace_locals_stmt, replace_locals_op, &wi); 547138fd1498Szrj 547238fd1498Szrj /* Clean up. */ 547338fd1498Szrj delete id.decl_map; 547438fd1498Szrj if (id.debug_map) 547538fd1498Szrj delete id.debug_map; 547638fd1498Szrj if (id.dependence_map) 547738fd1498Szrj { 547838fd1498Szrj delete id.dependence_map; 547938fd1498Szrj id.dependence_map = NULL; 548038fd1498Szrj } 548138fd1498Szrj 548238fd1498Szrj return copy; 548338fd1498Szrj } 548438fd1498Szrj 548538fd1498Szrj 548638fd1498Szrj /* Allow someone to determine if SEARCH is a child of TOP from gdb. */ 548738fd1498Szrj 548838fd1498Szrj static tree 548938fd1498Szrj debug_find_tree_1 (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data) 549038fd1498Szrj { 549138fd1498Szrj if (*tp == data) 549238fd1498Szrj return (tree) data; 549338fd1498Szrj else 549438fd1498Szrj return NULL; 549538fd1498Szrj } 549638fd1498Szrj 549738fd1498Szrj DEBUG_FUNCTION bool 549838fd1498Szrj debug_find_tree (tree top, tree search) 549938fd1498Szrj { 550038fd1498Szrj return walk_tree_without_duplicates (&top, debug_find_tree_1, search) != 0; 550138fd1498Szrj } 550238fd1498Szrj 550338fd1498Szrj 550438fd1498Szrj /* Declare the variables created by the inliner. Add all the variables in 550538fd1498Szrj VARS to BIND_EXPR. */ 550638fd1498Szrj 550738fd1498Szrj static void 550838fd1498Szrj declare_inline_vars (tree block, tree vars) 550938fd1498Szrj { 551038fd1498Szrj tree t; 551138fd1498Szrj for (t = vars; t; t = DECL_CHAIN (t)) 551238fd1498Szrj { 551338fd1498Szrj DECL_SEEN_IN_BIND_EXPR_P (t) = 1; 551438fd1498Szrj gcc_assert (!TREE_STATIC (t) && !TREE_ASM_WRITTEN (t)); 551538fd1498Szrj add_local_decl (cfun, t); 551638fd1498Szrj } 551738fd1498Szrj 551838fd1498Szrj if (block) 551938fd1498Szrj BLOCK_VARS (block) = chainon (BLOCK_VARS (block), vars); 552038fd1498Szrj } 552138fd1498Szrj 552238fd1498Szrj /* Copy NODE (which must be a DECL). The DECL originally was in the FROM_FN, 552338fd1498Szrj but now it will be in the TO_FN. PARM_TO_VAR means enable PARM_DECL to 552438fd1498Szrj VAR_DECL translation. */ 552538fd1498Szrj 552638fd1498Szrj tree 552738fd1498Szrj copy_decl_for_dup_finish (copy_body_data *id, tree decl, tree copy) 552838fd1498Szrj { 552938fd1498Szrj /* Don't generate debug information for the copy if we wouldn't have 553038fd1498Szrj generated it for the copy either. */ 553138fd1498Szrj DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (decl); 553238fd1498Szrj DECL_IGNORED_P (copy) = DECL_IGNORED_P (decl); 553338fd1498Szrj 553438fd1498Szrj /* Set the DECL_ABSTRACT_ORIGIN so the debugging routines know what 553538fd1498Szrj declaration inspired this copy. */ 553638fd1498Szrj DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (decl); 553738fd1498Szrj 553838fd1498Szrj /* The new variable/label has no RTL, yet. */ 553938fd1498Szrj if (CODE_CONTAINS_STRUCT (TREE_CODE (copy), TS_DECL_WRTL) 554038fd1498Szrj && !TREE_STATIC (copy) && !DECL_EXTERNAL (copy)) 554138fd1498Szrj SET_DECL_RTL (copy, 0); 554238fd1498Szrj 554338fd1498Szrj /* These args would always appear unused, if not for this. */ 554438fd1498Szrj TREE_USED (copy) = 1; 554538fd1498Szrj 554638fd1498Szrj /* Set the context for the new declaration. */ 554738fd1498Szrj if (!DECL_CONTEXT (decl)) 554838fd1498Szrj /* Globals stay global. */ 554938fd1498Szrj ; 555038fd1498Szrj else if (DECL_CONTEXT (decl) != id->src_fn) 555138fd1498Szrj /* Things that weren't in the scope of the function we're inlining 555238fd1498Szrj from aren't in the scope we're inlining to, either. */ 555338fd1498Szrj ; 555438fd1498Szrj else if (TREE_STATIC (decl)) 555538fd1498Szrj /* Function-scoped static variables should stay in the original 555638fd1498Szrj function. */ 555738fd1498Szrj ; 555838fd1498Szrj else 555938fd1498Szrj { 556038fd1498Szrj /* Ordinary automatic local variables are now in the scope of the 556138fd1498Szrj new function. */ 556238fd1498Szrj DECL_CONTEXT (copy) = id->dst_fn; 556338fd1498Szrj if (VAR_P (copy) && id->dst_simt_vars && !is_gimple_reg (copy)) 556438fd1498Szrj { 556538fd1498Szrj if (!lookup_attribute ("omp simt private", DECL_ATTRIBUTES (copy))) 556638fd1498Szrj DECL_ATTRIBUTES (copy) 556738fd1498Szrj = tree_cons (get_identifier ("omp simt private"), NULL, 556838fd1498Szrj DECL_ATTRIBUTES (copy)); 556938fd1498Szrj id->dst_simt_vars->safe_push (copy); 557038fd1498Szrj } 557138fd1498Szrj } 557238fd1498Szrj 557338fd1498Szrj return copy; 557438fd1498Szrj } 557538fd1498Szrj 557638fd1498Szrj static tree 557738fd1498Szrj copy_decl_to_var (tree decl, copy_body_data *id) 557838fd1498Szrj { 557938fd1498Szrj tree copy, type; 558038fd1498Szrj 558138fd1498Szrj gcc_assert (TREE_CODE (decl) == PARM_DECL 558238fd1498Szrj || TREE_CODE (decl) == RESULT_DECL); 558338fd1498Szrj 558438fd1498Szrj type = TREE_TYPE (decl); 558538fd1498Szrj 558638fd1498Szrj copy = build_decl (DECL_SOURCE_LOCATION (id->dst_fn), 558738fd1498Szrj VAR_DECL, DECL_NAME (decl), type); 558838fd1498Szrj if (DECL_PT_UID_SET_P (decl)) 558938fd1498Szrj SET_DECL_PT_UID (copy, DECL_PT_UID (decl)); 559038fd1498Szrj TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl); 559138fd1498Szrj TREE_READONLY (copy) = TREE_READONLY (decl); 559238fd1498Szrj TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl); 559338fd1498Szrj DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (decl); 559438fd1498Szrj 559538fd1498Szrj return copy_decl_for_dup_finish (id, decl, copy); 559638fd1498Szrj } 559738fd1498Szrj 559838fd1498Szrj /* Like copy_decl_to_var, but create a return slot object instead of a 559938fd1498Szrj pointer variable for return by invisible reference. */ 560038fd1498Szrj 560138fd1498Szrj static tree 560238fd1498Szrj copy_result_decl_to_var (tree decl, copy_body_data *id) 560338fd1498Szrj { 560438fd1498Szrj tree copy, type; 560538fd1498Szrj 560638fd1498Szrj gcc_assert (TREE_CODE (decl) == PARM_DECL 560738fd1498Szrj || TREE_CODE (decl) == RESULT_DECL); 560838fd1498Szrj 560938fd1498Szrj type = TREE_TYPE (decl); 561038fd1498Szrj if (DECL_BY_REFERENCE (decl)) 561138fd1498Szrj type = TREE_TYPE (type); 561238fd1498Szrj 561338fd1498Szrj copy = build_decl (DECL_SOURCE_LOCATION (id->dst_fn), 561438fd1498Szrj VAR_DECL, DECL_NAME (decl), type); 561538fd1498Szrj if (DECL_PT_UID_SET_P (decl)) 561638fd1498Szrj SET_DECL_PT_UID (copy, DECL_PT_UID (decl)); 561738fd1498Szrj TREE_READONLY (copy) = TREE_READONLY (decl); 561838fd1498Szrj TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl); 561938fd1498Szrj if (!DECL_BY_REFERENCE (decl)) 562038fd1498Szrj { 562138fd1498Szrj TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl); 562238fd1498Szrj DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (decl); 562338fd1498Szrj } 562438fd1498Szrj 562538fd1498Szrj return copy_decl_for_dup_finish (id, decl, copy); 562638fd1498Szrj } 562738fd1498Szrj 562838fd1498Szrj tree 562938fd1498Szrj copy_decl_no_change (tree decl, copy_body_data *id) 563038fd1498Szrj { 563138fd1498Szrj tree copy; 563238fd1498Szrj 563338fd1498Szrj copy = copy_node (decl); 563438fd1498Szrj 563538fd1498Szrj /* The COPY is not abstract; it will be generated in DST_FN. */ 563638fd1498Szrj DECL_ABSTRACT_P (copy) = false; 563738fd1498Szrj lang_hooks.dup_lang_specific_decl (copy); 563838fd1498Szrj 563938fd1498Szrj /* TREE_ADDRESSABLE isn't used to indicate that a label's address has 564038fd1498Szrj been taken; it's for internal bookkeeping in expand_goto_internal. */ 564138fd1498Szrj if (TREE_CODE (copy) == LABEL_DECL) 564238fd1498Szrj { 564338fd1498Szrj TREE_ADDRESSABLE (copy) = 0; 564438fd1498Szrj LABEL_DECL_UID (copy) = -1; 564538fd1498Szrj } 564638fd1498Szrj 564738fd1498Szrj return copy_decl_for_dup_finish (id, decl, copy); 564838fd1498Szrj } 564938fd1498Szrj 565038fd1498Szrj static tree 565138fd1498Szrj copy_decl_maybe_to_var (tree decl, copy_body_data *id) 565238fd1498Szrj { 565338fd1498Szrj if (TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == RESULT_DECL) 565438fd1498Szrj return copy_decl_to_var (decl, id); 565538fd1498Szrj else 565638fd1498Szrj return copy_decl_no_change (decl, id); 565738fd1498Szrj } 565838fd1498Szrj 565938fd1498Szrj /* Return a copy of the function's argument tree. */ 566038fd1498Szrj static tree 566138fd1498Szrj copy_arguments_for_versioning (tree orig_parm, copy_body_data * id, 566238fd1498Szrj bitmap args_to_skip, tree *vars) 566338fd1498Szrj { 566438fd1498Szrj tree arg, *parg; 566538fd1498Szrj tree new_parm = NULL; 566638fd1498Szrj int i = 0; 566738fd1498Szrj 566838fd1498Szrj parg = &new_parm; 566938fd1498Szrj 567038fd1498Szrj for (arg = orig_parm; arg; arg = DECL_CHAIN (arg), i++) 567138fd1498Szrj if (!args_to_skip || !bitmap_bit_p (args_to_skip, i)) 567238fd1498Szrj { 567338fd1498Szrj tree new_tree = remap_decl (arg, id); 567438fd1498Szrj if (TREE_CODE (new_tree) != PARM_DECL) 567538fd1498Szrj new_tree = id->copy_decl (arg, id); 567638fd1498Szrj lang_hooks.dup_lang_specific_decl (new_tree); 567738fd1498Szrj *parg = new_tree; 567838fd1498Szrj parg = &DECL_CHAIN (new_tree); 567938fd1498Szrj } 568038fd1498Szrj else if (!id->decl_map->get (arg)) 568138fd1498Szrj { 568238fd1498Szrj /* Make an equivalent VAR_DECL. If the argument was used 568338fd1498Szrj as temporary variable later in function, the uses will be 568438fd1498Szrj replaced by local variable. */ 568538fd1498Szrj tree var = copy_decl_to_var (arg, id); 568638fd1498Szrj insert_decl_map (id, arg, var); 568738fd1498Szrj /* Declare this new variable. */ 568838fd1498Szrj DECL_CHAIN (var) = *vars; 568938fd1498Szrj *vars = var; 569038fd1498Szrj } 569138fd1498Szrj return new_parm; 569238fd1498Szrj } 569338fd1498Szrj 569438fd1498Szrj /* Return a copy of the function's static chain. */ 569538fd1498Szrj static tree 569638fd1498Szrj copy_static_chain (tree static_chain, copy_body_data * id) 569738fd1498Szrj { 569838fd1498Szrj tree *chain_copy, *pvar; 569938fd1498Szrj 570038fd1498Szrj chain_copy = &static_chain; 570138fd1498Szrj for (pvar = chain_copy; *pvar; pvar = &DECL_CHAIN (*pvar)) 570238fd1498Szrj { 570338fd1498Szrj tree new_tree = remap_decl (*pvar, id); 570438fd1498Szrj lang_hooks.dup_lang_specific_decl (new_tree); 570538fd1498Szrj DECL_CHAIN (new_tree) = DECL_CHAIN (*pvar); 570638fd1498Szrj *pvar = new_tree; 570738fd1498Szrj } 570838fd1498Szrj return static_chain; 570938fd1498Szrj } 571038fd1498Szrj 571138fd1498Szrj /* Return true if the function is allowed to be versioned. 571238fd1498Szrj This is a guard for the versioning functionality. */ 571338fd1498Szrj 571438fd1498Szrj bool 571538fd1498Szrj tree_versionable_function_p (tree fndecl) 571638fd1498Szrj { 571738fd1498Szrj return (!lookup_attribute ("noclone", DECL_ATTRIBUTES (fndecl)) 571838fd1498Szrj && copy_forbidden (DECL_STRUCT_FUNCTION (fndecl)) == NULL); 571938fd1498Szrj } 572038fd1498Szrj 572138fd1498Szrj /* Delete all unreachable basic blocks and update callgraph. 572238fd1498Szrj Doing so is somewhat nontrivial because we need to update all clones and 572338fd1498Szrj remove inline function that become unreachable. */ 572438fd1498Szrj 572538fd1498Szrj static bool 572638fd1498Szrj delete_unreachable_blocks_update_callgraph (copy_body_data *id) 572738fd1498Szrj { 572838fd1498Szrj bool changed = false; 572938fd1498Szrj basic_block b, next_bb; 573038fd1498Szrj 573138fd1498Szrj find_unreachable_blocks (); 573238fd1498Szrj 573338fd1498Szrj /* Delete all unreachable basic blocks. */ 573438fd1498Szrj 573538fd1498Szrj for (b = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb; b 573638fd1498Szrj != EXIT_BLOCK_PTR_FOR_FN (cfun); b = next_bb) 573738fd1498Szrj { 573838fd1498Szrj next_bb = b->next_bb; 573938fd1498Szrj 574038fd1498Szrj if (!(b->flags & BB_REACHABLE)) 574138fd1498Szrj { 574238fd1498Szrj gimple_stmt_iterator bsi; 574338fd1498Szrj 574438fd1498Szrj for (bsi = gsi_start_bb (b); !gsi_end_p (bsi); gsi_next (&bsi)) 574538fd1498Szrj { 574638fd1498Szrj struct cgraph_edge *e; 574738fd1498Szrj struct cgraph_node *node; 574838fd1498Szrj 574938fd1498Szrj id->dst_node->remove_stmt_references (gsi_stmt (bsi)); 575038fd1498Szrj 575138fd1498Szrj if (gimple_code (gsi_stmt (bsi)) == GIMPLE_CALL 575238fd1498Szrj &&(e = id->dst_node->get_edge (gsi_stmt (bsi))) != NULL) 575338fd1498Szrj { 575438fd1498Szrj if (!e->inline_failed) 575538fd1498Szrj e->callee->remove_symbol_and_inline_clones (id->dst_node); 575638fd1498Szrj else 575738fd1498Szrj e->remove (); 575838fd1498Szrj } 575938fd1498Szrj if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES 576038fd1498Szrj && id->dst_node->clones) 576138fd1498Szrj for (node = id->dst_node->clones; node != id->dst_node;) 576238fd1498Szrj { 576338fd1498Szrj node->remove_stmt_references (gsi_stmt (bsi)); 576438fd1498Szrj if (gimple_code (gsi_stmt (bsi)) == GIMPLE_CALL 576538fd1498Szrj && (e = node->get_edge (gsi_stmt (bsi))) != NULL) 576638fd1498Szrj { 576738fd1498Szrj if (!e->inline_failed) 576838fd1498Szrj e->callee->remove_symbol_and_inline_clones (id->dst_node); 576938fd1498Szrj else 577038fd1498Szrj e->remove (); 577138fd1498Szrj } 577238fd1498Szrj 577338fd1498Szrj if (node->clones) 577438fd1498Szrj node = node->clones; 577538fd1498Szrj else if (node->next_sibling_clone) 577638fd1498Szrj node = node->next_sibling_clone; 577738fd1498Szrj else 577838fd1498Szrj { 577938fd1498Szrj while (node != id->dst_node && !node->next_sibling_clone) 578038fd1498Szrj node = node->clone_of; 578138fd1498Szrj if (node != id->dst_node) 578238fd1498Szrj node = node->next_sibling_clone; 578338fd1498Szrj } 578438fd1498Szrj } 578538fd1498Szrj } 578638fd1498Szrj delete_basic_block (b); 578738fd1498Szrj changed = true; 578838fd1498Szrj } 578938fd1498Szrj } 579038fd1498Szrj 579138fd1498Szrj return changed; 579238fd1498Szrj } 579338fd1498Szrj 579438fd1498Szrj /* Update clone info after duplication. */ 579538fd1498Szrj 579638fd1498Szrj static void 579738fd1498Szrj update_clone_info (copy_body_data * id) 579838fd1498Szrj { 579938fd1498Szrj struct cgraph_node *node; 580038fd1498Szrj if (!id->dst_node->clones) 580138fd1498Szrj return; 580238fd1498Szrj for (node = id->dst_node->clones; node != id->dst_node;) 580338fd1498Szrj { 580438fd1498Szrj /* First update replace maps to match the new body. */ 580538fd1498Szrj if (node->clone.tree_map) 580638fd1498Szrj { 580738fd1498Szrj unsigned int i; 580838fd1498Szrj for (i = 0; i < vec_safe_length (node->clone.tree_map); i++) 580938fd1498Szrj { 581038fd1498Szrj struct ipa_replace_map *replace_info; 581138fd1498Szrj replace_info = (*node->clone.tree_map)[i]; 581238fd1498Szrj walk_tree (&replace_info->old_tree, copy_tree_body_r, id, NULL); 581338fd1498Szrj walk_tree (&replace_info->new_tree, copy_tree_body_r, id, NULL); 581438fd1498Szrj } 581538fd1498Szrj } 581638fd1498Szrj if (node->clones) 581738fd1498Szrj node = node->clones; 581838fd1498Szrj else if (node->next_sibling_clone) 581938fd1498Szrj node = node->next_sibling_clone; 582038fd1498Szrj else 582138fd1498Szrj { 582238fd1498Szrj while (node != id->dst_node && !node->next_sibling_clone) 582338fd1498Szrj node = node->clone_of; 582438fd1498Szrj if (node != id->dst_node) 582538fd1498Szrj node = node->next_sibling_clone; 582638fd1498Szrj } 582738fd1498Szrj } 582838fd1498Szrj } 582938fd1498Szrj 583038fd1498Szrj /* Create a copy of a function's tree. 583138fd1498Szrj OLD_DECL and NEW_DECL are FUNCTION_DECL tree nodes 583238fd1498Szrj of the original function and the new copied function 583338fd1498Szrj respectively. In case we want to replace a DECL 583438fd1498Szrj tree with another tree while duplicating the function's 583538fd1498Szrj body, TREE_MAP represents the mapping between these 583638fd1498Szrj trees. If UPDATE_CLONES is set, the call_stmt fields 583738fd1498Szrj of edges of clones of the function will be updated. 583838fd1498Szrj 583938fd1498Szrj If non-NULL ARGS_TO_SKIP determine function parameters to remove 584038fd1498Szrj from new version. 584138fd1498Szrj If SKIP_RETURN is true, the new version will return void. 584238fd1498Szrj If non-NULL BLOCK_TO_COPY determine what basic blocks to copy. 584338fd1498Szrj If non_NULL NEW_ENTRY determine new entry BB of the clone. 584438fd1498Szrj */ 584538fd1498Szrj void 584638fd1498Szrj tree_function_versioning (tree old_decl, tree new_decl, 584738fd1498Szrj vec<ipa_replace_map *, va_gc> *tree_map, 584838fd1498Szrj bool update_clones, bitmap args_to_skip, 584938fd1498Szrj bool skip_return, bitmap blocks_to_copy, 585038fd1498Szrj basic_block new_entry) 585138fd1498Szrj { 585238fd1498Szrj struct cgraph_node *old_version_node; 585338fd1498Szrj struct cgraph_node *new_version_node; 585438fd1498Szrj copy_body_data id; 585538fd1498Szrj tree p; 585638fd1498Szrj unsigned i; 585738fd1498Szrj struct ipa_replace_map *replace_info; 585838fd1498Szrj basic_block old_entry_block, bb; 585938fd1498Szrj auto_vec<gimple *, 10> init_stmts; 586038fd1498Szrj tree vars = NULL_TREE; 586138fd1498Szrj bitmap debug_args_to_skip = args_to_skip; 586238fd1498Szrj 586338fd1498Szrj gcc_assert (TREE_CODE (old_decl) == FUNCTION_DECL 586438fd1498Szrj && TREE_CODE (new_decl) == FUNCTION_DECL); 586538fd1498Szrj DECL_POSSIBLY_INLINED (old_decl) = 1; 586638fd1498Szrj 586738fd1498Szrj old_version_node = cgraph_node::get (old_decl); 586838fd1498Szrj gcc_checking_assert (old_version_node); 586938fd1498Szrj new_version_node = cgraph_node::get (new_decl); 587038fd1498Szrj gcc_checking_assert (new_version_node); 587138fd1498Szrj 587238fd1498Szrj /* Copy over debug args. */ 587338fd1498Szrj if (DECL_HAS_DEBUG_ARGS_P (old_decl)) 587438fd1498Szrj { 587538fd1498Szrj vec<tree, va_gc> **new_debug_args, **old_debug_args; 587638fd1498Szrj gcc_checking_assert (decl_debug_args_lookup (new_decl) == NULL); 587738fd1498Szrj DECL_HAS_DEBUG_ARGS_P (new_decl) = 0; 587838fd1498Szrj old_debug_args = decl_debug_args_lookup (old_decl); 587938fd1498Szrj if (old_debug_args) 588038fd1498Szrj { 588138fd1498Szrj new_debug_args = decl_debug_args_insert (new_decl); 588238fd1498Szrj *new_debug_args = vec_safe_copy (*old_debug_args); 588338fd1498Szrj } 588438fd1498Szrj } 588538fd1498Szrj 588638fd1498Szrj /* Output the inlining info for this abstract function, since it has been 588738fd1498Szrj inlined. If we don't do this now, we can lose the information about the 588838fd1498Szrj variables in the function when the blocks get blown away as soon as we 588938fd1498Szrj remove the cgraph node. */ 589038fd1498Szrj (*debug_hooks->outlining_inline_function) (old_decl); 589138fd1498Szrj 589238fd1498Szrj DECL_ARTIFICIAL (new_decl) = 1; 589338fd1498Szrj DECL_ABSTRACT_ORIGIN (new_decl) = DECL_ORIGIN (old_decl); 589438fd1498Szrj if (DECL_ORIGIN (old_decl) == old_decl) 589538fd1498Szrj old_version_node->used_as_abstract_origin = true; 589638fd1498Szrj DECL_FUNCTION_PERSONALITY (new_decl) = DECL_FUNCTION_PERSONALITY (old_decl); 589738fd1498Szrj 589838fd1498Szrj /* Prepare the data structures for the tree copy. */ 589938fd1498Szrj memset (&id, 0, sizeof (id)); 590038fd1498Szrj 590138fd1498Szrj /* Generate a new name for the new version. */ 590238fd1498Szrj id.statements_to_fold = new hash_set<gimple *>; 590338fd1498Szrj 590438fd1498Szrj id.decl_map = new hash_map<tree, tree>; 590538fd1498Szrj id.debug_map = NULL; 590638fd1498Szrj id.src_fn = old_decl; 590738fd1498Szrj id.dst_fn = new_decl; 590838fd1498Szrj id.src_node = old_version_node; 590938fd1498Szrj id.dst_node = new_version_node; 591038fd1498Szrj id.src_cfun = DECL_STRUCT_FUNCTION (old_decl); 591138fd1498Szrj id.blocks_to_copy = blocks_to_copy; 591238fd1498Szrj 591338fd1498Szrj id.copy_decl = copy_decl_no_change; 591438fd1498Szrj id.transform_call_graph_edges 591538fd1498Szrj = update_clones ? CB_CGE_MOVE_CLONES : CB_CGE_MOVE; 591638fd1498Szrj id.transform_new_cfg = true; 591738fd1498Szrj id.transform_return_to_modify = false; 591838fd1498Szrj id.transform_parameter = false; 591938fd1498Szrj id.transform_lang_insert_block = NULL; 592038fd1498Szrj 592138fd1498Szrj old_entry_block = ENTRY_BLOCK_PTR_FOR_FN 592238fd1498Szrj (DECL_STRUCT_FUNCTION (old_decl)); 592338fd1498Szrj DECL_RESULT (new_decl) = DECL_RESULT (old_decl); 592438fd1498Szrj DECL_ARGUMENTS (new_decl) = DECL_ARGUMENTS (old_decl); 592538fd1498Szrj initialize_cfun (new_decl, old_decl, 592638fd1498Szrj new_entry ? new_entry->count : old_entry_block->count); 592738fd1498Szrj if (DECL_STRUCT_FUNCTION (new_decl)->gimple_df) 592838fd1498Szrj DECL_STRUCT_FUNCTION (new_decl)->gimple_df->ipa_pta 592938fd1498Szrj = id.src_cfun->gimple_df->ipa_pta; 593038fd1498Szrj 593138fd1498Szrj /* Copy the function's static chain. */ 593238fd1498Szrj p = DECL_STRUCT_FUNCTION (old_decl)->static_chain_decl; 593338fd1498Szrj if (p) 593438fd1498Szrj DECL_STRUCT_FUNCTION (new_decl)->static_chain_decl 593538fd1498Szrj = copy_static_chain (p, &id); 593638fd1498Szrj 593738fd1498Szrj /* If there's a tree_map, prepare for substitution. */ 593838fd1498Szrj if (tree_map) 593938fd1498Szrj for (i = 0; i < tree_map->length (); i++) 594038fd1498Szrj { 594138fd1498Szrj gimple *init; 594238fd1498Szrj replace_info = (*tree_map)[i]; 594338fd1498Szrj if (replace_info->replace_p) 594438fd1498Szrj { 594538fd1498Szrj int parm_num = -1; 594638fd1498Szrj if (!replace_info->old_tree) 594738fd1498Szrj { 594838fd1498Szrj int p = replace_info->parm_num; 594938fd1498Szrj tree parm; 595038fd1498Szrj tree req_type, new_type; 595138fd1498Szrj 595238fd1498Szrj for (parm = DECL_ARGUMENTS (old_decl); p; 595338fd1498Szrj parm = DECL_CHAIN (parm)) 595438fd1498Szrj p--; 595538fd1498Szrj replace_info->old_tree = parm; 595638fd1498Szrj parm_num = replace_info->parm_num; 595738fd1498Szrj req_type = TREE_TYPE (parm); 595838fd1498Szrj new_type = TREE_TYPE (replace_info->new_tree); 595938fd1498Szrj if (!useless_type_conversion_p (req_type, new_type)) 596038fd1498Szrj { 596138fd1498Szrj if (fold_convertible_p (req_type, replace_info->new_tree)) 596238fd1498Szrj replace_info->new_tree 596338fd1498Szrj = fold_build1 (NOP_EXPR, req_type, 596438fd1498Szrj replace_info->new_tree); 596538fd1498Szrj else if (TYPE_SIZE (req_type) == TYPE_SIZE (new_type)) 596638fd1498Szrj replace_info->new_tree 596738fd1498Szrj = fold_build1 (VIEW_CONVERT_EXPR, req_type, 596838fd1498Szrj replace_info->new_tree); 596938fd1498Szrj else 597038fd1498Szrj { 597138fd1498Szrj if (dump_file) 597238fd1498Szrj { 597338fd1498Szrj fprintf (dump_file, " const "); 597438fd1498Szrj print_generic_expr (dump_file, 597538fd1498Szrj replace_info->new_tree); 597638fd1498Szrj fprintf (dump_file, 597738fd1498Szrj " can't be converted to param "); 597838fd1498Szrj print_generic_expr (dump_file, parm); 597938fd1498Szrj fprintf (dump_file, "\n"); 598038fd1498Szrj } 598138fd1498Szrj replace_info->old_tree = NULL; 598238fd1498Szrj } 598338fd1498Szrj } 598438fd1498Szrj } 598538fd1498Szrj else 598638fd1498Szrj gcc_assert (TREE_CODE (replace_info->old_tree) == PARM_DECL); 598738fd1498Szrj if (replace_info->old_tree) 598838fd1498Szrj { 598938fd1498Szrj init = setup_one_parameter (&id, replace_info->old_tree, 599038fd1498Szrj replace_info->new_tree, id.src_fn, 599138fd1498Szrj NULL, 599238fd1498Szrj &vars); 599338fd1498Szrj if (init) 599438fd1498Szrj init_stmts.safe_push (init); 599538fd1498Szrj if (MAY_HAVE_DEBUG_BIND_STMTS && args_to_skip) 599638fd1498Szrj { 599738fd1498Szrj if (parm_num == -1) 599838fd1498Szrj { 599938fd1498Szrj tree parm; 600038fd1498Szrj int p; 600138fd1498Szrj for (parm = DECL_ARGUMENTS (old_decl), p = 0; parm; 600238fd1498Szrj parm = DECL_CHAIN (parm), p++) 600338fd1498Szrj if (parm == replace_info->old_tree) 600438fd1498Szrj { 600538fd1498Szrj parm_num = p; 600638fd1498Szrj break; 600738fd1498Szrj } 600838fd1498Szrj } 600938fd1498Szrj if (parm_num != -1) 601038fd1498Szrj { 601138fd1498Szrj if (debug_args_to_skip == args_to_skip) 601238fd1498Szrj { 601338fd1498Szrj debug_args_to_skip = BITMAP_ALLOC (NULL); 601438fd1498Szrj bitmap_copy (debug_args_to_skip, args_to_skip); 601538fd1498Szrj } 601638fd1498Szrj bitmap_clear_bit (debug_args_to_skip, parm_num); 601738fd1498Szrj } 601838fd1498Szrj } 601938fd1498Szrj } 602038fd1498Szrj } 602138fd1498Szrj } 602238fd1498Szrj /* Copy the function's arguments. */ 602338fd1498Szrj if (DECL_ARGUMENTS (old_decl) != NULL_TREE) 602438fd1498Szrj DECL_ARGUMENTS (new_decl) 602538fd1498Szrj = copy_arguments_for_versioning (DECL_ARGUMENTS (old_decl), &id, 602638fd1498Szrj args_to_skip, &vars); 602738fd1498Szrj 602838fd1498Szrj DECL_INITIAL (new_decl) = remap_blocks (DECL_INITIAL (id.src_fn), &id); 602938fd1498Szrj BLOCK_SUPERCONTEXT (DECL_INITIAL (new_decl)) = new_decl; 603038fd1498Szrj 603138fd1498Szrj declare_inline_vars (DECL_INITIAL (new_decl), vars); 603238fd1498Szrj 603338fd1498Szrj if (!vec_safe_is_empty (DECL_STRUCT_FUNCTION (old_decl)->local_decls)) 603438fd1498Szrj /* Add local vars. */ 603538fd1498Szrj add_local_variables (DECL_STRUCT_FUNCTION (old_decl), cfun, &id); 603638fd1498Szrj 603738fd1498Szrj if (DECL_RESULT (old_decl) == NULL_TREE) 603838fd1498Szrj ; 603938fd1498Szrj else if (skip_return && !VOID_TYPE_P (TREE_TYPE (DECL_RESULT (old_decl)))) 604038fd1498Szrj { 604138fd1498Szrj DECL_RESULT (new_decl) 604238fd1498Szrj = build_decl (DECL_SOURCE_LOCATION (DECL_RESULT (old_decl)), 604338fd1498Szrj RESULT_DECL, NULL_TREE, void_type_node); 604438fd1498Szrj DECL_CONTEXT (DECL_RESULT (new_decl)) = new_decl; 604538fd1498Szrj cfun->returns_struct = 0; 604638fd1498Szrj cfun->returns_pcc_struct = 0; 604738fd1498Szrj } 604838fd1498Szrj else 604938fd1498Szrj { 605038fd1498Szrj tree old_name; 605138fd1498Szrj DECL_RESULT (new_decl) = remap_decl (DECL_RESULT (old_decl), &id); 605238fd1498Szrj lang_hooks.dup_lang_specific_decl (DECL_RESULT (new_decl)); 605338fd1498Szrj if (gimple_in_ssa_p (id.src_cfun) 605438fd1498Szrj && DECL_BY_REFERENCE (DECL_RESULT (old_decl)) 605538fd1498Szrj && (old_name = ssa_default_def (id.src_cfun, DECL_RESULT (old_decl)))) 605638fd1498Szrj { 605738fd1498Szrj tree new_name = make_ssa_name (DECL_RESULT (new_decl)); 605838fd1498Szrj insert_decl_map (&id, old_name, new_name); 605938fd1498Szrj SSA_NAME_DEF_STMT (new_name) = gimple_build_nop (); 606038fd1498Szrj set_ssa_default_def (cfun, DECL_RESULT (new_decl), new_name); 606138fd1498Szrj } 606238fd1498Szrj } 606338fd1498Szrj 606438fd1498Szrj /* Set up the destination functions loop tree. */ 606538fd1498Szrj if (loops_for_fn (DECL_STRUCT_FUNCTION (old_decl)) != NULL) 606638fd1498Szrj { 606738fd1498Szrj cfun->curr_properties &= ~PROP_loops; 606838fd1498Szrj loop_optimizer_init (AVOID_CFG_MODIFICATIONS); 606938fd1498Szrj cfun->curr_properties |= PROP_loops; 607038fd1498Szrj } 607138fd1498Szrj 607238fd1498Szrj /* Copy the Function's body. */ 607338fd1498Szrj copy_body (&id, ENTRY_BLOCK_PTR_FOR_FN (cfun), EXIT_BLOCK_PTR_FOR_FN (cfun), 607438fd1498Szrj new_entry); 607538fd1498Szrj 607638fd1498Szrj /* Renumber the lexical scoping (non-code) blocks consecutively. */ 607738fd1498Szrj number_blocks (new_decl); 607838fd1498Szrj 607938fd1498Szrj /* We want to create the BB unconditionally, so that the addition of 608038fd1498Szrj debug stmts doesn't affect BB count, which may in the end cause 608138fd1498Szrj codegen differences. */ 608238fd1498Szrj bb = split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun))); 608338fd1498Szrj while (init_stmts.length ()) 608438fd1498Szrj insert_init_stmt (&id, bb, init_stmts.pop ()); 608538fd1498Szrj update_clone_info (&id); 608638fd1498Szrj 608738fd1498Szrj /* Remap the nonlocal_goto_save_area, if any. */ 608838fd1498Szrj if (cfun->nonlocal_goto_save_area) 608938fd1498Szrj { 609038fd1498Szrj struct walk_stmt_info wi; 609138fd1498Szrj 609238fd1498Szrj memset (&wi, 0, sizeof (wi)); 609338fd1498Szrj wi.info = &id; 609438fd1498Szrj walk_tree (&cfun->nonlocal_goto_save_area, remap_gimple_op_r, &wi, NULL); 609538fd1498Szrj } 609638fd1498Szrj 609738fd1498Szrj /* Clean up. */ 609838fd1498Szrj delete id.decl_map; 609938fd1498Szrj if (id.debug_map) 610038fd1498Szrj delete id.debug_map; 610138fd1498Szrj free_dominance_info (CDI_DOMINATORS); 610238fd1498Szrj free_dominance_info (CDI_POST_DOMINATORS); 610338fd1498Szrj 610438fd1498Szrj update_max_bb_count (); 610538fd1498Szrj fold_marked_statements (0, id.statements_to_fold); 610638fd1498Szrj delete id.statements_to_fold; 610738fd1498Szrj delete_unreachable_blocks_update_callgraph (&id); 610838fd1498Szrj if (id.dst_node->definition) 610938fd1498Szrj cgraph_edge::rebuild_references (); 611038fd1498Szrj if (loops_state_satisfies_p (LOOPS_NEED_FIXUP)) 611138fd1498Szrj { 611238fd1498Szrj calculate_dominance_info (CDI_DOMINATORS); 611338fd1498Szrj fix_loop_structure (NULL); 611438fd1498Szrj } 611538fd1498Szrj update_ssa (TODO_update_ssa); 611638fd1498Szrj 611738fd1498Szrj /* After partial cloning we need to rescale frequencies, so they are 611838fd1498Szrj within proper range in the cloned function. */ 611938fd1498Szrj if (new_entry) 612038fd1498Szrj { 612138fd1498Szrj struct cgraph_edge *e; 612238fd1498Szrj rebuild_frequencies (); 612338fd1498Szrj 612438fd1498Szrj new_version_node->count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count; 612538fd1498Szrj for (e = new_version_node->callees; e; e = e->next_callee) 612638fd1498Szrj { 612738fd1498Szrj basic_block bb = gimple_bb (e->call_stmt); 612838fd1498Szrj e->count = bb->count; 612938fd1498Szrj } 613038fd1498Szrj for (e = new_version_node->indirect_calls; e; e = e->next_callee) 613138fd1498Szrj { 613238fd1498Szrj basic_block bb = gimple_bb (e->call_stmt); 613338fd1498Szrj e->count = bb->count; 613438fd1498Szrj } 613538fd1498Szrj } 613638fd1498Szrj 613738fd1498Szrj if (debug_args_to_skip && MAY_HAVE_DEBUG_BIND_STMTS) 613838fd1498Szrj { 613938fd1498Szrj tree parm; 614038fd1498Szrj vec<tree, va_gc> **debug_args = NULL; 614138fd1498Szrj unsigned int len = 0; 614238fd1498Szrj for (parm = DECL_ARGUMENTS (old_decl), i = 0; 614338fd1498Szrj parm; parm = DECL_CHAIN (parm), i++) 614438fd1498Szrj if (bitmap_bit_p (debug_args_to_skip, i) && is_gimple_reg (parm)) 614538fd1498Szrj { 614638fd1498Szrj tree ddecl; 614738fd1498Szrj 614838fd1498Szrj if (debug_args == NULL) 614938fd1498Szrj { 615038fd1498Szrj debug_args = decl_debug_args_insert (new_decl); 615138fd1498Szrj len = vec_safe_length (*debug_args); 615238fd1498Szrj } 615338fd1498Szrj ddecl = make_node (DEBUG_EXPR_DECL); 615438fd1498Szrj DECL_ARTIFICIAL (ddecl) = 1; 615538fd1498Szrj TREE_TYPE (ddecl) = TREE_TYPE (parm); 615638fd1498Szrj SET_DECL_MODE (ddecl, DECL_MODE (parm)); 615738fd1498Szrj vec_safe_push (*debug_args, DECL_ORIGIN (parm)); 615838fd1498Szrj vec_safe_push (*debug_args, ddecl); 615938fd1498Szrj } 616038fd1498Szrj if (debug_args != NULL) 616138fd1498Szrj { 616238fd1498Szrj /* On the callee side, add 616338fd1498Szrj DEBUG D#Y s=> parm 616438fd1498Szrj DEBUG var => D#Y 616538fd1498Szrj stmts to the first bb where var is a VAR_DECL created for the 616638fd1498Szrj optimized away parameter in DECL_INITIAL block. This hints 616738fd1498Szrj in the debug info that var (whole DECL_ORIGIN is the parm 616838fd1498Szrj PARM_DECL) is optimized away, but could be looked up at the 616938fd1498Szrj call site as value of D#X there. */ 617038fd1498Szrj tree var = vars, vexpr; 617138fd1498Szrj gimple_stmt_iterator cgsi 617238fd1498Szrj = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun))); 617338fd1498Szrj gimple *def_temp; 617438fd1498Szrj var = vars; 617538fd1498Szrj i = vec_safe_length (*debug_args); 617638fd1498Szrj do 617738fd1498Szrj { 617838fd1498Szrj i -= 2; 617938fd1498Szrj while (var != NULL_TREE 618038fd1498Szrj && DECL_ABSTRACT_ORIGIN (var) != (**debug_args)[i]) 618138fd1498Szrj var = TREE_CHAIN (var); 618238fd1498Szrj if (var == NULL_TREE) 618338fd1498Szrj break; 618438fd1498Szrj vexpr = make_node (DEBUG_EXPR_DECL); 618538fd1498Szrj parm = (**debug_args)[i]; 618638fd1498Szrj DECL_ARTIFICIAL (vexpr) = 1; 618738fd1498Szrj TREE_TYPE (vexpr) = TREE_TYPE (parm); 618838fd1498Szrj SET_DECL_MODE (vexpr, DECL_MODE (parm)); 618938fd1498Szrj def_temp = gimple_build_debug_bind (var, vexpr, NULL); 619038fd1498Szrj gsi_insert_before (&cgsi, def_temp, GSI_NEW_STMT); 619138fd1498Szrj def_temp = gimple_build_debug_source_bind (vexpr, parm, NULL); 619238fd1498Szrj gsi_insert_before (&cgsi, def_temp, GSI_NEW_STMT); 619338fd1498Szrj } 619438fd1498Szrj while (i > len); 619538fd1498Szrj } 619638fd1498Szrj } 619738fd1498Szrj 619838fd1498Szrj if (debug_args_to_skip && debug_args_to_skip != args_to_skip) 619938fd1498Szrj BITMAP_FREE (debug_args_to_skip); 620038fd1498Szrj free_dominance_info (CDI_DOMINATORS); 620138fd1498Szrj free_dominance_info (CDI_POST_DOMINATORS); 620238fd1498Szrj 620338fd1498Szrj gcc_assert (!id.debug_stmts.exists ()); 620438fd1498Szrj pop_cfun (); 620538fd1498Szrj return; 620638fd1498Szrj } 620738fd1498Szrj 620838fd1498Szrj /* EXP is CALL_EXPR present in a GENERIC expression tree. Try to integrate 620938fd1498Szrj the callee and return the inlined body on success. */ 621038fd1498Szrj 621138fd1498Szrj tree 621238fd1498Szrj maybe_inline_call_in_expr (tree exp) 621338fd1498Szrj { 621438fd1498Szrj tree fn = get_callee_fndecl (exp); 621538fd1498Szrj 621638fd1498Szrj /* We can only try to inline "const" functions. */ 621738fd1498Szrj if (fn && TREE_READONLY (fn) && DECL_SAVED_TREE (fn)) 621838fd1498Szrj { 621938fd1498Szrj call_expr_arg_iterator iter; 622038fd1498Szrj copy_body_data id; 622138fd1498Szrj tree param, arg, t; 622238fd1498Szrj hash_map<tree, tree> decl_map; 622338fd1498Szrj 622438fd1498Szrj /* Remap the parameters. */ 622538fd1498Szrj for (param = DECL_ARGUMENTS (fn), arg = first_call_expr_arg (exp, &iter); 622638fd1498Szrj param; 622738fd1498Szrj param = DECL_CHAIN (param), arg = next_call_expr_arg (&iter)) 622838fd1498Szrj decl_map.put (param, arg); 622938fd1498Szrj 623038fd1498Szrj memset (&id, 0, sizeof (id)); 623138fd1498Szrj id.src_fn = fn; 623238fd1498Szrj id.dst_fn = current_function_decl; 623338fd1498Szrj id.src_cfun = DECL_STRUCT_FUNCTION (fn); 623438fd1498Szrj id.decl_map = &decl_map; 623538fd1498Szrj 623638fd1498Szrj id.copy_decl = copy_decl_no_change; 623738fd1498Szrj id.transform_call_graph_edges = CB_CGE_DUPLICATE; 623838fd1498Szrj id.transform_new_cfg = false; 623938fd1498Szrj id.transform_return_to_modify = true; 624038fd1498Szrj id.transform_parameter = true; 624138fd1498Szrj id.transform_lang_insert_block = NULL; 624238fd1498Szrj 624338fd1498Szrj /* Make sure not to unshare trees behind the front-end's back 624438fd1498Szrj since front-end specific mechanisms may rely on sharing. */ 624538fd1498Szrj id.regimplify = false; 624638fd1498Szrj id.do_not_unshare = true; 624738fd1498Szrj 624838fd1498Szrj /* We're not inside any EH region. */ 624938fd1498Szrj id.eh_lp_nr = 0; 625038fd1498Szrj 625138fd1498Szrj t = copy_tree_body (&id); 625238fd1498Szrj 625338fd1498Szrj /* We can only return something suitable for use in a GENERIC 625438fd1498Szrj expression tree. */ 625538fd1498Szrj if (TREE_CODE (t) == MODIFY_EXPR) 625638fd1498Szrj return TREE_OPERAND (t, 1); 625738fd1498Szrj } 625838fd1498Szrj 625938fd1498Szrj return NULL_TREE; 626038fd1498Szrj } 626138fd1498Szrj 626238fd1498Szrj /* Duplicate a type, fields and all. */ 626338fd1498Szrj 626438fd1498Szrj tree 626538fd1498Szrj build_duplicate_type (tree type) 626638fd1498Szrj { 626738fd1498Szrj struct copy_body_data id; 626838fd1498Szrj 626938fd1498Szrj memset (&id, 0, sizeof (id)); 627038fd1498Szrj id.src_fn = current_function_decl; 627138fd1498Szrj id.dst_fn = current_function_decl; 627238fd1498Szrj id.src_cfun = cfun; 627338fd1498Szrj id.decl_map = new hash_map<tree, tree>; 627438fd1498Szrj id.debug_map = NULL; 627538fd1498Szrj id.copy_decl = copy_decl_no_change; 627638fd1498Szrj 627738fd1498Szrj type = remap_type_1 (type, &id); 627838fd1498Szrj 627938fd1498Szrj delete id.decl_map; 628038fd1498Szrj if (id.debug_map) 628138fd1498Szrj delete id.debug_map; 628238fd1498Szrj 628338fd1498Szrj TYPE_CANONICAL (type) = type; 628438fd1498Szrj 628538fd1498Szrj return type; 628638fd1498Szrj } 628738fd1498Szrj 628838fd1498Szrj /* Unshare the entire DECL_SAVED_TREE of FN and return the remapped 628938fd1498Szrj parameters and RESULT_DECL in PARMS and RESULT. Used by C++ constexpr 629038fd1498Szrj evaluation. */ 629138fd1498Szrj 629238fd1498Szrj tree 629338fd1498Szrj copy_fn (tree fn, tree& parms, tree& result) 629438fd1498Szrj { 629538fd1498Szrj copy_body_data id; 629638fd1498Szrj tree param; 629738fd1498Szrj hash_map<tree, tree> decl_map; 629838fd1498Szrj 629938fd1498Szrj tree *p = &parms; 630038fd1498Szrj *p = NULL_TREE; 630138fd1498Szrj 630238fd1498Szrj memset (&id, 0, sizeof (id)); 630338fd1498Szrj id.src_fn = fn; 630438fd1498Szrj id.dst_fn = current_function_decl; 630538fd1498Szrj id.src_cfun = DECL_STRUCT_FUNCTION (fn); 630638fd1498Szrj id.decl_map = &decl_map; 630738fd1498Szrj 630838fd1498Szrj id.copy_decl = copy_decl_no_change; 630938fd1498Szrj id.transform_call_graph_edges = CB_CGE_DUPLICATE; 631038fd1498Szrj id.transform_new_cfg = false; 631138fd1498Szrj id.transform_return_to_modify = false; 631238fd1498Szrj id.transform_parameter = true; 631338fd1498Szrj id.transform_lang_insert_block = NULL; 631438fd1498Szrj 631538fd1498Szrj /* Make sure not to unshare trees behind the front-end's back 631638fd1498Szrj since front-end specific mechanisms may rely on sharing. */ 631738fd1498Szrj id.regimplify = false; 631838fd1498Szrj id.do_not_unshare = true; 631938fd1498Szrj 632038fd1498Szrj /* We're not inside any EH region. */ 632138fd1498Szrj id.eh_lp_nr = 0; 632238fd1498Szrj 632338fd1498Szrj /* Remap the parameters and result and return them to the caller. */ 632438fd1498Szrj for (param = DECL_ARGUMENTS (fn); 632538fd1498Szrj param; 632638fd1498Szrj param = DECL_CHAIN (param)) 632738fd1498Szrj { 632838fd1498Szrj *p = remap_decl (param, &id); 632938fd1498Szrj p = &DECL_CHAIN (*p); 633038fd1498Szrj } 633138fd1498Szrj 633238fd1498Szrj if (DECL_RESULT (fn)) 633338fd1498Szrj result = remap_decl (DECL_RESULT (fn), &id); 633438fd1498Szrj else 633538fd1498Szrj result = NULL_TREE; 633638fd1498Szrj 633738fd1498Szrj return copy_tree_body (&id); 633838fd1498Szrj } 6339