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 (©_gsi);
1602e4b17023SJohn Marino
1603e4b17023SJohn Marino /* Process the new statement. The call to gimple_regimplify_operands
1604e4b17023SJohn Marino possibly turned the statement into multiple statements, we
1605e4b17023SJohn Marino need to process all of them. */
1606e4b17023SJohn Marino do
1607e4b17023SJohn Marino {
1608e4b17023SJohn Marino tree fn;
1609e4b17023SJohn Marino
1610e4b17023SJohn Marino stmt = gsi_stmt (copy_gsi);
1611e4b17023SJohn Marino if (is_gimple_call (stmt)
1612e4b17023SJohn Marino && gimple_call_va_arg_pack_p (stmt)
1613e4b17023SJohn Marino && id->gimple_call)
1614e4b17023SJohn Marino {
1615e4b17023SJohn Marino /* __builtin_va_arg_pack () should be replaced by
1616e4b17023SJohn Marino all arguments corresponding to ... in the caller. */
1617e4b17023SJohn Marino tree p;
1618e4b17023SJohn Marino gimple new_call;
1619e4b17023SJohn Marino VEC(tree, heap) *argarray;
1620e4b17023SJohn Marino size_t nargs = gimple_call_num_args (id->gimple_call);
1621e4b17023SJohn Marino size_t n;
1622e4b17023SJohn Marino
1623e4b17023SJohn Marino for (p = DECL_ARGUMENTS (id->src_fn); p; p = DECL_CHAIN (p))
1624e4b17023SJohn Marino nargs--;
1625e4b17023SJohn Marino
1626e4b17023SJohn Marino /* Create the new array of arguments. */
1627e4b17023SJohn Marino n = nargs + gimple_call_num_args (stmt);
1628e4b17023SJohn Marino argarray = VEC_alloc (tree, heap, n);
1629e4b17023SJohn Marino VEC_safe_grow (tree, heap, argarray, n);
1630e4b17023SJohn Marino
1631e4b17023SJohn Marino /* Copy all the arguments before '...' */
1632e4b17023SJohn Marino memcpy (VEC_address (tree, argarray),
1633e4b17023SJohn Marino gimple_call_arg_ptr (stmt, 0),
1634e4b17023SJohn Marino gimple_call_num_args (stmt) * sizeof (tree));
1635e4b17023SJohn Marino
1636e4b17023SJohn Marino /* Append the arguments passed in '...' */
1637e4b17023SJohn Marino memcpy (VEC_address(tree, argarray) + gimple_call_num_args (stmt),
1638e4b17023SJohn Marino gimple_call_arg_ptr (id->gimple_call, 0)
1639e4b17023SJohn Marino + (gimple_call_num_args (id->gimple_call) - nargs),
1640e4b17023SJohn Marino nargs * sizeof (tree));
1641e4b17023SJohn Marino
1642e4b17023SJohn Marino new_call = gimple_build_call_vec (gimple_call_fn (stmt),
1643e4b17023SJohn Marino argarray);
1644e4b17023SJohn Marino
1645e4b17023SJohn Marino VEC_free (tree, heap, argarray);
1646e4b17023SJohn Marino
1647e4b17023SJohn Marino /* Copy all GIMPLE_CALL flags, location and block, except
1648e4b17023SJohn Marino GF_CALL_VA_ARG_PACK. */
1649e4b17023SJohn Marino gimple_call_copy_flags (new_call, stmt);
1650e4b17023SJohn Marino gimple_call_set_va_arg_pack (new_call, false);
1651e4b17023SJohn Marino gimple_set_location (new_call, gimple_location (stmt));
1652e4b17023SJohn Marino gimple_set_block (new_call, gimple_block (stmt));
1653e4b17023SJohn Marino gimple_call_set_lhs (new_call, gimple_call_lhs (stmt));
1654e4b17023SJohn Marino
1655e4b17023SJohn Marino gsi_replace (©_gsi, new_call, false);
1656e4b17023SJohn Marino stmt = new_call;
1657e4b17023SJohn Marino }
1658e4b17023SJohn Marino else if (is_gimple_call (stmt)
1659e4b17023SJohn Marino && id->gimple_call
1660e4b17023SJohn Marino && (decl = gimple_call_fndecl (stmt))
1661e4b17023SJohn Marino && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
1662e4b17023SJohn Marino && DECL_FUNCTION_CODE (decl) == BUILT_IN_VA_ARG_PACK_LEN)
1663e4b17023SJohn Marino {
1664e4b17023SJohn Marino /* __builtin_va_arg_pack_len () should be replaced by
1665e4b17023SJohn Marino the number of anonymous arguments. */
1666e4b17023SJohn Marino size_t nargs = gimple_call_num_args (id->gimple_call);
1667e4b17023SJohn Marino tree count, p;
1668e4b17023SJohn Marino gimple new_stmt;
1669e4b17023SJohn Marino
1670e4b17023SJohn Marino for (p = DECL_ARGUMENTS (id->src_fn); p; p = DECL_CHAIN (p))
1671e4b17023SJohn Marino nargs--;
1672e4b17023SJohn Marino
1673e4b17023SJohn Marino count = build_int_cst (integer_type_node, nargs);
1674e4b17023SJohn Marino new_stmt = gimple_build_assign (gimple_call_lhs (stmt), count);
1675e4b17023SJohn Marino gsi_replace (©_gsi, new_stmt, false);
1676e4b17023SJohn Marino stmt = new_stmt;
1677e4b17023SJohn Marino }
1678e4b17023SJohn Marino
1679e4b17023SJohn Marino /* Statements produced by inlining can be unfolded, especially
1680e4b17023SJohn Marino when we constant propagated some operands. We can't fold
1681e4b17023SJohn Marino them right now for two reasons:
1682e4b17023SJohn Marino 1) folding require SSA_NAME_DEF_STMTs to be correct
1683e4b17023SJohn Marino 2) we can't change function calls to builtins.
1684e4b17023SJohn Marino So we just mark statement for later folding. We mark
1685e4b17023SJohn Marino all new statements, instead just statements that has changed
1686e4b17023SJohn Marino by some nontrivial substitution so even statements made
1687e4b17023SJohn Marino foldable indirectly are updated. If this turns out to be
1688e4b17023SJohn Marino expensive, copy_body can be told to watch for nontrivial
1689e4b17023SJohn Marino changes. */
1690e4b17023SJohn Marino if (id->statements_to_fold)
1691e4b17023SJohn Marino pointer_set_insert (id->statements_to_fold, stmt);
1692e4b17023SJohn Marino
1693e4b17023SJohn Marino /* We're duplicating a CALL_EXPR. Find any corresponding
1694e4b17023SJohn Marino callgraph edges and update or duplicate them. */
1695e4b17023SJohn Marino if (is_gimple_call (stmt))
1696e4b17023SJohn Marino {
1697e4b17023SJohn Marino struct cgraph_edge *edge;
1698e4b17023SJohn Marino int flags;
1699e4b17023SJohn Marino
1700e4b17023SJohn Marino switch (id->transform_call_graph_edges)
1701e4b17023SJohn Marino {
1702e4b17023SJohn Marino case CB_CGE_DUPLICATE:
1703e4b17023SJohn Marino edge = cgraph_edge (id->src_node, orig_stmt);
1704e4b17023SJohn Marino if (edge)
1705e4b17023SJohn Marino {
1706e4b17023SJohn Marino int edge_freq = edge->frequency;
1707e4b17023SJohn Marino edge = cgraph_clone_edge (edge, id->dst_node, stmt,
1708e4b17023SJohn Marino gimple_uid (stmt),
1709e4b17023SJohn Marino REG_BR_PROB_BASE, CGRAPH_FREQ_BASE,
1710e4b17023SJohn Marino true);
1711e4b17023SJohn Marino /* We could also just rescale the frequency, but
1712e4b17023SJohn Marino doing so would introduce roundoff errors and make
1713e4b17023SJohn Marino verifier unhappy. */
1714e4b17023SJohn Marino edge->frequency
1715e4b17023SJohn Marino = compute_call_stmt_bb_frequency (id->dst_node->decl,
1716e4b17023SJohn Marino copy_basic_block);
1717e4b17023SJohn Marino if (dump_file
1718e4b17023SJohn Marino && profile_status_for_function (cfun) != PROFILE_ABSENT
1719e4b17023SJohn Marino && (edge_freq > edge->frequency + 10
1720e4b17023SJohn Marino || edge_freq < edge->frequency - 10))
1721e4b17023SJohn Marino {
1722e4b17023SJohn Marino fprintf (dump_file, "Edge frequency estimated by "
1723e4b17023SJohn Marino "cgraph %i diverge from inliner's estimate %i\n",
1724e4b17023SJohn Marino edge_freq,
1725e4b17023SJohn Marino edge->frequency);
1726e4b17023SJohn Marino fprintf (dump_file,
1727e4b17023SJohn Marino "Orig bb: %i, orig bb freq %i, new bb freq %i\n",
1728e4b17023SJohn Marino bb->index,
1729e4b17023SJohn Marino bb->frequency,
1730e4b17023SJohn Marino copy_basic_block->frequency);
1731e4b17023SJohn Marino }
1732e4b17023SJohn Marino stmt = cgraph_redirect_edge_call_stmt_to_callee (edge);
1733e4b17023SJohn Marino }
1734e4b17023SJohn Marino break;
1735e4b17023SJohn Marino
1736e4b17023SJohn Marino case CB_CGE_MOVE_CLONES:
1737e4b17023SJohn Marino cgraph_set_call_stmt_including_clones (id->dst_node,
1738e4b17023SJohn Marino orig_stmt, stmt);
1739e4b17023SJohn Marino edge = cgraph_edge (id->dst_node, stmt);
1740e4b17023SJohn Marino break;
1741e4b17023SJohn Marino
1742e4b17023SJohn Marino case CB_CGE_MOVE:
1743e4b17023SJohn Marino edge = cgraph_edge (id->dst_node, orig_stmt);
1744e4b17023SJohn Marino if (edge)
1745e4b17023SJohn Marino cgraph_set_call_stmt (edge, stmt);
1746e4b17023SJohn Marino break;
1747e4b17023SJohn Marino
1748e4b17023SJohn Marino default:
1749e4b17023SJohn Marino gcc_unreachable ();
1750e4b17023SJohn Marino }
1751e4b17023SJohn Marino
1752e4b17023SJohn Marino /* Constant propagation on argument done during inlining
1753e4b17023SJohn Marino may create new direct call. Produce an edge for it. */
1754e4b17023SJohn Marino if ((!edge
1755e4b17023SJohn Marino || (edge->indirect_inlining_edge
1756e4b17023SJohn Marino && id->transform_call_graph_edges == CB_CGE_MOVE_CLONES))
1757e4b17023SJohn Marino && id->dst_node->analyzed
1758e4b17023SJohn Marino && (fn = gimple_call_fndecl (stmt)) != NULL)
1759e4b17023SJohn Marino {
1760e4b17023SJohn Marino struct cgraph_node *dest = cgraph_get_node (fn);
1761e4b17023SJohn Marino
1762e4b17023SJohn Marino /* We have missing edge in the callgraph. This can happen
1763e4b17023SJohn Marino when previous inlining turned an indirect call into a
1764e4b17023SJohn Marino direct call by constant propagating arguments or we are
1765e4b17023SJohn Marino producing dead clone (for further cloning). In all
1766e4b17023SJohn Marino other cases we hit a bug (incorrect node sharing is the
1767e4b17023SJohn Marino most common reason for missing edges). */
1768e4b17023SJohn Marino gcc_assert (dest->needed || !dest->analyzed
1769e4b17023SJohn Marino || dest->address_taken
1770e4b17023SJohn Marino || !id->src_node->analyzed
1771e4b17023SJohn Marino || !id->dst_node->analyzed);
1772e4b17023SJohn Marino if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES)
1773e4b17023SJohn Marino cgraph_create_edge_including_clones
1774e4b17023SJohn Marino (id->dst_node, dest, orig_stmt, stmt, bb->count,
1775e4b17023SJohn Marino compute_call_stmt_bb_frequency (id->dst_node->decl,
1776e4b17023SJohn Marino copy_basic_block),
1777e4b17023SJohn Marino CIF_ORIGINALLY_INDIRECT_CALL);
1778e4b17023SJohn Marino else
1779e4b17023SJohn Marino cgraph_create_edge (id->dst_node, dest, stmt,
1780e4b17023SJohn Marino bb->count,
1781e4b17023SJohn Marino compute_call_stmt_bb_frequency
1782e4b17023SJohn Marino (id->dst_node->decl, copy_basic_block))->inline_failed
1783e4b17023SJohn Marino = CIF_ORIGINALLY_INDIRECT_CALL;
1784e4b17023SJohn Marino if (dump_file)
1785e4b17023SJohn Marino {
1786e4b17023SJohn Marino fprintf (dump_file, "Created new direct edge to %s\n",
1787e4b17023SJohn Marino cgraph_node_name (dest));
1788e4b17023SJohn Marino }
1789e4b17023SJohn Marino }
1790e4b17023SJohn Marino
1791e4b17023SJohn Marino flags = gimple_call_flags (stmt);
1792e4b17023SJohn Marino if (flags & ECF_MAY_BE_ALLOCA)
1793e4b17023SJohn Marino cfun->calls_alloca = true;
1794e4b17023SJohn Marino if (flags & ECF_RETURNS_TWICE)
1795e4b17023SJohn Marino cfun->calls_setjmp = true;
1796e4b17023SJohn Marino }
1797e4b17023SJohn Marino
1798e4b17023SJohn Marino maybe_duplicate_eh_stmt_fn (cfun, stmt, id->src_cfun, orig_stmt,
1799e4b17023SJohn Marino id->eh_map, id->eh_lp_nr);
1800e4b17023SJohn Marino
1801e4b17023SJohn Marino if (gimple_in_ssa_p (cfun) && !is_gimple_debug (stmt))
1802e4b17023SJohn Marino {
1803e4b17023SJohn Marino ssa_op_iter i;
1804e4b17023SJohn Marino tree def;
1805e4b17023SJohn Marino
1806e4b17023SJohn Marino find_new_referenced_vars (gsi_stmt (copy_gsi));
1807e4b17023SJohn Marino FOR_EACH_SSA_TREE_OPERAND (def, stmt, i, SSA_OP_DEF)
1808e4b17023SJohn Marino if (TREE_CODE (def) == SSA_NAME)
1809e4b17023SJohn Marino SSA_NAME_DEF_STMT (def) = stmt;
1810e4b17023SJohn Marino }
1811e4b17023SJohn Marino
1812e4b17023SJohn Marino gsi_next (©_gsi);
1813e4b17023SJohn Marino }
1814e4b17023SJohn Marino while (!gsi_end_p (copy_gsi));
1815e4b17023SJohn Marino
1816e4b17023SJohn Marino copy_gsi = gsi_last_bb (copy_basic_block);
1817e4b17023SJohn Marino }
1818e4b17023SJohn Marino
1819e4b17023SJohn Marino return copy_basic_block;
1820e4b17023SJohn Marino }
1821e4b17023SJohn Marino
1822e4b17023SJohn Marino /* Inserting Single Entry Multiple Exit region in SSA form into code in SSA
1823e4b17023SJohn Marino form is quite easy, since dominator relationship for old basic blocks does
1824e4b17023SJohn Marino not change.
1825e4b17023SJohn Marino
1826e4b17023SJohn Marino There is however exception where inlining might change dominator relation
1827e4b17023SJohn Marino across EH edges from basic block within inlined functions destinating
1828e4b17023SJohn Marino to landing pads in function we inline into.
1829e4b17023SJohn Marino
1830e4b17023SJohn Marino The function fills in PHI_RESULTs of such PHI nodes if they refer
1831e4b17023SJohn Marino to gimple regs. Otherwise, the function mark PHI_RESULT of such
1832e4b17023SJohn Marino PHI nodes for renaming. For non-gimple regs, renaming is safe: the
1833e4b17023SJohn Marino EH edges are abnormal and SSA_NAME_OCCURS_IN_ABNORMAL_PHI must be
1834e4b17023SJohn Marino set, and this means that there will be no overlapping live ranges
1835e4b17023SJohn Marino for the underlying symbol.
1836e4b17023SJohn Marino
1837e4b17023SJohn Marino This might change in future if we allow redirecting of EH edges and
1838e4b17023SJohn Marino we might want to change way build CFG pre-inlining to include
1839e4b17023SJohn Marino all the possible edges then. */
1840e4b17023SJohn Marino static void
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