xref: /dragonfly/contrib/gcc-4.7/gcc/tree-inline.c (revision 5ce9237c)
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
insert_decl_map(copy_body_data * id,tree key,tree value)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
insert_debug_decl_map(copy_body_data * id,tree key,tree value)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
remap_ssa_name(tree name,copy_body_data * id)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
remap_decl(tree decl,copy_body_data * id)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
remap_type_1(tree type,copy_body_data * id)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
remap_type(tree type,copy_body_data * id)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
remapped_type(tree type,copy_body_data * id)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
can_be_nonlocal(tree decl,copy_body_data * id)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
remap_decls(tree decls,VEC (tree,gc)** nonlocalized_list,copy_body_data * id)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
remap_block(tree * block,copy_body_data * id)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
remap_blocks(tree block,copy_body_data * id)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
copy_statement_list(tree * tp)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
copy_bind_expr(tree * tp,int * walk_subtrees,copy_body_data * id)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
remap_gimple_seq(gimple_seq body,copy_body_data * id)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
copy_gimple_bind(gimple stmt,copy_body_data * id)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
remap_gimple_op_r(tree * tp,int * walk_subtrees,void * data)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
copy_tree_body_r(tree * tp,int * walk_subtrees,void * data)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
remap_eh_region_nr(int old_nr,copy_body_data * id)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
remap_eh_region_tree_nr(tree old_t_nr,copy_body_data * id)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
remap_gimple_stmt(gimple stmt,copy_body_data * id)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
copy_bb(copy_body_data * id,basic_block bb,int frequency_scale,gcov_type count_scale)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 (&copy_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 (&copy_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 (&copy_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 (&copy_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
update_ssa_across_abnormal_edges(basic_block bb,basic_block ret_bb,bool can_throw,bool nonlocal_goto)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
copy_edges_for_bb(basic_block bb,gcov_type count_scale,basic_block ret_bb)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
copy_phis_for_bb(basic_block bb,copy_body_data * id)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
remap_decl_1(tree decl,void * data)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
initialize_cfun(tree new_fndecl,tree callee_fndecl,gcov_type count)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
maybe_move_debug_stmts_to_successors(copy_body_data * id,basic_block new_bb)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
copy_cfg_body(copy_body_data * id,gcov_type count,int frequency_scale,basic_block entry_block_map,basic_block exit_block_map,bitmap blocks_to_copy,basic_block new_entry)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
copy_debug_stmt(gimple stmt,copy_body_data * id)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
copy_debug_stmts(copy_body_data * id)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
copy_tree_body(copy_body_data * id)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
copy_body(copy_body_data * id,gcov_type count,int frequency_scale,basic_block entry_block_map,basic_block exit_block_map,bitmap blocks_to_copy,basic_block new_entry)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
self_inlining_addr_expr(tree value,tree fn)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
insert_init_debug_bind(copy_body_data * id,basic_block bb,tree var,tree value,gimple base_stmt)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
insert_init_stmt(copy_body_data * id,basic_block bb,gimple init_stmt)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
setup_one_parameter(copy_body_data * id,tree p,tree value,tree fn,basic_block bb,tree * vars)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
initialize_inlined_parameters(copy_body_data * id,gimple stmt,tree fn,basic_block bb)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
declare_return_variable(copy_body_data * id,tree return_slot,tree modify_dest,basic_block entry_bb)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
has_label_address_in_static_1(tree * nodep,int * walk_subtrees,void * fnp)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 *
copy_forbidden(struct function * fun,tree fndecl)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
inline_forbidden_p_stmt(gimple_stmt_iterator * gsi,bool * handled_ops_p,struct walk_stmt_info * wip)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
inline_forbidden_p(tree fndecl)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
tree_inlinable_function_p(tree fn)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
estimate_move_cost(tree type)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
estimate_operator_cost(enum tree_code code,eni_weights * weights,tree op1 ATTRIBUTE_UNUSED,tree op2)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
estimate_num_insns_seq(gimple_seq stmts,eni_weights * weights)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
estimate_num_insns(gimple stmt,eni_weights * weights)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
estimate_num_insns_fn(tree fndecl,eni_weights * weights)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
init_inline_once(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
count_insns_seq(gimple_seq seq,eni_weights * weights)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
prepend_lexical_block(tree current_block,tree new_block)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
add_local_variables(struct function * callee,struct function * caller,copy_body_data * id,bool check_var_ann)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
expand_call_inline(basic_block bb,gimple stmt,copy_body_data * id)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 	       && reason != CIF_UNLIKELY_CALL)
3870e4b17023SJohn Marino 	{
3871e4b17023SJohn Marino 	  warning (OPT_Winline, "inlining failed in call to %q+F: %s",
3872e4b17023SJohn Marino 		   fn, _(cgraph_inline_failed_string (reason)));
3873e4b17023SJohn Marino 	  warning (OPT_Winline, "called from here");
3874e4b17023SJohn Marino 	}
3875e4b17023SJohn Marino       goto egress;
3876e4b17023SJohn Marino     }
3877e4b17023SJohn Marino   fn = cg_edge->callee->decl;
3878e4b17023SJohn Marino 
3879e4b17023SJohn Marino #ifdef ENABLE_CHECKING
3880e4b17023SJohn Marino   if (cg_edge->callee->decl != id->dst_node->decl)
3881e4b17023SJohn Marino     verify_cgraph_node (cg_edge->callee);
3882e4b17023SJohn Marino #endif
3883e4b17023SJohn Marino 
3884e4b17023SJohn Marino   /* We will be inlining this callee.  */
3885e4b17023SJohn Marino   id->eh_lp_nr = lookup_stmt_eh_lp (stmt);
3886e4b17023SJohn Marino 
3887e4b17023SJohn Marino   /* Update the callers EH personality.  */
3888e4b17023SJohn Marino   if (DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl))
3889e4b17023SJohn Marino     DECL_FUNCTION_PERSONALITY (cg_edge->caller->decl)
3890e4b17023SJohn Marino       = DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl);
3891e4b17023SJohn Marino 
3892e4b17023SJohn Marino   /* Split the block holding the GIMPLE_CALL.  */
3893e4b17023SJohn Marino   e = split_block (bb, stmt);
3894e4b17023SJohn Marino   bb = e->src;
3895e4b17023SJohn Marino   return_block = e->dest;
3896e4b17023SJohn Marino   remove_edge (e);
3897e4b17023SJohn Marino 
3898e4b17023SJohn Marino   /* split_block splits after the statement; work around this by
3899e4b17023SJohn Marino      moving the call into the second block manually.  Not pretty,
3900e4b17023SJohn Marino      but seems easier than doing the CFG manipulation by hand
3901e4b17023SJohn Marino      when the GIMPLE_CALL is in the last statement of BB.  */
3902e4b17023SJohn Marino   stmt_gsi = gsi_last_bb (bb);
3903e4b17023SJohn Marino   gsi_remove (&stmt_gsi, false);
3904e4b17023SJohn Marino 
3905e4b17023SJohn Marino   /* If the GIMPLE_CALL was in the last statement of BB, it may have
3906e4b17023SJohn Marino      been the source of abnormal edges.  In this case, schedule
3907e4b17023SJohn Marino      the removal of dead abnormal edges.  */
3908e4b17023SJohn Marino   gsi = gsi_start_bb (return_block);
3909e4b17023SJohn Marino   if (gsi_end_p (gsi))
3910e4b17023SJohn Marino     {
3911e4b17023SJohn Marino       gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
3912e4b17023SJohn Marino       purge_dead_abnormal_edges = true;
3913e4b17023SJohn Marino     }
3914e4b17023SJohn Marino   else
3915e4b17023SJohn Marino     {
3916e4b17023SJohn Marino       gsi_insert_before (&gsi, stmt, GSI_NEW_STMT);
3917e4b17023SJohn Marino       purge_dead_abnormal_edges = false;
3918e4b17023SJohn Marino     }
3919e4b17023SJohn Marino 
3920e4b17023SJohn Marino   stmt_gsi = gsi_start_bb (return_block);
3921e4b17023SJohn Marino 
3922e4b17023SJohn Marino   /* Build a block containing code to initialize the arguments, the
3923e4b17023SJohn Marino      actual inline expansion of the body, and a label for the return
3924e4b17023SJohn Marino      statements within the function to jump to.  The type of the
3925e4b17023SJohn Marino      statement expression is the return type of the function call.  */
3926e4b17023SJohn Marino   id->block = make_node (BLOCK);
3927e4b17023SJohn Marino   BLOCK_ABSTRACT_ORIGIN (id->block) = fn;
3928e4b17023SJohn Marino   BLOCK_SOURCE_LOCATION (id->block) = input_location;
3929e4b17023SJohn Marino   prepend_lexical_block (gimple_block (stmt), id->block);
3930e4b17023SJohn Marino 
3931e4b17023SJohn Marino   /* Local declarations will be replaced by their equivalents in this
3932e4b17023SJohn Marino      map.  */
3933e4b17023SJohn Marino   st = id->decl_map;
3934e4b17023SJohn Marino   id->decl_map = pointer_map_create ();
3935e4b17023SJohn Marino   dst = id->debug_map;
3936e4b17023SJohn Marino   id->debug_map = NULL;
3937e4b17023SJohn Marino 
3938e4b17023SJohn Marino   /* Record the function we are about to inline.  */
3939e4b17023SJohn Marino   id->src_fn = fn;
3940e4b17023SJohn Marino   id->src_node = cg_edge->callee;
3941e4b17023SJohn Marino   id->src_cfun = DECL_STRUCT_FUNCTION (fn);
3942e4b17023SJohn Marino   id->gimple_call = stmt;
3943e4b17023SJohn Marino 
3944e4b17023SJohn Marino   gcc_assert (!id->src_cfun->after_inlining);
3945e4b17023SJohn Marino 
3946e4b17023SJohn Marino   id->entry_bb = bb;
3947e4b17023SJohn Marino   if (lookup_attribute ("cold", DECL_ATTRIBUTES (fn)))
3948e4b17023SJohn Marino     {
3949e4b17023SJohn Marino       gimple_stmt_iterator si = gsi_last_bb (bb);
3950e4b17023SJohn Marino       gsi_insert_after (&si, gimple_build_predict (PRED_COLD_FUNCTION,
3951e4b17023SJohn Marino       						   NOT_TAKEN),
3952e4b17023SJohn Marino 			GSI_NEW_STMT);
3953e4b17023SJohn Marino     }
3954e4b17023SJohn Marino   initialize_inlined_parameters (id, stmt, fn, bb);
3955e4b17023SJohn Marino 
3956e4b17023SJohn Marino   if (DECL_INITIAL (fn))
3957e4b17023SJohn Marino     prepend_lexical_block (id->block, remap_blocks (DECL_INITIAL (fn), id));
3958e4b17023SJohn Marino 
3959e4b17023SJohn Marino   /* Return statements in the function body will be replaced by jumps
3960e4b17023SJohn Marino      to the RET_LABEL.  */
3961e4b17023SJohn Marino   gcc_assert (DECL_INITIAL (fn));
3962e4b17023SJohn Marino   gcc_assert (TREE_CODE (DECL_INITIAL (fn)) == BLOCK);
3963e4b17023SJohn Marino 
3964e4b17023SJohn Marino   /* Find the LHS to which the result of this call is assigned.  */
3965e4b17023SJohn Marino   return_slot = NULL;
3966e4b17023SJohn Marino   if (gimple_call_lhs (stmt))
3967e4b17023SJohn Marino     {
3968e4b17023SJohn Marino       modify_dest = gimple_call_lhs (stmt);
3969e4b17023SJohn Marino 
3970e4b17023SJohn Marino       /* The function which we are inlining might not return a value,
3971e4b17023SJohn Marino 	 in which case we should issue a warning that the function
3972e4b17023SJohn Marino 	 does not return a value.  In that case the optimizers will
3973e4b17023SJohn Marino 	 see that the variable to which the value is assigned was not
3974e4b17023SJohn Marino 	 initialized.  We do not want to issue a warning about that
3975e4b17023SJohn Marino 	 uninitialized variable.  */
3976e4b17023SJohn Marino       if (DECL_P (modify_dest))
3977e4b17023SJohn Marino 	TREE_NO_WARNING (modify_dest) = 1;
3978e4b17023SJohn Marino 
3979e4b17023SJohn Marino       if (gimple_call_return_slot_opt_p (stmt))
3980e4b17023SJohn Marino 	{
3981e4b17023SJohn Marino 	  return_slot = modify_dest;
3982e4b17023SJohn Marino 	  modify_dest = NULL;
3983e4b17023SJohn Marino 	}
3984e4b17023SJohn Marino     }
3985e4b17023SJohn Marino   else
3986e4b17023SJohn Marino     modify_dest = NULL;
3987e4b17023SJohn Marino 
3988e4b17023SJohn Marino   /* If we are inlining a call to the C++ operator new, we don't want
3989e4b17023SJohn Marino      to use type based alias analysis on the return value.  Otherwise
3990e4b17023SJohn Marino      we may get confused if the compiler sees that the inlined new
3991e4b17023SJohn Marino      function returns a pointer which was just deleted.  See bug
3992e4b17023SJohn Marino      33407.  */
3993e4b17023SJohn Marino   if (DECL_IS_OPERATOR_NEW (fn))
3994e4b17023SJohn Marino     {
3995e4b17023SJohn Marino       return_slot = NULL;
3996e4b17023SJohn Marino       modify_dest = NULL;
3997e4b17023SJohn Marino     }
3998e4b17023SJohn Marino 
3999e4b17023SJohn Marino   /* Declare the return variable for the function.  */
4000e4b17023SJohn Marino   use_retvar = declare_return_variable (id, return_slot, modify_dest, bb);
4001e4b17023SJohn Marino 
4002e4b17023SJohn Marino   /* Add local vars in this inlined callee to caller.  */
4003e4b17023SJohn Marino   add_local_variables (id->src_cfun, cfun, id, true);
4004e4b17023SJohn Marino 
4005e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
4006e4b17023SJohn Marino     {
4007e4b17023SJohn Marino       fprintf (dump_file, "Inlining ");
4008e4b17023SJohn Marino       print_generic_expr (dump_file, id->src_fn, 0);
4009e4b17023SJohn Marino       fprintf (dump_file, " to ");
4010e4b17023SJohn Marino       print_generic_expr (dump_file, id->dst_fn, 0);
4011e4b17023SJohn Marino       fprintf (dump_file, " with frequency %i\n", cg_edge->frequency);
4012e4b17023SJohn Marino     }
4013e4b17023SJohn Marino 
4014e4b17023SJohn Marino   /* This is it.  Duplicate the callee body.  Assume callee is
4015e4b17023SJohn Marino      pre-gimplified.  Note that we must not alter the caller
4016e4b17023SJohn Marino      function in any way before this point, as this CALL_EXPR may be
4017e4b17023SJohn Marino      a self-referential call; if we're calling ourselves, we need to
4018e4b17023SJohn Marino      duplicate our body before altering anything.  */
4019e4b17023SJohn Marino   copy_body (id, bb->count,
4020e4b17023SJohn Marino   	     cg_edge->frequency * REG_BR_PROB_BASE / CGRAPH_FREQ_BASE,
4021e4b17023SJohn Marino 	     bb, return_block, NULL, NULL);
4022e4b17023SJohn Marino 
4023e4b17023SJohn Marino   /* Reset the escaped solution.  */
4024e4b17023SJohn Marino   if (cfun->gimple_df)
4025e4b17023SJohn Marino     pt_solution_reset (&cfun->gimple_df->escaped);
4026e4b17023SJohn Marino 
4027e4b17023SJohn Marino   /* Clean up.  */
4028e4b17023SJohn Marino   if (id->debug_map)
4029e4b17023SJohn Marino     {
4030e4b17023SJohn Marino       pointer_map_destroy (id->debug_map);
4031e4b17023SJohn Marino       id->debug_map = dst;
4032e4b17023SJohn Marino     }
4033e4b17023SJohn Marino   pointer_map_destroy (id->decl_map);
4034e4b17023SJohn Marino   id->decl_map = st;
4035e4b17023SJohn Marino 
4036e4b17023SJohn Marino   /* Unlink the calls virtual operands before replacing it.  */
4037e4b17023SJohn Marino   unlink_stmt_vdef (stmt);
4038e4b17023SJohn Marino 
4039e4b17023SJohn Marino   /* If the inlined function returns a result that we care about,
4040e4b17023SJohn Marino      substitute the GIMPLE_CALL with an assignment of the return
4041e4b17023SJohn Marino      variable to the LHS of the call.  That is, if STMT was
4042e4b17023SJohn Marino      'a = foo (...)', substitute the call with 'a = USE_RETVAR'.  */
4043e4b17023SJohn Marino   if (use_retvar && gimple_call_lhs (stmt))
4044e4b17023SJohn Marino     {
4045e4b17023SJohn Marino       gimple old_stmt = stmt;
4046e4b17023SJohn Marino       stmt = gimple_build_assign (gimple_call_lhs (stmt), use_retvar);
4047e4b17023SJohn Marino       gsi_replace (&stmt_gsi, stmt, false);
4048e4b17023SJohn Marino       if (gimple_in_ssa_p (cfun))
4049e4b17023SJohn Marino 	mark_symbols_for_renaming (stmt);
4050e4b17023SJohn Marino       maybe_clean_or_replace_eh_stmt (old_stmt, stmt);
4051e4b17023SJohn Marino     }
4052e4b17023SJohn Marino   else
4053e4b17023SJohn Marino     {
4054e4b17023SJohn Marino       /* Handle the case of inlining a function with no return
4055e4b17023SJohn Marino 	 statement, which causes the return value to become undefined.  */
4056e4b17023SJohn Marino       if (gimple_call_lhs (stmt)
4057e4b17023SJohn Marino 	  && TREE_CODE (gimple_call_lhs (stmt)) == SSA_NAME)
4058e4b17023SJohn Marino 	{
4059e4b17023SJohn Marino 	  tree name = gimple_call_lhs (stmt);
4060e4b17023SJohn Marino 	  tree var = SSA_NAME_VAR (name);
4061e4b17023SJohn Marino 	  tree def = gimple_default_def (cfun, var);
4062e4b17023SJohn Marino 
4063e4b17023SJohn Marino 	  if (def)
4064e4b17023SJohn Marino 	    {
4065e4b17023SJohn Marino 	      /* If the variable is used undefined, make this name
4066e4b17023SJohn Marino 		 undefined via a move.  */
4067e4b17023SJohn Marino 	      stmt = gimple_build_assign (gimple_call_lhs (stmt), def);
4068e4b17023SJohn Marino 	      gsi_replace (&stmt_gsi, stmt, true);
4069e4b17023SJohn Marino 	    }
4070e4b17023SJohn Marino 	  else
4071e4b17023SJohn Marino 	    {
4072e4b17023SJohn Marino 	      /* Otherwise make this variable undefined.  */
4073e4b17023SJohn Marino 	      gsi_remove (&stmt_gsi, true);
4074e4b17023SJohn Marino 	      set_default_def (var, name);
4075e4b17023SJohn Marino 	      SSA_NAME_DEF_STMT (name) = gimple_build_nop ();
4076e4b17023SJohn Marino 	    }
4077e4b17023SJohn Marino 	}
4078e4b17023SJohn Marino       else
4079e4b17023SJohn Marino         gsi_remove (&stmt_gsi, true);
4080e4b17023SJohn Marino     }
4081e4b17023SJohn Marino 
4082e4b17023SJohn Marino   if (purge_dead_abnormal_edges)
4083e4b17023SJohn Marino     {
4084e4b17023SJohn Marino       gimple_purge_dead_eh_edges (return_block);
4085e4b17023SJohn Marino       gimple_purge_dead_abnormal_call_edges (return_block);
4086e4b17023SJohn Marino     }
4087e4b17023SJohn Marino 
4088e4b17023SJohn Marino   /* If the value of the new expression is ignored, that's OK.  We
4089e4b17023SJohn Marino      don't warn about this for CALL_EXPRs, so we shouldn't warn about
4090e4b17023SJohn Marino      the equivalent inlined version either.  */
4091e4b17023SJohn Marino   if (is_gimple_assign (stmt))
4092e4b17023SJohn Marino     {
4093e4b17023SJohn Marino       gcc_assert (gimple_assign_single_p (stmt)
4094e4b17023SJohn Marino 		  || CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt)));
4095e4b17023SJohn Marino       TREE_USED (gimple_assign_rhs1 (stmt)) = 1;
4096e4b17023SJohn Marino     }
4097e4b17023SJohn Marino 
4098e4b17023SJohn Marino   /* Output the inlining info for this abstract function, since it has been
4099e4b17023SJohn Marino      inlined.  If we don't do this now, we can lose the information about the
4100e4b17023SJohn Marino      variables in the function when the blocks get blown away as soon as we
4101e4b17023SJohn Marino      remove the cgraph node.  */
4102e4b17023SJohn Marino   (*debug_hooks->outlining_inline_function) (cg_edge->callee->decl);
4103e4b17023SJohn Marino 
4104e4b17023SJohn Marino   /* Update callgraph if needed.  */
4105e4b17023SJohn Marino   cgraph_remove_node (cg_edge->callee);
4106e4b17023SJohn Marino 
4107e4b17023SJohn Marino   id->block = NULL_TREE;
4108e4b17023SJohn Marino   successfully_inlined = TRUE;
4109e4b17023SJohn Marino 
4110e4b17023SJohn Marino  egress:
4111e4b17023SJohn Marino   input_location = saved_location;
4112e4b17023SJohn Marino   return successfully_inlined;
4113e4b17023SJohn Marino }
4114e4b17023SJohn Marino 
4115e4b17023SJohn Marino /* Expand call statements reachable from STMT_P.
4116e4b17023SJohn Marino    We can only have CALL_EXPRs as the "toplevel" tree code or nested
4117e4b17023SJohn Marino    in a MODIFY_EXPR.  */
4118e4b17023SJohn Marino 
4119e4b17023SJohn Marino static bool
gimple_expand_calls_inline(basic_block bb,copy_body_data * id)4120e4b17023SJohn Marino gimple_expand_calls_inline (basic_block bb, copy_body_data *id)
4121e4b17023SJohn Marino {
4122e4b17023SJohn Marino   gimple_stmt_iterator gsi;
4123e4b17023SJohn Marino 
4124e4b17023SJohn Marino   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4125e4b17023SJohn Marino     {
4126e4b17023SJohn Marino       gimple stmt = gsi_stmt (gsi);
4127e4b17023SJohn Marino 
4128e4b17023SJohn Marino       if (is_gimple_call (stmt)
4129e4b17023SJohn Marino 	  && expand_call_inline (bb, stmt, id))
4130e4b17023SJohn Marino 	return true;
4131e4b17023SJohn Marino     }
4132e4b17023SJohn Marino 
4133e4b17023SJohn Marino   return false;
4134e4b17023SJohn Marino }
4135e4b17023SJohn Marino 
4136e4b17023SJohn Marino 
4137e4b17023SJohn Marino /* Walk all basic blocks created after FIRST and try to fold every statement
4138e4b17023SJohn Marino    in the STATEMENTS pointer set.  */
4139e4b17023SJohn Marino 
4140e4b17023SJohn Marino static void
fold_marked_statements(int first,struct pointer_set_t * statements)4141e4b17023SJohn Marino fold_marked_statements (int first, struct pointer_set_t *statements)
4142e4b17023SJohn Marino {
4143e4b17023SJohn Marino   for (; first < n_basic_blocks; first++)
4144e4b17023SJohn Marino     if (BASIC_BLOCK (first))
4145e4b17023SJohn Marino       {
4146e4b17023SJohn Marino         gimple_stmt_iterator gsi;
4147e4b17023SJohn Marino 
4148e4b17023SJohn Marino 	for (gsi = gsi_start_bb (BASIC_BLOCK (first));
4149e4b17023SJohn Marino 	     !gsi_end_p (gsi);
4150e4b17023SJohn Marino 	     gsi_next (&gsi))
4151e4b17023SJohn Marino 	  if (pointer_set_contains (statements, gsi_stmt (gsi)))
4152e4b17023SJohn Marino 	    {
4153e4b17023SJohn Marino 	      gimple old_stmt = gsi_stmt (gsi);
4154e4b17023SJohn Marino 	      tree old_decl = is_gimple_call (old_stmt) ? gimple_call_fndecl (old_stmt) : 0;
4155e4b17023SJohn Marino 
4156e4b17023SJohn Marino 	      if (old_decl && DECL_BUILT_IN (old_decl))
4157e4b17023SJohn Marino 		{
4158e4b17023SJohn Marino 		  /* Folding builtins can create multiple instructions,
4159e4b17023SJohn Marino 		     we need to look at all of them.  */
4160e4b17023SJohn Marino 		  gimple_stmt_iterator i2 = gsi;
4161e4b17023SJohn Marino 		  gsi_prev (&i2);
4162e4b17023SJohn Marino 		  if (fold_stmt (&gsi))
4163e4b17023SJohn Marino 		    {
4164e4b17023SJohn Marino 		      gimple new_stmt;
4165e4b17023SJohn Marino 		      /* If a builtin at the end of a bb folded into nothing,
4166e4b17023SJohn Marino 			 the following loop won't work.  */
4167e4b17023SJohn Marino 		      if (gsi_end_p (gsi))
4168e4b17023SJohn Marino 			{
4169e4b17023SJohn Marino 			  cgraph_update_edges_for_call_stmt (old_stmt,
4170e4b17023SJohn Marino 							     old_decl, NULL);
4171e4b17023SJohn Marino 			  break;
4172e4b17023SJohn Marino 			}
4173e4b17023SJohn Marino 		      if (gsi_end_p (i2))
4174e4b17023SJohn Marino 			i2 = gsi_start_bb (BASIC_BLOCK (first));
4175e4b17023SJohn Marino 		      else
4176e4b17023SJohn Marino 			gsi_next (&i2);
4177e4b17023SJohn Marino 		      while (1)
4178e4b17023SJohn Marino 			{
4179e4b17023SJohn Marino 			  new_stmt = gsi_stmt (i2);
4180e4b17023SJohn Marino 			  update_stmt (new_stmt);
4181e4b17023SJohn Marino 			  cgraph_update_edges_for_call_stmt (old_stmt, old_decl,
4182e4b17023SJohn Marino 							     new_stmt);
4183e4b17023SJohn Marino 
4184e4b17023SJohn Marino 			  if (new_stmt == gsi_stmt (gsi))
4185e4b17023SJohn Marino 			    {
4186e4b17023SJohn Marino 			      /* It is okay to check only for the very last
4187e4b17023SJohn Marino 				 of these statements.  If it is a throwing
4188e4b17023SJohn Marino 				 statement nothing will change.  If it isn't
4189e4b17023SJohn Marino 				 this can remove EH edges.  If that weren't
4190e4b17023SJohn Marino 				 correct then because some intermediate stmts
4191e4b17023SJohn Marino 				 throw, but not the last one.  That would mean
4192e4b17023SJohn Marino 				 we'd have to split the block, which we can't
4193e4b17023SJohn Marino 				 here and we'd loose anyway.  And as builtins
4194e4b17023SJohn Marino 				 probably never throw, this all
4195e4b17023SJohn Marino 				 is mood anyway.  */
4196e4b17023SJohn Marino 			      if (maybe_clean_or_replace_eh_stmt (old_stmt,
4197e4b17023SJohn Marino 								  new_stmt))
4198e4b17023SJohn Marino 				gimple_purge_dead_eh_edges (BASIC_BLOCK (first));
4199e4b17023SJohn Marino 			      break;
4200e4b17023SJohn Marino 			    }
4201e4b17023SJohn Marino 			  gsi_next (&i2);
4202e4b17023SJohn Marino 			}
4203e4b17023SJohn Marino 		    }
4204e4b17023SJohn Marino 		}
4205e4b17023SJohn Marino 	      else if (fold_stmt (&gsi))
4206e4b17023SJohn Marino 		{
4207e4b17023SJohn Marino 		  /* Re-read the statement from GSI as fold_stmt() may
4208e4b17023SJohn Marino 		     have changed it.  */
4209e4b17023SJohn Marino 		  gimple new_stmt = gsi_stmt (gsi);
4210e4b17023SJohn Marino 		  update_stmt (new_stmt);
4211e4b17023SJohn Marino 
4212e4b17023SJohn Marino 		  if (is_gimple_call (old_stmt)
4213e4b17023SJohn Marino 		      || is_gimple_call (new_stmt))
4214e4b17023SJohn Marino 		    cgraph_update_edges_for_call_stmt (old_stmt, old_decl,
4215e4b17023SJohn Marino 						       new_stmt);
4216e4b17023SJohn Marino 
4217e4b17023SJohn Marino 		  if (maybe_clean_or_replace_eh_stmt (old_stmt, new_stmt))
4218e4b17023SJohn Marino 		    gimple_purge_dead_eh_edges (BASIC_BLOCK (first));
4219e4b17023SJohn Marino 		}
4220e4b17023SJohn Marino 	    }
4221e4b17023SJohn Marino       }
4222e4b17023SJohn Marino }
4223e4b17023SJohn Marino 
4224e4b17023SJohn Marino /* Return true if BB has at least one abnormal outgoing edge.  */
4225e4b17023SJohn Marino 
4226e4b17023SJohn Marino static inline bool
has_abnormal_outgoing_edge_p(basic_block bb)4227e4b17023SJohn Marino has_abnormal_outgoing_edge_p (basic_block bb)
4228e4b17023SJohn Marino {
4229e4b17023SJohn Marino   edge e;
4230e4b17023SJohn Marino   edge_iterator ei;
4231e4b17023SJohn Marino 
4232e4b17023SJohn Marino   FOR_EACH_EDGE (e, ei, bb->succs)
4233e4b17023SJohn Marino     if (e->flags & EDGE_ABNORMAL)
4234e4b17023SJohn Marino       return true;
4235e4b17023SJohn Marino 
4236e4b17023SJohn Marino   return false;
4237e4b17023SJohn Marino }
4238e4b17023SJohn Marino 
4239e4b17023SJohn Marino /* Expand calls to inline functions in the body of FN.  */
4240e4b17023SJohn Marino 
4241e4b17023SJohn Marino unsigned int
optimize_inline_calls(tree fn)4242e4b17023SJohn Marino optimize_inline_calls (tree fn)
4243e4b17023SJohn Marino {
4244e4b17023SJohn Marino   copy_body_data id;
4245e4b17023SJohn Marino   basic_block bb;
4246e4b17023SJohn Marino   int last = n_basic_blocks;
4247e4b17023SJohn Marino   struct gimplify_ctx gctx;
4248e4b17023SJohn Marino   bool inlined_p = false;
4249e4b17023SJohn Marino 
4250e4b17023SJohn Marino   /* Clear out ID.  */
4251e4b17023SJohn Marino   memset (&id, 0, sizeof (id));
4252e4b17023SJohn Marino 
4253e4b17023SJohn Marino   id.src_node = id.dst_node = cgraph_get_node (fn);
4254e4b17023SJohn Marino   gcc_assert (id.dst_node->analyzed);
4255e4b17023SJohn Marino   id.dst_fn = fn;
4256e4b17023SJohn Marino   /* Or any functions that aren't finished yet.  */
4257e4b17023SJohn Marino   if (current_function_decl)
4258e4b17023SJohn Marino     id.dst_fn = current_function_decl;
4259e4b17023SJohn Marino 
4260e4b17023SJohn Marino   id.copy_decl = copy_decl_maybe_to_var;
4261e4b17023SJohn Marino   id.transform_call_graph_edges = CB_CGE_DUPLICATE;
4262e4b17023SJohn Marino   id.transform_new_cfg = false;
4263e4b17023SJohn Marino   id.transform_return_to_modify = true;
4264e4b17023SJohn Marino   id.transform_lang_insert_block = NULL;
4265e4b17023SJohn Marino   id.statements_to_fold = pointer_set_create ();
4266e4b17023SJohn Marino 
4267e4b17023SJohn Marino   push_gimplify_context (&gctx);
4268e4b17023SJohn Marino 
4269e4b17023SJohn Marino   /* We make no attempts to keep dominance info up-to-date.  */
4270e4b17023SJohn Marino   free_dominance_info (CDI_DOMINATORS);
4271e4b17023SJohn Marino   free_dominance_info (CDI_POST_DOMINATORS);
4272e4b17023SJohn Marino 
4273e4b17023SJohn Marino   /* Register specific gimple functions.  */
4274e4b17023SJohn Marino   gimple_register_cfg_hooks ();
4275e4b17023SJohn Marino 
4276e4b17023SJohn Marino   /* Reach the trees by walking over the CFG, and note the
4277e4b17023SJohn Marino      enclosing basic-blocks in the call edges.  */
4278e4b17023SJohn Marino   /* We walk the blocks going forward, because inlined function bodies
4279e4b17023SJohn Marino      will split id->current_basic_block, and the new blocks will
4280e4b17023SJohn Marino      follow it; we'll trudge through them, processing their CALL_EXPRs
4281e4b17023SJohn Marino      along the way.  */
4282e4b17023SJohn Marino   FOR_EACH_BB (bb)
4283e4b17023SJohn Marino     inlined_p |= gimple_expand_calls_inline (bb, &id);
4284e4b17023SJohn Marino 
4285e4b17023SJohn Marino   pop_gimplify_context (NULL);
4286e4b17023SJohn Marino 
4287e4b17023SJohn Marino #ifdef ENABLE_CHECKING
4288e4b17023SJohn Marino     {
4289e4b17023SJohn Marino       struct cgraph_edge *e;
4290e4b17023SJohn Marino 
4291e4b17023SJohn Marino       verify_cgraph_node (id.dst_node);
4292e4b17023SJohn Marino 
4293e4b17023SJohn Marino       /* Double check that we inlined everything we are supposed to inline.  */
4294e4b17023SJohn Marino       for (e = id.dst_node->callees; e; e = e->next_callee)
4295e4b17023SJohn Marino 	gcc_assert (e->inline_failed);
4296e4b17023SJohn Marino     }
4297e4b17023SJohn Marino #endif
4298e4b17023SJohn Marino 
4299e4b17023SJohn Marino   /* Fold queued statements.  */
4300e4b17023SJohn Marino   fold_marked_statements (last, id.statements_to_fold);
4301e4b17023SJohn Marino   pointer_set_destroy (id.statements_to_fold);
4302e4b17023SJohn Marino 
4303e4b17023SJohn Marino   gcc_assert (!id.debug_stmts);
4304e4b17023SJohn Marino 
4305e4b17023SJohn Marino   /* If we didn't inline into the function there is nothing to do.  */
4306e4b17023SJohn Marino   if (!inlined_p)
4307e4b17023SJohn Marino     return 0;
4308e4b17023SJohn Marino 
4309e4b17023SJohn Marino   /* Renumber the lexical scoping (non-code) blocks consecutively.  */
4310e4b17023SJohn Marino   number_blocks (fn);
4311e4b17023SJohn Marino 
4312e4b17023SJohn Marino   delete_unreachable_blocks_update_callgraph (&id);
4313e4b17023SJohn Marino #ifdef ENABLE_CHECKING
4314e4b17023SJohn Marino   verify_cgraph_node (id.dst_node);
4315e4b17023SJohn Marino #endif
4316e4b17023SJohn Marino 
4317e4b17023SJohn Marino   /* It would be nice to check SSA/CFG/statement consistency here, but it is
4318e4b17023SJohn Marino      not possible yet - the IPA passes might make various functions to not
4319e4b17023SJohn Marino      throw and they don't care to proactively update local EH info.  This is
4320e4b17023SJohn Marino      done later in fixup_cfg pass that also execute the verification.  */
4321e4b17023SJohn Marino   return (TODO_update_ssa
4322e4b17023SJohn Marino 	  | TODO_cleanup_cfg
4323e4b17023SJohn Marino 	  | (gimple_in_ssa_p (cfun) ? TODO_remove_unused_locals : 0)
4324e4b17023SJohn Marino 	  | (gimple_in_ssa_p (cfun) ? TODO_update_address_taken : 0)
4325e4b17023SJohn Marino 	  | (profile_status != PROFILE_ABSENT ? TODO_rebuild_frequencies : 0));
4326e4b17023SJohn Marino }
4327e4b17023SJohn Marino 
4328e4b17023SJohn Marino /* Passed to walk_tree.  Copies the node pointed to, if appropriate.  */
4329e4b17023SJohn Marino 
4330e4b17023SJohn Marino tree
copy_tree_r(tree * tp,int * walk_subtrees,void * data ATTRIBUTE_UNUSED)4331e4b17023SJohn Marino copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
4332e4b17023SJohn Marino {
4333e4b17023SJohn Marino   enum tree_code code = TREE_CODE (*tp);
4334e4b17023SJohn Marino   enum tree_code_class cl = TREE_CODE_CLASS (code);
4335e4b17023SJohn Marino 
4336e4b17023SJohn Marino   /* We make copies of most nodes.  */
4337e4b17023SJohn Marino   if (IS_EXPR_CODE_CLASS (cl)
4338e4b17023SJohn Marino       || code == TREE_LIST
4339e4b17023SJohn Marino       || code == TREE_VEC
4340e4b17023SJohn Marino       || code == TYPE_DECL
4341e4b17023SJohn Marino       || code == OMP_CLAUSE)
4342e4b17023SJohn Marino     {
4343e4b17023SJohn Marino       /* Because the chain gets clobbered when we make a copy, we save it
4344e4b17023SJohn Marino 	 here.  */
4345e4b17023SJohn Marino       tree chain = NULL_TREE, new_tree;
4346e4b17023SJohn Marino 
4347e4b17023SJohn Marino       if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
4348e4b17023SJohn Marino 	chain = TREE_CHAIN (*tp);
4349e4b17023SJohn Marino 
4350e4b17023SJohn Marino       /* Copy the node.  */
4351e4b17023SJohn Marino       new_tree = copy_node (*tp);
4352e4b17023SJohn Marino 
4353e4b17023SJohn Marino       /* Propagate mudflap marked-ness.  */
4354e4b17023SJohn Marino       if (flag_mudflap && mf_marked_p (*tp))
4355e4b17023SJohn Marino         mf_mark (new_tree);
4356e4b17023SJohn Marino 
4357e4b17023SJohn Marino       *tp = new_tree;
4358e4b17023SJohn Marino 
4359e4b17023SJohn Marino       /* Now, restore the chain, if appropriate.  That will cause
4360e4b17023SJohn Marino 	 walk_tree to walk into the chain as well.  */
4361e4b17023SJohn Marino       if (code == PARM_DECL
4362e4b17023SJohn Marino 	  || code == TREE_LIST
4363e4b17023SJohn Marino 	  || code == OMP_CLAUSE)
4364e4b17023SJohn Marino 	TREE_CHAIN (*tp) = chain;
4365e4b17023SJohn Marino 
4366e4b17023SJohn Marino       /* For now, we don't update BLOCKs when we make copies.  So, we
4367e4b17023SJohn Marino 	 have to nullify all BIND_EXPRs.  */
4368e4b17023SJohn Marino       if (TREE_CODE (*tp) == BIND_EXPR)
4369e4b17023SJohn Marino 	BIND_EXPR_BLOCK (*tp) = NULL_TREE;
4370e4b17023SJohn Marino     }
4371e4b17023SJohn Marino   else if (code == CONSTRUCTOR)
4372e4b17023SJohn Marino     {
4373e4b17023SJohn Marino       /* CONSTRUCTOR nodes need special handling because
4374e4b17023SJohn Marino          we need to duplicate the vector of elements.  */
4375e4b17023SJohn Marino       tree new_tree;
4376e4b17023SJohn Marino 
4377e4b17023SJohn Marino       new_tree = copy_node (*tp);
4378e4b17023SJohn Marino 
4379e4b17023SJohn Marino       /* Propagate mudflap marked-ness.  */
4380e4b17023SJohn Marino       if (flag_mudflap && mf_marked_p (*tp))
4381e4b17023SJohn Marino         mf_mark (new_tree);
4382e4b17023SJohn Marino 
4383e4b17023SJohn Marino       CONSTRUCTOR_ELTS (new_tree) = VEC_copy (constructor_elt, gc,
4384e4b17023SJohn Marino 					 CONSTRUCTOR_ELTS (*tp));
4385e4b17023SJohn Marino       *tp = new_tree;
4386e4b17023SJohn Marino     }
4387e4b17023SJohn Marino   else if (code == STATEMENT_LIST)
4388e4b17023SJohn Marino     /* We used to just abort on STATEMENT_LIST, but we can run into them
4389e4b17023SJohn Marino        with statement-expressions (c++/40975).  */
4390e4b17023SJohn Marino     copy_statement_list (tp);
4391e4b17023SJohn Marino   else if (TREE_CODE_CLASS (code) == tcc_type)
4392e4b17023SJohn Marino     *walk_subtrees = 0;
4393e4b17023SJohn Marino   else if (TREE_CODE_CLASS (code) == tcc_declaration)
4394e4b17023SJohn Marino     *walk_subtrees = 0;
4395e4b17023SJohn Marino   else if (TREE_CODE_CLASS (code) == tcc_constant)
4396e4b17023SJohn Marino     *walk_subtrees = 0;
4397e4b17023SJohn Marino   return NULL_TREE;
4398e4b17023SJohn Marino }
4399e4b17023SJohn Marino 
4400e4b17023SJohn Marino /* The SAVE_EXPR pointed to by TP is being copied.  If ST contains
4401e4b17023SJohn Marino    information indicating to what new SAVE_EXPR this one should be mapped,
4402e4b17023SJohn Marino    use that one.  Otherwise, create a new node and enter it in ST.  FN is
4403e4b17023SJohn Marino    the function into which the copy will be placed.  */
4404e4b17023SJohn Marino 
4405e4b17023SJohn Marino static void
remap_save_expr(tree * tp,void * st_,int * walk_subtrees)4406e4b17023SJohn Marino remap_save_expr (tree *tp, void *st_, int *walk_subtrees)
4407e4b17023SJohn Marino {
4408e4b17023SJohn Marino   struct pointer_map_t *st = (struct pointer_map_t *) st_;
4409e4b17023SJohn Marino   tree *n;
4410e4b17023SJohn Marino   tree t;
4411e4b17023SJohn Marino 
4412e4b17023SJohn Marino   /* See if we already encountered this SAVE_EXPR.  */
4413e4b17023SJohn Marino   n = (tree *) pointer_map_contains (st, *tp);
4414e4b17023SJohn Marino 
4415e4b17023SJohn Marino   /* If we didn't already remap this SAVE_EXPR, do so now.  */
4416e4b17023SJohn Marino   if (!n)
4417e4b17023SJohn Marino     {
4418e4b17023SJohn Marino       t = copy_node (*tp);
4419e4b17023SJohn Marino 
4420e4b17023SJohn Marino       /* Remember this SAVE_EXPR.  */
4421e4b17023SJohn Marino       *pointer_map_insert (st, *tp) = t;
4422e4b17023SJohn Marino       /* Make sure we don't remap an already-remapped SAVE_EXPR.  */
4423e4b17023SJohn Marino       *pointer_map_insert (st, t) = t;
4424e4b17023SJohn Marino     }
4425e4b17023SJohn Marino   else
4426e4b17023SJohn Marino     {
4427e4b17023SJohn Marino       /* We've already walked into this SAVE_EXPR; don't do it again.  */
4428e4b17023SJohn Marino       *walk_subtrees = 0;
4429e4b17023SJohn Marino       t = *n;
4430e4b17023SJohn Marino     }
4431e4b17023SJohn Marino 
4432e4b17023SJohn Marino   /* Replace this SAVE_EXPR with the copy.  */
4433e4b17023SJohn Marino   *tp = t;
4434e4b17023SJohn Marino }
4435e4b17023SJohn Marino 
4436e4b17023SJohn Marino /* Called via walk_tree.  If *TP points to a DECL_STMT for a local label,
4437e4b17023SJohn Marino    copies the declaration and enters it in the splay_tree in DATA (which is
4438e4b17023SJohn Marino    really an `copy_body_data *').  */
4439e4b17023SJohn Marino 
4440e4b17023SJohn Marino static tree
mark_local_for_remap_r(tree * tp,int * walk_subtrees ATTRIBUTE_UNUSED,void * data)4441e4b17023SJohn Marino mark_local_for_remap_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
4442e4b17023SJohn Marino 			void *data)
4443e4b17023SJohn Marino {
4444e4b17023SJohn Marino   copy_body_data *id = (copy_body_data *) data;
4445e4b17023SJohn Marino 
4446e4b17023SJohn Marino   /* Don't walk into types.  */
4447e4b17023SJohn Marino   if (TYPE_P (*tp))
4448e4b17023SJohn Marino     *walk_subtrees = 0;
4449e4b17023SJohn Marino 
4450e4b17023SJohn Marino   else if (TREE_CODE (*tp) == LABEL_EXPR)
4451e4b17023SJohn Marino     {
4452e4b17023SJohn Marino       tree decl = TREE_OPERAND (*tp, 0);
4453e4b17023SJohn Marino 
4454e4b17023SJohn Marino       /* Copy the decl and remember the copy.  */
4455e4b17023SJohn Marino       insert_decl_map (id, decl, id->copy_decl (decl, id));
4456e4b17023SJohn Marino     }
4457e4b17023SJohn Marino 
4458e4b17023SJohn Marino   return NULL_TREE;
4459e4b17023SJohn Marino }
4460e4b17023SJohn Marino 
4461e4b17023SJohn Marino /* Perform any modifications to EXPR required when it is unsaved.  Does
4462e4b17023SJohn Marino    not recurse into EXPR's subtrees.  */
4463e4b17023SJohn Marino 
4464e4b17023SJohn Marino static void
unsave_expr_1(tree expr)4465e4b17023SJohn Marino unsave_expr_1 (tree expr)
4466e4b17023SJohn Marino {
4467e4b17023SJohn Marino   switch (TREE_CODE (expr))
4468e4b17023SJohn Marino     {
4469e4b17023SJohn Marino     case TARGET_EXPR:
4470e4b17023SJohn Marino       /* Don't mess with a TARGET_EXPR that hasn't been expanded.
4471e4b17023SJohn Marino          It's OK for this to happen if it was part of a subtree that
4472e4b17023SJohn Marino          isn't immediately expanded, such as operand 2 of another
4473e4b17023SJohn Marino          TARGET_EXPR.  */
4474e4b17023SJohn Marino       if (TREE_OPERAND (expr, 1))
4475e4b17023SJohn Marino 	break;
4476e4b17023SJohn Marino 
4477e4b17023SJohn Marino       TREE_OPERAND (expr, 1) = TREE_OPERAND (expr, 3);
4478e4b17023SJohn Marino       TREE_OPERAND (expr, 3) = NULL_TREE;
4479e4b17023SJohn Marino       break;
4480e4b17023SJohn Marino 
4481e4b17023SJohn Marino     default:
4482e4b17023SJohn Marino       break;
4483e4b17023SJohn Marino     }
4484e4b17023SJohn Marino }
4485e4b17023SJohn Marino 
4486e4b17023SJohn Marino /* Called via walk_tree when an expression is unsaved.  Using the
4487e4b17023SJohn Marino    splay_tree pointed to by ST (which is really a `splay_tree'),
4488e4b17023SJohn Marino    remaps all local declarations to appropriate replacements.  */
4489e4b17023SJohn Marino 
4490e4b17023SJohn Marino static tree
unsave_r(tree * tp,int * walk_subtrees,void * data)4491e4b17023SJohn Marino unsave_r (tree *tp, int *walk_subtrees, void *data)
4492e4b17023SJohn Marino {
4493e4b17023SJohn Marino   copy_body_data *id = (copy_body_data *) data;
4494e4b17023SJohn Marino   struct pointer_map_t *st = id->decl_map;
4495e4b17023SJohn Marino   tree *n;
4496e4b17023SJohn Marino 
4497e4b17023SJohn Marino   /* Only a local declaration (variable or label).  */
4498e4b17023SJohn Marino   if ((TREE_CODE (*tp) == VAR_DECL && !TREE_STATIC (*tp))
4499e4b17023SJohn Marino       || TREE_CODE (*tp) == LABEL_DECL)
4500e4b17023SJohn Marino     {
4501e4b17023SJohn Marino       /* Lookup the declaration.  */
4502e4b17023SJohn Marino       n = (tree *) pointer_map_contains (st, *tp);
4503e4b17023SJohn Marino 
4504e4b17023SJohn Marino       /* If it's there, remap it.  */
4505e4b17023SJohn Marino       if (n)
4506e4b17023SJohn Marino 	*tp = *n;
4507e4b17023SJohn Marino     }
4508e4b17023SJohn Marino 
4509e4b17023SJohn Marino   else if (TREE_CODE (*tp) == STATEMENT_LIST)
4510e4b17023SJohn Marino     gcc_unreachable ();
4511e4b17023SJohn Marino   else if (TREE_CODE (*tp) == BIND_EXPR)
4512e4b17023SJohn Marino     copy_bind_expr (tp, walk_subtrees, id);
4513e4b17023SJohn Marino   else if (TREE_CODE (*tp) == SAVE_EXPR
4514e4b17023SJohn Marino 	   || TREE_CODE (*tp) == TARGET_EXPR)
4515e4b17023SJohn Marino     remap_save_expr (tp, st, walk_subtrees);
4516e4b17023SJohn Marino   else
4517e4b17023SJohn Marino     {
4518e4b17023SJohn Marino       copy_tree_r (tp, walk_subtrees, NULL);
4519e4b17023SJohn Marino 
4520e4b17023SJohn Marino       /* Do whatever unsaving is required.  */
4521e4b17023SJohn Marino       unsave_expr_1 (*tp);
4522e4b17023SJohn Marino     }
4523e4b17023SJohn Marino 
4524e4b17023SJohn Marino   /* Keep iterating.  */
4525e4b17023SJohn Marino   return NULL_TREE;
4526e4b17023SJohn Marino }
4527e4b17023SJohn Marino 
4528e4b17023SJohn Marino /* Copies everything in EXPR and replaces variables, labels
4529e4b17023SJohn Marino    and SAVE_EXPRs local to EXPR.  */
4530e4b17023SJohn Marino 
4531e4b17023SJohn Marino tree
unsave_expr_now(tree expr)4532e4b17023SJohn Marino unsave_expr_now (tree expr)
4533e4b17023SJohn Marino {
4534e4b17023SJohn Marino   copy_body_data id;
4535e4b17023SJohn Marino 
4536e4b17023SJohn Marino   /* There's nothing to do for NULL_TREE.  */
4537e4b17023SJohn Marino   if (expr == 0)
4538e4b17023SJohn Marino     return expr;
4539e4b17023SJohn Marino 
4540e4b17023SJohn Marino   /* Set up ID.  */
4541e4b17023SJohn Marino   memset (&id, 0, sizeof (id));
4542e4b17023SJohn Marino   id.src_fn = current_function_decl;
4543e4b17023SJohn Marino   id.dst_fn = current_function_decl;
4544e4b17023SJohn Marino   id.decl_map = pointer_map_create ();
4545e4b17023SJohn Marino   id.debug_map = NULL;
4546e4b17023SJohn Marino 
4547e4b17023SJohn Marino   id.copy_decl = copy_decl_no_change;
4548e4b17023SJohn Marino   id.transform_call_graph_edges = CB_CGE_DUPLICATE;
4549e4b17023SJohn Marino   id.transform_new_cfg = false;
4550e4b17023SJohn Marino   id.transform_return_to_modify = false;
4551e4b17023SJohn Marino   id.transform_lang_insert_block = NULL;
4552e4b17023SJohn Marino 
4553e4b17023SJohn Marino   /* Walk the tree once to find local labels.  */
4554e4b17023SJohn Marino   walk_tree_without_duplicates (&expr, mark_local_for_remap_r, &id);
4555e4b17023SJohn Marino 
4556e4b17023SJohn Marino   /* Walk the tree again, copying, remapping, and unsaving.  */
4557e4b17023SJohn Marino   walk_tree (&expr, unsave_r, &id, NULL);
4558e4b17023SJohn Marino 
4559e4b17023SJohn Marino   /* Clean up.  */
4560e4b17023SJohn Marino   pointer_map_destroy (id.decl_map);
4561e4b17023SJohn Marino   if (id.debug_map)
4562e4b17023SJohn Marino     pointer_map_destroy (id.debug_map);
4563e4b17023SJohn Marino 
4564e4b17023SJohn Marino   return expr;
4565e4b17023SJohn Marino }
4566e4b17023SJohn Marino 
4567e4b17023SJohn Marino /* Called via walk_gimple_seq.  If *GSIP points to a GIMPLE_LABEL for a local
4568e4b17023SJohn Marino    label, copies the declaration and enters it in the splay_tree in DATA (which
4569e4b17023SJohn Marino    is really a 'copy_body_data *'.  */
4570e4b17023SJohn Marino 
4571e4b17023SJohn Marino static tree
mark_local_labels_stmt(gimple_stmt_iterator * gsip,bool * handled_ops_p ATTRIBUTE_UNUSED,struct walk_stmt_info * wi)4572e4b17023SJohn Marino mark_local_labels_stmt (gimple_stmt_iterator *gsip,
4573e4b17023SJohn Marino 		        bool *handled_ops_p ATTRIBUTE_UNUSED,
4574e4b17023SJohn Marino 		        struct walk_stmt_info *wi)
4575e4b17023SJohn Marino {
4576e4b17023SJohn Marino   copy_body_data *id = (copy_body_data *) wi->info;
4577e4b17023SJohn Marino   gimple stmt = gsi_stmt (*gsip);
4578e4b17023SJohn Marino 
4579e4b17023SJohn Marino   if (gimple_code (stmt) == GIMPLE_LABEL)
4580e4b17023SJohn Marino     {
4581e4b17023SJohn Marino       tree decl = gimple_label_label (stmt);
4582e4b17023SJohn Marino 
4583e4b17023SJohn Marino       /* Copy the decl and remember the copy.  */
4584e4b17023SJohn Marino       insert_decl_map (id, decl, id->copy_decl (decl, id));
4585e4b17023SJohn Marino     }
4586e4b17023SJohn Marino 
4587e4b17023SJohn Marino   return NULL_TREE;
4588e4b17023SJohn Marino }
4589e4b17023SJohn Marino 
4590e4b17023SJohn Marino 
4591e4b17023SJohn Marino /* Called via walk_gimple_seq by copy_gimple_seq_and_replace_local.
4592e4b17023SJohn Marino    Using the splay_tree pointed to by ST (which is really a `splay_tree'),
4593e4b17023SJohn Marino    remaps all local declarations to appropriate replacements in gimple
4594e4b17023SJohn Marino    operands. */
4595e4b17023SJohn Marino 
4596e4b17023SJohn Marino static tree
replace_locals_op(tree * tp,int * walk_subtrees,void * data)4597e4b17023SJohn Marino replace_locals_op (tree *tp, int *walk_subtrees, void *data)
4598e4b17023SJohn Marino {
4599e4b17023SJohn Marino   struct walk_stmt_info *wi = (struct walk_stmt_info*) data;
4600e4b17023SJohn Marino   copy_body_data *id = (copy_body_data *) wi->info;
4601e4b17023SJohn Marino   struct pointer_map_t *st = id->decl_map;
4602e4b17023SJohn Marino   tree *n;
4603e4b17023SJohn Marino   tree expr = *tp;
4604e4b17023SJohn Marino 
4605e4b17023SJohn Marino   /* Only a local declaration (variable or label).  */
4606e4b17023SJohn Marino   if ((TREE_CODE (expr) == VAR_DECL
4607e4b17023SJohn Marino        && !TREE_STATIC (expr))
4608e4b17023SJohn Marino       || TREE_CODE (expr) == LABEL_DECL)
4609e4b17023SJohn Marino     {
4610e4b17023SJohn Marino       /* Lookup the declaration.  */
4611e4b17023SJohn Marino       n = (tree *) pointer_map_contains (st, expr);
4612e4b17023SJohn Marino 
4613e4b17023SJohn Marino       /* If it's there, remap it.  */
4614e4b17023SJohn Marino       if (n)
4615e4b17023SJohn Marino 	*tp = *n;
4616e4b17023SJohn Marino       *walk_subtrees = 0;
4617e4b17023SJohn Marino     }
4618e4b17023SJohn Marino   else if (TREE_CODE (expr) == STATEMENT_LIST
4619e4b17023SJohn Marino 	   || TREE_CODE (expr) == BIND_EXPR
4620e4b17023SJohn Marino 	   || TREE_CODE (expr) == SAVE_EXPR)
4621e4b17023SJohn Marino     gcc_unreachable ();
4622e4b17023SJohn Marino   else if (TREE_CODE (expr) == TARGET_EXPR)
4623e4b17023SJohn Marino     {
4624e4b17023SJohn Marino       /* Don't mess with a TARGET_EXPR that hasn't been expanded.
4625e4b17023SJohn Marino          It's OK for this to happen if it was part of a subtree that
4626e4b17023SJohn Marino          isn't immediately expanded, such as operand 2 of another
4627e4b17023SJohn Marino          TARGET_EXPR.  */
4628e4b17023SJohn Marino       if (!TREE_OPERAND (expr, 1))
4629e4b17023SJohn Marino 	{
4630e4b17023SJohn Marino 	  TREE_OPERAND (expr, 1) = TREE_OPERAND (expr, 3);
4631e4b17023SJohn Marino 	  TREE_OPERAND (expr, 3) = NULL_TREE;
4632e4b17023SJohn Marino 	}
4633e4b17023SJohn Marino     }
4634e4b17023SJohn Marino 
4635e4b17023SJohn Marino   /* Keep iterating.  */
4636e4b17023SJohn Marino   return NULL_TREE;
4637e4b17023SJohn Marino }
4638e4b17023SJohn Marino 
4639e4b17023SJohn Marino 
4640e4b17023SJohn Marino /* Called via walk_gimple_seq by copy_gimple_seq_and_replace_local.
4641e4b17023SJohn Marino    Using the splay_tree pointed to by ST (which is really a `splay_tree'),
4642e4b17023SJohn Marino    remaps all local declarations to appropriate replacements in gimple
4643e4b17023SJohn Marino    statements. */
4644e4b17023SJohn Marino 
4645e4b17023SJohn Marino static tree
replace_locals_stmt(gimple_stmt_iterator * gsip,bool * handled_ops_p ATTRIBUTE_UNUSED,struct walk_stmt_info * wi)4646e4b17023SJohn Marino replace_locals_stmt (gimple_stmt_iterator *gsip,
4647e4b17023SJohn Marino 		     bool *handled_ops_p ATTRIBUTE_UNUSED,
4648e4b17023SJohn Marino 		     struct walk_stmt_info *wi)
4649e4b17023SJohn Marino {
4650e4b17023SJohn Marino   copy_body_data *id = (copy_body_data *) wi->info;
4651e4b17023SJohn Marino   gimple stmt = gsi_stmt (*gsip);
4652e4b17023SJohn Marino 
4653e4b17023SJohn Marino   if (gimple_code (stmt) == GIMPLE_BIND)
4654e4b17023SJohn Marino     {
4655e4b17023SJohn Marino       tree block = gimple_bind_block (stmt);
4656e4b17023SJohn Marino 
4657e4b17023SJohn Marino       if (block)
4658e4b17023SJohn Marino 	{
4659e4b17023SJohn Marino 	  remap_block (&block, id);
4660e4b17023SJohn Marino 	  gimple_bind_set_block (stmt, block);
4661e4b17023SJohn Marino 	}
4662e4b17023SJohn Marino 
4663e4b17023SJohn Marino       /* This will remap a lot of the same decls again, but this should be
4664e4b17023SJohn Marino 	 harmless.  */
4665e4b17023SJohn Marino       if (gimple_bind_vars (stmt))
4666e4b17023SJohn Marino 	gimple_bind_set_vars (stmt, remap_decls (gimple_bind_vars (stmt), NULL, id));
4667e4b17023SJohn Marino     }
4668e4b17023SJohn Marino 
4669e4b17023SJohn Marino   /* Keep iterating.  */
4670e4b17023SJohn Marino   return NULL_TREE;
4671e4b17023SJohn Marino }
4672e4b17023SJohn Marino 
4673e4b17023SJohn Marino 
4674e4b17023SJohn Marino /* Copies everything in SEQ and replaces variables and labels local to
4675e4b17023SJohn Marino    current_function_decl.  */
4676e4b17023SJohn Marino 
4677e4b17023SJohn Marino gimple_seq
copy_gimple_seq_and_replace_locals(gimple_seq seq)4678e4b17023SJohn Marino copy_gimple_seq_and_replace_locals (gimple_seq seq)
4679e4b17023SJohn Marino {
4680e4b17023SJohn Marino   copy_body_data id;
4681e4b17023SJohn Marino   struct walk_stmt_info wi;
4682e4b17023SJohn Marino   struct pointer_set_t *visited;
4683e4b17023SJohn Marino   gimple_seq copy;
4684e4b17023SJohn Marino 
4685e4b17023SJohn Marino   /* There's nothing to do for NULL_TREE.  */
4686e4b17023SJohn Marino   if (seq == NULL)
4687e4b17023SJohn Marino     return seq;
4688e4b17023SJohn Marino 
4689e4b17023SJohn Marino   /* Set up ID.  */
4690e4b17023SJohn Marino   memset (&id, 0, sizeof (id));
4691e4b17023SJohn Marino   id.src_fn = current_function_decl;
4692e4b17023SJohn Marino   id.dst_fn = current_function_decl;
4693e4b17023SJohn Marino   id.decl_map = pointer_map_create ();
4694e4b17023SJohn Marino   id.debug_map = NULL;
4695e4b17023SJohn Marino 
4696e4b17023SJohn Marino   id.copy_decl = copy_decl_no_change;
4697e4b17023SJohn Marino   id.transform_call_graph_edges = CB_CGE_DUPLICATE;
4698e4b17023SJohn Marino   id.transform_new_cfg = false;
4699e4b17023SJohn Marino   id.transform_return_to_modify = false;
4700e4b17023SJohn Marino   id.transform_lang_insert_block = NULL;
4701e4b17023SJohn Marino 
4702e4b17023SJohn Marino   /* Walk the tree once to find local labels.  */
4703e4b17023SJohn Marino   memset (&wi, 0, sizeof (wi));
4704e4b17023SJohn Marino   visited = pointer_set_create ();
4705e4b17023SJohn Marino   wi.info = &id;
4706e4b17023SJohn Marino   wi.pset = visited;
4707e4b17023SJohn Marino   walk_gimple_seq (seq, mark_local_labels_stmt, NULL, &wi);
4708e4b17023SJohn Marino   pointer_set_destroy (visited);
4709e4b17023SJohn Marino 
4710e4b17023SJohn Marino   copy = gimple_seq_copy (seq);
4711e4b17023SJohn Marino 
4712e4b17023SJohn Marino   /* Walk the copy, remapping decls.  */
4713e4b17023SJohn Marino   memset (&wi, 0, sizeof (wi));
4714e4b17023SJohn Marino   wi.info = &id;
4715e4b17023SJohn Marino   walk_gimple_seq (copy, replace_locals_stmt, replace_locals_op, &wi);
4716e4b17023SJohn Marino 
4717e4b17023SJohn Marino   /* Clean up.  */
4718e4b17023SJohn Marino   pointer_map_destroy (id.decl_map);
4719e4b17023SJohn Marino   if (id.debug_map)
4720e4b17023SJohn Marino     pointer_map_destroy (id.debug_map);
4721e4b17023SJohn Marino 
4722e4b17023SJohn Marino   return copy;
4723e4b17023SJohn Marino }
4724e4b17023SJohn Marino 
4725e4b17023SJohn Marino 
4726e4b17023SJohn Marino /* Allow someone to determine if SEARCH is a child of TOP from gdb.  */
4727e4b17023SJohn Marino 
4728e4b17023SJohn Marino static tree
debug_find_tree_1(tree * tp,int * walk_subtrees ATTRIBUTE_UNUSED,void * data)4729e4b17023SJohn Marino debug_find_tree_1 (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
4730e4b17023SJohn Marino {
4731e4b17023SJohn Marino   if (*tp == data)
4732e4b17023SJohn Marino     return (tree) data;
4733e4b17023SJohn Marino   else
4734e4b17023SJohn Marino     return NULL;
4735e4b17023SJohn Marino }
4736e4b17023SJohn Marino 
4737e4b17023SJohn Marino DEBUG_FUNCTION bool
debug_find_tree(tree top,tree search)4738e4b17023SJohn Marino debug_find_tree (tree top, tree search)
4739e4b17023SJohn Marino {
4740e4b17023SJohn Marino   return walk_tree_without_duplicates (&top, debug_find_tree_1, search) != 0;
4741e4b17023SJohn Marino }
4742e4b17023SJohn Marino 
4743e4b17023SJohn Marino 
4744e4b17023SJohn Marino /* Declare the variables created by the inliner.  Add all the variables in
4745e4b17023SJohn Marino    VARS to BIND_EXPR.  */
4746e4b17023SJohn Marino 
4747e4b17023SJohn Marino static void
declare_inline_vars(tree block,tree vars)4748e4b17023SJohn Marino declare_inline_vars (tree block, tree vars)
4749e4b17023SJohn Marino {
4750e4b17023SJohn Marino   tree t;
4751e4b17023SJohn Marino   for (t = vars; t; t = DECL_CHAIN (t))
4752e4b17023SJohn Marino     {
4753e4b17023SJohn Marino       DECL_SEEN_IN_BIND_EXPR_P (t) = 1;
4754e4b17023SJohn Marino       gcc_assert (!TREE_STATIC (t) && !TREE_ASM_WRITTEN (t));
4755e4b17023SJohn Marino       add_local_decl (cfun, t);
4756e4b17023SJohn Marino     }
4757e4b17023SJohn Marino 
4758e4b17023SJohn Marino   if (block)
4759e4b17023SJohn Marino     BLOCK_VARS (block) = chainon (BLOCK_VARS (block), vars);
4760e4b17023SJohn Marino }
4761e4b17023SJohn Marino 
4762e4b17023SJohn Marino /* Copy NODE (which must be a DECL).  The DECL originally was in the FROM_FN,
4763e4b17023SJohn Marino    but now it will be in the TO_FN.  PARM_TO_VAR means enable PARM_DECL to
4764e4b17023SJohn Marino    VAR_DECL translation.  */
4765e4b17023SJohn Marino 
4766e4b17023SJohn Marino static tree
copy_decl_for_dup_finish(copy_body_data * id,tree decl,tree copy)4767e4b17023SJohn Marino copy_decl_for_dup_finish (copy_body_data *id, tree decl, tree copy)
4768e4b17023SJohn Marino {
4769e4b17023SJohn Marino   /* Don't generate debug information for the copy if we wouldn't have
4770e4b17023SJohn Marino      generated it for the copy either.  */
4771e4b17023SJohn Marino   DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (decl);
4772e4b17023SJohn Marino   DECL_IGNORED_P (copy) = DECL_IGNORED_P (decl);
4773e4b17023SJohn Marino 
4774e4b17023SJohn Marino   /* Set the DECL_ABSTRACT_ORIGIN so the debugging routines know what
4775e4b17023SJohn Marino      declaration inspired this copy.  */
4776e4b17023SJohn Marino   DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (decl);
4777e4b17023SJohn Marino 
4778e4b17023SJohn Marino   /* The new variable/label has no RTL, yet.  */
4779e4b17023SJohn Marino   if (CODE_CONTAINS_STRUCT (TREE_CODE (copy), TS_DECL_WRTL)
4780e4b17023SJohn Marino       && !TREE_STATIC (copy) && !DECL_EXTERNAL (copy))
4781e4b17023SJohn Marino     SET_DECL_RTL (copy, 0);
4782e4b17023SJohn Marino 
4783e4b17023SJohn Marino   /* These args would always appear unused, if not for this.  */
4784e4b17023SJohn Marino   TREE_USED (copy) = 1;
4785e4b17023SJohn Marino 
4786e4b17023SJohn Marino   /* Set the context for the new declaration.  */
4787e4b17023SJohn Marino   if (!DECL_CONTEXT (decl))
4788e4b17023SJohn Marino     /* Globals stay global.  */
4789e4b17023SJohn Marino     ;
4790e4b17023SJohn Marino   else if (DECL_CONTEXT (decl) != id->src_fn)
4791e4b17023SJohn Marino     /* Things that weren't in the scope of the function we're inlining
4792e4b17023SJohn Marino        from aren't in the scope we're inlining to, either.  */
4793e4b17023SJohn Marino     ;
4794e4b17023SJohn Marino   else if (TREE_STATIC (decl))
4795e4b17023SJohn Marino     /* Function-scoped static variables should stay in the original
4796e4b17023SJohn Marino        function.  */
4797e4b17023SJohn Marino     ;
4798e4b17023SJohn Marino   else
4799e4b17023SJohn Marino     /* Ordinary automatic local variables are now in the scope of the
4800e4b17023SJohn Marino        new function.  */
4801e4b17023SJohn Marino     DECL_CONTEXT (copy) = id->dst_fn;
4802e4b17023SJohn Marino 
4803e4b17023SJohn Marino   if (TREE_CODE (decl) == VAR_DECL
4804e4b17023SJohn Marino       /* C++ clones functions during parsing, before
4805e4b17023SJohn Marino 	 referenced_vars.  */
4806e4b17023SJohn Marino       && gimple_referenced_vars (DECL_STRUCT_FUNCTION (id->src_fn))
4807e4b17023SJohn Marino       && referenced_var_lookup (DECL_STRUCT_FUNCTION (id->src_fn),
4808e4b17023SJohn Marino 				DECL_UID (decl)))
4809e4b17023SJohn Marino     add_referenced_var (copy);
4810e4b17023SJohn Marino 
4811e4b17023SJohn Marino   return copy;
4812e4b17023SJohn Marino }
4813e4b17023SJohn Marino 
4814e4b17023SJohn Marino static tree
copy_decl_to_var(tree decl,copy_body_data * id)4815e4b17023SJohn Marino copy_decl_to_var (tree decl, copy_body_data *id)
4816e4b17023SJohn Marino {
4817e4b17023SJohn Marino   tree copy, type;
4818e4b17023SJohn Marino 
4819e4b17023SJohn Marino   gcc_assert (TREE_CODE (decl) == PARM_DECL
4820e4b17023SJohn Marino 	      || TREE_CODE (decl) == RESULT_DECL);
4821e4b17023SJohn Marino 
4822e4b17023SJohn Marino   type = TREE_TYPE (decl);
4823e4b17023SJohn Marino 
4824e4b17023SJohn Marino   copy = build_decl (DECL_SOURCE_LOCATION (id->dst_fn),
4825e4b17023SJohn Marino 		     VAR_DECL, DECL_NAME (decl), type);
4826e4b17023SJohn Marino   if (DECL_PT_UID_SET_P (decl))
4827e4b17023SJohn Marino     SET_DECL_PT_UID (copy, DECL_PT_UID (decl));
4828e4b17023SJohn Marino   TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
4829e4b17023SJohn Marino   TREE_READONLY (copy) = TREE_READONLY (decl);
4830e4b17023SJohn Marino   TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
4831e4b17023SJohn Marino   DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (decl);
4832e4b17023SJohn Marino 
4833e4b17023SJohn Marino   return copy_decl_for_dup_finish (id, decl, copy);
4834e4b17023SJohn Marino }
4835e4b17023SJohn Marino 
4836e4b17023SJohn Marino /* Like copy_decl_to_var, but create a return slot object instead of a
4837e4b17023SJohn Marino    pointer variable for return by invisible reference.  */
4838e4b17023SJohn Marino 
4839e4b17023SJohn Marino static tree
copy_result_decl_to_var(tree decl,copy_body_data * id)4840e4b17023SJohn Marino copy_result_decl_to_var (tree decl, copy_body_data *id)
4841e4b17023SJohn Marino {
4842e4b17023SJohn Marino   tree copy, type;
4843e4b17023SJohn Marino 
4844e4b17023SJohn Marino   gcc_assert (TREE_CODE (decl) == PARM_DECL
4845e4b17023SJohn Marino 	      || TREE_CODE (decl) == RESULT_DECL);
4846e4b17023SJohn Marino 
4847e4b17023SJohn Marino   type = TREE_TYPE (decl);
4848e4b17023SJohn Marino   if (DECL_BY_REFERENCE (decl))
4849e4b17023SJohn Marino     type = TREE_TYPE (type);
4850e4b17023SJohn Marino 
4851e4b17023SJohn Marino   copy = build_decl (DECL_SOURCE_LOCATION (id->dst_fn),
4852e4b17023SJohn Marino 		     VAR_DECL, DECL_NAME (decl), type);
4853e4b17023SJohn Marino   if (DECL_PT_UID_SET_P (decl))
4854e4b17023SJohn Marino     SET_DECL_PT_UID (copy, DECL_PT_UID (decl));
4855e4b17023SJohn Marino   TREE_READONLY (copy) = TREE_READONLY (decl);
4856e4b17023SJohn Marino   TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
4857e4b17023SJohn Marino   if (!DECL_BY_REFERENCE (decl))
4858e4b17023SJohn Marino     {
4859e4b17023SJohn Marino       TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
4860e4b17023SJohn Marino       DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (decl);
4861e4b17023SJohn Marino     }
4862e4b17023SJohn Marino 
4863e4b17023SJohn Marino   return copy_decl_for_dup_finish (id, decl, copy);
4864e4b17023SJohn Marino }
4865e4b17023SJohn Marino 
4866e4b17023SJohn Marino tree
copy_decl_no_change(tree decl,copy_body_data * id)4867e4b17023SJohn Marino copy_decl_no_change (tree decl, copy_body_data *id)
4868e4b17023SJohn Marino {
4869e4b17023SJohn Marino   tree copy;
4870e4b17023SJohn Marino 
4871e4b17023SJohn Marino   copy = copy_node (decl);
4872e4b17023SJohn Marino 
4873e4b17023SJohn Marino   /* The COPY is not abstract; it will be generated in DST_FN.  */
4874e4b17023SJohn Marino   DECL_ABSTRACT (copy) = 0;
4875e4b17023SJohn Marino   lang_hooks.dup_lang_specific_decl (copy);
4876e4b17023SJohn Marino 
4877e4b17023SJohn Marino   /* TREE_ADDRESSABLE isn't used to indicate that a label's address has
4878e4b17023SJohn Marino      been taken; it's for internal bookkeeping in expand_goto_internal.  */
4879e4b17023SJohn Marino   if (TREE_CODE (copy) == LABEL_DECL)
4880e4b17023SJohn Marino     {
4881e4b17023SJohn Marino       TREE_ADDRESSABLE (copy) = 0;
4882e4b17023SJohn Marino       LABEL_DECL_UID (copy) = -1;
4883e4b17023SJohn Marino     }
4884e4b17023SJohn Marino 
4885e4b17023SJohn Marino   return copy_decl_for_dup_finish (id, decl, copy);
4886e4b17023SJohn Marino }
4887e4b17023SJohn Marino 
4888e4b17023SJohn Marino static tree
copy_decl_maybe_to_var(tree decl,copy_body_data * id)4889e4b17023SJohn Marino copy_decl_maybe_to_var (tree decl, copy_body_data *id)
4890e4b17023SJohn Marino {
4891e4b17023SJohn Marino   if (TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == RESULT_DECL)
4892e4b17023SJohn Marino     return copy_decl_to_var (decl, id);
4893e4b17023SJohn Marino   else
4894e4b17023SJohn Marino     return copy_decl_no_change (decl, id);
4895e4b17023SJohn Marino }
4896e4b17023SJohn Marino 
4897e4b17023SJohn Marino /* Return a copy of the function's argument tree.  */
4898e4b17023SJohn Marino static tree
copy_arguments_for_versioning(tree orig_parm,copy_body_data * id,bitmap args_to_skip,tree * vars)4899e4b17023SJohn Marino copy_arguments_for_versioning (tree orig_parm, copy_body_data * id,
4900e4b17023SJohn Marino 			       bitmap args_to_skip, tree *vars)
4901e4b17023SJohn Marino {
4902e4b17023SJohn Marino   tree arg, *parg;
4903e4b17023SJohn Marino   tree new_parm = NULL;
4904e4b17023SJohn Marino   int i = 0;
4905e4b17023SJohn Marino 
4906e4b17023SJohn Marino   parg = &new_parm;
4907e4b17023SJohn Marino 
4908e4b17023SJohn Marino   for (arg = orig_parm; arg; arg = DECL_CHAIN (arg), i++)
4909e4b17023SJohn Marino     if (!args_to_skip || !bitmap_bit_p (args_to_skip, i))
4910e4b17023SJohn Marino       {
4911e4b17023SJohn Marino         tree new_tree = remap_decl (arg, id);
4912e4b17023SJohn Marino 	if (TREE_CODE (new_tree) != PARM_DECL)
4913e4b17023SJohn Marino 	  new_tree = id->copy_decl (arg, id);
4914e4b17023SJohn Marino         lang_hooks.dup_lang_specific_decl (new_tree);
4915e4b17023SJohn Marino         *parg = new_tree;
4916e4b17023SJohn Marino 	parg = &DECL_CHAIN (new_tree);
4917e4b17023SJohn Marino       }
4918e4b17023SJohn Marino     else if (!pointer_map_contains (id->decl_map, arg))
4919e4b17023SJohn Marino       {
4920e4b17023SJohn Marino 	/* Make an equivalent VAR_DECL.  If the argument was used
4921e4b17023SJohn Marino 	   as temporary variable later in function, the uses will be
4922e4b17023SJohn Marino 	   replaced by local variable.  */
4923e4b17023SJohn Marino 	tree var = copy_decl_to_var (arg, id);
4924e4b17023SJohn Marino 	add_referenced_var (var);
4925e4b17023SJohn Marino 	insert_decl_map (id, arg, var);
4926e4b17023SJohn Marino         /* Declare this new variable.  */
4927e4b17023SJohn Marino         DECL_CHAIN (var) = *vars;
4928e4b17023SJohn Marino         *vars = var;
4929e4b17023SJohn Marino       }
4930e4b17023SJohn Marino   return new_parm;
4931e4b17023SJohn Marino }
4932e4b17023SJohn Marino 
4933e4b17023SJohn Marino /* Return a copy of the function's static chain.  */
4934e4b17023SJohn Marino static tree
copy_static_chain(tree static_chain,copy_body_data * id)4935e4b17023SJohn Marino copy_static_chain (tree static_chain, copy_body_data * id)
4936e4b17023SJohn Marino {
4937e4b17023SJohn Marino   tree *chain_copy, *pvar;
4938e4b17023SJohn Marino 
4939e4b17023SJohn Marino   chain_copy = &static_chain;
4940e4b17023SJohn Marino   for (pvar = chain_copy; *pvar; pvar = &DECL_CHAIN (*pvar))
4941e4b17023SJohn Marino     {
4942e4b17023SJohn Marino       tree new_tree = remap_decl (*pvar, id);
4943e4b17023SJohn Marino       lang_hooks.dup_lang_specific_decl (new_tree);
4944e4b17023SJohn Marino       DECL_CHAIN (new_tree) = DECL_CHAIN (*pvar);
4945e4b17023SJohn Marino       *pvar = new_tree;
4946e4b17023SJohn Marino     }
4947e4b17023SJohn Marino   return static_chain;
4948e4b17023SJohn Marino }
4949e4b17023SJohn Marino 
4950e4b17023SJohn Marino /* Return true if the function is allowed to be versioned.
4951e4b17023SJohn Marino    This is a guard for the versioning functionality.  */
4952e4b17023SJohn Marino 
4953e4b17023SJohn Marino bool
tree_versionable_function_p(tree fndecl)4954e4b17023SJohn Marino tree_versionable_function_p (tree fndecl)
4955e4b17023SJohn Marino {
4956e4b17023SJohn Marino   return (!lookup_attribute ("noclone", DECL_ATTRIBUTES (fndecl))
4957e4b17023SJohn Marino 	  && copy_forbidden (DECL_STRUCT_FUNCTION (fndecl), fndecl) == NULL);
4958e4b17023SJohn Marino }
4959e4b17023SJohn Marino 
4960e4b17023SJohn Marino /* Delete all unreachable basic blocks and update callgraph.
4961e4b17023SJohn Marino    Doing so is somewhat nontrivial because we need to update all clones and
4962e4b17023SJohn Marino    remove inline function that become unreachable.  */
4963e4b17023SJohn Marino 
4964e4b17023SJohn Marino static bool
delete_unreachable_blocks_update_callgraph(copy_body_data * id)4965e4b17023SJohn Marino delete_unreachable_blocks_update_callgraph (copy_body_data *id)
4966e4b17023SJohn Marino {
4967e4b17023SJohn Marino   bool changed = false;
4968e4b17023SJohn Marino   basic_block b, next_bb;
4969e4b17023SJohn Marino 
4970e4b17023SJohn Marino   find_unreachable_blocks ();
4971e4b17023SJohn Marino 
4972e4b17023SJohn Marino   /* Delete all unreachable basic blocks.  */
4973e4b17023SJohn Marino 
4974e4b17023SJohn Marino   for (b = ENTRY_BLOCK_PTR->next_bb; b != EXIT_BLOCK_PTR; b = next_bb)
4975e4b17023SJohn Marino     {
4976e4b17023SJohn Marino       next_bb = b->next_bb;
4977e4b17023SJohn Marino 
4978e4b17023SJohn Marino       if (!(b->flags & BB_REACHABLE))
4979e4b17023SJohn Marino 	{
4980e4b17023SJohn Marino           gimple_stmt_iterator bsi;
4981e4b17023SJohn Marino 
4982e4b17023SJohn Marino           for (bsi = gsi_start_bb (b); !gsi_end_p (bsi); gsi_next (&bsi))
4983e4b17023SJohn Marino 	    if (gimple_code (gsi_stmt (bsi)) == GIMPLE_CALL)
4984e4b17023SJohn Marino 	      {
4985e4b17023SJohn Marino 	        struct cgraph_edge *e;
4986e4b17023SJohn Marino 		struct cgraph_node *node;
4987e4b17023SJohn Marino 
4988e4b17023SJohn Marino 	        if ((e = cgraph_edge (id->dst_node, gsi_stmt (bsi))) != NULL)
4989e4b17023SJohn Marino 		  {
4990e4b17023SJohn Marino 		    if (!e->inline_failed)
4991e4b17023SJohn Marino 		      cgraph_remove_node_and_inline_clones (e->callee);
4992e4b17023SJohn Marino 		    else
4993e4b17023SJohn Marino 	              cgraph_remove_edge (e);
4994e4b17023SJohn Marino 		  }
4995e4b17023SJohn Marino 		if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES
4996e4b17023SJohn Marino 		    && id->dst_node->clones)
4997e4b17023SJohn Marino      		  for (node = id->dst_node->clones; node != id->dst_node;)
4998e4b17023SJohn Marino 		    {
4999e4b17023SJohn Marino 	              if ((e = cgraph_edge (node, gsi_stmt (bsi))) != NULL)
5000e4b17023SJohn Marino 			{
5001e4b17023SJohn Marino 		          if (!e->inline_failed)
5002e4b17023SJohn Marino 		            cgraph_remove_node_and_inline_clones (e->callee);
5003e4b17023SJohn Marino 			  else
5004e4b17023SJohn Marino 	                    cgraph_remove_edge (e);
5005e4b17023SJohn Marino 			}
5006e4b17023SJohn Marino 
5007e4b17023SJohn Marino 		      if (node->clones)
5008e4b17023SJohn Marino 			node = node->clones;
5009e4b17023SJohn Marino 		      else if (node->next_sibling_clone)
5010e4b17023SJohn Marino 			node = node->next_sibling_clone;
5011e4b17023SJohn Marino 		      else
5012e4b17023SJohn Marino 			{
5013e4b17023SJohn Marino 			  while (node != id->dst_node && !node->next_sibling_clone)
5014e4b17023SJohn Marino 			    node = node->clone_of;
5015e4b17023SJohn Marino 			  if (node != id->dst_node)
5016e4b17023SJohn Marino 			    node = node->next_sibling_clone;
5017e4b17023SJohn Marino 			}
5018e4b17023SJohn Marino 		    }
5019e4b17023SJohn Marino 	      }
5020e4b17023SJohn Marino 	  delete_basic_block (b);
5021e4b17023SJohn Marino 	  changed = true;
5022e4b17023SJohn Marino 	}
5023e4b17023SJohn Marino     }
5024e4b17023SJohn Marino 
5025e4b17023SJohn Marino   return changed;
5026e4b17023SJohn Marino }
5027e4b17023SJohn Marino 
5028e4b17023SJohn Marino /* Update clone info after duplication.  */
5029e4b17023SJohn Marino 
5030e4b17023SJohn Marino static void
update_clone_info(copy_body_data * id)5031e4b17023SJohn Marino update_clone_info (copy_body_data * id)
5032e4b17023SJohn Marino {
5033e4b17023SJohn Marino   struct cgraph_node *node;
5034e4b17023SJohn Marino   if (!id->dst_node->clones)
5035e4b17023SJohn Marino     return;
5036e4b17023SJohn Marino   for (node = id->dst_node->clones; node != id->dst_node;)
5037e4b17023SJohn Marino     {
5038e4b17023SJohn Marino       /* First update replace maps to match the new body.  */
5039e4b17023SJohn Marino       if (node->clone.tree_map)
5040e4b17023SJohn Marino         {
5041e4b17023SJohn Marino 	  unsigned int i;
5042e4b17023SJohn Marino           for (i = 0; i < VEC_length (ipa_replace_map_p, node->clone.tree_map); i++)
5043e4b17023SJohn Marino 	    {
5044e4b17023SJohn Marino 	      struct ipa_replace_map *replace_info;
5045e4b17023SJohn Marino 	      replace_info = VEC_index (ipa_replace_map_p, node->clone.tree_map, i);
5046e4b17023SJohn Marino 	      walk_tree (&replace_info->old_tree, copy_tree_body_r, id, NULL);
5047e4b17023SJohn Marino 	      walk_tree (&replace_info->new_tree, copy_tree_body_r, id, NULL);
5048e4b17023SJohn Marino 	    }
5049e4b17023SJohn Marino 	}
5050e4b17023SJohn Marino       if (node->clones)
5051e4b17023SJohn Marino 	node = node->clones;
5052e4b17023SJohn Marino       else if (node->next_sibling_clone)
5053e4b17023SJohn Marino 	node = node->next_sibling_clone;
5054e4b17023SJohn Marino       else
5055e4b17023SJohn Marino 	{
5056e4b17023SJohn Marino 	  while (node != id->dst_node && !node->next_sibling_clone)
5057e4b17023SJohn Marino 	    node = node->clone_of;
5058e4b17023SJohn Marino 	  if (node != id->dst_node)
5059e4b17023SJohn Marino 	    node = node->next_sibling_clone;
5060e4b17023SJohn Marino 	}
5061e4b17023SJohn Marino     }
5062e4b17023SJohn Marino }
5063e4b17023SJohn Marino 
5064e4b17023SJohn Marino /* Create a copy of a function's tree.
5065e4b17023SJohn Marino    OLD_DECL and NEW_DECL are FUNCTION_DECL tree nodes
5066e4b17023SJohn Marino    of the original function and the new copied function
5067e4b17023SJohn Marino    respectively.  In case we want to replace a DECL
5068e4b17023SJohn Marino    tree with another tree while duplicating the function's
5069e4b17023SJohn Marino    body, TREE_MAP represents the mapping between these
5070e4b17023SJohn Marino    trees. If UPDATE_CLONES is set, the call_stmt fields
5071e4b17023SJohn Marino    of edges of clones of the function will be updated.
5072e4b17023SJohn Marino 
5073e4b17023SJohn Marino    If non-NULL ARGS_TO_SKIP determine function parameters to remove
5074e4b17023SJohn Marino    from new version.
5075e4b17023SJohn Marino    If SKIP_RETURN is true, the new version will return void.
5076e4b17023SJohn Marino    If non-NULL BLOCK_TO_COPY determine what basic blocks to copy.
5077e4b17023SJohn Marino    If non_NULL NEW_ENTRY determine new entry BB of the clone.
5078e4b17023SJohn Marino */
5079e4b17023SJohn Marino void
tree_function_versioning(tree old_decl,tree new_decl,VEC (ipa_replace_map_p,gc)* tree_map,bool update_clones,bitmap args_to_skip,bool skip_return,bitmap blocks_to_copy,basic_block new_entry)5080e4b17023SJohn Marino tree_function_versioning (tree old_decl, tree new_decl,
5081e4b17023SJohn Marino 			  VEC(ipa_replace_map_p,gc)* tree_map,
5082e4b17023SJohn Marino 			  bool update_clones, bitmap args_to_skip,
5083e4b17023SJohn Marino 			  bool skip_return, bitmap blocks_to_copy,
5084e4b17023SJohn Marino 			  basic_block new_entry)
5085e4b17023SJohn Marino {
5086e4b17023SJohn Marino   struct cgraph_node *old_version_node;
5087e4b17023SJohn Marino   struct cgraph_node *new_version_node;
5088e4b17023SJohn Marino   copy_body_data id;
5089e4b17023SJohn Marino   tree p;
5090e4b17023SJohn Marino   unsigned i;
5091e4b17023SJohn Marino   struct ipa_replace_map *replace_info;
5092e4b17023SJohn Marino   basic_block old_entry_block, bb;
5093e4b17023SJohn Marino   VEC (gimple, heap) *init_stmts = VEC_alloc (gimple, heap, 10);
5094e4b17023SJohn Marino 
5095e4b17023SJohn Marino   tree old_current_function_decl = current_function_decl;
5096e4b17023SJohn Marino   tree vars = NULL_TREE;
5097e4b17023SJohn Marino 
5098e4b17023SJohn Marino   gcc_assert (TREE_CODE (old_decl) == FUNCTION_DECL
5099e4b17023SJohn Marino 	      && TREE_CODE (new_decl) == FUNCTION_DECL);
5100e4b17023SJohn Marino   DECL_POSSIBLY_INLINED (old_decl) = 1;
5101e4b17023SJohn Marino 
5102e4b17023SJohn Marino   old_version_node = cgraph_get_node (old_decl);
5103e4b17023SJohn Marino   gcc_checking_assert (old_version_node);
5104e4b17023SJohn Marino   new_version_node = cgraph_get_node (new_decl);
5105e4b17023SJohn Marino   gcc_checking_assert (new_version_node);
5106e4b17023SJohn Marino 
5107e4b17023SJohn Marino   /* Copy over debug args.  */
5108e4b17023SJohn Marino   if (DECL_HAS_DEBUG_ARGS_P (old_decl))
5109e4b17023SJohn Marino     {
5110e4b17023SJohn Marino       VEC(tree, gc) **new_debug_args, **old_debug_args;
5111e4b17023SJohn Marino       gcc_checking_assert (decl_debug_args_lookup (new_decl) == NULL);
5112e4b17023SJohn Marino       DECL_HAS_DEBUG_ARGS_P (new_decl) = 0;
5113e4b17023SJohn Marino       old_debug_args = decl_debug_args_lookup (old_decl);
5114e4b17023SJohn Marino       if (old_debug_args)
5115e4b17023SJohn Marino 	{
5116e4b17023SJohn Marino 	  new_debug_args = decl_debug_args_insert (new_decl);
5117e4b17023SJohn Marino 	  *new_debug_args = VEC_copy (tree, gc, *old_debug_args);
5118e4b17023SJohn Marino 	}
5119e4b17023SJohn Marino     }
5120e4b17023SJohn Marino 
5121e4b17023SJohn Marino   /* Output the inlining info for this abstract function, since it has been
5122e4b17023SJohn Marino      inlined.  If we don't do this now, we can lose the information about the
5123e4b17023SJohn Marino      variables in the function when the blocks get blown away as soon as we
5124e4b17023SJohn Marino      remove the cgraph node.  */
5125e4b17023SJohn Marino   (*debug_hooks->outlining_inline_function) (old_decl);
5126e4b17023SJohn Marino 
5127e4b17023SJohn Marino   DECL_ARTIFICIAL (new_decl) = 1;
5128e4b17023SJohn Marino   DECL_ABSTRACT_ORIGIN (new_decl) = DECL_ORIGIN (old_decl);
5129e4b17023SJohn Marino   DECL_FUNCTION_PERSONALITY (new_decl) = DECL_FUNCTION_PERSONALITY (old_decl);
5130e4b17023SJohn Marino 
5131e4b17023SJohn Marino   /* Prepare the data structures for the tree copy.  */
5132e4b17023SJohn Marino   memset (&id, 0, sizeof (id));
5133e4b17023SJohn Marino 
5134e4b17023SJohn Marino   /* Generate a new name for the new version. */
5135e4b17023SJohn Marino   id.statements_to_fold = pointer_set_create ();
5136e4b17023SJohn Marino 
5137e4b17023SJohn Marino   id.decl_map = pointer_map_create ();
5138e4b17023SJohn Marino   id.debug_map = NULL;
5139e4b17023SJohn Marino   id.src_fn = old_decl;
5140e4b17023SJohn Marino   id.dst_fn = new_decl;
5141e4b17023SJohn Marino   id.src_node = old_version_node;
5142e4b17023SJohn Marino   id.dst_node = new_version_node;
5143e4b17023SJohn Marino   id.src_cfun = DECL_STRUCT_FUNCTION (old_decl);
5144e4b17023SJohn Marino   if (id.src_node->ipa_transforms_to_apply)
5145e4b17023SJohn Marino     {
5146e4b17023SJohn Marino       VEC(ipa_opt_pass,heap) * old_transforms_to_apply = id.dst_node->ipa_transforms_to_apply;
5147e4b17023SJohn Marino       unsigned int i;
5148e4b17023SJohn Marino 
5149e4b17023SJohn Marino       id.dst_node->ipa_transforms_to_apply = VEC_copy (ipa_opt_pass, heap,
5150e4b17023SJohn Marino 					               id.src_node->ipa_transforms_to_apply);
5151e4b17023SJohn Marino       for (i = 0; i < VEC_length (ipa_opt_pass, old_transforms_to_apply); i++)
5152e4b17023SJohn Marino         VEC_safe_push (ipa_opt_pass, heap, id.dst_node->ipa_transforms_to_apply,
5153e4b17023SJohn Marino 		       VEC_index (ipa_opt_pass,
5154e4b17023SJohn Marino 		       		  old_transforms_to_apply,
5155e4b17023SJohn Marino 				  i));
5156e4b17023SJohn Marino     }
5157e4b17023SJohn Marino 
5158e4b17023SJohn Marino   id.copy_decl = copy_decl_no_change;
5159e4b17023SJohn Marino   id.transform_call_graph_edges
5160e4b17023SJohn Marino     = update_clones ? CB_CGE_MOVE_CLONES : CB_CGE_MOVE;
5161e4b17023SJohn Marino   id.transform_new_cfg = true;
5162e4b17023SJohn Marino   id.transform_return_to_modify = false;
5163e4b17023SJohn Marino   id.transform_lang_insert_block = NULL;
5164e4b17023SJohn Marino 
5165e4b17023SJohn Marino   current_function_decl = new_decl;
5166e4b17023SJohn Marino   old_entry_block = ENTRY_BLOCK_PTR_FOR_FUNCTION
5167e4b17023SJohn Marino     (DECL_STRUCT_FUNCTION (old_decl));
5168e4b17023SJohn Marino   initialize_cfun (new_decl, old_decl,
5169e4b17023SJohn Marino 		   old_entry_block->count);
5170e4b17023SJohn Marino   DECL_STRUCT_FUNCTION (new_decl)->gimple_df->ipa_pta
5171e4b17023SJohn Marino     = id.src_cfun->gimple_df->ipa_pta;
5172e4b17023SJohn Marino   push_cfun (DECL_STRUCT_FUNCTION (new_decl));
5173e4b17023SJohn Marino 
5174e4b17023SJohn Marino   /* Copy the function's static chain.  */
5175e4b17023SJohn Marino   p = DECL_STRUCT_FUNCTION (old_decl)->static_chain_decl;
5176e4b17023SJohn Marino   if (p)
5177e4b17023SJohn Marino     DECL_STRUCT_FUNCTION (new_decl)->static_chain_decl =
5178e4b17023SJohn Marino       copy_static_chain (DECL_STRUCT_FUNCTION (old_decl)->static_chain_decl,
5179e4b17023SJohn Marino 			 &id);
5180e4b17023SJohn Marino 
5181e4b17023SJohn Marino   /* If there's a tree_map, prepare for substitution.  */
5182e4b17023SJohn Marino   if (tree_map)
5183e4b17023SJohn Marino     for (i = 0; i < VEC_length (ipa_replace_map_p, tree_map); i++)
5184e4b17023SJohn Marino       {
5185e4b17023SJohn Marino 	gimple init;
5186e4b17023SJohn Marino 	replace_info = VEC_index (ipa_replace_map_p, tree_map, i);
5187e4b17023SJohn Marino 	if (replace_info->replace_p)
5188e4b17023SJohn Marino 	  {
5189e4b17023SJohn Marino 	    tree op = replace_info->new_tree;
5190e4b17023SJohn Marino 	    if (!replace_info->old_tree)
5191e4b17023SJohn Marino 	      {
5192e4b17023SJohn Marino 		int i = replace_info->parm_num;
5193e4b17023SJohn Marino 		tree parm;
5194e4b17023SJohn Marino 		for (parm = DECL_ARGUMENTS (old_decl); i; parm = DECL_CHAIN (parm))
5195e4b17023SJohn Marino 		  i --;
5196e4b17023SJohn Marino 		replace_info->old_tree = parm;
5197e4b17023SJohn Marino 	      }
5198e4b17023SJohn Marino 
5199e4b17023SJohn Marino 
5200e4b17023SJohn Marino 	    STRIP_NOPS (op);
5201e4b17023SJohn Marino 
5202e4b17023SJohn Marino 	    if (TREE_CODE (op) == VIEW_CONVERT_EXPR)
5203e4b17023SJohn Marino 	      op = TREE_OPERAND (op, 0);
5204e4b17023SJohn Marino 
5205e4b17023SJohn Marino 	    if (TREE_CODE (op) == ADDR_EXPR)
5206e4b17023SJohn Marino 	      {
5207e4b17023SJohn Marino 		op = TREE_OPERAND (op, 0);
5208e4b17023SJohn Marino 		while (handled_component_p (op))
5209e4b17023SJohn Marino 		  op = TREE_OPERAND (op, 0);
5210e4b17023SJohn Marino 		if (TREE_CODE (op) == VAR_DECL)
5211e4b17023SJohn Marino 		  add_referenced_var (op);
5212e4b17023SJohn Marino 	      }
5213e4b17023SJohn Marino 	    gcc_assert (TREE_CODE (replace_info->old_tree) == PARM_DECL);
5214e4b17023SJohn Marino 	    init = setup_one_parameter (&id, replace_info->old_tree,
5215e4b17023SJohn Marino 	    			        replace_info->new_tree, id.src_fn,
5216e4b17023SJohn Marino 				        NULL,
5217e4b17023SJohn Marino 				        &vars);
5218e4b17023SJohn Marino 	    if (init)
5219e4b17023SJohn Marino 	      VEC_safe_push (gimple, heap, init_stmts, init);
5220e4b17023SJohn Marino 	  }
5221e4b17023SJohn Marino       }
5222e4b17023SJohn Marino   /* Copy the function's arguments.  */
5223e4b17023SJohn Marino   if (DECL_ARGUMENTS (old_decl) != NULL_TREE)
5224e4b17023SJohn Marino     DECL_ARGUMENTS (new_decl) =
5225e4b17023SJohn Marino       copy_arguments_for_versioning (DECL_ARGUMENTS (old_decl), &id,
5226e4b17023SJohn Marino       				     args_to_skip, &vars);
5227e4b17023SJohn Marino 
5228e4b17023SJohn Marino   DECL_INITIAL (new_decl) = remap_blocks (DECL_INITIAL (id.src_fn), &id);
5229e4b17023SJohn Marino   BLOCK_SUPERCONTEXT (DECL_INITIAL (new_decl)) = new_decl;
5230e4b17023SJohn Marino 
5231e4b17023SJohn Marino   declare_inline_vars (DECL_INITIAL (new_decl), vars);
5232e4b17023SJohn Marino 
5233e4b17023SJohn Marino   if (!VEC_empty (tree, DECL_STRUCT_FUNCTION (old_decl)->local_decls))
5234e4b17023SJohn Marino     /* Add local vars.  */
5235e4b17023SJohn Marino     add_local_variables (DECL_STRUCT_FUNCTION (old_decl), cfun, &id, false);
5236e4b17023SJohn Marino 
5237e4b17023SJohn Marino   if (DECL_RESULT (old_decl) == NULL_TREE)
5238e4b17023SJohn Marino     ;
5239e4b17023SJohn Marino   else if (skip_return && !VOID_TYPE_P (TREE_TYPE (DECL_RESULT (old_decl))))
5240e4b17023SJohn Marino     {
5241e4b17023SJohn Marino       DECL_RESULT (new_decl)
5242e4b17023SJohn Marino 	= build_decl (DECL_SOURCE_LOCATION (DECL_RESULT (old_decl)),
5243e4b17023SJohn Marino 		      RESULT_DECL, NULL_TREE, void_type_node);
5244e4b17023SJohn Marino       DECL_CONTEXT (DECL_RESULT (new_decl)) = new_decl;
5245e4b17023SJohn Marino       cfun->returns_struct = 0;
5246e4b17023SJohn Marino       cfun->returns_pcc_struct = 0;
5247e4b17023SJohn Marino     }
5248e4b17023SJohn Marino   else
5249e4b17023SJohn Marino     {
5250e4b17023SJohn Marino       tree old_name;
5251e4b17023SJohn Marino       DECL_RESULT (new_decl) = remap_decl (DECL_RESULT (old_decl), &id);
5252e4b17023SJohn Marino       lang_hooks.dup_lang_specific_decl (DECL_RESULT (new_decl));
5253e4b17023SJohn Marino       if (gimple_in_ssa_p (id.src_cfun)
5254e4b17023SJohn Marino 	  && DECL_BY_REFERENCE (DECL_RESULT (old_decl))
5255e4b17023SJohn Marino 	  && (old_name
5256e4b17023SJohn Marino 	      = gimple_default_def (id.src_cfun, DECL_RESULT (old_decl))))
5257e4b17023SJohn Marino 	{
5258e4b17023SJohn Marino 	  tree new_name = make_ssa_name (DECL_RESULT (new_decl), NULL);
5259e4b17023SJohn Marino 	  insert_decl_map (&id, old_name, new_name);
5260e4b17023SJohn Marino 	  SSA_NAME_DEF_STMT (new_name) = gimple_build_nop ();
5261e4b17023SJohn Marino 	  set_default_def (DECL_RESULT (new_decl), new_name);
5262e4b17023SJohn Marino 	}
5263e4b17023SJohn Marino     }
5264e4b17023SJohn Marino 
5265e4b17023SJohn Marino   /* Copy the Function's body.  */
5266e4b17023SJohn Marino   copy_body (&id, old_entry_block->count, REG_BR_PROB_BASE,
5267e4b17023SJohn Marino 	     ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, blocks_to_copy, new_entry);
5268e4b17023SJohn Marino 
5269e4b17023SJohn Marino   /* Renumber the lexical scoping (non-code) blocks consecutively.  */
5270e4b17023SJohn Marino   number_blocks (new_decl);
5271e4b17023SJohn Marino 
5272e4b17023SJohn Marino   /* We want to create the BB unconditionally, so that the addition of
5273e4b17023SJohn Marino      debug stmts doesn't affect BB count, which may in the end cause
5274e4b17023SJohn Marino      codegen differences.  */
5275e4b17023SJohn Marino   bb = split_edge (single_succ_edge (ENTRY_BLOCK_PTR));
5276e4b17023SJohn Marino   while (VEC_length (gimple, init_stmts))
5277e4b17023SJohn Marino     insert_init_stmt (&id, bb, VEC_pop (gimple, init_stmts));
5278e4b17023SJohn Marino   update_clone_info (&id);
5279e4b17023SJohn Marino 
5280e4b17023SJohn Marino   /* Remap the nonlocal_goto_save_area, if any.  */
5281e4b17023SJohn Marino   if (cfun->nonlocal_goto_save_area)
5282e4b17023SJohn Marino     {
5283e4b17023SJohn Marino       struct walk_stmt_info wi;
5284e4b17023SJohn Marino 
5285e4b17023SJohn Marino       memset (&wi, 0, sizeof (wi));
5286e4b17023SJohn Marino       wi.info = &id;
5287e4b17023SJohn Marino       walk_tree (&cfun->nonlocal_goto_save_area, remap_gimple_op_r, &wi, NULL);
5288e4b17023SJohn Marino     }
5289e4b17023SJohn Marino 
5290e4b17023SJohn Marino   /* Clean up.  */
5291e4b17023SJohn Marino   pointer_map_destroy (id.decl_map);
5292e4b17023SJohn Marino   if (id.debug_map)
5293e4b17023SJohn Marino     pointer_map_destroy (id.debug_map);
5294e4b17023SJohn Marino   free_dominance_info (CDI_DOMINATORS);
5295e4b17023SJohn Marino   free_dominance_info (CDI_POST_DOMINATORS);
5296e4b17023SJohn Marino 
5297e4b17023SJohn Marino   fold_marked_statements (0, id.statements_to_fold);
5298e4b17023SJohn Marino   pointer_set_destroy (id.statements_to_fold);
5299e4b17023SJohn Marino   fold_cond_expr_cond ();
5300e4b17023SJohn Marino   delete_unreachable_blocks_update_callgraph (&id);
5301e4b17023SJohn Marino   if (id.dst_node->analyzed)
5302e4b17023SJohn Marino     cgraph_rebuild_references ();
5303e4b17023SJohn Marino   update_ssa (TODO_update_ssa);
5304e4b17023SJohn Marino 
5305e4b17023SJohn Marino   /* After partial cloning we need to rescale frequencies, so they are
5306e4b17023SJohn Marino      within proper range in the cloned function.  */
5307e4b17023SJohn Marino   if (new_entry)
5308e4b17023SJohn Marino     {
5309e4b17023SJohn Marino       struct cgraph_edge *e;
5310e4b17023SJohn Marino       rebuild_frequencies ();
5311e4b17023SJohn Marino 
5312e4b17023SJohn Marino       new_version_node->count = ENTRY_BLOCK_PTR->count;
5313e4b17023SJohn Marino       for (e = new_version_node->callees; e; e = e->next_callee)
5314e4b17023SJohn Marino 	{
5315e4b17023SJohn Marino 	  basic_block bb = gimple_bb (e->call_stmt);
5316e4b17023SJohn Marino 	  e->frequency = compute_call_stmt_bb_frequency (current_function_decl,
5317e4b17023SJohn Marino 							 bb);
5318e4b17023SJohn Marino 	  e->count = bb->count;
5319e4b17023SJohn Marino 	}
5320e4b17023SJohn Marino       for (e = new_version_node->indirect_calls; e; e = e->next_callee)
5321e4b17023SJohn Marino 	{
5322e4b17023SJohn Marino 	  basic_block bb = gimple_bb (e->call_stmt);
5323e4b17023SJohn Marino 	  e->frequency = compute_call_stmt_bb_frequency (current_function_decl,
5324e4b17023SJohn Marino 							 bb);
5325e4b17023SJohn Marino 	  e->count = bb->count;
5326e4b17023SJohn Marino 	}
5327e4b17023SJohn Marino     }
5328e4b17023SJohn Marino 
5329e4b17023SJohn Marino   free_dominance_info (CDI_DOMINATORS);
5330e4b17023SJohn Marino   free_dominance_info (CDI_POST_DOMINATORS);
5331e4b17023SJohn Marino 
5332e4b17023SJohn Marino   gcc_assert (!id.debug_stmts);
5333e4b17023SJohn Marino   VEC_free (gimple, heap, init_stmts);
5334e4b17023SJohn Marino   pop_cfun ();
5335e4b17023SJohn Marino   current_function_decl = old_current_function_decl;
5336e4b17023SJohn Marino   gcc_assert (!current_function_decl
5337e4b17023SJohn Marino 	      || DECL_STRUCT_FUNCTION (current_function_decl) == cfun);
5338e4b17023SJohn Marino   return;
5339e4b17023SJohn Marino }
5340e4b17023SJohn Marino 
5341e4b17023SJohn Marino /* EXP is CALL_EXPR present in a GENERIC expression tree.  Try to integrate
5342e4b17023SJohn Marino    the callee and return the inlined body on success.  */
5343e4b17023SJohn Marino 
5344e4b17023SJohn Marino tree
maybe_inline_call_in_expr(tree exp)5345e4b17023SJohn Marino maybe_inline_call_in_expr (tree exp)
5346e4b17023SJohn Marino {
5347e4b17023SJohn Marino   tree fn = get_callee_fndecl (exp);
5348e4b17023SJohn Marino 
5349e4b17023SJohn Marino   /* We can only try to inline "const" functions.  */
5350e4b17023SJohn Marino   if (fn && TREE_READONLY (fn) && DECL_SAVED_TREE (fn))
5351e4b17023SJohn Marino     {
5352e4b17023SJohn Marino       struct pointer_map_t *decl_map = pointer_map_create ();
5353e4b17023SJohn Marino       call_expr_arg_iterator iter;
5354e4b17023SJohn Marino       copy_body_data id;
5355e4b17023SJohn Marino       tree param, arg, t;
5356e4b17023SJohn Marino 
5357e4b17023SJohn Marino       /* Remap the parameters.  */
5358e4b17023SJohn Marino       for (param = DECL_ARGUMENTS (fn), arg = first_call_expr_arg (exp, &iter);
5359e4b17023SJohn Marino 	   param;
5360e4b17023SJohn Marino 	   param = DECL_CHAIN (param), arg = next_call_expr_arg (&iter))
5361e4b17023SJohn Marino 	*pointer_map_insert (decl_map, param) = arg;
5362e4b17023SJohn Marino 
5363e4b17023SJohn Marino       memset (&id, 0, sizeof (id));
5364e4b17023SJohn Marino       id.src_fn = fn;
5365e4b17023SJohn Marino       id.dst_fn = current_function_decl;
5366e4b17023SJohn Marino       id.src_cfun = DECL_STRUCT_FUNCTION (fn);
5367e4b17023SJohn Marino       id.decl_map = decl_map;
5368e4b17023SJohn Marino 
5369e4b17023SJohn Marino       id.copy_decl = copy_decl_no_change;
5370e4b17023SJohn Marino       id.transform_call_graph_edges = CB_CGE_DUPLICATE;
5371e4b17023SJohn Marino       id.transform_new_cfg = false;
5372e4b17023SJohn Marino       id.transform_return_to_modify = true;
5373e4b17023SJohn Marino       id.transform_lang_insert_block = NULL;
5374e4b17023SJohn Marino 
5375e4b17023SJohn Marino       /* Make sure not to unshare trees behind the front-end's back
5376e4b17023SJohn Marino 	 since front-end specific mechanisms may rely on sharing.  */
5377e4b17023SJohn Marino       id.regimplify = false;
5378e4b17023SJohn Marino       id.do_not_unshare = true;
5379e4b17023SJohn Marino 
5380e4b17023SJohn Marino       /* We're not inside any EH region.  */
5381e4b17023SJohn Marino       id.eh_lp_nr = 0;
5382e4b17023SJohn Marino 
5383e4b17023SJohn Marino       t = copy_tree_body (&id);
5384e4b17023SJohn Marino       pointer_map_destroy (decl_map);
5385e4b17023SJohn Marino 
5386e4b17023SJohn Marino       /* We can only return something suitable for use in a GENERIC
5387e4b17023SJohn Marino 	 expression tree.  */
5388e4b17023SJohn Marino       if (TREE_CODE (t) == MODIFY_EXPR)
5389e4b17023SJohn Marino 	return TREE_OPERAND (t, 1);
5390e4b17023SJohn Marino     }
5391e4b17023SJohn Marino 
5392e4b17023SJohn Marino    return NULL_TREE;
5393e4b17023SJohn Marino }
5394e4b17023SJohn Marino 
5395e4b17023SJohn Marino /* Duplicate a type, fields and all.  */
5396e4b17023SJohn Marino 
5397e4b17023SJohn Marino tree
build_duplicate_type(tree type)5398e4b17023SJohn Marino build_duplicate_type (tree type)
5399e4b17023SJohn Marino {
5400e4b17023SJohn Marino   struct copy_body_data id;
5401e4b17023SJohn Marino 
5402e4b17023SJohn Marino   memset (&id, 0, sizeof (id));
5403e4b17023SJohn Marino   id.src_fn = current_function_decl;
5404e4b17023SJohn Marino   id.dst_fn = current_function_decl;
5405e4b17023SJohn Marino   id.src_cfun = cfun;
5406e4b17023SJohn Marino   id.decl_map = pointer_map_create ();
5407e4b17023SJohn Marino   id.debug_map = NULL;
5408e4b17023SJohn Marino   id.copy_decl = copy_decl_no_change;
5409e4b17023SJohn Marino 
5410e4b17023SJohn Marino   type = remap_type_1 (type, &id);
5411e4b17023SJohn Marino 
5412e4b17023SJohn Marino   pointer_map_destroy (id.decl_map);
5413e4b17023SJohn Marino   if (id.debug_map)
5414e4b17023SJohn Marino     pointer_map_destroy (id.debug_map);
5415e4b17023SJohn Marino 
5416e4b17023SJohn Marino   TYPE_CANONICAL (type) = type;
5417e4b17023SJohn Marino 
5418e4b17023SJohn Marino   return type;
5419 }
5420