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

source code of gcc/ipa-param-manipulation.cc