Branch data Line data Source code
1 : : /* Manipulation of formal and actual parameters of functions and function
2 : : calls.
3 : : Copyright (C) 2017-2025 Free Software Foundation, Inc.
4 : :
5 : : This file is part of GCC.
6 : :
7 : : GCC is free software; you can redistribute it and/or modify it under
8 : : the terms of the GNU General Public License as published by the Free
9 : : Software Foundation; either version 3, or (at your option) any later
10 : : version.
11 : :
12 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 : : for more details.
16 : :
17 : : You should have received a copy of the GNU General Public License
18 : : along with GCC; see the file COPYING3. If not see
19 : : <http://www.gnu.org/licenses/>. */
20 : :
21 : : #define INCLUDE_ALGORITHM
22 : : #include "config.h"
23 : : #include "system.h"
24 : : #include "coretypes.h"
25 : : #include "backend.h"
26 : : #include "tree.h"
27 : : #include "gimple.h"
28 : : #include "ssa.h"
29 : : #include "cgraph.h"
30 : : #include "fold-const.h"
31 : : #include "tree-eh.h"
32 : : #include "stor-layout.h"
33 : : #include "gimplify.h"
34 : : #include "gimple-iterator.h"
35 : : #include "gimplify-me.h"
36 : : #include "tree-cfg.h"
37 : : #include "tree-dfa.h"
38 : : #include "ipa-param-manipulation.h"
39 : : #include "print-tree.h"
40 : : #include "gimple-pretty-print.h"
41 : : #include "builtins.h"
42 : : #include "tree-ssa.h"
43 : : #include "tree-inline.h"
44 : : #include "alloc-pool.h"
45 : : #include "symbol-summary.h"
46 : : #include "symtab-clones.h"
47 : : #include "tree-phinodes.h"
48 : : #include "cfgexpand.h"
49 : : #include "attribs.h"
50 : : #include "sreal.h"
51 : : #include "ipa-cp.h"
52 : : #include "ipa-prop.h"
53 : :
54 : : /* Actual prefixes of different newly synthetized parameters. Keep in sync
55 : : with IPA_PARAM_PREFIX_* defines. */
56 : :
57 : : static const char *ipa_param_prefixes[IPA_PARAM_PREFIX_COUNT]
58 : : = {"SYNTH",
59 : : "ISRA",
60 : : "simd",
61 : : "mask"};
62 : :
63 : : /* Names of parameters for dumping. Keep in sync with enum ipa_parm_op. */
64 : :
65 : : static const char *ipa_param_op_names[IPA_PARAM_PREFIX_COUNT]
66 : : = {"IPA_PARAM_OP_UNDEFINED",
67 : : "IPA_PARAM_OP_COPY",
68 : : "IPA_PARAM_OP_NEW",
69 : : "IPA_PARAM_OP_SPLIT"};
70 : :
71 : : /* Structure to hold declarations representing pass-through IPA-SRA splits. In
72 : : essence, it tells new index for a combination of original index and
73 : : offset. */
74 : :
75 : : struct pass_through_split_map
76 : : {
77 : : /* Original argument index. */
78 : : unsigned base_index;
79 : : /* Offset of the split part in the original argument. */
80 : : unsigned unit_offset;
81 : : /* Index of the split part in the call statement - where clone
82 : : materialization put it. */
83 : : int new_index;
84 : : };
85 : :
86 : : /* Information about some call statements that needs to be conveyed from clone
87 : : materialization to edge redirection. */
88 : :
89 : 52954 : class ipa_edge_modification_info
90 : : {
91 : : public:
92 : 52954 : ipa_edge_modification_info ()
93 : 52954 : {}
94 : :
95 : : /* Mapping of original argument indices to where those arguments sit in the
96 : : call statement now or to a negative index if they were removed. */
97 : : auto_vec<int> index_map;
98 : : /* Information about ISRA replacements put into the call statement at the
99 : : clone materialization stages. */
100 : : auto_vec<pass_through_split_map> pass_through_map;
101 : : /* Necessary adjustment to ipa_param_adjustments::m_always_copy_start when
102 : : redirecting the call. */
103 : : int always_copy_delta = 0;
104 : : };
105 : :
106 : : /* Class for storing and retrieving summaries about cal statement
107 : : modifications. */
108 : :
109 : : class ipa_edge_modification_sum
110 : : : public call_summary <ipa_edge_modification_info *>
111 : : {
112 : : public:
113 : 2312 : ipa_edge_modification_sum (symbol_table *table)
114 : 4624 : : call_summary<ipa_edge_modification_info *> (table)
115 : : {
116 : : }
117 : :
118 : : /* Hook that is called by summary when an edge is duplicated. */
119 : :
120 : 24410 : void duplicate (cgraph_edge *,
121 : : cgraph_edge *,
122 : : ipa_edge_modification_info *old_info,
123 : : ipa_edge_modification_info *new_info) final override
124 : : {
125 : 24410 : new_info->index_map.safe_splice (old_info->index_map);
126 : 24410 : new_info->pass_through_map.safe_splice (old_info->pass_through_map);
127 : 24410 : new_info->always_copy_delta = old_info->always_copy_delta;
128 : 24410 : }
129 : : };
130 : :
131 : : /* Call summary to store information about edges which have had their arguments
132 : : partially modified already. */
133 : :
134 : : static ipa_edge_modification_sum *ipa_edge_modifications;
135 : :
136 : : /* Fail compilation if CS has any summary associated with it in
137 : : ipa_edge_modifications. */
138 : :
139 : : DEBUG_FUNCTION void
140 : 286709 : ipa_verify_edge_has_no_modifications (cgraph_edge *cs)
141 : : {
142 : 286709 : gcc_assert (!ipa_edge_modifications || !ipa_edge_modifications->get (cs));
143 : 286709 : }
144 : :
145 : : /* Fill an empty vector ARGS with PARM_DECLs representing formal parameters of
146 : : FNDECL. The function should not be called during LTO WPA phase except for
147 : : thunks (or functions with bodies streamed in). */
148 : :
149 : : void
150 : 172347 : push_function_arg_decls (vec<tree> *args, tree fndecl)
151 : : {
152 : 172347 : int count;
153 : 172347 : tree parm;
154 : :
155 : : /* Safety check that we do not attempt to use the function in WPA, except
156 : : when the function is a thunk and then we have DECL_ARGUMENTS or when we
157 : : have already explicitely loaded its body. */
158 : 172348 : gcc_assert (!flag_wpa
159 : : || DECL_ARGUMENTS (fndecl)
160 : : || gimple_has_body_p (fndecl));
161 : 172347 : count = 0;
162 : 611315 : for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm))
163 : 438968 : count++;
164 : :
165 : 172347 : args->reserve_exact (count);
166 : 611315 : for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm))
167 : 438968 : args->quick_push (parm);
168 : 172347 : }
169 : :
170 : : /* Fill an empty vector TYPES with trees representing formal parameters of
171 : : function type FNTYPE. */
172 : :
173 : : void
174 : 391592 : push_function_arg_types (vec<tree> *types, tree fntype)
175 : : {
176 : 391592 : int count = 0;
177 : 391592 : tree t;
178 : :
179 : 1790365 : for (t = TYPE_ARG_TYPES (fntype); t; t = TREE_CHAIN (t))
180 : 1398773 : count++;
181 : :
182 : 391592 : types->reserve_exact (count);
183 : 1790365 : for (t = TYPE_ARG_TYPES (fntype); t; t = TREE_CHAIN (t))
184 : 1398773 : types->quick_push (TREE_VALUE (t));
185 : 391592 : }
186 : :
187 : : /* Dump the adjustments in the vector ADJUSTMENTS to dump_file in a human
188 : : friendly way, assuming they are meant to be applied to FNDECL. */
189 : :
190 : : void
191 : 9 : ipa_dump_adjusted_parameters (FILE *f,
192 : : vec<ipa_adjusted_param, va_gc> *adj_params)
193 : : {
194 : 9 : unsigned i, len = vec_safe_length (adj_params);
195 : 17 : bool first = true;
196 : :
197 : 8 : if (!len)
198 : : return;
199 : :
200 : 8 : fprintf (f, " IPA adjusted parameters: ");
201 : 29 : for (i = 0; i < len; i++)
202 : : {
203 : 21 : struct ipa_adjusted_param *apm;
204 : 21 : apm = &(*adj_params)[i];
205 : :
206 : 21 : if (!first)
207 : 13 : fprintf (f, " ");
208 : : else
209 : : first = false;
210 : :
211 : 21 : fprintf (f, "%i. %s %s", i, ipa_param_op_names[apm->op],
212 : 21 : apm->prev_clone_adjustment ? "prev_clone_adjustment " : "");
213 : 21 : switch (apm->op)
214 : : {
215 : : case IPA_PARAM_OP_UNDEFINED:
216 : : break;
217 : :
218 : 8 : case IPA_PARAM_OP_COPY:
219 : 8 : fprintf (f, ", base_index: %u", apm->base_index);
220 : 8 : fprintf (f, ", prev_clone_index: %u", apm->prev_clone_index);
221 : 8 : break;
222 : :
223 : 13 : case IPA_PARAM_OP_SPLIT:
224 : 13 : fprintf (f, ", offset: %u", apm->unit_offset);
225 : : /* fall-through */
226 : 13 : case IPA_PARAM_OP_NEW:
227 : 13 : fprintf (f, ", base_index: %u", apm->base_index);
228 : 13 : fprintf (f, ", prev_clone_index: %u", apm->prev_clone_index);
229 : 13 : print_node_brief (f, ", type: ", apm->type, 0);
230 : 13 : print_node_brief (f, ", alias type: ", apm->alias_ptr_type, 0);
231 : 13 : fprintf (f, " prefix: %s",
232 : 13 : ipa_param_prefixes[apm->param_prefix_index]);
233 : 13 : if (apm->reverse)
234 : 0 : fprintf (f, ", reverse");
235 : : break;
236 : : }
237 : 21 : fprintf (f, "\n");
238 : : }
239 : : }
240 : :
241 : : /* Fill NEW_TYPES with types of a function after its current OTYPES have been
242 : : modified as described in ADJ_PARAMS. When USE_PREV_INDICES is true, use
243 : : prev_clone_index from ADJ_PARAMS as opposed to base_index when the parameter
244 : : is false. */
245 : :
246 : : static void
247 : 387128 : fill_vector_of_new_param_types (vec<tree> *new_types, vec<tree> *otypes,
248 : : vec<ipa_adjusted_param, va_gc> *adj_params,
249 : : bool use_prev_indices)
250 : : {
251 : 387128 : unsigned adj_len = vec_safe_length (adj_params);
252 : 387128 : new_types->reserve_exact (adj_len);
253 : 1193378 : for (unsigned i = 0; i < adj_len ; i++)
254 : : {
255 : 806250 : ipa_adjusted_param *apm = &(*adj_params)[i];
256 : 806250 : if (apm->op == IPA_PARAM_OP_COPY)
257 : : {
258 : 1158084 : unsigned index
259 : 579042 : = use_prev_indices ? apm->prev_clone_index : apm->base_index;
260 : : /* The following needs to be handled gracefully because of type
261 : : mismatches. This happens with LTO but apparently also in Fortran
262 : : with -fcoarray=lib -O2 -lcaf_single -latomic. */
263 : 579042 : if (index >= otypes->length ())
264 : 0 : continue;
265 : 579042 : new_types->quick_push ((*otypes)[index]);
266 : : }
267 : 227208 : else if (apm->op == IPA_PARAM_OP_NEW
268 : 227208 : || apm->op == IPA_PARAM_OP_SPLIT)
269 : : {
270 : 227208 : tree ntype = apm->type;
271 : 227208 : if (is_gimple_reg_type (ntype)
272 : 227208 : && TYPE_MODE (ntype) != BLKmode)
273 : : {
274 : 225544 : unsigned malign = GET_MODE_ALIGNMENT (TYPE_MODE (ntype));
275 : 225544 : if (TYPE_ALIGN (ntype) != malign)
276 : 2685 : ntype = build_aligned_type (ntype, malign);
277 : : }
278 : 227208 : new_types->quick_push (ntype);
279 : : }
280 : : else
281 : 0 : gcc_unreachable ();
282 : : }
283 : 387128 : }
284 : :
285 : : /* Return false if given attribute should prevent type adjustments. */
286 : :
287 : : bool
288 : 377779 : ipa_param_adjustments::type_attribute_allowed_p (tree name)
289 : : {
290 : 609357 : if ((is_attribute_p ("fn spec", name) && flag_ipa_modref)
291 : 171074 : || is_attribute_p ("access", name)
292 : 157878 : || is_attribute_p ("returns_nonnull", name)
293 : 156560 : || is_attribute_p ("assume_aligned", name)
294 : 156560 : || is_attribute_p ("nocf_check", name)
295 : 534314 : || is_attribute_p ("warn_unused_result", name))
296 : : return true;
297 : : return false;
298 : : }
299 : :
300 : : /* Return true if attribute should be dropped if parameter changed. */
301 : :
302 : : static bool
303 : 4479 : drop_type_attribute_if_params_changed_p (tree name)
304 : : {
305 : 4479 : if (is_attribute_p ("fn spec", name)
306 : 4479 : || is_attribute_p ("access", name))
307 : : return true;
308 : : return false;
309 : : }
310 : :
311 : : /* Build and return a function type just like ORIG_TYPE but with parameter
312 : : types given in NEW_PARAM_TYPES - which can be NULL if, but only if,
313 : : ORIG_TYPE itself has NULL TREE_ARG_TYPEs. If METHOD2FUNC is true, also make
314 : : it a FUNCTION_TYPE instead of FUNCTION_TYPE.
315 : : If ARG_MODIFIED is true drop attributes that are no longer up to date. */
316 : :
317 : : static tree
318 : 244163 : build_adjusted_function_type (tree orig_type, vec<tree> *new_param_types,
319 : : bool method2func, bool skip_return,
320 : : bool args_modified)
321 : : {
322 : 244163 : tree new_arg_types = NULL;
323 : 244163 : if (TYPE_ARG_TYPES (orig_type))
324 : : {
325 : 244037 : gcc_checking_assert (new_param_types);
326 : 244037 : bool last_parm_void = (TREE_VALUE (tree_last (TYPE_ARG_TYPES (orig_type)))
327 : 244037 : == void_type_node);
328 : 244037 : unsigned len = new_param_types->length ();
329 : 755942 : for (unsigned i = 0; i < len; i++)
330 : 511905 : new_arg_types = tree_cons (NULL_TREE, (*new_param_types)[i],
331 : : new_arg_types);
332 : :
333 : 244037 : tree new_reversed = nreverse (new_arg_types);
334 : 244037 : if (last_parm_void)
335 : : {
336 : 244028 : if (new_reversed)
337 : 220980 : TREE_CHAIN (new_arg_types) = void_list_node;
338 : : else
339 : 23048 : new_reversed = void_list_node;
340 : : }
341 : : new_arg_types = new_reversed;
342 : : }
343 : :
344 : : /* Use build_distinct_type_copy to preserve as much as possible from original
345 : : type (debug info, attribute lists etc.). The one exception is
346 : : METHOD_TYPEs which must have THIS argument and when we are asked to remove
347 : : it, we need to build new FUNCTION_TYPE instead. */
348 : 244163 : tree new_type = NULL;
349 : 244163 : if (method2func)
350 : : {
351 : 94690 : tree ret_type;
352 : 94690 : if (skip_return)
353 : 12821 : ret_type = void_type_node;
354 : : else
355 : 81869 : ret_type = TREE_TYPE (orig_type);
356 : :
357 : 94690 : new_type
358 : 94690 : = build_distinct_type_copy (build_function_type (ret_type,
359 : : new_arg_types));
360 : 94690 : TYPE_CONTEXT (new_type) = TYPE_CONTEXT (orig_type);
361 : : }
362 : : else
363 : : {
364 : 149473 : new_type = build_distinct_type_copy (orig_type);
365 : 149473 : TYPE_ARG_TYPES (new_type) = new_arg_types;
366 : 149473 : if (skip_return)
367 : 57646 : TREE_TYPE (new_type) = void_type_node;
368 : : }
369 : 244163 : if (args_modified && TYPE_ATTRIBUTES (new_type))
370 : : {
371 : 4479 : tree t = TYPE_ATTRIBUTES (new_type);
372 : 4479 : tree *last = &TYPE_ATTRIBUTES (new_type);
373 : 4479 : TYPE_ATTRIBUTES (new_type) = NULL;
374 : 8958 : for (;t; t = TREE_CHAIN (t))
375 : 4479 : if (!drop_type_attribute_if_params_changed_p
376 : 4479 : (get_attribute_name (t)))
377 : : {
378 : 12 : *last = copy_node (t);
379 : 12 : TREE_CHAIN (*last) = NULL;
380 : 12 : last = &TREE_CHAIN (*last);
381 : : }
382 : : }
383 : :
384 : 244163 : return new_type;
385 : : }
386 : :
387 : : /* Return the maximum index in any IPA_PARAM_OP_COPY adjustment or -1 if there
388 : : is none. */
389 : :
390 : : int
391 : 40466 : ipa_param_adjustments::get_max_base_index ()
392 : : {
393 : 40466 : unsigned adj_len = vec_safe_length (m_adj_params);
394 : 40466 : int max_index = -1;
395 : 94667 : for (unsigned i = 0; i < adj_len ; i++)
396 : : {
397 : 54201 : ipa_adjusted_param *apm = &(*m_adj_params)[i];
398 : 54201 : if (apm->op == IPA_PARAM_OP_COPY
399 : 48831 : && max_index < apm->base_index)
400 : 54201 : max_index = apm->base_index;
401 : : }
402 : 40466 : return max_index;
403 : : }
404 : :
405 : :
406 : : /* Fill SURVIVING_PARAMS with an array of bools where each one says whether a
407 : : parameter that originally was at that position still survives in the given
408 : : clone or is removed/replaced. If the final array is smaller than an index
409 : : of an original parameter, that parameter also did not survive. That a
410 : : parameter survives does not mean it has the same index as before. */
411 : :
412 : : void
413 : 25898 : ipa_param_adjustments::get_surviving_params (vec<bool> *surviving_params)
414 : : {
415 : 25898 : unsigned adj_len = vec_safe_length (m_adj_params);
416 : 25898 : int max_index = get_max_base_index ();
417 : :
418 : 25898 : if (max_index < 0)
419 : : return;
420 : 14962 : surviving_params->reserve_exact (max_index + 1);
421 : 14962 : surviving_params->quick_grow_cleared (max_index + 1);
422 : 42382 : for (unsigned i = 0; i < adj_len ; i++)
423 : : {
424 : 27420 : ipa_adjusted_param *apm = &(*m_adj_params)[i];
425 : 27420 : if (apm->op == IPA_PARAM_OP_COPY)
426 : 27420 : (*surviving_params)[apm->base_index] = true;
427 : : }
428 : : }
429 : :
430 : : /* Fill NEW_INDICES with new indices of each surviving parameter or -1 for
431 : : those which do not survive. Any parameter outside of lenght of the vector
432 : : does not survive. There is currently no support for a parameter to be
433 : : copied to two distinct new parameters. */
434 : :
435 : : void
436 : 14568 : ipa_param_adjustments::get_updated_indices (vec<int> *new_indices)
437 : : {
438 : 14568 : unsigned adj_len = vec_safe_length (m_adj_params);
439 : 14568 : int max_index = get_max_base_index ();
440 : :
441 : 14568 : if (max_index < 0)
442 : : return;
443 : 10984 : unsigned res_len = max_index + 1;
444 : 10984 : new_indices->reserve_exact (res_len);
445 : 38510 : for (unsigned i = 0; i < res_len ; i++)
446 : 27526 : new_indices->quick_push (-1);
447 : 35715 : for (unsigned i = 0; i < adj_len ; i++)
448 : : {
449 : 24731 : ipa_adjusted_param *apm = &(*m_adj_params)[i];
450 : 24731 : if (apm->op == IPA_PARAM_OP_COPY)
451 : 21411 : (*new_indices)[apm->base_index] = i;
452 : : }
453 : : }
454 : :
455 : : /* Return the original index for the given new parameter index. Return a
456 : : negative number if not available. */
457 : :
458 : : int
459 : 595126 : ipa_param_adjustments::get_original_index (int newidx)
460 : : {
461 : 595126 : const ipa_adjusted_param *adj = &(*m_adj_params)[newidx];
462 : 595126 : if (adj->op != IPA_PARAM_OP_COPY)
463 : : return -1;
464 : 461486 : return adj->base_index;
465 : : }
466 : :
467 : : /* Return true if the first parameter (assuming there was one) survives the
468 : : transformation intact and remains the first one. */
469 : :
470 : : bool
471 : 252678 : ipa_param_adjustments::first_param_intact_p ()
472 : : {
473 : 252678 : return (!vec_safe_is_empty (m_adj_params)
474 : 235499 : && (*m_adj_params)[0].op == IPA_PARAM_OP_COPY
475 : 163178 : && (*m_adj_params)[0].base_index == 0);
476 : : }
477 : :
478 : : /* Return true if we have to change what has formerly been a method into a
479 : : function. */
480 : :
481 : : bool
482 : 383579 : ipa_param_adjustments::method2func_p (tree orig_type)
483 : : {
484 : 383579 : return ((TREE_CODE (orig_type) == METHOD_TYPE) && !first_param_intact_p ());
485 : : }
486 : :
487 : : /* Given function type OLD_TYPE, return a new type derived from it after
488 : : performing all atored modifications. TYPE_ORIGINAL_P should be true when
489 : : OLD_TYPE refers to the type before any IPA transformations, as opposed to a
490 : : type that can be an intermediate one in between various IPA
491 : : transformations. */
492 : :
493 : : tree
494 : 239703 : ipa_param_adjustments::build_new_function_type (tree old_type,
495 : : bool type_original_p)
496 : : {
497 : 239703 : auto_vec<tree,16> new_param_types, *new_param_types_p;
498 : 239703 : if (prototype_p (old_type))
499 : : {
500 : 239641 : auto_vec<tree, 16> otypes;
501 : 239641 : push_function_arg_types (&otypes, old_type);
502 : 239641 : fill_vector_of_new_param_types (&new_param_types, &otypes, m_adj_params,
503 : 239641 : !type_original_p);
504 : 239641 : new_param_types_p = &new_param_types;
505 : 239641 : }
506 : : else
507 : : new_param_types_p = NULL;
508 : :
509 : : /* Check if any params type cares about are modified. In this case will
510 : : need to drop some type attributes. */
511 : 239703 : bool modified = false;
512 : 239703 : size_t index = 0;
513 : 239703 : if (m_adj_params)
514 : 216954 : for (tree t = TYPE_ARG_TYPES (old_type);
515 : 646254 : t && (int)index < m_always_copy_start && !modified;
516 : 429300 : t = TREE_CHAIN (t), index++)
517 : 429300 : if (index >= m_adj_params->length ()
518 : 429300 : || get_original_index (index) != (int)index)
519 : : modified = true;
520 : :
521 : :
522 : 239703 : return build_adjusted_function_type (old_type, new_param_types_p,
523 : 239703 : method2func_p (old_type), m_skip_return,
524 : 239703 : modified);
525 : 239703 : }
526 : :
527 : : /* Build variant of function decl ORIG_DECL which has no return value if
528 : : M_SKIP_RETURN is true and, if ORIG_DECL's types or parameters is known, has
529 : : this type adjusted as indicated in M_ADJ_PARAMS. Arguments from
530 : : DECL_ARGUMENTS list are not processed now, since they are linked by
531 : : TREE_CHAIN directly and not accessible in LTO during WPA. The caller is
532 : : responsible for eliminating them when clones are properly materialized. */
533 : :
534 : : tree
535 : 143876 : ipa_param_adjustments::adjust_decl (tree orig_decl)
536 : : {
537 : 143876 : tree new_decl = copy_node (orig_decl);
538 : 143876 : tree orig_type = TREE_TYPE (orig_decl);
539 : 143876 : if (prototype_p (orig_type)
540 : 143876 : || (m_skip_return && !VOID_TYPE_P (TREE_TYPE (orig_type))))
541 : : {
542 : 143816 : tree new_type = build_new_function_type (orig_type, false);
543 : 143816 : TREE_TYPE (new_decl) = new_type;
544 : : }
545 : 143876 : if (method2func_p (orig_type))
546 : 45966 : DECL_VINDEX (new_decl) = NULL_TREE;
547 : :
548 : : /* When signature changes, we need to clear builtin info. */
549 : 143876 : if (fndecl_built_in_p (new_decl))
550 : 97 : set_decl_built_in_function (new_decl, NOT_BUILT_IN, 0);
551 : :
552 : 143876 : DECL_VIRTUAL_P (new_decl) = 0;
553 : 143876 : DECL_LANG_SPECIFIC (new_decl) = NULL;
554 : :
555 : : /* Drop MALLOC attribute for a void function. */
556 : 143876 : if (m_skip_return)
557 : 44877 : DECL_IS_MALLOC (new_decl) = 0;
558 : :
559 : 143876 : return new_decl;
560 : : }
561 : :
562 : : /* Wrapper around get_base_ref_and_offset for cases interesting for IPA-SRA
563 : : transformations. Return true if EXPR has an interesting form and fill in
564 : : *BASE_P and *UNIT_OFFSET_P with the appropriate info. */
565 : :
566 : : static bool
567 : 1188728 : isra_get_ref_base_and_offset (tree expr, tree *base_p, unsigned *unit_offset_p)
568 : : {
569 : 1188728 : HOST_WIDE_INT offset, size;
570 : 1188728 : bool reverse;
571 : 1188728 : tree base
572 : 1188728 : = get_ref_base_and_extent_hwi (expr, &offset, &size, &reverse);
573 : 1188728 : if (!base || size < 0)
574 : : return false;
575 : :
576 : 1183934 : if ((offset % BITS_PER_UNIT) != 0)
577 : : return false;
578 : :
579 : 1183201 : if (TREE_CODE (base) == MEM_REF)
580 : : {
581 : 181892 : poly_int64 plmoff = mem_ref_offset (base).force_shwi ();
582 : 181892 : HOST_WIDE_INT moff;
583 : 181892 : bool is_cst = plmoff.is_constant (&moff);
584 : 181892 : if (!is_cst)
585 : : return false;
586 : 181892 : offset += moff * BITS_PER_UNIT;
587 : 181892 : base = TREE_OPERAND (base, 0);
588 : : }
589 : :
590 : 1183201 : if (offset < 0 || (offset / BITS_PER_UNIT) > UINT_MAX)
591 : : return false;
592 : :
593 : 1183023 : *base_p = base;
594 : 1183023 : *unit_offset_p = offset / BITS_PER_UNIT;
595 : 1183023 : return true;
596 : : }
597 : :
598 : : /* Remove all statements that use NAME directly or indirectly. KILLED_SSAS
599 : : contains the SSA_NAMEs that are already being or have been processed and new
600 : : ones need to be added to it. The function only has to process situations
601 : : handled by ssa_name_only_returned_p in ipa-sra.cc with the exception that it
602 : : can assume it must never reach a use in a return statement. */
603 : :
604 : : static void
605 : 11880 : purge_all_uses (tree name, hash_set <tree> *killed_ssas)
606 : : {
607 : 11880 : imm_use_iterator imm_iter;
608 : 11880 : gimple *stmt;
609 : 11880 : auto_vec <tree, 4> worklist;
610 : :
611 : 11880 : worklist.safe_push (name);
612 : 50265 : while (!worklist.is_empty ())
613 : : {
614 : 14625 : tree cur_name = worklist.pop ();
615 : 32055 : FOR_EACH_IMM_USE_STMT (stmt, imm_iter, cur_name)
616 : : {
617 : 2805 : if (gimple_debug_bind_p (stmt))
618 : : {
619 : : /* When runing within tree-inline, we will never end up here but
620 : : adding the SSAs to killed_ssas will do the trick in this case
621 : : and the respective debug statements will get reset. */
622 : 60 : gimple_debug_bind_reset_value (stmt);
623 : 60 : update_stmt (stmt);
624 : 60 : continue;
625 : : }
626 : :
627 : 2745 : tree lhs = NULL_TREE;
628 : 2745 : if (is_gimple_assign (stmt))
629 : 741 : lhs = gimple_assign_lhs (stmt);
630 : 2004 : else if (gimple_code (stmt) == GIMPLE_PHI)
631 : 2004 : lhs = gimple_phi_result (stmt);
632 : 3486 : gcc_assert (lhs
633 : : && (TREE_CODE (lhs) == SSA_NAME)
634 : : && !gimple_vdef (stmt));
635 : 2745 : if (!killed_ssas->add (lhs))
636 : : {
637 : 2745 : worklist.safe_push (lhs);
638 : 2745 : gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
639 : 2745 : gsi_remove (&gsi, true);
640 : : }
641 : 14625 : }
642 : : }
643 : 11880 : }
644 : :
645 : : /* Modify actual arguments of a function call in statement currently belonging
646 : : to CS, and make it call CS->callee->decl. Return the new statement that
647 : : replaced the old one. When invoked, cfun and current_function_decl have to
648 : : be set to the caller. When called from within tree-inline, KILLED_SSAs has
649 : : to contain the pointer to killed_new_ssa_names within the copy_body_data
650 : : structure and SSAs discovered to be useless (if LHS is removed) will be
651 : : added to it, otherwise it needs to be NULL. */
652 : :
653 : : gcall *
654 : 438410 : ipa_param_adjustments::modify_call (cgraph_edge *cs,
655 : : bool update_references,
656 : : hash_set <tree> *killed_ssas)
657 : : {
658 : 438410 : gcall *stmt = cs->call_stmt;
659 : 438410 : tree callee_decl = cs->callee->decl;
660 : :
661 : 1121433 : ipa_edge_modification_info *mod_info
662 : 438410 : = ipa_edge_modifications ? ipa_edge_modifications->get (cs) : NULL;
663 : 244613 : if (mod_info && symtab->dump_file)
664 : : {
665 : 0 : fprintf (symtab->dump_file, "Information about pre-exiting "
666 : : "modifications.\n Index map:");
667 : 0 : unsigned idx_len = mod_info->index_map.length ();
668 : 0 : for (unsigned i = 0; i < idx_len; i++)
669 : 0 : fprintf (symtab->dump_file, " %i", mod_info->index_map[i]);
670 : 0 : fprintf (symtab->dump_file, "\n Pass-through split map: ");
671 : 0 : unsigned ptm_len = mod_info->pass_through_map.length ();
672 : 0 : for (unsigned i = 0; i < ptm_len; i++)
673 : 0 : fprintf (symtab->dump_file,
674 : : " (base_index: %u, offset: %u, new_index: %i)",
675 : 0 : mod_info->pass_through_map[i].base_index,
676 : 0 : mod_info->pass_through_map[i].unit_offset,
677 : 0 : mod_info->pass_through_map[i].new_index);
678 : 0 : fprintf (symtab->dump_file, "\n Always-copy delta: %i\n",
679 : : mod_info->always_copy_delta);
680 : : }
681 : :
682 : 438410 : unsigned len = vec_safe_length (m_adj_params);
683 : 438410 : auto_vec<tree, 16> vargs (len);
684 : 438410 : unsigned old_nargs = gimple_call_num_args (stmt);
685 : 438410 : unsigned orig_nargs = mod_info ? mod_info->index_map.length () : old_nargs;
686 : 438410 : auto_vec<bool, 16> kept (old_nargs);
687 : 438410 : kept.quick_grow_cleared (old_nargs);
688 : :
689 : 438410 : cgraph_node *current_node = cgraph_node::get (current_function_decl);
690 : 438410 : if (update_references)
691 : 0 : current_node->remove_stmt_references (stmt);
692 : :
693 : 438410 : gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
694 : 438410 : gimple_stmt_iterator prev_gsi = gsi;
695 : 438410 : gsi_prev (&prev_gsi);
696 : 1427768 : for (unsigned i = 0; i < len; i++)
697 : : {
698 : 989358 : ipa_adjusted_param *apm = &(*m_adj_params)[i];
699 : 989358 : if (apm->op == IPA_PARAM_OP_COPY)
700 : : {
701 : 682679 : int index = apm->base_index;
702 : 682679 : if ((unsigned) index >= orig_nargs)
703 : : /* Can happen if the original call has argument mismatch,
704 : : ignore. */
705 : 0 : continue;
706 : 682679 : if (mod_info)
707 : : {
708 : 36372 : index = mod_info->index_map[apm->base_index];
709 : 36372 : gcc_assert (index >= 0);
710 : : }
711 : :
712 : 682679 : tree arg = gimple_call_arg (stmt, index);
713 : :
714 : 682679 : vargs.quick_push (arg);
715 : 682679 : kept[index] = true;
716 : 682679 : continue;
717 : 682679 : }
718 : :
719 : : /* At the moment the only user of IPA_PARAM_OP_NEW modifies calls itself.
720 : : If we ever want to support it during WPA IPA stage, we'll need a
721 : : mechanism to call into the IPA passes that introduced them. Currently
722 : : we simply mandate that IPA infrastructure understands all argument
723 : : modifications. Remember, edge redirection/modification is done only
724 : : once, not in steps for each pass modifying the callee like clone
725 : : materialization. */
726 : 306679 : gcc_assert (apm->op == IPA_PARAM_OP_SPLIT);
727 : :
728 : : /* We have to handle pass-through changes differently using the map
729 : : clone materialziation might have left behind. */
730 : 306679 : tree repl = NULL_TREE;
731 : 306679 : unsigned ptm_len = mod_info ? mod_info->pass_through_map.length () : 0;
732 : 330030 : for (unsigned j = 0; j < ptm_len; j++)
733 : 41945 : if (mod_info->pass_through_map[j].base_index == apm->base_index
734 : 41945 : && mod_info->pass_through_map[j].unit_offset == apm->unit_offset)
735 : : {
736 : 18594 : int repl_idx = mod_info->pass_through_map[j].new_index;
737 : 18594 : gcc_assert (repl_idx >= 0);
738 : 18594 : repl = gimple_call_arg (stmt, repl_idx);
739 : 18594 : break;
740 : : }
741 : 306679 : if (repl)
742 : : {
743 : 18594 : if (!useless_type_conversion_p(apm->type, repl->typed.type))
744 : : {
745 : 0 : repl = force_value_to_type (apm->type, repl);
746 : 0 : repl = force_gimple_operand_gsi (&gsi, repl,
747 : : true, NULL, true, GSI_SAME_STMT);
748 : : }
749 : 18594 : vargs.quick_push (repl);
750 : 18594 : continue;
751 : : }
752 : :
753 : 288085 : int index = apm->base_index;
754 : 288085 : if ((unsigned) index >= orig_nargs)
755 : : /* Can happen if the original call has argument mismatch, ignore. */
756 : 1 : continue;
757 : 288084 : if (mod_info)
758 : : {
759 : 4310 : index = mod_info->index_map[apm->base_index];
760 : 4310 : gcc_assert (index >= 0);
761 : : }
762 : 288084 : tree base = gimple_call_arg (stmt, index);
763 : :
764 : : /* We create a new parameter out of the value of the old one, we can
765 : : do the following kind of transformations:
766 : :
767 : : - A scalar passed by reference, potentially as a part of a larger
768 : : aggregate, is converted to a scalar passed by value.
769 : :
770 : : - A part of an aggregate is passed instead of the whole aggregate. */
771 : :
772 : 288084 : location_t loc = gimple_location (stmt);
773 : 288084 : tree off;
774 : 288084 : bool deref_base = false;
775 : 288084 : unsigned int deref_align = 0;
776 : 288084 : if (TREE_CODE (base) != ADDR_EXPR
777 : 288084 : && is_gimple_reg_type (TREE_TYPE (base)))
778 : : {
779 : : /* Detect type mismatches in calls in invalid programs and make a
780 : : poor attempt to gracefully convert them so that we don't ICE. */
781 : 78732 : if (!POINTER_TYPE_P (TREE_TYPE (base)))
782 : 11 : base = force_value_to_type (ptr_type_node, base);
783 : :
784 : 78732 : off = build_int_cst (apm->alias_ptr_type, apm->unit_offset);
785 : : }
786 : : else
787 : : {
788 : 209352 : bool addrof;
789 : 209352 : if (TREE_CODE (base) == ADDR_EXPR)
790 : : {
791 : 170810 : base = TREE_OPERAND (base, 0);
792 : 170810 : addrof = true;
793 : : }
794 : : else
795 : : addrof = false;
796 : :
797 : 209352 : tree prev_base = base;
798 : 209352 : poly_int64 base_offset;
799 : 209352 : base = get_addr_base_and_unit_offset (base, &base_offset);
800 : :
801 : : /* Aggregate arguments can have non-invariant addresses. */
802 : 209352 : if (!base)
803 : : {
804 : 0 : base = build_fold_addr_expr (prev_base);
805 : 0 : off = build_int_cst (apm->alias_ptr_type, apm->unit_offset);
806 : : }
807 : 209352 : else if (TREE_CODE (base) == MEM_REF)
808 : : {
809 : 4856 : if (!addrof)
810 : : {
811 : 4856 : deref_base = true;
812 : 4856 : deref_align = TYPE_ALIGN (TREE_TYPE (base));
813 : : }
814 : 9712 : off = build_int_cst (apm->alias_ptr_type,
815 : 4856 : base_offset + apm->unit_offset);
816 : 4856 : off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1),
817 : : off);
818 : 4856 : base = TREE_OPERAND (base, 0);
819 : : }
820 : : else
821 : : {
822 : 408992 : off = build_int_cst (apm->alias_ptr_type,
823 : 204496 : base_offset + apm->unit_offset);
824 : 204496 : base = build_fold_addr_expr (base);
825 : : }
826 : : }
827 : :
828 : 288084 : tree type = apm->type;
829 : 288084 : unsigned int align;
830 : 288084 : unsigned HOST_WIDE_INT misalign;
831 : :
832 : 288084 : if (deref_base)
833 : : {
834 : 4856 : align = deref_align;
835 : 4856 : misalign = 0;
836 : : }
837 : : else
838 : : {
839 : 283228 : get_pointer_alignment_1 (base, &align, &misalign);
840 : : /* All users must make sure that we can be optimistic when it
841 : : comes to alignment in this case (by inspecting the final users
842 : : of these new parameters). */
843 : 283228 : if (TYPE_ALIGN (type) > align)
844 : 77341 : align = TYPE_ALIGN (type);
845 : : }
846 : 288084 : misalign
847 : 576168 : += (offset_int::from (wi::to_wide (off), SIGNED).to_short_addr ()
848 : 288084 : * BITS_PER_UNIT);
849 : 288084 : misalign = misalign & (align - 1);
850 : 288084 : if (misalign != 0)
851 : 2934 : align = least_bit_hwi (misalign);
852 : 288084 : if (align < TYPE_ALIGN (type))
853 : 0 : type = build_aligned_type (type, align);
854 : 288084 : base = force_gimple_operand_gsi (&gsi, base,
855 : : true, NULL, true, GSI_SAME_STMT);
856 : 288084 : tree expr = fold_build2_loc (loc, MEM_REF, type, base, off);
857 : 288084 : REF_REVERSE_STORAGE_ORDER (expr) = apm->reverse;
858 : : /* If expr is not a valid gimple call argument emit
859 : : a load into a temporary. */
860 : 288084 : if (is_gimple_reg_type (TREE_TYPE (expr)))
861 : : {
862 : 286346 : gimple *tem = gimple_build_assign (NULL_TREE, expr);
863 : 286346 : if (gimple_in_ssa_p (cfun))
864 : : {
865 : 572692 : gimple_set_vuse (tem, gimple_vuse (stmt));
866 : 286346 : expr = make_ssa_name (TREE_TYPE (expr), tem);
867 : : }
868 : : else
869 : 0 : expr = create_tmp_reg (TREE_TYPE (expr));
870 : 286346 : gimple_assign_set_lhs (tem, expr);
871 : 286346 : gsi_insert_before (&gsi, tem, GSI_SAME_STMT);
872 : : }
873 : 288084 : vargs.quick_push (expr);
874 : : }
875 : :
876 : 438410 : if (m_always_copy_start >= 0)
877 : : {
878 : 438410 : int always_copy_start = m_always_copy_start;
879 : 438410 : if (mod_info)
880 : : {
881 : 28509 : always_copy_start += mod_info->always_copy_delta;
882 : 28509 : gcc_assert (always_copy_start >= 0);
883 : : }
884 : 438417 : for (unsigned i = always_copy_start; i < old_nargs; i++)
885 : 7 : vargs.safe_push (gimple_call_arg (stmt, i));
886 : : }
887 : :
888 : : /* For optimized away parameters, add on the caller side
889 : : before the call
890 : : DEBUG D#X => parm_Y(D)
891 : : stmts and associate D#X with parm in decl_debug_args_lookup
892 : : vector to say for debug info that if parameter parm had been passed,
893 : : it would have value parm_Y(D). */
894 : 438410 : tree old_decl = gimple_call_fndecl (stmt);
895 : 438410 : if (MAY_HAVE_DEBUG_BIND_STMTS && old_decl && callee_decl)
896 : : {
897 : 401075 : vec<tree, va_gc> **debug_args = NULL;
898 : 401075 : unsigned i = 0;
899 : 401075 : cgraph_node *callee_node = cgraph_node::get (callee_decl);
900 : :
901 : : /* FIXME: we don't seem to be able to insert debug args before clone
902 : : is materialized. Materializing them early leads to extra memory
903 : : use. */
904 : 401075 : if (callee_node->clone_of)
905 : 0 : callee_node->get_untransformed_body ();
906 : 401075 : for (tree old_parm = DECL_ARGUMENTS (old_decl);
907 : 1264251 : old_parm && i < old_nargs && ((int) i) < m_always_copy_start;
908 : 863176 : old_parm = DECL_CHAIN (old_parm), i++)
909 : : {
910 : 1563521 : if (!is_gimple_reg (old_parm) || kept[i])
911 : 673380 : continue;
912 : 193681 : tree arg;
913 : 193681 : if (mod_info)
914 : : {
915 : 8147 : if (mod_info->index_map[i] < 0)
916 : 3884 : continue;
917 : 4263 : arg = gimple_call_arg (stmt, mod_info->index_map[i]);
918 : : }
919 : : else
920 : 185534 : arg = gimple_call_arg (stmt, i);
921 : :
922 : 189797 : tree origin = DECL_ORIGIN (old_parm);
923 : 189797 : if (!useless_type_conversion_p (TREE_TYPE (origin), TREE_TYPE (arg)))
924 : : {
925 : 859 : if (!fold_convertible_p (TREE_TYPE (origin), arg))
926 : 1 : continue;
927 : 858 : tree rhs1;
928 : 858 : if (TREE_CODE (arg) == SSA_NAME
929 : 572 : && gimple_assign_cast_p (SSA_NAME_DEF_STMT (arg))
930 : 569 : && (rhs1
931 : 569 : = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (arg)))
932 : 1427 : && useless_type_conversion_p (TREE_TYPE (origin),
933 : 569 : TREE_TYPE (rhs1)))
934 : : arg = rhs1;
935 : : else
936 : 289 : arg = fold_convert_loc (gimple_location (stmt),
937 : 289 : TREE_TYPE (origin), arg);
938 : : }
939 : 189796 : if (debug_args == NULL)
940 : 150549 : debug_args = decl_debug_args_insert (callee_decl);
941 : 189796 : unsigned int ix;
942 : 189796 : tree ddecl = NULL_TREE;
943 : 243655 : for (ix = 0; vec_safe_iterate (*debug_args, ix, &ddecl); ix += 2)
944 : 238460 : if (ddecl == origin)
945 : : {
946 : 184601 : ddecl = (**debug_args)[ix + 1];
947 : 184601 : break;
948 : : }
949 : 189796 : if (ddecl == NULL)
950 : : {
951 : 5195 : ddecl = build_debug_expr_decl (TREE_TYPE (origin));
952 : : /* FIXME: Is setting the mode really necessary? */
953 : 5195 : SET_DECL_MODE (ddecl, DECL_MODE (origin));
954 : :
955 : 5195 : vec_safe_push (*debug_args, origin);
956 : 5195 : vec_safe_push (*debug_args, ddecl);
957 : : }
958 : 189796 : gimple *def_temp = gimple_build_debug_bind (ddecl,
959 : : unshare_expr (arg), stmt);
960 : 189796 : gsi_insert_before (&gsi, def_temp, GSI_SAME_STMT);
961 : : }
962 : : }
963 : :
964 : 438410 : if (dump_file && (dump_flags & TDF_DETAILS))
965 : : {
966 : 10 : fprintf (dump_file, "replacing stmt:");
967 : 10 : print_gimple_stmt (dump_file, gsi_stmt (gsi), 0);
968 : : }
969 : :
970 : 438410 : gcall *new_stmt = gimple_build_call_vec (callee_decl, vargs);
971 : :
972 : 438410 : hash_set <tree> *ssas_to_remove = NULL;
973 : 438410 : if (tree lhs = gimple_call_lhs (stmt))
974 : : {
975 : 164651 : if (!m_skip_return)
976 : 152771 : gimple_call_set_lhs (new_stmt, lhs);
977 : 11880 : else if (TREE_CODE (lhs) == SSA_NAME)
978 : : {
979 : 11880 : if (!killed_ssas)
980 : : {
981 : 641 : ssas_to_remove = new hash_set<tree> (8);
982 : 641 : killed_ssas = ssas_to_remove;
983 : : }
984 : 11880 : killed_ssas->add (lhs);
985 : 11880 : purge_all_uses (lhs, killed_ssas);
986 : : }
987 : : }
988 : :
989 : 438410 : gimple_set_block (new_stmt, gimple_block (stmt));
990 : 438410 : if (gimple_has_location (stmt))
991 : 743087 : gimple_set_location (new_stmt, gimple_location (stmt));
992 : 438410 : gimple_call_set_chain (new_stmt, gimple_call_chain (stmt));
993 : 438410 : gimple_call_copy_flags (new_stmt, stmt);
994 : 438410 : if (gimple_in_ssa_p (cfun))
995 : 438410 : gimple_move_vops (new_stmt, stmt);
996 : :
997 : 438410 : if (dump_file && (dump_flags & TDF_DETAILS))
998 : : {
999 : 10 : fprintf (dump_file, "with stmt:");
1000 : 10 : print_gimple_stmt (dump_file, new_stmt, 0);
1001 : 10 : fprintf (dump_file, "\n");
1002 : : }
1003 : 438410 : gsi_replace (&gsi, new_stmt, true);
1004 : 438410 : if (ssas_to_remove)
1005 : : {
1006 : 641 : ipa_release_ssas_in_hash (ssas_to_remove);
1007 : 641 : delete ssas_to_remove;
1008 : : }
1009 : 438410 : if (update_references)
1010 : 0 : do
1011 : : {
1012 : 0 : current_node->record_stmt_references (gsi_stmt (gsi));
1013 : 0 : gsi_prev (&gsi);
1014 : : }
1015 : 0 : while (gsi_stmt (gsi) != gsi_stmt (prev_gsi));
1016 : :
1017 : 438410 : if (mod_info)
1018 : 28509 : ipa_edge_modifications->remove (cs);
1019 : 438410 : return new_stmt;
1020 : 438410 : }
1021 : :
1022 : : /* Dump information contained in the object in textual form to F. */
1023 : :
1024 : : void
1025 : 9 : ipa_param_adjustments::dump (FILE *f)
1026 : : {
1027 : 9 : fprintf (f, " m_always_copy_start: %i\n", m_always_copy_start);
1028 : 9 : ipa_dump_adjusted_parameters (f, m_adj_params);
1029 : 9 : if (m_skip_return)
1030 : 5 : fprintf (f, " Will SKIP return.\n");
1031 : 9 : }
1032 : :
1033 : : /* Dump information contained in the object in textual form to stderr. */
1034 : :
1035 : : void
1036 : 0 : ipa_param_adjustments::debug ()
1037 : : {
1038 : 0 : dump (stderr);
1039 : 0 : }
1040 : :
1041 : : /* Register a REPLACEMENT for accesses to BASE at UNIT_OFFSET. */
1042 : :
1043 : : void
1044 : 91778 : ipa_param_body_adjustments::register_replacement (tree base,
1045 : : unsigned unit_offset,
1046 : : tree replacement)
1047 : : {
1048 : 91778 : ipa_param_body_replacement psr;
1049 : 91778 : psr.base = base;
1050 : 91778 : psr.repl = replacement;
1051 : 91778 : psr.dummy = NULL_TREE;
1052 : 91778 : psr.unit_offset = unit_offset;
1053 : 91778 : m_replacements.safe_push (psr);
1054 : 91778 : m_sorted_replacements_p = false;
1055 : 91778 : }
1056 : :
1057 : : /* Register that REPLACEMENT should replace parameter described in APM. */
1058 : :
1059 : : void
1060 : 81036 : ipa_param_body_adjustments::register_replacement (ipa_adjusted_param *apm,
1061 : : tree replacement)
1062 : : {
1063 : 81036 : gcc_checking_assert (apm->op == IPA_PARAM_OP_SPLIT
1064 : : || apm->op == IPA_PARAM_OP_NEW);
1065 : 81036 : gcc_checking_assert (!apm->prev_clone_adjustment);
1066 : 81036 : register_replacement (m_oparms[apm->prev_clone_index], apm->unit_offset,
1067 : : replacement);
1068 : 81036 : }
1069 : :
1070 : : /* Comparator for sorting and searching
1071 : : ipa_param_body_adjustments::m_replacements. */
1072 : :
1073 : : static int
1074 : 1551787 : compare_param_body_replacement (const void *va, const void *vb)
1075 : : {
1076 : 1551787 : const ipa_param_body_replacement *a = (const ipa_param_body_replacement *) va;
1077 : 1551787 : const ipa_param_body_replacement *b = (const ipa_param_body_replacement *) vb;
1078 : :
1079 : 1551787 : if (DECL_UID (a->base) < DECL_UID (b->base))
1080 : : return -1;
1081 : 1279476 : if (DECL_UID (a->base) > DECL_UID (b->base))
1082 : : return 1;
1083 : 967859 : if (a->unit_offset < b->unit_offset)
1084 : : return -1;
1085 : 536446 : if (a->unit_offset > b->unit_offset)
1086 : 448195 : return 1;
1087 : : return 0;
1088 : : }
1089 : :
1090 : : /* Sort m_replacements and set m_sorted_replacements_p to true. */
1091 : :
1092 : : void
1093 : 161450 : ipa_param_body_adjustments::sort_replacements ()
1094 : : {
1095 : 161450 : if (m_sorted_replacements_p)
1096 : : return;
1097 : 50960 : m_replacements.qsort (compare_param_body_replacement);
1098 : 50960 : m_sorted_replacements_p = true;
1099 : : }
1100 : :
1101 : : /* Copy or not, as appropriate given m_id and decl context, a pre-existing
1102 : : PARM_DECL T so that it can be included in the parameters of the modified
1103 : : function. */
1104 : :
1105 : : tree
1106 : 221090 : ipa_param_body_adjustments::carry_over_param (tree t)
1107 : : {
1108 : 221090 : tree new_parm;
1109 : 221090 : if (m_id)
1110 : : {
1111 : 217162 : new_parm = remap_decl (t, m_id);
1112 : 217162 : if (TREE_CODE (new_parm) != PARM_DECL)
1113 : 0 : new_parm = m_id->copy_decl (t, m_id);
1114 : : }
1115 : 3928 : else if (DECL_CONTEXT (t) != m_fndecl)
1116 : : {
1117 : 30 : new_parm = copy_node (t);
1118 : 30 : DECL_CONTEXT (new_parm) = m_fndecl;
1119 : : }
1120 : : else
1121 : : new_parm = t;
1122 : 221090 : return new_parm;
1123 : : }
1124 : :
1125 : : /* If DECL is a gimple register that has a default definition SSA name and that
1126 : : has some uses, return the default definition, otherwise return NULL_TREE. */
1127 : :
1128 : : tree
1129 : 139452 : ipa_param_body_adjustments::get_ddef_if_exists_and_is_used (tree decl)
1130 : : {
1131 : 139452 : if (!is_gimple_reg (decl))
1132 : : return NULL_TREE;
1133 : 116157 : tree ddef = ssa_default_def (m_id->src_cfun, decl);
1134 : 116157 : if (!ddef || has_zero_uses (ddef))
1135 : : return NULL_TREE;
1136 : : return ddef;
1137 : : }
1138 : :
1139 : : /* Populate m_dead_stmts given that DEAD_PARAM is going to be removed without
1140 : : any replacement or splitting. REPL is the replacement VAR_SECL to base any
1141 : : remaining uses of a removed parameter on. Push all removed SSA names that
1142 : : are used within debug statements to DEBUGSTACK. */
1143 : :
1144 : : void
1145 : 98962 : ipa_param_body_adjustments::mark_dead_statements (tree dead_param,
1146 : : vec<tree> *debugstack)
1147 : : {
1148 : : /* Current IPA analyses which remove unused parameters never remove a
1149 : : non-gimple register ones which have any use except as parameters in other
1150 : : calls, so we can safely leve them as they are. */
1151 : 98962 : tree parm_ddef = get_ddef_if_exists_and_is_used (dead_param);
1152 : 98962 : if (!parm_ddef)
1153 : 69277 : return;
1154 : :
1155 : 34263 : auto_vec<tree, 4> stack;
1156 : 34263 : hash_set<tree> used_in_debug;
1157 : 34263 : m_dead_ssas.add (parm_ddef);
1158 : 34263 : stack.safe_push (parm_ddef);
1159 : 104659 : while (!stack.is_empty ())
1160 : : {
1161 : 36133 : imm_use_iterator imm_iter;
1162 : 36133 : use_operand_p use_p;
1163 : 36133 : tree t = stack.pop ();
1164 : :
1165 : 36133 : insert_decl_map (m_id, t, error_mark_node);
1166 : 136354 : FOR_EACH_IMM_USE_FAST (use_p, imm_iter, t)
1167 : : {
1168 : 100221 : gimple *stmt = USE_STMT (use_p);
1169 : :
1170 : : /* Calls containing dead arguments cannot be deleted,
1171 : : modify_call_stmt will instead remove just the argument later on.
1172 : : If isra_track_scalar_value_uses in ipa-sra.cc is extended to look
1173 : : through const functions, we will need to do so here too. */
1174 : 100221 : if (is_gimple_call (stmt)
1175 : 100221 : || (m_id->blocks_to_copy
1176 : 70320 : && !bitmap_bit_p (m_id->blocks_to_copy,
1177 : 70320 : gimple_bb (stmt)->index)))
1178 : 90391 : continue;
1179 : :
1180 : 9830 : if (is_gimple_debug (stmt))
1181 : : {
1182 : 7433 : m_dead_stmts.add (stmt);
1183 : 7433 : gcc_assert (gimple_debug_bind_p (stmt));
1184 : 7433 : if (!used_in_debug.contains (t))
1185 : : {
1186 : 3273 : used_in_debug.add (t);
1187 : 3273 : debugstack->safe_push (t);
1188 : : }
1189 : : }
1190 : 2397 : else if (gimple_code (stmt) == GIMPLE_PHI)
1191 : : {
1192 : 409 : gphi *phi = as_a <gphi *> (stmt);
1193 : 409 : int ix = PHI_ARG_INDEX_FROM_USE (use_p);
1194 : :
1195 : 409 : if (!m_id->blocks_to_copy
1196 : 440 : || bitmap_bit_p (m_id->blocks_to_copy,
1197 : 31 : gimple_phi_arg_edge (phi, ix)->src->index))
1198 : : {
1199 : 378 : m_dead_stmts.add (phi);
1200 : 378 : tree res = gimple_phi_result (phi);
1201 : 378 : if (!m_dead_ssas.add (res))
1202 : 262 : stack.safe_push (res);
1203 : : }
1204 : : }
1205 : 1988 : else if (is_gimple_assign (stmt))
1206 : : {
1207 : 1896 : m_dead_stmts.add (stmt);
1208 : 1896 : if (!gimple_clobber_p (stmt))
1209 : : {
1210 : 1866 : tree lhs = gimple_assign_lhs (stmt);
1211 : 1866 : gcc_assert (TREE_CODE (lhs) == SSA_NAME);
1212 : 1866 : if (!m_dead_ssas.add (lhs))
1213 : 1608 : stack.safe_push (lhs);
1214 : : }
1215 : : }
1216 : 92 : else if (gimple_code (stmt) == GIMPLE_RETURN)
1217 : 92 : gcc_assert (m_adjustments && m_adjustments->m_skip_return);
1218 : : else
1219 : : /* IPA-SRA does not analyze other types of statements. */
1220 : 0 : gcc_unreachable ();
1221 : : }
1222 : : }
1223 : :
1224 : 34263 : if (!MAY_HAVE_DEBUG_STMTS)
1225 : : {
1226 : 4578 : gcc_assert (debugstack->is_empty ());
1227 : 4578 : return;
1228 : : }
1229 : :
1230 : 29685 : tree dp_ddecl = build_debug_expr_decl (TREE_TYPE (dead_param));
1231 : : /* FIXME: Is setting the mode really necessary? */
1232 : 29685 : SET_DECL_MODE (dp_ddecl, DECL_MODE (dead_param));
1233 : 29685 : m_dead_ssa_debug_equiv.put (parm_ddef, dp_ddecl);
1234 : 34263 : }
1235 : :
1236 : : /* Put all clobbers of of dereference of default definition of PARAM into
1237 : : m_dead_stmts. If there are returns among uses of the default definition of
1238 : : PARAM, verify they will be stripped off the return value. */
1239 : :
1240 : : void
1241 : 47346 : ipa_param_body_adjustments::mark_clobbers_dead (tree param)
1242 : : {
1243 : 47346 : if (!is_gimple_reg (param))
1244 : 6856 : return;
1245 : 40490 : tree ddef = get_ddef_if_exists_and_is_used (param);
1246 : 40490 : if (!ddef)
1247 : : return;
1248 : :
1249 : 40490 : imm_use_iterator imm_iter;
1250 : 40490 : use_operand_p use_p;
1251 : 178346 : FOR_EACH_IMM_USE_FAST (use_p, imm_iter, ddef)
1252 : : {
1253 : 137856 : gimple *stmt = USE_STMT (use_p);
1254 : 137856 : if (gimple_clobber_p (stmt))
1255 : 302 : m_dead_stmts.add (stmt);
1256 : 137554 : else if (gimple_code (stmt) == GIMPLE_RETURN)
1257 : 170 : gcc_assert (m_adjustments && m_adjustments->m_skip_return);
1258 : : }
1259 : : }
1260 : :
1261 : : /* Callback to walk_tree. If REMAP is an SSA_NAME that is present in hash_map
1262 : : passed in DATA, replace it with unshared version of what it was mapped to.
1263 : : If an SSA argument would be remapped to NULL, the whole operation needs to
1264 : : abort which is signaled by returning error_mark_node. */
1265 : :
1266 : : static tree
1267 : 15178 : replace_with_mapped_expr (tree *remap, int *walk_subtrees, void *data)
1268 : : {
1269 : 15178 : if (TYPE_P (*remap))
1270 : : {
1271 : 0 : *walk_subtrees = 0;
1272 : 0 : return 0;
1273 : : }
1274 : 15178 : if (TREE_CODE (*remap) != SSA_NAME)
1275 : : return 0;
1276 : :
1277 : 2736 : *walk_subtrees = 0;
1278 : :
1279 : 2736 : hash_map<tree, tree> *equivs = (hash_map<tree, tree> *) data;
1280 : 2736 : if (tree *p = equivs->get (*remap))
1281 : : {
1282 : 2641 : if (!*p)
1283 : 1 : return error_mark_node;
1284 : 2640 : *remap = unshare_expr (*p);
1285 : : }
1286 : : return 0;
1287 : : }
1288 : :
1289 : : /* Replace all occurances of SSAs in m_dead_ssa_debug_equiv in t with what they
1290 : : are mapped to. */
1291 : :
1292 : : void
1293 : 8224 : ipa_param_body_adjustments::remap_with_debug_expressions (tree *t)
1294 : : {
1295 : : /* If *t is an SSA_NAME which should have its debug statements reset, it is
1296 : : mapped to NULL in the hash_map.
1297 : :
1298 : : It is perhaps simpler to handle the SSA_NAME cases directly and only
1299 : : invoke walk_tree on more complex expressions. When
1300 : : remap_with_debug_expressions is called from tree-inline.cc, a to-be-reset
1301 : : SSA_NAME can be an operand to such expressions and the entire debug
1302 : : variable we are remapping should be reset. This is signaled by walk_tree
1303 : : returning error_mark_node and done by setting *t to NULL. */
1304 : 8224 : if (TREE_CODE (*t) == SSA_NAME)
1305 : : {
1306 : 5641 : if (tree *p = m_dead_ssa_debug_equiv.get (*t))
1307 : 5641 : *t = *p;
1308 : : }
1309 : 2583 : else if (walk_tree (t, replace_with_mapped_expr,
1310 : 2583 : &m_dead_ssa_debug_equiv, NULL) == error_mark_node)
1311 : 1 : *t = NULL_TREE;
1312 : 8224 : }
1313 : :
1314 : : /* For an SSA_NAME DEAD_SSA which is about to be DCEd because it is based on a
1315 : : useless parameter, prepare an expression that should represent it in
1316 : : debug_binds in the cloned function and add a mapping from DEAD_SSA to
1317 : : m_dead_ssa_debug_equiv. That mapping is to NULL when the associated
1318 : : debug_statement has to be reset instead. In such case return false,
1319 : : ottherwise return true. If DEAD_SSA comes from a basic block which is not
1320 : : about to be copied, ignore it and return true. */
1321 : :
1322 : : bool
1323 : 4380 : ipa_param_body_adjustments::prepare_debug_expressions (tree dead_ssa)
1324 : : {
1325 : 4380 : gcc_checking_assert (m_dead_ssas.contains (dead_ssa));
1326 : 4380 : if (tree *d = m_dead_ssa_debug_equiv.get (dead_ssa))
1327 : 3206 : return (*d != NULL_TREE);
1328 : :
1329 : 1174 : gcc_assert (!SSA_NAME_IS_DEFAULT_DEF (dead_ssa));
1330 : 1174 : gimple *def = SSA_NAME_DEF_STMT (dead_ssa);
1331 : 1174 : if (m_id->blocks_to_copy
1332 : 1174 : && !bitmap_bit_p (m_id->blocks_to_copy, gimple_bb (def)->index))
1333 : : return true;
1334 : :
1335 : 1174 : if (gimple_code (def) == GIMPLE_PHI)
1336 : : {
1337 : : /* In theory, we could ignore all SSAs coming from BBs not in
1338 : : m_id->blocks_to_copy but at the time of the writing this code that
1339 : : should never really be the case because only fnsplit uses that bitmap,
1340 : : so don't bother. */
1341 : 185 : tree value = degenerate_phi_result (as_a <gphi *> (def));
1342 : 185 : if (!value
1343 : 185 : || (m_dead_ssas.contains (value)
1344 : 0 : && !prepare_debug_expressions (value)))
1345 : : {
1346 : 185 : m_dead_ssa_debug_equiv.put (dead_ssa, NULL_TREE);
1347 : 185 : return false;
1348 : : }
1349 : :
1350 : 0 : gcc_assert (TREE_CODE (value) == SSA_NAME);
1351 : 0 : tree *d = m_dead_ssa_debug_equiv.get (value);
1352 : 0 : m_dead_ssa_debug_equiv.put (dead_ssa, *d);
1353 : 0 : return true;
1354 : : }
1355 : :
1356 : 989 : bool lost = false;
1357 : 989 : use_operand_p use_p;
1358 : 989 : ssa_op_iter oi;
1359 : 2007 : FOR_EACH_PHI_OR_STMT_USE (use_p, def, oi, SSA_OP_USE)
1360 : : {
1361 : 1216 : tree use = USE_FROM_PTR (use_p);
1362 : 1216 : if (m_dead_ssas.contains (use)
1363 : 1216 : && !prepare_debug_expressions (use))
1364 : : {
1365 : 198 : lost = true;
1366 : 198 : break;
1367 : : }
1368 : : }
1369 : :
1370 : 989 : if (lost)
1371 : : {
1372 : 198 : m_dead_ssa_debug_equiv.put (dead_ssa, NULL_TREE);
1373 : 198 : return false;
1374 : : }
1375 : :
1376 : 791 : if (is_gimple_assign (def))
1377 : : {
1378 : 791 : gcc_assert (!gimple_clobber_p (def));
1379 : 791 : if (gimple_assign_copy_p (def)
1380 : 791 : && TREE_CODE (gimple_assign_rhs1 (def)) == SSA_NAME)
1381 : : {
1382 : 0 : tree d = *m_dead_ssa_debug_equiv.get (gimple_assign_rhs1 (def));
1383 : 0 : gcc_assert (d);
1384 : 0 : m_dead_ssa_debug_equiv.put (dead_ssa, d);
1385 : 0 : return true;
1386 : : }
1387 : :
1388 : 791 : tree val
1389 : 791 : = unshare_expr_without_location (gimple_assign_rhs_to_tree (def));
1390 : 791 : remap_with_debug_expressions (&val);
1391 : :
1392 : 791 : tree vexpr = build_debug_expr_decl (TREE_TYPE (val));
1393 : 791 : m_dead_stmt_debug_equiv.put (def, val);
1394 : 791 : m_dead_ssa_debug_equiv.put (dead_ssa, vexpr);
1395 : 791 : return true;
1396 : : }
1397 : : else
1398 : 0 : gcc_unreachable ();
1399 : : }
1400 : :
1401 : : /* Common initialization performed by all ipa_param_body_adjustments
1402 : : constructors. OLD_FNDECL is the declaration we take original arguments
1403 : : from, (it may be the same as M_FNDECL). VARS, if non-NULL, is a pointer to
1404 : : a chained list of new local variables. TREE_MAP is the IPA-CP produced
1405 : : mapping of trees to constants.
1406 : :
1407 : : The function is rather long but it really onlu initializes all data members
1408 : : of the class. It creates new param DECLs, finds their new types, */
1409 : :
1410 : : void
1411 : 147487 : ipa_param_body_adjustments::common_initialization (tree old_fndecl,
1412 : : tree *vars,
1413 : : vec<ipa_replace_map *,
1414 : : va_gc> *tree_map)
1415 : : {
1416 : 147487 : push_function_arg_decls (&m_oparms, old_fndecl);
1417 : 147487 : auto_vec<tree,16> otypes;
1418 : 147487 : if (TYPE_ARG_TYPES (TREE_TYPE (old_fndecl)) != NULL_TREE)
1419 : 147325 : push_function_arg_types (&otypes, TREE_TYPE (old_fndecl));
1420 : : else
1421 : : {
1422 : 162 : auto_vec<tree,16> oparms;
1423 : 162 : push_function_arg_decls (&oparms, old_fndecl);
1424 : 162 : unsigned ocount = oparms.length ();
1425 : 162 : otypes.reserve_exact (ocount);
1426 : 432 : for (unsigned i = 0; i < ocount; i++)
1427 : 270 : otypes.quick_push (TREE_TYPE (oparms[i]));
1428 : 162 : }
1429 : 147487 : fill_vector_of_new_param_types (&m_new_types, &otypes, m_adj_params, true);
1430 : :
1431 : 147487 : auto_vec<bool, 16> kept;
1432 : 294974 : kept.reserve_exact (m_oparms.length ());
1433 : 294974 : kept.quick_grow_cleared (m_oparms.length ());
1434 : 147487 : auto_vec<bool, 16> split;
1435 : 147487 : split.reserve_exact (m_oparms.length ());
1436 : 294974 : split.quick_grow_cleared (m_oparms.length ());
1437 : :
1438 : 147487 : unsigned adj_len = vec_safe_length (m_adj_params);
1439 : 147487 : m_method2func = ((TREE_CODE (TREE_TYPE (m_fndecl)) == METHOD_TYPE)
1440 : 147487 : && (adj_len == 0
1441 : 40074 : || (*m_adj_params)[0].op != IPA_PARAM_OP_COPY
1442 : 39954 : || (*m_adj_params)[0].base_index != 0));
1443 : :
1444 : : /* The main job of the this function is to go over the vector of adjusted
1445 : : parameters and create declarations or find corresponding old ones and push
1446 : : them to m_new_decls. For IPA-SRA replacements it also creates
1447 : : corresponding m_id->dst_node->clone.performed_splits entries. */
1448 : :
1449 : 147487 : m_new_decls.reserve_exact (adj_len);
1450 : 453902 : for (unsigned i = 0; i < adj_len ; i++)
1451 : : {
1452 : 306415 : ipa_adjusted_param *apm = &(*m_adj_params)[i];
1453 : 306415 : unsigned prev_index = apm->prev_clone_index;
1454 : 306415 : tree new_parm;
1455 : 306415 : if (apm->op == IPA_PARAM_OP_COPY
1456 : 85325 : || apm->prev_clone_adjustment)
1457 : : {
1458 : 221090 : kept[prev_index] = true;
1459 : 221090 : new_parm = carry_over_param (m_oparms[prev_index]);
1460 : 221090 : m_new_decls.quick_push (new_parm);
1461 : : }
1462 : 85325 : else if (apm->op == IPA_PARAM_OP_NEW
1463 : 85325 : || apm->op == IPA_PARAM_OP_SPLIT)
1464 : : {
1465 : 85325 : tree new_type = m_new_types[i];
1466 : 85325 : gcc_checking_assert (new_type);
1467 : 85325 : new_parm = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL_TREE,
1468 : : new_type);
1469 : 85325 : const char *prefix = ipa_param_prefixes[apm->param_prefix_index];
1470 : 85325 : DECL_NAME (new_parm) = create_tmp_var_name (prefix);
1471 : 85325 : DECL_ARTIFICIAL (new_parm) = 1;
1472 : 85325 : DECL_ARG_TYPE (new_parm) = new_type;
1473 : 85325 : DECL_CONTEXT (new_parm) = m_fndecl;
1474 : 85325 : TREE_USED (new_parm) = 1;
1475 : 85325 : DECL_IGNORED_P (new_parm) = 1;
1476 : 85325 : layout_decl (new_parm, 0);
1477 : 85325 : m_new_decls.quick_push (new_parm);
1478 : :
1479 : 85325 : if (apm->op == IPA_PARAM_OP_SPLIT)
1480 : : {
1481 : 76597 : split[prev_index] = true;
1482 : 76597 : register_replacement (apm, new_parm);
1483 : : }
1484 : : }
1485 : : else
1486 : 0 : gcc_unreachable ();
1487 : : }
1488 : :
1489 : 147487 : auto_vec <int, 16> index_mapping;
1490 : 147487 : bool need_remap = false;
1491 : 147487 : if (m_id)
1492 : : {
1493 : 143027 : clone_info *cinfo = clone_info::get (m_id->src_node);
1494 : 143027 : if (cinfo && cinfo->param_adjustments)
1495 : : {
1496 : 2254 : cinfo->param_adjustments->get_updated_indices (&index_mapping);
1497 : 2254 : need_remap = true;
1498 : : }
1499 : :
1500 : 143027 : if (ipcp_transformation *ipcp_ts
1501 : 143027 : = ipcp_get_transformation_summary (m_id->src_node))
1502 : : {
1503 : 37120 : for (const ipa_argagg_value &av : ipcp_ts->m_agg_values)
1504 : : {
1505 : 14181 : int parm_num = av.index;
1506 : :
1507 : 14181 : if (need_remap)
1508 : : {
1509 : : /* FIXME: We cannot handle the situation when IPA-CP
1510 : : identified that a parameter is a pointer to a global
1511 : : variable and at the same time the variable has some known
1512 : : constant contents (PR 107640). The best place to make
1513 : : sure we don't drop such constants on the floor probably is
1514 : : not here, but we have to make sure that it does not
1515 : : confuse the remapping. */
1516 : 13110 : if (parm_num >= (int) index_mapping.length ())
1517 : 23 : continue;
1518 : 6532 : parm_num = index_mapping[parm_num];
1519 : 6532 : if (parm_num < 0)
1520 : 30 : continue;
1521 : : }
1522 : :
1523 : 14128 : if (!kept[parm_num])
1524 : : {
1525 : : /* IPA-CP has detected an aggregate constant in a parameter
1526 : : that will not be kept, which means that IPA-SRA would have
1527 : : split it if there wasn't a constant. Because we are about
1528 : : to remove the original, this is the last chance where we
1529 : : can substitute the uses with a constant (for values passed
1530 : : by reference) or do the split but initialize the
1531 : : replacement with a constant (for split aggregates passed
1532 : : by value). */
1533 : :
1534 : 10744 : if (split[parm_num])
1535 : : {
1536 : : /* We must be careful not to add a duplicate
1537 : : replacement. */
1538 : 9531 : sort_replacements ();
1539 : 9531 : ipa_param_body_replacement *pbr
1540 : 9531 : = lookup_replacement_1 (m_oparms[parm_num],
1541 : 9531 : av.unit_offset);
1542 : 9531 : if (pbr)
1543 : : {
1544 : : /* Otherwise IPA-SRA should have bailed out. */
1545 : 2 : gcc_assert (AGGREGATE_TYPE_P (TREE_TYPE (pbr->repl)));
1546 : 2 : continue;
1547 : : }
1548 : : }
1549 : :
1550 : 10742 : tree repl;
1551 : 10742 : if (av.by_ref)
1552 : 9482 : repl = av.value;
1553 : : else
1554 : : {
1555 : 1260 : repl = create_tmp_var (TREE_TYPE (av.value),
1556 : : "removed_ipa_cp");
1557 : 1260 : gimple *init_stmt = gimple_build_assign (repl, av.value);
1558 : 1260 : m_split_agg_csts_inits.safe_push (init_stmt);
1559 : : }
1560 : 10742 : register_replacement (m_oparms[parm_num], av.unit_offset,
1561 : : repl);
1562 : 10742 : split[parm_num] = true;
1563 : : }
1564 : : }
1565 : : }
1566 : : }
1567 : 147487 : sort_replacements ();
1568 : :
1569 : 147487 : if (tree_map)
1570 : : {
1571 : : /* Do not treat parameters which were replaced with a constant as
1572 : : completely vanished. */
1573 : 27598 : for (unsigned i = 0; i < tree_map->length (); i++)
1574 : : {
1575 : 16673 : int parm_num = (*tree_map)[i]->parm_num;
1576 : 16673 : gcc_assert (parm_num >= 0);
1577 : 16673 : if (need_remap)
1578 : 0 : parm_num = index_mapping[parm_num];
1579 : 16673 : kept[parm_num] = true;
1580 : : }
1581 : : }
1582 : :
1583 : : /* As part of body modifications, we will also have to replace remaining uses
1584 : : of remaining uses of removed PARM_DECLs (which do not however use the
1585 : : initial value) with their VAR_DECL copies.
1586 : :
1587 : : We do this differently with and without m_id. With m_id, we rely on its
1588 : : mapping and create a replacement straight away. Without it, we have our
1589 : : own mechanism for which we have to populate m_removed_decls vector. Just
1590 : : don't mix them, that is why you should not call
1591 : : replace_removed_params_ssa_names or perform_cfun_body_modifications when
1592 : : you construct with ID not equal to NULL. */
1593 : :
1594 : 147487 : auto_vec<tree, 8> ssas_to_process_debug;
1595 : 147487 : unsigned op_len = m_oparms.length ();
1596 : 536049 : for (unsigned i = 0; i < op_len; i++)
1597 : 388562 : if (!kept[i])
1598 : : {
1599 : 150799 : if (m_id)
1600 : : {
1601 : 146308 : gcc_assert (!m_id->decl_map->get (m_oparms[i]));
1602 : 146308 : tree var = copy_decl_to_var (m_oparms[i], m_id);
1603 : 146308 : insert_decl_map (m_id, m_oparms[i], var);
1604 : : /* Declare this new variable. */
1605 : 146308 : DECL_CHAIN (var) = *vars;
1606 : 146308 : *vars = var;
1607 : :
1608 : : /* If this is not a split but a real removal, init hash sets
1609 : : that will guide what not to copy to the new body. */
1610 : 146308 : if (!split[i])
1611 : 98962 : mark_dead_statements (m_oparms[i], &ssas_to_process_debug);
1612 : : else
1613 : 47346 : mark_clobbers_dead (m_oparms[i]);
1614 : 18160 : if (MAY_HAVE_DEBUG_STMTS
1615 : 146308 : && is_gimple_reg (m_oparms[i]))
1616 : 99558 : m_reset_debug_decls.safe_push (m_oparms[i]);
1617 : : }
1618 : : else
1619 : : {
1620 : 4491 : m_removed_decls.safe_push (m_oparms[i]);
1621 : 8982 : m_removed_map.put (m_oparms[i], m_removed_decls.length () - 1);
1622 : 4218 : if (MAY_HAVE_DEBUG_STMTS
1623 : 273 : && !kept[i]
1624 : 4764 : && is_gimple_reg (m_oparms[i]))
1625 : 233 : m_reset_debug_decls.safe_push (m_oparms[i]);
1626 : : }
1627 : : }
1628 : :
1629 : 298247 : while (!ssas_to_process_debug.is_empty ())
1630 : 3273 : prepare_debug_expressions (ssas_to_process_debug.pop ());
1631 : 147487 : }
1632 : :
1633 : : /* Constructor of ipa_param_body_adjustments from a simple list of
1634 : : modifications to parameters listed in ADJ_PARAMS which will prepare ground
1635 : : for modification of parameters of fndecl. Return value of the function will
1636 : : not be removed and the object will assume it does not run as a part of
1637 : : tree-function_versioning. */
1638 : :
1639 : 4432 : ipa_param_body_adjustments
1640 : : ::ipa_param_body_adjustments (vec<ipa_adjusted_param, va_gc> *adj_params,
1641 : 4432 : tree fndecl)
1642 : 4432 : : m_adj_params (adj_params), m_adjustments (NULL), m_reset_debug_decls (),
1643 : 4432 : m_dead_stmts (), m_dead_ssas (), m_dead_ssa_debug_equiv (),
1644 : 4432 : m_dead_stmt_debug_equiv (), m_fndecl (fndecl), m_id (NULL), m_oparms (),
1645 : 4432 : m_new_decls (), m_new_types (), m_replacements (),
1646 : 4432 : m_split_agg_csts_inits (), m_removed_decls (), m_removed_map (),
1647 : 4432 : m_method2func (false), m_sorted_replacements_p (true)
1648 : : {
1649 : 4432 : common_initialization (fndecl, NULL, NULL);
1650 : 4432 : }
1651 : :
1652 : : /* Constructor of ipa_param_body_adjustments from ipa_param_adjustments in
1653 : : ADJUSTMENTS which will prepare ground for modification of parameters of
1654 : : fndecl. The object will assume it does not run as a part of
1655 : : tree-function_versioning. */
1656 : :
1657 : 28 : ipa_param_body_adjustments
1658 : : ::ipa_param_body_adjustments (ipa_param_adjustments *adjustments,
1659 : 28 : tree fndecl)
1660 : 28 : : m_adj_params (adjustments->m_adj_params), m_adjustments (adjustments),
1661 : 28 : m_reset_debug_decls (), m_dead_stmts (), m_dead_ssas (),
1662 : 28 : m_dead_ssa_debug_equiv (), m_dead_stmt_debug_equiv (), m_fndecl (fndecl),
1663 : 28 : m_id (NULL), m_oparms (), m_new_decls (), m_new_types (), m_replacements (),
1664 : 28 : m_split_agg_csts_inits (), m_removed_decls (), m_removed_map (),
1665 : 28 : m_method2func (false), m_sorted_replacements_p (true)
1666 : : {
1667 : 28 : common_initialization (fndecl, NULL, NULL);
1668 : 28 : }
1669 : :
1670 : : /* Constructor of ipa_param_body_adjustments which sets it up as a part of
1671 : : running tree_function_versioning. Planned modifications to the function are
1672 : : in ADJUSTMENTS. FNDECL designates the new function clone which is being
1673 : : modified. OLD_FNDECL is the function of which FNDECL is a clone (and which
1674 : : at the time of invocation still share DECL_ARGUMENTS). ID is the
1675 : : copy_body_data structure driving the wholy body copying process. VARS is a
1676 : : pointer to the head of the list of new local variables, TREE_MAP is the map
1677 : : that drives tree substitution in the cloning process. */
1678 : :
1679 : 143027 : ipa_param_body_adjustments
1680 : : ::ipa_param_body_adjustments (ipa_param_adjustments *adjustments,
1681 : : tree fndecl, tree old_fndecl,
1682 : : copy_body_data *id, tree *vars,
1683 : 143027 : vec<ipa_replace_map *, va_gc> *tree_map)
1684 : 143027 : : m_adj_params (adjustments->m_adj_params), m_adjustments (adjustments),
1685 : 143027 : m_reset_debug_decls (), m_dead_stmts (), m_dead_ssas (),
1686 : 143027 : m_dead_ssa_debug_equiv (), m_dead_stmt_debug_equiv (), m_fndecl (fndecl),
1687 : 143027 : m_id (id), m_oparms (), m_new_decls (), m_new_types (), m_replacements (),
1688 : 143027 : m_split_agg_csts_inits (), m_removed_decls (), m_removed_map (),
1689 : 143027 : m_method2func (false), m_sorted_replacements_p (true)
1690 : : {
1691 : 143027 : common_initialization (old_fndecl, vars, tree_map);
1692 : 143027 : }
1693 : :
1694 : : /* Chain new param decls up and return them. */
1695 : :
1696 : : tree
1697 : 147487 : ipa_param_body_adjustments::get_new_param_chain ()
1698 : : {
1699 : 147487 : tree result;
1700 : 147487 : tree *link = &result;
1701 : :
1702 : 147487 : unsigned len = vec_safe_length (m_adj_params);
1703 : 453902 : for (unsigned i = 0; i < len; i++)
1704 : : {
1705 : 306415 : tree new_decl = m_new_decls[i];
1706 : 306415 : *link = new_decl;
1707 : 306415 : link = &DECL_CHAIN (new_decl);
1708 : : }
1709 : 147487 : *link = NULL_TREE;
1710 : 147487 : return result;
1711 : : }
1712 : :
1713 : : /* Modify the function parameters FNDECL and its type according to the plan in
1714 : : ADJUSTMENTS. This function needs to be called when the decl has not already
1715 : : been processed with ipa_param_adjustments::adjust_decl, otherwise just
1716 : : seting DECL_ARGUMENTS to whatever get_new_param_chain will do is enough. */
1717 : :
1718 : : void
1719 : 4460 : ipa_param_body_adjustments::modify_formal_parameters ()
1720 : : {
1721 : 4460 : tree orig_type = TREE_TYPE (m_fndecl);
1722 : 4460 : DECL_ARGUMENTS (m_fndecl) = get_new_param_chain ();
1723 : :
1724 : : /* When signature changes, we need to clear builtin info. */
1725 : 4460 : if (fndecl_built_in_p (m_fndecl))
1726 : 0 : set_decl_built_in_function (m_fndecl, NOT_BUILT_IN, 0);
1727 : :
1728 : 4460 : bool modified = false;
1729 : 4460 : size_t index = 0;
1730 : 4460 : if (m_adj_params)
1731 : 4108 : for (tree t = TYPE_ARG_TYPES (orig_type);
1732 : 10554 : t && !modified;
1733 : 6446 : t = TREE_CHAIN (t), index++)
1734 : 6446 : if (index >= m_adj_params->length ()
1735 : 5861 : || (*m_adj_params)[index].op != IPA_PARAM_OP_COPY
1736 : 8825 : || (*m_adj_params)[index].base_index != index)
1737 : : modified = true;
1738 : :
1739 : : /* At this point, removing return value is only implemented when going
1740 : : through tree_function_versioning, not when modifying function body
1741 : : directly. */
1742 : 4460 : gcc_assert (!m_adjustments || !m_adjustments->m_skip_return);
1743 : 8920 : tree new_type = build_adjusted_function_type (orig_type, &m_new_types,
1744 : 4460 : m_method2func, false, modified);
1745 : :
1746 : 4460 : TREE_TYPE (m_fndecl) = new_type;
1747 : 4460 : DECL_VIRTUAL_P (m_fndecl) = 0;
1748 : 4460 : DECL_LANG_SPECIFIC (m_fndecl) = NULL;
1749 : 4460 : if (m_method2func)
1750 : 120 : DECL_VINDEX (m_fndecl) = NULL_TREE;
1751 : 4460 : }
1752 : :
1753 : : /* Given BASE and UNIT_OFFSET, find the corresponding record among replacement
1754 : : structures. */
1755 : :
1756 : : ipa_param_body_replacement *
1757 : 167198 : ipa_param_body_adjustments::lookup_replacement_1 (tree base,
1758 : : unsigned unit_offset)
1759 : : {
1760 : 167198 : gcc_assert (m_sorted_replacements_p);
1761 : 167198 : ipa_param_body_replacement key;
1762 : 167198 : key.base = base;
1763 : 167198 : key.unit_offset = unit_offset;
1764 : 167198 : ipa_param_body_replacement *res
1765 : 334396 : = std::lower_bound (m_replacements.begin (), m_replacements.end (), key,
1766 : 321905 : [] (const ipa_param_body_replacement &elt,
1767 : : const ipa_param_body_replacement &val)
1768 : : {
1769 : 321905 : return (compare_param_body_replacement (&elt, &val)
1770 : : < 0);
1771 : : });
1772 : :
1773 : 167198 : if (res == m_replacements.end ()
1774 : 132255 : || res->base != base
1775 : 256629 : || res->unit_offset != unit_offset)
1776 : 78947 : return NULL;
1777 : : return res;
1778 : : }
1779 : :
1780 : : /* Find the first replacement for BASE among m_replacements and return pointer
1781 : : to it, or NULL if there is none. */
1782 : :
1783 : : ipa_param_body_replacement *
1784 : 24351 : ipa_param_body_adjustments::lookup_first_base_replacement (tree base)
1785 : : {
1786 : 24351 : gcc_assert (m_sorted_replacements_p);
1787 : 24351 : ipa_param_body_replacement key;
1788 : 24351 : key.base = base;
1789 : 24351 : ipa_param_body_replacement *res
1790 : 48702 : = std::lower_bound (m_replacements.begin (), m_replacements.end (), key,
1791 : 37629 : [] (const ipa_param_body_replacement &elt,
1792 : : const ipa_param_body_replacement &val)
1793 : : {
1794 : 37629 : if (DECL_UID (elt.base) < DECL_UID (val.base))
1795 : 12275 : return true;
1796 : : return false;
1797 : : });
1798 : :
1799 : 24351 : if (res == m_replacements.end ()
1800 : 24351 : || res->base != base)
1801 : 18982 : return NULL;
1802 : : return res;
1803 : : }
1804 : :
1805 : : /* Given BASE and UNIT_OFFSET, find the corresponding replacement expression
1806 : : and return it, assuming it is known it does not hold value by reference or
1807 : : in reverse storage order. */
1808 : :
1809 : : tree
1810 : 4019 : ipa_param_body_adjustments::lookup_replacement (tree base, unsigned unit_offset)
1811 : : {
1812 : 4019 : ipa_param_body_replacement *pbr = lookup_replacement_1 (base, unit_offset);
1813 : 4019 : if (!pbr)
1814 : : return NULL;
1815 : 4019 : return pbr->repl;
1816 : : }
1817 : :
1818 : : /* If T is an SSA_NAME, return NULL if it is not a default def or
1819 : : return its base variable if it is. If IGNORE_DEFAULT_DEF is true,
1820 : : the base variable is always returned, regardless if it is a default
1821 : : def. Return T if it is not an SSA_NAME. */
1822 : :
1823 : : static tree
1824 : 998643 : get_ssa_base_param (tree t, bool ignore_default_def)
1825 : : {
1826 : 998643 : if (TREE_CODE (t) == SSA_NAME)
1827 : : {
1828 : 614548 : if (ignore_default_def || SSA_NAME_IS_DEFAULT_DEF (t))
1829 : 129298 : return SSA_NAME_VAR (t);
1830 : : else
1831 : : return NULL_TREE;
1832 : : }
1833 : : return t;
1834 : : }
1835 : :
1836 : : /* Given an expression, return the structure describing how it should be
1837 : : replaced if it accesses a part of a split parameter or NULL otherwise.
1838 : :
1839 : : Do not free the result, it will be deallocated when the object is destroyed.
1840 : :
1841 : : If IGNORE_DEFAULT_DEF is cleared, consider only SSA_NAMEs of PARM_DECLs
1842 : : which are default definitions, if set, consider all SSA_NAMEs of
1843 : : PARM_DECLs. */
1844 : :
1845 : : ipa_param_body_replacement *
1846 : 1004348 : ipa_param_body_adjustments::get_expr_replacement (tree expr,
1847 : : bool ignore_default_def)
1848 : : {
1849 : 1004348 : tree base;
1850 : 1004348 : unsigned unit_offset;
1851 : :
1852 : 1004348 : if (!isra_get_ref_base_and_offset (expr, &base, &unit_offset))
1853 : : return NULL;
1854 : :
1855 : 998643 : base = get_ssa_base_param (base, ignore_default_def);
1856 : 998643 : if (!base || TREE_CODE (base) != PARM_DECL)
1857 : : return NULL;
1858 : 152740 : return lookup_replacement_1 (base, unit_offset);
1859 : : }
1860 : :
1861 : : /* Given OLD_DECL, which is a PARM_DECL of a parameter that is being removed
1862 : : (which includes it being split or replaced), return a new variable that
1863 : : should be used for any SSA names that will remain in the function that
1864 : : previously belonged to OLD_DECL. */
1865 : :
1866 : : tree
1867 : 7905 : ipa_param_body_adjustments::get_replacement_ssa_base (tree old_decl)
1868 : : {
1869 : 7905 : unsigned *idx = m_removed_map.get (old_decl);
1870 : 7905 : if (!idx)
1871 : : return NULL;
1872 : :
1873 : 4451 : tree repl;
1874 : 4451 : if (TREE_CODE (m_removed_decls[*idx]) == PARM_DECL)
1875 : : {
1876 : 4019 : gcc_assert (m_removed_decls[*idx] == old_decl);
1877 : 4019 : repl = copy_var_decl (old_decl, DECL_NAME (old_decl),
1878 : 4019 : TREE_TYPE (old_decl));
1879 : 4019 : m_removed_decls[*idx] = repl;
1880 : : }
1881 : : else
1882 : : repl = m_removed_decls[*idx];
1883 : : return repl;
1884 : : }
1885 : :
1886 : : /* If OLD_NAME, which is being defined by statement STMT, is an SSA_NAME of a
1887 : : parameter which is to be removed because its value is not used, create a new
1888 : : SSA_NAME relating to a replacement VAR_DECL, replace all uses of the
1889 : : original with it and return it. If there is no need to re-map, return NULL.
1890 : : ADJUSTMENTS is a pointer to a vector of IPA-SRA adjustments. */
1891 : :
1892 : : tree
1893 : 0 : ipa_param_body_adjustments::replace_removed_params_ssa_names (tree old_name,
1894 : : gimple *stmt)
1895 : : {
1896 : 0 : gcc_assert (!m_id);
1897 : 0 : if (TREE_CODE (old_name) != SSA_NAME)
1898 : : return NULL;
1899 : :
1900 : 0 : tree decl = SSA_NAME_VAR (old_name);
1901 : 0 : if (decl == NULL_TREE
1902 : 0 : || TREE_CODE (decl) != PARM_DECL)
1903 : : return NULL;
1904 : :
1905 : 0 : tree repl = get_replacement_ssa_base (decl);
1906 : 0 : if (!repl)
1907 : : return NULL;
1908 : :
1909 : 0 : tree new_name = make_ssa_name (repl, stmt);
1910 : 0 : SSA_NAME_OCCURS_IN_ABNORMAL_PHI (new_name)
1911 : 0 : = SSA_NAME_OCCURS_IN_ABNORMAL_PHI (old_name);
1912 : :
1913 : 0 : if (dump_file && (dump_flags & TDF_DETAILS))
1914 : : {
1915 : 0 : fprintf (dump_file, "replacing an SSA name of a removed param ");
1916 : 0 : print_generic_expr (dump_file, old_name);
1917 : 0 : fprintf (dump_file, " with ");
1918 : 0 : print_generic_expr (dump_file, new_name);
1919 : 0 : fprintf (dump_file, "\n");
1920 : : }
1921 : :
1922 : 0 : replace_uses_by (old_name, new_name);
1923 : 0 : return new_name;
1924 : : }
1925 : :
1926 : : /* If the expression *EXPR_P should be replaced, do so. CONVERT specifies
1927 : : whether the function should care about type incompatibility of the current
1928 : : and new expressions. If it is false, the function will leave
1929 : : incompatibility issues to the caller - note that when the function
1930 : : encounters a BIT_FIELD_REF, IMAGPART_EXPR or REALPART_EXPR, it will modify
1931 : : their bases instead of the expressions themselves and then also performs any
1932 : : necessary conversions. */
1933 : :
1934 : : bool
1935 : 2322018 : ipa_param_body_adjustments::modify_expression (tree *expr_p, bool convert,
1936 : : gimple_seq *extra_stmts)
1937 : : {
1938 : 2322018 : tree expr = *expr_p;
1939 : :
1940 : 4562012 : if (m_replacements.is_empty ())
1941 : : return false;
1942 : 1002264 : if (TREE_CODE (expr) == BIT_FIELD_REF
1943 : 1002264 : || TREE_CODE (expr) == IMAGPART_EXPR
1944 : 1001476 : || TREE_CODE (expr) == REALPART_EXPR)
1945 : : {
1946 : : /* For a BIT_FIELD_REF do not bother to VIEW_CONVERT the base,
1947 : : instead reference the replacement directly. */
1948 : 1117 : convert = TREE_CODE (expr) != BIT_FIELD_REF;
1949 : 1117 : expr_p = &TREE_OPERAND (expr, 0);
1950 : 1117 : expr = *expr_p;
1951 : : }
1952 : :
1953 : 1002264 : ipa_param_body_replacement *pbr = get_expr_replacement (expr, false);
1954 : 1002264 : if (!pbr)
1955 : : return false;
1956 : :
1957 : 82024 : tree repl = pbr->repl;
1958 : 82024 : if (dump_file && (dump_flags & TDF_DETAILS))
1959 : : {
1960 : 8 : fprintf (dump_file, "About to replace expr ");
1961 : 8 : print_generic_expr (dump_file, expr);
1962 : 8 : fprintf (dump_file, " with ");
1963 : 8 : print_generic_expr (dump_file, repl);
1964 : 8 : fprintf (dump_file, "\n");
1965 : : }
1966 : :
1967 : 82261 : if (convert && !useless_type_conversion_p (TREE_TYPE (expr),
1968 : 237 : TREE_TYPE (repl)))
1969 : : {
1970 : 8 : gcc_checking_assert (tree_to_shwi (TYPE_SIZE (TREE_TYPE (expr)))
1971 : : == tree_to_shwi (TYPE_SIZE (TREE_TYPE (repl))));
1972 : 8 : tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (expr), repl);
1973 : 8 : if (is_gimple_reg (repl)
1974 : 8 : && is_gimple_reg_type (TREE_TYPE (expr)))
1975 : : {
1976 : 0 : gcc_assert (extra_stmts);
1977 : 0 : vce = force_gimple_operand (vce, extra_stmts, true, NULL_TREE);
1978 : : }
1979 : 8 : *expr_p = vce;
1980 : : }
1981 : : else
1982 : 82016 : *expr_p = repl;
1983 : : return true;
1984 : : }
1985 : :
1986 : : /* If the assignment statement STMT contains any expressions that need to
1987 : : replaced with a different one as noted by ADJUSTMENTS, do so. Handle any
1988 : : potential type incompatibilities. If any conversion sttements have to be
1989 : : pre-pended to STMT, they will be added to EXTRA_STMTS. Return true iff the
1990 : : statement was modified. */
1991 : :
1992 : : bool
1993 : 1738579 : ipa_param_body_adjustments::modify_assignment (gimple *stmt,
1994 : : gimple_seq *extra_stmts)
1995 : : {
1996 : 1738579 : tree *lhs_p, *rhs_p;
1997 : 1738579 : bool any;
1998 : :
1999 : 2288635 : if (m_replacements.is_empty () || !gimple_assign_single_p (stmt))
2000 : : return false;
2001 : :
2002 : 378292 : rhs_p = gimple_assign_rhs1_ptr (stmt);
2003 : 378292 : lhs_p = gimple_assign_lhs_ptr (stmt);
2004 : :
2005 : 378292 : any = modify_expression (lhs_p, false);
2006 : 378292 : any |= modify_expression (rhs_p, false, extra_stmts);
2007 : 378292 : if (any
2008 : 378292 : && !useless_type_conversion_p (TREE_TYPE (*lhs_p), TREE_TYPE (*rhs_p)))
2009 : : {
2010 : 3 : if (TREE_CODE (*rhs_p) == CONSTRUCTOR)
2011 : : {
2012 : : /* V_C_Es of constructors can cause trouble (PR 42714). */
2013 : 0 : if (is_gimple_reg_type (TREE_TYPE (*lhs_p)))
2014 : 0 : *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
2015 : : else
2016 : 0 : *rhs_p = build_constructor (TREE_TYPE (*lhs_p),
2017 : : NULL);
2018 : : }
2019 : : else
2020 : : {
2021 : 3 : gcc_checking_assert (tree_to_shwi (TYPE_SIZE (TREE_TYPE (*lhs_p)))
2022 : : == tree_to_shwi (TYPE_SIZE (TREE_TYPE (*rhs_p))));
2023 : 3 : tree new_rhs = fold_build1_loc (gimple_location (stmt),
2024 : 3 : VIEW_CONVERT_EXPR, TREE_TYPE (*lhs_p),
2025 : : *rhs_p);
2026 : 3 : tree tmp = force_gimple_operand (new_rhs, extra_stmts, true,
2027 : : NULL_TREE);
2028 : 3 : gimple_assign_set_rhs1 (stmt, tmp);
2029 : : }
2030 : 3 : return true;
2031 : : }
2032 : :
2033 : : return any;
2034 : : }
2035 : :
2036 : : /* Record information about what modifications to call arguments have already
2037 : : been done by clone materialization into a summary describing CS. The
2038 : : information is stored in NEW_INDEX_MAP, NEW_PT_MAP and NEW_ALWAYS_COPY_DELTA
2039 : : and correspond to equivalent fields in ipa_edge_modification_info. Return
2040 : : the edge summary. */
2041 : :
2042 : : static ipa_edge_modification_info *
2043 : 11376 : record_argument_state_1 (cgraph_edge *cs, const vec<int> &new_index_map,
2044 : : const vec<pass_through_split_map> &new_pt_map,
2045 : : int new_always_copy_delta)
2046 : :
2047 : : {
2048 : 11376 : ipa_edge_modification_info *sum = ipa_edge_modifications->get_create (cs);
2049 : :
2050 : 11376 : unsigned len = sum->pass_through_map.length ();
2051 : 11376 : for (unsigned i = 0; i < len; i++)
2052 : : {
2053 : 0 : unsigned oldnew = sum->pass_through_map[i].new_index;
2054 : 0 : sum->pass_through_map[i].new_index = new_index_map[oldnew];
2055 : : }
2056 : :
2057 : 11376 : len = sum->index_map.length ();
2058 : 0 : if (len > 0)
2059 : : {
2060 : 0 : unsigned nptlen = new_pt_map.length ();
2061 : 0 : for (unsigned j = 0; j < nptlen; j++)
2062 : : {
2063 : 0 : int inverse = -1;
2064 : 0 : for (unsigned i = 0; i < len ; i++)
2065 : 0 : if ((unsigned) sum->index_map[i] == new_pt_map[j].base_index)
2066 : : {
2067 : 0 : inverse = i;
2068 : 0 : break;
2069 : : }
2070 : 0 : gcc_assert (inverse >= 0);
2071 : 0 : pass_through_split_map ptm_item;
2072 : :
2073 : 0 : ptm_item.base_index = inverse;
2074 : 0 : ptm_item.unit_offset = new_pt_map[j].unit_offset;
2075 : 0 : ptm_item.new_index = new_pt_map[j].new_index;
2076 : 0 : sum->pass_through_map.safe_push (ptm_item);
2077 : : }
2078 : :
2079 : 0 : for (unsigned i = 0; i < len; i++)
2080 : : {
2081 : 0 : int idx = sum->index_map[i];
2082 : 0 : if (idx < 0)
2083 : 0 : continue;
2084 : 0 : sum->index_map[i] = new_index_map[idx];
2085 : : }
2086 : : }
2087 : : else
2088 : : {
2089 : 11376 : sum->pass_through_map.safe_splice (new_pt_map);
2090 : 11376 : sum->index_map.safe_splice (new_index_map);
2091 : : }
2092 : 11376 : sum->always_copy_delta += new_always_copy_delta;
2093 : 11376 : return sum;
2094 : : }
2095 : :
2096 : : /* Record information about what modifications to call arguments have already
2097 : : been done by clone materialization into a summary of an edge describing the
2098 : : call in this clone and all its clones. NEW_INDEX_MAP, NEW_PT_MAP and
2099 : : NEW_ALWAYS_COPY_DELTA have the same meaning as record_argument_state_1.
2100 : :
2101 : : In order to associate the info with the right edge summaries, we need
2102 : : address of the ORIG_STMT in the function from which we are cloning (because
2103 : : the edges have not yet been re-assigned to the new statement that has just
2104 : : been created) and ID, the structure governing function body copying. */
2105 : :
2106 : : static void
2107 : 11376 : record_argument_state (copy_body_data *id, gimple *orig_stmt,
2108 : : const vec<int> &new_index_map,
2109 : : const vec<pass_through_split_map> &new_pt_map,
2110 : : int new_always_copy_delta)
2111 : : {
2112 : 11376 : if (!ipa_edge_modifications)
2113 : 2312 : ipa_edge_modifications = new ipa_edge_modification_sum (symtab);
2114 : :
2115 : 11376 : struct cgraph_node *this_node = id->dst_node;
2116 : 11376 : ipa_edge_modification_info *first_sum = NULL;
2117 : 11376 : cgraph_edge *cs = this_node->get_edge (orig_stmt);
2118 : 11376 : if (cs)
2119 : 11376 : first_sum = record_argument_state_1 (cs, new_index_map, new_pt_map,
2120 : : new_always_copy_delta);
2121 : : else
2122 : 0 : gcc_assert (this_node->clones);
2123 : :
2124 : 11376 : if (!this_node->clones)
2125 : : return;
2126 : 20649 : for (cgraph_node *subclone = this_node->clones; subclone != this_node;)
2127 : : {
2128 : 17168 : cs = subclone->get_edge (orig_stmt);
2129 : 17168 : if (cs)
2130 : : {
2131 : 17168 : if (!first_sum)
2132 : 0 : first_sum = record_argument_state_1 (cs, new_index_map, new_pt_map,
2133 : : new_always_copy_delta);
2134 : : else
2135 : : {
2136 : 17168 : ipa_edge_modification_info *s2
2137 : 17168 : = ipa_edge_modifications->get_create (cs);
2138 : 17168 : s2->index_map.truncate (0);
2139 : 17168 : s2->index_map.safe_splice (first_sum->index_map);
2140 : 17168 : s2->pass_through_map.truncate (0);
2141 : 17168 : s2->pass_through_map.safe_splice (first_sum->pass_through_map);
2142 : 17168 : s2->always_copy_delta = first_sum->always_copy_delta;
2143 : : }
2144 : : }
2145 : : else
2146 : 0 : gcc_assert (subclone->clones);
2147 : :
2148 : 17168 : if (subclone->clones)
2149 : : subclone = subclone->clones;
2150 : 16441 : else if (subclone->next_sibling_clone)
2151 : : subclone = subclone->next_sibling_clone;
2152 : : else
2153 : : {
2154 : 8098 : while (subclone != this_node && !subclone->next_sibling_clone)
2155 : 4208 : subclone = subclone->clone_of;
2156 : 3890 : if (subclone != this_node)
2157 : 409 : subclone = subclone->next_sibling_clone;
2158 : : }
2159 : : }
2160 : : }
2161 : :
2162 : : /* If the call statement pointed at by STMT_P contains any expressions that
2163 : : need to replaced with a different one as noted by ADJUSTMENTS, do so. f the
2164 : : statement needs to be rebuilt, do so. Return true if any modifications have
2165 : : been performed. ORIG_STMT, if not NULL, is the original statement in the
2166 : : function that is being cloned from, which at this point can be used to look
2167 : : up call_graph edges.
2168 : :
2169 : : If the method is invoked as a part of IPA clone materialization and if any
2170 : : parameter split is pass-through, i.e. it applies to the functin that is
2171 : : being modified and also to the callee of the statement, replace the
2172 : : parameter passed to old callee with all of the replacement a callee might
2173 : : possibly want and record the performed argument modifications in
2174 : : ipa_edge_modifications. Likewise if any argument has already been left out
2175 : : because it is not necessary. */
2176 : :
2177 : : bool
2178 : 564485 : ipa_param_body_adjustments::modify_call_stmt (gcall **stmt_p,
2179 : : gimple *orig_stmt)
2180 : : {
2181 : 564485 : auto_vec <unsigned, 4> pass_through_args;
2182 : 564485 : auto_vec <unsigned, 4> pass_through_pbr_indices;
2183 : 564485 : auto_vec <HOST_WIDE_INT, 4> pass_through_offsets;
2184 : 564485 : gcall *stmt = *stmt_p;
2185 : 564485 : unsigned nargs = gimple_call_num_args (stmt);
2186 : 564485 : bool recreate = false;
2187 : 564485 : gcc_assert (m_sorted_replacements_p);
2188 : :
2189 : 1884026 : for (unsigned i = 0; i < gimple_call_num_args (stmt); i++)
2190 : : {
2191 : 1319541 : tree t = gimple_call_arg (stmt, i);
2192 : 1319541 : gcc_assert (TREE_CODE (t) != BIT_FIELD_REF
2193 : : && TREE_CODE (t) != IMAGPART_EXPR
2194 : : && TREE_CODE (t) != REALPART_EXPR);
2195 : :
2196 : 1319541 : if (TREE_CODE (t) == SSA_NAME
2197 : 1319541 : && m_dead_ssas.contains (t))
2198 : : recreate = true;
2199 : :
2200 : 1319541 : if (m_replacements.is_empty ())
2201 : 1314172 : continue;
2202 : :
2203 : 184380 : tree base;
2204 : 184380 : unsigned agg_arg_offset;
2205 : 184380 : if (!isra_get_ref_base_and_offset (t, &base, &agg_arg_offset))
2206 : 0 : continue;
2207 : :
2208 : 184380 : bool by_ref = false;
2209 : 184380 : if (TREE_CODE (base) == SSA_NAME)
2210 : : {
2211 : 95688 : if (!SSA_NAME_IS_DEFAULT_DEF (base))
2212 : 74531 : continue;
2213 : 21157 : base = SSA_NAME_VAR (base);
2214 : 21157 : gcc_checking_assert (base);
2215 : : by_ref = true;
2216 : : }
2217 : 109849 : if (TREE_CODE (base) != PARM_DECL)
2218 : 85498 : continue;
2219 : :
2220 : 24351 : ipa_param_body_replacement *first_rep
2221 : 24351 : = lookup_first_base_replacement (base);
2222 : 24351 : if (!first_rep)
2223 : 18982 : continue;
2224 : 5369 : unsigned first_rep_index = first_rep - m_replacements.begin ();
2225 : :
2226 : : /* We still have to distinguish between an end-use that we have to
2227 : : transform now and a pass-through, which happens in the following
2228 : : two cases. */
2229 : :
2230 : : /* TODO: After we adjust ptr_parm_has_nonarg_uses to also consider
2231 : : &MEM_REF[ssa_name + offset], we will also have to detect that case
2232 : : here. */
2233 : :
2234 : 5369 : if (TREE_CODE (t) == SSA_NAME
2235 : 4452 : && SSA_NAME_IS_DEFAULT_DEF (t)
2236 : 4452 : && SSA_NAME_VAR (t)
2237 : 9821 : && TREE_CODE (SSA_NAME_VAR (t)) == PARM_DECL)
2238 : : {
2239 : : /* This must be a by_reference pass-through. */
2240 : 4452 : recreate = true;
2241 : 4452 : gcc_assert (POINTER_TYPE_P (TREE_TYPE (t)));
2242 : 4452 : pass_through_args.safe_push (i);
2243 : 4452 : pass_through_pbr_indices.safe_push (first_rep_index);
2244 : 4452 : pass_through_offsets.safe_push (agg_arg_offset);
2245 : : }
2246 : 917 : else if (!by_ref && AGGREGATE_TYPE_P (TREE_TYPE (t)))
2247 : : {
2248 : : /* Currently IPA-SRA guarantees the aggregate access type
2249 : : exactly matches in this case. So if it does not match, it is
2250 : : a pass-through argument that will be sorted out at edge
2251 : : redirection time. */
2252 : 908 : ipa_param_body_replacement *pbr
2253 : 908 : = lookup_replacement_1 (base, agg_arg_offset);
2254 : :
2255 : 908 : if (!pbr
2256 : 908 : || (TYPE_MAIN_VARIANT (TREE_TYPE (t))
2257 : 902 : != TYPE_MAIN_VARIANT (TREE_TYPE (pbr->repl))))
2258 : : {
2259 : 887 : recreate = true;
2260 : 887 : pass_through_args.safe_push (i);
2261 : 887 : pass_through_pbr_indices.safe_push (first_rep_index);
2262 : 887 : pass_through_offsets.safe_push (agg_arg_offset);
2263 : : }
2264 : : }
2265 : : }
2266 : :
2267 : 564485 : if (!recreate)
2268 : : {
2269 : : /* No need to rebuild the statement, let's just modify arguments
2270 : : and the LHS if/as appropriate. */
2271 : : bool modified = false;
2272 : 1833888 : for (unsigned i = 0; i < nargs; i++)
2273 : : {
2274 : 1280779 : tree *t = gimple_call_arg_ptr (stmt, i);
2275 : 1280779 : modified |= modify_expression (t, true);
2276 : : }
2277 : 553109 : if (gimple_call_lhs (stmt))
2278 : : {
2279 : 193740 : tree *t = gimple_call_lhs_ptr (stmt);
2280 : 193740 : modified |= modify_expression (t, false);
2281 : : }
2282 : 553109 : return modified;
2283 : : }
2284 : :
2285 : 11376 : auto_vec<int, 16> index_map;
2286 : 11376 : auto_vec<pass_through_split_map, 4> pass_through_map;
2287 : 11376 : auto_vec<tree, 16> vargs;
2288 : 11376 : int always_copy_delta = 0;
2289 : 11376 : unsigned pt_idx = 0;
2290 : 11376 : int new_arg_idx = 0;
2291 : 50138 : for (unsigned i = 0; i < nargs; i++)
2292 : : {
2293 : 38762 : if (pt_idx < pass_through_args.length ()
2294 : 46737 : && i == pass_through_args[pt_idx])
2295 : : {
2296 : 5339 : unsigned j = pass_through_pbr_indices[pt_idx];
2297 : 5339 : unsigned agg_arg_offset = pass_through_offsets[pt_idx];
2298 : 5339 : pt_idx++;
2299 : 5339 : always_copy_delta--;
2300 : 5339 : tree base = m_replacements[j].base;
2301 : :
2302 : : /* In order to be put into SSA form, we have to push all replacements
2303 : : pertaining to this parameter as parameters to the call statement.
2304 : : Edge redirection will need to use edge summary to weed out the
2305 : : unnecessary ones. */
2306 : 5339 : unsigned repl_list_len = m_replacements.length ();
2307 : 15074 : for (; j < repl_list_len; j++)
2308 : : {
2309 : 10425 : if (m_replacements[j].base != base)
2310 : : break;
2311 : 9735 : if (m_replacements[j].unit_offset < agg_arg_offset)
2312 : 1 : continue;
2313 : 9734 : pass_through_split_map pt_map;
2314 : 9734 : pt_map.base_index = i;
2315 : 9734 : pt_map.unit_offset
2316 : 9734 : = m_replacements[j].unit_offset - agg_arg_offset;
2317 : 9734 : pt_map.new_index = new_arg_idx;
2318 : 9734 : pass_through_map.safe_push (pt_map);
2319 : 9734 : vargs.safe_push (m_replacements[j].repl);
2320 : 9734 : new_arg_idx++;
2321 : 9734 : always_copy_delta++;
2322 : : }
2323 : 5339 : index_map.safe_push (-1);
2324 : : }
2325 : : else
2326 : : {
2327 : 33423 : tree t = gimple_call_arg (stmt, i);
2328 : 33423 : if (TREE_CODE (t) == SSA_NAME
2329 : 33423 : && m_dead_ssas.contains (t))
2330 : : {
2331 : 7052 : always_copy_delta--;
2332 : 7052 : index_map.safe_push (-1);
2333 : : }
2334 : : else
2335 : : {
2336 : 26371 : modify_expression (&t, true);
2337 : 26371 : vargs.safe_push (t);
2338 : 26371 : index_map.safe_push (new_arg_idx);
2339 : 26371 : new_arg_idx++;
2340 : : }
2341 : : }
2342 : : }
2343 : :
2344 : 11376 : gcall *new_stmt = gimple_build_call_vec (gimple_call_fn (stmt), vargs);
2345 : 11376 : if (gimple_has_location (stmt))
2346 : 9979 : gimple_set_location (new_stmt, gimple_location (stmt));
2347 : 11376 : gimple_call_set_chain (new_stmt, gimple_call_chain (stmt));
2348 : 11376 : gimple_call_copy_flags (new_stmt, stmt);
2349 : 11376 : if (tree lhs = gimple_call_lhs (stmt))
2350 : : {
2351 : 8900 : modify_expression (&lhs, false);
2352 : : /* Avoid adjusting SSA_NAME_DEF_STMT of a SSA lhs, SSA names
2353 : : have not yet been remapped. */
2354 : 8900 : *gimple_call_lhs_ptr (new_stmt) = lhs;
2355 : : }
2356 : 11376 : *stmt_p = new_stmt;
2357 : :
2358 : 11376 : if (orig_stmt)
2359 : 11376 : record_argument_state (m_id, orig_stmt, index_map, pass_through_map,
2360 : : always_copy_delta);
2361 : 11376 : return true;
2362 : 575861 : }
2363 : :
2364 : : /* If the statement STMT contains any expressions that need to replaced with a
2365 : : different one as noted by ADJUSTMENTS, do so. Handle any potential type
2366 : : incompatibilities. If any conversion sttements have to be pre-pended to
2367 : : STMT, they will be added to EXTRA_STMTS. Return true iff the statement was
2368 : : modified. */
2369 : :
2370 : : bool
2371 : 2930743 : ipa_param_body_adjustments::modify_gimple_stmt (gimple **stmt,
2372 : : gimple_seq *extra_stmts,
2373 : : gimple *orig_stmt)
2374 : : {
2375 : 2930743 : bool modified = false;
2376 : 2930743 : tree *t;
2377 : :
2378 : 2930743 : switch (gimple_code (*stmt))
2379 : : {
2380 : 129804 : case GIMPLE_RETURN:
2381 : 129804 : t = gimple_return_retval_ptr (as_a <greturn *> (*stmt));
2382 : 129804 : if (m_adjustments && m_adjustments->m_skip_return)
2383 : 31819 : *t = NULL_TREE;
2384 : 97985 : else if (*t != NULL_TREE)
2385 : 52625 : modified |= modify_expression (t, true);
2386 : : break;
2387 : :
2388 : 1738579 : case GIMPLE_ASSIGN:
2389 : 1738579 : modified |= modify_assignment (*stmt, extra_stmts);
2390 : 1738579 : break;
2391 : :
2392 : 564485 : case GIMPLE_CALL:
2393 : 564485 : modified |= modify_call_stmt ((gcall **) stmt, orig_stmt);
2394 : 564485 : break;
2395 : :
2396 : 1054 : case GIMPLE_ASM:
2397 : 1054 : {
2398 : 1054 : gasm *asm_stmt = as_a <gasm *> (*stmt);
2399 : 2559 : for (unsigned i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
2400 : : {
2401 : 1505 : t = &TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
2402 : 1505 : modified |= modify_expression (t, true);
2403 : : }
2404 : 2568 : for (unsigned i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
2405 : : {
2406 : 1514 : t = &TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
2407 : 1514 : modified |= modify_expression (t, false);
2408 : : }
2409 : : }
2410 : : break;
2411 : :
2412 : : default:
2413 : : break;
2414 : : }
2415 : 2930743 : return modified;
2416 : : }
2417 : :
2418 : :
2419 : : /* Traverse body of the current function and perform the requested adjustments
2420 : : on its statements. Return true iff the CFG has been changed. */
2421 : :
2422 : : bool
2423 : 0 : ipa_param_body_adjustments::modify_cfun_body ()
2424 : : {
2425 : 0 : bool cfg_changed = false;
2426 : 0 : basic_block bb;
2427 : :
2428 : 0 : FOR_EACH_BB_FN (bb, cfun)
2429 : : {
2430 : 0 : gimple_stmt_iterator gsi;
2431 : :
2432 : 0 : for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
2433 : : {
2434 : 0 : gphi *phi = as_a <gphi *> (gsi_stmt (gsi));
2435 : 0 : tree new_lhs, old_lhs = gimple_phi_result (phi);
2436 : 0 : new_lhs = replace_removed_params_ssa_names (old_lhs, phi);
2437 : 0 : if (new_lhs)
2438 : : {
2439 : 0 : gimple_phi_set_result (phi, new_lhs);
2440 : 0 : release_ssa_name (old_lhs);
2441 : : }
2442 : : }
2443 : :
2444 : 0 : gsi = gsi_start_bb (bb);
2445 : 0 : while (!gsi_end_p (gsi))
2446 : : {
2447 : 0 : gimple *stmt = gsi_stmt (gsi);
2448 : 0 : gimple *stmt_copy = stmt;
2449 : 0 : gimple_seq extra_stmts = NULL;
2450 : 0 : bool modified = modify_gimple_stmt (&stmt, &extra_stmts, NULL);
2451 : 0 : if (stmt != stmt_copy)
2452 : : {
2453 : 0 : gcc_checking_assert (modified);
2454 : 0 : gsi_replace (&gsi, stmt, false);
2455 : : }
2456 : 0 : if (!gimple_seq_empty_p (extra_stmts))
2457 : 0 : gsi_insert_seq_before (&gsi, extra_stmts, GSI_SAME_STMT);
2458 : :
2459 : 0 : def_operand_p defp;
2460 : 0 : ssa_op_iter iter;
2461 : 0 : FOR_EACH_SSA_DEF_OPERAND (defp, stmt, iter, SSA_OP_DEF)
2462 : : {
2463 : 0 : tree old_def = DEF_FROM_PTR (defp);
2464 : 0 : if (tree new_def = replace_removed_params_ssa_names (old_def,
2465 : : stmt))
2466 : : {
2467 : 0 : SET_DEF (defp, new_def);
2468 : 0 : release_ssa_name (old_def);
2469 : 0 : modified = true;
2470 : : }
2471 : : }
2472 : :
2473 : 0 : if (modified)
2474 : : {
2475 : 0 : update_stmt (stmt);
2476 : 0 : if (maybe_clean_eh_stmt (stmt)
2477 : 0 : && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
2478 : : cfg_changed = true;
2479 : : }
2480 : 0 : gsi_next (&gsi);
2481 : : }
2482 : : }
2483 : :
2484 : 0 : return cfg_changed;
2485 : : }
2486 : :
2487 : : /* Call gimple_debug_bind_reset_value on all debug statements describing
2488 : : gimple register parameters that are being removed or replaced. */
2489 : :
2490 : : void
2491 : 0 : ipa_param_body_adjustments::reset_debug_stmts ()
2492 : : {
2493 : 0 : int i, len;
2494 : 0 : gimple_stmt_iterator *gsip = NULL, gsi;
2495 : :
2496 : 0 : if (MAY_HAVE_DEBUG_STMTS && single_succ_p (ENTRY_BLOCK_PTR_FOR_FN (cfun)))
2497 : : {
2498 : 0 : gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
2499 : 0 : gsip = &gsi;
2500 : : }
2501 : 0 : len = m_reset_debug_decls.length ();
2502 : 0 : for (i = 0; i < len; i++)
2503 : : {
2504 : 0 : imm_use_iterator ui;
2505 : 0 : gimple *stmt;
2506 : 0 : gdebug *def_temp;
2507 : 0 : tree name, vexpr, copy = NULL_TREE;
2508 : 0 : use_operand_p use_p;
2509 : 0 : tree decl = m_reset_debug_decls[i];
2510 : :
2511 : 0 : gcc_checking_assert (is_gimple_reg (decl));
2512 : 0 : name = ssa_default_def (cfun, decl);
2513 : 0 : vexpr = NULL;
2514 : 0 : if (name)
2515 : 0 : FOR_EACH_IMM_USE_STMT (stmt, ui, name)
2516 : : {
2517 : 0 : if (gimple_clobber_p (stmt))
2518 : : {
2519 : 0 : gimple_stmt_iterator cgsi = gsi_for_stmt (stmt);
2520 : 0 : unlink_stmt_vdef (stmt);
2521 : 0 : gsi_remove (&cgsi, true);
2522 : 0 : release_defs (stmt);
2523 : 0 : continue;
2524 : 0 : }
2525 : : /* All other users must have been removed by function body
2526 : : modification. */
2527 : 0 : gcc_assert (is_gimple_debug (stmt));
2528 : 0 : if (vexpr == NULL && gsip != NULL)
2529 : : {
2530 : 0 : vexpr = build_debug_expr_decl (TREE_TYPE (name));
2531 : : /* FIXME: Is setting the mode really necessary? */
2532 : 0 : SET_DECL_MODE (vexpr, DECL_MODE (decl));
2533 : 0 : def_temp = gimple_build_debug_source_bind (vexpr, decl, NULL);
2534 : 0 : gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
2535 : : }
2536 : 0 : if (vexpr)
2537 : : {
2538 : 0 : FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
2539 : 0 : SET_USE (use_p, vexpr);
2540 : : }
2541 : : else
2542 : 0 : gimple_debug_bind_reset_value (stmt);
2543 : 0 : update_stmt (stmt);
2544 : 0 : }
2545 : : /* Create a VAR_DECL for debug info purposes. */
2546 : 0 : if (!DECL_IGNORED_P (decl))
2547 : : {
2548 : 0 : copy = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
2549 : 0 : VAR_DECL, DECL_NAME (decl),
2550 : 0 : TREE_TYPE (decl));
2551 : 0 : if (DECL_PT_UID_SET_P (decl))
2552 : 0 : SET_DECL_PT_UID (copy, DECL_PT_UID (decl));
2553 : 0 : TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
2554 : 0 : TREE_READONLY (copy) = TREE_READONLY (decl);
2555 : 0 : TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
2556 : 0 : DECL_NOT_GIMPLE_REG_P (copy) = DECL_NOT_GIMPLE_REG_P (decl);
2557 : 0 : DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (decl);
2558 : 0 : DECL_IGNORED_P (copy) = DECL_IGNORED_P (decl);
2559 : 0 : DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (decl);
2560 : 0 : DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
2561 : 0 : SET_DECL_RTL (copy, 0);
2562 : 0 : TREE_USED (copy) = 1;
2563 : 0 : DECL_CONTEXT (copy) = current_function_decl;
2564 : 0 : add_local_decl (cfun, copy);
2565 : 0 : DECL_CHAIN (copy)
2566 : 0 : = BLOCK_VARS (DECL_INITIAL (current_function_decl));
2567 : 0 : BLOCK_VARS (DECL_INITIAL (current_function_decl)) = copy;
2568 : : }
2569 : 0 : if (gsip != NULL && copy && target_for_debug_bind (decl))
2570 : : {
2571 : 0 : gcc_assert (TREE_CODE (decl) == PARM_DECL);
2572 : 0 : if (vexpr)
2573 : 0 : def_temp = gimple_build_debug_bind (copy, vexpr, NULL);
2574 : : else
2575 : 0 : def_temp = gimple_build_debug_source_bind (copy, decl,
2576 : : NULL);
2577 : 0 : gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
2578 : : }
2579 : : }
2580 : 0 : }
2581 : :
2582 : : /* Perform all necessary body changes to change signature, body and debug info
2583 : : of fun according to adjustments passed at construction. Return true if CFG
2584 : : was changed in any way. The main entry point for modification of standalone
2585 : : functions that is not part of IPA clone materialization. */
2586 : :
2587 : : bool
2588 : 0 : ipa_param_body_adjustments::perform_cfun_body_modifications ()
2589 : : {
2590 : 0 : bool cfg_changed;
2591 : 0 : modify_formal_parameters ();
2592 : 0 : cfg_changed = modify_cfun_body ();
2593 : 0 : reset_debug_stmts ();
2594 : :
2595 : 0 : return cfg_changed;
2596 : : }
2597 : :
2598 : :
2599 : : /* If there are any initialization statements that need to be emitted into
2600 : : the basic block BB right at ther start of the new function, do so. */
2601 : : void
2602 : 143027 : ipa_param_body_adjustments::append_init_stmts (basic_block bb)
2603 : : {
2604 : 143027 : gimple_stmt_iterator si = gsi_last_bb (bb);
2605 : 144287 : while (!m_split_agg_csts_inits.is_empty ())
2606 : 1260 : gsi_insert_after (&si, m_split_agg_csts_inits.pop (), GSI_NEW_STMT);
2607 : 143027 : }
2608 : :
2609 : : /* Deallocate summaries which otherwise stay alive until the end of
2610 : : compilation. */
2611 : :
2612 : : void
2613 : 249859 : ipa_edge_modifications_finalize ()
2614 : : {
2615 : 249859 : if (!ipa_edge_modifications)
2616 : : return;
2617 : 2312 : delete ipa_edge_modifications;
2618 : 2312 : ipa_edge_modifications = NULL;
2619 : : }
2620 : :
2621 : : /* Helper used to sort a vector of SSA_NAMES. */
2622 : :
2623 : : static int
2624 : 20902 : compare_ssa_versions (const void *va, const void *vb)
2625 : : {
2626 : 20902 : const_tree const a = *(const_tree const*)va;
2627 : 20902 : const_tree const b = *(const_tree const*)vb;
2628 : :
2629 : 20902 : if (SSA_NAME_VERSION (a) < SSA_NAME_VERSION (b))
2630 : : return -1;
2631 : 8920 : if (SSA_NAME_VERSION (a) > SSA_NAME_VERSION (b))
2632 : 8920 : return 1;
2633 : : return 0;
2634 : : }
2635 : :
2636 : : /* Call release_ssa_name on all elements in KILLED_SSAS in a defined order. */
2637 : :
2638 : : void
2639 : 1962974 : ipa_release_ssas_in_hash (hash_set <tree> *killed_ssas)
2640 : : {
2641 : 1962974 : auto_vec<tree, 16> ssas_to_release;
2642 : 1977599 : for (tree sn : *killed_ssas)
2643 : 14625 : ssas_to_release.safe_push (sn);
2644 : 1962974 : ssas_to_release.qsort (compare_ssa_versions);
2645 : 5903547 : for (tree sn : ssas_to_release)
2646 : 14625 : release_ssa_name (sn);
2647 : 1962974 : }
|