1e4b17023SJohn Marino /* Tree inlining. 2e4b17023SJohn Marino Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 3e4b17023SJohn Marino 2012 Free Software Foundation, Inc. 4e4b17023SJohn Marino Contributed by Alexandre Oliva <aoliva@redhat.com> 5e4b17023SJohn Marino 6e4b17023SJohn Marino This file is part of GCC. 7e4b17023SJohn Marino 8e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify 9e4b17023SJohn Marino it under the terms of the GNU General Public License as published by 10e4b17023SJohn Marino the Free Software Foundation; either version 3, or (at your option) 11e4b17023SJohn Marino any later version. 12e4b17023SJohn Marino 13e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, 14e4b17023SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of 15e4b17023SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16e4b17023SJohn Marino GNU General Public License for more details. 17e4b17023SJohn Marino 18e4b17023SJohn Marino You should have received a copy of the GNU General Public License 19e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see 20e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */ 21e4b17023SJohn Marino 22e4b17023SJohn Marino #include "config.h" 23e4b17023SJohn Marino #include "system.h" 24e4b17023SJohn Marino #include "coretypes.h" 25e4b17023SJohn Marino #include "tm.h" 26e4b17023SJohn Marino #include "diagnostic-core.h" 27e4b17023SJohn Marino #include "tree.h" 28e4b17023SJohn Marino #include "tree-inline.h" 29e4b17023SJohn Marino #include "flags.h" 30e4b17023SJohn Marino #include "params.h" 31e4b17023SJohn Marino #include "input.h" 32e4b17023SJohn Marino #include "insn-config.h" 33e4b17023SJohn Marino #include "hashtab.h" 34e4b17023SJohn Marino #include "langhooks.h" 35e4b17023SJohn Marino #include "basic-block.h" 36e4b17023SJohn Marino #include "tree-iterator.h" 37e4b17023SJohn Marino #include "cgraph.h" 38e4b17023SJohn Marino #include "intl.h" 39e4b17023SJohn Marino #include "tree-mudflap.h" 40e4b17023SJohn Marino #include "tree-flow.h" 41e4b17023SJohn Marino #include "function.h" 42e4b17023SJohn Marino #include "tree-flow.h" 43e4b17023SJohn Marino #include "tree-pretty-print.h" 44e4b17023SJohn Marino #include "except.h" 45e4b17023SJohn Marino #include "debug.h" 46e4b17023SJohn Marino #include "pointer-set.h" 47e4b17023SJohn Marino #include "ipa-prop.h" 48e4b17023SJohn Marino #include "value-prof.h" 49e4b17023SJohn Marino #include "tree-pass.h" 50e4b17023SJohn Marino #include "target.h" 51e4b17023SJohn Marino #include "integrate.h" 52e4b17023SJohn Marino 53e4b17023SJohn Marino #include "rtl.h" /* FIXME: For asm_str_count. */ 54e4b17023SJohn Marino 55e4b17023SJohn Marino /* I'm not real happy about this, but we need to handle gimple and 56e4b17023SJohn Marino non-gimple trees. */ 57e4b17023SJohn Marino #include "gimple.h" 58e4b17023SJohn Marino 59e4b17023SJohn Marino /* Inlining, Cloning, Versioning, Parallelization 60e4b17023SJohn Marino 61e4b17023SJohn Marino Inlining: a function body is duplicated, but the PARM_DECLs are 62e4b17023SJohn Marino remapped into VAR_DECLs, and non-void RETURN_EXPRs become 63e4b17023SJohn Marino MODIFY_EXPRs that store to a dedicated returned-value variable. 64e4b17023SJohn Marino The duplicated eh_region info of the copy will later be appended 65e4b17023SJohn Marino to the info for the caller; the eh_region info in copied throwing 66e4b17023SJohn Marino statements and RESX statements are adjusted accordingly. 67e4b17023SJohn Marino 68e4b17023SJohn Marino Cloning: (only in C++) We have one body for a con/de/structor, and 69e4b17023SJohn Marino multiple function decls, each with a unique parameter list. 70e4b17023SJohn Marino Duplicate the body, using the given splay tree; some parameters 71e4b17023SJohn Marino will become constants (like 0 or 1). 72e4b17023SJohn Marino 73e4b17023SJohn Marino Versioning: a function body is duplicated and the result is a new 74e4b17023SJohn Marino function rather than into blocks of an existing function as with 75e4b17023SJohn Marino inlining. Some parameters will become constants. 76e4b17023SJohn Marino 77e4b17023SJohn Marino Parallelization: a region of a function is duplicated resulting in 78e4b17023SJohn Marino a new function. Variables may be replaced with complex expressions 79e4b17023SJohn Marino to enable shared variable semantics. 80e4b17023SJohn Marino 81e4b17023SJohn Marino All of these will simultaneously lookup any callgraph edges. If 82e4b17023SJohn Marino we're going to inline the duplicated function body, and the given 83e4b17023SJohn Marino function has some cloned callgraph nodes (one for each place this 84e4b17023SJohn Marino function will be inlined) those callgraph edges will be duplicated. 85e4b17023SJohn Marino If we're cloning the body, those callgraph edges will be 86e4b17023SJohn Marino updated to point into the new body. (Note that the original 87e4b17023SJohn Marino callgraph node and edge list will not be altered.) 88e4b17023SJohn Marino 89e4b17023SJohn Marino See the CALL_EXPR handling case in copy_tree_body_r (). */ 90e4b17023SJohn Marino 91e4b17023SJohn Marino /* To Do: 92e4b17023SJohn Marino 93e4b17023SJohn Marino o In order to make inlining-on-trees work, we pessimized 94e4b17023SJohn Marino function-local static constants. In particular, they are now 95e4b17023SJohn Marino always output, even when not addressed. Fix this by treating 96e4b17023SJohn Marino function-local static constants just like global static 97e4b17023SJohn Marino constants; the back-end already knows not to output them if they 98e4b17023SJohn Marino are not needed. 99e4b17023SJohn Marino 100e4b17023SJohn Marino o Provide heuristics to clamp inlining of recursive template 101e4b17023SJohn Marino calls? */ 102e4b17023SJohn Marino 103e4b17023SJohn Marino 104e4b17023SJohn Marino /* Weights that estimate_num_insns uses to estimate the size of the 105e4b17023SJohn Marino produced code. */ 106e4b17023SJohn Marino 107e4b17023SJohn Marino eni_weights eni_size_weights; 108e4b17023SJohn Marino 109e4b17023SJohn Marino /* Weights that estimate_num_insns uses to estimate the time necessary 110e4b17023SJohn Marino to execute the produced code. */ 111e4b17023SJohn Marino 112e4b17023SJohn Marino eni_weights eni_time_weights; 113e4b17023SJohn Marino 114e4b17023SJohn Marino /* Prototypes. */ 115e4b17023SJohn Marino 116e4b17023SJohn Marino static tree declare_return_variable (copy_body_data *, tree, tree, basic_block); 117e4b17023SJohn Marino static void remap_block (tree *, copy_body_data *); 118e4b17023SJohn Marino static void copy_bind_expr (tree *, int *, copy_body_data *); 119e4b17023SJohn Marino static tree mark_local_for_remap_r (tree *, int *, void *); 120e4b17023SJohn Marino static void unsave_expr_1 (tree); 121e4b17023SJohn Marino static tree unsave_r (tree *, int *, void *); 122e4b17023SJohn Marino static void declare_inline_vars (tree, tree); 123e4b17023SJohn Marino static void remap_save_expr (tree *, void *, int *); 124e4b17023SJohn Marino static void prepend_lexical_block (tree current_block, tree new_block); 125e4b17023SJohn Marino static tree copy_decl_to_var (tree, copy_body_data *); 126e4b17023SJohn Marino static tree copy_result_decl_to_var (tree, copy_body_data *); 127e4b17023SJohn Marino static tree copy_decl_maybe_to_var (tree, copy_body_data *); 128e4b17023SJohn Marino static gimple remap_gimple_stmt (gimple, copy_body_data *); 129e4b17023SJohn Marino static bool delete_unreachable_blocks_update_callgraph (copy_body_data *id); 130e4b17023SJohn Marino 131e4b17023SJohn Marino /* Insert a tree->tree mapping for ID. Despite the name suggests 132e4b17023SJohn Marino that the trees should be variables, it is used for more than that. */ 133e4b17023SJohn Marino 134e4b17023SJohn Marino void 135e4b17023SJohn Marino insert_decl_map (copy_body_data *id, tree key, tree value) 136e4b17023SJohn Marino { 137e4b17023SJohn Marino *pointer_map_insert (id->decl_map, key) = value; 138e4b17023SJohn Marino 139e4b17023SJohn Marino /* Always insert an identity map as well. If we see this same new 140e4b17023SJohn Marino node again, we won't want to duplicate it a second time. */ 141e4b17023SJohn Marino if (key != value) 142e4b17023SJohn Marino *pointer_map_insert (id->decl_map, value) = value; 143e4b17023SJohn Marino } 144e4b17023SJohn Marino 145e4b17023SJohn Marino /* Insert a tree->tree mapping for ID. This is only used for 146e4b17023SJohn Marino variables. */ 147e4b17023SJohn Marino 148e4b17023SJohn Marino static void 149e4b17023SJohn Marino insert_debug_decl_map (copy_body_data *id, tree key, tree value) 150e4b17023SJohn Marino { 151e4b17023SJohn Marino if (!gimple_in_ssa_p (id->src_cfun)) 152e4b17023SJohn Marino return; 153e4b17023SJohn Marino 154e4b17023SJohn Marino if (!MAY_HAVE_DEBUG_STMTS) 155e4b17023SJohn Marino return; 156e4b17023SJohn Marino 157e4b17023SJohn Marino if (!target_for_debug_bind (key)) 158e4b17023SJohn Marino return; 159e4b17023SJohn Marino 160e4b17023SJohn Marino gcc_assert (TREE_CODE (key) == PARM_DECL); 161e4b17023SJohn Marino gcc_assert (TREE_CODE (value) == VAR_DECL); 162e4b17023SJohn Marino 163e4b17023SJohn Marino if (!id->debug_map) 164e4b17023SJohn Marino id->debug_map = pointer_map_create (); 165e4b17023SJohn Marino 166e4b17023SJohn Marino *pointer_map_insert (id->debug_map, key) = value; 167e4b17023SJohn Marino } 168e4b17023SJohn Marino 169e4b17023SJohn Marino /* If nonzero, we're remapping the contents of inlined debug 170e4b17023SJohn Marino statements. If negative, an error has occurred, such as a 171e4b17023SJohn Marino reference to a variable that isn't available in the inlined 172e4b17023SJohn Marino context. */ 173e4b17023SJohn Marino static int processing_debug_stmt = 0; 174e4b17023SJohn Marino 175e4b17023SJohn Marino /* Construct new SSA name for old NAME. ID is the inline context. */ 176e4b17023SJohn Marino 177e4b17023SJohn Marino static tree 178e4b17023SJohn Marino remap_ssa_name (tree name, copy_body_data *id) 179e4b17023SJohn Marino { 180e4b17023SJohn Marino tree new_tree; 181e4b17023SJohn Marino tree *n; 182e4b17023SJohn Marino 183e4b17023SJohn Marino gcc_assert (TREE_CODE (name) == SSA_NAME); 184e4b17023SJohn Marino 185e4b17023SJohn Marino n = (tree *) pointer_map_contains (id->decl_map, name); 186e4b17023SJohn Marino if (n) 187e4b17023SJohn Marino return unshare_expr (*n); 188e4b17023SJohn Marino 189e4b17023SJohn Marino if (processing_debug_stmt) 190e4b17023SJohn Marino { 191e4b17023SJohn Marino if (TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL 192e4b17023SJohn Marino && SSA_NAME_IS_DEFAULT_DEF (name) 193e4b17023SJohn Marino && id->entry_bb == NULL 194e4b17023SJohn Marino && single_succ_p (ENTRY_BLOCK_PTR)) 195e4b17023SJohn Marino { 196e4b17023SJohn Marino tree vexpr = make_node (DEBUG_EXPR_DECL); 197e4b17023SJohn Marino gimple def_temp; 198e4b17023SJohn Marino gimple_stmt_iterator gsi; 199e4b17023SJohn Marino tree val = SSA_NAME_VAR (name); 200e4b17023SJohn Marino 201e4b17023SJohn Marino n = (tree *) pointer_map_contains (id->decl_map, val); 202e4b17023SJohn Marino if (n != NULL) 203e4b17023SJohn Marino val = *n; 204e4b17023SJohn Marino if (TREE_CODE (val) != PARM_DECL) 205e4b17023SJohn Marino { 206e4b17023SJohn Marino processing_debug_stmt = -1; 207e4b17023SJohn Marino return name; 208e4b17023SJohn Marino } 209e4b17023SJohn Marino def_temp = gimple_build_debug_source_bind (vexpr, val, NULL); 210e4b17023SJohn Marino DECL_ARTIFICIAL (vexpr) = 1; 211e4b17023SJohn Marino TREE_TYPE (vexpr) = TREE_TYPE (name); 212e4b17023SJohn Marino DECL_MODE (vexpr) = DECL_MODE (SSA_NAME_VAR (name)); 213e4b17023SJohn Marino gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR)); 214e4b17023SJohn Marino gsi_insert_before (&gsi, def_temp, GSI_SAME_STMT); 215e4b17023SJohn Marino return vexpr; 216e4b17023SJohn Marino } 217e4b17023SJohn Marino 218e4b17023SJohn Marino processing_debug_stmt = -1; 219e4b17023SJohn Marino return name; 220e4b17023SJohn Marino } 221e4b17023SJohn Marino 222e4b17023SJohn Marino /* Do not set DEF_STMT yet as statement is not copied yet. We do that 223e4b17023SJohn Marino in copy_bb. */ 224e4b17023SJohn Marino new_tree = remap_decl (SSA_NAME_VAR (name), id); 225e4b17023SJohn Marino 226e4b17023SJohn Marino /* We might've substituted constant or another SSA_NAME for 227e4b17023SJohn Marino the variable. 228e4b17023SJohn Marino 229e4b17023SJohn Marino Replace the SSA name representing RESULT_DECL by variable during 230e4b17023SJohn Marino inlining: this saves us from need to introduce PHI node in a case 231e4b17023SJohn Marino return value is just partly initialized. */ 232e4b17023SJohn Marino if ((TREE_CODE (new_tree) == VAR_DECL || TREE_CODE (new_tree) == PARM_DECL) 233e4b17023SJohn Marino && (TREE_CODE (SSA_NAME_VAR (name)) != RESULT_DECL 234e4b17023SJohn Marino || !id->transform_return_to_modify)) 235e4b17023SJohn Marino { 236e4b17023SJohn Marino struct ptr_info_def *pi; 237e4b17023SJohn Marino new_tree = make_ssa_name (new_tree, NULL); 238e4b17023SJohn Marino insert_decl_map (id, name, new_tree); 239e4b17023SJohn Marino SSA_NAME_OCCURS_IN_ABNORMAL_PHI (new_tree) 240e4b17023SJohn Marino = SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name); 241e4b17023SJohn Marino TREE_TYPE (new_tree) = TREE_TYPE (SSA_NAME_VAR (new_tree)); 242e4b17023SJohn Marino /* At least IPA points-to info can be directly transferred. */ 243e4b17023SJohn Marino if (id->src_cfun->gimple_df 244e4b17023SJohn Marino && id->src_cfun->gimple_df->ipa_pta 245e4b17023SJohn Marino && (pi = SSA_NAME_PTR_INFO (name)) 246e4b17023SJohn Marino && !pi->pt.anything) 247e4b17023SJohn Marino { 248e4b17023SJohn Marino struct ptr_info_def *new_pi = get_ptr_info (new_tree); 249e4b17023SJohn Marino new_pi->pt = pi->pt; 250e4b17023SJohn Marino } 251e4b17023SJohn Marino if (gimple_nop_p (SSA_NAME_DEF_STMT (name))) 252e4b17023SJohn Marino { 253e4b17023SJohn Marino /* By inlining function having uninitialized variable, we might 254e4b17023SJohn Marino extend the lifetime (variable might get reused). This cause 255e4b17023SJohn Marino ICE in the case we end up extending lifetime of SSA name across 256e4b17023SJohn Marino abnormal edge, but also increase register pressure. 257e4b17023SJohn Marino 258e4b17023SJohn Marino We simply initialize all uninitialized vars by 0 except 259e4b17023SJohn Marino for case we are inlining to very first BB. We can avoid 260e4b17023SJohn Marino this for all BBs that are not inside strongly connected 261e4b17023SJohn Marino regions of the CFG, but this is expensive to test. */ 262e4b17023SJohn Marino if (id->entry_bb 263e4b17023SJohn Marino && is_gimple_reg (SSA_NAME_VAR (name)) 264e4b17023SJohn Marino && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name) 265e4b17023SJohn Marino && TREE_CODE (SSA_NAME_VAR (name)) != PARM_DECL 266e4b17023SJohn Marino && (id->entry_bb != EDGE_SUCC (ENTRY_BLOCK_PTR, 0)->dest 267e4b17023SJohn Marino || EDGE_COUNT (id->entry_bb->preds) != 1)) 268e4b17023SJohn Marino { 269e4b17023SJohn Marino gimple_stmt_iterator gsi = gsi_last_bb (id->entry_bb); 270e4b17023SJohn Marino gimple init_stmt; 271e4b17023SJohn Marino tree zero = build_zero_cst (TREE_TYPE (new_tree)); 272e4b17023SJohn Marino 273e4b17023SJohn Marino init_stmt = gimple_build_assign (new_tree, zero); 274e4b17023SJohn Marino gsi_insert_after (&gsi, init_stmt, GSI_NEW_STMT); 275e4b17023SJohn Marino SSA_NAME_IS_DEFAULT_DEF (new_tree) = 0; 276e4b17023SJohn Marino } 277e4b17023SJohn Marino else 278e4b17023SJohn Marino { 279e4b17023SJohn Marino SSA_NAME_DEF_STMT (new_tree) = gimple_build_nop (); 280e4b17023SJohn Marino if (gimple_default_def (id->src_cfun, SSA_NAME_VAR (name)) 281e4b17023SJohn Marino == name) 282e4b17023SJohn Marino set_default_def (SSA_NAME_VAR (new_tree), new_tree); 283e4b17023SJohn Marino } 284e4b17023SJohn Marino } 285e4b17023SJohn Marino } 286e4b17023SJohn Marino else 287e4b17023SJohn Marino insert_decl_map (id, name, new_tree); 288e4b17023SJohn Marino return new_tree; 289e4b17023SJohn Marino } 290e4b17023SJohn Marino 291e4b17023SJohn Marino /* Remap DECL during the copying of the BLOCK tree for the function. */ 292e4b17023SJohn Marino 293e4b17023SJohn Marino tree 294e4b17023SJohn Marino remap_decl (tree decl, copy_body_data *id) 295e4b17023SJohn Marino { 296e4b17023SJohn Marino tree *n; 297e4b17023SJohn Marino 298e4b17023SJohn Marino /* We only remap local variables in the current function. */ 299e4b17023SJohn Marino 300e4b17023SJohn Marino /* See if we have remapped this declaration. */ 301e4b17023SJohn Marino 302e4b17023SJohn Marino n = (tree *) pointer_map_contains (id->decl_map, decl); 303e4b17023SJohn Marino 304e4b17023SJohn Marino if (!n && processing_debug_stmt) 305e4b17023SJohn Marino { 306e4b17023SJohn Marino processing_debug_stmt = -1; 307e4b17023SJohn Marino return decl; 308e4b17023SJohn Marino } 309e4b17023SJohn Marino 310e4b17023SJohn Marino /* If we didn't already have an equivalent for this declaration, 311e4b17023SJohn Marino create one now. */ 312e4b17023SJohn Marino if (!n) 313e4b17023SJohn Marino { 314e4b17023SJohn Marino /* Make a copy of the variable or label. */ 315e4b17023SJohn Marino tree t = id->copy_decl (decl, id); 316e4b17023SJohn Marino 317e4b17023SJohn Marino /* Remember it, so that if we encounter this local entity again 318e4b17023SJohn Marino we can reuse this copy. Do this early because remap_type may 319e4b17023SJohn Marino need this decl for TYPE_STUB_DECL. */ 320e4b17023SJohn Marino insert_decl_map (id, decl, t); 321e4b17023SJohn Marino 322e4b17023SJohn Marino if (!DECL_P (t)) 323e4b17023SJohn Marino return t; 324e4b17023SJohn Marino 325e4b17023SJohn Marino /* Remap types, if necessary. */ 326e4b17023SJohn Marino TREE_TYPE (t) = remap_type (TREE_TYPE (t), id); 327e4b17023SJohn Marino if (TREE_CODE (t) == TYPE_DECL) 328e4b17023SJohn Marino DECL_ORIGINAL_TYPE (t) = remap_type (DECL_ORIGINAL_TYPE (t), id); 329e4b17023SJohn Marino 330e4b17023SJohn Marino /* Remap sizes as necessary. */ 331e4b17023SJohn Marino walk_tree (&DECL_SIZE (t), copy_tree_body_r, id, NULL); 332e4b17023SJohn Marino walk_tree (&DECL_SIZE_UNIT (t), copy_tree_body_r, id, NULL); 333e4b17023SJohn Marino 334e4b17023SJohn Marino /* If fields, do likewise for offset and qualifier. */ 335e4b17023SJohn Marino if (TREE_CODE (t) == FIELD_DECL) 336e4b17023SJohn Marino { 337e4b17023SJohn Marino walk_tree (&DECL_FIELD_OFFSET (t), copy_tree_body_r, id, NULL); 338e4b17023SJohn Marino if (TREE_CODE (DECL_CONTEXT (t)) == QUAL_UNION_TYPE) 339e4b17023SJohn Marino walk_tree (&DECL_QUALIFIER (t), copy_tree_body_r, id, NULL); 340e4b17023SJohn Marino } 341e4b17023SJohn Marino 342e4b17023SJohn Marino if ((TREE_CODE (t) == VAR_DECL 343e4b17023SJohn Marino || TREE_CODE (t) == RESULT_DECL 344e4b17023SJohn Marino || TREE_CODE (t) == PARM_DECL) 345e4b17023SJohn Marino && id->src_fn && DECL_STRUCT_FUNCTION (id->src_fn) 346e4b17023SJohn Marino && gimple_referenced_vars (DECL_STRUCT_FUNCTION (id->src_fn)) 347e4b17023SJohn Marino /* We don't want to mark as referenced VAR_DECLs that were 348e4b17023SJohn Marino not marked as such in the src function. */ 349e4b17023SJohn Marino && (TREE_CODE (decl) != VAR_DECL 350e4b17023SJohn Marino || referenced_var_lookup (DECL_STRUCT_FUNCTION (id->src_fn), 351e4b17023SJohn Marino DECL_UID (decl)))) 352e4b17023SJohn Marino add_referenced_var (t); 353e4b17023SJohn Marino return t; 354e4b17023SJohn Marino } 355e4b17023SJohn Marino 356e4b17023SJohn Marino if (id->do_not_unshare) 357e4b17023SJohn Marino return *n; 358e4b17023SJohn Marino else 359e4b17023SJohn Marino return unshare_expr (*n); 360e4b17023SJohn Marino } 361e4b17023SJohn Marino 362e4b17023SJohn Marino static tree 363e4b17023SJohn Marino remap_type_1 (tree type, copy_body_data *id) 364e4b17023SJohn Marino { 365e4b17023SJohn Marino tree new_tree, t; 366e4b17023SJohn Marino 367e4b17023SJohn Marino /* We do need a copy. build and register it now. If this is a pointer or 368e4b17023SJohn Marino reference type, remap the designated type and make a new pointer or 369e4b17023SJohn Marino reference type. */ 370e4b17023SJohn Marino if (TREE_CODE (type) == POINTER_TYPE) 371e4b17023SJohn Marino { 372e4b17023SJohn Marino new_tree = build_pointer_type_for_mode (remap_type (TREE_TYPE (type), id), 373e4b17023SJohn Marino TYPE_MODE (type), 374e4b17023SJohn Marino TYPE_REF_CAN_ALIAS_ALL (type)); 375e4b17023SJohn Marino if (TYPE_ATTRIBUTES (type) || TYPE_QUALS (type)) 376e4b17023SJohn Marino new_tree = build_type_attribute_qual_variant (new_tree, 377e4b17023SJohn Marino TYPE_ATTRIBUTES (type), 378e4b17023SJohn Marino TYPE_QUALS (type)); 379e4b17023SJohn Marino insert_decl_map (id, type, new_tree); 380e4b17023SJohn Marino return new_tree; 381e4b17023SJohn Marino } 382e4b17023SJohn Marino else if (TREE_CODE (type) == REFERENCE_TYPE) 383e4b17023SJohn Marino { 384e4b17023SJohn Marino new_tree = build_reference_type_for_mode (remap_type (TREE_TYPE (type), id), 385e4b17023SJohn Marino TYPE_MODE (type), 386e4b17023SJohn Marino TYPE_REF_CAN_ALIAS_ALL (type)); 387e4b17023SJohn Marino if (TYPE_ATTRIBUTES (type) || TYPE_QUALS (type)) 388e4b17023SJohn Marino new_tree = build_type_attribute_qual_variant (new_tree, 389e4b17023SJohn Marino TYPE_ATTRIBUTES (type), 390e4b17023SJohn Marino TYPE_QUALS (type)); 391e4b17023SJohn Marino insert_decl_map (id, type, new_tree); 392e4b17023SJohn Marino return new_tree; 393e4b17023SJohn Marino } 394e4b17023SJohn Marino else 395e4b17023SJohn Marino new_tree = copy_node (type); 396e4b17023SJohn Marino 397e4b17023SJohn Marino insert_decl_map (id, type, new_tree); 398e4b17023SJohn Marino 399e4b17023SJohn Marino /* This is a new type, not a copy of an old type. Need to reassociate 400e4b17023SJohn Marino variants. We can handle everything except the main variant lazily. */ 401e4b17023SJohn Marino t = TYPE_MAIN_VARIANT (type); 402e4b17023SJohn Marino if (type != t) 403e4b17023SJohn Marino { 404e4b17023SJohn Marino t = remap_type (t, id); 405e4b17023SJohn Marino TYPE_MAIN_VARIANT (new_tree) = t; 406e4b17023SJohn Marino TYPE_NEXT_VARIANT (new_tree) = TYPE_NEXT_VARIANT (t); 407e4b17023SJohn Marino TYPE_NEXT_VARIANT (t) = new_tree; 408e4b17023SJohn Marino } 409e4b17023SJohn Marino else 410e4b17023SJohn Marino { 411e4b17023SJohn Marino TYPE_MAIN_VARIANT (new_tree) = new_tree; 412e4b17023SJohn Marino TYPE_NEXT_VARIANT (new_tree) = NULL; 413e4b17023SJohn Marino } 414e4b17023SJohn Marino 415e4b17023SJohn Marino if (TYPE_STUB_DECL (type)) 416e4b17023SJohn Marino TYPE_STUB_DECL (new_tree) = remap_decl (TYPE_STUB_DECL (type), id); 417e4b17023SJohn Marino 418e4b17023SJohn Marino /* Lazily create pointer and reference types. */ 419e4b17023SJohn Marino TYPE_POINTER_TO (new_tree) = NULL; 420e4b17023SJohn Marino TYPE_REFERENCE_TO (new_tree) = NULL; 421e4b17023SJohn Marino 422e4b17023SJohn Marino switch (TREE_CODE (new_tree)) 423e4b17023SJohn Marino { 424e4b17023SJohn Marino case INTEGER_TYPE: 425e4b17023SJohn Marino case REAL_TYPE: 426e4b17023SJohn Marino case FIXED_POINT_TYPE: 427e4b17023SJohn Marino case ENUMERAL_TYPE: 428e4b17023SJohn Marino case BOOLEAN_TYPE: 429e4b17023SJohn Marino t = TYPE_MIN_VALUE (new_tree); 430e4b17023SJohn Marino if (t && TREE_CODE (t) != INTEGER_CST) 431e4b17023SJohn Marino walk_tree (&TYPE_MIN_VALUE (new_tree), copy_tree_body_r, id, NULL); 432e4b17023SJohn Marino 433e4b17023SJohn Marino t = TYPE_MAX_VALUE (new_tree); 434e4b17023SJohn Marino if (t && TREE_CODE (t) != INTEGER_CST) 435e4b17023SJohn Marino walk_tree (&TYPE_MAX_VALUE (new_tree), copy_tree_body_r, id, NULL); 436e4b17023SJohn Marino return new_tree; 437e4b17023SJohn Marino 438e4b17023SJohn Marino case FUNCTION_TYPE: 439e4b17023SJohn Marino TREE_TYPE (new_tree) = remap_type (TREE_TYPE (new_tree), id); 440e4b17023SJohn Marino walk_tree (&TYPE_ARG_TYPES (new_tree), copy_tree_body_r, id, NULL); 441e4b17023SJohn Marino return new_tree; 442e4b17023SJohn Marino 443e4b17023SJohn Marino case ARRAY_TYPE: 444e4b17023SJohn Marino TREE_TYPE (new_tree) = remap_type (TREE_TYPE (new_tree), id); 445e4b17023SJohn Marino TYPE_DOMAIN (new_tree) = remap_type (TYPE_DOMAIN (new_tree), id); 446e4b17023SJohn Marino break; 447e4b17023SJohn Marino 448e4b17023SJohn Marino case RECORD_TYPE: 449e4b17023SJohn Marino case UNION_TYPE: 450e4b17023SJohn Marino case QUAL_UNION_TYPE: 451e4b17023SJohn Marino { 452e4b17023SJohn Marino tree f, nf = NULL; 453e4b17023SJohn Marino 454e4b17023SJohn Marino for (f = TYPE_FIELDS (new_tree); f ; f = DECL_CHAIN (f)) 455e4b17023SJohn Marino { 456e4b17023SJohn Marino t = remap_decl (f, id); 457e4b17023SJohn Marino DECL_CONTEXT (t) = new_tree; 458e4b17023SJohn Marino DECL_CHAIN (t) = nf; 459e4b17023SJohn Marino nf = t; 460e4b17023SJohn Marino } 461e4b17023SJohn Marino TYPE_FIELDS (new_tree) = nreverse (nf); 462e4b17023SJohn Marino } 463e4b17023SJohn Marino break; 464e4b17023SJohn Marino 465e4b17023SJohn Marino case OFFSET_TYPE: 466e4b17023SJohn Marino default: 467e4b17023SJohn Marino /* Shouldn't have been thought variable sized. */ 468e4b17023SJohn Marino gcc_unreachable (); 469e4b17023SJohn Marino } 470e4b17023SJohn Marino 471e4b17023SJohn Marino walk_tree (&TYPE_SIZE (new_tree), copy_tree_body_r, id, NULL); 472e4b17023SJohn Marino walk_tree (&TYPE_SIZE_UNIT (new_tree), copy_tree_body_r, id, NULL); 473e4b17023SJohn Marino 474e4b17023SJohn Marino return new_tree; 475e4b17023SJohn Marino } 476e4b17023SJohn Marino 477e4b17023SJohn Marino tree 478e4b17023SJohn Marino remap_type (tree type, copy_body_data *id) 479e4b17023SJohn Marino { 480e4b17023SJohn Marino tree *node; 481e4b17023SJohn Marino tree tmp; 482e4b17023SJohn Marino 483e4b17023SJohn Marino if (type == NULL) 484e4b17023SJohn Marino return type; 485e4b17023SJohn Marino 486e4b17023SJohn Marino /* See if we have remapped this type. */ 487e4b17023SJohn Marino node = (tree *) pointer_map_contains (id->decl_map, type); 488e4b17023SJohn Marino if (node) 489e4b17023SJohn Marino return *node; 490e4b17023SJohn Marino 491e4b17023SJohn Marino /* The type only needs remapping if it's variably modified. */ 492e4b17023SJohn Marino if (! variably_modified_type_p (type, id->src_fn)) 493e4b17023SJohn Marino { 494e4b17023SJohn Marino insert_decl_map (id, type, type); 495e4b17023SJohn Marino return type; 496e4b17023SJohn Marino } 497e4b17023SJohn Marino 498e4b17023SJohn Marino id->remapping_type_depth++; 499e4b17023SJohn Marino tmp = remap_type_1 (type, id); 500e4b17023SJohn Marino id->remapping_type_depth--; 501e4b17023SJohn Marino 502e4b17023SJohn Marino return tmp; 503e4b17023SJohn Marino } 504e4b17023SJohn Marino 505e4b17023SJohn Marino /* Return previously remapped type of TYPE in ID. Return NULL if TYPE 506e4b17023SJohn Marino is NULL or TYPE has not been remapped before. */ 507e4b17023SJohn Marino 508e4b17023SJohn Marino static tree 509e4b17023SJohn Marino remapped_type (tree type, copy_body_data *id) 510e4b17023SJohn Marino { 511e4b17023SJohn Marino tree *node; 512e4b17023SJohn Marino 513e4b17023SJohn Marino if (type == NULL) 514e4b17023SJohn Marino return type; 515e4b17023SJohn Marino 516e4b17023SJohn Marino /* See if we have remapped this type. */ 517e4b17023SJohn Marino node = (tree *) pointer_map_contains (id->decl_map, type); 518e4b17023SJohn Marino if (node) 519e4b17023SJohn Marino return *node; 520e4b17023SJohn Marino else 521e4b17023SJohn Marino return NULL; 522e4b17023SJohn Marino } 523e4b17023SJohn Marino 524e4b17023SJohn Marino /* The type only needs remapping if it's variably modified. */ 525e4b17023SJohn Marino /* Decide if DECL can be put into BLOCK_NONLOCAL_VARs. */ 526e4b17023SJohn Marino 527e4b17023SJohn Marino static bool 528e4b17023SJohn Marino can_be_nonlocal (tree decl, copy_body_data *id) 529e4b17023SJohn Marino { 530e4b17023SJohn Marino /* We can not duplicate function decls. */ 531e4b17023SJohn Marino if (TREE_CODE (decl) == FUNCTION_DECL) 532e4b17023SJohn Marino return true; 533e4b17023SJohn Marino 534e4b17023SJohn Marino /* Local static vars must be non-local or we get multiple declaration 535e4b17023SJohn Marino problems. */ 536e4b17023SJohn Marino if (TREE_CODE (decl) == VAR_DECL 537e4b17023SJohn Marino && !auto_var_in_fn_p (decl, id->src_fn)) 538e4b17023SJohn Marino return true; 539e4b17023SJohn Marino 540e4b17023SJohn Marino /* At the moment dwarf2out can handle only these types of nodes. We 541e4b17023SJohn Marino can support more later. */ 542e4b17023SJohn Marino if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != PARM_DECL) 543e4b17023SJohn Marino return false; 544e4b17023SJohn Marino 545e4b17023SJohn Marino /* We must use global type. We call remapped_type instead of 546e4b17023SJohn Marino remap_type since we don't want to remap this type here if it 547e4b17023SJohn Marino hasn't been remapped before. */ 548e4b17023SJohn Marino if (TREE_TYPE (decl) != remapped_type (TREE_TYPE (decl), id)) 549e4b17023SJohn Marino return false; 550e4b17023SJohn Marino 551e4b17023SJohn Marino /* Wihtout SSA we can't tell if variable is used. */ 552e4b17023SJohn Marino if (!gimple_in_ssa_p (cfun)) 553e4b17023SJohn Marino return false; 554e4b17023SJohn Marino 555e4b17023SJohn Marino /* Live variables must be copied so we can attach DECL_RTL. */ 556e4b17023SJohn Marino if (var_ann (decl)) 557e4b17023SJohn Marino return false; 558e4b17023SJohn Marino 559e4b17023SJohn Marino return true; 560e4b17023SJohn Marino } 561e4b17023SJohn Marino 562e4b17023SJohn Marino static tree 563e4b17023SJohn Marino remap_decls (tree decls, VEC(tree,gc) **nonlocalized_list, copy_body_data *id) 564e4b17023SJohn Marino { 565e4b17023SJohn Marino tree old_var; 566e4b17023SJohn Marino tree new_decls = NULL_TREE; 567e4b17023SJohn Marino 568e4b17023SJohn Marino /* Remap its variables. */ 569e4b17023SJohn Marino for (old_var = decls; old_var; old_var = DECL_CHAIN (old_var)) 570e4b17023SJohn Marino { 571e4b17023SJohn Marino tree new_var; 572e4b17023SJohn Marino 573e4b17023SJohn Marino if (can_be_nonlocal (old_var, id)) 574e4b17023SJohn Marino { 575e4b17023SJohn Marino if (TREE_CODE (old_var) == VAR_DECL 576e4b17023SJohn Marino && ! DECL_EXTERNAL (old_var) 577e4b17023SJohn Marino && (var_ann (old_var) || !gimple_in_ssa_p (cfun))) 578e4b17023SJohn Marino add_local_decl (cfun, old_var); 579e4b17023SJohn Marino if ((!optimize || debug_info_level > DINFO_LEVEL_TERSE) 580e4b17023SJohn Marino && !DECL_IGNORED_P (old_var) 581e4b17023SJohn Marino && nonlocalized_list) 582e4b17023SJohn Marino VEC_safe_push (tree, gc, *nonlocalized_list, old_var); 583e4b17023SJohn Marino continue; 584e4b17023SJohn Marino } 585e4b17023SJohn Marino 586e4b17023SJohn Marino /* Remap the variable. */ 587e4b17023SJohn Marino new_var = remap_decl (old_var, id); 588e4b17023SJohn Marino 589e4b17023SJohn Marino /* If we didn't remap this variable, we can't mess with its 590e4b17023SJohn Marino TREE_CHAIN. If we remapped this variable to the return slot, it's 591e4b17023SJohn Marino already declared somewhere else, so don't declare it here. */ 592e4b17023SJohn Marino 593e4b17023SJohn Marino if (new_var == id->retvar) 594e4b17023SJohn Marino ; 595e4b17023SJohn Marino else if (!new_var) 596e4b17023SJohn Marino { 597e4b17023SJohn Marino if ((!optimize || debug_info_level > DINFO_LEVEL_TERSE) 598e4b17023SJohn Marino && !DECL_IGNORED_P (old_var) 599e4b17023SJohn Marino && nonlocalized_list) 600e4b17023SJohn Marino VEC_safe_push (tree, gc, *nonlocalized_list, old_var); 601e4b17023SJohn Marino } 602e4b17023SJohn Marino else 603e4b17023SJohn Marino { 604e4b17023SJohn Marino gcc_assert (DECL_P (new_var)); 605e4b17023SJohn Marino DECL_CHAIN (new_var) = new_decls; 606e4b17023SJohn Marino new_decls = new_var; 607e4b17023SJohn Marino 608e4b17023SJohn Marino /* Also copy value-expressions. */ 609e4b17023SJohn Marino if (TREE_CODE (new_var) == VAR_DECL 610e4b17023SJohn Marino && DECL_HAS_VALUE_EXPR_P (new_var)) 611e4b17023SJohn Marino { 612e4b17023SJohn Marino tree tem = DECL_VALUE_EXPR (new_var); 613e4b17023SJohn Marino bool old_regimplify = id->regimplify; 614e4b17023SJohn Marino id->remapping_type_depth++; 615e4b17023SJohn Marino walk_tree (&tem, copy_tree_body_r, id, NULL); 616e4b17023SJohn Marino id->remapping_type_depth--; 617e4b17023SJohn Marino id->regimplify = old_regimplify; 618e4b17023SJohn Marino SET_DECL_VALUE_EXPR (new_var, tem); 619e4b17023SJohn Marino } 620e4b17023SJohn Marino } 621e4b17023SJohn Marino } 622e4b17023SJohn Marino 623e4b17023SJohn Marino return nreverse (new_decls); 624e4b17023SJohn Marino } 625e4b17023SJohn Marino 626e4b17023SJohn Marino /* Copy the BLOCK to contain remapped versions of the variables 627e4b17023SJohn Marino therein. And hook the new block into the block-tree. */ 628e4b17023SJohn Marino 629e4b17023SJohn Marino static void 630e4b17023SJohn Marino remap_block (tree *block, copy_body_data *id) 631e4b17023SJohn Marino { 632e4b17023SJohn Marino tree old_block; 633e4b17023SJohn Marino tree new_block; 634e4b17023SJohn Marino 635e4b17023SJohn Marino /* Make the new block. */ 636e4b17023SJohn Marino old_block = *block; 637e4b17023SJohn Marino new_block = make_node (BLOCK); 638e4b17023SJohn Marino TREE_USED (new_block) = TREE_USED (old_block); 639e4b17023SJohn Marino BLOCK_ABSTRACT_ORIGIN (new_block) = old_block; 640e4b17023SJohn Marino BLOCK_SOURCE_LOCATION (new_block) = BLOCK_SOURCE_LOCATION (old_block); 641e4b17023SJohn Marino BLOCK_NONLOCALIZED_VARS (new_block) 642e4b17023SJohn Marino = VEC_copy (tree, gc, BLOCK_NONLOCALIZED_VARS (old_block)); 643e4b17023SJohn Marino *block = new_block; 644e4b17023SJohn Marino 645e4b17023SJohn Marino /* Remap its variables. */ 646e4b17023SJohn Marino BLOCK_VARS (new_block) = remap_decls (BLOCK_VARS (old_block), 647e4b17023SJohn Marino &BLOCK_NONLOCALIZED_VARS (new_block), 648e4b17023SJohn Marino id); 649e4b17023SJohn Marino 650e4b17023SJohn Marino if (id->transform_lang_insert_block) 651e4b17023SJohn Marino id->transform_lang_insert_block (new_block); 652e4b17023SJohn Marino 653e4b17023SJohn Marino /* Remember the remapped block. */ 654e4b17023SJohn Marino insert_decl_map (id, old_block, new_block); 655e4b17023SJohn Marino } 656e4b17023SJohn Marino 657e4b17023SJohn Marino /* Copy the whole block tree and root it in id->block. */ 658e4b17023SJohn Marino static tree 659e4b17023SJohn Marino remap_blocks (tree block, copy_body_data *id) 660e4b17023SJohn Marino { 661e4b17023SJohn Marino tree t; 662e4b17023SJohn Marino tree new_tree = block; 663e4b17023SJohn Marino 664e4b17023SJohn Marino if (!block) 665e4b17023SJohn Marino return NULL; 666e4b17023SJohn Marino 667e4b17023SJohn Marino remap_block (&new_tree, id); 668e4b17023SJohn Marino gcc_assert (new_tree != block); 669e4b17023SJohn Marino for (t = BLOCK_SUBBLOCKS (block); t ; t = BLOCK_CHAIN (t)) 670e4b17023SJohn Marino prepend_lexical_block (new_tree, remap_blocks (t, id)); 671e4b17023SJohn Marino /* Blocks are in arbitrary order, but make things slightly prettier and do 672e4b17023SJohn Marino not swap order when producing a copy. */ 673e4b17023SJohn Marino BLOCK_SUBBLOCKS (new_tree) = blocks_nreverse (BLOCK_SUBBLOCKS (new_tree)); 674e4b17023SJohn Marino return new_tree; 675e4b17023SJohn Marino } 676e4b17023SJohn Marino 677e4b17023SJohn Marino static void 678e4b17023SJohn Marino copy_statement_list (tree *tp) 679e4b17023SJohn Marino { 680e4b17023SJohn Marino tree_stmt_iterator oi, ni; 681e4b17023SJohn Marino tree new_tree; 682e4b17023SJohn Marino 683e4b17023SJohn Marino new_tree = alloc_stmt_list (); 684e4b17023SJohn Marino ni = tsi_start (new_tree); 685e4b17023SJohn Marino oi = tsi_start (*tp); 686e4b17023SJohn Marino TREE_TYPE (new_tree) = TREE_TYPE (*tp); 687e4b17023SJohn Marino *tp = new_tree; 688e4b17023SJohn Marino 689e4b17023SJohn Marino for (; !tsi_end_p (oi); tsi_next (&oi)) 690e4b17023SJohn Marino { 691e4b17023SJohn Marino tree stmt = tsi_stmt (oi); 692e4b17023SJohn Marino if (TREE_CODE (stmt) == STATEMENT_LIST) 693e4b17023SJohn Marino /* This copy is not redundant; tsi_link_after will smash this 694e4b17023SJohn Marino STATEMENT_LIST into the end of the one we're building, and we 695e4b17023SJohn Marino don't want to do that with the original. */ 696e4b17023SJohn Marino copy_statement_list (&stmt); 697e4b17023SJohn Marino tsi_link_after (&ni, stmt, TSI_CONTINUE_LINKING); 698e4b17023SJohn Marino } 699e4b17023SJohn Marino } 700e4b17023SJohn Marino 701e4b17023SJohn Marino static void 702e4b17023SJohn Marino copy_bind_expr (tree *tp, int *walk_subtrees, copy_body_data *id) 703e4b17023SJohn Marino { 704e4b17023SJohn Marino tree block = BIND_EXPR_BLOCK (*tp); 705e4b17023SJohn Marino /* Copy (and replace) the statement. */ 706e4b17023SJohn Marino copy_tree_r (tp, walk_subtrees, NULL); 707e4b17023SJohn Marino if (block) 708e4b17023SJohn Marino { 709e4b17023SJohn Marino remap_block (&block, id); 710e4b17023SJohn Marino BIND_EXPR_BLOCK (*tp) = block; 711e4b17023SJohn Marino } 712e4b17023SJohn Marino 713e4b17023SJohn Marino if (BIND_EXPR_VARS (*tp)) 714e4b17023SJohn Marino /* This will remap a lot of the same decls again, but this should be 715e4b17023SJohn Marino harmless. */ 716e4b17023SJohn Marino BIND_EXPR_VARS (*tp) = remap_decls (BIND_EXPR_VARS (*tp), NULL, id); 717e4b17023SJohn Marino } 718e4b17023SJohn Marino 719e4b17023SJohn Marino 720e4b17023SJohn Marino /* Create a new gimple_seq by remapping all the statements in BODY 721e4b17023SJohn Marino using the inlining information in ID. */ 722e4b17023SJohn Marino 723e4b17023SJohn Marino static gimple_seq 724e4b17023SJohn Marino remap_gimple_seq (gimple_seq body, copy_body_data *id) 725e4b17023SJohn Marino { 726e4b17023SJohn Marino gimple_stmt_iterator si; 727e4b17023SJohn Marino gimple_seq new_body = NULL; 728e4b17023SJohn Marino 729e4b17023SJohn Marino for (si = gsi_start (body); !gsi_end_p (si); gsi_next (&si)) 730e4b17023SJohn Marino { 731e4b17023SJohn Marino gimple new_stmt = remap_gimple_stmt (gsi_stmt (si), id); 732e4b17023SJohn Marino gimple_seq_add_stmt (&new_body, new_stmt); 733e4b17023SJohn Marino } 734e4b17023SJohn Marino 735e4b17023SJohn Marino return new_body; 736e4b17023SJohn Marino } 737e4b17023SJohn Marino 738e4b17023SJohn Marino 739e4b17023SJohn Marino /* Copy a GIMPLE_BIND statement STMT, remapping all the symbols in its 740e4b17023SJohn Marino block using the mapping information in ID. */ 741e4b17023SJohn Marino 742e4b17023SJohn Marino static gimple 743e4b17023SJohn Marino copy_gimple_bind (gimple stmt, copy_body_data *id) 744e4b17023SJohn Marino { 745e4b17023SJohn Marino gimple new_bind; 746e4b17023SJohn Marino tree new_block, new_vars; 747e4b17023SJohn Marino gimple_seq body, new_body; 748e4b17023SJohn Marino 749e4b17023SJohn Marino /* Copy the statement. Note that we purposely don't use copy_stmt 750e4b17023SJohn Marino here because we need to remap statements as we copy. */ 751e4b17023SJohn Marino body = gimple_bind_body (stmt); 752e4b17023SJohn Marino new_body = remap_gimple_seq (body, id); 753e4b17023SJohn Marino 754e4b17023SJohn Marino new_block = gimple_bind_block (stmt); 755e4b17023SJohn Marino if (new_block) 756e4b17023SJohn Marino remap_block (&new_block, id); 757e4b17023SJohn Marino 758e4b17023SJohn Marino /* This will remap a lot of the same decls again, but this should be 759e4b17023SJohn Marino harmless. */ 760e4b17023SJohn Marino new_vars = gimple_bind_vars (stmt); 761e4b17023SJohn Marino if (new_vars) 762e4b17023SJohn Marino new_vars = remap_decls (new_vars, NULL, id); 763e4b17023SJohn Marino 764e4b17023SJohn Marino new_bind = gimple_build_bind (new_vars, new_body, new_block); 765e4b17023SJohn Marino 766e4b17023SJohn Marino return new_bind; 767e4b17023SJohn Marino } 768e4b17023SJohn Marino 769e4b17023SJohn Marino 770e4b17023SJohn Marino /* Remap the GIMPLE operand pointed to by *TP. DATA is really a 771e4b17023SJohn Marino 'struct walk_stmt_info *'. DATA->INFO is a 'copy_body_data *'. 772e4b17023SJohn Marino WALK_SUBTREES is used to indicate walk_gimple_op whether to keep 773e4b17023SJohn Marino recursing into the children nodes of *TP. */ 774e4b17023SJohn Marino 775e4b17023SJohn Marino static tree 776e4b17023SJohn Marino remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data) 777e4b17023SJohn Marino { 778e4b17023SJohn Marino struct walk_stmt_info *wi_p = (struct walk_stmt_info *) data; 779e4b17023SJohn Marino copy_body_data *id = (copy_body_data *) wi_p->info; 780e4b17023SJohn Marino tree fn = id->src_fn; 781e4b17023SJohn Marino 782e4b17023SJohn Marino if (TREE_CODE (*tp) == SSA_NAME) 783e4b17023SJohn Marino { 784e4b17023SJohn Marino *tp = remap_ssa_name (*tp, id); 785e4b17023SJohn Marino *walk_subtrees = 0; 786e4b17023SJohn Marino return NULL; 787e4b17023SJohn Marino } 788e4b17023SJohn Marino else if (auto_var_in_fn_p (*tp, fn)) 789e4b17023SJohn Marino { 790e4b17023SJohn Marino /* Local variables and labels need to be replaced by equivalent 791e4b17023SJohn Marino variables. We don't want to copy static variables; there's 792e4b17023SJohn Marino only one of those, no matter how many times we inline the 793e4b17023SJohn Marino containing function. Similarly for globals from an outer 794e4b17023SJohn Marino function. */ 795e4b17023SJohn Marino tree new_decl; 796e4b17023SJohn Marino 797e4b17023SJohn Marino /* Remap the declaration. */ 798e4b17023SJohn Marino new_decl = remap_decl (*tp, id); 799e4b17023SJohn Marino gcc_assert (new_decl); 800e4b17023SJohn Marino /* Replace this variable with the copy. */ 801e4b17023SJohn Marino STRIP_TYPE_NOPS (new_decl); 802e4b17023SJohn Marino /* ??? The C++ frontend uses void * pointer zero to initialize 803e4b17023SJohn Marino any other type. This confuses the middle-end type verification. 804e4b17023SJohn Marino As cloned bodies do not go through gimplification again the fixup 805e4b17023SJohn Marino there doesn't trigger. */ 806e4b17023SJohn Marino if (TREE_CODE (new_decl) == INTEGER_CST 807e4b17023SJohn Marino && !useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (new_decl))) 808e4b17023SJohn Marino new_decl = fold_convert (TREE_TYPE (*tp), new_decl); 809e4b17023SJohn Marino *tp = new_decl; 810e4b17023SJohn Marino *walk_subtrees = 0; 811e4b17023SJohn Marino } 812e4b17023SJohn Marino else if (TREE_CODE (*tp) == STATEMENT_LIST) 813e4b17023SJohn Marino gcc_unreachable (); 814e4b17023SJohn Marino else if (TREE_CODE (*tp) == SAVE_EXPR) 815e4b17023SJohn Marino gcc_unreachable (); 816e4b17023SJohn Marino else if (TREE_CODE (*tp) == LABEL_DECL 817e4b17023SJohn Marino && (!DECL_CONTEXT (*tp) 818e4b17023SJohn Marino || decl_function_context (*tp) == id->src_fn)) 819e4b17023SJohn Marino /* These may need to be remapped for EH handling. */ 820e4b17023SJohn Marino *tp = remap_decl (*tp, id); 821e4b17023SJohn Marino else if (TREE_CODE (*tp) == FIELD_DECL) 822e4b17023SJohn Marino { 823e4b17023SJohn Marino /* If the enclosing record type is variably_modified_type_p, the field 824e4b17023SJohn Marino has already been remapped. Otherwise, it need not be. */ 825e4b17023SJohn Marino tree *n = (tree *) pointer_map_contains (id->decl_map, *tp); 826e4b17023SJohn Marino if (n) 827e4b17023SJohn Marino *tp = *n; 828e4b17023SJohn Marino *walk_subtrees = 0; 829e4b17023SJohn Marino } 830e4b17023SJohn Marino else if (TYPE_P (*tp)) 831e4b17023SJohn Marino /* Types may need remapping as well. */ 832e4b17023SJohn Marino *tp = remap_type (*tp, id); 833e4b17023SJohn Marino else if (CONSTANT_CLASS_P (*tp)) 834e4b17023SJohn Marino { 835e4b17023SJohn Marino /* If this is a constant, we have to copy the node iff the type 836e4b17023SJohn Marino will be remapped. copy_tree_r will not copy a constant. */ 837e4b17023SJohn Marino tree new_type = remap_type (TREE_TYPE (*tp), id); 838e4b17023SJohn Marino 839e4b17023SJohn Marino if (new_type == TREE_TYPE (*tp)) 840e4b17023SJohn Marino *walk_subtrees = 0; 841e4b17023SJohn Marino 842e4b17023SJohn Marino else if (TREE_CODE (*tp) == INTEGER_CST) 843e4b17023SJohn Marino *tp = build_int_cst_wide (new_type, TREE_INT_CST_LOW (*tp), 844e4b17023SJohn Marino TREE_INT_CST_HIGH (*tp)); 845e4b17023SJohn Marino else 846e4b17023SJohn Marino { 847e4b17023SJohn Marino *tp = copy_node (*tp); 848e4b17023SJohn Marino TREE_TYPE (*tp) = new_type; 849e4b17023SJohn Marino } 850e4b17023SJohn Marino } 851e4b17023SJohn Marino else 852e4b17023SJohn Marino { 853e4b17023SJohn Marino /* Otherwise, just copy the node. Note that copy_tree_r already 854e4b17023SJohn Marino knows not to copy VAR_DECLs, etc., so this is safe. */ 855e4b17023SJohn Marino 856e4b17023SJohn Marino /* We should never have TREE_BLOCK set on non-statements. */ 857e4b17023SJohn Marino if (EXPR_P (*tp)) 858e4b17023SJohn Marino gcc_assert (!TREE_BLOCK (*tp)); 859e4b17023SJohn Marino 860e4b17023SJohn Marino if (TREE_CODE (*tp) == MEM_REF) 861e4b17023SJohn Marino { 862e4b17023SJohn Marino tree ptr = TREE_OPERAND (*tp, 0); 863e4b17023SJohn Marino tree type = remap_type (TREE_TYPE (*tp), id); 864e4b17023SJohn Marino tree old = *tp; 865e4b17023SJohn Marino 866e4b17023SJohn Marino /* We need to re-canonicalize MEM_REFs from inline substitutions 867e4b17023SJohn Marino that can happen when a pointer argument is an ADDR_EXPR. 868e4b17023SJohn Marino Recurse here manually to allow that. */ 869e4b17023SJohn Marino walk_tree (&ptr, remap_gimple_op_r, data, NULL); 870e4b17023SJohn Marino *tp = fold_build2 (MEM_REF, type, 871e4b17023SJohn Marino ptr, TREE_OPERAND (*tp, 1)); 872e4b17023SJohn Marino TREE_THIS_NOTRAP (*tp) = TREE_THIS_NOTRAP (old); 873e4b17023SJohn Marino TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old); 874e4b17023SJohn Marino TREE_SIDE_EFFECTS (*tp) = TREE_SIDE_EFFECTS (old); 875e4b17023SJohn Marino TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old); 876e4b17023SJohn Marino *walk_subtrees = 0; 877e4b17023SJohn Marino return NULL; 878e4b17023SJohn Marino } 879e4b17023SJohn Marino 880e4b17023SJohn Marino /* Here is the "usual case". Copy this tree node, and then 881e4b17023SJohn Marino tweak some special cases. */ 882e4b17023SJohn Marino copy_tree_r (tp, walk_subtrees, NULL); 883e4b17023SJohn Marino 884e4b17023SJohn Marino if (TREE_CODE (*tp) != OMP_CLAUSE) 885e4b17023SJohn Marino TREE_TYPE (*tp) = remap_type (TREE_TYPE (*tp), id); 886e4b17023SJohn Marino 887e4b17023SJohn Marino /* Global variables we haven't seen yet need to go into referenced 888e4b17023SJohn Marino vars. If not referenced from types only. */ 889e4b17023SJohn Marino if (gimple_in_ssa_p (cfun) 890e4b17023SJohn Marino && TREE_CODE (*tp) == VAR_DECL 891e4b17023SJohn Marino && id->remapping_type_depth == 0 892e4b17023SJohn Marino && !processing_debug_stmt) 893e4b17023SJohn Marino add_referenced_var (*tp); 894e4b17023SJohn Marino 895e4b17023SJohn Marino if (TREE_CODE (*tp) == TARGET_EXPR && TREE_OPERAND (*tp, 3)) 896e4b17023SJohn Marino { 897e4b17023SJohn Marino /* The copied TARGET_EXPR has never been expanded, even if the 898e4b17023SJohn Marino original node was expanded already. */ 899e4b17023SJohn Marino TREE_OPERAND (*tp, 1) = TREE_OPERAND (*tp, 3); 900e4b17023SJohn Marino TREE_OPERAND (*tp, 3) = NULL_TREE; 901e4b17023SJohn Marino } 902e4b17023SJohn Marino else if (TREE_CODE (*tp) == ADDR_EXPR) 903e4b17023SJohn Marino { 904e4b17023SJohn Marino /* Variable substitution need not be simple. In particular, 905e4b17023SJohn Marino the MEM_REF substitution above. Make sure that 906e4b17023SJohn Marino TREE_CONSTANT and friends are up-to-date. But make sure 907e4b17023SJohn Marino to not improperly set TREE_BLOCK on some sub-expressions. */ 908e4b17023SJohn Marino int invariant = is_gimple_min_invariant (*tp); 909e4b17023SJohn Marino tree block = id->block; 910e4b17023SJohn Marino id->block = NULL_TREE; 911e4b17023SJohn Marino walk_tree (&TREE_OPERAND (*tp, 0), remap_gimple_op_r, data, NULL); 912e4b17023SJohn Marino id->block = block; 913e4b17023SJohn Marino recompute_tree_invariant_for_addr_expr (*tp); 914e4b17023SJohn Marino 915e4b17023SJohn Marino /* If this used to be invariant, but is not any longer, 916e4b17023SJohn Marino then regimplification is probably needed. */ 917e4b17023SJohn Marino if (invariant && !is_gimple_min_invariant (*tp)) 918e4b17023SJohn Marino id->regimplify = true; 919e4b17023SJohn Marino 920e4b17023SJohn Marino *walk_subtrees = 0; 921e4b17023SJohn Marino } 922e4b17023SJohn Marino } 923e4b17023SJohn Marino 924e4b17023SJohn Marino /* Keep iterating. */ 925e4b17023SJohn Marino return NULL_TREE; 926e4b17023SJohn Marino } 927e4b17023SJohn Marino 928e4b17023SJohn Marino 929e4b17023SJohn Marino /* Called from copy_body_id via walk_tree. DATA is really a 930e4b17023SJohn Marino `copy_body_data *'. */ 931e4b17023SJohn Marino 932e4b17023SJohn Marino tree 933e4b17023SJohn Marino copy_tree_body_r (tree *tp, int *walk_subtrees, void *data) 934e4b17023SJohn Marino { 935e4b17023SJohn Marino copy_body_data *id = (copy_body_data *) data; 936e4b17023SJohn Marino tree fn = id->src_fn; 937e4b17023SJohn Marino tree new_block; 938e4b17023SJohn Marino 939e4b17023SJohn Marino /* Begin by recognizing trees that we'll completely rewrite for the 940e4b17023SJohn Marino inlining context. Our output for these trees is completely 941e4b17023SJohn Marino different from out input (e.g. RETURN_EXPR is deleted, and morphs 942e4b17023SJohn Marino into an edge). Further down, we'll handle trees that get 943e4b17023SJohn Marino duplicated and/or tweaked. */ 944e4b17023SJohn Marino 945e4b17023SJohn Marino /* When requested, RETURN_EXPRs should be transformed to just the 946e4b17023SJohn Marino contained MODIFY_EXPR. The branch semantics of the return will 947e4b17023SJohn Marino be handled elsewhere by manipulating the CFG rather than a statement. */ 948e4b17023SJohn Marino if (TREE_CODE (*tp) == RETURN_EXPR && id->transform_return_to_modify) 949e4b17023SJohn Marino { 950e4b17023SJohn Marino tree assignment = TREE_OPERAND (*tp, 0); 951e4b17023SJohn Marino 952e4b17023SJohn Marino /* If we're returning something, just turn that into an 953e4b17023SJohn Marino assignment into the equivalent of the original RESULT_DECL. 954e4b17023SJohn Marino If the "assignment" is just the result decl, the result 955e4b17023SJohn Marino decl has already been set (e.g. a recent "foo (&result_decl, 956e4b17023SJohn Marino ...)"); just toss the entire RETURN_EXPR. */ 957e4b17023SJohn Marino if (assignment && TREE_CODE (assignment) == MODIFY_EXPR) 958e4b17023SJohn Marino { 959e4b17023SJohn Marino /* Replace the RETURN_EXPR with (a copy of) the 960e4b17023SJohn Marino MODIFY_EXPR hanging underneath. */ 961e4b17023SJohn Marino *tp = copy_node (assignment); 962e4b17023SJohn Marino } 963e4b17023SJohn Marino else /* Else the RETURN_EXPR returns no value. */ 964e4b17023SJohn Marino { 965e4b17023SJohn Marino *tp = NULL; 966e4b17023SJohn Marino return (tree) (void *)1; 967e4b17023SJohn Marino } 968e4b17023SJohn Marino } 969e4b17023SJohn Marino else if (TREE_CODE (*tp) == SSA_NAME) 970e4b17023SJohn Marino { 971e4b17023SJohn Marino *tp = remap_ssa_name (*tp, id); 972e4b17023SJohn Marino *walk_subtrees = 0; 973e4b17023SJohn Marino return NULL; 974e4b17023SJohn Marino } 975e4b17023SJohn Marino 976e4b17023SJohn Marino /* Local variables and labels need to be replaced by equivalent 977e4b17023SJohn Marino variables. We don't want to copy static variables; there's only 978e4b17023SJohn Marino one of those, no matter how many times we inline the containing 979e4b17023SJohn Marino function. Similarly for globals from an outer function. */ 980e4b17023SJohn Marino else if (auto_var_in_fn_p (*tp, fn)) 981e4b17023SJohn Marino { 982e4b17023SJohn Marino tree new_decl; 983e4b17023SJohn Marino 984e4b17023SJohn Marino /* Remap the declaration. */ 985e4b17023SJohn Marino new_decl = remap_decl (*tp, id); 986e4b17023SJohn Marino gcc_assert (new_decl); 987e4b17023SJohn Marino /* Replace this variable with the copy. */ 988e4b17023SJohn Marino STRIP_TYPE_NOPS (new_decl); 989e4b17023SJohn Marino *tp = new_decl; 990e4b17023SJohn Marino *walk_subtrees = 0; 991e4b17023SJohn Marino } 992e4b17023SJohn Marino else if (TREE_CODE (*tp) == STATEMENT_LIST) 993e4b17023SJohn Marino copy_statement_list (tp); 994e4b17023SJohn Marino else if (TREE_CODE (*tp) == SAVE_EXPR 995e4b17023SJohn Marino || TREE_CODE (*tp) == TARGET_EXPR) 996e4b17023SJohn Marino remap_save_expr (tp, id->decl_map, walk_subtrees); 997e4b17023SJohn Marino else if (TREE_CODE (*tp) == LABEL_DECL 998e4b17023SJohn Marino && (! DECL_CONTEXT (*tp) 999e4b17023SJohn Marino || decl_function_context (*tp) == id->src_fn)) 1000e4b17023SJohn Marino /* These may need to be remapped for EH handling. */ 1001e4b17023SJohn Marino *tp = remap_decl (*tp, id); 1002e4b17023SJohn Marino else if (TREE_CODE (*tp) == BIND_EXPR) 1003e4b17023SJohn Marino copy_bind_expr (tp, walk_subtrees, id); 1004e4b17023SJohn Marino /* Types may need remapping as well. */ 1005e4b17023SJohn Marino else if (TYPE_P (*tp)) 1006e4b17023SJohn Marino *tp = remap_type (*tp, id); 1007e4b17023SJohn Marino 1008e4b17023SJohn Marino /* If this is a constant, we have to copy the node iff the type will be 1009e4b17023SJohn Marino remapped. copy_tree_r will not copy a constant. */ 1010e4b17023SJohn Marino else if (CONSTANT_CLASS_P (*tp)) 1011e4b17023SJohn Marino { 1012e4b17023SJohn Marino tree new_type = remap_type (TREE_TYPE (*tp), id); 1013e4b17023SJohn Marino 1014e4b17023SJohn Marino if (new_type == TREE_TYPE (*tp)) 1015e4b17023SJohn Marino *walk_subtrees = 0; 1016e4b17023SJohn Marino 1017e4b17023SJohn Marino else if (TREE_CODE (*tp) == INTEGER_CST) 1018e4b17023SJohn Marino *tp = build_int_cst_wide (new_type, TREE_INT_CST_LOW (*tp), 1019e4b17023SJohn Marino TREE_INT_CST_HIGH (*tp)); 1020e4b17023SJohn Marino else 1021e4b17023SJohn Marino { 1022e4b17023SJohn Marino *tp = copy_node (*tp); 1023e4b17023SJohn Marino TREE_TYPE (*tp) = new_type; 1024e4b17023SJohn Marino } 1025e4b17023SJohn Marino } 1026e4b17023SJohn Marino 1027e4b17023SJohn Marino /* Otherwise, just copy the node. Note that copy_tree_r already 1028e4b17023SJohn Marino knows not to copy VAR_DECLs, etc., so this is safe. */ 1029e4b17023SJohn Marino else 1030e4b17023SJohn Marino { 1031e4b17023SJohn Marino /* Here we handle trees that are not completely rewritten. 1032e4b17023SJohn Marino First we detect some inlining-induced bogosities for 1033e4b17023SJohn Marino discarding. */ 1034e4b17023SJohn Marino if (TREE_CODE (*tp) == MODIFY_EXPR 1035e4b17023SJohn Marino && TREE_OPERAND (*tp, 0) == TREE_OPERAND (*tp, 1) 1036e4b17023SJohn Marino && (auto_var_in_fn_p (TREE_OPERAND (*tp, 0), fn))) 1037e4b17023SJohn Marino { 1038e4b17023SJohn Marino /* Some assignments VAR = VAR; don't generate any rtl code 1039e4b17023SJohn Marino and thus don't count as variable modification. Avoid 1040e4b17023SJohn Marino keeping bogosities like 0 = 0. */ 1041e4b17023SJohn Marino tree decl = TREE_OPERAND (*tp, 0), value; 1042e4b17023SJohn Marino tree *n; 1043e4b17023SJohn Marino 1044e4b17023SJohn Marino n = (tree *) pointer_map_contains (id->decl_map, decl); 1045e4b17023SJohn Marino if (n) 1046e4b17023SJohn Marino { 1047e4b17023SJohn Marino value = *n; 1048e4b17023SJohn Marino STRIP_TYPE_NOPS (value); 1049e4b17023SJohn Marino if (TREE_CONSTANT (value) || TREE_READONLY (value)) 1050e4b17023SJohn Marino { 1051e4b17023SJohn Marino *tp = build_empty_stmt (EXPR_LOCATION (*tp)); 1052e4b17023SJohn Marino return copy_tree_body_r (tp, walk_subtrees, data); 1053e4b17023SJohn Marino } 1054e4b17023SJohn Marino } 1055e4b17023SJohn Marino } 1056e4b17023SJohn Marino else if (TREE_CODE (*tp) == INDIRECT_REF) 1057e4b17023SJohn Marino { 1058e4b17023SJohn Marino /* Get rid of *& from inline substitutions that can happen when a 1059e4b17023SJohn Marino pointer argument is an ADDR_EXPR. */ 1060e4b17023SJohn Marino tree decl = TREE_OPERAND (*tp, 0); 1061e4b17023SJohn Marino tree *n; 1062e4b17023SJohn Marino 1063e4b17023SJohn Marino n = (tree *) pointer_map_contains (id->decl_map, decl); 1064e4b17023SJohn Marino if (n) 1065e4b17023SJohn Marino { 1066e4b17023SJohn Marino tree new_tree; 1067e4b17023SJohn Marino tree old; 1068e4b17023SJohn Marino /* If we happen to get an ADDR_EXPR in n->value, strip 1069e4b17023SJohn Marino it manually here as we'll eventually get ADDR_EXPRs 1070e4b17023SJohn Marino which lie about their types pointed to. In this case 1071e4b17023SJohn Marino build_fold_indirect_ref wouldn't strip the INDIRECT_REF, 1072e4b17023SJohn Marino but we absolutely rely on that. As fold_indirect_ref 1073e4b17023SJohn Marino does other useful transformations, try that first, though. */ 1074e4b17023SJohn Marino tree type = TREE_TYPE (TREE_TYPE (*n)); 1075e4b17023SJohn Marino if (id->do_not_unshare) 1076e4b17023SJohn Marino new_tree = *n; 1077e4b17023SJohn Marino else 1078e4b17023SJohn Marino new_tree = unshare_expr (*n); 1079e4b17023SJohn Marino old = *tp; 1080e4b17023SJohn Marino *tp = gimple_fold_indirect_ref (new_tree); 1081e4b17023SJohn Marino if (! *tp) 1082e4b17023SJohn Marino { 1083e4b17023SJohn Marino if (TREE_CODE (new_tree) == ADDR_EXPR) 1084e4b17023SJohn Marino { 1085e4b17023SJohn Marino *tp = fold_indirect_ref_1 (EXPR_LOCATION (new_tree), 1086e4b17023SJohn Marino type, new_tree); 1087e4b17023SJohn Marino /* ??? We should either assert here or build 1088e4b17023SJohn Marino a VIEW_CONVERT_EXPR instead of blindly leaking 1089e4b17023SJohn Marino incompatible types to our IL. */ 1090e4b17023SJohn Marino if (! *tp) 1091e4b17023SJohn Marino *tp = TREE_OPERAND (new_tree, 0); 1092e4b17023SJohn Marino } 1093e4b17023SJohn Marino else 1094e4b17023SJohn Marino { 1095e4b17023SJohn Marino *tp = build1 (INDIRECT_REF, type, new_tree); 1096e4b17023SJohn Marino TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old); 1097e4b17023SJohn Marino TREE_SIDE_EFFECTS (*tp) = TREE_SIDE_EFFECTS (old); 1098e4b17023SJohn Marino TREE_READONLY (*tp) = TREE_READONLY (old); 1099e4b17023SJohn Marino TREE_THIS_NOTRAP (*tp) = TREE_THIS_NOTRAP (old); 1100e4b17023SJohn Marino } 1101e4b17023SJohn Marino } 1102e4b17023SJohn Marino *walk_subtrees = 0; 1103e4b17023SJohn Marino return NULL; 1104e4b17023SJohn Marino } 1105e4b17023SJohn Marino } 1106e4b17023SJohn Marino else if (TREE_CODE (*tp) == MEM_REF) 1107e4b17023SJohn Marino { 1108e4b17023SJohn Marino /* We need to re-canonicalize MEM_REFs from inline substitutions 1109e4b17023SJohn Marino that can happen when a pointer argument is an ADDR_EXPR. */ 1110e4b17023SJohn Marino tree decl = TREE_OPERAND (*tp, 0); 1111e4b17023SJohn Marino tree *n; 1112e4b17023SJohn Marino 1113e4b17023SJohn Marino n = (tree *) pointer_map_contains (id->decl_map, decl); 1114e4b17023SJohn Marino if (n) 1115e4b17023SJohn Marino { 1116e4b17023SJohn Marino tree old = *tp; 1117e4b17023SJohn Marino *tp = fold_build2 (MEM_REF, TREE_TYPE (*tp), 1118e4b17023SJohn Marino unshare_expr (*n), TREE_OPERAND (*tp, 1)); 1119e4b17023SJohn Marino TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old); 1120e4b17023SJohn Marino TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old); 1121e4b17023SJohn Marino *walk_subtrees = 0; 1122e4b17023SJohn Marino return NULL; 1123e4b17023SJohn Marino } 1124e4b17023SJohn Marino } 1125e4b17023SJohn Marino 1126e4b17023SJohn Marino /* Here is the "usual case". Copy this tree node, and then 1127e4b17023SJohn Marino tweak some special cases. */ 1128e4b17023SJohn Marino copy_tree_r (tp, walk_subtrees, NULL); 1129e4b17023SJohn Marino 1130e4b17023SJohn Marino /* Global variables we haven't seen yet needs to go into referenced 1131e4b17023SJohn Marino vars. If not referenced from types or debug stmts only. */ 1132e4b17023SJohn Marino if (gimple_in_ssa_p (cfun) 1133e4b17023SJohn Marino && TREE_CODE (*tp) == VAR_DECL 1134e4b17023SJohn Marino && id->remapping_type_depth == 0 1135e4b17023SJohn Marino && !processing_debug_stmt) 1136e4b17023SJohn Marino add_referenced_var (*tp); 1137e4b17023SJohn Marino 1138e4b17023SJohn Marino /* If EXPR has block defined, map it to newly constructed block. 1139e4b17023SJohn Marino When inlining we want EXPRs without block appear in the block 1140e4b17023SJohn Marino of function call if we are not remapping a type. */ 1141e4b17023SJohn Marino if (EXPR_P (*tp)) 1142e4b17023SJohn Marino { 1143e4b17023SJohn Marino new_block = id->remapping_type_depth == 0 ? id->block : NULL; 1144e4b17023SJohn Marino if (TREE_BLOCK (*tp)) 1145e4b17023SJohn Marino { 1146e4b17023SJohn Marino tree *n; 1147e4b17023SJohn Marino n = (tree *) pointer_map_contains (id->decl_map, 1148e4b17023SJohn Marino TREE_BLOCK (*tp)); 1149e4b17023SJohn Marino gcc_assert (n || id->remapping_type_depth != 0); 1150e4b17023SJohn Marino if (n) 1151e4b17023SJohn Marino new_block = *n; 1152e4b17023SJohn Marino } 1153e4b17023SJohn Marino TREE_BLOCK (*tp) = new_block; 1154e4b17023SJohn Marino } 1155e4b17023SJohn Marino 1156e4b17023SJohn Marino if (TREE_CODE (*tp) != OMP_CLAUSE) 1157e4b17023SJohn Marino TREE_TYPE (*tp) = remap_type (TREE_TYPE (*tp), id); 1158e4b17023SJohn Marino 1159e4b17023SJohn Marino /* The copied TARGET_EXPR has never been expanded, even if the 1160e4b17023SJohn Marino original node was expanded already. */ 1161e4b17023SJohn Marino if (TREE_CODE (*tp) == TARGET_EXPR && TREE_OPERAND (*tp, 3)) 1162e4b17023SJohn Marino { 1163e4b17023SJohn Marino TREE_OPERAND (*tp, 1) = TREE_OPERAND (*tp, 3); 1164e4b17023SJohn Marino TREE_OPERAND (*tp, 3) = NULL_TREE; 1165e4b17023SJohn Marino } 1166e4b17023SJohn Marino 1167e4b17023SJohn Marino /* Variable substitution need not be simple. In particular, the 1168e4b17023SJohn Marino INDIRECT_REF substitution above. Make sure that TREE_CONSTANT 1169e4b17023SJohn Marino and friends are up-to-date. */ 1170e4b17023SJohn Marino else if (TREE_CODE (*tp) == ADDR_EXPR) 1171e4b17023SJohn Marino { 1172e4b17023SJohn Marino int invariant = is_gimple_min_invariant (*tp); 1173e4b17023SJohn Marino walk_tree (&TREE_OPERAND (*tp, 0), copy_tree_body_r, id, NULL); 1174e4b17023SJohn Marino 1175e4b17023SJohn Marino /* Handle the case where we substituted an INDIRECT_REF 1176e4b17023SJohn Marino into the operand of the ADDR_EXPR. */ 1177e4b17023SJohn Marino if (TREE_CODE (TREE_OPERAND (*tp, 0)) == INDIRECT_REF) 1178e4b17023SJohn Marino *tp = TREE_OPERAND (TREE_OPERAND (*tp, 0), 0); 1179e4b17023SJohn Marino else 1180e4b17023SJohn Marino recompute_tree_invariant_for_addr_expr (*tp); 1181e4b17023SJohn Marino 1182e4b17023SJohn Marino /* If this used to be invariant, but is not any longer, 1183e4b17023SJohn Marino then regimplification is probably needed. */ 1184e4b17023SJohn Marino if (invariant && !is_gimple_min_invariant (*tp)) 1185e4b17023SJohn Marino id->regimplify = true; 1186e4b17023SJohn Marino 1187e4b17023SJohn Marino *walk_subtrees = 0; 1188e4b17023SJohn Marino } 1189e4b17023SJohn Marino } 1190e4b17023SJohn Marino 1191e4b17023SJohn Marino /* Keep iterating. */ 1192e4b17023SJohn Marino return NULL_TREE; 1193e4b17023SJohn Marino } 1194e4b17023SJohn Marino 1195e4b17023SJohn Marino /* Helper for remap_gimple_stmt. Given an EH region number for the 1196e4b17023SJohn Marino source function, map that to the duplicate EH region number in 1197e4b17023SJohn Marino the destination function. */ 1198e4b17023SJohn Marino 1199e4b17023SJohn Marino static int 1200e4b17023SJohn Marino remap_eh_region_nr (int old_nr, copy_body_data *id) 1201e4b17023SJohn Marino { 1202e4b17023SJohn Marino eh_region old_r, new_r; 1203e4b17023SJohn Marino void **slot; 1204e4b17023SJohn Marino 1205e4b17023SJohn Marino old_r = get_eh_region_from_number_fn (id->src_cfun, old_nr); 1206e4b17023SJohn Marino slot = pointer_map_contains (id->eh_map, old_r); 1207e4b17023SJohn Marino new_r = (eh_region) *slot; 1208e4b17023SJohn Marino 1209e4b17023SJohn Marino return new_r->index; 1210e4b17023SJohn Marino } 1211e4b17023SJohn Marino 1212e4b17023SJohn Marino /* Similar, but operate on INTEGER_CSTs. */ 1213e4b17023SJohn Marino 1214e4b17023SJohn Marino static tree 1215e4b17023SJohn Marino remap_eh_region_tree_nr (tree old_t_nr, copy_body_data *id) 1216e4b17023SJohn Marino { 1217e4b17023SJohn Marino int old_nr, new_nr; 1218e4b17023SJohn Marino 1219e4b17023SJohn Marino old_nr = tree_low_cst (old_t_nr, 0); 1220e4b17023SJohn Marino new_nr = remap_eh_region_nr (old_nr, id); 1221e4b17023SJohn Marino 1222e4b17023SJohn Marino return build_int_cst (integer_type_node, new_nr); 1223e4b17023SJohn Marino } 1224e4b17023SJohn Marino 1225e4b17023SJohn Marino /* Helper for copy_bb. Remap statement STMT using the inlining 1226e4b17023SJohn Marino information in ID. Return the new statement copy. */ 1227e4b17023SJohn Marino 1228e4b17023SJohn Marino static gimple 1229e4b17023SJohn Marino remap_gimple_stmt (gimple stmt, copy_body_data *id) 1230e4b17023SJohn Marino { 1231e4b17023SJohn Marino gimple copy = NULL; 1232e4b17023SJohn Marino struct walk_stmt_info wi; 1233e4b17023SJohn Marino tree new_block; 1234e4b17023SJohn Marino bool skip_first = false; 1235e4b17023SJohn Marino 1236e4b17023SJohn Marino /* Begin by recognizing trees that we'll completely rewrite for the 1237e4b17023SJohn Marino inlining context. Our output for these trees is completely 1238e4b17023SJohn Marino different from out input (e.g. RETURN_EXPR is deleted, and morphs 1239e4b17023SJohn Marino into an edge). Further down, we'll handle trees that get 1240e4b17023SJohn Marino duplicated and/or tweaked. */ 1241e4b17023SJohn Marino 1242e4b17023SJohn Marino /* When requested, GIMPLE_RETURNs should be transformed to just the 1243e4b17023SJohn Marino contained GIMPLE_ASSIGN. The branch semantics of the return will 1244e4b17023SJohn Marino be handled elsewhere by manipulating the CFG rather than the 1245e4b17023SJohn Marino statement. */ 1246e4b17023SJohn Marino if (gimple_code (stmt) == GIMPLE_RETURN && id->transform_return_to_modify) 1247e4b17023SJohn Marino { 1248e4b17023SJohn Marino tree retval = gimple_return_retval (stmt); 1249e4b17023SJohn Marino 1250e4b17023SJohn Marino /* If we're returning something, just turn that into an 1251e4b17023SJohn Marino assignment into the equivalent of the original RESULT_DECL. 1252e4b17023SJohn Marino If RETVAL is just the result decl, the result decl has 1253e4b17023SJohn Marino already been set (e.g. a recent "foo (&result_decl, ...)"); 1254e4b17023SJohn Marino just toss the entire GIMPLE_RETURN. */ 1255e4b17023SJohn Marino if (retval 1256e4b17023SJohn Marino && (TREE_CODE (retval) != RESULT_DECL 1257e4b17023SJohn Marino && (TREE_CODE (retval) != SSA_NAME 1258e4b17023SJohn Marino || TREE_CODE (SSA_NAME_VAR (retval)) != RESULT_DECL))) 1259e4b17023SJohn Marino { 1260e4b17023SJohn Marino copy = gimple_build_assign (id->retvar, retval); 1261e4b17023SJohn Marino /* id->retvar is already substituted. Skip it on later remapping. */ 1262e4b17023SJohn Marino skip_first = true; 1263e4b17023SJohn Marino } 1264e4b17023SJohn Marino else 1265e4b17023SJohn Marino return gimple_build_nop (); 1266e4b17023SJohn Marino } 1267e4b17023SJohn Marino else if (gimple_has_substatements (stmt)) 1268e4b17023SJohn Marino { 1269e4b17023SJohn Marino gimple_seq s1, s2; 1270e4b17023SJohn Marino 1271e4b17023SJohn Marino /* When cloning bodies from the C++ front end, we will be handed bodies 1272e4b17023SJohn Marino in High GIMPLE form. Handle here all the High GIMPLE statements that 1273e4b17023SJohn Marino have embedded statements. */ 1274e4b17023SJohn Marino switch (gimple_code (stmt)) 1275e4b17023SJohn Marino { 1276e4b17023SJohn Marino case GIMPLE_BIND: 1277e4b17023SJohn Marino copy = copy_gimple_bind (stmt, id); 1278e4b17023SJohn Marino break; 1279e4b17023SJohn Marino 1280e4b17023SJohn Marino case GIMPLE_CATCH: 1281e4b17023SJohn Marino s1 = remap_gimple_seq (gimple_catch_handler (stmt), id); 1282e4b17023SJohn Marino copy = gimple_build_catch (gimple_catch_types (stmt), s1); 1283e4b17023SJohn Marino break; 1284e4b17023SJohn Marino 1285e4b17023SJohn Marino case GIMPLE_EH_FILTER: 1286e4b17023SJohn Marino s1 = remap_gimple_seq (gimple_eh_filter_failure (stmt), id); 1287e4b17023SJohn Marino copy = gimple_build_eh_filter (gimple_eh_filter_types (stmt), s1); 1288e4b17023SJohn Marino break; 1289e4b17023SJohn Marino 1290e4b17023SJohn Marino case GIMPLE_TRY: 1291e4b17023SJohn Marino s1 = remap_gimple_seq (gimple_try_eval (stmt), id); 1292e4b17023SJohn Marino s2 = remap_gimple_seq (gimple_try_cleanup (stmt), id); 1293e4b17023SJohn Marino copy = gimple_build_try (s1, s2, gimple_try_kind (stmt)); 1294e4b17023SJohn Marino break; 1295e4b17023SJohn Marino 1296e4b17023SJohn Marino case GIMPLE_WITH_CLEANUP_EXPR: 1297e4b17023SJohn Marino s1 = remap_gimple_seq (gimple_wce_cleanup (stmt), id); 1298e4b17023SJohn Marino copy = gimple_build_wce (s1); 1299e4b17023SJohn Marino break; 1300e4b17023SJohn Marino 1301e4b17023SJohn Marino case GIMPLE_OMP_PARALLEL: 1302e4b17023SJohn Marino s1 = remap_gimple_seq (gimple_omp_body (stmt), id); 1303e4b17023SJohn Marino copy = gimple_build_omp_parallel 1304e4b17023SJohn Marino (s1, 1305e4b17023SJohn Marino gimple_omp_parallel_clauses (stmt), 1306e4b17023SJohn Marino gimple_omp_parallel_child_fn (stmt), 1307e4b17023SJohn Marino gimple_omp_parallel_data_arg (stmt)); 1308e4b17023SJohn Marino break; 1309e4b17023SJohn Marino 1310e4b17023SJohn Marino case GIMPLE_OMP_TASK: 1311e4b17023SJohn Marino s1 = remap_gimple_seq (gimple_omp_body (stmt), id); 1312e4b17023SJohn Marino copy = gimple_build_omp_task 1313e4b17023SJohn Marino (s1, 1314e4b17023SJohn Marino gimple_omp_task_clauses (stmt), 1315e4b17023SJohn Marino gimple_omp_task_child_fn (stmt), 1316e4b17023SJohn Marino gimple_omp_task_data_arg (stmt), 1317e4b17023SJohn Marino gimple_omp_task_copy_fn (stmt), 1318e4b17023SJohn Marino gimple_omp_task_arg_size (stmt), 1319e4b17023SJohn Marino gimple_omp_task_arg_align (stmt)); 1320e4b17023SJohn Marino break; 1321e4b17023SJohn Marino 1322e4b17023SJohn Marino case GIMPLE_OMP_FOR: 1323e4b17023SJohn Marino s1 = remap_gimple_seq (gimple_omp_body (stmt), id); 1324e4b17023SJohn Marino s2 = remap_gimple_seq (gimple_omp_for_pre_body (stmt), id); 1325e4b17023SJohn Marino copy = gimple_build_omp_for (s1, gimple_omp_for_clauses (stmt), 1326e4b17023SJohn Marino gimple_omp_for_collapse (stmt), s2); 1327e4b17023SJohn Marino { 1328e4b17023SJohn Marino size_t i; 1329e4b17023SJohn Marino for (i = 0; i < gimple_omp_for_collapse (stmt); i++) 1330e4b17023SJohn Marino { 1331e4b17023SJohn Marino gimple_omp_for_set_index (copy, i, 1332e4b17023SJohn Marino gimple_omp_for_index (stmt, i)); 1333e4b17023SJohn Marino gimple_omp_for_set_initial (copy, i, 1334e4b17023SJohn Marino gimple_omp_for_initial (stmt, i)); 1335e4b17023SJohn Marino gimple_omp_for_set_final (copy, i, 1336e4b17023SJohn Marino gimple_omp_for_final (stmt, i)); 1337e4b17023SJohn Marino gimple_omp_for_set_incr (copy, i, 1338e4b17023SJohn Marino gimple_omp_for_incr (stmt, i)); 1339e4b17023SJohn Marino gimple_omp_for_set_cond (copy, i, 1340e4b17023SJohn Marino gimple_omp_for_cond (stmt, i)); 1341e4b17023SJohn Marino } 1342e4b17023SJohn Marino } 1343e4b17023SJohn Marino break; 1344e4b17023SJohn Marino 1345e4b17023SJohn Marino case GIMPLE_OMP_MASTER: 1346e4b17023SJohn Marino s1 = remap_gimple_seq (gimple_omp_body (stmt), id); 1347e4b17023SJohn Marino copy = gimple_build_omp_master (s1); 1348e4b17023SJohn Marino break; 1349e4b17023SJohn Marino 1350e4b17023SJohn Marino case GIMPLE_OMP_ORDERED: 1351e4b17023SJohn Marino s1 = remap_gimple_seq (gimple_omp_body (stmt), id); 1352e4b17023SJohn Marino copy = gimple_build_omp_ordered (s1); 1353e4b17023SJohn Marino break; 1354e4b17023SJohn Marino 1355e4b17023SJohn Marino case GIMPLE_OMP_SECTION: 1356e4b17023SJohn Marino s1 = remap_gimple_seq (gimple_omp_body (stmt), id); 1357e4b17023SJohn Marino copy = gimple_build_omp_section (s1); 1358e4b17023SJohn Marino break; 1359e4b17023SJohn Marino 1360e4b17023SJohn Marino case GIMPLE_OMP_SECTIONS: 1361e4b17023SJohn Marino s1 = remap_gimple_seq (gimple_omp_body (stmt), id); 1362e4b17023SJohn Marino copy = gimple_build_omp_sections 1363e4b17023SJohn Marino (s1, gimple_omp_sections_clauses (stmt)); 1364e4b17023SJohn Marino break; 1365e4b17023SJohn Marino 1366e4b17023SJohn Marino case GIMPLE_OMP_SINGLE: 1367e4b17023SJohn Marino s1 = remap_gimple_seq (gimple_omp_body (stmt), id); 1368e4b17023SJohn Marino copy = gimple_build_omp_single 1369e4b17023SJohn Marino (s1, gimple_omp_single_clauses (stmt)); 1370e4b17023SJohn Marino break; 1371e4b17023SJohn Marino 1372e4b17023SJohn Marino case GIMPLE_OMP_CRITICAL: 1373e4b17023SJohn Marino s1 = remap_gimple_seq (gimple_omp_body (stmt), id); 1374e4b17023SJohn Marino copy 1375e4b17023SJohn Marino = gimple_build_omp_critical (s1, gimple_omp_critical_name (stmt)); 1376e4b17023SJohn Marino break; 1377e4b17023SJohn Marino 1378e4b17023SJohn Marino case GIMPLE_TRANSACTION: 1379e4b17023SJohn Marino s1 = remap_gimple_seq (gimple_transaction_body (stmt), id); 1380e4b17023SJohn Marino copy = gimple_build_transaction (s1, gimple_transaction_label (stmt)); 1381e4b17023SJohn Marino gimple_transaction_set_subcode (copy, gimple_transaction_subcode (stmt)); 1382e4b17023SJohn Marino break; 1383e4b17023SJohn Marino 1384e4b17023SJohn Marino default: 1385e4b17023SJohn Marino gcc_unreachable (); 1386e4b17023SJohn Marino } 1387e4b17023SJohn Marino } 1388e4b17023SJohn Marino else 1389e4b17023SJohn Marino { 1390e4b17023SJohn Marino if (gimple_assign_copy_p (stmt) 1391e4b17023SJohn Marino && gimple_assign_lhs (stmt) == gimple_assign_rhs1 (stmt) 1392e4b17023SJohn Marino && auto_var_in_fn_p (gimple_assign_lhs (stmt), id->src_fn)) 1393e4b17023SJohn Marino { 1394e4b17023SJohn Marino /* Here we handle statements that are not completely rewritten. 1395e4b17023SJohn Marino First we detect some inlining-induced bogosities for 1396e4b17023SJohn Marino discarding. */ 1397e4b17023SJohn Marino 1398e4b17023SJohn Marino /* Some assignments VAR = VAR; don't generate any rtl code 1399e4b17023SJohn Marino and thus don't count as variable modification. Avoid 1400e4b17023SJohn Marino keeping bogosities like 0 = 0. */ 1401e4b17023SJohn Marino tree decl = gimple_assign_lhs (stmt), value; 1402e4b17023SJohn Marino tree *n; 1403e4b17023SJohn Marino 1404e4b17023SJohn Marino n = (tree *) pointer_map_contains (id->decl_map, decl); 1405e4b17023SJohn Marino if (n) 1406e4b17023SJohn Marino { 1407e4b17023SJohn Marino value = *n; 1408e4b17023SJohn Marino STRIP_TYPE_NOPS (value); 1409e4b17023SJohn Marino if (TREE_CONSTANT (value) || TREE_READONLY (value)) 1410e4b17023SJohn Marino return gimple_build_nop (); 1411e4b17023SJohn Marino } 1412e4b17023SJohn Marino } 1413e4b17023SJohn Marino 1414e4b17023SJohn Marino if (gimple_debug_bind_p (stmt)) 1415e4b17023SJohn Marino { 1416e4b17023SJohn Marino copy = gimple_build_debug_bind (gimple_debug_bind_get_var (stmt), 1417e4b17023SJohn Marino gimple_debug_bind_get_value (stmt), 1418e4b17023SJohn Marino stmt); 1419e4b17023SJohn Marino VEC_safe_push (gimple, heap, id->debug_stmts, copy); 1420e4b17023SJohn Marino return copy; 1421e4b17023SJohn Marino } 1422e4b17023SJohn Marino if (gimple_debug_source_bind_p (stmt)) 1423e4b17023SJohn Marino { 1424e4b17023SJohn Marino copy = gimple_build_debug_source_bind 1425e4b17023SJohn Marino (gimple_debug_source_bind_get_var (stmt), 1426e4b17023SJohn Marino gimple_debug_source_bind_get_value (stmt), stmt); 1427e4b17023SJohn Marino VEC_safe_push (gimple, heap, id->debug_stmts, copy); 1428e4b17023SJohn Marino return copy; 1429e4b17023SJohn Marino } 1430e4b17023SJohn Marino 1431e4b17023SJohn Marino /* Create a new deep copy of the statement. */ 1432e4b17023SJohn Marino copy = gimple_copy (stmt); 1433e4b17023SJohn Marino 1434e4b17023SJohn Marino /* Remap the region numbers for __builtin_eh_{pointer,filter}, 1435e4b17023SJohn Marino RESX and EH_DISPATCH. */ 1436e4b17023SJohn Marino if (id->eh_map) 1437e4b17023SJohn Marino switch (gimple_code (copy)) 1438e4b17023SJohn Marino { 1439e4b17023SJohn Marino case GIMPLE_CALL: 1440e4b17023SJohn Marino { 1441e4b17023SJohn Marino tree r, fndecl = gimple_call_fndecl (copy); 1442e4b17023SJohn Marino if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) 1443e4b17023SJohn Marino switch (DECL_FUNCTION_CODE (fndecl)) 1444e4b17023SJohn Marino { 1445e4b17023SJohn Marino case BUILT_IN_EH_COPY_VALUES: 1446e4b17023SJohn Marino r = gimple_call_arg (copy, 1); 1447e4b17023SJohn Marino r = remap_eh_region_tree_nr (r, id); 1448e4b17023SJohn Marino gimple_call_set_arg (copy, 1, r); 1449e4b17023SJohn Marino /* FALLTHRU */ 1450e4b17023SJohn Marino 1451e4b17023SJohn Marino case BUILT_IN_EH_POINTER: 1452e4b17023SJohn Marino case BUILT_IN_EH_FILTER: 1453e4b17023SJohn Marino r = gimple_call_arg (copy, 0); 1454e4b17023SJohn Marino r = remap_eh_region_tree_nr (r, id); 1455e4b17023SJohn Marino gimple_call_set_arg (copy, 0, r); 1456e4b17023SJohn Marino break; 1457e4b17023SJohn Marino 1458e4b17023SJohn Marino default: 1459e4b17023SJohn Marino break; 1460e4b17023SJohn Marino } 1461e4b17023SJohn Marino 1462e4b17023SJohn Marino /* Reset alias info if we didn't apply measures to 1463e4b17023SJohn Marino keep it valid over inlining by setting DECL_PT_UID. */ 1464e4b17023SJohn Marino if (!id->src_cfun->gimple_df 1465e4b17023SJohn Marino || !id->src_cfun->gimple_df->ipa_pta) 1466e4b17023SJohn Marino gimple_call_reset_alias_info (copy); 1467e4b17023SJohn Marino } 1468e4b17023SJohn Marino break; 1469e4b17023SJohn Marino 1470e4b17023SJohn Marino case GIMPLE_RESX: 1471e4b17023SJohn Marino { 1472e4b17023SJohn Marino int r = gimple_resx_region (copy); 1473e4b17023SJohn Marino r = remap_eh_region_nr (r, id); 1474e4b17023SJohn Marino gimple_resx_set_region (copy, r); 1475e4b17023SJohn Marino } 1476e4b17023SJohn Marino break; 1477e4b17023SJohn Marino 1478e4b17023SJohn Marino case GIMPLE_EH_DISPATCH: 1479e4b17023SJohn Marino { 1480e4b17023SJohn Marino int r = gimple_eh_dispatch_region (copy); 1481e4b17023SJohn Marino r = remap_eh_region_nr (r, id); 1482e4b17023SJohn Marino gimple_eh_dispatch_set_region (copy, r); 1483e4b17023SJohn Marino } 1484e4b17023SJohn Marino break; 1485e4b17023SJohn Marino 1486e4b17023SJohn Marino default: 1487e4b17023SJohn Marino break; 1488e4b17023SJohn Marino } 1489e4b17023SJohn Marino } 1490e4b17023SJohn Marino 1491e4b17023SJohn Marino /* If STMT has a block defined, map it to the newly constructed 1492e4b17023SJohn Marino block. When inlining we want statements without a block to 1493e4b17023SJohn Marino appear in the block of the function call. */ 1494e4b17023SJohn Marino new_block = id->block; 1495e4b17023SJohn Marino if (gimple_block (copy)) 1496e4b17023SJohn Marino { 1497e4b17023SJohn Marino tree *n; 1498e4b17023SJohn Marino n = (tree *) pointer_map_contains (id->decl_map, gimple_block (copy)); 1499e4b17023SJohn Marino gcc_assert (n); 1500e4b17023SJohn Marino new_block = *n; 1501e4b17023SJohn Marino } 1502e4b17023SJohn Marino 1503e4b17023SJohn Marino gimple_set_block (copy, new_block); 1504e4b17023SJohn Marino 1505e4b17023SJohn Marino if (gimple_debug_bind_p (copy) || gimple_debug_source_bind_p (copy)) 1506e4b17023SJohn Marino return copy; 1507e4b17023SJohn Marino 1508e4b17023SJohn Marino /* Remap all the operands in COPY. */ 1509e4b17023SJohn Marino memset (&wi, 0, sizeof (wi)); 1510e4b17023SJohn Marino wi.info = id; 1511e4b17023SJohn Marino if (skip_first) 1512e4b17023SJohn Marino walk_tree (gimple_op_ptr (copy, 1), remap_gimple_op_r, &wi, NULL); 1513e4b17023SJohn Marino else 1514e4b17023SJohn Marino walk_gimple_op (copy, remap_gimple_op_r, &wi); 1515e4b17023SJohn Marino 1516e4b17023SJohn Marino /* Clear the copied virtual operands. We are not remapping them here 1517e4b17023SJohn Marino but are going to recreate them from scratch. */ 1518e4b17023SJohn Marino if (gimple_has_mem_ops (copy)) 1519e4b17023SJohn Marino { 1520e4b17023SJohn Marino gimple_set_vdef (copy, NULL_TREE); 1521e4b17023SJohn Marino gimple_set_vuse (copy, NULL_TREE); 1522e4b17023SJohn Marino } 1523e4b17023SJohn Marino 1524e4b17023SJohn Marino return copy; 1525e4b17023SJohn Marino } 1526e4b17023SJohn Marino 1527e4b17023SJohn Marino 1528e4b17023SJohn Marino /* Copy basic block, scale profile accordingly. Edges will be taken care of 1529e4b17023SJohn Marino later */ 1530e4b17023SJohn Marino 1531e4b17023SJohn Marino static basic_block 1532e4b17023SJohn Marino copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, 1533e4b17023SJohn Marino gcov_type count_scale) 1534e4b17023SJohn Marino { 1535e4b17023SJohn Marino gimple_stmt_iterator gsi, copy_gsi, seq_gsi; 1536e4b17023SJohn Marino basic_block copy_basic_block; 1537e4b17023SJohn Marino tree decl; 1538e4b17023SJohn Marino gcov_type freq; 1539e4b17023SJohn Marino basic_block prev; 1540e4b17023SJohn Marino 1541e4b17023SJohn Marino /* Search for previous copied basic block. */ 1542e4b17023SJohn Marino prev = bb->prev_bb; 1543e4b17023SJohn Marino while (!prev->aux) 1544e4b17023SJohn Marino prev = prev->prev_bb; 1545e4b17023SJohn Marino 1546e4b17023SJohn Marino /* create_basic_block() will append every new block to 1547e4b17023SJohn Marino basic_block_info automatically. */ 1548e4b17023SJohn Marino copy_basic_block = create_basic_block (NULL, (void *) 0, 1549e4b17023SJohn Marino (basic_block) prev->aux); 1550e4b17023SJohn Marino copy_basic_block->count = bb->count * count_scale / REG_BR_PROB_BASE; 1551e4b17023SJohn Marino 1552e4b17023SJohn Marino /* We are going to rebuild frequencies from scratch. These values 1553e4b17023SJohn Marino have just small importance to drive canonicalize_loop_headers. */ 1554e4b17023SJohn Marino freq = ((gcov_type)bb->frequency * frequency_scale / REG_BR_PROB_BASE); 1555e4b17023SJohn Marino 1556e4b17023SJohn Marino /* We recompute frequencies after inlining, so this is quite safe. */ 1557e4b17023SJohn Marino if (freq > BB_FREQ_MAX) 1558e4b17023SJohn Marino freq = BB_FREQ_MAX; 1559e4b17023SJohn Marino copy_basic_block->frequency = freq; 1560e4b17023SJohn Marino 1561e4b17023SJohn Marino copy_gsi = gsi_start_bb (copy_basic_block); 1562e4b17023SJohn Marino 1563e4b17023SJohn Marino for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) 1564e4b17023SJohn Marino { 1565e4b17023SJohn Marino gimple stmt = gsi_stmt (gsi); 1566e4b17023SJohn Marino gimple orig_stmt = stmt; 1567e4b17023SJohn Marino 1568e4b17023SJohn Marino id->regimplify = false; 1569e4b17023SJohn Marino stmt = remap_gimple_stmt (stmt, id); 1570e4b17023SJohn Marino if (gimple_nop_p (stmt)) 1571e4b17023SJohn Marino continue; 1572e4b17023SJohn Marino 1573e4b17023SJohn Marino gimple_duplicate_stmt_histograms (cfun, stmt, id->src_cfun, orig_stmt); 1574e4b17023SJohn Marino seq_gsi = copy_gsi; 1575e4b17023SJohn Marino 1576e4b17023SJohn Marino /* With return slot optimization we can end up with 1577e4b17023SJohn Marino non-gimple (foo *)&this->m, fix that here. */ 1578e4b17023SJohn Marino if (is_gimple_assign (stmt) 1579e4b17023SJohn Marino && gimple_assign_rhs_code (stmt) == NOP_EXPR 1580e4b17023SJohn Marino && !is_gimple_val (gimple_assign_rhs1 (stmt))) 1581e4b17023SJohn Marino { 1582e4b17023SJohn Marino tree new_rhs; 1583e4b17023SJohn Marino new_rhs = force_gimple_operand_gsi (&seq_gsi, 1584e4b17023SJohn Marino gimple_assign_rhs1 (stmt), 1585e4b17023SJohn Marino true, NULL, false, 1586e4b17023SJohn Marino GSI_CONTINUE_LINKING); 1587e4b17023SJohn Marino gimple_assign_set_rhs1 (stmt, new_rhs); 1588e4b17023SJohn Marino id->regimplify = false; 1589e4b17023SJohn Marino } 1590e4b17023SJohn Marino 1591e4b17023SJohn Marino gsi_insert_after (&seq_gsi, stmt, GSI_NEW_STMT); 1592e4b17023SJohn Marino 1593e4b17023SJohn Marino if (id->regimplify) 1594e4b17023SJohn Marino gimple_regimplify_operands (stmt, &seq_gsi); 1595e4b17023SJohn Marino 1596e4b17023SJohn Marino /* If copy_basic_block has been empty at the start of this iteration, 1597e4b17023SJohn Marino call gsi_start_bb again to get at the newly added statements. */ 1598e4b17023SJohn Marino if (gsi_end_p (copy_gsi)) 1599e4b17023SJohn Marino copy_gsi = gsi_start_bb (copy_basic_block); 1600e4b17023SJohn Marino else 1601e4b17023SJohn Marino gsi_next (©_gsi); 1602e4b17023SJohn Marino 1603e4b17023SJohn Marino /* Process the new statement. The call to gimple_regimplify_operands 1604e4b17023SJohn Marino possibly turned the statement into multiple statements, we 1605e4b17023SJohn Marino need to process all of them. */ 1606e4b17023SJohn Marino do 1607e4b17023SJohn Marino { 1608e4b17023SJohn Marino tree fn; 1609e4b17023SJohn Marino 1610e4b17023SJohn Marino stmt = gsi_stmt (copy_gsi); 1611e4b17023SJohn Marino if (is_gimple_call (stmt) 1612e4b17023SJohn Marino && gimple_call_va_arg_pack_p (stmt) 1613e4b17023SJohn Marino && id->gimple_call) 1614e4b17023SJohn Marino { 1615e4b17023SJohn Marino /* __builtin_va_arg_pack () should be replaced by 1616e4b17023SJohn Marino all arguments corresponding to ... in the caller. */ 1617e4b17023SJohn Marino tree p; 1618e4b17023SJohn Marino gimple new_call; 1619e4b17023SJohn Marino VEC(tree, heap) *argarray; 1620e4b17023SJohn Marino size_t nargs = gimple_call_num_args (id->gimple_call); 1621e4b17023SJohn Marino size_t n; 1622e4b17023SJohn Marino 1623e4b17023SJohn Marino for (p = DECL_ARGUMENTS (id->src_fn); p; p = DECL_CHAIN (p)) 1624e4b17023SJohn Marino nargs--; 1625e4b17023SJohn Marino 1626e4b17023SJohn Marino /* Create the new array of arguments. */ 1627e4b17023SJohn Marino n = nargs + gimple_call_num_args (stmt); 1628e4b17023SJohn Marino argarray = VEC_alloc (tree, heap, n); 1629e4b17023SJohn Marino VEC_safe_grow (tree, heap, argarray, n); 1630e4b17023SJohn Marino 1631e4b17023SJohn Marino /* Copy all the arguments before '...' */ 1632e4b17023SJohn Marino memcpy (VEC_address (tree, argarray), 1633e4b17023SJohn Marino gimple_call_arg_ptr (stmt, 0), 1634e4b17023SJohn Marino gimple_call_num_args (stmt) * sizeof (tree)); 1635e4b17023SJohn Marino 1636e4b17023SJohn Marino /* Append the arguments passed in '...' */ 1637e4b17023SJohn Marino memcpy (VEC_address(tree, argarray) + gimple_call_num_args (stmt), 1638e4b17023SJohn Marino gimple_call_arg_ptr (id->gimple_call, 0) 1639e4b17023SJohn Marino + (gimple_call_num_args (id->gimple_call) - nargs), 1640e4b17023SJohn Marino nargs * sizeof (tree)); 1641e4b17023SJohn Marino 1642e4b17023SJohn Marino new_call = gimple_build_call_vec (gimple_call_fn (stmt), 1643e4b17023SJohn Marino argarray); 1644e4b17023SJohn Marino 1645e4b17023SJohn Marino VEC_free (tree, heap, argarray); 1646e4b17023SJohn Marino 1647e4b17023SJohn Marino /* Copy all GIMPLE_CALL flags, location and block, except 1648e4b17023SJohn Marino GF_CALL_VA_ARG_PACK. */ 1649e4b17023SJohn Marino gimple_call_copy_flags (new_call, stmt); 1650e4b17023SJohn Marino gimple_call_set_va_arg_pack (new_call, false); 1651e4b17023SJohn Marino gimple_set_location (new_call, gimple_location (stmt)); 1652e4b17023SJohn Marino gimple_set_block (new_call, gimple_block (stmt)); 1653e4b17023SJohn Marino gimple_call_set_lhs (new_call, gimple_call_lhs (stmt)); 1654e4b17023SJohn Marino 1655e4b17023SJohn Marino gsi_replace (©_gsi, new_call, false); 1656e4b17023SJohn Marino stmt = new_call; 1657e4b17023SJohn Marino } 1658e4b17023SJohn Marino else if (is_gimple_call (stmt) 1659e4b17023SJohn Marino && id->gimple_call 1660e4b17023SJohn Marino && (decl = gimple_call_fndecl (stmt)) 1661e4b17023SJohn Marino && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL 1662e4b17023SJohn Marino && DECL_FUNCTION_CODE (decl) == BUILT_IN_VA_ARG_PACK_LEN) 1663e4b17023SJohn Marino { 1664e4b17023SJohn Marino /* __builtin_va_arg_pack_len () should be replaced by 1665e4b17023SJohn Marino the number of anonymous arguments. */ 1666e4b17023SJohn Marino size_t nargs = gimple_call_num_args (id->gimple_call); 1667e4b17023SJohn Marino tree count, p; 1668e4b17023SJohn Marino gimple new_stmt; 1669e4b17023SJohn Marino 1670e4b17023SJohn Marino for (p = DECL_ARGUMENTS (id->src_fn); p; p = DECL_CHAIN (p)) 1671e4b17023SJohn Marino nargs--; 1672e4b17023SJohn Marino 1673e4b17023SJohn Marino count = build_int_cst (integer_type_node, nargs); 1674e4b17023SJohn Marino new_stmt = gimple_build_assign (gimple_call_lhs (stmt), count); 1675e4b17023SJohn Marino gsi_replace (©_gsi, new_stmt, false); 1676e4b17023SJohn Marino stmt = new_stmt; 1677e4b17023SJohn Marino } 1678e4b17023SJohn Marino 1679e4b17023SJohn Marino /* Statements produced by inlining can be unfolded, especially 1680e4b17023SJohn Marino when we constant propagated some operands. We can't fold 1681e4b17023SJohn Marino them right now for two reasons: 1682e4b17023SJohn Marino 1) folding require SSA_NAME_DEF_STMTs to be correct 1683e4b17023SJohn Marino 2) we can't change function calls to builtins. 1684e4b17023SJohn Marino So we just mark statement for later folding. We mark 1685e4b17023SJohn Marino all new statements, instead just statements that has changed 1686e4b17023SJohn Marino by some nontrivial substitution so even statements made 1687e4b17023SJohn Marino foldable indirectly are updated. If this turns out to be 1688e4b17023SJohn Marino expensive, copy_body can be told to watch for nontrivial 1689e4b17023SJohn Marino changes. */ 1690e4b17023SJohn Marino if (id->statements_to_fold) 1691e4b17023SJohn Marino pointer_set_insert (id->statements_to_fold, stmt); 1692e4b17023SJohn Marino 1693e4b17023SJohn Marino /* We're duplicating a CALL_EXPR. Find any corresponding 1694e4b17023SJohn Marino callgraph edges and update or duplicate them. */ 1695e4b17023SJohn Marino if (is_gimple_call (stmt)) 1696e4b17023SJohn Marino { 1697e4b17023SJohn Marino struct cgraph_edge *edge; 1698e4b17023SJohn Marino int flags; 1699e4b17023SJohn Marino 1700e4b17023SJohn Marino switch (id->transform_call_graph_edges) 1701e4b17023SJohn Marino { 1702e4b17023SJohn Marino case CB_CGE_DUPLICATE: 1703e4b17023SJohn Marino edge = cgraph_edge (id->src_node, orig_stmt); 1704e4b17023SJohn Marino if (edge) 1705e4b17023SJohn Marino { 1706e4b17023SJohn Marino int edge_freq = edge->frequency; 1707e4b17023SJohn Marino edge = cgraph_clone_edge (edge, id->dst_node, stmt, 1708e4b17023SJohn Marino gimple_uid (stmt), 1709e4b17023SJohn Marino REG_BR_PROB_BASE, CGRAPH_FREQ_BASE, 1710e4b17023SJohn Marino true); 1711e4b17023SJohn Marino /* We could also just rescale the frequency, but 1712e4b17023SJohn Marino doing so would introduce roundoff errors and make 1713e4b17023SJohn Marino verifier unhappy. */ 1714e4b17023SJohn Marino edge->frequency 1715e4b17023SJohn Marino = compute_call_stmt_bb_frequency (id->dst_node->decl, 1716e4b17023SJohn Marino copy_basic_block); 1717e4b17023SJohn Marino if (dump_file 1718e4b17023SJohn Marino && profile_status_for_function (cfun) != PROFILE_ABSENT 1719e4b17023SJohn Marino && (edge_freq > edge->frequency + 10 1720e4b17023SJohn Marino || edge_freq < edge->frequency - 10)) 1721e4b17023SJohn Marino { 1722e4b17023SJohn Marino fprintf (dump_file, "Edge frequency estimated by " 1723e4b17023SJohn Marino "cgraph %i diverge from inliner's estimate %i\n", 1724e4b17023SJohn Marino edge_freq, 1725e4b17023SJohn Marino edge->frequency); 1726e4b17023SJohn Marino fprintf (dump_file, 1727e4b17023SJohn Marino "Orig bb: %i, orig bb freq %i, new bb freq %i\n", 1728e4b17023SJohn Marino bb->index, 1729e4b17023SJohn Marino bb->frequency, 1730e4b17023SJohn Marino copy_basic_block->frequency); 1731e4b17023SJohn Marino } 1732e4b17023SJohn Marino stmt = cgraph_redirect_edge_call_stmt_to_callee (edge); 1733e4b17023SJohn Marino } 1734e4b17023SJohn Marino break; 1735e4b17023SJohn Marino 1736e4b17023SJohn Marino case CB_CGE_MOVE_CLONES: 1737e4b17023SJohn Marino cgraph_set_call_stmt_including_clones (id->dst_node, 1738e4b17023SJohn Marino orig_stmt, stmt); 1739e4b17023SJohn Marino edge = cgraph_edge (id->dst_node, stmt); 1740e4b17023SJohn Marino break; 1741e4b17023SJohn Marino 1742e4b17023SJohn Marino case CB_CGE_MOVE: 1743e4b17023SJohn Marino edge = cgraph_edge (id->dst_node, orig_stmt); 1744e4b17023SJohn Marino if (edge) 1745e4b17023SJohn Marino cgraph_set_call_stmt (edge, stmt); 1746e4b17023SJohn Marino break; 1747e4b17023SJohn Marino 1748e4b17023SJohn Marino default: 1749e4b17023SJohn Marino gcc_unreachable (); 1750e4b17023SJohn Marino } 1751e4b17023SJohn Marino 1752e4b17023SJohn Marino /* Constant propagation on argument done during inlining 1753e4b17023SJohn Marino may create new direct call. Produce an edge for it. */ 1754e4b17023SJohn Marino if ((!edge 1755e4b17023SJohn Marino || (edge->indirect_inlining_edge 1756e4b17023SJohn Marino && id->transform_call_graph_edges == CB_CGE_MOVE_CLONES)) 1757e4b17023SJohn Marino && id->dst_node->analyzed 1758e4b17023SJohn Marino && (fn = gimple_call_fndecl (stmt)) != NULL) 1759e4b17023SJohn Marino { 1760e4b17023SJohn Marino struct cgraph_node *dest = cgraph_get_node (fn); 1761e4b17023SJohn Marino 1762e4b17023SJohn Marino /* We have missing edge in the callgraph. This can happen 1763e4b17023SJohn Marino when previous inlining turned an indirect call into a 1764e4b17023SJohn Marino direct call by constant propagating arguments or we are 1765e4b17023SJohn Marino producing dead clone (for further cloning). In all 1766e4b17023SJohn Marino other cases we hit a bug (incorrect node sharing is the 1767e4b17023SJohn Marino most common reason for missing edges). */ 1768e4b17023SJohn Marino gcc_assert (dest->needed || !dest->analyzed 1769e4b17023SJohn Marino || dest->address_taken 1770e4b17023SJohn Marino || !id->src_node->analyzed 1771e4b17023SJohn Marino || !id->dst_node->analyzed); 1772e4b17023SJohn Marino if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES) 1773e4b17023SJohn Marino cgraph_create_edge_including_clones 1774e4b17023SJohn Marino (id->dst_node, dest, orig_stmt, stmt, bb->count, 1775e4b17023SJohn Marino compute_call_stmt_bb_frequency (id->dst_node->decl, 1776e4b17023SJohn Marino copy_basic_block), 1777e4b17023SJohn Marino CIF_ORIGINALLY_INDIRECT_CALL); 1778e4b17023SJohn Marino else 1779e4b17023SJohn Marino cgraph_create_edge (id->dst_node, dest, stmt, 1780e4b17023SJohn Marino bb->count, 1781e4b17023SJohn Marino compute_call_stmt_bb_frequency 1782e4b17023SJohn Marino (id->dst_node->decl, copy_basic_block))->inline_failed 1783e4b17023SJohn Marino = CIF_ORIGINALLY_INDIRECT_CALL; 1784e4b17023SJohn Marino if (dump_file) 1785e4b17023SJohn Marino { 1786e4b17023SJohn Marino fprintf (dump_file, "Created new direct edge to %s\n", 1787e4b17023SJohn Marino cgraph_node_name (dest)); 1788e4b17023SJohn Marino } 1789e4b17023SJohn Marino } 1790e4b17023SJohn Marino 1791e4b17023SJohn Marino flags = gimple_call_flags (stmt); 1792e4b17023SJohn Marino if (flags & ECF_MAY_BE_ALLOCA) 1793e4b17023SJohn Marino cfun->calls_alloca = true; 1794e4b17023SJohn Marino if (flags & ECF_RETURNS_TWICE) 1795e4b17023SJohn Marino cfun->calls_setjmp = true; 1796e4b17023SJohn Marino } 1797e4b17023SJohn Marino 1798e4b17023SJohn Marino maybe_duplicate_eh_stmt_fn (cfun, stmt, id->src_cfun, orig_stmt, 1799e4b17023SJohn Marino id->eh_map, id->eh_lp_nr); 1800e4b17023SJohn Marino 1801e4b17023SJohn Marino if (gimple_in_ssa_p (cfun) && !is_gimple_debug (stmt)) 1802e4b17023SJohn Marino { 1803e4b17023SJohn Marino ssa_op_iter i; 1804e4b17023SJohn Marino tree def; 1805e4b17023SJohn Marino 1806e4b17023SJohn Marino find_new_referenced_vars (gsi_stmt (copy_gsi)); 1807e4b17023SJohn Marino FOR_EACH_SSA_TREE_OPERAND (def, stmt, i, SSA_OP_DEF) 1808e4b17023SJohn Marino if (TREE_CODE (def) == SSA_NAME) 1809e4b17023SJohn Marino SSA_NAME_DEF_STMT (def) = stmt; 1810e4b17023SJohn Marino } 1811e4b17023SJohn Marino 1812e4b17023SJohn Marino gsi_next (©_gsi); 1813e4b17023SJohn Marino } 1814e4b17023SJohn Marino while (!gsi_end_p (copy_gsi)); 1815e4b17023SJohn Marino 1816e4b17023SJohn Marino copy_gsi = gsi_last_bb (copy_basic_block); 1817e4b17023SJohn Marino } 1818e4b17023SJohn Marino 1819e4b17023SJohn Marino return copy_basic_block; 1820e4b17023SJohn Marino } 1821e4b17023SJohn Marino 1822e4b17023SJohn Marino /* Inserting Single Entry Multiple Exit region in SSA form into code in SSA 1823e4b17023SJohn Marino form is quite easy, since dominator relationship for old basic blocks does 1824e4b17023SJohn Marino not change. 1825e4b17023SJohn Marino 1826e4b17023SJohn Marino There is however exception where inlining might change dominator relation 1827e4b17023SJohn Marino across EH edges from basic block within inlined functions destinating 1828e4b17023SJohn Marino to landing pads in function we inline into. 1829e4b17023SJohn Marino 1830e4b17023SJohn Marino The function fills in PHI_RESULTs of such PHI nodes if they refer 1831e4b17023SJohn Marino to gimple regs. Otherwise, the function mark PHI_RESULT of such 1832e4b17023SJohn Marino PHI nodes for renaming. For non-gimple regs, renaming is safe: the 1833e4b17023SJohn Marino EH edges are abnormal and SSA_NAME_OCCURS_IN_ABNORMAL_PHI must be 1834e4b17023SJohn Marino set, and this means that there will be no overlapping live ranges 1835e4b17023SJohn Marino for the underlying symbol. 1836e4b17023SJohn Marino 1837e4b17023SJohn Marino This might change in future if we allow redirecting of EH edges and 1838e4b17023SJohn Marino we might want to change way build CFG pre-inlining to include 1839e4b17023SJohn Marino all the possible edges then. */ 1840e4b17023SJohn Marino static void 1841e4b17023SJohn Marino update_ssa_across_abnormal_edges (basic_block bb, basic_block ret_bb, 1842e4b17023SJohn Marino bool can_throw, bool nonlocal_goto) 1843e4b17023SJohn Marino { 1844e4b17023SJohn Marino edge e; 1845e4b17023SJohn Marino edge_iterator ei; 1846e4b17023SJohn Marino 1847e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs) 1848e4b17023SJohn Marino if (!e->dest->aux 1849e4b17023SJohn Marino || ((basic_block)e->dest->aux)->index == ENTRY_BLOCK) 1850e4b17023SJohn Marino { 1851e4b17023SJohn Marino gimple phi; 1852e4b17023SJohn Marino gimple_stmt_iterator si; 1853e4b17023SJohn Marino 1854e4b17023SJohn Marino if (!nonlocal_goto) 1855e4b17023SJohn Marino gcc_assert (e->flags & EDGE_EH); 1856e4b17023SJohn Marino 1857e4b17023SJohn Marino if (!can_throw) 1858e4b17023SJohn Marino gcc_assert (!(e->flags & EDGE_EH)); 1859e4b17023SJohn Marino 1860e4b17023SJohn Marino for (si = gsi_start_phis (e->dest); !gsi_end_p (si); gsi_next (&si)) 1861e4b17023SJohn Marino { 1862e4b17023SJohn Marino edge re; 1863e4b17023SJohn Marino 1864e4b17023SJohn Marino phi = gsi_stmt (si); 1865e4b17023SJohn Marino 1866e4b17023SJohn Marino /* There shouldn't be any PHI nodes in the ENTRY_BLOCK. */ 1867e4b17023SJohn Marino gcc_assert (!e->dest->aux); 1868e4b17023SJohn Marino 1869e4b17023SJohn Marino gcc_assert ((e->flags & EDGE_EH) 1870e4b17023SJohn Marino || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (phi))); 1871e4b17023SJohn Marino 1872e4b17023SJohn Marino if (!is_gimple_reg (PHI_RESULT (phi))) 1873e4b17023SJohn Marino { 1874e4b17023SJohn Marino mark_sym_for_renaming (SSA_NAME_VAR (PHI_RESULT (phi))); 1875e4b17023SJohn Marino continue; 1876e4b17023SJohn Marino } 1877e4b17023SJohn Marino 1878e4b17023SJohn Marino re = find_edge (ret_bb, e->dest); 1879e4b17023SJohn Marino gcc_assert (re); 1880e4b17023SJohn Marino gcc_assert ((re->flags & (EDGE_EH | EDGE_ABNORMAL)) 1881e4b17023SJohn Marino == (e->flags & (EDGE_EH | EDGE_ABNORMAL))); 1882e4b17023SJohn Marino 1883e4b17023SJohn Marino SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), 1884e4b17023SJohn Marino USE_FROM_PTR (PHI_ARG_DEF_PTR_FROM_EDGE (phi, re))); 1885e4b17023SJohn Marino } 1886e4b17023SJohn Marino } 1887e4b17023SJohn Marino } 1888e4b17023SJohn Marino 1889e4b17023SJohn Marino 1890e4b17023SJohn Marino /* Copy edges from BB into its copy constructed earlier, scale profile 1891e4b17023SJohn Marino accordingly. Edges will be taken care of later. Assume aux 1892e4b17023SJohn Marino pointers to point to the copies of each BB. Return true if any 1893e4b17023SJohn Marino debug stmts are left after a statement that must end the basic block. */ 1894e4b17023SJohn Marino 1895e4b17023SJohn Marino static bool 1896e4b17023SJohn Marino copy_edges_for_bb (basic_block bb, gcov_type count_scale, basic_block ret_bb) 1897e4b17023SJohn Marino { 1898e4b17023SJohn Marino basic_block new_bb = (basic_block) bb->aux; 1899e4b17023SJohn Marino edge_iterator ei; 1900e4b17023SJohn Marino edge old_edge; 1901e4b17023SJohn Marino gimple_stmt_iterator si; 1902e4b17023SJohn Marino int flags; 1903e4b17023SJohn Marino bool need_debug_cleanup = false; 1904e4b17023SJohn Marino 1905e4b17023SJohn Marino /* Use the indices from the original blocks to create edges for the 1906e4b17023SJohn Marino new ones. */ 1907e4b17023SJohn Marino FOR_EACH_EDGE (old_edge, ei, bb->succs) 1908e4b17023SJohn Marino if (!(old_edge->flags & EDGE_EH)) 1909e4b17023SJohn Marino { 1910e4b17023SJohn Marino edge new_edge; 1911e4b17023SJohn Marino 1912e4b17023SJohn Marino flags = old_edge->flags; 1913e4b17023SJohn Marino 1914e4b17023SJohn Marino /* Return edges do get a FALLTHRU flag when the get inlined. */ 1915e4b17023SJohn Marino if (old_edge->dest->index == EXIT_BLOCK && !old_edge->flags 1916e4b17023SJohn Marino && old_edge->dest->aux != EXIT_BLOCK_PTR) 1917e4b17023SJohn Marino flags |= EDGE_FALLTHRU; 1918e4b17023SJohn Marino new_edge = make_edge (new_bb, (basic_block) old_edge->dest->aux, flags); 1919e4b17023SJohn Marino new_edge->count = old_edge->count * count_scale / REG_BR_PROB_BASE; 1920e4b17023SJohn Marino new_edge->probability = old_edge->probability; 1921e4b17023SJohn Marino } 1922e4b17023SJohn Marino 1923e4b17023SJohn Marino if (bb->index == ENTRY_BLOCK || bb->index == EXIT_BLOCK) 1924e4b17023SJohn Marino return false; 1925e4b17023SJohn Marino 1926e4b17023SJohn Marino for (si = gsi_start_bb (new_bb); !gsi_end_p (si);) 1927e4b17023SJohn Marino { 1928e4b17023SJohn Marino gimple copy_stmt; 1929e4b17023SJohn Marino bool can_throw, nonlocal_goto; 1930e4b17023SJohn Marino 1931e4b17023SJohn Marino copy_stmt = gsi_stmt (si); 1932e4b17023SJohn Marino if (!is_gimple_debug (copy_stmt)) 1933e4b17023SJohn Marino { 1934e4b17023SJohn Marino update_stmt (copy_stmt); 1935e4b17023SJohn Marino if (gimple_in_ssa_p (cfun)) 1936e4b17023SJohn Marino mark_symbols_for_renaming (copy_stmt); 1937e4b17023SJohn Marino } 1938e4b17023SJohn Marino 1939e4b17023SJohn Marino /* Do this before the possible split_block. */ 1940e4b17023SJohn Marino gsi_next (&si); 1941e4b17023SJohn Marino 1942e4b17023SJohn Marino /* If this tree could throw an exception, there are two 1943e4b17023SJohn Marino cases where we need to add abnormal edge(s): the 1944e4b17023SJohn Marino tree wasn't in a region and there is a "current 1945e4b17023SJohn Marino region" in the caller; or the original tree had 1946e4b17023SJohn Marino EH edges. In both cases split the block after the tree, 1947e4b17023SJohn Marino and add abnormal edge(s) as needed; we need both 1948e4b17023SJohn Marino those from the callee and the caller. 1949e4b17023SJohn Marino We check whether the copy can throw, because the const 1950e4b17023SJohn Marino propagation can change an INDIRECT_REF which throws 1951e4b17023SJohn Marino into a COMPONENT_REF which doesn't. If the copy 1952e4b17023SJohn Marino can throw, the original could also throw. */ 1953e4b17023SJohn Marino can_throw = stmt_can_throw_internal (copy_stmt); 1954e4b17023SJohn Marino nonlocal_goto = stmt_can_make_abnormal_goto (copy_stmt); 1955e4b17023SJohn Marino 1956e4b17023SJohn Marino if (can_throw || nonlocal_goto) 1957e4b17023SJohn Marino { 1958e4b17023SJohn Marino if (!gsi_end_p (si)) 1959e4b17023SJohn Marino { 1960e4b17023SJohn Marino while (!gsi_end_p (si) && is_gimple_debug (gsi_stmt (si))) 1961e4b17023SJohn Marino gsi_next (&si); 1962e4b17023SJohn Marino if (gsi_end_p (si)) 1963e4b17023SJohn Marino need_debug_cleanup = true; 1964e4b17023SJohn Marino } 1965e4b17023SJohn Marino if (!gsi_end_p (si)) 1966e4b17023SJohn Marino /* Note that bb's predecessor edges aren't necessarily 1967e4b17023SJohn Marino right at this point; split_block doesn't care. */ 1968e4b17023SJohn Marino { 1969e4b17023SJohn Marino edge e = split_block (new_bb, copy_stmt); 1970e4b17023SJohn Marino 1971e4b17023SJohn Marino new_bb = e->dest; 1972e4b17023SJohn Marino new_bb->aux = e->src->aux; 1973e4b17023SJohn Marino si = gsi_start_bb (new_bb); 1974e4b17023SJohn Marino } 1975e4b17023SJohn Marino } 1976e4b17023SJohn Marino 1977e4b17023SJohn Marino if (gimple_code (copy_stmt) == GIMPLE_EH_DISPATCH) 1978e4b17023SJohn Marino make_eh_dispatch_edges (copy_stmt); 1979e4b17023SJohn Marino else if (can_throw) 1980e4b17023SJohn Marino make_eh_edges (copy_stmt); 1981e4b17023SJohn Marino 1982e4b17023SJohn Marino if (nonlocal_goto) 1983e4b17023SJohn Marino make_abnormal_goto_edges (gimple_bb (copy_stmt), true); 1984e4b17023SJohn Marino 1985e4b17023SJohn Marino if ((can_throw || nonlocal_goto) 1986e4b17023SJohn Marino && gimple_in_ssa_p (cfun)) 1987e4b17023SJohn Marino update_ssa_across_abnormal_edges (gimple_bb (copy_stmt), ret_bb, 1988e4b17023SJohn Marino can_throw, nonlocal_goto); 1989e4b17023SJohn Marino } 1990e4b17023SJohn Marino return need_debug_cleanup; 1991e4b17023SJohn Marino } 1992e4b17023SJohn Marino 1993e4b17023SJohn Marino /* Copy the PHIs. All blocks and edges are copied, some blocks 1994e4b17023SJohn Marino was possibly split and new outgoing EH edges inserted. 1995e4b17023SJohn Marino BB points to the block of original function and AUX pointers links 1996e4b17023SJohn Marino the original and newly copied blocks. */ 1997e4b17023SJohn Marino 1998e4b17023SJohn Marino static void 1999e4b17023SJohn Marino copy_phis_for_bb (basic_block bb, copy_body_data *id) 2000e4b17023SJohn Marino { 2001e4b17023SJohn Marino basic_block const new_bb = (basic_block) bb->aux; 2002e4b17023SJohn Marino edge_iterator ei; 2003e4b17023SJohn Marino gimple phi; 2004e4b17023SJohn Marino gimple_stmt_iterator si; 2005e4b17023SJohn Marino edge new_edge; 2006e4b17023SJohn Marino bool inserted = false; 2007e4b17023SJohn Marino 2008e4b17023SJohn Marino for (si = gsi_start (phi_nodes (bb)); !gsi_end_p (si); gsi_next (&si)) 2009e4b17023SJohn Marino { 2010e4b17023SJohn Marino tree res, new_res; 2011e4b17023SJohn Marino gimple new_phi; 2012e4b17023SJohn Marino 2013e4b17023SJohn Marino phi = gsi_stmt (si); 2014e4b17023SJohn Marino res = PHI_RESULT (phi); 2015e4b17023SJohn Marino new_res = res; 2016e4b17023SJohn Marino if (is_gimple_reg (res)) 2017e4b17023SJohn Marino { 2018e4b17023SJohn Marino walk_tree (&new_res, copy_tree_body_r, id, NULL); 2019e4b17023SJohn Marino SSA_NAME_DEF_STMT (new_res) 2020e4b17023SJohn Marino = new_phi = create_phi_node (new_res, new_bb); 2021e4b17023SJohn Marino FOR_EACH_EDGE (new_edge, ei, new_bb->preds) 2022e4b17023SJohn Marino { 2023e4b17023SJohn Marino edge old_edge = find_edge ((basic_block) new_edge->src->aux, bb); 2024e4b17023SJohn Marino tree arg; 2025e4b17023SJohn Marino tree new_arg; 2026e4b17023SJohn Marino tree block = id->block; 2027e4b17023SJohn Marino edge_iterator ei2; 2028e4b17023SJohn Marino 2029e4b17023SJohn Marino /* When doing partial cloning, we allow PHIs on the entry block 2030e4b17023SJohn Marino as long as all the arguments are the same. Find any input 2031e4b17023SJohn Marino edge to see argument to copy. */ 2032e4b17023SJohn Marino if (!old_edge) 2033e4b17023SJohn Marino FOR_EACH_EDGE (old_edge, ei2, bb->preds) 2034e4b17023SJohn Marino if (!old_edge->src->aux) 2035e4b17023SJohn Marino break; 2036e4b17023SJohn Marino 2037e4b17023SJohn Marino arg = PHI_ARG_DEF_FROM_EDGE (phi, old_edge); 2038e4b17023SJohn Marino new_arg = arg; 2039e4b17023SJohn Marino id->block = NULL_TREE; 2040e4b17023SJohn Marino walk_tree (&new_arg, copy_tree_body_r, id, NULL); 2041e4b17023SJohn Marino id->block = block; 2042e4b17023SJohn Marino gcc_assert (new_arg); 2043e4b17023SJohn Marino /* With return slot optimization we can end up with 2044e4b17023SJohn Marino non-gimple (foo *)&this->m, fix that here. */ 2045e4b17023SJohn Marino if (TREE_CODE (new_arg) != SSA_NAME 2046e4b17023SJohn Marino && TREE_CODE (new_arg) != FUNCTION_DECL 2047e4b17023SJohn Marino && !is_gimple_val (new_arg)) 2048e4b17023SJohn Marino { 2049e4b17023SJohn Marino gimple_seq stmts = NULL; 2050e4b17023SJohn Marino new_arg = force_gimple_operand (new_arg, &stmts, true, NULL); 2051e4b17023SJohn Marino gsi_insert_seq_on_edge (new_edge, stmts); 2052e4b17023SJohn Marino inserted = true; 2053e4b17023SJohn Marino } 2054e4b17023SJohn Marino add_phi_arg (new_phi, new_arg, new_edge, 2055e4b17023SJohn Marino gimple_phi_arg_location_from_edge (phi, old_edge)); 2056e4b17023SJohn Marino } 2057e4b17023SJohn Marino } 2058e4b17023SJohn Marino } 2059e4b17023SJohn Marino 2060e4b17023SJohn Marino /* Commit the delayed edge insertions. */ 2061e4b17023SJohn Marino if (inserted) 2062e4b17023SJohn Marino FOR_EACH_EDGE (new_edge, ei, new_bb->preds) 2063e4b17023SJohn Marino gsi_commit_one_edge_insert (new_edge, NULL); 2064e4b17023SJohn Marino } 2065e4b17023SJohn Marino 2066e4b17023SJohn Marino 2067e4b17023SJohn Marino /* Wrapper for remap_decl so it can be used as a callback. */ 2068e4b17023SJohn Marino 2069e4b17023SJohn Marino static tree 2070e4b17023SJohn Marino remap_decl_1 (tree decl, void *data) 2071e4b17023SJohn Marino { 2072e4b17023SJohn Marino return remap_decl (decl, (copy_body_data *) data); 2073e4b17023SJohn Marino } 2074e4b17023SJohn Marino 2075e4b17023SJohn Marino /* Build struct function and associated datastructures for the new clone 2076e4b17023SJohn Marino NEW_FNDECL to be build. CALLEE_FNDECL is the original */ 2077e4b17023SJohn Marino 2078e4b17023SJohn Marino static void 2079e4b17023SJohn Marino initialize_cfun (tree new_fndecl, tree callee_fndecl, gcov_type count) 2080e4b17023SJohn Marino { 2081e4b17023SJohn Marino struct function *src_cfun = DECL_STRUCT_FUNCTION (callee_fndecl); 2082e4b17023SJohn Marino gcov_type count_scale; 2083e4b17023SJohn Marino 2084e4b17023SJohn Marino if (ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count) 2085e4b17023SJohn Marino count_scale = (REG_BR_PROB_BASE * count 2086e4b17023SJohn Marino / ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count); 2087e4b17023SJohn Marino else 2088e4b17023SJohn Marino count_scale = REG_BR_PROB_BASE; 2089e4b17023SJohn Marino 2090e4b17023SJohn Marino /* Register specific tree functions. */ 2091e4b17023SJohn Marino gimple_register_cfg_hooks (); 2092e4b17023SJohn Marino 2093e4b17023SJohn Marino /* Get clean struct function. */ 2094e4b17023SJohn Marino push_struct_function (new_fndecl); 2095e4b17023SJohn Marino 2096e4b17023SJohn Marino /* We will rebuild these, so just sanity check that they are empty. */ 2097e4b17023SJohn Marino gcc_assert (VALUE_HISTOGRAMS (cfun) == NULL); 2098e4b17023SJohn Marino gcc_assert (cfun->local_decls == NULL); 2099e4b17023SJohn Marino gcc_assert (cfun->cfg == NULL); 2100e4b17023SJohn Marino gcc_assert (cfun->decl == new_fndecl); 2101e4b17023SJohn Marino 2102e4b17023SJohn Marino /* Copy items we preserve during cloning. */ 2103e4b17023SJohn Marino cfun->static_chain_decl = src_cfun->static_chain_decl; 2104e4b17023SJohn Marino cfun->nonlocal_goto_save_area = src_cfun->nonlocal_goto_save_area; 2105e4b17023SJohn Marino cfun->function_end_locus = src_cfun->function_end_locus; 2106e4b17023SJohn Marino cfun->curr_properties = src_cfun->curr_properties; 2107e4b17023SJohn Marino cfun->last_verified = src_cfun->last_verified; 2108e4b17023SJohn Marino cfun->va_list_gpr_size = src_cfun->va_list_gpr_size; 2109e4b17023SJohn Marino cfun->va_list_fpr_size = src_cfun->va_list_fpr_size; 2110e4b17023SJohn Marino cfun->has_nonlocal_label = src_cfun->has_nonlocal_label; 2111e4b17023SJohn Marino cfun->stdarg = src_cfun->stdarg; 2112e4b17023SJohn Marino cfun->after_inlining = src_cfun->after_inlining; 2113e4b17023SJohn Marino cfun->can_throw_non_call_exceptions 2114e4b17023SJohn Marino = src_cfun->can_throw_non_call_exceptions; 2115e4b17023SJohn Marino cfun->returns_struct = src_cfun->returns_struct; 2116e4b17023SJohn Marino cfun->returns_pcc_struct = src_cfun->returns_pcc_struct; 2117e4b17023SJohn Marino cfun->after_tree_profile = src_cfun->after_tree_profile; 2118e4b17023SJohn Marino 2119e4b17023SJohn Marino init_empty_tree_cfg (); 2120e4b17023SJohn Marino 2121e4b17023SJohn Marino profile_status_for_function (cfun) = profile_status_for_function (src_cfun); 2122e4b17023SJohn Marino ENTRY_BLOCK_PTR->count = 2123e4b17023SJohn Marino (ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count * count_scale / 2124e4b17023SJohn Marino REG_BR_PROB_BASE); 2125e4b17023SJohn Marino ENTRY_BLOCK_PTR->frequency 2126e4b17023SJohn Marino = ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->frequency; 2127e4b17023SJohn Marino EXIT_BLOCK_PTR->count = 2128e4b17023SJohn Marino (EXIT_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count * count_scale / 2129e4b17023SJohn Marino REG_BR_PROB_BASE); 2130e4b17023SJohn Marino EXIT_BLOCK_PTR->frequency = 2131e4b17023SJohn Marino EXIT_BLOCK_PTR_FOR_FUNCTION (src_cfun)->frequency; 2132e4b17023SJohn Marino if (src_cfun->eh) 2133e4b17023SJohn Marino init_eh_for_function (); 2134e4b17023SJohn Marino 2135e4b17023SJohn Marino if (src_cfun->gimple_df) 2136e4b17023SJohn Marino { 2137e4b17023SJohn Marino init_tree_ssa (cfun); 2138e4b17023SJohn Marino cfun->gimple_df->in_ssa_p = true; 2139e4b17023SJohn Marino init_ssa_operands (); 2140e4b17023SJohn Marino } 2141e4b17023SJohn Marino pop_cfun (); 2142e4b17023SJohn Marino } 2143e4b17023SJohn Marino 2144e4b17023SJohn Marino /* Helper function for copy_cfg_body. Move debug stmts from the end 2145e4b17023SJohn Marino of NEW_BB to the beginning of successor basic blocks when needed. If the 2146e4b17023SJohn Marino successor has multiple predecessors, reset them, otherwise keep 2147e4b17023SJohn Marino their value. */ 2148e4b17023SJohn Marino 2149e4b17023SJohn Marino static void 2150e4b17023SJohn Marino maybe_move_debug_stmts_to_successors (copy_body_data *id, basic_block new_bb) 2151e4b17023SJohn Marino { 2152e4b17023SJohn Marino edge e; 2153e4b17023SJohn Marino edge_iterator ei; 2154e4b17023SJohn Marino gimple_stmt_iterator si = gsi_last_nondebug_bb (new_bb); 2155e4b17023SJohn Marino 2156e4b17023SJohn Marino if (gsi_end_p (si) 2157e4b17023SJohn Marino || gsi_one_before_end_p (si) 2158e4b17023SJohn Marino || !(stmt_can_throw_internal (gsi_stmt (si)) 2159e4b17023SJohn Marino || stmt_can_make_abnormal_goto (gsi_stmt (si)))) 2160e4b17023SJohn Marino return; 2161e4b17023SJohn Marino 2162e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, new_bb->succs) 2163e4b17023SJohn Marino { 2164e4b17023SJohn Marino gimple_stmt_iterator ssi = gsi_last_bb (new_bb); 2165e4b17023SJohn Marino gimple_stmt_iterator dsi = gsi_after_labels (e->dest); 2166e4b17023SJohn Marino while (is_gimple_debug (gsi_stmt (ssi))) 2167e4b17023SJohn Marino { 2168e4b17023SJohn Marino gimple stmt = gsi_stmt (ssi), new_stmt; 2169e4b17023SJohn Marino tree var; 2170e4b17023SJohn Marino tree value; 2171e4b17023SJohn Marino 2172e4b17023SJohn Marino /* For the last edge move the debug stmts instead of copying 2173e4b17023SJohn Marino them. */ 2174e4b17023SJohn Marino if (ei_one_before_end_p (ei)) 2175e4b17023SJohn Marino { 2176e4b17023SJohn Marino si = ssi; 2177e4b17023SJohn Marino gsi_prev (&ssi); 2178e4b17023SJohn Marino if (!single_pred_p (e->dest) && gimple_debug_bind_p (stmt)) 2179e4b17023SJohn Marino gimple_debug_bind_reset_value (stmt); 2180e4b17023SJohn Marino gsi_remove (&si, false); 2181e4b17023SJohn Marino gsi_insert_before (&dsi, stmt, GSI_SAME_STMT); 2182e4b17023SJohn Marino continue; 2183e4b17023SJohn Marino } 2184e4b17023SJohn Marino 2185e4b17023SJohn Marino if (gimple_debug_bind_p (stmt)) 2186e4b17023SJohn Marino { 2187e4b17023SJohn Marino var = gimple_debug_bind_get_var (stmt); 2188e4b17023SJohn Marino if (single_pred_p (e->dest)) 2189e4b17023SJohn Marino { 2190e4b17023SJohn Marino value = gimple_debug_bind_get_value (stmt); 2191e4b17023SJohn Marino value = unshare_expr (value); 2192e4b17023SJohn Marino } 2193e4b17023SJohn Marino else 2194e4b17023SJohn Marino value = NULL_TREE; 2195e4b17023SJohn Marino new_stmt = gimple_build_debug_bind (var, value, stmt); 2196e4b17023SJohn Marino } 2197e4b17023SJohn Marino else if (gimple_debug_source_bind_p (stmt)) 2198e4b17023SJohn Marino { 2199e4b17023SJohn Marino var = gimple_debug_source_bind_get_var (stmt); 2200e4b17023SJohn Marino value = gimple_debug_source_bind_get_value (stmt); 2201e4b17023SJohn Marino new_stmt = gimple_build_debug_source_bind (var, value, stmt); 2202e4b17023SJohn Marino } 2203e4b17023SJohn Marino else 2204e4b17023SJohn Marino gcc_unreachable (); 2205e4b17023SJohn Marino gsi_insert_before (&dsi, new_stmt, GSI_SAME_STMT); 2206e4b17023SJohn Marino VEC_safe_push (gimple, heap, id->debug_stmts, new_stmt); 2207e4b17023SJohn Marino gsi_prev (&ssi); 2208e4b17023SJohn Marino } 2209e4b17023SJohn Marino } 2210e4b17023SJohn Marino } 2211e4b17023SJohn Marino 2212e4b17023SJohn Marino /* Make a copy of the body of FN so that it can be inserted inline in 2213e4b17023SJohn Marino another function. Walks FN via CFG, returns new fndecl. */ 2214e4b17023SJohn Marino 2215e4b17023SJohn Marino static tree 2216e4b17023SJohn Marino copy_cfg_body (copy_body_data * id, gcov_type count, int frequency_scale, 2217e4b17023SJohn Marino basic_block entry_block_map, basic_block exit_block_map, 2218e4b17023SJohn Marino bitmap blocks_to_copy, basic_block new_entry) 2219e4b17023SJohn Marino { 2220e4b17023SJohn Marino tree callee_fndecl = id->src_fn; 2221e4b17023SJohn Marino /* Original cfun for the callee, doesn't change. */ 2222e4b17023SJohn Marino struct function *src_cfun = DECL_STRUCT_FUNCTION (callee_fndecl); 2223e4b17023SJohn Marino struct function *cfun_to_copy; 2224e4b17023SJohn Marino basic_block bb; 2225e4b17023SJohn Marino tree new_fndecl = NULL; 2226e4b17023SJohn Marino bool need_debug_cleanup = false; 2227e4b17023SJohn Marino gcov_type count_scale; 2228e4b17023SJohn Marino int last; 2229e4b17023SJohn Marino int incoming_frequency = 0; 2230e4b17023SJohn Marino gcov_type incoming_count = 0; 2231e4b17023SJohn Marino 2232e4b17023SJohn Marino if (ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count) 2233e4b17023SJohn Marino count_scale = (REG_BR_PROB_BASE * count 2234e4b17023SJohn Marino / ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count); 2235e4b17023SJohn Marino else 2236e4b17023SJohn Marino count_scale = REG_BR_PROB_BASE; 2237e4b17023SJohn Marino 2238e4b17023SJohn Marino /* Register specific tree functions. */ 2239e4b17023SJohn Marino gimple_register_cfg_hooks (); 2240e4b17023SJohn Marino 2241e4b17023SJohn Marino /* If we are inlining just region of the function, make sure to connect new entry 2242e4b17023SJohn Marino to ENTRY_BLOCK_PTR. Since new entry can be part of loop, we must compute 2243e4b17023SJohn Marino frequency and probability of ENTRY_BLOCK_PTR based on the frequencies and 2244e4b17023SJohn Marino probabilities of edges incoming from nonduplicated region. */ 2245e4b17023SJohn Marino if (new_entry) 2246e4b17023SJohn Marino { 2247e4b17023SJohn Marino edge e; 2248e4b17023SJohn Marino edge_iterator ei; 2249e4b17023SJohn Marino 2250e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, new_entry->preds) 2251e4b17023SJohn Marino if (!e->src->aux) 2252e4b17023SJohn Marino { 2253e4b17023SJohn Marino incoming_frequency += EDGE_FREQUENCY (e); 2254e4b17023SJohn Marino incoming_count += e->count; 2255e4b17023SJohn Marino } 2256e4b17023SJohn Marino incoming_count = incoming_count * count_scale / REG_BR_PROB_BASE; 2257e4b17023SJohn Marino incoming_frequency 2258e4b17023SJohn Marino = incoming_frequency * frequency_scale / REG_BR_PROB_BASE; 2259e4b17023SJohn Marino ENTRY_BLOCK_PTR->count = incoming_count; 2260e4b17023SJohn Marino ENTRY_BLOCK_PTR->frequency = incoming_frequency; 2261e4b17023SJohn Marino } 2262e4b17023SJohn Marino 2263e4b17023SJohn Marino /* Must have a CFG here at this point. */ 2264e4b17023SJohn Marino gcc_assert (ENTRY_BLOCK_PTR_FOR_FUNCTION 2265e4b17023SJohn Marino (DECL_STRUCT_FUNCTION (callee_fndecl))); 2266e4b17023SJohn Marino 2267e4b17023SJohn Marino cfun_to_copy = id->src_cfun = DECL_STRUCT_FUNCTION (callee_fndecl); 2268e4b17023SJohn Marino 2269e4b17023SJohn Marino ENTRY_BLOCK_PTR_FOR_FUNCTION (cfun_to_copy)->aux = entry_block_map; 2270e4b17023SJohn Marino EXIT_BLOCK_PTR_FOR_FUNCTION (cfun_to_copy)->aux = exit_block_map; 2271e4b17023SJohn Marino entry_block_map->aux = ENTRY_BLOCK_PTR_FOR_FUNCTION (cfun_to_copy); 2272e4b17023SJohn Marino exit_block_map->aux = EXIT_BLOCK_PTR_FOR_FUNCTION (cfun_to_copy); 2273e4b17023SJohn Marino 2274e4b17023SJohn Marino /* Duplicate any exception-handling regions. */ 2275e4b17023SJohn Marino if (cfun->eh) 2276e4b17023SJohn Marino id->eh_map = duplicate_eh_regions (cfun_to_copy, NULL, id->eh_lp_nr, 2277e4b17023SJohn Marino remap_decl_1, id); 2278e4b17023SJohn Marino 2279e4b17023SJohn Marino /* Use aux pointers to map the original blocks to copy. */ 2280e4b17023SJohn Marino FOR_EACH_BB_FN (bb, cfun_to_copy) 2281e4b17023SJohn Marino if (!blocks_to_copy || bitmap_bit_p (blocks_to_copy, bb->index)) 2282e4b17023SJohn Marino { 2283e4b17023SJohn Marino basic_block new_bb = copy_bb (id, bb, frequency_scale, count_scale); 2284e4b17023SJohn Marino bb->aux = new_bb; 2285e4b17023SJohn Marino new_bb->aux = bb; 2286e4b17023SJohn Marino } 2287e4b17023SJohn Marino 2288e4b17023SJohn Marino last = last_basic_block; 2289e4b17023SJohn Marino 2290e4b17023SJohn Marino /* Now that we've duplicated the blocks, duplicate their edges. */ 2291e4b17023SJohn Marino FOR_ALL_BB_FN (bb, cfun_to_copy) 2292e4b17023SJohn Marino if (!blocks_to_copy 2293e4b17023SJohn Marino || (bb->index > 0 && bitmap_bit_p (blocks_to_copy, bb->index))) 2294e4b17023SJohn Marino need_debug_cleanup |= copy_edges_for_bb (bb, count_scale, exit_block_map); 2295e4b17023SJohn Marino 2296e4b17023SJohn Marino if (new_entry) 2297e4b17023SJohn Marino { 2298e4b17023SJohn Marino edge e = make_edge (entry_block_map, (basic_block)new_entry->aux, EDGE_FALLTHRU); 2299e4b17023SJohn Marino e->probability = REG_BR_PROB_BASE; 2300e4b17023SJohn Marino e->count = incoming_count; 2301e4b17023SJohn Marino } 2302e4b17023SJohn Marino 2303e4b17023SJohn Marino if (gimple_in_ssa_p (cfun)) 2304e4b17023SJohn Marino FOR_ALL_BB_FN (bb, cfun_to_copy) 2305e4b17023SJohn Marino if (!blocks_to_copy 2306e4b17023SJohn Marino || (bb->index > 0 && bitmap_bit_p (blocks_to_copy, bb->index))) 2307e4b17023SJohn Marino copy_phis_for_bb (bb, id); 2308e4b17023SJohn Marino 2309e4b17023SJohn Marino FOR_ALL_BB_FN (bb, cfun_to_copy) 2310e4b17023SJohn Marino if (bb->aux) 2311e4b17023SJohn Marino { 2312e4b17023SJohn Marino if (need_debug_cleanup 2313e4b17023SJohn Marino && bb->index != ENTRY_BLOCK 2314e4b17023SJohn Marino && bb->index != EXIT_BLOCK) 2315e4b17023SJohn Marino maybe_move_debug_stmts_to_successors (id, (basic_block) bb->aux); 2316e4b17023SJohn Marino ((basic_block)bb->aux)->aux = NULL; 2317e4b17023SJohn Marino bb->aux = NULL; 2318e4b17023SJohn Marino } 2319e4b17023SJohn Marino 2320e4b17023SJohn Marino /* Zero out AUX fields of newly created block during EH edge 2321e4b17023SJohn Marino insertion. */ 2322e4b17023SJohn Marino for (; last < last_basic_block; last++) 2323e4b17023SJohn Marino { 2324e4b17023SJohn Marino if (need_debug_cleanup) 2325e4b17023SJohn Marino maybe_move_debug_stmts_to_successors (id, BASIC_BLOCK (last)); 2326e4b17023SJohn Marino BASIC_BLOCK (last)->aux = NULL; 2327e4b17023SJohn Marino } 2328e4b17023SJohn Marino entry_block_map->aux = NULL; 2329e4b17023SJohn Marino exit_block_map->aux = NULL; 2330e4b17023SJohn Marino 2331e4b17023SJohn Marino if (id->eh_map) 2332e4b17023SJohn Marino { 2333e4b17023SJohn Marino pointer_map_destroy (id->eh_map); 2334e4b17023SJohn Marino id->eh_map = NULL; 2335e4b17023SJohn Marino } 2336e4b17023SJohn Marino 2337e4b17023SJohn Marino return new_fndecl; 2338e4b17023SJohn Marino } 2339e4b17023SJohn Marino 2340e4b17023SJohn Marino /* Copy the debug STMT using ID. We deal with these statements in a 2341e4b17023SJohn Marino special way: if any variable in their VALUE expression wasn't 2342e4b17023SJohn Marino remapped yet, we won't remap it, because that would get decl uids 2343e4b17023SJohn Marino out of sync, causing codegen differences between -g and -g0. If 2344e4b17023SJohn Marino this arises, we drop the VALUE expression altogether. */ 2345e4b17023SJohn Marino 2346e4b17023SJohn Marino static void 2347e4b17023SJohn Marino copy_debug_stmt (gimple stmt, copy_body_data *id) 2348e4b17023SJohn Marino { 2349e4b17023SJohn Marino tree t, *n; 2350e4b17023SJohn Marino struct walk_stmt_info wi; 2351e4b17023SJohn Marino 2352e4b17023SJohn Marino t = id->block; 2353e4b17023SJohn Marino if (gimple_block (stmt)) 2354e4b17023SJohn Marino { 2355e4b17023SJohn Marino n = (tree *) pointer_map_contains (id->decl_map, gimple_block (stmt)); 2356e4b17023SJohn Marino if (n) 2357e4b17023SJohn Marino t = *n; 2358e4b17023SJohn Marino } 2359e4b17023SJohn Marino gimple_set_block (stmt, t); 2360e4b17023SJohn Marino 2361e4b17023SJohn Marino /* Remap all the operands in COPY. */ 2362e4b17023SJohn Marino memset (&wi, 0, sizeof (wi)); 2363e4b17023SJohn Marino wi.info = id; 2364e4b17023SJohn Marino 2365e4b17023SJohn Marino processing_debug_stmt = 1; 2366e4b17023SJohn Marino 2367e4b17023SJohn Marino if (gimple_debug_source_bind_p (stmt)) 2368e4b17023SJohn Marino t = gimple_debug_source_bind_get_var (stmt); 2369e4b17023SJohn Marino else 2370e4b17023SJohn Marino t = gimple_debug_bind_get_var (stmt); 2371e4b17023SJohn Marino 2372e4b17023SJohn Marino if (TREE_CODE (t) == PARM_DECL && id->debug_map 2373e4b17023SJohn Marino && (n = (tree *) pointer_map_contains (id->debug_map, t))) 2374e4b17023SJohn Marino { 2375e4b17023SJohn Marino gcc_assert (TREE_CODE (*n) == VAR_DECL); 2376e4b17023SJohn Marino t = *n; 2377e4b17023SJohn Marino } 2378e4b17023SJohn Marino else if (TREE_CODE (t) == VAR_DECL 2379e4b17023SJohn Marino && !TREE_STATIC (t) 2380e4b17023SJohn Marino && gimple_in_ssa_p (cfun) 2381e4b17023SJohn Marino && !pointer_map_contains (id->decl_map, t) 2382e4b17023SJohn Marino && !var_ann (t)) 2383e4b17023SJohn Marino /* T is a non-localized variable. */; 2384e4b17023SJohn Marino else 2385e4b17023SJohn Marino walk_tree (&t, remap_gimple_op_r, &wi, NULL); 2386e4b17023SJohn Marino 2387e4b17023SJohn Marino if (gimple_debug_bind_p (stmt)) 2388e4b17023SJohn Marino { 2389e4b17023SJohn Marino gimple_debug_bind_set_var (stmt, t); 2390e4b17023SJohn Marino 2391e4b17023SJohn Marino if (gimple_debug_bind_has_value_p (stmt)) 2392e4b17023SJohn Marino walk_tree (gimple_debug_bind_get_value_ptr (stmt), 2393e4b17023SJohn Marino remap_gimple_op_r, &wi, NULL); 2394e4b17023SJohn Marino 2395e4b17023SJohn Marino /* Punt if any decl couldn't be remapped. */ 2396e4b17023SJohn Marino if (processing_debug_stmt < 0) 2397e4b17023SJohn Marino gimple_debug_bind_reset_value (stmt); 2398e4b17023SJohn Marino } 2399e4b17023SJohn Marino else if (gimple_debug_source_bind_p (stmt)) 2400e4b17023SJohn Marino { 2401e4b17023SJohn Marino gimple_debug_source_bind_set_var (stmt, t); 2402e4b17023SJohn Marino walk_tree (gimple_debug_source_bind_get_value_ptr (stmt), 2403e4b17023SJohn Marino remap_gimple_op_r, &wi, NULL); 2404e4b17023SJohn Marino } 2405e4b17023SJohn Marino 2406e4b17023SJohn Marino processing_debug_stmt = 0; 2407e4b17023SJohn Marino 2408e4b17023SJohn Marino update_stmt (stmt); 2409e4b17023SJohn Marino if (gimple_in_ssa_p (cfun)) 2410e4b17023SJohn Marino mark_symbols_for_renaming (stmt); 2411e4b17023SJohn Marino } 2412e4b17023SJohn Marino 2413e4b17023SJohn Marino /* Process deferred debug stmts. In order to give values better odds 2414e4b17023SJohn Marino of being successfully remapped, we delay the processing of debug 2415e4b17023SJohn Marino stmts until all other stmts that might require remapping are 2416e4b17023SJohn Marino processed. */ 2417e4b17023SJohn Marino 2418e4b17023SJohn Marino static void 2419e4b17023SJohn Marino copy_debug_stmts (copy_body_data *id) 2420e4b17023SJohn Marino { 2421e4b17023SJohn Marino size_t i; 2422e4b17023SJohn Marino gimple stmt; 2423e4b17023SJohn Marino 2424e4b17023SJohn Marino if (!id->debug_stmts) 2425e4b17023SJohn Marino return; 2426e4b17023SJohn Marino 2427e4b17023SJohn Marino FOR_EACH_VEC_ELT (gimple, id->debug_stmts, i, stmt) 2428e4b17023SJohn Marino copy_debug_stmt (stmt, id); 2429e4b17023SJohn Marino 2430e4b17023SJohn Marino VEC_free (gimple, heap, id->debug_stmts); 2431e4b17023SJohn Marino } 2432e4b17023SJohn Marino 2433e4b17023SJohn Marino /* Make a copy of the body of SRC_FN so that it can be inserted inline in 2434e4b17023SJohn Marino another function. */ 2435e4b17023SJohn Marino 2436e4b17023SJohn Marino static tree 2437e4b17023SJohn Marino copy_tree_body (copy_body_data *id) 2438e4b17023SJohn Marino { 2439e4b17023SJohn Marino tree fndecl = id->src_fn; 2440e4b17023SJohn Marino tree body = DECL_SAVED_TREE (fndecl); 2441e4b17023SJohn Marino 2442e4b17023SJohn Marino walk_tree (&body, copy_tree_body_r, id, NULL); 2443e4b17023SJohn Marino 2444e4b17023SJohn Marino return body; 2445e4b17023SJohn Marino } 2446e4b17023SJohn Marino 2447e4b17023SJohn Marino /* Make a copy of the body of FN so that it can be inserted inline in 2448e4b17023SJohn Marino another function. */ 2449e4b17023SJohn Marino 2450e4b17023SJohn Marino static tree 2451e4b17023SJohn Marino copy_body (copy_body_data *id, gcov_type count, int frequency_scale, 2452e4b17023SJohn Marino basic_block entry_block_map, basic_block exit_block_map, 2453e4b17023SJohn Marino bitmap blocks_to_copy, basic_block new_entry) 2454e4b17023SJohn Marino { 2455e4b17023SJohn Marino tree fndecl = id->src_fn; 2456e4b17023SJohn Marino tree body; 2457e4b17023SJohn Marino 2458e4b17023SJohn Marino /* If this body has a CFG, walk CFG and copy. */ 2459e4b17023SJohn Marino gcc_assert (ENTRY_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (fndecl))); 2460e4b17023SJohn Marino body = copy_cfg_body (id, count, frequency_scale, entry_block_map, exit_block_map, 2461e4b17023SJohn Marino blocks_to_copy, new_entry); 2462e4b17023SJohn Marino copy_debug_stmts (id); 2463e4b17023SJohn Marino 2464e4b17023SJohn Marino return body; 2465e4b17023SJohn Marino } 2466e4b17023SJohn Marino 2467e4b17023SJohn Marino /* Return true if VALUE is an ADDR_EXPR of an automatic variable 2468e4b17023SJohn Marino defined in function FN, or of a data member thereof. */ 2469e4b17023SJohn Marino 2470e4b17023SJohn Marino static bool 2471e4b17023SJohn Marino self_inlining_addr_expr (tree value, tree fn) 2472e4b17023SJohn Marino { 2473e4b17023SJohn Marino tree var; 2474e4b17023SJohn Marino 2475e4b17023SJohn Marino if (TREE_CODE (value) != ADDR_EXPR) 2476e4b17023SJohn Marino return false; 2477e4b17023SJohn Marino 2478e4b17023SJohn Marino var = get_base_address (TREE_OPERAND (value, 0)); 2479e4b17023SJohn Marino 2480e4b17023SJohn Marino return var && auto_var_in_fn_p (var, fn); 2481e4b17023SJohn Marino } 2482e4b17023SJohn Marino 2483e4b17023SJohn Marino /* Append to BB a debug annotation that binds VAR to VALUE, inheriting 2484e4b17023SJohn Marino lexical block and line number information from base_stmt, if given, 2485e4b17023SJohn Marino or from the last stmt of the block otherwise. */ 2486e4b17023SJohn Marino 2487e4b17023SJohn Marino static gimple 2488e4b17023SJohn Marino insert_init_debug_bind (copy_body_data *id, 2489e4b17023SJohn Marino basic_block bb, tree var, tree value, 2490e4b17023SJohn Marino gimple base_stmt) 2491e4b17023SJohn Marino { 2492e4b17023SJohn Marino gimple note; 2493e4b17023SJohn Marino gimple_stmt_iterator gsi; 2494e4b17023SJohn Marino tree tracked_var; 2495e4b17023SJohn Marino 2496e4b17023SJohn Marino if (!gimple_in_ssa_p (id->src_cfun)) 2497e4b17023SJohn Marino return NULL; 2498e4b17023SJohn Marino 2499e4b17023SJohn Marino if (!MAY_HAVE_DEBUG_STMTS) 2500e4b17023SJohn Marino return NULL; 2501e4b17023SJohn Marino 2502e4b17023SJohn Marino tracked_var = target_for_debug_bind (var); 2503e4b17023SJohn Marino if (!tracked_var) 2504e4b17023SJohn Marino return NULL; 2505e4b17023SJohn Marino 2506e4b17023SJohn Marino if (bb) 2507e4b17023SJohn Marino { 2508e4b17023SJohn Marino gsi = gsi_last_bb (bb); 2509e4b17023SJohn Marino if (!base_stmt && !gsi_end_p (gsi)) 2510e4b17023SJohn Marino base_stmt = gsi_stmt (gsi); 2511e4b17023SJohn Marino } 2512e4b17023SJohn Marino 2513e4b17023SJohn Marino note = gimple_build_debug_bind (tracked_var, value, base_stmt); 2514e4b17023SJohn Marino 2515e4b17023SJohn Marino if (bb) 2516e4b17023SJohn Marino { 2517e4b17023SJohn Marino if (!gsi_end_p (gsi)) 2518e4b17023SJohn Marino gsi_insert_after (&gsi, note, GSI_SAME_STMT); 2519e4b17023SJohn Marino else 2520e4b17023SJohn Marino gsi_insert_before (&gsi, note, GSI_SAME_STMT); 2521e4b17023SJohn Marino } 2522e4b17023SJohn Marino 2523e4b17023SJohn Marino return note; 2524e4b17023SJohn Marino } 2525e4b17023SJohn Marino 2526e4b17023SJohn Marino static void 2527e4b17023SJohn Marino insert_init_stmt (copy_body_data *id, basic_block bb, gimple init_stmt) 2528e4b17023SJohn Marino { 2529e4b17023SJohn Marino /* If VAR represents a zero-sized variable, it's possible that the 2530e4b17023SJohn Marino assignment statement may result in no gimple statements. */ 2531e4b17023SJohn Marino if (init_stmt) 2532e4b17023SJohn Marino { 2533e4b17023SJohn Marino gimple_stmt_iterator si = gsi_last_bb (bb); 2534e4b17023SJohn Marino 2535e4b17023SJohn Marino /* We can end up with init statements that store to a non-register 2536e4b17023SJohn Marino from a rhs with a conversion. Handle that here by forcing the 2537e4b17023SJohn Marino rhs into a temporary. gimple_regimplify_operands is not 2538e4b17023SJohn Marino prepared to do this for us. */ 2539e4b17023SJohn Marino if (!is_gimple_debug (init_stmt) 2540e4b17023SJohn Marino && !is_gimple_reg (gimple_assign_lhs (init_stmt)) 2541e4b17023SJohn Marino && is_gimple_reg_type (TREE_TYPE (gimple_assign_lhs (init_stmt))) 2542e4b17023SJohn Marino && gimple_assign_rhs_class (init_stmt) == GIMPLE_UNARY_RHS) 2543e4b17023SJohn Marino { 2544e4b17023SJohn Marino tree rhs = build1 (gimple_assign_rhs_code (init_stmt), 2545e4b17023SJohn Marino gimple_expr_type (init_stmt), 2546e4b17023SJohn Marino gimple_assign_rhs1 (init_stmt)); 2547e4b17023SJohn Marino rhs = force_gimple_operand_gsi (&si, rhs, true, NULL_TREE, false, 2548e4b17023SJohn Marino GSI_NEW_STMT); 2549e4b17023SJohn Marino gimple_assign_set_rhs_code (init_stmt, TREE_CODE (rhs)); 2550e4b17023SJohn Marino gimple_assign_set_rhs1 (init_stmt, rhs); 2551e4b17023SJohn Marino } 2552e4b17023SJohn Marino gsi_insert_after (&si, init_stmt, GSI_NEW_STMT); 2553e4b17023SJohn Marino gimple_regimplify_operands (init_stmt, &si); 2554e4b17023SJohn Marino mark_symbols_for_renaming (init_stmt); 2555e4b17023SJohn Marino 2556e4b17023SJohn Marino if (!is_gimple_debug (init_stmt) && MAY_HAVE_DEBUG_STMTS) 2557e4b17023SJohn Marino { 2558e4b17023SJohn Marino tree var, def = gimple_assign_lhs (init_stmt); 2559e4b17023SJohn Marino 2560e4b17023SJohn Marino if (TREE_CODE (def) == SSA_NAME) 2561e4b17023SJohn Marino var = SSA_NAME_VAR (def); 2562e4b17023SJohn Marino else 2563e4b17023SJohn Marino var = def; 2564e4b17023SJohn Marino 2565e4b17023SJohn Marino insert_init_debug_bind (id, bb, var, def, init_stmt); 2566e4b17023SJohn Marino } 2567e4b17023SJohn Marino } 2568e4b17023SJohn Marino } 2569e4b17023SJohn Marino 2570e4b17023SJohn Marino /* Initialize parameter P with VALUE. If needed, produce init statement 2571e4b17023SJohn Marino at the end of BB. When BB is NULL, we return init statement to be 2572e4b17023SJohn Marino output later. */ 2573e4b17023SJohn Marino static gimple 2574e4b17023SJohn Marino setup_one_parameter (copy_body_data *id, tree p, tree value, tree fn, 2575e4b17023SJohn Marino basic_block bb, tree *vars) 2576e4b17023SJohn Marino { 2577e4b17023SJohn Marino gimple init_stmt = NULL; 2578e4b17023SJohn Marino tree var; 2579e4b17023SJohn Marino tree rhs = value; 2580e4b17023SJohn Marino tree def = (gimple_in_ssa_p (cfun) 2581e4b17023SJohn Marino ? gimple_default_def (id->src_cfun, p) : NULL); 2582e4b17023SJohn Marino 2583e4b17023SJohn Marino if (value 2584e4b17023SJohn Marino && value != error_mark_node 2585e4b17023SJohn Marino && !useless_type_conversion_p (TREE_TYPE (p), TREE_TYPE (value))) 2586e4b17023SJohn Marino { 2587e4b17023SJohn Marino /* If we can match up types by promotion/demotion do so. */ 2588e4b17023SJohn Marino if (fold_convertible_p (TREE_TYPE (p), value)) 2589e4b17023SJohn Marino rhs = fold_convert (TREE_TYPE (p), value); 2590e4b17023SJohn Marino else 2591e4b17023SJohn Marino { 2592e4b17023SJohn Marino /* ??? For valid programs we should not end up here. 2593e4b17023SJohn Marino Still if we end up with truly mismatched types here, fall back 2594e4b17023SJohn Marino to using a VIEW_CONVERT_EXPR or a literal zero to not leak invalid 2595e4b17023SJohn Marino GIMPLE to the following passes. */ 2596e4b17023SJohn Marino if (!is_gimple_reg_type (TREE_TYPE (value)) 2597e4b17023SJohn Marino || TYPE_SIZE (TREE_TYPE (p)) == TYPE_SIZE (TREE_TYPE (value))) 2598e4b17023SJohn Marino rhs = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (p), value); 2599e4b17023SJohn Marino else 2600e4b17023SJohn Marino rhs = build_zero_cst (TREE_TYPE (p)); 2601e4b17023SJohn Marino } 2602e4b17023SJohn Marino } 2603e4b17023SJohn Marino 2604e4b17023SJohn Marino /* Make an equivalent VAR_DECL. Note that we must NOT remap the type 2605e4b17023SJohn Marino here since the type of this decl must be visible to the calling 2606e4b17023SJohn Marino function. */ 2607e4b17023SJohn Marino var = copy_decl_to_var (p, id); 2608e4b17023SJohn Marino 2609e4b17023SJohn Marino /* We're actually using the newly-created var. */ 2610e4b17023SJohn Marino if (gimple_in_ssa_p (cfun) && TREE_CODE (var) == VAR_DECL) 2611e4b17023SJohn Marino add_referenced_var (var); 2612e4b17023SJohn Marino 2613e4b17023SJohn Marino /* Declare this new variable. */ 2614e4b17023SJohn Marino DECL_CHAIN (var) = *vars; 2615e4b17023SJohn Marino *vars = var; 2616e4b17023SJohn Marino 2617e4b17023SJohn Marino /* Make gimplifier happy about this variable. */ 2618e4b17023SJohn Marino DECL_SEEN_IN_BIND_EXPR_P (var) = 1; 2619e4b17023SJohn Marino 2620e4b17023SJohn Marino /* We are eventually using the value - make sure all variables 2621e4b17023SJohn Marino referenced therein are properly recorded. */ 2622e4b17023SJohn Marino if (value 2623e4b17023SJohn Marino && gimple_in_ssa_p (cfun) 2624e4b17023SJohn Marino && TREE_CODE (value) == ADDR_EXPR) 2625e4b17023SJohn Marino { 2626e4b17023SJohn Marino tree base = get_base_address (TREE_OPERAND (value, 0)); 2627e4b17023SJohn Marino if (base && TREE_CODE (base) == VAR_DECL) 2628e4b17023SJohn Marino add_referenced_var (base); 2629e4b17023SJohn Marino } 2630e4b17023SJohn Marino 2631e4b17023SJohn Marino /* If the parameter is never assigned to, has no SSA_NAMEs created, 2632e4b17023SJohn Marino we would not need to create a new variable here at all, if it 2633e4b17023SJohn Marino weren't for debug info. Still, we can just use the argument 2634e4b17023SJohn Marino value. */ 2635e4b17023SJohn Marino if (TREE_READONLY (p) 2636e4b17023SJohn Marino && !TREE_ADDRESSABLE (p) 2637e4b17023SJohn Marino && value && !TREE_SIDE_EFFECTS (value) 2638e4b17023SJohn Marino && !def) 2639e4b17023SJohn Marino { 2640e4b17023SJohn Marino /* We may produce non-gimple trees by adding NOPs or introduce 2641e4b17023SJohn Marino invalid sharing when operand is not really constant. 2642e4b17023SJohn Marino It is not big deal to prohibit constant propagation here as 2643e4b17023SJohn Marino we will constant propagate in DOM1 pass anyway. */ 2644e4b17023SJohn Marino if (is_gimple_min_invariant (value) 2645e4b17023SJohn Marino && useless_type_conversion_p (TREE_TYPE (p), 2646e4b17023SJohn Marino TREE_TYPE (value)) 2647e4b17023SJohn Marino /* We have to be very careful about ADDR_EXPR. Make sure 2648e4b17023SJohn Marino the base variable isn't a local variable of the inlined 2649e4b17023SJohn Marino function, e.g., when doing recursive inlining, direct or 2650e4b17023SJohn Marino mutually-recursive or whatever, which is why we don't 2651e4b17023SJohn Marino just test whether fn == current_function_decl. */ 2652e4b17023SJohn Marino && ! self_inlining_addr_expr (value, fn)) 2653e4b17023SJohn Marino { 2654e4b17023SJohn Marino insert_decl_map (id, p, value); 2655e4b17023SJohn Marino insert_debug_decl_map (id, p, var); 2656e4b17023SJohn Marino return insert_init_debug_bind (id, bb, var, value, NULL); 2657e4b17023SJohn Marino } 2658e4b17023SJohn Marino } 2659e4b17023SJohn Marino 2660e4b17023SJohn Marino /* Register the VAR_DECL as the equivalent for the PARM_DECL; 2661e4b17023SJohn Marino that way, when the PARM_DECL is encountered, it will be 2662e4b17023SJohn Marino automatically replaced by the VAR_DECL. */ 2663e4b17023SJohn Marino insert_decl_map (id, p, var); 2664e4b17023SJohn Marino 2665e4b17023SJohn Marino /* Even if P was TREE_READONLY, the new VAR should not be. 2666e4b17023SJohn Marino In the original code, we would have constructed a 2667e4b17023SJohn Marino temporary, and then the function body would have never 2668e4b17023SJohn Marino changed the value of P. However, now, we will be 2669e4b17023SJohn Marino constructing VAR directly. The constructor body may 2670e4b17023SJohn Marino change its value multiple times as it is being 2671e4b17023SJohn Marino constructed. Therefore, it must not be TREE_READONLY; 2672e4b17023SJohn Marino the back-end assumes that TREE_READONLY variable is 2673e4b17023SJohn Marino assigned to only once. */ 2674e4b17023SJohn Marino if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (p))) 2675e4b17023SJohn Marino TREE_READONLY (var) = 0; 2676e4b17023SJohn Marino 2677e4b17023SJohn Marino /* If there is no setup required and we are in SSA, take the easy route 2678e4b17023SJohn Marino replacing all SSA names representing the function parameter by the 2679e4b17023SJohn Marino SSA name passed to function. 2680e4b17023SJohn Marino 2681e4b17023SJohn Marino We need to construct map for the variable anyway as it might be used 2682e4b17023SJohn Marino in different SSA names when parameter is set in function. 2683e4b17023SJohn Marino 2684e4b17023SJohn Marino Do replacement at -O0 for const arguments replaced by constant. 2685e4b17023SJohn Marino This is important for builtin_constant_p and other construct requiring 2686e4b17023SJohn Marino constant argument to be visible in inlined function body. */ 2687e4b17023SJohn Marino if (gimple_in_ssa_p (cfun) && rhs && def && is_gimple_reg (p) 2688e4b17023SJohn Marino && (optimize 2689e4b17023SJohn Marino || (TREE_READONLY (p) 2690e4b17023SJohn Marino && is_gimple_min_invariant (rhs))) 2691e4b17023SJohn Marino && (TREE_CODE (rhs) == SSA_NAME 2692e4b17023SJohn Marino || is_gimple_min_invariant (rhs)) 2693e4b17023SJohn Marino && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (def)) 2694e4b17023SJohn Marino { 2695e4b17023SJohn Marino insert_decl_map (id, def, rhs); 2696e4b17023SJohn Marino return insert_init_debug_bind (id, bb, var, rhs, NULL); 2697e4b17023SJohn Marino } 2698e4b17023SJohn Marino 2699e4b17023SJohn Marino /* If the value of argument is never used, don't care about initializing 2700e4b17023SJohn Marino it. */ 2701e4b17023SJohn Marino if (optimize && gimple_in_ssa_p (cfun) && !def && is_gimple_reg (p)) 2702e4b17023SJohn Marino { 2703e4b17023SJohn Marino gcc_assert (!value || !TREE_SIDE_EFFECTS (value)); 2704e4b17023SJohn Marino return insert_init_debug_bind (id, bb, var, rhs, NULL); 2705e4b17023SJohn Marino } 2706e4b17023SJohn Marino 2707e4b17023SJohn Marino /* Initialize this VAR_DECL from the equivalent argument. Convert 2708e4b17023SJohn Marino the argument to the proper type in case it was promoted. */ 2709e4b17023SJohn Marino if (value) 2710e4b17023SJohn Marino { 2711e4b17023SJohn Marino if (rhs == error_mark_node) 2712e4b17023SJohn Marino { 2713e4b17023SJohn Marino insert_decl_map (id, p, var); 2714e4b17023SJohn Marino return insert_init_debug_bind (id, bb, var, rhs, NULL); 2715e4b17023SJohn Marino } 2716e4b17023SJohn Marino 2717e4b17023SJohn Marino STRIP_USELESS_TYPE_CONVERSION (rhs); 2718e4b17023SJohn Marino 2719e4b17023SJohn Marino /* We want to use MODIFY_EXPR, not INIT_EXPR here so that we 2720e4b17023SJohn Marino keep our trees in gimple form. */ 2721e4b17023SJohn Marino if (def && gimple_in_ssa_p (cfun) && is_gimple_reg (p)) 2722e4b17023SJohn Marino { 2723e4b17023SJohn Marino def = remap_ssa_name (def, id); 2724e4b17023SJohn Marino init_stmt = gimple_build_assign (def, rhs); 2725e4b17023SJohn Marino SSA_NAME_IS_DEFAULT_DEF (def) = 0; 2726e4b17023SJohn Marino set_default_def (var, NULL); 2727e4b17023SJohn Marino } 2728e4b17023SJohn Marino else 2729e4b17023SJohn Marino init_stmt = gimple_build_assign (var, rhs); 2730e4b17023SJohn Marino 2731e4b17023SJohn Marino if (bb && init_stmt) 2732e4b17023SJohn Marino insert_init_stmt (id, bb, init_stmt); 2733e4b17023SJohn Marino } 2734e4b17023SJohn Marino return init_stmt; 2735e4b17023SJohn Marino } 2736e4b17023SJohn Marino 2737e4b17023SJohn Marino /* Generate code to initialize the parameters of the function at the 2738e4b17023SJohn Marino top of the stack in ID from the GIMPLE_CALL STMT. */ 2739e4b17023SJohn Marino 2740e4b17023SJohn Marino static void 2741e4b17023SJohn Marino initialize_inlined_parameters (copy_body_data *id, gimple stmt, 2742e4b17023SJohn Marino tree fn, basic_block bb) 2743e4b17023SJohn Marino { 2744e4b17023SJohn Marino tree parms; 2745e4b17023SJohn Marino size_t i; 2746e4b17023SJohn Marino tree p; 2747e4b17023SJohn Marino tree vars = NULL_TREE; 2748e4b17023SJohn Marino tree static_chain = gimple_call_chain (stmt); 2749e4b17023SJohn Marino 2750e4b17023SJohn Marino /* Figure out what the parameters are. */ 2751e4b17023SJohn Marino parms = DECL_ARGUMENTS (fn); 2752e4b17023SJohn Marino 2753e4b17023SJohn Marino /* Loop through the parameter declarations, replacing each with an 2754e4b17023SJohn Marino equivalent VAR_DECL, appropriately initialized. */ 2755e4b17023SJohn Marino for (p = parms, i = 0; p; p = DECL_CHAIN (p), i++) 2756e4b17023SJohn Marino { 2757e4b17023SJohn Marino tree val; 2758e4b17023SJohn Marino val = i < gimple_call_num_args (stmt) ? gimple_call_arg (stmt, i) : NULL; 2759e4b17023SJohn Marino setup_one_parameter (id, p, val, fn, bb, &vars); 2760e4b17023SJohn Marino } 2761e4b17023SJohn Marino /* After remapping parameters remap their types. This has to be done 2762e4b17023SJohn Marino in a second loop over all parameters to appropriately remap 2763e4b17023SJohn Marino variable sized arrays when the size is specified in a 2764e4b17023SJohn Marino parameter following the array. */ 2765e4b17023SJohn Marino for (p = parms, i = 0; p; p = DECL_CHAIN (p), i++) 2766e4b17023SJohn Marino { 2767e4b17023SJohn Marino tree *varp = (tree *) pointer_map_contains (id->decl_map, p); 2768e4b17023SJohn Marino if (varp 2769e4b17023SJohn Marino && TREE_CODE (*varp) == VAR_DECL) 2770e4b17023SJohn Marino { 2771e4b17023SJohn Marino tree def = (gimple_in_ssa_p (cfun) && is_gimple_reg (p) 2772e4b17023SJohn Marino ? gimple_default_def (id->src_cfun, p) : NULL); 2773e4b17023SJohn Marino tree var = *varp; 2774e4b17023SJohn Marino TREE_TYPE (var) = remap_type (TREE_TYPE (var), id); 2775e4b17023SJohn Marino /* Also remap the default definition if it was remapped 2776e4b17023SJohn Marino to the default definition of the parameter replacement 2777e4b17023SJohn Marino by the parameter setup. */ 2778e4b17023SJohn Marino if (def) 2779e4b17023SJohn Marino { 2780e4b17023SJohn Marino tree *defp = (tree *) pointer_map_contains (id->decl_map, def); 2781e4b17023SJohn Marino if (defp 2782e4b17023SJohn Marino && TREE_CODE (*defp) == SSA_NAME 2783e4b17023SJohn Marino && SSA_NAME_VAR (*defp) == var) 2784e4b17023SJohn Marino TREE_TYPE (*defp) = TREE_TYPE (var); 2785e4b17023SJohn Marino } 2786e4b17023SJohn Marino } 2787e4b17023SJohn Marino } 2788e4b17023SJohn Marino 2789e4b17023SJohn Marino /* Initialize the static chain. */ 2790e4b17023SJohn Marino p = DECL_STRUCT_FUNCTION (fn)->static_chain_decl; 2791e4b17023SJohn Marino gcc_assert (fn != current_function_decl); 2792e4b17023SJohn Marino if (p) 2793e4b17023SJohn Marino { 2794e4b17023SJohn Marino /* No static chain? Seems like a bug in tree-nested.c. */ 2795e4b17023SJohn Marino gcc_assert (static_chain); 2796e4b17023SJohn Marino 2797e4b17023SJohn Marino setup_one_parameter (id, p, static_chain, fn, bb, &vars); 2798e4b17023SJohn Marino } 2799e4b17023SJohn Marino 2800e4b17023SJohn Marino declare_inline_vars (id->block, vars); 2801e4b17023SJohn Marino } 2802e4b17023SJohn Marino 2803e4b17023SJohn Marino 2804e4b17023SJohn Marino /* Declare a return variable to replace the RESULT_DECL for the 2805e4b17023SJohn Marino function we are calling. An appropriate DECL_STMT is returned. 2806e4b17023SJohn Marino The USE_STMT is filled to contain a use of the declaration to 2807e4b17023SJohn Marino indicate the return value of the function. 2808e4b17023SJohn Marino 2809e4b17023SJohn Marino RETURN_SLOT, if non-null is place where to store the result. It 2810e4b17023SJohn Marino is set only for CALL_EXPR_RETURN_SLOT_OPT. MODIFY_DEST, if non-null, 2811e4b17023SJohn Marino was the LHS of the MODIFY_EXPR to which this call is the RHS. 2812e4b17023SJohn Marino 2813e4b17023SJohn Marino The return value is a (possibly null) value that holds the result 2814e4b17023SJohn Marino as seen by the caller. */ 2815e4b17023SJohn Marino 2816e4b17023SJohn Marino static tree 2817e4b17023SJohn Marino declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest, 2818e4b17023SJohn Marino basic_block entry_bb) 2819e4b17023SJohn Marino { 2820e4b17023SJohn Marino tree callee = id->src_fn; 2821e4b17023SJohn Marino tree result = DECL_RESULT (callee); 2822e4b17023SJohn Marino tree callee_type = TREE_TYPE (result); 2823e4b17023SJohn Marino tree caller_type; 2824e4b17023SJohn Marino tree var, use; 2825e4b17023SJohn Marino 2826e4b17023SJohn Marino /* Handle type-mismatches in the function declaration return type 2827e4b17023SJohn Marino vs. the call expression. */ 2828e4b17023SJohn Marino if (modify_dest) 2829e4b17023SJohn Marino caller_type = TREE_TYPE (modify_dest); 2830e4b17023SJohn Marino else 2831e4b17023SJohn Marino caller_type = TREE_TYPE (TREE_TYPE (callee)); 2832e4b17023SJohn Marino 2833e4b17023SJohn Marino /* We don't need to do anything for functions that don't return anything. */ 2834e4b17023SJohn Marino if (VOID_TYPE_P (callee_type)) 2835e4b17023SJohn Marino return NULL_TREE; 2836e4b17023SJohn Marino 2837e4b17023SJohn Marino /* If there was a return slot, then the return value is the 2838e4b17023SJohn Marino dereferenced address of that object. */ 2839e4b17023SJohn Marino if (return_slot) 2840e4b17023SJohn Marino { 2841e4b17023SJohn Marino /* The front end shouldn't have used both return_slot and 2842e4b17023SJohn Marino a modify expression. */ 2843e4b17023SJohn Marino gcc_assert (!modify_dest); 2844e4b17023SJohn Marino if (DECL_BY_REFERENCE (result)) 2845e4b17023SJohn Marino { 2846e4b17023SJohn Marino tree return_slot_addr = build_fold_addr_expr (return_slot); 2847e4b17023SJohn Marino STRIP_USELESS_TYPE_CONVERSION (return_slot_addr); 2848e4b17023SJohn Marino 2849e4b17023SJohn Marino /* We are going to construct *&return_slot and we can't do that 2850e4b17023SJohn Marino for variables believed to be not addressable. 2851e4b17023SJohn Marino 2852e4b17023SJohn Marino FIXME: This check possibly can match, because values returned 2853e4b17023SJohn Marino via return slot optimization are not believed to have address 2854e4b17023SJohn Marino taken by alias analysis. */ 2855e4b17023SJohn Marino gcc_assert (TREE_CODE (return_slot) != SSA_NAME); 2856e4b17023SJohn Marino var = return_slot_addr; 2857e4b17023SJohn Marino } 2858e4b17023SJohn Marino else 2859e4b17023SJohn Marino { 2860e4b17023SJohn Marino var = return_slot; 2861e4b17023SJohn Marino gcc_assert (TREE_CODE (var) != SSA_NAME); 2862e4b17023SJohn Marino TREE_ADDRESSABLE (var) |= TREE_ADDRESSABLE (result); 2863e4b17023SJohn Marino } 2864e4b17023SJohn Marino if ((TREE_CODE (TREE_TYPE (result)) == COMPLEX_TYPE 2865e4b17023SJohn Marino || TREE_CODE (TREE_TYPE (result)) == VECTOR_TYPE) 2866e4b17023SJohn Marino && !DECL_GIMPLE_REG_P (result) 2867e4b17023SJohn Marino && DECL_P (var)) 2868e4b17023SJohn Marino DECL_GIMPLE_REG_P (var) = 0; 2869e4b17023SJohn Marino use = NULL; 2870e4b17023SJohn Marino goto done; 2871e4b17023SJohn Marino } 2872e4b17023SJohn Marino 2873e4b17023SJohn Marino /* All types requiring non-trivial constructors should have been handled. */ 2874e4b17023SJohn Marino gcc_assert (!TREE_ADDRESSABLE (callee_type)); 2875e4b17023SJohn Marino 2876e4b17023SJohn Marino /* Attempt to avoid creating a new temporary variable. */ 2877e4b17023SJohn Marino if (modify_dest 2878e4b17023SJohn Marino && TREE_CODE (modify_dest) != SSA_NAME) 2879e4b17023SJohn Marino { 2880e4b17023SJohn Marino bool use_it = false; 2881e4b17023SJohn Marino 2882e4b17023SJohn Marino /* We can't use MODIFY_DEST if there's type promotion involved. */ 2883e4b17023SJohn Marino if (!useless_type_conversion_p (callee_type, caller_type)) 2884e4b17023SJohn Marino use_it = false; 2885e4b17023SJohn Marino 2886e4b17023SJohn Marino /* ??? If we're assigning to a variable sized type, then we must 2887e4b17023SJohn Marino reuse the destination variable, because we've no good way to 2888e4b17023SJohn Marino create variable sized temporaries at this point. */ 2889e4b17023SJohn Marino else if (TREE_CODE (TYPE_SIZE_UNIT (caller_type)) != INTEGER_CST) 2890e4b17023SJohn Marino use_it = true; 2891e4b17023SJohn Marino 2892e4b17023SJohn Marino /* If the callee cannot possibly modify MODIFY_DEST, then we can 2893e4b17023SJohn Marino reuse it as the result of the call directly. Don't do this if 2894e4b17023SJohn Marino it would promote MODIFY_DEST to addressable. */ 2895e4b17023SJohn Marino else if (TREE_ADDRESSABLE (result)) 2896e4b17023SJohn Marino use_it = false; 2897e4b17023SJohn Marino else 2898e4b17023SJohn Marino { 2899e4b17023SJohn Marino tree base_m = get_base_address (modify_dest); 2900e4b17023SJohn Marino 2901e4b17023SJohn Marino /* If the base isn't a decl, then it's a pointer, and we don't 2902e4b17023SJohn Marino know where that's going to go. */ 2903e4b17023SJohn Marino if (!DECL_P (base_m)) 2904e4b17023SJohn Marino use_it = false; 2905e4b17023SJohn Marino else if (is_global_var (base_m)) 2906e4b17023SJohn Marino use_it = false; 2907e4b17023SJohn Marino else if ((TREE_CODE (TREE_TYPE (result)) == COMPLEX_TYPE 2908e4b17023SJohn Marino || TREE_CODE (TREE_TYPE (result)) == VECTOR_TYPE) 2909e4b17023SJohn Marino && !DECL_GIMPLE_REG_P (result) 2910e4b17023SJohn Marino && DECL_GIMPLE_REG_P (base_m)) 2911e4b17023SJohn Marino use_it = false; 2912e4b17023SJohn Marino else if (!TREE_ADDRESSABLE (base_m)) 2913e4b17023SJohn Marino use_it = true; 2914e4b17023SJohn Marino } 2915e4b17023SJohn Marino 2916e4b17023SJohn Marino if (use_it) 2917e4b17023SJohn Marino { 2918e4b17023SJohn Marino var = modify_dest; 2919e4b17023SJohn Marino use = NULL; 2920e4b17023SJohn Marino goto done; 2921e4b17023SJohn Marino } 2922e4b17023SJohn Marino } 2923e4b17023SJohn Marino 2924e4b17023SJohn Marino gcc_assert (TREE_CODE (TYPE_SIZE_UNIT (callee_type)) == INTEGER_CST); 2925e4b17023SJohn Marino 2926e4b17023SJohn Marino var = copy_result_decl_to_var (result, id); 2927e4b17023SJohn Marino if (gimple_in_ssa_p (cfun)) 2928e4b17023SJohn Marino add_referenced_var (var); 2929e4b17023SJohn Marino 2930e4b17023SJohn Marino DECL_SEEN_IN_BIND_EXPR_P (var) = 1; 2931e4b17023SJohn Marino 2932e4b17023SJohn Marino /* Do not have the rest of GCC warn about this variable as it should 2933e4b17023SJohn Marino not be visible to the user. */ 2934e4b17023SJohn Marino TREE_NO_WARNING (var) = 1; 2935e4b17023SJohn Marino 2936e4b17023SJohn Marino declare_inline_vars (id->block, var); 2937e4b17023SJohn Marino 2938e4b17023SJohn Marino /* Build the use expr. If the return type of the function was 2939e4b17023SJohn Marino promoted, convert it back to the expected type. */ 2940e4b17023SJohn Marino use = var; 2941e4b17023SJohn Marino if (!useless_type_conversion_p (caller_type, TREE_TYPE (var))) 2942e4b17023SJohn Marino { 2943e4b17023SJohn Marino /* If we can match up types by promotion/demotion do so. */ 2944e4b17023SJohn Marino if (fold_convertible_p (caller_type, var)) 2945e4b17023SJohn Marino use = fold_convert (caller_type, var); 2946e4b17023SJohn Marino else 2947e4b17023SJohn Marino { 2948e4b17023SJohn Marino /* ??? For valid programs we should not end up here. 2949e4b17023SJohn Marino Still if we end up with truly mismatched types here, fall back 2950e4b17023SJohn Marino to using a MEM_REF to not leak invalid GIMPLE to the following 2951e4b17023SJohn Marino passes. */ 2952e4b17023SJohn Marino /* Prevent var from being written into SSA form. */ 2953e4b17023SJohn Marino if (TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE 2954e4b17023SJohn Marino || TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE) 2955e4b17023SJohn Marino DECL_GIMPLE_REG_P (var) = false; 2956e4b17023SJohn Marino else if (is_gimple_reg_type (TREE_TYPE (var))) 2957e4b17023SJohn Marino TREE_ADDRESSABLE (var) = true; 2958e4b17023SJohn Marino use = fold_build2 (MEM_REF, caller_type, 2959e4b17023SJohn Marino build_fold_addr_expr (var), 2960e4b17023SJohn Marino build_int_cst (ptr_type_node, 0)); 2961e4b17023SJohn Marino } 2962e4b17023SJohn Marino } 2963e4b17023SJohn Marino 2964e4b17023SJohn Marino STRIP_USELESS_TYPE_CONVERSION (use); 2965e4b17023SJohn Marino 2966e4b17023SJohn Marino if (DECL_BY_REFERENCE (result)) 2967e4b17023SJohn Marino { 2968e4b17023SJohn Marino TREE_ADDRESSABLE (var) = 1; 2969e4b17023SJohn Marino var = build_fold_addr_expr (var); 2970e4b17023SJohn Marino } 2971e4b17023SJohn Marino 2972e4b17023SJohn Marino done: 2973e4b17023SJohn Marino /* Register the VAR_DECL as the equivalent for the RESULT_DECL; that 2974e4b17023SJohn Marino way, when the RESULT_DECL is encountered, it will be 2975e4b17023SJohn Marino automatically replaced by the VAR_DECL. 2976e4b17023SJohn Marino 2977e4b17023SJohn Marino When returning by reference, ensure that RESULT_DECL remaps to 2978e4b17023SJohn Marino gimple_val. */ 2979e4b17023SJohn Marino if (DECL_BY_REFERENCE (result) 2980e4b17023SJohn Marino && !is_gimple_val (var)) 2981e4b17023SJohn Marino { 2982e4b17023SJohn Marino tree temp = create_tmp_var (TREE_TYPE (result), "retvalptr"); 2983e4b17023SJohn Marino if (gimple_in_ssa_p (id->src_cfun)) 2984e4b17023SJohn Marino add_referenced_var (temp); 2985e4b17023SJohn Marino insert_decl_map (id, result, temp); 2986*5ce9237cSJohn Marino /* When RESULT_DECL is in SSA form, we need to remap and initialize 2987*5ce9237cSJohn Marino it's default_def SSA_NAME. */ 2988*5ce9237cSJohn Marino if (gimple_in_ssa_p (id->src_cfun) 2989*5ce9237cSJohn Marino && is_gimple_reg (result)) 2990*5ce9237cSJohn Marino { 2991*5ce9237cSJohn Marino temp = make_ssa_name (temp, NULL); 2992*5ce9237cSJohn Marino insert_decl_map (id, gimple_default_def (id->src_cfun, result), 2993*5ce9237cSJohn Marino temp); 2994*5ce9237cSJohn Marino } 2995e4b17023SJohn Marino insert_init_stmt (id, entry_bb, gimple_build_assign (temp, var)); 2996e4b17023SJohn Marino } 2997e4b17023SJohn Marino else 2998e4b17023SJohn Marino insert_decl_map (id, result, var); 2999e4b17023SJohn Marino 3000e4b17023SJohn Marino /* Remember this so we can ignore it in remap_decls. */ 3001e4b17023SJohn Marino id->retvar = var; 3002e4b17023SJohn Marino 3003e4b17023SJohn Marino return use; 3004e4b17023SJohn Marino } 3005e4b17023SJohn Marino 3006e4b17023SJohn Marino /* Callback through walk_tree. Determine if a DECL_INITIAL makes reference 3007e4b17023SJohn Marino to a local label. */ 3008e4b17023SJohn Marino 3009e4b17023SJohn Marino static tree 3010e4b17023SJohn Marino has_label_address_in_static_1 (tree *nodep, int *walk_subtrees, void *fnp) 3011e4b17023SJohn Marino { 3012e4b17023SJohn Marino tree node = *nodep; 3013e4b17023SJohn Marino tree fn = (tree) fnp; 3014e4b17023SJohn Marino 3015e4b17023SJohn Marino if (TREE_CODE (node) == LABEL_DECL && DECL_CONTEXT (node) == fn) 3016e4b17023SJohn Marino return node; 3017e4b17023SJohn Marino 3018e4b17023SJohn Marino if (TYPE_P (node)) 3019e4b17023SJohn Marino *walk_subtrees = 0; 3020e4b17023SJohn Marino 3021e4b17023SJohn Marino return NULL_TREE; 3022e4b17023SJohn Marino } 3023e4b17023SJohn Marino 3024e4b17023SJohn Marino /* Determine if the function can be copied. If so return NULL. If 3025e4b17023SJohn Marino not return a string describng the reason for failure. */ 3026e4b17023SJohn Marino 3027e4b17023SJohn Marino static const char * 3028e4b17023SJohn Marino copy_forbidden (struct function *fun, tree fndecl) 3029e4b17023SJohn Marino { 3030e4b17023SJohn Marino const char *reason = fun->cannot_be_copied_reason; 3031e4b17023SJohn Marino tree decl; 3032e4b17023SJohn Marino unsigned ix; 3033e4b17023SJohn Marino 3034e4b17023SJohn Marino /* Only examine the function once. */ 3035e4b17023SJohn Marino if (fun->cannot_be_copied_set) 3036e4b17023SJohn Marino return reason; 3037e4b17023SJohn Marino 3038e4b17023SJohn Marino /* We cannot copy a function that receives a non-local goto 3039e4b17023SJohn Marino because we cannot remap the destination label used in the 3040e4b17023SJohn Marino function that is performing the non-local goto. */ 3041e4b17023SJohn Marino /* ??? Actually, this should be possible, if we work at it. 3042e4b17023SJohn Marino No doubt there's just a handful of places that simply 3043e4b17023SJohn Marino assume it doesn't happen and don't substitute properly. */ 3044e4b17023SJohn Marino if (fun->has_nonlocal_label) 3045e4b17023SJohn Marino { 3046e4b17023SJohn Marino reason = G_("function %q+F can never be copied " 3047e4b17023SJohn Marino "because it receives a non-local goto"); 3048e4b17023SJohn Marino goto fail; 3049e4b17023SJohn Marino } 3050e4b17023SJohn Marino 3051e4b17023SJohn Marino FOR_EACH_LOCAL_DECL (fun, ix, decl) 3052e4b17023SJohn Marino if (TREE_CODE (decl) == VAR_DECL 3053e4b17023SJohn Marino && TREE_STATIC (decl) 3054e4b17023SJohn Marino && !DECL_EXTERNAL (decl) 3055e4b17023SJohn Marino && DECL_INITIAL (decl) 3056e4b17023SJohn Marino && walk_tree_without_duplicates (&DECL_INITIAL (decl), 3057e4b17023SJohn Marino has_label_address_in_static_1, 3058e4b17023SJohn Marino fndecl)) 3059e4b17023SJohn Marino { 3060e4b17023SJohn Marino reason = G_("function %q+F can never be copied because it saves " 3061e4b17023SJohn Marino "address of local label in a static variable"); 3062e4b17023SJohn Marino goto fail; 3063e4b17023SJohn Marino } 3064e4b17023SJohn Marino 3065e4b17023SJohn Marino fail: 3066e4b17023SJohn Marino fun->cannot_be_copied_reason = reason; 3067e4b17023SJohn Marino fun->cannot_be_copied_set = true; 3068e4b17023SJohn Marino return reason; 3069e4b17023SJohn Marino } 3070e4b17023SJohn Marino 3071e4b17023SJohn Marino 3072e4b17023SJohn Marino static const char *inline_forbidden_reason; 3073e4b17023SJohn Marino 3074e4b17023SJohn Marino /* A callback for walk_gimple_seq to handle statements. Returns non-null 3075e4b17023SJohn Marino iff a function can not be inlined. Also sets the reason why. */ 3076e4b17023SJohn Marino 3077e4b17023SJohn Marino static tree 3078e4b17023SJohn Marino inline_forbidden_p_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p, 3079e4b17023SJohn Marino struct walk_stmt_info *wip) 3080e4b17023SJohn Marino { 3081e4b17023SJohn Marino tree fn = (tree) wip->info; 3082e4b17023SJohn Marino tree t; 3083e4b17023SJohn Marino gimple stmt = gsi_stmt (*gsi); 3084e4b17023SJohn Marino 3085e4b17023SJohn Marino switch (gimple_code (stmt)) 3086e4b17023SJohn Marino { 3087e4b17023SJohn Marino case GIMPLE_CALL: 3088e4b17023SJohn Marino /* Refuse to inline alloca call unless user explicitly forced so as 3089e4b17023SJohn Marino this may change program's memory overhead drastically when the 3090e4b17023SJohn Marino function using alloca is called in loop. In GCC present in 3091e4b17023SJohn Marino SPEC2000 inlining into schedule_block cause it to require 2GB of 3092e4b17023SJohn Marino RAM instead of 256MB. Don't do so for alloca calls emitted for 3093e4b17023SJohn Marino VLA objects as those can't cause unbounded growth (they're always 3094e4b17023SJohn Marino wrapped inside stack_save/stack_restore regions. */ 3095e4b17023SJohn Marino if (gimple_alloca_call_p (stmt) 3096e4b17023SJohn Marino && !gimple_call_alloca_for_var_p (stmt) 3097e4b17023SJohn Marino && !lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn))) 3098e4b17023SJohn Marino { 3099e4b17023SJohn Marino inline_forbidden_reason 3100e4b17023SJohn Marino = G_("function %q+F can never be inlined because it uses " 3101e4b17023SJohn Marino "alloca (override using the always_inline attribute)"); 3102e4b17023SJohn Marino *handled_ops_p = true; 3103e4b17023SJohn Marino return fn; 3104e4b17023SJohn Marino } 3105e4b17023SJohn Marino 3106e4b17023SJohn Marino t = gimple_call_fndecl (stmt); 3107e4b17023SJohn Marino if (t == NULL_TREE) 3108e4b17023SJohn Marino break; 3109e4b17023SJohn Marino 3110e4b17023SJohn Marino /* We cannot inline functions that call setjmp. */ 3111e4b17023SJohn Marino if (setjmp_call_p (t)) 3112e4b17023SJohn Marino { 3113e4b17023SJohn Marino inline_forbidden_reason 3114e4b17023SJohn Marino = G_("function %q+F can never be inlined because it uses setjmp"); 3115e4b17023SJohn Marino *handled_ops_p = true; 3116e4b17023SJohn Marino return t; 3117e4b17023SJohn Marino } 3118e4b17023SJohn Marino 3119e4b17023SJohn Marino if (DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL) 3120e4b17023SJohn Marino switch (DECL_FUNCTION_CODE (t)) 3121e4b17023SJohn Marino { 3122e4b17023SJohn Marino /* We cannot inline functions that take a variable number of 3123e4b17023SJohn Marino arguments. */ 3124e4b17023SJohn Marino case BUILT_IN_VA_START: 3125e4b17023SJohn Marino case BUILT_IN_NEXT_ARG: 3126e4b17023SJohn Marino case BUILT_IN_VA_END: 3127e4b17023SJohn Marino inline_forbidden_reason 3128e4b17023SJohn Marino = G_("function %q+F can never be inlined because it " 3129e4b17023SJohn Marino "uses variable argument lists"); 3130e4b17023SJohn Marino *handled_ops_p = true; 3131e4b17023SJohn Marino return t; 3132e4b17023SJohn Marino 3133e4b17023SJohn Marino case BUILT_IN_LONGJMP: 3134e4b17023SJohn Marino /* We can't inline functions that call __builtin_longjmp at 3135e4b17023SJohn Marino all. The non-local goto machinery really requires the 3136e4b17023SJohn Marino destination be in a different function. If we allow the 3137e4b17023SJohn Marino function calling __builtin_longjmp to be inlined into the 3138e4b17023SJohn Marino function calling __builtin_setjmp, Things will Go Awry. */ 3139e4b17023SJohn Marino inline_forbidden_reason 3140e4b17023SJohn Marino = G_("function %q+F can never be inlined because " 3141e4b17023SJohn Marino "it uses setjmp-longjmp exception handling"); 3142e4b17023SJohn Marino *handled_ops_p = true; 3143e4b17023SJohn Marino return t; 3144e4b17023SJohn Marino 3145e4b17023SJohn Marino case BUILT_IN_NONLOCAL_GOTO: 3146e4b17023SJohn Marino /* Similarly. */ 3147e4b17023SJohn Marino inline_forbidden_reason 3148e4b17023SJohn Marino = G_("function %q+F can never be inlined because " 3149e4b17023SJohn Marino "it uses non-local goto"); 3150e4b17023SJohn Marino *handled_ops_p = true; 3151e4b17023SJohn Marino return t; 3152e4b17023SJohn Marino 3153e4b17023SJohn Marino case BUILT_IN_RETURN: 3154e4b17023SJohn Marino case BUILT_IN_APPLY_ARGS: 3155e4b17023SJohn Marino /* If a __builtin_apply_args caller would be inlined, 3156e4b17023SJohn Marino it would be saving arguments of the function it has 3157e4b17023SJohn Marino been inlined into. Similarly __builtin_return would 3158e4b17023SJohn Marino return from the function the inline has been inlined into. */ 3159e4b17023SJohn Marino inline_forbidden_reason 3160e4b17023SJohn Marino = G_("function %q+F can never be inlined because " 3161e4b17023SJohn Marino "it uses __builtin_return or __builtin_apply_args"); 3162e4b17023SJohn Marino *handled_ops_p = true; 3163e4b17023SJohn Marino return t; 3164e4b17023SJohn Marino 3165e4b17023SJohn Marino default: 3166e4b17023SJohn Marino break; 3167e4b17023SJohn Marino } 3168e4b17023SJohn Marino break; 3169e4b17023SJohn Marino 3170e4b17023SJohn Marino case GIMPLE_GOTO: 3171e4b17023SJohn Marino t = gimple_goto_dest (stmt); 3172e4b17023SJohn Marino 3173e4b17023SJohn Marino /* We will not inline a function which uses computed goto. The 3174e4b17023SJohn Marino addresses of its local labels, which may be tucked into 3175e4b17023SJohn Marino global storage, are of course not constant across 3176e4b17023SJohn Marino instantiations, which causes unexpected behavior. */ 3177e4b17023SJohn Marino if (TREE_CODE (t) != LABEL_DECL) 3178e4b17023SJohn Marino { 3179e4b17023SJohn Marino inline_forbidden_reason 3180e4b17023SJohn Marino = G_("function %q+F can never be inlined " 3181e4b17023SJohn Marino "because it contains a computed goto"); 3182e4b17023SJohn Marino *handled_ops_p = true; 3183e4b17023SJohn Marino return t; 3184e4b17023SJohn Marino } 3185e4b17023SJohn Marino break; 3186e4b17023SJohn Marino 3187e4b17023SJohn Marino default: 3188e4b17023SJohn Marino break; 3189e4b17023SJohn Marino } 3190e4b17023SJohn Marino 3191e4b17023SJohn Marino *handled_ops_p = false; 3192e4b17023SJohn Marino return NULL_TREE; 3193e4b17023SJohn Marino } 3194e4b17023SJohn Marino 3195e4b17023SJohn Marino /* Return true if FNDECL is a function that cannot be inlined into 3196e4b17023SJohn Marino another one. */ 3197e4b17023SJohn Marino 3198e4b17023SJohn Marino static bool 3199e4b17023SJohn Marino inline_forbidden_p (tree fndecl) 3200e4b17023SJohn Marino { 3201e4b17023SJohn Marino struct function *fun = DECL_STRUCT_FUNCTION (fndecl); 3202e4b17023SJohn Marino struct walk_stmt_info wi; 3203e4b17023SJohn Marino struct pointer_set_t *visited_nodes; 3204e4b17023SJohn Marino basic_block bb; 3205e4b17023SJohn Marino bool forbidden_p = false; 3206e4b17023SJohn Marino 3207e4b17023SJohn Marino /* First check for shared reasons not to copy the code. */ 3208e4b17023SJohn Marino inline_forbidden_reason = copy_forbidden (fun, fndecl); 3209e4b17023SJohn Marino if (inline_forbidden_reason != NULL) 3210e4b17023SJohn Marino return true; 3211e4b17023SJohn Marino 3212e4b17023SJohn Marino /* Next, walk the statements of the function looking for 3213e4b17023SJohn Marino constraucts we can't handle, or are non-optimal for inlining. */ 3214e4b17023SJohn Marino visited_nodes = pointer_set_create (); 3215e4b17023SJohn Marino memset (&wi, 0, sizeof (wi)); 3216e4b17023SJohn Marino wi.info = (void *) fndecl; 3217e4b17023SJohn Marino wi.pset = visited_nodes; 3218e4b17023SJohn Marino 3219e4b17023SJohn Marino FOR_EACH_BB_FN (bb, fun) 3220e4b17023SJohn Marino { 3221e4b17023SJohn Marino gimple ret; 3222e4b17023SJohn Marino gimple_seq seq = bb_seq (bb); 3223e4b17023SJohn Marino ret = walk_gimple_seq (seq, inline_forbidden_p_stmt, NULL, &wi); 3224e4b17023SJohn Marino forbidden_p = (ret != NULL); 3225e4b17023SJohn Marino if (forbidden_p) 3226e4b17023SJohn Marino break; 3227e4b17023SJohn Marino } 3228e4b17023SJohn Marino 3229e4b17023SJohn Marino pointer_set_destroy (visited_nodes); 3230e4b17023SJohn Marino return forbidden_p; 3231e4b17023SJohn Marino } 3232e4b17023SJohn Marino 3233e4b17023SJohn Marino /* Returns nonzero if FN is a function that does not have any 3234e4b17023SJohn Marino fundamental inline blocking properties. */ 3235e4b17023SJohn Marino 3236e4b17023SJohn Marino bool 3237e4b17023SJohn Marino tree_inlinable_function_p (tree fn) 3238e4b17023SJohn Marino { 3239e4b17023SJohn Marino bool inlinable = true; 3240e4b17023SJohn Marino bool do_warning; 3241e4b17023SJohn Marino tree always_inline; 3242e4b17023SJohn Marino 3243e4b17023SJohn Marino /* If we've already decided this function shouldn't be inlined, 3244e4b17023SJohn Marino there's no need to check again. */ 3245e4b17023SJohn Marino if (DECL_UNINLINABLE (fn)) 3246e4b17023SJohn Marino return false; 3247e4b17023SJohn Marino 3248e4b17023SJohn Marino /* We only warn for functions declared `inline' by the user. */ 3249e4b17023SJohn Marino do_warning = (warn_inline 3250e4b17023SJohn Marino && DECL_DECLARED_INLINE_P (fn) 3251e4b17023SJohn Marino && !DECL_NO_INLINE_WARNING_P (fn) 3252e4b17023SJohn Marino && !DECL_IN_SYSTEM_HEADER (fn)); 3253e4b17023SJohn Marino 3254e4b17023SJohn Marino always_inline = lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)); 3255e4b17023SJohn Marino 3256e4b17023SJohn Marino if (flag_no_inline 3257e4b17023SJohn Marino && always_inline == NULL) 3258e4b17023SJohn Marino { 3259e4b17023SJohn Marino if (do_warning) 3260e4b17023SJohn Marino warning (OPT_Winline, "function %q+F can never be inlined because it " 3261e4b17023SJohn Marino "is suppressed using -fno-inline", fn); 3262e4b17023SJohn Marino inlinable = false; 3263e4b17023SJohn Marino } 3264e4b17023SJohn Marino 3265e4b17023SJohn Marino else if (!function_attribute_inlinable_p (fn)) 3266e4b17023SJohn Marino { 3267e4b17023SJohn Marino if (do_warning) 3268e4b17023SJohn Marino warning (OPT_Winline, "function %q+F can never be inlined because it " 3269e4b17023SJohn Marino "uses attributes conflicting with inlining", fn); 3270e4b17023SJohn Marino inlinable = false; 3271e4b17023SJohn Marino } 3272e4b17023SJohn Marino 3273e4b17023SJohn Marino else if (inline_forbidden_p (fn)) 3274e4b17023SJohn Marino { 3275e4b17023SJohn Marino /* See if we should warn about uninlinable functions. Previously, 3276e4b17023SJohn Marino some of these warnings would be issued while trying to expand 3277e4b17023SJohn Marino the function inline, but that would cause multiple warnings 3278e4b17023SJohn Marino about functions that would for example call alloca. But since 3279e4b17023SJohn Marino this a property of the function, just one warning is enough. 3280e4b17023SJohn Marino As a bonus we can now give more details about the reason why a 3281e4b17023SJohn Marino function is not inlinable. */ 3282e4b17023SJohn Marino if (always_inline) 3283e4b17023SJohn Marino error (inline_forbidden_reason, fn); 3284e4b17023SJohn Marino else if (do_warning) 3285e4b17023SJohn Marino warning (OPT_Winline, inline_forbidden_reason, fn); 3286e4b17023SJohn Marino 3287e4b17023SJohn Marino inlinable = false; 3288e4b17023SJohn Marino } 3289e4b17023SJohn Marino 3290e4b17023SJohn Marino /* Squirrel away the result so that we don't have to check again. */ 3291e4b17023SJohn Marino DECL_UNINLINABLE (fn) = !inlinable; 3292e4b17023SJohn Marino 3293e4b17023SJohn Marino return inlinable; 3294e4b17023SJohn Marino } 3295e4b17023SJohn Marino 3296e4b17023SJohn Marino /* Estimate the cost of a memory move. Use machine dependent 3297e4b17023SJohn Marino word size and take possible memcpy call into account. */ 3298e4b17023SJohn Marino 3299e4b17023SJohn Marino int 3300e4b17023SJohn Marino estimate_move_cost (tree type) 3301e4b17023SJohn Marino { 3302e4b17023SJohn Marino HOST_WIDE_INT size; 3303e4b17023SJohn Marino 3304e4b17023SJohn Marino gcc_assert (!VOID_TYPE_P (type)); 3305e4b17023SJohn Marino 3306e4b17023SJohn Marino if (TREE_CODE (type) == VECTOR_TYPE) 3307e4b17023SJohn Marino { 3308e4b17023SJohn Marino enum machine_mode inner = TYPE_MODE (TREE_TYPE (type)); 3309e4b17023SJohn Marino enum machine_mode simd 3310e4b17023SJohn Marino = targetm.vectorize.preferred_simd_mode (inner); 3311e4b17023SJohn Marino int simd_mode_size = GET_MODE_SIZE (simd); 3312e4b17023SJohn Marino return ((GET_MODE_SIZE (TYPE_MODE (type)) + simd_mode_size - 1) 3313e4b17023SJohn Marino / simd_mode_size); 3314e4b17023SJohn Marino } 3315e4b17023SJohn Marino 3316e4b17023SJohn Marino size = int_size_in_bytes (type); 3317e4b17023SJohn Marino 3318e4b17023SJohn Marino if (size < 0 || size > MOVE_MAX_PIECES * MOVE_RATIO (!optimize_size)) 3319e4b17023SJohn Marino /* Cost of a memcpy call, 3 arguments and the call. */ 3320e4b17023SJohn Marino return 4; 3321e4b17023SJohn Marino else 3322e4b17023SJohn Marino return ((size + MOVE_MAX_PIECES - 1) / MOVE_MAX_PIECES); 3323e4b17023SJohn Marino } 3324e4b17023SJohn Marino 3325e4b17023SJohn Marino /* Returns cost of operation CODE, according to WEIGHTS */ 3326e4b17023SJohn Marino 3327e4b17023SJohn Marino static int 3328e4b17023SJohn Marino estimate_operator_cost (enum tree_code code, eni_weights *weights, 3329e4b17023SJohn Marino tree op1 ATTRIBUTE_UNUSED, tree op2) 3330e4b17023SJohn Marino { 3331e4b17023SJohn Marino switch (code) 3332e4b17023SJohn Marino { 3333e4b17023SJohn Marino /* These are "free" conversions, or their presumed cost 3334e4b17023SJohn Marino is folded into other operations. */ 3335e4b17023SJohn Marino case RANGE_EXPR: 3336e4b17023SJohn Marino CASE_CONVERT: 3337e4b17023SJohn Marino case COMPLEX_EXPR: 3338e4b17023SJohn Marino case PAREN_EXPR: 3339e4b17023SJohn Marino case VIEW_CONVERT_EXPR: 3340e4b17023SJohn Marino return 0; 3341e4b17023SJohn Marino 3342e4b17023SJohn Marino /* Assign cost of 1 to usual operations. 3343e4b17023SJohn Marino ??? We may consider mapping RTL costs to this. */ 3344e4b17023SJohn Marino case COND_EXPR: 3345e4b17023SJohn Marino case VEC_COND_EXPR: 3346e4b17023SJohn Marino case VEC_PERM_EXPR: 3347e4b17023SJohn Marino 3348e4b17023SJohn Marino case PLUS_EXPR: 3349e4b17023SJohn Marino case POINTER_PLUS_EXPR: 3350e4b17023SJohn Marino case MINUS_EXPR: 3351e4b17023SJohn Marino case MULT_EXPR: 3352e4b17023SJohn Marino case FMA_EXPR: 3353e4b17023SJohn Marino 3354e4b17023SJohn Marino case ADDR_SPACE_CONVERT_EXPR: 3355e4b17023SJohn Marino case FIXED_CONVERT_EXPR: 3356e4b17023SJohn Marino case FIX_TRUNC_EXPR: 3357e4b17023SJohn Marino 3358e4b17023SJohn Marino case NEGATE_EXPR: 3359e4b17023SJohn Marino case FLOAT_EXPR: 3360e4b17023SJohn Marino case MIN_EXPR: 3361e4b17023SJohn Marino case MAX_EXPR: 3362e4b17023SJohn Marino case ABS_EXPR: 3363e4b17023SJohn Marino 3364e4b17023SJohn Marino case LSHIFT_EXPR: 3365e4b17023SJohn Marino case RSHIFT_EXPR: 3366e4b17023SJohn Marino case LROTATE_EXPR: 3367e4b17023SJohn Marino case RROTATE_EXPR: 3368e4b17023SJohn Marino case VEC_LSHIFT_EXPR: 3369e4b17023SJohn Marino case VEC_RSHIFT_EXPR: 3370e4b17023SJohn Marino 3371e4b17023SJohn Marino case BIT_IOR_EXPR: 3372e4b17023SJohn Marino case BIT_XOR_EXPR: 3373e4b17023SJohn Marino case BIT_AND_EXPR: 3374e4b17023SJohn Marino case BIT_NOT_EXPR: 3375e4b17023SJohn Marino 3376e4b17023SJohn Marino case TRUTH_ANDIF_EXPR: 3377e4b17023SJohn Marino case TRUTH_ORIF_EXPR: 3378e4b17023SJohn Marino case TRUTH_AND_EXPR: 3379e4b17023SJohn Marino case TRUTH_OR_EXPR: 3380e4b17023SJohn Marino case TRUTH_XOR_EXPR: 3381e4b17023SJohn Marino case TRUTH_NOT_EXPR: 3382e4b17023SJohn Marino 3383e4b17023SJohn Marino case LT_EXPR: 3384e4b17023SJohn Marino case LE_EXPR: 3385e4b17023SJohn Marino case GT_EXPR: 3386e4b17023SJohn Marino case GE_EXPR: 3387e4b17023SJohn Marino case EQ_EXPR: 3388e4b17023SJohn Marino case NE_EXPR: 3389e4b17023SJohn Marino case ORDERED_EXPR: 3390e4b17023SJohn Marino case UNORDERED_EXPR: 3391e4b17023SJohn Marino 3392e4b17023SJohn Marino case UNLT_EXPR: 3393e4b17023SJohn Marino case UNLE_EXPR: 3394e4b17023SJohn Marino case UNGT_EXPR: 3395e4b17023SJohn Marino case UNGE_EXPR: 3396e4b17023SJohn Marino case UNEQ_EXPR: 3397e4b17023SJohn Marino case LTGT_EXPR: 3398e4b17023SJohn Marino 3399e4b17023SJohn Marino case CONJ_EXPR: 3400e4b17023SJohn Marino 3401e4b17023SJohn Marino case PREDECREMENT_EXPR: 3402e4b17023SJohn Marino case PREINCREMENT_EXPR: 3403e4b17023SJohn Marino case POSTDECREMENT_EXPR: 3404e4b17023SJohn Marino case POSTINCREMENT_EXPR: 3405e4b17023SJohn Marino 3406e4b17023SJohn Marino case REALIGN_LOAD_EXPR: 3407e4b17023SJohn Marino 3408e4b17023SJohn Marino case REDUC_MAX_EXPR: 3409e4b17023SJohn Marino case REDUC_MIN_EXPR: 3410e4b17023SJohn Marino case REDUC_PLUS_EXPR: 3411e4b17023SJohn Marino case WIDEN_SUM_EXPR: 3412e4b17023SJohn Marino case WIDEN_MULT_EXPR: 3413e4b17023SJohn Marino case DOT_PROD_EXPR: 3414e4b17023SJohn Marino case WIDEN_MULT_PLUS_EXPR: 3415e4b17023SJohn Marino case WIDEN_MULT_MINUS_EXPR: 3416e4b17023SJohn Marino case WIDEN_LSHIFT_EXPR: 3417e4b17023SJohn Marino 3418e4b17023SJohn Marino case VEC_WIDEN_MULT_HI_EXPR: 3419e4b17023SJohn Marino case VEC_WIDEN_MULT_LO_EXPR: 3420e4b17023SJohn Marino case VEC_UNPACK_HI_EXPR: 3421e4b17023SJohn Marino case VEC_UNPACK_LO_EXPR: 3422e4b17023SJohn Marino case VEC_UNPACK_FLOAT_HI_EXPR: 3423e4b17023SJohn Marino case VEC_UNPACK_FLOAT_LO_EXPR: 3424e4b17023SJohn Marino case VEC_PACK_TRUNC_EXPR: 3425e4b17023SJohn Marino case VEC_PACK_SAT_EXPR: 3426e4b17023SJohn Marino case VEC_PACK_FIX_TRUNC_EXPR: 3427e4b17023SJohn Marino case VEC_WIDEN_LSHIFT_HI_EXPR: 3428e4b17023SJohn Marino case VEC_WIDEN_LSHIFT_LO_EXPR: 3429e4b17023SJohn Marino 3430e4b17023SJohn Marino return 1; 3431e4b17023SJohn Marino 3432e4b17023SJohn Marino /* Few special cases of expensive operations. This is useful 3433e4b17023SJohn Marino to avoid inlining on functions having too many of these. */ 3434e4b17023SJohn Marino case TRUNC_DIV_EXPR: 3435e4b17023SJohn Marino case CEIL_DIV_EXPR: 3436e4b17023SJohn Marino case FLOOR_DIV_EXPR: 3437e4b17023SJohn Marino case ROUND_DIV_EXPR: 3438e4b17023SJohn Marino case EXACT_DIV_EXPR: 3439e4b17023SJohn Marino case TRUNC_MOD_EXPR: 3440e4b17023SJohn Marino case CEIL_MOD_EXPR: 3441e4b17023SJohn Marino case FLOOR_MOD_EXPR: 3442e4b17023SJohn Marino case ROUND_MOD_EXPR: 3443e4b17023SJohn Marino case RDIV_EXPR: 3444e4b17023SJohn Marino if (TREE_CODE (op2) != INTEGER_CST) 3445e4b17023SJohn Marino return weights->div_mod_cost; 3446e4b17023SJohn Marino return 1; 3447e4b17023SJohn Marino 3448e4b17023SJohn Marino default: 3449e4b17023SJohn Marino /* We expect a copy assignment with no operator. */ 3450e4b17023SJohn Marino gcc_assert (get_gimple_rhs_class (code) == GIMPLE_SINGLE_RHS); 3451e4b17023SJohn Marino return 0; 3452e4b17023SJohn Marino } 3453e4b17023SJohn Marino } 3454e4b17023SJohn Marino 3455e4b17023SJohn Marino 3456e4b17023SJohn Marino /* Estimate number of instructions that will be created by expanding 3457e4b17023SJohn Marino the statements in the statement sequence STMTS. 3458e4b17023SJohn Marino WEIGHTS contains weights attributed to various constructs. */ 3459e4b17023SJohn Marino 3460e4b17023SJohn Marino static 3461e4b17023SJohn Marino int estimate_num_insns_seq (gimple_seq stmts, eni_weights *weights) 3462e4b17023SJohn Marino { 3463e4b17023SJohn Marino int cost; 3464e4b17023SJohn Marino gimple_stmt_iterator gsi; 3465e4b17023SJohn Marino 3466e4b17023SJohn Marino cost = 0; 3467e4b17023SJohn Marino for (gsi = gsi_start (stmts); !gsi_end_p (gsi); gsi_next (&gsi)) 3468e4b17023SJohn Marino cost += estimate_num_insns (gsi_stmt (gsi), weights); 3469e4b17023SJohn Marino 3470e4b17023SJohn Marino return cost; 3471e4b17023SJohn Marino } 3472e4b17023SJohn Marino 3473e4b17023SJohn Marino 3474e4b17023SJohn Marino /* Estimate number of instructions that will be created by expanding STMT. 3475e4b17023SJohn Marino WEIGHTS contains weights attributed to various constructs. */ 3476e4b17023SJohn Marino 3477e4b17023SJohn Marino int 3478e4b17023SJohn Marino estimate_num_insns (gimple stmt, eni_weights *weights) 3479e4b17023SJohn Marino { 3480e4b17023SJohn Marino unsigned cost, i; 3481e4b17023SJohn Marino enum gimple_code code = gimple_code (stmt); 3482e4b17023SJohn Marino tree lhs; 3483e4b17023SJohn Marino tree rhs; 3484e4b17023SJohn Marino 3485e4b17023SJohn Marino switch (code) 3486e4b17023SJohn Marino { 3487e4b17023SJohn Marino case GIMPLE_ASSIGN: 3488e4b17023SJohn Marino /* Try to estimate the cost of assignments. We have three cases to 3489e4b17023SJohn Marino deal with: 3490e4b17023SJohn Marino 1) Simple assignments to registers; 3491e4b17023SJohn Marino 2) Stores to things that must live in memory. This includes 3492e4b17023SJohn Marino "normal" stores to scalars, but also assignments of large 3493e4b17023SJohn Marino structures, or constructors of big arrays; 3494e4b17023SJohn Marino 3495e4b17023SJohn Marino Let us look at the first two cases, assuming we have "a = b + C": 3496e4b17023SJohn Marino <GIMPLE_ASSIGN <var_decl "a"> 3497e4b17023SJohn Marino <plus_expr <var_decl "b"> <constant C>> 3498e4b17023SJohn Marino If "a" is a GIMPLE register, the assignment to it is free on almost 3499e4b17023SJohn Marino any target, because "a" usually ends up in a real register. Hence 3500e4b17023SJohn Marino the only cost of this expression comes from the PLUS_EXPR, and we 3501e4b17023SJohn Marino can ignore the GIMPLE_ASSIGN. 3502e4b17023SJohn Marino If "a" is not a GIMPLE register, the assignment to "a" will most 3503e4b17023SJohn Marino likely be a real store, so the cost of the GIMPLE_ASSIGN is the cost 3504e4b17023SJohn Marino of moving something into "a", which we compute using the function 3505e4b17023SJohn Marino estimate_move_cost. */ 3506e4b17023SJohn Marino if (gimple_clobber_p (stmt)) 3507e4b17023SJohn Marino return 0; /* ={v} {CLOBBER} stmt expands to nothing. */ 3508e4b17023SJohn Marino 3509e4b17023SJohn Marino lhs = gimple_assign_lhs (stmt); 3510e4b17023SJohn Marino rhs = gimple_assign_rhs1 (stmt); 3511e4b17023SJohn Marino 3512e4b17023SJohn Marino if (is_gimple_reg (lhs)) 3513e4b17023SJohn Marino cost = 0; 3514e4b17023SJohn Marino else 3515e4b17023SJohn Marino cost = estimate_move_cost (TREE_TYPE (lhs)); 3516e4b17023SJohn Marino 3517e4b17023SJohn Marino if (!is_gimple_reg (rhs) && !is_gimple_min_invariant (rhs)) 3518e4b17023SJohn Marino cost += estimate_move_cost (TREE_TYPE (rhs)); 3519e4b17023SJohn Marino 3520e4b17023SJohn Marino cost += estimate_operator_cost (gimple_assign_rhs_code (stmt), weights, 3521e4b17023SJohn Marino gimple_assign_rhs1 (stmt), 3522e4b17023SJohn Marino get_gimple_rhs_class (gimple_assign_rhs_code (stmt)) 3523e4b17023SJohn Marino == GIMPLE_BINARY_RHS 3524e4b17023SJohn Marino ? gimple_assign_rhs2 (stmt) : NULL); 3525e4b17023SJohn Marino break; 3526e4b17023SJohn Marino 3527e4b17023SJohn Marino case GIMPLE_COND: 3528e4b17023SJohn Marino cost = 1 + estimate_operator_cost (gimple_cond_code (stmt), weights, 3529e4b17023SJohn Marino gimple_op (stmt, 0), 3530e4b17023SJohn Marino gimple_op (stmt, 1)); 3531e4b17023SJohn Marino break; 3532e4b17023SJohn Marino 3533e4b17023SJohn Marino case GIMPLE_SWITCH: 3534e4b17023SJohn Marino /* Take into account cost of the switch + guess 2 conditional jumps for 3535e4b17023SJohn Marino each case label. 3536e4b17023SJohn Marino 3537e4b17023SJohn Marino TODO: once the switch expansion logic is sufficiently separated, we can 3538e4b17023SJohn Marino do better job on estimating cost of the switch. */ 3539e4b17023SJohn Marino if (weights->time_based) 3540e4b17023SJohn Marino cost = floor_log2 (gimple_switch_num_labels (stmt)) * 2; 3541e4b17023SJohn Marino else 3542e4b17023SJohn Marino cost = gimple_switch_num_labels (stmt) * 2; 3543e4b17023SJohn Marino break; 3544e4b17023SJohn Marino 3545e4b17023SJohn Marino case GIMPLE_CALL: 3546e4b17023SJohn Marino { 3547e4b17023SJohn Marino tree decl = gimple_call_fndecl (stmt); 3548e4b17023SJohn Marino struct cgraph_node *node = NULL; 3549e4b17023SJohn Marino 3550e4b17023SJohn Marino /* Do not special case builtins where we see the body. 3551e4b17023SJohn Marino This just confuse inliner. */ 3552e4b17023SJohn Marino if (!decl || !(node = cgraph_get_node (decl)) || node->analyzed) 3553e4b17023SJohn Marino ; 3554e4b17023SJohn Marino /* For buitins that are likely expanded to nothing or 3555e4b17023SJohn Marino inlined do not account operand costs. */ 3556e4b17023SJohn Marino else if (is_simple_builtin (decl)) 3557e4b17023SJohn Marino return 0; 3558e4b17023SJohn Marino else if (is_inexpensive_builtin (decl)) 3559e4b17023SJohn Marino return weights->target_builtin_call_cost; 3560e4b17023SJohn Marino else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL) 3561e4b17023SJohn Marino { 3562e4b17023SJohn Marino /* We canonicalize x * x to pow (x, 2.0) with -ffast-math, so 3563e4b17023SJohn Marino specialize the cheap expansion we do here. 3564e4b17023SJohn Marino ??? This asks for a more general solution. */ 3565e4b17023SJohn Marino switch (DECL_FUNCTION_CODE (decl)) 3566e4b17023SJohn Marino { 3567e4b17023SJohn Marino case BUILT_IN_POW: 3568e4b17023SJohn Marino case BUILT_IN_POWF: 3569e4b17023SJohn Marino case BUILT_IN_POWL: 3570e4b17023SJohn Marino if (TREE_CODE (gimple_call_arg (stmt, 1)) == REAL_CST 3571e4b17023SJohn Marino && REAL_VALUES_EQUAL 3572e4b17023SJohn Marino (TREE_REAL_CST (gimple_call_arg (stmt, 1)), dconst2)) 3573e4b17023SJohn Marino return estimate_operator_cost (MULT_EXPR, weights, 3574e4b17023SJohn Marino gimple_call_arg (stmt, 0), 3575e4b17023SJohn Marino gimple_call_arg (stmt, 0)); 3576e4b17023SJohn Marino break; 3577e4b17023SJohn Marino 3578e4b17023SJohn Marino default: 3579e4b17023SJohn Marino break; 3580e4b17023SJohn Marino } 3581e4b17023SJohn Marino } 3582e4b17023SJohn Marino 3583e4b17023SJohn Marino cost = node ? weights->call_cost : weights->indirect_call_cost; 3584e4b17023SJohn Marino if (gimple_call_lhs (stmt)) 3585e4b17023SJohn Marino cost += estimate_move_cost (TREE_TYPE (gimple_call_lhs (stmt))); 3586e4b17023SJohn Marino for (i = 0; i < gimple_call_num_args (stmt); i++) 3587e4b17023SJohn Marino { 3588e4b17023SJohn Marino tree arg = gimple_call_arg (stmt, i); 3589e4b17023SJohn Marino cost += estimate_move_cost (TREE_TYPE (arg)); 3590e4b17023SJohn Marino } 3591e4b17023SJohn Marino break; 3592e4b17023SJohn Marino } 3593e4b17023SJohn Marino 3594e4b17023SJohn Marino case GIMPLE_RETURN: 3595e4b17023SJohn Marino return weights->return_cost; 3596e4b17023SJohn Marino 3597e4b17023SJohn Marino case GIMPLE_GOTO: 3598e4b17023SJohn Marino case GIMPLE_LABEL: 3599e4b17023SJohn Marino case GIMPLE_NOP: 3600e4b17023SJohn Marino case GIMPLE_PHI: 3601e4b17023SJohn Marino case GIMPLE_PREDICT: 3602e4b17023SJohn Marino case GIMPLE_DEBUG: 3603e4b17023SJohn Marino return 0; 3604e4b17023SJohn Marino 3605e4b17023SJohn Marino case GIMPLE_ASM: 3606e4b17023SJohn Marino return asm_str_count (gimple_asm_string (stmt)); 3607e4b17023SJohn Marino 3608e4b17023SJohn Marino case GIMPLE_RESX: 3609e4b17023SJohn Marino /* This is either going to be an external function call with one 3610e4b17023SJohn Marino argument, or two register copy statements plus a goto. */ 3611e4b17023SJohn Marino return 2; 3612e4b17023SJohn Marino 3613e4b17023SJohn Marino case GIMPLE_EH_DISPATCH: 3614e4b17023SJohn Marino /* ??? This is going to turn into a switch statement. Ideally 3615e4b17023SJohn Marino we'd have a look at the eh region and estimate the number of 3616e4b17023SJohn Marino edges involved. */ 3617e4b17023SJohn Marino return 10; 3618e4b17023SJohn Marino 3619e4b17023SJohn Marino case GIMPLE_BIND: 3620e4b17023SJohn Marino return estimate_num_insns_seq (gimple_bind_body (stmt), weights); 3621e4b17023SJohn Marino 3622e4b17023SJohn Marino case GIMPLE_EH_FILTER: 3623e4b17023SJohn Marino return estimate_num_insns_seq (gimple_eh_filter_failure (stmt), weights); 3624e4b17023SJohn Marino 3625e4b17023SJohn Marino case GIMPLE_CATCH: 3626e4b17023SJohn Marino return estimate_num_insns_seq (gimple_catch_handler (stmt), weights); 3627e4b17023SJohn Marino 3628e4b17023SJohn Marino case GIMPLE_TRY: 3629e4b17023SJohn Marino return (estimate_num_insns_seq (gimple_try_eval (stmt), weights) 3630e4b17023SJohn Marino + estimate_num_insns_seq (gimple_try_cleanup (stmt), weights)); 3631e4b17023SJohn Marino 3632e4b17023SJohn Marino /* OpenMP directives are generally very expensive. */ 3633e4b17023SJohn Marino 3634e4b17023SJohn Marino case GIMPLE_OMP_RETURN: 3635e4b17023SJohn Marino case GIMPLE_OMP_SECTIONS_SWITCH: 3636e4b17023SJohn Marino case GIMPLE_OMP_ATOMIC_STORE: 3637e4b17023SJohn Marino case GIMPLE_OMP_CONTINUE: 3638e4b17023SJohn Marino /* ...except these, which are cheap. */ 3639e4b17023SJohn Marino return 0; 3640e4b17023SJohn Marino 3641e4b17023SJohn Marino case GIMPLE_OMP_ATOMIC_LOAD: 3642e4b17023SJohn Marino return weights->omp_cost; 3643e4b17023SJohn Marino 3644e4b17023SJohn Marino case GIMPLE_OMP_FOR: 3645e4b17023SJohn Marino return (weights->omp_cost 3646e4b17023SJohn Marino + estimate_num_insns_seq (gimple_omp_body (stmt), weights) 3647e4b17023SJohn Marino + estimate_num_insns_seq (gimple_omp_for_pre_body (stmt), weights)); 3648e4b17023SJohn Marino 3649e4b17023SJohn Marino case GIMPLE_OMP_PARALLEL: 3650e4b17023SJohn Marino case GIMPLE_OMP_TASK: 3651e4b17023SJohn Marino case GIMPLE_OMP_CRITICAL: 3652e4b17023SJohn Marino case GIMPLE_OMP_MASTER: 3653e4b17023SJohn Marino case GIMPLE_OMP_ORDERED: 3654e4b17023SJohn Marino case GIMPLE_OMP_SECTION: 3655e4b17023SJohn Marino case GIMPLE_OMP_SECTIONS: 3656e4b17023SJohn Marino case GIMPLE_OMP_SINGLE: 3657e4b17023SJohn Marino return (weights->omp_cost 3658e4b17023SJohn Marino + estimate_num_insns_seq (gimple_omp_body (stmt), weights)); 3659e4b17023SJohn Marino 3660e4b17023SJohn Marino case GIMPLE_TRANSACTION: 3661e4b17023SJohn Marino return (weights->tm_cost 3662e4b17023SJohn Marino + estimate_num_insns_seq (gimple_transaction_body (stmt), 3663e4b17023SJohn Marino weights)); 3664e4b17023SJohn Marino 3665e4b17023SJohn Marino default: 3666e4b17023SJohn Marino gcc_unreachable (); 3667e4b17023SJohn Marino } 3668e4b17023SJohn Marino 3669e4b17023SJohn Marino return cost; 3670e4b17023SJohn Marino } 3671e4b17023SJohn Marino 3672e4b17023SJohn Marino /* Estimate number of instructions that will be created by expanding 3673e4b17023SJohn Marino function FNDECL. WEIGHTS contains weights attributed to various 3674e4b17023SJohn Marino constructs. */ 3675e4b17023SJohn Marino 3676e4b17023SJohn Marino int 3677e4b17023SJohn Marino estimate_num_insns_fn (tree fndecl, eni_weights *weights) 3678e4b17023SJohn Marino { 3679e4b17023SJohn Marino struct function *my_function = DECL_STRUCT_FUNCTION (fndecl); 3680e4b17023SJohn Marino gimple_stmt_iterator bsi; 3681e4b17023SJohn Marino basic_block bb; 3682e4b17023SJohn Marino int n = 0; 3683e4b17023SJohn Marino 3684e4b17023SJohn Marino gcc_assert (my_function && my_function->cfg); 3685e4b17023SJohn Marino FOR_EACH_BB_FN (bb, my_function) 3686e4b17023SJohn Marino { 3687e4b17023SJohn Marino for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) 3688e4b17023SJohn Marino n += estimate_num_insns (gsi_stmt (bsi), weights); 3689e4b17023SJohn Marino } 3690e4b17023SJohn Marino 3691e4b17023SJohn Marino return n; 3692e4b17023SJohn Marino } 3693e4b17023SJohn Marino 3694e4b17023SJohn Marino 3695e4b17023SJohn Marino /* Initializes weights used by estimate_num_insns. */ 3696e4b17023SJohn Marino 3697e4b17023SJohn Marino void 3698e4b17023SJohn Marino init_inline_once (void) 3699e4b17023SJohn Marino { 3700e4b17023SJohn Marino eni_size_weights.call_cost = 1; 3701e4b17023SJohn Marino eni_size_weights.indirect_call_cost = 3; 3702e4b17023SJohn Marino eni_size_weights.target_builtin_call_cost = 1; 3703e4b17023SJohn Marino eni_size_weights.div_mod_cost = 1; 3704e4b17023SJohn Marino eni_size_weights.omp_cost = 40; 3705e4b17023SJohn Marino eni_size_weights.tm_cost = 10; 3706e4b17023SJohn Marino eni_size_weights.time_based = false; 3707e4b17023SJohn Marino eni_size_weights.return_cost = 1; 3708e4b17023SJohn Marino 3709e4b17023SJohn Marino /* Estimating time for call is difficult, since we have no idea what the 3710e4b17023SJohn Marino called function does. In the current uses of eni_time_weights, 3711e4b17023SJohn Marino underestimating the cost does less harm than overestimating it, so 3712e4b17023SJohn Marino we choose a rather small value here. */ 3713e4b17023SJohn Marino eni_time_weights.call_cost = 10; 3714e4b17023SJohn Marino eni_time_weights.indirect_call_cost = 15; 3715e4b17023SJohn Marino eni_time_weights.target_builtin_call_cost = 1; 3716e4b17023SJohn Marino eni_time_weights.div_mod_cost = 10; 3717e4b17023SJohn Marino eni_time_weights.omp_cost = 40; 3718e4b17023SJohn Marino eni_time_weights.tm_cost = 40; 3719e4b17023SJohn Marino eni_time_weights.time_based = true; 3720e4b17023SJohn Marino eni_time_weights.return_cost = 2; 3721e4b17023SJohn Marino } 3722e4b17023SJohn Marino 3723e4b17023SJohn Marino /* Estimate the number of instructions in a gimple_seq. */ 3724e4b17023SJohn Marino 3725e4b17023SJohn Marino int 3726e4b17023SJohn Marino count_insns_seq (gimple_seq seq, eni_weights *weights) 3727e4b17023SJohn Marino { 3728e4b17023SJohn Marino gimple_stmt_iterator gsi; 3729e4b17023SJohn Marino int n = 0; 3730e4b17023SJohn Marino for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi)) 3731e4b17023SJohn Marino n += estimate_num_insns (gsi_stmt (gsi), weights); 3732e4b17023SJohn Marino 3733e4b17023SJohn Marino return n; 3734e4b17023SJohn Marino } 3735e4b17023SJohn Marino 3736e4b17023SJohn Marino 3737e4b17023SJohn Marino /* Install new lexical TREE_BLOCK underneath 'current_block'. */ 3738e4b17023SJohn Marino 3739e4b17023SJohn Marino static void 3740e4b17023SJohn Marino prepend_lexical_block (tree current_block, tree new_block) 3741e4b17023SJohn Marino { 3742e4b17023SJohn Marino BLOCK_CHAIN (new_block) = BLOCK_SUBBLOCKS (current_block); 3743e4b17023SJohn Marino BLOCK_SUBBLOCKS (current_block) = new_block; 3744e4b17023SJohn Marino BLOCK_SUPERCONTEXT (new_block) = current_block; 3745e4b17023SJohn Marino } 3746e4b17023SJohn Marino 3747e4b17023SJohn Marino /* Add local variables from CALLEE to CALLER. */ 3748e4b17023SJohn Marino 3749e4b17023SJohn Marino static inline void 3750e4b17023SJohn Marino add_local_variables (struct function *callee, struct function *caller, 3751e4b17023SJohn Marino copy_body_data *id, bool check_var_ann) 3752e4b17023SJohn Marino { 3753e4b17023SJohn Marino tree var; 3754e4b17023SJohn Marino unsigned ix; 3755e4b17023SJohn Marino 3756e4b17023SJohn Marino FOR_EACH_LOCAL_DECL (callee, ix, var) 3757e4b17023SJohn Marino if (TREE_STATIC (var) && !TREE_ASM_WRITTEN (var)) 3758e4b17023SJohn Marino { 3759e4b17023SJohn Marino if (!check_var_ann 3760e4b17023SJohn Marino || (var_ann (var) && add_referenced_var (var))) 3761e4b17023SJohn Marino add_local_decl (caller, var); 3762e4b17023SJohn Marino } 3763e4b17023SJohn Marino else if (!can_be_nonlocal (var, id)) 3764e4b17023SJohn Marino { 3765e4b17023SJohn Marino tree new_var = remap_decl (var, id); 3766e4b17023SJohn Marino 3767e4b17023SJohn Marino /* Remap debug-expressions. */ 3768e4b17023SJohn Marino if (TREE_CODE (new_var) == VAR_DECL 3769e4b17023SJohn Marino && DECL_DEBUG_EXPR_IS_FROM (new_var) 3770e4b17023SJohn Marino && new_var != var) 3771e4b17023SJohn Marino { 3772e4b17023SJohn Marino tree tem = DECL_DEBUG_EXPR (var); 3773e4b17023SJohn Marino bool old_regimplify = id->regimplify; 3774e4b17023SJohn Marino id->remapping_type_depth++; 3775e4b17023SJohn Marino walk_tree (&tem, copy_tree_body_r, id, NULL); 3776e4b17023SJohn Marino id->remapping_type_depth--; 3777e4b17023SJohn Marino id->regimplify = old_regimplify; 3778e4b17023SJohn Marino SET_DECL_DEBUG_EXPR (new_var, tem); 3779e4b17023SJohn Marino } 3780e4b17023SJohn Marino add_local_decl (caller, new_var); 3781e4b17023SJohn Marino } 3782e4b17023SJohn Marino } 3783e4b17023SJohn Marino 3784e4b17023SJohn Marino /* If STMT is a GIMPLE_CALL, replace it with its inline expansion. */ 3785e4b17023SJohn Marino 3786e4b17023SJohn Marino static bool 3787e4b17023SJohn Marino expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id) 3788e4b17023SJohn Marino { 3789e4b17023SJohn Marino tree use_retvar; 3790e4b17023SJohn Marino tree fn; 3791e4b17023SJohn Marino struct pointer_map_t *st, *dst; 3792e4b17023SJohn Marino tree return_slot; 3793e4b17023SJohn Marino tree modify_dest; 3794e4b17023SJohn Marino location_t saved_location; 3795e4b17023SJohn Marino struct cgraph_edge *cg_edge; 3796e4b17023SJohn Marino cgraph_inline_failed_t reason; 3797e4b17023SJohn Marino basic_block return_block; 3798e4b17023SJohn Marino edge e; 3799e4b17023SJohn Marino gimple_stmt_iterator gsi, stmt_gsi; 3800e4b17023SJohn Marino bool successfully_inlined = FALSE; 3801e4b17023SJohn Marino bool purge_dead_abnormal_edges; 3802e4b17023SJohn Marino 3803e4b17023SJohn Marino /* Set input_location here so we get the right instantiation context 3804e4b17023SJohn Marino if we call instantiate_decl from inlinable_function_p. */ 3805e4b17023SJohn Marino saved_location = input_location; 3806e4b17023SJohn Marino if (gimple_has_location (stmt)) 3807e4b17023SJohn Marino input_location = gimple_location (stmt); 3808e4b17023SJohn Marino 3809e4b17023SJohn Marino /* From here on, we're only interested in CALL_EXPRs. */ 3810e4b17023SJohn Marino if (gimple_code (stmt) != GIMPLE_CALL) 3811e4b17023SJohn Marino goto egress; 3812e4b17023SJohn Marino 3813e4b17023SJohn Marino cg_edge = cgraph_edge (id->dst_node, stmt); 3814e4b17023SJohn Marino gcc_checking_assert (cg_edge); 3815e4b17023SJohn Marino /* First, see if we can figure out what function is being called. 3816e4b17023SJohn Marino If we cannot, then there is no hope of inlining the function. */ 3817e4b17023SJohn Marino if (cg_edge->indirect_unknown_callee) 3818e4b17023SJohn Marino goto egress; 3819e4b17023SJohn Marino fn = cg_edge->callee->decl; 3820e4b17023SJohn Marino gcc_checking_assert (fn); 3821e4b17023SJohn Marino 3822e4b17023SJohn Marino /* If FN is a declaration of a function in a nested scope that was 3823e4b17023SJohn Marino globally declared inline, we don't set its DECL_INITIAL. 3824e4b17023SJohn Marino However, we can't blindly follow DECL_ABSTRACT_ORIGIN because the 3825e4b17023SJohn Marino C++ front-end uses it for cdtors to refer to their internal 3826e4b17023SJohn Marino declarations, that are not real functions. Fortunately those 3827e4b17023SJohn Marino don't have trees to be saved, so we can tell by checking their 3828e4b17023SJohn Marino gimple_body. */ 3829e4b17023SJohn Marino if (!DECL_INITIAL (fn) 3830e4b17023SJohn Marino && DECL_ABSTRACT_ORIGIN (fn) 3831e4b17023SJohn Marino && gimple_has_body_p (DECL_ABSTRACT_ORIGIN (fn))) 3832e4b17023SJohn Marino fn = DECL_ABSTRACT_ORIGIN (fn); 3833e4b17023SJohn Marino 3834e4b17023SJohn Marino /* Don't try to inline functions that are not well-suited to inlining. */ 3835e4b17023SJohn Marino if (!cgraph_inline_p (cg_edge, &reason)) 3836e4b17023SJohn Marino { 3837e4b17023SJohn Marino /* If this call was originally indirect, we do not want to emit any 3838e4b17023SJohn Marino inlining related warnings or sorry messages because there are no 3839e4b17023SJohn Marino guarantees regarding those. */ 3840e4b17023SJohn Marino if (cg_edge->indirect_inlining_edge) 3841e4b17023SJohn Marino goto egress; 3842e4b17023SJohn Marino 3843e4b17023SJohn Marino if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) 3844*5ce9237cSJohn Marino /* For extern inline functions that get redefined we always 3845*5ce9237cSJohn Marino silently ignored always_inline flag. Better behaviour would 3846*5ce9237cSJohn Marino be to be able to keep both bodies and use extern inline body 3847*5ce9237cSJohn Marino for inlining, but we can't do that because frontends overwrite 3848*5ce9237cSJohn Marino the body. */ 3849*5ce9237cSJohn Marino && !cg_edge->callee->local.redefined_extern_inline 3850e4b17023SJohn Marino /* Avoid warnings during early inline pass. */ 3851e4b17023SJohn Marino && cgraph_global_info_ready 3852e4b17023SJohn Marino /* PR 20090218-1_0.c. Body can be provided by another module. */ 3853e4b17023SJohn Marino && (reason != CIF_BODY_NOT_AVAILABLE || !flag_generate_lto)) 3854e4b17023SJohn Marino { 3855e4b17023SJohn Marino error ("inlining failed in call to always_inline %q+F: %s", fn, 3856e4b17023SJohn Marino cgraph_inline_failed_string (reason)); 3857e4b17023SJohn Marino error ("called from here"); 3858e4b17023SJohn Marino } 3859e4b17023SJohn Marino else if (warn_inline 3860e4b17023SJohn Marino && DECL_DECLARED_INLINE_P (fn) 3861e4b17023SJohn Marino && !DECL_NO_INLINE_WARNING_P (fn) 3862e4b17023SJohn Marino && !DECL_IN_SYSTEM_HEADER (fn) 3863e4b17023SJohn Marino && reason != CIF_UNSPECIFIED 3864e4b17023SJohn Marino && !lookup_attribute ("noinline", DECL_ATTRIBUTES (fn)) 3865e4b17023SJohn Marino /* Do not warn about not inlined recursive calls. */ 3866e4b17023SJohn Marino && !cgraph_edge_recursive_p (cg_edge) 3867e4b17023SJohn Marino /* Avoid warnings during early inline pass. */ 3868e4b17023SJohn Marino && cgraph_global_info_ready) 3869e4b17023SJohn Marino { 3870e4b17023SJohn Marino warning (OPT_Winline, "inlining failed in call to %q+F: %s", 3871e4b17023SJohn Marino fn, _(cgraph_inline_failed_string (reason))); 3872e4b17023SJohn Marino warning (OPT_Winline, "called from here"); 3873e4b17023SJohn Marino } 3874e4b17023SJohn Marino goto egress; 3875e4b17023SJohn Marino } 3876e4b17023SJohn Marino fn = cg_edge->callee->decl; 3877e4b17023SJohn Marino 3878e4b17023SJohn Marino #ifdef ENABLE_CHECKING 3879e4b17023SJohn Marino if (cg_edge->callee->decl != id->dst_node->decl) 3880e4b17023SJohn Marino verify_cgraph_node (cg_edge->callee); 3881e4b17023SJohn Marino #endif 3882e4b17023SJohn Marino 3883e4b17023SJohn Marino /* We will be inlining this callee. */ 3884e4b17023SJohn Marino id->eh_lp_nr = lookup_stmt_eh_lp (stmt); 3885e4b17023SJohn Marino 3886e4b17023SJohn Marino /* Update the callers EH personality. */ 3887e4b17023SJohn Marino if (DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl)) 3888e4b17023SJohn Marino DECL_FUNCTION_PERSONALITY (cg_edge->caller->decl) 3889e4b17023SJohn Marino = DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl); 3890e4b17023SJohn Marino 3891e4b17023SJohn Marino /* Split the block holding the GIMPLE_CALL. */ 3892e4b17023SJohn Marino e = split_block (bb, stmt); 3893e4b17023SJohn Marino bb = e->src; 3894e4b17023SJohn Marino return_block = e->dest; 3895e4b17023SJohn Marino remove_edge (e); 3896e4b17023SJohn Marino 3897e4b17023SJohn Marino /* split_block splits after the statement; work around this by 3898e4b17023SJohn Marino moving the call into the second block manually. Not pretty, 3899e4b17023SJohn Marino but seems easier than doing the CFG manipulation by hand 3900e4b17023SJohn Marino when the GIMPLE_CALL is in the last statement of BB. */ 3901e4b17023SJohn Marino stmt_gsi = gsi_last_bb (bb); 3902e4b17023SJohn Marino gsi_remove (&stmt_gsi, false); 3903e4b17023SJohn Marino 3904e4b17023SJohn Marino /* If the GIMPLE_CALL was in the last statement of BB, it may have 3905e4b17023SJohn Marino been the source of abnormal edges. In this case, schedule 3906e4b17023SJohn Marino the removal of dead abnormal edges. */ 3907e4b17023SJohn Marino gsi = gsi_start_bb (return_block); 3908e4b17023SJohn Marino if (gsi_end_p (gsi)) 3909e4b17023SJohn Marino { 3910e4b17023SJohn Marino gsi_insert_after (&gsi, stmt, GSI_NEW_STMT); 3911e4b17023SJohn Marino purge_dead_abnormal_edges = true; 3912e4b17023SJohn Marino } 3913e4b17023SJohn Marino else 3914e4b17023SJohn Marino { 3915e4b17023SJohn Marino gsi_insert_before (&gsi, stmt, GSI_NEW_STMT); 3916e4b17023SJohn Marino purge_dead_abnormal_edges = false; 3917e4b17023SJohn Marino } 3918e4b17023SJohn Marino 3919e4b17023SJohn Marino stmt_gsi = gsi_start_bb (return_block); 3920e4b17023SJohn Marino 3921e4b17023SJohn Marino /* Build a block containing code to initialize the arguments, the 3922e4b17023SJohn Marino actual inline expansion of the body, and a label for the return 3923e4b17023SJohn Marino statements within the function to jump to. The type of the 3924e4b17023SJohn Marino statement expression is the return type of the function call. */ 3925e4b17023SJohn Marino id->block = make_node (BLOCK); 3926e4b17023SJohn Marino BLOCK_ABSTRACT_ORIGIN (id->block) = fn; 3927e4b17023SJohn Marino BLOCK_SOURCE_LOCATION (id->block) = input_location; 3928e4b17023SJohn Marino prepend_lexical_block (gimple_block (stmt), id->block); 3929e4b17023SJohn Marino 3930e4b17023SJohn Marino /* Local declarations will be replaced by their equivalents in this 3931e4b17023SJohn Marino map. */ 3932e4b17023SJohn Marino st = id->decl_map; 3933e4b17023SJohn Marino id->decl_map = pointer_map_create (); 3934e4b17023SJohn Marino dst = id->debug_map; 3935e4b17023SJohn Marino id->debug_map = NULL; 3936e4b17023SJohn Marino 3937e4b17023SJohn Marino /* Record the function we are about to inline. */ 3938e4b17023SJohn Marino id->src_fn = fn; 3939e4b17023SJohn Marino id->src_node = cg_edge->callee; 3940e4b17023SJohn Marino id->src_cfun = DECL_STRUCT_FUNCTION (fn); 3941e4b17023SJohn Marino id->gimple_call = stmt; 3942e4b17023SJohn Marino 3943e4b17023SJohn Marino gcc_assert (!id->src_cfun->after_inlining); 3944e4b17023SJohn Marino 3945e4b17023SJohn Marino id->entry_bb = bb; 3946e4b17023SJohn Marino if (lookup_attribute ("cold", DECL_ATTRIBUTES (fn))) 3947e4b17023SJohn Marino { 3948e4b17023SJohn Marino gimple_stmt_iterator si = gsi_last_bb (bb); 3949e4b17023SJohn Marino gsi_insert_after (&si, gimple_build_predict (PRED_COLD_FUNCTION, 3950e4b17023SJohn Marino NOT_TAKEN), 3951e4b17023SJohn Marino GSI_NEW_STMT); 3952e4b17023SJohn Marino } 3953e4b17023SJohn Marino initialize_inlined_parameters (id, stmt, fn, bb); 3954e4b17023SJohn Marino 3955e4b17023SJohn Marino if (DECL_INITIAL (fn)) 3956e4b17023SJohn Marino prepend_lexical_block (id->block, remap_blocks (DECL_INITIAL (fn), id)); 3957e4b17023SJohn Marino 3958e4b17023SJohn Marino /* Return statements in the function body will be replaced by jumps 3959e4b17023SJohn Marino to the RET_LABEL. */ 3960e4b17023SJohn Marino gcc_assert (DECL_INITIAL (fn)); 3961e4b17023SJohn Marino gcc_assert (TREE_CODE (DECL_INITIAL (fn)) == BLOCK); 3962e4b17023SJohn Marino 3963e4b17023SJohn Marino /* Find the LHS to which the result of this call is assigned. */ 3964e4b17023SJohn Marino return_slot = NULL; 3965e4b17023SJohn Marino if (gimple_call_lhs (stmt)) 3966e4b17023SJohn Marino { 3967e4b17023SJohn Marino modify_dest = gimple_call_lhs (stmt); 3968e4b17023SJohn Marino 3969e4b17023SJohn Marino /* The function which we are inlining might not return a value, 3970e4b17023SJohn Marino in which case we should issue a warning that the function 3971e4b17023SJohn Marino does not return a value. In that case the optimizers will 3972e4b17023SJohn Marino see that the variable to which the value is assigned was not 3973e4b17023SJohn Marino initialized. We do not want to issue a warning about that 3974e4b17023SJohn Marino uninitialized variable. */ 3975e4b17023SJohn Marino if (DECL_P (modify_dest)) 3976e4b17023SJohn Marino TREE_NO_WARNING (modify_dest) = 1; 3977e4b17023SJohn Marino 3978e4b17023SJohn Marino if (gimple_call_return_slot_opt_p (stmt)) 3979e4b17023SJohn Marino { 3980e4b17023SJohn Marino return_slot = modify_dest; 3981e4b17023SJohn Marino modify_dest = NULL; 3982e4b17023SJohn Marino } 3983e4b17023SJohn Marino } 3984e4b17023SJohn Marino else 3985e4b17023SJohn Marino modify_dest = NULL; 3986e4b17023SJohn Marino 3987e4b17023SJohn Marino /* If we are inlining a call to the C++ operator new, we don't want 3988e4b17023SJohn Marino to use type based alias analysis on the return value. Otherwise 3989e4b17023SJohn Marino we may get confused if the compiler sees that the inlined new 3990e4b17023SJohn Marino function returns a pointer which was just deleted. See bug 3991e4b17023SJohn Marino 33407. */ 3992e4b17023SJohn Marino if (DECL_IS_OPERATOR_NEW (fn)) 3993e4b17023SJohn Marino { 3994e4b17023SJohn Marino return_slot = NULL; 3995e4b17023SJohn Marino modify_dest = NULL; 3996e4b17023SJohn Marino } 3997e4b17023SJohn Marino 3998e4b17023SJohn Marino /* Declare the return variable for the function. */ 3999e4b17023SJohn Marino use_retvar = declare_return_variable (id, return_slot, modify_dest, bb); 4000e4b17023SJohn Marino 4001e4b17023SJohn Marino /* Add local vars in this inlined callee to caller. */ 4002e4b17023SJohn Marino add_local_variables (id->src_cfun, cfun, id, true); 4003e4b17023SJohn Marino 4004e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 4005e4b17023SJohn Marino { 4006e4b17023SJohn Marino fprintf (dump_file, "Inlining "); 4007e4b17023SJohn Marino print_generic_expr (dump_file, id->src_fn, 0); 4008e4b17023SJohn Marino fprintf (dump_file, " to "); 4009e4b17023SJohn Marino print_generic_expr (dump_file, id->dst_fn, 0); 4010e4b17023SJohn Marino fprintf (dump_file, " with frequency %i\n", cg_edge->frequency); 4011e4b17023SJohn Marino } 4012e4b17023SJohn Marino 4013e4b17023SJohn Marino /* This is it. Duplicate the callee body. Assume callee is 4014e4b17023SJohn Marino pre-gimplified. Note that we must not alter the caller 4015e4b17023SJohn Marino function in any way before this point, as this CALL_EXPR may be 4016e4b17023SJohn Marino a self-referential call; if we're calling ourselves, we need to 4017e4b17023SJohn Marino duplicate our body before altering anything. */ 4018e4b17023SJohn Marino copy_body (id, bb->count, 4019e4b17023SJohn Marino cg_edge->frequency * REG_BR_PROB_BASE / CGRAPH_FREQ_BASE, 4020e4b17023SJohn Marino bb, return_block, NULL, NULL); 4021e4b17023SJohn Marino 4022e4b17023SJohn Marino /* Reset the escaped solution. */ 4023e4b17023SJohn Marino if (cfun->gimple_df) 4024e4b17023SJohn Marino pt_solution_reset (&cfun->gimple_df->escaped); 4025e4b17023SJohn Marino 4026e4b17023SJohn Marino /* Clean up. */ 4027e4b17023SJohn Marino if (id->debug_map) 4028e4b17023SJohn Marino { 4029e4b17023SJohn Marino pointer_map_destroy (id->debug_map); 4030e4b17023SJohn Marino id->debug_map = dst; 4031e4b17023SJohn Marino } 4032e4b17023SJohn Marino pointer_map_destroy (id->decl_map); 4033e4b17023SJohn Marino id->decl_map = st; 4034e4b17023SJohn Marino 4035e4b17023SJohn Marino /* Unlink the calls virtual operands before replacing it. */ 4036e4b17023SJohn Marino unlink_stmt_vdef (stmt); 4037e4b17023SJohn Marino 4038e4b17023SJohn Marino /* If the inlined function returns a result that we care about, 4039e4b17023SJohn Marino substitute the GIMPLE_CALL with an assignment of the return 4040e4b17023SJohn Marino variable to the LHS of the call. That is, if STMT was 4041e4b17023SJohn Marino 'a = foo (...)', substitute the call with 'a = USE_RETVAR'. */ 4042e4b17023SJohn Marino if (use_retvar && gimple_call_lhs (stmt)) 4043e4b17023SJohn Marino { 4044e4b17023SJohn Marino gimple old_stmt = stmt; 4045e4b17023SJohn Marino stmt = gimple_build_assign (gimple_call_lhs (stmt), use_retvar); 4046e4b17023SJohn Marino gsi_replace (&stmt_gsi, stmt, false); 4047e4b17023SJohn Marino if (gimple_in_ssa_p (cfun)) 4048e4b17023SJohn Marino mark_symbols_for_renaming (stmt); 4049e4b17023SJohn Marino maybe_clean_or_replace_eh_stmt (old_stmt, stmt); 4050e4b17023SJohn Marino } 4051e4b17023SJohn Marino else 4052e4b17023SJohn Marino { 4053e4b17023SJohn Marino /* Handle the case of inlining a function with no return 4054e4b17023SJohn Marino statement, which causes the return value to become undefined. */ 4055e4b17023SJohn Marino if (gimple_call_lhs (stmt) 4056e4b17023SJohn Marino && TREE_CODE (gimple_call_lhs (stmt)) == SSA_NAME) 4057e4b17023SJohn Marino { 4058e4b17023SJohn Marino tree name = gimple_call_lhs (stmt); 4059e4b17023SJohn Marino tree var = SSA_NAME_VAR (name); 4060e4b17023SJohn Marino tree def = gimple_default_def (cfun, var); 4061e4b17023SJohn Marino 4062e4b17023SJohn Marino if (def) 4063e4b17023SJohn Marino { 4064e4b17023SJohn Marino /* If the variable is used undefined, make this name 4065e4b17023SJohn Marino undefined via a move. */ 4066e4b17023SJohn Marino stmt = gimple_build_assign (gimple_call_lhs (stmt), def); 4067e4b17023SJohn Marino gsi_replace (&stmt_gsi, stmt, true); 4068e4b17023SJohn Marino } 4069e4b17023SJohn Marino else 4070e4b17023SJohn Marino { 4071e4b17023SJohn Marino /* Otherwise make this variable undefined. */ 4072e4b17023SJohn Marino gsi_remove (&stmt_gsi, true); 4073e4b17023SJohn Marino set_default_def (var, name); 4074e4b17023SJohn Marino SSA_NAME_DEF_STMT (name) = gimple_build_nop (); 4075e4b17023SJohn Marino } 4076e4b17023SJohn Marino } 4077e4b17023SJohn Marino else 4078e4b17023SJohn Marino gsi_remove (&stmt_gsi, true); 4079e4b17023SJohn Marino } 4080e4b17023SJohn Marino 4081e4b17023SJohn Marino if (purge_dead_abnormal_edges) 4082e4b17023SJohn Marino { 4083e4b17023SJohn Marino gimple_purge_dead_eh_edges (return_block); 4084e4b17023SJohn Marino gimple_purge_dead_abnormal_call_edges (return_block); 4085e4b17023SJohn Marino } 4086e4b17023SJohn Marino 4087e4b17023SJohn Marino /* If the value of the new expression is ignored, that's OK. We 4088e4b17023SJohn Marino don't warn about this for CALL_EXPRs, so we shouldn't warn about 4089e4b17023SJohn Marino the equivalent inlined version either. */ 4090e4b17023SJohn Marino if (is_gimple_assign (stmt)) 4091e4b17023SJohn Marino { 4092e4b17023SJohn Marino gcc_assert (gimple_assign_single_p (stmt) 4093e4b17023SJohn Marino || CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt))); 4094e4b17023SJohn Marino TREE_USED (gimple_assign_rhs1 (stmt)) = 1; 4095e4b17023SJohn Marino } 4096e4b17023SJohn Marino 4097e4b17023SJohn Marino /* Output the inlining info for this abstract function, since it has been 4098e4b17023SJohn Marino inlined. If we don't do this now, we can lose the information about the 4099e4b17023SJohn Marino variables in the function when the blocks get blown away as soon as we 4100e4b17023SJohn Marino remove the cgraph node. */ 4101e4b17023SJohn Marino (*debug_hooks->outlining_inline_function) (cg_edge->callee->decl); 4102e4b17023SJohn Marino 4103e4b17023SJohn Marino /* Update callgraph if needed. */ 4104e4b17023SJohn Marino cgraph_remove_node (cg_edge->callee); 4105e4b17023SJohn Marino 4106e4b17023SJohn Marino id->block = NULL_TREE; 4107e4b17023SJohn Marino successfully_inlined = TRUE; 4108e4b17023SJohn Marino 4109e4b17023SJohn Marino egress: 4110e4b17023SJohn Marino input_location = saved_location; 4111e4b17023SJohn Marino return successfully_inlined; 4112e4b17023SJohn Marino } 4113e4b17023SJohn Marino 4114e4b17023SJohn Marino /* Expand call statements reachable from STMT_P. 4115e4b17023SJohn Marino We can only have CALL_EXPRs as the "toplevel" tree code or nested 4116e4b17023SJohn Marino in a MODIFY_EXPR. */ 4117e4b17023SJohn Marino 4118e4b17023SJohn Marino static bool 4119e4b17023SJohn Marino gimple_expand_calls_inline (basic_block bb, copy_body_data *id) 4120e4b17023SJohn Marino { 4121e4b17023SJohn Marino gimple_stmt_iterator gsi; 4122e4b17023SJohn Marino 4123e4b17023SJohn Marino for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) 4124e4b17023SJohn Marino { 4125e4b17023SJohn Marino gimple stmt = gsi_stmt (gsi); 4126e4b17023SJohn Marino 4127e4b17023SJohn Marino if (is_gimple_call (stmt) 4128e4b17023SJohn Marino && expand_call_inline (bb, stmt, id)) 4129e4b17023SJohn Marino return true; 4130e4b17023SJohn Marino } 4131e4b17023SJohn Marino 4132e4b17023SJohn Marino return false; 4133e4b17023SJohn Marino } 4134e4b17023SJohn Marino 4135e4b17023SJohn Marino 4136e4b17023SJohn Marino /* Walk all basic blocks created after FIRST and try to fold every statement 4137e4b17023SJohn Marino in the STATEMENTS pointer set. */ 4138e4b17023SJohn Marino 4139e4b17023SJohn Marino static void 4140e4b17023SJohn Marino fold_marked_statements (int first, struct pointer_set_t *statements) 4141e4b17023SJohn Marino { 4142e4b17023SJohn Marino for (; first < n_basic_blocks; first++) 4143e4b17023SJohn Marino if (BASIC_BLOCK (first)) 4144e4b17023SJohn Marino { 4145e4b17023SJohn Marino gimple_stmt_iterator gsi; 4146e4b17023SJohn Marino 4147e4b17023SJohn Marino for (gsi = gsi_start_bb (BASIC_BLOCK (first)); 4148e4b17023SJohn Marino !gsi_end_p (gsi); 4149e4b17023SJohn Marino gsi_next (&gsi)) 4150e4b17023SJohn Marino if (pointer_set_contains (statements, gsi_stmt (gsi))) 4151e4b17023SJohn Marino { 4152e4b17023SJohn Marino gimple old_stmt = gsi_stmt (gsi); 4153e4b17023SJohn Marino tree old_decl = is_gimple_call (old_stmt) ? gimple_call_fndecl (old_stmt) : 0; 4154e4b17023SJohn Marino 4155e4b17023SJohn Marino if (old_decl && DECL_BUILT_IN (old_decl)) 4156e4b17023SJohn Marino { 4157e4b17023SJohn Marino /* Folding builtins can create multiple instructions, 4158e4b17023SJohn Marino we need to look at all of them. */ 4159e4b17023SJohn Marino gimple_stmt_iterator i2 = gsi; 4160e4b17023SJohn Marino gsi_prev (&i2); 4161e4b17023SJohn Marino if (fold_stmt (&gsi)) 4162e4b17023SJohn Marino { 4163e4b17023SJohn Marino gimple new_stmt; 4164e4b17023SJohn Marino /* If a builtin at the end of a bb folded into nothing, 4165e4b17023SJohn Marino the following loop won't work. */ 4166e4b17023SJohn Marino if (gsi_end_p (gsi)) 4167e4b17023SJohn Marino { 4168e4b17023SJohn Marino cgraph_update_edges_for_call_stmt (old_stmt, 4169e4b17023SJohn Marino old_decl, NULL); 4170e4b17023SJohn Marino break; 4171e4b17023SJohn Marino } 4172e4b17023SJohn Marino if (gsi_end_p (i2)) 4173e4b17023SJohn Marino i2 = gsi_start_bb (BASIC_BLOCK (first)); 4174e4b17023SJohn Marino else 4175e4b17023SJohn Marino gsi_next (&i2); 4176e4b17023SJohn Marino while (1) 4177e4b17023SJohn Marino { 4178e4b17023SJohn Marino new_stmt = gsi_stmt (i2); 4179e4b17023SJohn Marino update_stmt (new_stmt); 4180e4b17023SJohn Marino cgraph_update_edges_for_call_stmt (old_stmt, old_decl, 4181e4b17023SJohn Marino new_stmt); 4182e4b17023SJohn Marino 4183e4b17023SJohn Marino if (new_stmt == gsi_stmt (gsi)) 4184e4b17023SJohn Marino { 4185e4b17023SJohn Marino /* It is okay to check only for the very last 4186e4b17023SJohn Marino of these statements. If it is a throwing 4187e4b17023SJohn Marino statement nothing will change. If it isn't 4188e4b17023SJohn Marino this can remove EH edges. If that weren't 4189e4b17023SJohn Marino correct then because some intermediate stmts 4190e4b17023SJohn Marino throw, but not the last one. That would mean 4191e4b17023SJohn Marino we'd have to split the block, which we can't 4192e4b17023SJohn Marino here and we'd loose anyway. And as builtins 4193e4b17023SJohn Marino probably never throw, this all 4194e4b17023SJohn Marino is mood anyway. */ 4195e4b17023SJohn Marino if (maybe_clean_or_replace_eh_stmt (old_stmt, 4196e4b17023SJohn Marino new_stmt)) 4197e4b17023SJohn Marino gimple_purge_dead_eh_edges (BASIC_BLOCK (first)); 4198e4b17023SJohn Marino break; 4199e4b17023SJohn Marino } 4200e4b17023SJohn Marino gsi_next (&i2); 4201e4b17023SJohn Marino } 4202e4b17023SJohn Marino } 4203e4b17023SJohn Marino } 4204e4b17023SJohn Marino else if (fold_stmt (&gsi)) 4205e4b17023SJohn Marino { 4206e4b17023SJohn Marino /* Re-read the statement from GSI as fold_stmt() may 4207e4b17023SJohn Marino have changed it. */ 4208e4b17023SJohn Marino gimple new_stmt = gsi_stmt (gsi); 4209e4b17023SJohn Marino update_stmt (new_stmt); 4210e4b17023SJohn Marino 4211e4b17023SJohn Marino if (is_gimple_call (old_stmt) 4212e4b17023SJohn Marino || is_gimple_call (new_stmt)) 4213e4b17023SJohn Marino cgraph_update_edges_for_call_stmt (old_stmt, old_decl, 4214e4b17023SJohn Marino new_stmt); 4215e4b17023SJohn Marino 4216e4b17023SJohn Marino if (maybe_clean_or_replace_eh_stmt (old_stmt, new_stmt)) 4217e4b17023SJohn Marino gimple_purge_dead_eh_edges (BASIC_BLOCK (first)); 4218e4b17023SJohn Marino } 4219e4b17023SJohn Marino } 4220e4b17023SJohn Marino } 4221e4b17023SJohn Marino } 4222e4b17023SJohn Marino 4223e4b17023SJohn Marino /* Return true if BB has at least one abnormal outgoing edge. */ 4224e4b17023SJohn Marino 4225e4b17023SJohn Marino static inline bool 4226e4b17023SJohn Marino has_abnormal_outgoing_edge_p (basic_block bb) 4227e4b17023SJohn Marino { 4228e4b17023SJohn Marino edge e; 4229e4b17023SJohn Marino edge_iterator ei; 4230e4b17023SJohn Marino 4231e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs) 4232e4b17023SJohn Marino if (e->flags & EDGE_ABNORMAL) 4233e4b17023SJohn Marino return true; 4234e4b17023SJohn Marino 4235e4b17023SJohn Marino return false; 4236e4b17023SJohn Marino } 4237e4b17023SJohn Marino 4238e4b17023SJohn Marino /* Expand calls to inline functions in the body of FN. */ 4239e4b17023SJohn Marino 4240e4b17023SJohn Marino unsigned int 4241e4b17023SJohn Marino optimize_inline_calls (tree fn) 4242e4b17023SJohn Marino { 4243e4b17023SJohn Marino copy_body_data id; 4244e4b17023SJohn Marino basic_block bb; 4245e4b17023SJohn Marino int last = n_basic_blocks; 4246e4b17023SJohn Marino struct gimplify_ctx gctx; 4247e4b17023SJohn Marino bool inlined_p = false; 4248e4b17023SJohn Marino 4249e4b17023SJohn Marino /* Clear out ID. */ 4250e4b17023SJohn Marino memset (&id, 0, sizeof (id)); 4251e4b17023SJohn Marino 4252e4b17023SJohn Marino id.src_node = id.dst_node = cgraph_get_node (fn); 4253e4b17023SJohn Marino gcc_assert (id.dst_node->analyzed); 4254e4b17023SJohn Marino id.dst_fn = fn; 4255e4b17023SJohn Marino /* Or any functions that aren't finished yet. */ 4256e4b17023SJohn Marino if (current_function_decl) 4257e4b17023SJohn Marino id.dst_fn = current_function_decl; 4258e4b17023SJohn Marino 4259e4b17023SJohn Marino id.copy_decl = copy_decl_maybe_to_var; 4260e4b17023SJohn Marino id.transform_call_graph_edges = CB_CGE_DUPLICATE; 4261e4b17023SJohn Marino id.transform_new_cfg = false; 4262e4b17023SJohn Marino id.transform_return_to_modify = true; 4263e4b17023SJohn Marino id.transform_lang_insert_block = NULL; 4264e4b17023SJohn Marino id.statements_to_fold = pointer_set_create (); 4265e4b17023SJohn Marino 4266e4b17023SJohn Marino push_gimplify_context (&gctx); 4267e4b17023SJohn Marino 4268e4b17023SJohn Marino /* We make no attempts to keep dominance info up-to-date. */ 4269e4b17023SJohn Marino free_dominance_info (CDI_DOMINATORS); 4270e4b17023SJohn Marino free_dominance_info (CDI_POST_DOMINATORS); 4271e4b17023SJohn Marino 4272e4b17023SJohn Marino /* Register specific gimple functions. */ 4273e4b17023SJohn Marino gimple_register_cfg_hooks (); 4274e4b17023SJohn Marino 4275e4b17023SJohn Marino /* Reach the trees by walking over the CFG, and note the 4276e4b17023SJohn Marino enclosing basic-blocks in the call edges. */ 4277e4b17023SJohn Marino /* We walk the blocks going forward, because inlined function bodies 4278e4b17023SJohn Marino will split id->current_basic_block, and the new blocks will 4279e4b17023SJohn Marino follow it; we'll trudge through them, processing their CALL_EXPRs 4280e4b17023SJohn Marino along the way. */ 4281e4b17023SJohn Marino FOR_EACH_BB (bb) 4282e4b17023SJohn Marino inlined_p |= gimple_expand_calls_inline (bb, &id); 4283e4b17023SJohn Marino 4284e4b17023SJohn Marino pop_gimplify_context (NULL); 4285e4b17023SJohn Marino 4286e4b17023SJohn Marino #ifdef ENABLE_CHECKING 4287e4b17023SJohn Marino { 4288e4b17023SJohn Marino struct cgraph_edge *e; 4289e4b17023SJohn Marino 4290e4b17023SJohn Marino verify_cgraph_node (id.dst_node); 4291e4b17023SJohn Marino 4292e4b17023SJohn Marino /* Double check that we inlined everything we are supposed to inline. */ 4293e4b17023SJohn Marino for (e = id.dst_node->callees; e; e = e->next_callee) 4294e4b17023SJohn Marino gcc_assert (e->inline_failed); 4295e4b17023SJohn Marino } 4296e4b17023SJohn Marino #endif 4297e4b17023SJohn Marino 4298e4b17023SJohn Marino /* Fold queued statements. */ 4299e4b17023SJohn Marino fold_marked_statements (last, id.statements_to_fold); 4300e4b17023SJohn Marino pointer_set_destroy (id.statements_to_fold); 4301e4b17023SJohn Marino 4302e4b17023SJohn Marino gcc_assert (!id.debug_stmts); 4303e4b17023SJohn Marino 4304e4b17023SJohn Marino /* If we didn't inline into the function there is nothing to do. */ 4305e4b17023SJohn Marino if (!inlined_p) 4306e4b17023SJohn Marino return 0; 4307e4b17023SJohn Marino 4308e4b17023SJohn Marino /* Renumber the lexical scoping (non-code) blocks consecutively. */ 4309e4b17023SJohn Marino number_blocks (fn); 4310e4b17023SJohn Marino 4311e4b17023SJohn Marino delete_unreachable_blocks_update_callgraph (&id); 4312e4b17023SJohn Marino #ifdef ENABLE_CHECKING 4313e4b17023SJohn Marino verify_cgraph_node (id.dst_node); 4314e4b17023SJohn Marino #endif 4315e4b17023SJohn Marino 4316e4b17023SJohn Marino /* It would be nice to check SSA/CFG/statement consistency here, but it is 4317e4b17023SJohn Marino not possible yet - the IPA passes might make various functions to not 4318e4b17023SJohn Marino throw and they don't care to proactively update local EH info. This is 4319e4b17023SJohn Marino done later in fixup_cfg pass that also execute the verification. */ 4320e4b17023SJohn Marino return (TODO_update_ssa 4321e4b17023SJohn Marino | TODO_cleanup_cfg 4322e4b17023SJohn Marino | (gimple_in_ssa_p (cfun) ? TODO_remove_unused_locals : 0) 4323e4b17023SJohn Marino | (gimple_in_ssa_p (cfun) ? TODO_update_address_taken : 0) 4324e4b17023SJohn Marino | (profile_status != PROFILE_ABSENT ? TODO_rebuild_frequencies : 0)); 4325e4b17023SJohn Marino } 4326e4b17023SJohn Marino 4327e4b17023SJohn Marino /* Passed to walk_tree. Copies the node pointed to, if appropriate. */ 4328e4b17023SJohn Marino 4329e4b17023SJohn Marino tree 4330e4b17023SJohn Marino copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) 4331e4b17023SJohn Marino { 4332e4b17023SJohn Marino enum tree_code code = TREE_CODE (*tp); 4333e4b17023SJohn Marino enum tree_code_class cl = TREE_CODE_CLASS (code); 4334e4b17023SJohn Marino 4335e4b17023SJohn Marino /* We make copies of most nodes. */ 4336e4b17023SJohn Marino if (IS_EXPR_CODE_CLASS (cl) 4337e4b17023SJohn Marino || code == TREE_LIST 4338e4b17023SJohn Marino || code == TREE_VEC 4339e4b17023SJohn Marino || code == TYPE_DECL 4340e4b17023SJohn Marino || code == OMP_CLAUSE) 4341e4b17023SJohn Marino { 4342e4b17023SJohn Marino /* Because the chain gets clobbered when we make a copy, we save it 4343e4b17023SJohn Marino here. */ 4344e4b17023SJohn Marino tree chain = NULL_TREE, new_tree; 4345e4b17023SJohn Marino 4346e4b17023SJohn Marino if (CODE_CONTAINS_STRUCT (code, TS_COMMON)) 4347e4b17023SJohn Marino chain = TREE_CHAIN (*tp); 4348e4b17023SJohn Marino 4349e4b17023SJohn Marino /* Copy the node. */ 4350e4b17023SJohn Marino new_tree = copy_node (*tp); 4351e4b17023SJohn Marino 4352e4b17023SJohn Marino /* Propagate mudflap marked-ness. */ 4353e4b17023SJohn Marino if (flag_mudflap && mf_marked_p (*tp)) 4354e4b17023SJohn Marino mf_mark (new_tree); 4355e4b17023SJohn Marino 4356e4b17023SJohn Marino *tp = new_tree; 4357e4b17023SJohn Marino 4358e4b17023SJohn Marino /* Now, restore the chain, if appropriate. That will cause 4359e4b17023SJohn Marino walk_tree to walk into the chain as well. */ 4360e4b17023SJohn Marino if (code == PARM_DECL 4361e4b17023SJohn Marino || code == TREE_LIST 4362e4b17023SJohn Marino || code == OMP_CLAUSE) 4363e4b17023SJohn Marino TREE_CHAIN (*tp) = chain; 4364e4b17023SJohn Marino 4365e4b17023SJohn Marino /* For now, we don't update BLOCKs when we make copies. So, we 4366e4b17023SJohn Marino have to nullify all BIND_EXPRs. */ 4367e4b17023SJohn Marino if (TREE_CODE (*tp) == BIND_EXPR) 4368e4b17023SJohn Marino BIND_EXPR_BLOCK (*tp) = NULL_TREE; 4369e4b17023SJohn Marino } 4370e4b17023SJohn Marino else if (code == CONSTRUCTOR) 4371e4b17023SJohn Marino { 4372e4b17023SJohn Marino /* CONSTRUCTOR nodes need special handling because 4373e4b17023SJohn Marino we need to duplicate the vector of elements. */ 4374e4b17023SJohn Marino tree new_tree; 4375e4b17023SJohn Marino 4376e4b17023SJohn Marino new_tree = copy_node (*tp); 4377e4b17023SJohn Marino 4378e4b17023SJohn Marino /* Propagate mudflap marked-ness. */ 4379e4b17023SJohn Marino if (flag_mudflap && mf_marked_p (*tp)) 4380e4b17023SJohn Marino mf_mark (new_tree); 4381e4b17023SJohn Marino 4382e4b17023SJohn Marino CONSTRUCTOR_ELTS (new_tree) = VEC_copy (constructor_elt, gc, 4383e4b17023SJohn Marino CONSTRUCTOR_ELTS (*tp)); 4384e4b17023SJohn Marino *tp = new_tree; 4385e4b17023SJohn Marino } 4386e4b17023SJohn Marino else if (code == STATEMENT_LIST) 4387e4b17023SJohn Marino /* We used to just abort on STATEMENT_LIST, but we can run into them 4388e4b17023SJohn Marino with statement-expressions (c++/40975). */ 4389e4b17023SJohn Marino copy_statement_list (tp); 4390e4b17023SJohn Marino else if (TREE_CODE_CLASS (code) == tcc_type) 4391e4b17023SJohn Marino *walk_subtrees = 0; 4392e4b17023SJohn Marino else if (TREE_CODE_CLASS (code) == tcc_declaration) 4393e4b17023SJohn Marino *walk_subtrees = 0; 4394e4b17023SJohn Marino else if (TREE_CODE_CLASS (code) == tcc_constant) 4395e4b17023SJohn Marino *walk_subtrees = 0; 4396e4b17023SJohn Marino return NULL_TREE; 4397e4b17023SJohn Marino } 4398e4b17023SJohn Marino 4399e4b17023SJohn Marino /* The SAVE_EXPR pointed to by TP is being copied. If ST contains 4400e4b17023SJohn Marino information indicating to what new SAVE_EXPR this one should be mapped, 4401e4b17023SJohn Marino use that one. Otherwise, create a new node and enter it in ST. FN is 4402e4b17023SJohn Marino the function into which the copy will be placed. */ 4403e4b17023SJohn Marino 4404e4b17023SJohn Marino static void 4405e4b17023SJohn Marino remap_save_expr (tree *tp, void *st_, int *walk_subtrees) 4406e4b17023SJohn Marino { 4407e4b17023SJohn Marino struct pointer_map_t *st = (struct pointer_map_t *) st_; 4408e4b17023SJohn Marino tree *n; 4409e4b17023SJohn Marino tree t; 4410e4b17023SJohn Marino 4411e4b17023SJohn Marino /* See if we already encountered this SAVE_EXPR. */ 4412e4b17023SJohn Marino n = (tree *) pointer_map_contains (st, *tp); 4413e4b17023SJohn Marino 4414e4b17023SJohn Marino /* If we didn't already remap this SAVE_EXPR, do so now. */ 4415e4b17023SJohn Marino if (!n) 4416e4b17023SJohn Marino { 4417e4b17023SJohn Marino t = copy_node (*tp); 4418e4b17023SJohn Marino 4419e4b17023SJohn Marino /* Remember this SAVE_EXPR. */ 4420e4b17023SJohn Marino *pointer_map_insert (st, *tp) = t; 4421e4b17023SJohn Marino /* Make sure we don't remap an already-remapped SAVE_EXPR. */ 4422e4b17023SJohn Marino *pointer_map_insert (st, t) = t; 4423e4b17023SJohn Marino } 4424e4b17023SJohn Marino else 4425e4b17023SJohn Marino { 4426e4b17023SJohn Marino /* We've already walked into this SAVE_EXPR; don't do it again. */ 4427e4b17023SJohn Marino *walk_subtrees = 0; 4428e4b17023SJohn Marino t = *n; 4429e4b17023SJohn Marino } 4430e4b17023SJohn Marino 4431e4b17023SJohn Marino /* Replace this SAVE_EXPR with the copy. */ 4432e4b17023SJohn Marino *tp = t; 4433e4b17023SJohn Marino } 4434e4b17023SJohn Marino 4435e4b17023SJohn Marino /* Called via walk_tree. If *TP points to a DECL_STMT for a local label, 4436e4b17023SJohn Marino copies the declaration and enters it in the splay_tree in DATA (which is 4437e4b17023SJohn Marino really an `copy_body_data *'). */ 4438e4b17023SJohn Marino 4439e4b17023SJohn Marino static tree 4440e4b17023SJohn Marino mark_local_for_remap_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, 4441e4b17023SJohn Marino void *data) 4442e4b17023SJohn Marino { 4443e4b17023SJohn Marino copy_body_data *id = (copy_body_data *) data; 4444e4b17023SJohn Marino 4445e4b17023SJohn Marino /* Don't walk into types. */ 4446e4b17023SJohn Marino if (TYPE_P (*tp)) 4447e4b17023SJohn Marino *walk_subtrees = 0; 4448e4b17023SJohn Marino 4449e4b17023SJohn Marino else if (TREE_CODE (*tp) == LABEL_EXPR) 4450e4b17023SJohn Marino { 4451e4b17023SJohn Marino tree decl = TREE_OPERAND (*tp, 0); 4452e4b17023SJohn Marino 4453e4b17023SJohn Marino /* Copy the decl and remember the copy. */ 4454e4b17023SJohn Marino insert_decl_map (id, decl, id->copy_decl (decl, id)); 4455e4b17023SJohn Marino } 4456e4b17023SJohn Marino 4457e4b17023SJohn Marino return NULL_TREE; 4458e4b17023SJohn Marino } 4459e4b17023SJohn Marino 4460e4b17023SJohn Marino /* Perform any modifications to EXPR required when it is unsaved. Does 4461e4b17023SJohn Marino not recurse into EXPR's subtrees. */ 4462e4b17023SJohn Marino 4463e4b17023SJohn Marino static void 4464e4b17023SJohn Marino unsave_expr_1 (tree expr) 4465e4b17023SJohn Marino { 4466e4b17023SJohn Marino switch (TREE_CODE (expr)) 4467e4b17023SJohn Marino { 4468e4b17023SJohn Marino case TARGET_EXPR: 4469e4b17023SJohn Marino /* Don't mess with a TARGET_EXPR that hasn't been expanded. 4470e4b17023SJohn Marino It's OK for this to happen if it was part of a subtree that 4471e4b17023SJohn Marino isn't immediately expanded, such as operand 2 of another 4472e4b17023SJohn Marino TARGET_EXPR. */ 4473e4b17023SJohn Marino if (TREE_OPERAND (expr, 1)) 4474e4b17023SJohn Marino break; 4475e4b17023SJohn Marino 4476e4b17023SJohn Marino TREE_OPERAND (expr, 1) = TREE_OPERAND (expr, 3); 4477e4b17023SJohn Marino TREE_OPERAND (expr, 3) = NULL_TREE; 4478e4b17023SJohn Marino break; 4479e4b17023SJohn Marino 4480e4b17023SJohn Marino default: 4481e4b17023SJohn Marino break; 4482e4b17023SJohn Marino } 4483e4b17023SJohn Marino } 4484e4b17023SJohn Marino 4485e4b17023SJohn Marino /* Called via walk_tree when an expression is unsaved. Using the 4486e4b17023SJohn Marino splay_tree pointed to by ST (which is really a `splay_tree'), 4487e4b17023SJohn Marino remaps all local declarations to appropriate replacements. */ 4488e4b17023SJohn Marino 4489e4b17023SJohn Marino static tree 4490e4b17023SJohn Marino unsave_r (tree *tp, int *walk_subtrees, void *data) 4491e4b17023SJohn Marino { 4492e4b17023SJohn Marino copy_body_data *id = (copy_body_data *) data; 4493e4b17023SJohn Marino struct pointer_map_t *st = id->decl_map; 4494e4b17023SJohn Marino tree *n; 4495e4b17023SJohn Marino 4496e4b17023SJohn Marino /* Only a local declaration (variable or label). */ 4497e4b17023SJohn Marino if ((TREE_CODE (*tp) == VAR_DECL && !TREE_STATIC (*tp)) 4498e4b17023SJohn Marino || TREE_CODE (*tp) == LABEL_DECL) 4499e4b17023SJohn Marino { 4500e4b17023SJohn Marino /* Lookup the declaration. */ 4501e4b17023SJohn Marino n = (tree *) pointer_map_contains (st, *tp); 4502e4b17023SJohn Marino 4503e4b17023SJohn Marino /* If it's there, remap it. */ 4504e4b17023SJohn Marino if (n) 4505e4b17023SJohn Marino *tp = *n; 4506e4b17023SJohn Marino } 4507e4b17023SJohn Marino 4508e4b17023SJohn Marino else if (TREE_CODE (*tp) == STATEMENT_LIST) 4509e4b17023SJohn Marino gcc_unreachable (); 4510e4b17023SJohn Marino else if (TREE_CODE (*tp) == BIND_EXPR) 4511e4b17023SJohn Marino copy_bind_expr (tp, walk_subtrees, id); 4512e4b17023SJohn Marino else if (TREE_CODE (*tp) == SAVE_EXPR 4513e4b17023SJohn Marino || TREE_CODE (*tp) == TARGET_EXPR) 4514e4b17023SJohn Marino remap_save_expr (tp, st, walk_subtrees); 4515e4b17023SJohn Marino else 4516e4b17023SJohn Marino { 4517e4b17023SJohn Marino copy_tree_r (tp, walk_subtrees, NULL); 4518e4b17023SJohn Marino 4519e4b17023SJohn Marino /* Do whatever unsaving is required. */ 4520e4b17023SJohn Marino unsave_expr_1 (*tp); 4521e4b17023SJohn Marino } 4522e4b17023SJohn Marino 4523e4b17023SJohn Marino /* Keep iterating. */ 4524e4b17023SJohn Marino return NULL_TREE; 4525e4b17023SJohn Marino } 4526e4b17023SJohn Marino 4527e4b17023SJohn Marino /* Copies everything in EXPR and replaces variables, labels 4528e4b17023SJohn Marino and SAVE_EXPRs local to EXPR. */ 4529e4b17023SJohn Marino 4530e4b17023SJohn Marino tree 4531e4b17023SJohn Marino unsave_expr_now (tree expr) 4532e4b17023SJohn Marino { 4533e4b17023SJohn Marino copy_body_data id; 4534e4b17023SJohn Marino 4535e4b17023SJohn Marino /* There's nothing to do for NULL_TREE. */ 4536e4b17023SJohn Marino if (expr == 0) 4537e4b17023SJohn Marino return expr; 4538e4b17023SJohn Marino 4539e4b17023SJohn Marino /* Set up ID. */ 4540e4b17023SJohn Marino memset (&id, 0, sizeof (id)); 4541e4b17023SJohn Marino id.src_fn = current_function_decl; 4542e4b17023SJohn Marino id.dst_fn = current_function_decl; 4543e4b17023SJohn Marino id.decl_map = pointer_map_create (); 4544e4b17023SJohn Marino id.debug_map = NULL; 4545e4b17023SJohn Marino 4546e4b17023SJohn Marino id.copy_decl = copy_decl_no_change; 4547e4b17023SJohn Marino id.transform_call_graph_edges = CB_CGE_DUPLICATE; 4548e4b17023SJohn Marino id.transform_new_cfg = false; 4549e4b17023SJohn Marino id.transform_return_to_modify = false; 4550e4b17023SJohn Marino id.transform_lang_insert_block = NULL; 4551e4b17023SJohn Marino 4552e4b17023SJohn Marino /* Walk the tree once to find local labels. */ 4553e4b17023SJohn Marino walk_tree_without_duplicates (&expr, mark_local_for_remap_r, &id); 4554e4b17023SJohn Marino 4555e4b17023SJohn Marino /* Walk the tree again, copying, remapping, and unsaving. */ 4556e4b17023SJohn Marino walk_tree (&expr, unsave_r, &id, NULL); 4557e4b17023SJohn Marino 4558e4b17023SJohn Marino /* Clean up. */ 4559e4b17023SJohn Marino pointer_map_destroy (id.decl_map); 4560e4b17023SJohn Marino if (id.debug_map) 4561e4b17023SJohn Marino pointer_map_destroy (id.debug_map); 4562e4b17023SJohn Marino 4563e4b17023SJohn Marino return expr; 4564e4b17023SJohn Marino } 4565e4b17023SJohn Marino 4566e4b17023SJohn Marino /* Called via walk_gimple_seq. If *GSIP points to a GIMPLE_LABEL for a local 4567e4b17023SJohn Marino label, copies the declaration and enters it in the splay_tree in DATA (which 4568e4b17023SJohn Marino is really a 'copy_body_data *'. */ 4569e4b17023SJohn Marino 4570e4b17023SJohn Marino static tree 4571e4b17023SJohn Marino mark_local_labels_stmt (gimple_stmt_iterator *gsip, 4572e4b17023SJohn Marino bool *handled_ops_p ATTRIBUTE_UNUSED, 4573e4b17023SJohn Marino struct walk_stmt_info *wi) 4574e4b17023SJohn Marino { 4575e4b17023SJohn Marino copy_body_data *id = (copy_body_data *) wi->info; 4576e4b17023SJohn Marino gimple stmt = gsi_stmt (*gsip); 4577e4b17023SJohn Marino 4578e4b17023SJohn Marino if (gimple_code (stmt) == GIMPLE_LABEL) 4579e4b17023SJohn Marino { 4580e4b17023SJohn Marino tree decl = gimple_label_label (stmt); 4581e4b17023SJohn Marino 4582e4b17023SJohn Marino /* Copy the decl and remember the copy. */ 4583e4b17023SJohn Marino insert_decl_map (id, decl, id->copy_decl (decl, id)); 4584e4b17023SJohn Marino } 4585e4b17023SJohn Marino 4586e4b17023SJohn Marino return NULL_TREE; 4587e4b17023SJohn Marino } 4588e4b17023SJohn Marino 4589e4b17023SJohn Marino 4590e4b17023SJohn Marino /* Called via walk_gimple_seq by copy_gimple_seq_and_replace_local. 4591e4b17023SJohn Marino Using the splay_tree pointed to by ST (which is really a `splay_tree'), 4592e4b17023SJohn Marino remaps all local declarations to appropriate replacements in gimple 4593e4b17023SJohn Marino operands. */ 4594e4b17023SJohn Marino 4595e4b17023SJohn Marino static tree 4596e4b17023SJohn Marino replace_locals_op (tree *tp, int *walk_subtrees, void *data) 4597e4b17023SJohn Marino { 4598e4b17023SJohn Marino struct walk_stmt_info *wi = (struct walk_stmt_info*) data; 4599e4b17023SJohn Marino copy_body_data *id = (copy_body_data *) wi->info; 4600e4b17023SJohn Marino struct pointer_map_t *st = id->decl_map; 4601e4b17023SJohn Marino tree *n; 4602e4b17023SJohn Marino tree expr = *tp; 4603e4b17023SJohn Marino 4604e4b17023SJohn Marino /* Only a local declaration (variable or label). */ 4605e4b17023SJohn Marino if ((TREE_CODE (expr) == VAR_DECL 4606e4b17023SJohn Marino && !TREE_STATIC (expr)) 4607e4b17023SJohn Marino || TREE_CODE (expr) == LABEL_DECL) 4608e4b17023SJohn Marino { 4609e4b17023SJohn Marino /* Lookup the declaration. */ 4610e4b17023SJohn Marino n = (tree *) pointer_map_contains (st, expr); 4611e4b17023SJohn Marino 4612e4b17023SJohn Marino /* If it's there, remap it. */ 4613e4b17023SJohn Marino if (n) 4614e4b17023SJohn Marino *tp = *n; 4615e4b17023SJohn Marino *walk_subtrees = 0; 4616e4b17023SJohn Marino } 4617e4b17023SJohn Marino else if (TREE_CODE (expr) == STATEMENT_LIST 4618e4b17023SJohn Marino || TREE_CODE (expr) == BIND_EXPR 4619e4b17023SJohn Marino || TREE_CODE (expr) == SAVE_EXPR) 4620e4b17023SJohn Marino gcc_unreachable (); 4621e4b17023SJohn Marino else if (TREE_CODE (expr) == TARGET_EXPR) 4622e4b17023SJohn Marino { 4623e4b17023SJohn Marino /* Don't mess with a TARGET_EXPR that hasn't been expanded. 4624e4b17023SJohn Marino It's OK for this to happen if it was part of a subtree that 4625e4b17023SJohn Marino isn't immediately expanded, such as operand 2 of another 4626e4b17023SJohn Marino TARGET_EXPR. */ 4627e4b17023SJohn Marino if (!TREE_OPERAND (expr, 1)) 4628e4b17023SJohn Marino { 4629e4b17023SJohn Marino TREE_OPERAND (expr, 1) = TREE_OPERAND (expr, 3); 4630e4b17023SJohn Marino TREE_OPERAND (expr, 3) = NULL_TREE; 4631e4b17023SJohn Marino } 4632e4b17023SJohn Marino } 4633e4b17023SJohn Marino 4634e4b17023SJohn Marino /* Keep iterating. */ 4635e4b17023SJohn Marino return NULL_TREE; 4636e4b17023SJohn Marino } 4637e4b17023SJohn Marino 4638e4b17023SJohn Marino 4639e4b17023SJohn Marino /* Called via walk_gimple_seq by copy_gimple_seq_and_replace_local. 4640e4b17023SJohn Marino Using the splay_tree pointed to by ST (which is really a `splay_tree'), 4641e4b17023SJohn Marino remaps all local declarations to appropriate replacements in gimple 4642e4b17023SJohn Marino statements. */ 4643e4b17023SJohn Marino 4644e4b17023SJohn Marino static tree 4645e4b17023SJohn Marino replace_locals_stmt (gimple_stmt_iterator *gsip, 4646e4b17023SJohn Marino bool *handled_ops_p ATTRIBUTE_UNUSED, 4647e4b17023SJohn Marino struct walk_stmt_info *wi) 4648e4b17023SJohn Marino { 4649e4b17023SJohn Marino copy_body_data *id = (copy_body_data *) wi->info; 4650e4b17023SJohn Marino gimple stmt = gsi_stmt (*gsip); 4651e4b17023SJohn Marino 4652e4b17023SJohn Marino if (gimple_code (stmt) == GIMPLE_BIND) 4653e4b17023SJohn Marino { 4654e4b17023SJohn Marino tree block = gimple_bind_block (stmt); 4655e4b17023SJohn Marino 4656e4b17023SJohn Marino if (block) 4657e4b17023SJohn Marino { 4658e4b17023SJohn Marino remap_block (&block, id); 4659e4b17023SJohn Marino gimple_bind_set_block (stmt, block); 4660e4b17023SJohn Marino } 4661e4b17023SJohn Marino 4662e4b17023SJohn Marino /* This will remap a lot of the same decls again, but this should be 4663e4b17023SJohn Marino harmless. */ 4664e4b17023SJohn Marino if (gimple_bind_vars (stmt)) 4665e4b17023SJohn Marino gimple_bind_set_vars (stmt, remap_decls (gimple_bind_vars (stmt), NULL, id)); 4666e4b17023SJohn Marino } 4667e4b17023SJohn Marino 4668e4b17023SJohn Marino /* Keep iterating. */ 4669e4b17023SJohn Marino return NULL_TREE; 4670e4b17023SJohn Marino } 4671e4b17023SJohn Marino 4672e4b17023SJohn Marino 4673e4b17023SJohn Marino /* Copies everything in SEQ and replaces variables and labels local to 4674e4b17023SJohn Marino current_function_decl. */ 4675e4b17023SJohn Marino 4676e4b17023SJohn Marino gimple_seq 4677e4b17023SJohn Marino copy_gimple_seq_and_replace_locals (gimple_seq seq) 4678e4b17023SJohn Marino { 4679e4b17023SJohn Marino copy_body_data id; 4680e4b17023SJohn Marino struct walk_stmt_info wi; 4681e4b17023SJohn Marino struct pointer_set_t *visited; 4682e4b17023SJohn Marino gimple_seq copy; 4683e4b17023SJohn Marino 4684e4b17023SJohn Marino /* There's nothing to do for NULL_TREE. */ 4685e4b17023SJohn Marino if (seq == NULL) 4686e4b17023SJohn Marino return seq; 4687e4b17023SJohn Marino 4688e4b17023SJohn Marino /* Set up ID. */ 4689e4b17023SJohn Marino memset (&id, 0, sizeof (id)); 4690e4b17023SJohn Marino id.src_fn = current_function_decl; 4691e4b17023SJohn Marino id.dst_fn = current_function_decl; 4692e4b17023SJohn Marino id.decl_map = pointer_map_create (); 4693e4b17023SJohn Marino id.debug_map = NULL; 4694e4b17023SJohn Marino 4695e4b17023SJohn Marino id.copy_decl = copy_decl_no_change; 4696e4b17023SJohn Marino id.transform_call_graph_edges = CB_CGE_DUPLICATE; 4697e4b17023SJohn Marino id.transform_new_cfg = false; 4698e4b17023SJohn Marino id.transform_return_to_modify = false; 4699e4b17023SJohn Marino id.transform_lang_insert_block = NULL; 4700e4b17023SJohn Marino 4701e4b17023SJohn Marino /* Walk the tree once to find local labels. */ 4702e4b17023SJohn Marino memset (&wi, 0, sizeof (wi)); 4703e4b17023SJohn Marino visited = pointer_set_create (); 4704e4b17023SJohn Marino wi.info = &id; 4705e4b17023SJohn Marino wi.pset = visited; 4706e4b17023SJohn Marino walk_gimple_seq (seq, mark_local_labels_stmt, NULL, &wi); 4707e4b17023SJohn Marino pointer_set_destroy (visited); 4708e4b17023SJohn Marino 4709e4b17023SJohn Marino copy = gimple_seq_copy (seq); 4710e4b17023SJohn Marino 4711e4b17023SJohn Marino /* Walk the copy, remapping decls. */ 4712e4b17023SJohn Marino memset (&wi, 0, sizeof (wi)); 4713e4b17023SJohn Marino wi.info = &id; 4714e4b17023SJohn Marino walk_gimple_seq (copy, replace_locals_stmt, replace_locals_op, &wi); 4715e4b17023SJohn Marino 4716e4b17023SJohn Marino /* Clean up. */ 4717e4b17023SJohn Marino pointer_map_destroy (id.decl_map); 4718e4b17023SJohn Marino if (id.debug_map) 4719e4b17023SJohn Marino pointer_map_destroy (id.debug_map); 4720e4b17023SJohn Marino 4721e4b17023SJohn Marino return copy; 4722e4b17023SJohn Marino } 4723e4b17023SJohn Marino 4724e4b17023SJohn Marino 4725e4b17023SJohn Marino /* Allow someone to determine if SEARCH is a child of TOP from gdb. */ 4726e4b17023SJohn Marino 4727e4b17023SJohn Marino static tree 4728e4b17023SJohn Marino debug_find_tree_1 (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data) 4729e4b17023SJohn Marino { 4730e4b17023SJohn Marino if (*tp == data) 4731e4b17023SJohn Marino return (tree) data; 4732e4b17023SJohn Marino else 4733e4b17023SJohn Marino return NULL; 4734e4b17023SJohn Marino } 4735e4b17023SJohn Marino 4736e4b17023SJohn Marino DEBUG_FUNCTION bool 4737e4b17023SJohn Marino debug_find_tree (tree top, tree search) 4738e4b17023SJohn Marino { 4739e4b17023SJohn Marino return walk_tree_without_duplicates (&top, debug_find_tree_1, search) != 0; 4740e4b17023SJohn Marino } 4741e4b17023SJohn Marino 4742e4b17023SJohn Marino 4743e4b17023SJohn Marino /* Declare the variables created by the inliner. Add all the variables in 4744e4b17023SJohn Marino VARS to BIND_EXPR. */ 4745e4b17023SJohn Marino 4746e4b17023SJohn Marino static void 4747e4b17023SJohn Marino declare_inline_vars (tree block, tree vars) 4748e4b17023SJohn Marino { 4749e4b17023SJohn Marino tree t; 4750e4b17023SJohn Marino for (t = vars; t; t = DECL_CHAIN (t)) 4751e4b17023SJohn Marino { 4752e4b17023SJohn Marino DECL_SEEN_IN_BIND_EXPR_P (t) = 1; 4753e4b17023SJohn Marino gcc_assert (!TREE_STATIC (t) && !TREE_ASM_WRITTEN (t)); 4754e4b17023SJohn Marino add_local_decl (cfun, t); 4755e4b17023SJohn Marino } 4756e4b17023SJohn Marino 4757e4b17023SJohn Marino if (block) 4758e4b17023SJohn Marino BLOCK_VARS (block) = chainon (BLOCK_VARS (block), vars); 4759e4b17023SJohn Marino } 4760e4b17023SJohn Marino 4761e4b17023SJohn Marino /* Copy NODE (which must be a DECL). The DECL originally was in the FROM_FN, 4762e4b17023SJohn Marino but now it will be in the TO_FN. PARM_TO_VAR means enable PARM_DECL to 4763e4b17023SJohn Marino VAR_DECL translation. */ 4764e4b17023SJohn Marino 4765e4b17023SJohn Marino static tree 4766e4b17023SJohn Marino copy_decl_for_dup_finish (copy_body_data *id, tree decl, tree copy) 4767e4b17023SJohn Marino { 4768e4b17023SJohn Marino /* Don't generate debug information for the copy if we wouldn't have 4769e4b17023SJohn Marino generated it for the copy either. */ 4770e4b17023SJohn Marino DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (decl); 4771e4b17023SJohn Marino DECL_IGNORED_P (copy) = DECL_IGNORED_P (decl); 4772e4b17023SJohn Marino 4773e4b17023SJohn Marino /* Set the DECL_ABSTRACT_ORIGIN so the debugging routines know what 4774e4b17023SJohn Marino declaration inspired this copy. */ 4775e4b17023SJohn Marino DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (decl); 4776e4b17023SJohn Marino 4777e4b17023SJohn Marino /* The new variable/label has no RTL, yet. */ 4778e4b17023SJohn Marino if (CODE_CONTAINS_STRUCT (TREE_CODE (copy), TS_DECL_WRTL) 4779e4b17023SJohn Marino && !TREE_STATIC (copy) && !DECL_EXTERNAL (copy)) 4780e4b17023SJohn Marino SET_DECL_RTL (copy, 0); 4781e4b17023SJohn Marino 4782e4b17023SJohn Marino /* These args would always appear unused, if not for this. */ 4783e4b17023SJohn Marino TREE_USED (copy) = 1; 4784e4b17023SJohn Marino 4785e4b17023SJohn Marino /* Set the context for the new declaration. */ 4786e4b17023SJohn Marino if (!DECL_CONTEXT (decl)) 4787e4b17023SJohn Marino /* Globals stay global. */ 4788e4b17023SJohn Marino ; 4789e4b17023SJohn Marino else if (DECL_CONTEXT (decl) != id->src_fn) 4790e4b17023SJohn Marino /* Things that weren't in the scope of the function we're inlining 4791e4b17023SJohn Marino from aren't in the scope we're inlining to, either. */ 4792e4b17023SJohn Marino ; 4793e4b17023SJohn Marino else if (TREE_STATIC (decl)) 4794e4b17023SJohn Marino /* Function-scoped static variables should stay in the original 4795e4b17023SJohn Marino function. */ 4796e4b17023SJohn Marino ; 4797e4b17023SJohn Marino else 4798e4b17023SJohn Marino /* Ordinary automatic local variables are now in the scope of the 4799e4b17023SJohn Marino new function. */ 4800e4b17023SJohn Marino DECL_CONTEXT (copy) = id->dst_fn; 4801e4b17023SJohn Marino 4802e4b17023SJohn Marino if (TREE_CODE (decl) == VAR_DECL 4803e4b17023SJohn Marino /* C++ clones functions during parsing, before 4804e4b17023SJohn Marino referenced_vars. */ 4805e4b17023SJohn Marino && gimple_referenced_vars (DECL_STRUCT_FUNCTION (id->src_fn)) 4806e4b17023SJohn Marino && referenced_var_lookup (DECL_STRUCT_FUNCTION (id->src_fn), 4807e4b17023SJohn Marino DECL_UID (decl))) 4808e4b17023SJohn Marino add_referenced_var (copy); 4809e4b17023SJohn Marino 4810e4b17023SJohn Marino return copy; 4811e4b17023SJohn Marino } 4812e4b17023SJohn Marino 4813e4b17023SJohn Marino static tree 4814e4b17023SJohn Marino copy_decl_to_var (tree decl, copy_body_data *id) 4815e4b17023SJohn Marino { 4816e4b17023SJohn Marino tree copy, type; 4817e4b17023SJohn Marino 4818e4b17023SJohn Marino gcc_assert (TREE_CODE (decl) == PARM_DECL 4819e4b17023SJohn Marino || TREE_CODE (decl) == RESULT_DECL); 4820e4b17023SJohn Marino 4821e4b17023SJohn Marino type = TREE_TYPE (decl); 4822e4b17023SJohn Marino 4823e4b17023SJohn Marino copy = build_decl (DECL_SOURCE_LOCATION (id->dst_fn), 4824e4b17023SJohn Marino VAR_DECL, DECL_NAME (decl), type); 4825e4b17023SJohn Marino if (DECL_PT_UID_SET_P (decl)) 4826e4b17023SJohn Marino SET_DECL_PT_UID (copy, DECL_PT_UID (decl)); 4827e4b17023SJohn Marino TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl); 4828e4b17023SJohn Marino TREE_READONLY (copy) = TREE_READONLY (decl); 4829e4b17023SJohn Marino TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl); 4830e4b17023SJohn Marino DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (decl); 4831e4b17023SJohn Marino 4832e4b17023SJohn Marino return copy_decl_for_dup_finish (id, decl, copy); 4833e4b17023SJohn Marino } 4834e4b17023SJohn Marino 4835e4b17023SJohn Marino /* Like copy_decl_to_var, but create a return slot object instead of a 4836e4b17023SJohn Marino pointer variable for return by invisible reference. */ 4837e4b17023SJohn Marino 4838e4b17023SJohn Marino static tree 4839e4b17023SJohn Marino copy_result_decl_to_var (tree decl, copy_body_data *id) 4840e4b17023SJohn Marino { 4841e4b17023SJohn Marino tree copy, type; 4842e4b17023SJohn Marino 4843e4b17023SJohn Marino gcc_assert (TREE_CODE (decl) == PARM_DECL 4844e4b17023SJohn Marino || TREE_CODE (decl) == RESULT_DECL); 4845e4b17023SJohn Marino 4846e4b17023SJohn Marino type = TREE_TYPE (decl); 4847e4b17023SJohn Marino if (DECL_BY_REFERENCE (decl)) 4848e4b17023SJohn Marino type = TREE_TYPE (type); 4849e4b17023SJohn Marino 4850e4b17023SJohn Marino copy = build_decl (DECL_SOURCE_LOCATION (id->dst_fn), 4851e4b17023SJohn Marino VAR_DECL, DECL_NAME (decl), type); 4852e4b17023SJohn Marino if (DECL_PT_UID_SET_P (decl)) 4853e4b17023SJohn Marino SET_DECL_PT_UID (copy, DECL_PT_UID (decl)); 4854e4b17023SJohn Marino TREE_READONLY (copy) = TREE_READONLY (decl); 4855e4b17023SJohn Marino TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl); 4856e4b17023SJohn Marino if (!DECL_BY_REFERENCE (decl)) 4857e4b17023SJohn Marino { 4858e4b17023SJohn Marino TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl); 4859e4b17023SJohn Marino DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (decl); 4860e4b17023SJohn Marino } 4861e4b17023SJohn Marino 4862e4b17023SJohn Marino return copy_decl_for_dup_finish (id, decl, copy); 4863e4b17023SJohn Marino } 4864e4b17023SJohn Marino 4865e4b17023SJohn Marino tree 4866e4b17023SJohn Marino copy_decl_no_change (tree decl, copy_body_data *id) 4867e4b17023SJohn Marino { 4868e4b17023SJohn Marino tree copy; 4869e4b17023SJohn Marino 4870e4b17023SJohn Marino copy = copy_node (decl); 4871e4b17023SJohn Marino 4872e4b17023SJohn Marino /* The COPY is not abstract; it will be generated in DST_FN. */ 4873e4b17023SJohn Marino DECL_ABSTRACT (copy) = 0; 4874e4b17023SJohn Marino lang_hooks.dup_lang_specific_decl (copy); 4875e4b17023SJohn Marino 4876e4b17023SJohn Marino /* TREE_ADDRESSABLE isn't used to indicate that a label's address has 4877e4b17023SJohn Marino been taken; it's for internal bookkeeping in expand_goto_internal. */ 4878e4b17023SJohn Marino if (TREE_CODE (copy) == LABEL_DECL) 4879e4b17023SJohn Marino { 4880e4b17023SJohn Marino TREE_ADDRESSABLE (copy) = 0; 4881e4b17023SJohn Marino LABEL_DECL_UID (copy) = -1; 4882e4b17023SJohn Marino } 4883e4b17023SJohn Marino 4884e4b17023SJohn Marino return copy_decl_for_dup_finish (id, decl, copy); 4885e4b17023SJohn Marino } 4886e4b17023SJohn Marino 4887e4b17023SJohn Marino static tree 4888e4b17023SJohn Marino copy_decl_maybe_to_var (tree decl, copy_body_data *id) 4889e4b17023SJohn Marino { 4890e4b17023SJohn Marino if (TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == RESULT_DECL) 4891e4b17023SJohn Marino return copy_decl_to_var (decl, id); 4892e4b17023SJohn Marino else 4893e4b17023SJohn Marino return copy_decl_no_change (decl, id); 4894e4b17023SJohn Marino } 4895e4b17023SJohn Marino 4896e4b17023SJohn Marino /* Return a copy of the function's argument tree. */ 4897e4b17023SJohn Marino static tree 4898e4b17023SJohn Marino copy_arguments_for_versioning (tree orig_parm, copy_body_data * id, 4899e4b17023SJohn Marino bitmap args_to_skip, tree *vars) 4900e4b17023SJohn Marino { 4901e4b17023SJohn Marino tree arg, *parg; 4902e4b17023SJohn Marino tree new_parm = NULL; 4903e4b17023SJohn Marino int i = 0; 4904e4b17023SJohn Marino 4905e4b17023SJohn Marino parg = &new_parm; 4906e4b17023SJohn Marino 4907e4b17023SJohn Marino for (arg = orig_parm; arg; arg = DECL_CHAIN (arg), i++) 4908e4b17023SJohn Marino if (!args_to_skip || !bitmap_bit_p (args_to_skip, i)) 4909e4b17023SJohn Marino { 4910e4b17023SJohn Marino tree new_tree = remap_decl (arg, id); 4911e4b17023SJohn Marino if (TREE_CODE (new_tree) != PARM_DECL) 4912e4b17023SJohn Marino new_tree = id->copy_decl (arg, id); 4913e4b17023SJohn Marino lang_hooks.dup_lang_specific_decl (new_tree); 4914e4b17023SJohn Marino *parg = new_tree; 4915e4b17023SJohn Marino parg = &DECL_CHAIN (new_tree); 4916e4b17023SJohn Marino } 4917e4b17023SJohn Marino else if (!pointer_map_contains (id->decl_map, arg)) 4918e4b17023SJohn Marino { 4919e4b17023SJohn Marino /* Make an equivalent VAR_DECL. If the argument was used 4920e4b17023SJohn Marino as temporary variable later in function, the uses will be 4921e4b17023SJohn Marino replaced by local variable. */ 4922e4b17023SJohn Marino tree var = copy_decl_to_var (arg, id); 4923e4b17023SJohn Marino add_referenced_var (var); 4924e4b17023SJohn Marino insert_decl_map (id, arg, var); 4925e4b17023SJohn Marino /* Declare this new variable. */ 4926e4b17023SJohn Marino DECL_CHAIN (var) = *vars; 4927e4b17023SJohn Marino *vars = var; 4928e4b17023SJohn Marino } 4929e4b17023SJohn Marino return new_parm; 4930e4b17023SJohn Marino } 4931e4b17023SJohn Marino 4932e4b17023SJohn Marino /* Return a copy of the function's static chain. */ 4933e4b17023SJohn Marino static tree 4934e4b17023SJohn Marino copy_static_chain (tree static_chain, copy_body_data * id) 4935e4b17023SJohn Marino { 4936e4b17023SJohn Marino tree *chain_copy, *pvar; 4937e4b17023SJohn Marino 4938e4b17023SJohn Marino chain_copy = &static_chain; 4939e4b17023SJohn Marino for (pvar = chain_copy; *pvar; pvar = &DECL_CHAIN (*pvar)) 4940e4b17023SJohn Marino { 4941e4b17023SJohn Marino tree new_tree = remap_decl (*pvar, id); 4942e4b17023SJohn Marino lang_hooks.dup_lang_specific_decl (new_tree); 4943e4b17023SJohn Marino DECL_CHAIN (new_tree) = DECL_CHAIN (*pvar); 4944e4b17023SJohn Marino *pvar = new_tree; 4945e4b17023SJohn Marino } 4946e4b17023SJohn Marino return static_chain; 4947e4b17023SJohn Marino } 4948e4b17023SJohn Marino 4949e4b17023SJohn Marino /* Return true if the function is allowed to be versioned. 4950e4b17023SJohn Marino This is a guard for the versioning functionality. */ 4951e4b17023SJohn Marino 4952e4b17023SJohn Marino bool 4953e4b17023SJohn Marino tree_versionable_function_p (tree fndecl) 4954e4b17023SJohn Marino { 4955e4b17023SJohn Marino return (!lookup_attribute ("noclone", DECL_ATTRIBUTES (fndecl)) 4956e4b17023SJohn Marino && copy_forbidden (DECL_STRUCT_FUNCTION (fndecl), fndecl) == NULL); 4957e4b17023SJohn Marino } 4958e4b17023SJohn Marino 4959e4b17023SJohn Marino /* Delete all unreachable basic blocks and update callgraph. 4960e4b17023SJohn Marino Doing so is somewhat nontrivial because we need to update all clones and 4961e4b17023SJohn Marino remove inline function that become unreachable. */ 4962e4b17023SJohn Marino 4963e4b17023SJohn Marino static bool 4964e4b17023SJohn Marino delete_unreachable_blocks_update_callgraph (copy_body_data *id) 4965e4b17023SJohn Marino { 4966e4b17023SJohn Marino bool changed = false; 4967e4b17023SJohn Marino basic_block b, next_bb; 4968e4b17023SJohn Marino 4969e4b17023SJohn Marino find_unreachable_blocks (); 4970e4b17023SJohn Marino 4971e4b17023SJohn Marino /* Delete all unreachable basic blocks. */ 4972e4b17023SJohn Marino 4973e4b17023SJohn Marino for (b = ENTRY_BLOCK_PTR->next_bb; b != EXIT_BLOCK_PTR; b = next_bb) 4974e4b17023SJohn Marino { 4975e4b17023SJohn Marino next_bb = b->next_bb; 4976e4b17023SJohn Marino 4977e4b17023SJohn Marino if (!(b->flags & BB_REACHABLE)) 4978e4b17023SJohn Marino { 4979e4b17023SJohn Marino gimple_stmt_iterator bsi; 4980e4b17023SJohn Marino 4981e4b17023SJohn Marino for (bsi = gsi_start_bb (b); !gsi_end_p (bsi); gsi_next (&bsi)) 4982e4b17023SJohn Marino if (gimple_code (gsi_stmt (bsi)) == GIMPLE_CALL) 4983e4b17023SJohn Marino { 4984e4b17023SJohn Marino struct cgraph_edge *e; 4985e4b17023SJohn Marino struct cgraph_node *node; 4986e4b17023SJohn Marino 4987e4b17023SJohn Marino if ((e = cgraph_edge (id->dst_node, gsi_stmt (bsi))) != NULL) 4988e4b17023SJohn Marino { 4989e4b17023SJohn Marino if (!e->inline_failed) 4990e4b17023SJohn Marino cgraph_remove_node_and_inline_clones (e->callee); 4991e4b17023SJohn Marino else 4992e4b17023SJohn Marino cgraph_remove_edge (e); 4993e4b17023SJohn Marino } 4994e4b17023SJohn Marino if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES 4995e4b17023SJohn Marino && id->dst_node->clones) 4996e4b17023SJohn Marino for (node = id->dst_node->clones; node != id->dst_node;) 4997e4b17023SJohn Marino { 4998e4b17023SJohn Marino if ((e = cgraph_edge (node, gsi_stmt (bsi))) != NULL) 4999e4b17023SJohn Marino { 5000e4b17023SJohn Marino if (!e->inline_failed) 5001e4b17023SJohn Marino cgraph_remove_node_and_inline_clones (e->callee); 5002e4b17023SJohn Marino else 5003e4b17023SJohn Marino cgraph_remove_edge (e); 5004e4b17023SJohn Marino } 5005e4b17023SJohn Marino 5006e4b17023SJohn Marino if (node->clones) 5007e4b17023SJohn Marino node = node->clones; 5008e4b17023SJohn Marino else if (node->next_sibling_clone) 5009e4b17023SJohn Marino node = node->next_sibling_clone; 5010e4b17023SJohn Marino else 5011e4b17023SJohn Marino { 5012e4b17023SJohn Marino while (node != id->dst_node && !node->next_sibling_clone) 5013e4b17023SJohn Marino node = node->clone_of; 5014e4b17023SJohn Marino if (node != id->dst_node) 5015e4b17023SJohn Marino node = node->next_sibling_clone; 5016e4b17023SJohn Marino } 5017e4b17023SJohn Marino } 5018e4b17023SJohn Marino } 5019e4b17023SJohn Marino delete_basic_block (b); 5020e4b17023SJohn Marino changed = true; 5021e4b17023SJohn Marino } 5022e4b17023SJohn Marino } 5023e4b17023SJohn Marino 5024e4b17023SJohn Marino return changed; 5025e4b17023SJohn Marino } 5026e4b17023SJohn Marino 5027e4b17023SJohn Marino /* Update clone info after duplication. */ 5028e4b17023SJohn Marino 5029e4b17023SJohn Marino static void 5030e4b17023SJohn Marino update_clone_info (copy_body_data * id) 5031e4b17023SJohn Marino { 5032e4b17023SJohn Marino struct cgraph_node *node; 5033e4b17023SJohn Marino if (!id->dst_node->clones) 5034e4b17023SJohn Marino return; 5035e4b17023SJohn Marino for (node = id->dst_node->clones; node != id->dst_node;) 5036e4b17023SJohn Marino { 5037e4b17023SJohn Marino /* First update replace maps to match the new body. */ 5038e4b17023SJohn Marino if (node->clone.tree_map) 5039e4b17023SJohn Marino { 5040e4b17023SJohn Marino unsigned int i; 5041e4b17023SJohn Marino for (i = 0; i < VEC_length (ipa_replace_map_p, node->clone.tree_map); i++) 5042e4b17023SJohn Marino { 5043e4b17023SJohn Marino struct ipa_replace_map *replace_info; 5044e4b17023SJohn Marino replace_info = VEC_index (ipa_replace_map_p, node->clone.tree_map, i); 5045e4b17023SJohn Marino walk_tree (&replace_info->old_tree, copy_tree_body_r, id, NULL); 5046e4b17023SJohn Marino walk_tree (&replace_info->new_tree, copy_tree_body_r, id, NULL); 5047e4b17023SJohn Marino } 5048e4b17023SJohn Marino } 5049e4b17023SJohn Marino if (node->clones) 5050e4b17023SJohn Marino node = node->clones; 5051e4b17023SJohn Marino else if (node->next_sibling_clone) 5052e4b17023SJohn Marino node = node->next_sibling_clone; 5053e4b17023SJohn Marino else 5054e4b17023SJohn Marino { 5055e4b17023SJohn Marino while (node != id->dst_node && !node->next_sibling_clone) 5056e4b17023SJohn Marino node = node->clone_of; 5057e4b17023SJohn Marino if (node != id->dst_node) 5058e4b17023SJohn Marino node = node->next_sibling_clone; 5059e4b17023SJohn Marino } 5060e4b17023SJohn Marino } 5061e4b17023SJohn Marino } 5062e4b17023SJohn Marino 5063e4b17023SJohn Marino /* Create a copy of a function's tree. 5064e4b17023SJohn Marino OLD_DECL and NEW_DECL are FUNCTION_DECL tree nodes 5065e4b17023SJohn Marino of the original function and the new copied function 5066e4b17023SJohn Marino respectively. In case we want to replace a DECL 5067e4b17023SJohn Marino tree with another tree while duplicating the function's 5068e4b17023SJohn Marino body, TREE_MAP represents the mapping between these 5069e4b17023SJohn Marino trees. If UPDATE_CLONES is set, the call_stmt fields 5070e4b17023SJohn Marino of edges of clones of the function will be updated. 5071e4b17023SJohn Marino 5072e4b17023SJohn Marino If non-NULL ARGS_TO_SKIP determine function parameters to remove 5073e4b17023SJohn Marino from new version. 5074e4b17023SJohn Marino If SKIP_RETURN is true, the new version will return void. 5075e4b17023SJohn Marino If non-NULL BLOCK_TO_COPY determine what basic blocks to copy. 5076e4b17023SJohn Marino If non_NULL NEW_ENTRY determine new entry BB of the clone. 5077e4b17023SJohn Marino */ 5078e4b17023SJohn Marino void 5079e4b17023SJohn Marino tree_function_versioning (tree old_decl, tree new_decl, 5080e4b17023SJohn Marino VEC(ipa_replace_map_p,gc)* tree_map, 5081e4b17023SJohn Marino bool update_clones, bitmap args_to_skip, 5082e4b17023SJohn Marino bool skip_return, bitmap blocks_to_copy, 5083e4b17023SJohn Marino basic_block new_entry) 5084e4b17023SJohn Marino { 5085e4b17023SJohn Marino struct cgraph_node *old_version_node; 5086e4b17023SJohn Marino struct cgraph_node *new_version_node; 5087e4b17023SJohn Marino copy_body_data id; 5088e4b17023SJohn Marino tree p; 5089e4b17023SJohn Marino unsigned i; 5090e4b17023SJohn Marino struct ipa_replace_map *replace_info; 5091e4b17023SJohn Marino basic_block old_entry_block, bb; 5092e4b17023SJohn Marino VEC (gimple, heap) *init_stmts = VEC_alloc (gimple, heap, 10); 5093e4b17023SJohn Marino 5094e4b17023SJohn Marino tree old_current_function_decl = current_function_decl; 5095e4b17023SJohn Marino tree vars = NULL_TREE; 5096e4b17023SJohn Marino 5097e4b17023SJohn Marino gcc_assert (TREE_CODE (old_decl) == FUNCTION_DECL 5098e4b17023SJohn Marino && TREE_CODE (new_decl) == FUNCTION_DECL); 5099e4b17023SJohn Marino DECL_POSSIBLY_INLINED (old_decl) = 1; 5100e4b17023SJohn Marino 5101e4b17023SJohn Marino old_version_node = cgraph_get_node (old_decl); 5102e4b17023SJohn Marino gcc_checking_assert (old_version_node); 5103e4b17023SJohn Marino new_version_node = cgraph_get_node (new_decl); 5104e4b17023SJohn Marino gcc_checking_assert (new_version_node); 5105e4b17023SJohn Marino 5106e4b17023SJohn Marino /* Copy over debug args. */ 5107e4b17023SJohn Marino if (DECL_HAS_DEBUG_ARGS_P (old_decl)) 5108e4b17023SJohn Marino { 5109e4b17023SJohn Marino VEC(tree, gc) **new_debug_args, **old_debug_args; 5110e4b17023SJohn Marino gcc_checking_assert (decl_debug_args_lookup (new_decl) == NULL); 5111e4b17023SJohn Marino DECL_HAS_DEBUG_ARGS_P (new_decl) = 0; 5112e4b17023SJohn Marino old_debug_args = decl_debug_args_lookup (old_decl); 5113e4b17023SJohn Marino if (old_debug_args) 5114e4b17023SJohn Marino { 5115e4b17023SJohn Marino new_debug_args = decl_debug_args_insert (new_decl); 5116e4b17023SJohn Marino *new_debug_args = VEC_copy (tree, gc, *old_debug_args); 5117e4b17023SJohn Marino } 5118e4b17023SJohn Marino } 5119e4b17023SJohn Marino 5120e4b17023SJohn Marino /* Output the inlining info for this abstract function, since it has been 5121e4b17023SJohn Marino inlined. If we don't do this now, we can lose the information about the 5122e4b17023SJohn Marino variables in the function when the blocks get blown away as soon as we 5123e4b17023SJohn Marino remove the cgraph node. */ 5124e4b17023SJohn Marino (*debug_hooks->outlining_inline_function) (old_decl); 5125e4b17023SJohn Marino 5126e4b17023SJohn Marino DECL_ARTIFICIAL (new_decl) = 1; 5127e4b17023SJohn Marino DECL_ABSTRACT_ORIGIN (new_decl) = DECL_ORIGIN (old_decl); 5128e4b17023SJohn Marino DECL_FUNCTION_PERSONALITY (new_decl) = DECL_FUNCTION_PERSONALITY (old_decl); 5129e4b17023SJohn Marino 5130e4b17023SJohn Marino /* Prepare the data structures for the tree copy. */ 5131e4b17023SJohn Marino memset (&id, 0, sizeof (id)); 5132e4b17023SJohn Marino 5133e4b17023SJohn Marino /* Generate a new name for the new version. */ 5134e4b17023SJohn Marino id.statements_to_fold = pointer_set_create (); 5135e4b17023SJohn Marino 5136e4b17023SJohn Marino id.decl_map = pointer_map_create (); 5137e4b17023SJohn Marino id.debug_map = NULL; 5138e4b17023SJohn Marino id.src_fn = old_decl; 5139e4b17023SJohn Marino id.dst_fn = new_decl; 5140e4b17023SJohn Marino id.src_node = old_version_node; 5141e4b17023SJohn Marino id.dst_node = new_version_node; 5142e4b17023SJohn Marino id.src_cfun = DECL_STRUCT_FUNCTION (old_decl); 5143e4b17023SJohn Marino if (id.src_node->ipa_transforms_to_apply) 5144e4b17023SJohn Marino { 5145e4b17023SJohn Marino VEC(ipa_opt_pass,heap) * old_transforms_to_apply = id.dst_node->ipa_transforms_to_apply; 5146e4b17023SJohn Marino unsigned int i; 5147e4b17023SJohn Marino 5148e4b17023SJohn Marino id.dst_node->ipa_transforms_to_apply = VEC_copy (ipa_opt_pass, heap, 5149e4b17023SJohn Marino id.src_node->ipa_transforms_to_apply); 5150e4b17023SJohn Marino for (i = 0; i < VEC_length (ipa_opt_pass, old_transforms_to_apply); i++) 5151e4b17023SJohn Marino VEC_safe_push (ipa_opt_pass, heap, id.dst_node->ipa_transforms_to_apply, 5152e4b17023SJohn Marino VEC_index (ipa_opt_pass, 5153e4b17023SJohn Marino old_transforms_to_apply, 5154e4b17023SJohn Marino i)); 5155e4b17023SJohn Marino } 5156e4b17023SJohn Marino 5157e4b17023SJohn Marino id.copy_decl = copy_decl_no_change; 5158e4b17023SJohn Marino id.transform_call_graph_edges 5159e4b17023SJohn Marino = update_clones ? CB_CGE_MOVE_CLONES : CB_CGE_MOVE; 5160e4b17023SJohn Marino id.transform_new_cfg = true; 5161e4b17023SJohn Marino id.transform_return_to_modify = false; 5162e4b17023SJohn Marino id.transform_lang_insert_block = NULL; 5163e4b17023SJohn Marino 5164e4b17023SJohn Marino current_function_decl = new_decl; 5165e4b17023SJohn Marino old_entry_block = ENTRY_BLOCK_PTR_FOR_FUNCTION 5166e4b17023SJohn Marino (DECL_STRUCT_FUNCTION (old_decl)); 5167e4b17023SJohn Marino initialize_cfun (new_decl, old_decl, 5168e4b17023SJohn Marino old_entry_block->count); 5169e4b17023SJohn Marino DECL_STRUCT_FUNCTION (new_decl)->gimple_df->ipa_pta 5170e4b17023SJohn Marino = id.src_cfun->gimple_df->ipa_pta; 5171e4b17023SJohn Marino push_cfun (DECL_STRUCT_FUNCTION (new_decl)); 5172e4b17023SJohn Marino 5173e4b17023SJohn Marino /* Copy the function's static chain. */ 5174e4b17023SJohn Marino p = DECL_STRUCT_FUNCTION (old_decl)->static_chain_decl; 5175e4b17023SJohn Marino if (p) 5176e4b17023SJohn Marino DECL_STRUCT_FUNCTION (new_decl)->static_chain_decl = 5177e4b17023SJohn Marino copy_static_chain (DECL_STRUCT_FUNCTION (old_decl)->static_chain_decl, 5178e4b17023SJohn Marino &id); 5179e4b17023SJohn Marino 5180e4b17023SJohn Marino /* If there's a tree_map, prepare for substitution. */ 5181e4b17023SJohn Marino if (tree_map) 5182e4b17023SJohn Marino for (i = 0; i < VEC_length (ipa_replace_map_p, tree_map); i++) 5183e4b17023SJohn Marino { 5184e4b17023SJohn Marino gimple init; 5185e4b17023SJohn Marino replace_info = VEC_index (ipa_replace_map_p, tree_map, i); 5186e4b17023SJohn Marino if (replace_info->replace_p) 5187e4b17023SJohn Marino { 5188e4b17023SJohn Marino tree op = replace_info->new_tree; 5189e4b17023SJohn Marino if (!replace_info->old_tree) 5190e4b17023SJohn Marino { 5191e4b17023SJohn Marino int i = replace_info->parm_num; 5192e4b17023SJohn Marino tree parm; 5193e4b17023SJohn Marino for (parm = DECL_ARGUMENTS (old_decl); i; parm = DECL_CHAIN (parm)) 5194e4b17023SJohn Marino i --; 5195e4b17023SJohn Marino replace_info->old_tree = parm; 5196e4b17023SJohn Marino } 5197e4b17023SJohn Marino 5198e4b17023SJohn Marino 5199e4b17023SJohn Marino STRIP_NOPS (op); 5200e4b17023SJohn Marino 5201e4b17023SJohn Marino if (TREE_CODE (op) == VIEW_CONVERT_EXPR) 5202e4b17023SJohn Marino op = TREE_OPERAND (op, 0); 5203e4b17023SJohn Marino 5204e4b17023SJohn Marino if (TREE_CODE (op) == ADDR_EXPR) 5205e4b17023SJohn Marino { 5206e4b17023SJohn Marino op = TREE_OPERAND (op, 0); 5207e4b17023SJohn Marino while (handled_component_p (op)) 5208e4b17023SJohn Marino op = TREE_OPERAND (op, 0); 5209e4b17023SJohn Marino if (TREE_CODE (op) == VAR_DECL) 5210e4b17023SJohn Marino add_referenced_var (op); 5211e4b17023SJohn Marino } 5212e4b17023SJohn Marino gcc_assert (TREE_CODE (replace_info->old_tree) == PARM_DECL); 5213e4b17023SJohn Marino init = setup_one_parameter (&id, replace_info->old_tree, 5214e4b17023SJohn Marino replace_info->new_tree, id.src_fn, 5215e4b17023SJohn Marino NULL, 5216e4b17023SJohn Marino &vars); 5217e4b17023SJohn Marino if (init) 5218e4b17023SJohn Marino VEC_safe_push (gimple, heap, init_stmts, init); 5219e4b17023SJohn Marino } 5220e4b17023SJohn Marino } 5221e4b17023SJohn Marino /* Copy the function's arguments. */ 5222e4b17023SJohn Marino if (DECL_ARGUMENTS (old_decl) != NULL_TREE) 5223e4b17023SJohn Marino DECL_ARGUMENTS (new_decl) = 5224e4b17023SJohn Marino copy_arguments_for_versioning (DECL_ARGUMENTS (old_decl), &id, 5225e4b17023SJohn Marino args_to_skip, &vars); 5226e4b17023SJohn Marino 5227e4b17023SJohn Marino DECL_INITIAL (new_decl) = remap_blocks (DECL_INITIAL (id.src_fn), &id); 5228e4b17023SJohn Marino BLOCK_SUPERCONTEXT (DECL_INITIAL (new_decl)) = new_decl; 5229e4b17023SJohn Marino 5230e4b17023SJohn Marino declare_inline_vars (DECL_INITIAL (new_decl), vars); 5231e4b17023SJohn Marino 5232e4b17023SJohn Marino if (!VEC_empty (tree, DECL_STRUCT_FUNCTION (old_decl)->local_decls)) 5233e4b17023SJohn Marino /* Add local vars. */ 5234e4b17023SJohn Marino add_local_variables (DECL_STRUCT_FUNCTION (old_decl), cfun, &id, false); 5235e4b17023SJohn Marino 5236e4b17023SJohn Marino if (DECL_RESULT (old_decl) == NULL_TREE) 5237e4b17023SJohn Marino ; 5238e4b17023SJohn Marino else if (skip_return && !VOID_TYPE_P (TREE_TYPE (DECL_RESULT (old_decl)))) 5239e4b17023SJohn Marino { 5240e4b17023SJohn Marino DECL_RESULT (new_decl) 5241e4b17023SJohn Marino = build_decl (DECL_SOURCE_LOCATION (DECL_RESULT (old_decl)), 5242e4b17023SJohn Marino RESULT_DECL, NULL_TREE, void_type_node); 5243e4b17023SJohn Marino DECL_CONTEXT (DECL_RESULT (new_decl)) = new_decl; 5244e4b17023SJohn Marino cfun->returns_struct = 0; 5245e4b17023SJohn Marino cfun->returns_pcc_struct = 0; 5246e4b17023SJohn Marino } 5247e4b17023SJohn Marino else 5248e4b17023SJohn Marino { 5249e4b17023SJohn Marino tree old_name; 5250e4b17023SJohn Marino DECL_RESULT (new_decl) = remap_decl (DECL_RESULT (old_decl), &id); 5251e4b17023SJohn Marino lang_hooks.dup_lang_specific_decl (DECL_RESULT (new_decl)); 5252e4b17023SJohn Marino if (gimple_in_ssa_p (id.src_cfun) 5253e4b17023SJohn Marino && DECL_BY_REFERENCE (DECL_RESULT (old_decl)) 5254e4b17023SJohn Marino && (old_name 5255e4b17023SJohn Marino = gimple_default_def (id.src_cfun, DECL_RESULT (old_decl)))) 5256e4b17023SJohn Marino { 5257e4b17023SJohn Marino tree new_name = make_ssa_name (DECL_RESULT (new_decl), NULL); 5258e4b17023SJohn Marino insert_decl_map (&id, old_name, new_name); 5259e4b17023SJohn Marino SSA_NAME_DEF_STMT (new_name) = gimple_build_nop (); 5260e4b17023SJohn Marino set_default_def (DECL_RESULT (new_decl), new_name); 5261e4b17023SJohn Marino } 5262e4b17023SJohn Marino } 5263e4b17023SJohn Marino 5264e4b17023SJohn Marino /* Copy the Function's body. */ 5265e4b17023SJohn Marino copy_body (&id, old_entry_block->count, REG_BR_PROB_BASE, 5266e4b17023SJohn Marino ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, blocks_to_copy, new_entry); 5267e4b17023SJohn Marino 5268e4b17023SJohn Marino /* Renumber the lexical scoping (non-code) blocks consecutively. */ 5269e4b17023SJohn Marino number_blocks (new_decl); 5270e4b17023SJohn Marino 5271e4b17023SJohn Marino /* We want to create the BB unconditionally, so that the addition of 5272e4b17023SJohn Marino debug stmts doesn't affect BB count, which may in the end cause 5273e4b17023SJohn Marino codegen differences. */ 5274e4b17023SJohn Marino bb = split_edge (single_succ_edge (ENTRY_BLOCK_PTR)); 5275e4b17023SJohn Marino while (VEC_length (gimple, init_stmts)) 5276e4b17023SJohn Marino insert_init_stmt (&id, bb, VEC_pop (gimple, init_stmts)); 5277e4b17023SJohn Marino update_clone_info (&id); 5278e4b17023SJohn Marino 5279e4b17023SJohn Marino /* Remap the nonlocal_goto_save_area, if any. */ 5280e4b17023SJohn Marino if (cfun->nonlocal_goto_save_area) 5281e4b17023SJohn Marino { 5282e4b17023SJohn Marino struct walk_stmt_info wi; 5283e4b17023SJohn Marino 5284e4b17023SJohn Marino memset (&wi, 0, sizeof (wi)); 5285e4b17023SJohn Marino wi.info = &id; 5286e4b17023SJohn Marino walk_tree (&cfun->nonlocal_goto_save_area, remap_gimple_op_r, &wi, NULL); 5287e4b17023SJohn Marino } 5288e4b17023SJohn Marino 5289e4b17023SJohn Marino /* Clean up. */ 5290e4b17023SJohn Marino pointer_map_destroy (id.decl_map); 5291e4b17023SJohn Marino if (id.debug_map) 5292e4b17023SJohn Marino pointer_map_destroy (id.debug_map); 5293e4b17023SJohn Marino free_dominance_info (CDI_DOMINATORS); 5294e4b17023SJohn Marino free_dominance_info (CDI_POST_DOMINATORS); 5295e4b17023SJohn Marino 5296e4b17023SJohn Marino fold_marked_statements (0, id.statements_to_fold); 5297e4b17023SJohn Marino pointer_set_destroy (id.statements_to_fold); 5298e4b17023SJohn Marino fold_cond_expr_cond (); 5299e4b17023SJohn Marino delete_unreachable_blocks_update_callgraph (&id); 5300e4b17023SJohn Marino if (id.dst_node->analyzed) 5301e4b17023SJohn Marino cgraph_rebuild_references (); 5302e4b17023SJohn Marino update_ssa (TODO_update_ssa); 5303e4b17023SJohn Marino 5304e4b17023SJohn Marino /* After partial cloning we need to rescale frequencies, so they are 5305e4b17023SJohn Marino within proper range in the cloned function. */ 5306e4b17023SJohn Marino if (new_entry) 5307e4b17023SJohn Marino { 5308e4b17023SJohn Marino struct cgraph_edge *e; 5309e4b17023SJohn Marino rebuild_frequencies (); 5310e4b17023SJohn Marino 5311e4b17023SJohn Marino new_version_node->count = ENTRY_BLOCK_PTR->count; 5312e4b17023SJohn Marino for (e = new_version_node->callees; e; e = e->next_callee) 5313e4b17023SJohn Marino { 5314e4b17023SJohn Marino basic_block bb = gimple_bb (e->call_stmt); 5315e4b17023SJohn Marino e->frequency = compute_call_stmt_bb_frequency (current_function_decl, 5316e4b17023SJohn Marino bb); 5317e4b17023SJohn Marino e->count = bb->count; 5318e4b17023SJohn Marino } 5319e4b17023SJohn Marino for (e = new_version_node->indirect_calls; e; e = e->next_callee) 5320e4b17023SJohn Marino { 5321e4b17023SJohn Marino basic_block bb = gimple_bb (e->call_stmt); 5322e4b17023SJohn Marino e->frequency = compute_call_stmt_bb_frequency (current_function_decl, 5323e4b17023SJohn Marino bb); 5324e4b17023SJohn Marino e->count = bb->count; 5325e4b17023SJohn Marino } 5326e4b17023SJohn Marino } 5327e4b17023SJohn Marino 5328e4b17023SJohn Marino free_dominance_info (CDI_DOMINATORS); 5329e4b17023SJohn Marino free_dominance_info (CDI_POST_DOMINATORS); 5330e4b17023SJohn Marino 5331e4b17023SJohn Marino gcc_assert (!id.debug_stmts); 5332e4b17023SJohn Marino VEC_free (gimple, heap, init_stmts); 5333e4b17023SJohn Marino pop_cfun (); 5334e4b17023SJohn Marino current_function_decl = old_current_function_decl; 5335e4b17023SJohn Marino gcc_assert (!current_function_decl 5336e4b17023SJohn Marino || DECL_STRUCT_FUNCTION (current_function_decl) == cfun); 5337e4b17023SJohn Marino return; 5338e4b17023SJohn Marino } 5339e4b17023SJohn Marino 5340e4b17023SJohn Marino /* EXP is CALL_EXPR present in a GENERIC expression tree. Try to integrate 5341e4b17023SJohn Marino the callee and return the inlined body on success. */ 5342e4b17023SJohn Marino 5343e4b17023SJohn Marino tree 5344e4b17023SJohn Marino maybe_inline_call_in_expr (tree exp) 5345e4b17023SJohn Marino { 5346e4b17023SJohn Marino tree fn = get_callee_fndecl (exp); 5347e4b17023SJohn Marino 5348e4b17023SJohn Marino /* We can only try to inline "const" functions. */ 5349e4b17023SJohn Marino if (fn && TREE_READONLY (fn) && DECL_SAVED_TREE (fn)) 5350e4b17023SJohn Marino { 5351e4b17023SJohn Marino struct pointer_map_t *decl_map = pointer_map_create (); 5352e4b17023SJohn Marino call_expr_arg_iterator iter; 5353e4b17023SJohn Marino copy_body_data id; 5354e4b17023SJohn Marino tree param, arg, t; 5355e4b17023SJohn Marino 5356e4b17023SJohn Marino /* Remap the parameters. */ 5357e4b17023SJohn Marino for (param = DECL_ARGUMENTS (fn), arg = first_call_expr_arg (exp, &iter); 5358e4b17023SJohn Marino param; 5359e4b17023SJohn Marino param = DECL_CHAIN (param), arg = next_call_expr_arg (&iter)) 5360e4b17023SJohn Marino *pointer_map_insert (decl_map, param) = arg; 5361e4b17023SJohn Marino 5362e4b17023SJohn Marino memset (&id, 0, sizeof (id)); 5363e4b17023SJohn Marino id.src_fn = fn; 5364e4b17023SJohn Marino id.dst_fn = current_function_decl; 5365e4b17023SJohn Marino id.src_cfun = DECL_STRUCT_FUNCTION (fn); 5366e4b17023SJohn Marino id.decl_map = decl_map; 5367e4b17023SJohn Marino 5368e4b17023SJohn Marino id.copy_decl = copy_decl_no_change; 5369e4b17023SJohn Marino id.transform_call_graph_edges = CB_CGE_DUPLICATE; 5370e4b17023SJohn Marino id.transform_new_cfg = false; 5371e4b17023SJohn Marino id.transform_return_to_modify = true; 5372e4b17023SJohn Marino id.transform_lang_insert_block = NULL; 5373e4b17023SJohn Marino 5374e4b17023SJohn Marino /* Make sure not to unshare trees behind the front-end's back 5375e4b17023SJohn Marino since front-end specific mechanisms may rely on sharing. */ 5376e4b17023SJohn Marino id.regimplify = false; 5377e4b17023SJohn Marino id.do_not_unshare = true; 5378e4b17023SJohn Marino 5379e4b17023SJohn Marino /* We're not inside any EH region. */ 5380e4b17023SJohn Marino id.eh_lp_nr = 0; 5381e4b17023SJohn Marino 5382e4b17023SJohn Marino t = copy_tree_body (&id); 5383e4b17023SJohn Marino pointer_map_destroy (decl_map); 5384e4b17023SJohn Marino 5385e4b17023SJohn Marino /* We can only return something suitable for use in a GENERIC 5386e4b17023SJohn Marino expression tree. */ 5387e4b17023SJohn Marino if (TREE_CODE (t) == MODIFY_EXPR) 5388e4b17023SJohn Marino return TREE_OPERAND (t, 1); 5389e4b17023SJohn Marino } 5390e4b17023SJohn Marino 5391e4b17023SJohn Marino return NULL_TREE; 5392e4b17023SJohn Marino } 5393e4b17023SJohn Marino 5394e4b17023SJohn Marino /* Duplicate a type, fields and all. */ 5395e4b17023SJohn Marino 5396e4b17023SJohn Marino tree 5397e4b17023SJohn Marino build_duplicate_type (tree type) 5398e4b17023SJohn Marino { 5399e4b17023SJohn Marino struct copy_body_data id; 5400e4b17023SJohn Marino 5401e4b17023SJohn Marino memset (&id, 0, sizeof (id)); 5402e4b17023SJohn Marino id.src_fn = current_function_decl; 5403e4b17023SJohn Marino id.dst_fn = current_function_decl; 5404e4b17023SJohn Marino id.src_cfun = cfun; 5405e4b17023SJohn Marino id.decl_map = pointer_map_create (); 5406e4b17023SJohn Marino id.debug_map = NULL; 5407e4b17023SJohn Marino id.copy_decl = copy_decl_no_change; 5408e4b17023SJohn Marino 5409e4b17023SJohn Marino type = remap_type_1 (type, &id); 5410e4b17023SJohn Marino 5411e4b17023SJohn Marino pointer_map_destroy (id.decl_map); 5412e4b17023SJohn Marino if (id.debug_map) 5413e4b17023SJohn Marino pointer_map_destroy (id.debug_map); 5414e4b17023SJohn Marino 5415e4b17023SJohn Marino TYPE_CANONICAL (type) = type; 5416e4b17023SJohn Marino 5417e4b17023SJohn Marino return type; 5418e4b17023SJohn Marino } 5419