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