Branch data Line data Source code
1 : : /* Manipulation of formal and actual parameters of functions and function
2 : : calls.
3 : : Copyright (C) 2017-2025 Free Software Foundation, Inc.
4 : :
5 : : This file is part of GCC.
6 : :
7 : : GCC is free software; you can redistribute it and/or modify it under
8 : : the terms of the GNU General Public License as published by the Free
9 : : Software Foundation; either version 3, or (at your option) any later
10 : : version.
11 : :
12 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 : : for more details.
16 : :
17 : : You should have received a copy of the GNU General Public License
18 : : along with GCC; see the file COPYING3. If not see
19 : : <http://www.gnu.org/licenses/>. */
20 : :
21 : : #define INCLUDE_ALGORITHM
22 : : #include "config.h"
23 : : #include "system.h"
24 : : #include "coretypes.h"
25 : : #include "backend.h"
26 : : #include "tree.h"
27 : : #include "gimple.h"
28 : : #include "ssa.h"
29 : : #include "cgraph.h"
30 : : #include "fold-const.h"
31 : : #include "tree-eh.h"
32 : : #include "stor-layout.h"
33 : : #include "gimplify.h"
34 : : #include "gimple-iterator.h"
35 : : #include "gimplify-me.h"
36 : : #include "tree-cfg.h"
37 : : #include "tree-dfa.h"
38 : : #include "ipa-param-manipulation.h"
39 : : #include "print-tree.h"
40 : : #include "gimple-pretty-print.h"
41 : : #include "builtins.h"
42 : : #include "tree-ssa.h"
43 : : #include "tree-inline.h"
44 : : #include "alloc-pool.h"
45 : : #include "symbol-summary.h"
46 : : #include "symtab-clones.h"
47 : : #include "tree-phinodes.h"
48 : : #include "cfgexpand.h"
49 : : #include "attribs.h"
50 : : #include "sreal.h"
51 : : #include "ipa-cp.h"
52 : : #include "ipa-prop.h"
53 : : #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 : 54552 : class ipa_edge_modification_info
91 : : {
92 : : public:
93 : 54552 : ipa_edge_modification_info ()
94 : 54552 : {}
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 : 2312 : ipa_edge_modification_sum (symbol_table *table)
115 : 4624 : : call_summary<ipa_edge_modification_info *> (table)
116 : : {
117 : : }
118 : :
119 : : /* Hook that is called by summary when an edge is duplicated. */
120 : :
121 : 25273 : 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 : 25273 : new_info->index_map.safe_splice (old_info->index_map);
127 : 25273 : new_info->pass_through_map.safe_splice (old_info->pass_through_map);
128 : 25273 : new_info->always_copy_delta = old_info->always_copy_delta;
129 : 25273 : }
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 : 330233 : ipa_verify_edge_has_no_modifications (cgraph_edge *cs)
142 : : {
143 : 330233 : gcc_assert (!ipa_edge_modifications || !ipa_edge_modifications->get (cs));
144 : 330233 : }
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 : 179188 : push_function_arg_decls (vec<tree> *args, tree fndecl)
152 : : {
153 : 179188 : int count;
154 : 179188 : 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 explicitely loaded its body. */
159 : 179189 : gcc_assert (!flag_wpa
160 : : || DECL_ARGUMENTS (fndecl)
161 : : || gimple_has_body_p (fndecl));
162 : 179188 : count = 0;
163 : 644267 : for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm))
164 : 465079 : count++;
165 : :
166 : 179188 : args->reserve_exact (count);
167 : 644267 : for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm))
168 : 465079 : args->quick_push (parm);
169 : 179188 : }
170 : :
171 : : /* Fill an empty vector TYPES with trees representing formal parameters of
172 : : function type FNTYPE. */
173 : :
174 : : void
175 : 414471 : push_function_arg_types (vec<tree> *types, tree fntype)
176 : : {
177 : 414471 : int count = 0;
178 : 414471 : tree t;
179 : :
180 : 1914570 : for (t = TYPE_ARG_TYPES (fntype); t; t = TREE_CHAIN (t))
181 : 1500099 : count++;
182 : :
183 : 414471 : types->reserve_exact (count);
184 : 1914570 : for (t = TYPE_ARG_TYPES (fntype); t; t = TREE_CHAIN (t))
185 : 1500099 : types->quick_push (TREE_VALUE (t));
186 : 414471 : }
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 : 410004 : 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 : 410004 : unsigned adj_len = vec_safe_length (adj_params);
253 : 410004 : new_types->reserve_exact (adj_len);
254 : 1278511 : for (unsigned i = 0; i < adj_len ; i++)
255 : : {
256 : 868507 : ipa_adjusted_param *apm = &(*adj_params)[i];
257 : 868507 : if (apm->op == IPA_PARAM_OP_COPY)
258 : : {
259 : 1248156 : unsigned index
260 : 624078 : = 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 : 624078 : if (index >= otypes->length ())
265 : 0 : continue;
266 : 624078 : new_types->quick_push ((*otypes)[index]);
267 : : }
268 : 244429 : else if (apm->op == IPA_PARAM_OP_NEW
269 : 244429 : || apm->op == IPA_PARAM_OP_SPLIT)
270 : : {
271 : 244429 : tree ntype = apm->type;
272 : 244429 : if (is_gimple_reg_type (ntype)
273 : 244429 : && TYPE_MODE (ntype) != BLKmode)
274 : : {
275 : 241692 : unsigned malign = GET_MODE_ALIGNMENT (TYPE_MODE (ntype));
276 : 241692 : if (TYPE_ALIGN (ntype) != malign)
277 : 1896 : ntype = build_aligned_type (ntype, malign);
278 : : }
279 : 244429 : new_types->quick_push (ntype);
280 : : }
281 : : else
282 : 0 : gcc_unreachable ();
283 : : }
284 : 410004 : }
285 : :
286 : : /* Return false if given attribute should prevent type adjustments. */
287 : :
288 : : bool
289 : 382004 : ipa_param_adjustments::type_attribute_allowed_p (tree name)
290 : : {
291 : 617200 : if ((is_attribute_p ("fn spec", name) && flag_ipa_modref)
292 : 172143 : || is_attribute_p ("access", name)
293 : 158580 : || is_attribute_p ("returns_nonnull", name)
294 : 157418 : || is_attribute_p ("assume_aligned", name)
295 : 157418 : || is_attribute_p ("nocf_check", name)
296 : 539397 : || 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 : 4562 : drop_type_attribute_if_params_changed_p (tree name)
305 : : {
306 : 4562 : if (is_attribute_p ("fn spec", name)
307 : 4562 : || 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 : 24159 : 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 : 260375 : build_adjusted_function_type (tree orig_type, vec<tree> *new_param_types,
330 : : bool method2func, bool skip_return,
331 : : bool args_modified)
332 : : {
333 : 260375 : tree new_arg_types = NULL;
334 : 260375 : if (TYPE_ARG_TYPES (orig_type))
335 : : {
336 : 260249 : gcc_checking_assert (new_param_types);
337 : 260249 : bool last_parm_void = (TREE_VALUE (tree_last (TYPE_ARG_TYPES (orig_type)))
338 : 260249 : == void_type_node);
339 : 260249 : unsigned len = new_param_types->length ();
340 : 817727 : for (unsigned i = 0; i < len; i++)
341 : 557478 : new_arg_types = tree_cons (NULL_TREE, (*new_param_types)[i],
342 : : new_arg_types);
343 : :
344 : 260249 : tree new_reversed = nreverse (new_arg_types);
345 : 260249 : if (last_parm_void)
346 : : {
347 : 260240 : if (new_reversed)
348 : 235611 : TREE_CHAIN (new_arg_types) = void_list_node;
349 : : else
350 : 24629 : 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 : 260375 : tree new_type = NULL;
360 : 260375 : if (method2func)
361 : : {
362 : 101344 : tree ret_type;
363 : 101344 : if (skip_return)
364 : 16098 : ret_type = void_type_node;
365 : : else
366 : 85246 : ret_type = TREE_TYPE (orig_type);
367 : :
368 : 101344 : new_type
369 : 101344 : = build_distinct_type_copy (build_function_type (ret_type,
370 : : new_arg_types));
371 : 101344 : TYPE_CONTEXT (new_type) = TYPE_CONTEXT (orig_type);
372 : : }
373 : : else
374 : : {
375 : 159031 : new_type = build_distinct_type_copy (orig_type);
376 : 159031 : TYPE_ARG_TYPES (new_type) = new_arg_types;
377 : 159031 : if (skip_return)
378 : 58252 : TREE_TYPE (new_type) = void_type_node;
379 : : }
380 : 260375 : if (args_modified && TYPE_ATTRIBUTES (new_type))
381 : : {
382 : 4562 : tree t = TYPE_ATTRIBUTES (new_type);
383 : 4562 : tree *last = &TYPE_ATTRIBUTES (new_type);
384 : 4562 : TYPE_ATTRIBUTES (new_type) = NULL;
385 : 9124 : for (;t; t = TREE_CHAIN (t))
386 : 4562 : if (!drop_type_attribute_if_params_changed_p
387 : 4562 : (get_attribute_name (t)))
388 : : {
389 : 12 : *last = copy_node (t);
390 : 12 : TREE_CHAIN (*last) = NULL;
391 : 12 : last = &TREE_CHAIN (*last);
392 : : }
393 : : }
394 : :
395 : 260375 : 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 : 42041 : ipa_param_adjustments::get_max_base_index ()
403 : : {
404 : 42041 : unsigned adj_len = vec_safe_length (m_adj_params);
405 : 42041 : int max_index = -1;
406 : 99801 : for (unsigned i = 0; i < adj_len ; i++)
407 : : {
408 : 57760 : ipa_adjusted_param *apm = &(*m_adj_params)[i];
409 : 57760 : if (apm->op == IPA_PARAM_OP_COPY
410 : 52445 : && max_index < apm->base_index)
411 : 57760 : max_index = apm->base_index;
412 : : }
413 : 42041 : 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 : 27236 : ipa_param_adjustments::get_surviving_params (vec<bool> *surviving_params)
425 : : {
426 : 27236 : unsigned adj_len = vec_safe_length (m_adj_params);
427 : 27236 : int max_index = get_max_base_index ();
428 : :
429 : 27236 : if (max_index < 0)
430 : : return;
431 : 15998 : surviving_params->reserve_exact (max_index + 1);
432 : 15998 : surviving_params->quick_grow_cleared (max_index + 1);
433 : 46404 : for (unsigned i = 0; i < adj_len ; i++)
434 : : {
435 : 30406 : ipa_adjusted_param *apm = &(*m_adj_params)[i];
436 : 30406 : if (apm->op == IPA_PARAM_OP_COPY)
437 : 30406 : (*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 : 14805 : ipa_param_adjustments::get_updated_indices (vec<int> *new_indices)
448 : : {
449 : 14805 : unsigned adj_len = vec_safe_length (m_adj_params);
450 : 14805 : int max_index = get_max_base_index ();
451 : :
452 : 14805 : if (max_index < 0)
453 : : return;
454 : 11192 : unsigned res_len = max_index + 1;
455 : 11192 : new_indices->reserve_exact (res_len);
456 : 39954 : for (unsigned i = 0; i < res_len ; i++)
457 : 28762 : new_indices->quick_push (-1);
458 : 36571 : for (unsigned i = 0; i < adj_len ; i++)
459 : : {
460 : 25379 : ipa_adjusted_param *apm = &(*m_adj_params)[i];
461 : 25379 : if (apm->op == IPA_PARAM_OP_COPY)
462 : 22039 : (*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 : 614275 : ipa_param_adjustments::get_original_index (int newidx)
471 : : {
472 : 614275 : const ipa_adjusted_param *adj = &(*m_adj_params)[newidx];
473 : 614275 : if (adj->op != IPA_PARAM_OP_COPY)
474 : : return -1;
475 : 477563 : 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 : 265140 : ipa_param_adjustments::first_param_intact_p ()
483 : : {
484 : 265140 : return (!vec_safe_is_empty (m_adj_params)
485 : 246305 : && (*m_adj_params)[0].op == IPA_PARAM_OP_COPY
486 : 172393 : && (*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 : 406447 : ipa_param_adjustments::method2func_p (tree orig_type)
494 : : {
495 : 406447 : 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 : 255899 : ipa_param_adjustments::build_new_function_type (
507 : : tree old_type, bool type_original_p, bool *args_modified /* = NULL */)
508 : : {
509 : 255899 : auto_vec<tree,16> new_param_types, *new_param_types_p;
510 : 255899 : if (prototype_p (old_type))
511 : : {
512 : 255837 : auto_vec<tree, 16> otypes;
513 : 255837 : push_function_arg_types (&otypes, old_type);
514 : 255837 : fill_vector_of_new_param_types (&new_param_types, &otypes, m_adj_params,
515 : 255837 : !type_original_p);
516 : 255837 : new_param_types_p = &new_param_types;
517 : 255837 : }
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 : 255899 : bool modified = false;
524 : 255899 : size_t index = 0;
525 : 255899 : if (m_adj_params)
526 : 231577 : for (tree t = TYPE_ARG_TYPES (old_type);
527 : 686928 : t && (int)index < m_always_copy_start && !modified;
528 : 455351 : t = TREE_CHAIN (t), index++)
529 : 455351 : if (index >= m_adj_params->length ()
530 : 455351 : || get_original_index (index) != (int)index)
531 : : modified = true;
532 : :
533 : 255899 : if (args_modified)
534 : 150484 : *args_modified = modified;
535 : :
536 : 255899 : return build_adjusted_function_type (old_type, new_param_types_p,
537 : 255899 : method2func_p (old_type), m_skip_return,
538 : 255899 : modified);
539 : 255899 : }
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 : 150548 : ipa_param_adjustments::adjust_decl (tree orig_decl)
550 : : {
551 : 150548 : tree new_decl = copy_node (orig_decl);
552 : 150548 : tree orig_type = TREE_TYPE (orig_decl);
553 : 150548 : bool args_modified = false;
554 : 150548 : if (prototype_p (orig_type)
555 : 150548 : || (m_skip_return && !VOID_TYPE_P (TREE_TYPE (orig_type))))
556 : : {
557 : 150484 : tree new_type = build_new_function_type (orig_type, false, &args_modified);
558 : 150484 : TREE_TYPE (new_decl) = new_type;
559 : : }
560 : 150548 : if (method2func_p (orig_type))
561 : 48838 : DECL_VINDEX (new_decl) = NULL_TREE;
562 : :
563 : : /* When signature changes, we need to clear builtin info. */
564 : 150548 : if (fndecl_built_in_p (new_decl))
565 : 97 : set_decl_built_in_function (new_decl, NOT_BUILT_IN, 0);
566 : :
567 : 150548 : DECL_VIRTUAL_P (new_decl) = 0;
568 : 150548 : DECL_LANG_SPECIFIC (new_decl) = NULL;
569 : :
570 : : /* Drop MALLOC attribute for a void function. */
571 : 150548 : if (m_skip_return)
572 : 46850 : DECL_IS_MALLOC (new_decl) = 0;
573 : :
574 : : /* If the decl's arguments changed, we might need to drop some attributes. */
575 : 150548 : if (args_modified && DECL_ATTRIBUTES (new_decl))
576 : : {
577 : 18274 : tree t = DECL_ATTRIBUTES (new_decl);
578 : 18274 : tree *last = &DECL_ATTRIBUTES (new_decl);
579 : 18274 : DECL_ATTRIBUTES (new_decl) = NULL;
580 : 42433 : for (; t; t = TREE_CHAIN (t))
581 : 24159 : if (!drop_decl_attribute_if_params_changed_p (get_attribute_name (t)))
582 : : {
583 : 24159 : *last = copy_node (t);
584 : 24159 : TREE_CHAIN (*last) = NULL;
585 : 24159 : last = &TREE_CHAIN (*last);
586 : : }
587 : : }
588 : 150548 : 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 : 1212925 : isra_get_ref_base_and_offset (tree expr, tree *base_p, unsigned *unit_offset_p)
597 : : {
598 : 1212925 : HOST_WIDE_INT offset, size;
599 : 1212925 : bool reverse;
600 : 1212925 : tree base
601 : 1212925 : = get_ref_base_and_extent_hwi (expr, &offset, &size, &reverse);
602 : 1212925 : if (!base || size < 0)
603 : : return false;
604 : :
605 : 1207560 : if ((offset % BITS_PER_UNIT) != 0)
606 : : return false;
607 : :
608 : 1206298 : if (TREE_CODE (base) == MEM_REF)
609 : : {
610 : 181691 : poly_int64 plmoff = mem_ref_offset (base).force_shwi ();
611 : 181691 : HOST_WIDE_INT moff;
612 : 181691 : bool is_cst = plmoff.is_constant (&moff);
613 : 181691 : if (!is_cst)
614 : : return false;
615 : 181691 : offset += moff * BITS_PER_UNIT;
616 : 181691 : base = TREE_OPERAND (base, 0);
617 : : }
618 : :
619 : 1206298 : if (offset < 0 || (offset / BITS_PER_UNIT) > UINT_MAX)
620 : : return false;
621 : :
622 : 1206109 : *base_p = base;
623 : 1206109 : *unit_offset_p = offset / BITS_PER_UNIT;
624 : 1206109 : 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 : 9796 : purge_all_uses (tree name, hash_set <tree> *killed_ssas)
635 : : {
636 : 9796 : imm_use_iterator imm_iter;
637 : 9796 : gimple *stmt;
638 : 9796 : auto_vec <tree, 4> worklist;
639 : :
640 : 9796 : worklist.safe_push (name);
641 : 41943 : while (!worklist.is_empty ())
642 : : {
643 : 12555 : tree cur_name = worklist.pop ();
644 : 27927 : FOR_EACH_IMM_USE_STMT (stmt, imm_iter, cur_name)
645 : : {
646 : 2817 : if (gimple_debug_bind_p (stmt))
647 : : {
648 : : /* When runing within tree-inline, we will never end up here but
649 : : adding the SSAs to killed_ssas will do the trick in this case
650 : : and the respective debug statements will get reset. */
651 : 58 : gimple_debug_bind_reset_value (stmt);
652 : 58 : update_stmt (stmt);
653 : 58 : continue;
654 : : }
655 : :
656 : 2759 : tree lhs = NULL_TREE;
657 : 2759 : if (is_gimple_assign (stmt))
658 : 739 : lhs = gimple_assign_lhs (stmt);
659 : 2020 : else if (gimple_code (stmt) == GIMPLE_PHI)
660 : 2020 : lhs = gimple_phi_result (stmt);
661 : 3498 : gcc_assert (lhs
662 : : && (TREE_CODE (lhs) == SSA_NAME)
663 : : && !gimple_vdef (stmt));
664 : 2759 : if (!killed_ssas->add (lhs))
665 : : {
666 : 2759 : worklist.safe_push (lhs);
667 : 2759 : gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
668 : 2759 : gsi_remove (&gsi, true);
669 : : }
670 : 12555 : }
671 : : }
672 : 9796 : }
673 : :
674 : : /* Modify actual arguments of a function call in statement currently belonging
675 : : to CS, and make it call CS->callee->decl. Return the new statement that
676 : : replaced the old one. When invoked, cfun and current_function_decl have to
677 : : be set to the caller. When called from within tree-inline, KILLED_SSAs has
678 : : to contain the pointer to killed_new_ssa_names within the copy_body_data
679 : : structure and SSAs discovered to be useless (if LHS is removed) will be
680 : : added to it, otherwise it needs to be NULL. */
681 : :
682 : : gcall *
683 : 451609 : ipa_param_adjustments::modify_call (cgraph_edge *cs,
684 : : bool update_references,
685 : : hash_set <tree> *killed_ssas)
686 : : {
687 : 451609 : gcall *stmt = cs->call_stmt;
688 : 451609 : tree callee_decl = cs->callee->decl;
689 : :
690 : 451609 : ipa_edge_modification_info *mod_info
691 : 451609 : = ipa_edge_modifications ? ipa_edge_modifications->get (cs) : NULL;
692 : 263220 : if (mod_info && symtab->dump_file)
693 : : {
694 : 0 : fprintf (symtab->dump_file, "Information about pre-exiting "
695 : : "modifications.\n Index map:");
696 : 0 : unsigned idx_len = mod_info->index_map.length ();
697 : 0 : for (unsigned i = 0; i < idx_len; i++)
698 : 0 : fprintf (symtab->dump_file, " %i", mod_info->index_map[i]);
699 : 0 : fprintf (symtab->dump_file, "\n Pass-through split map: ");
700 : 0 : unsigned ptm_len = mod_info->pass_through_map.length ();
701 : 0 : for (unsigned i = 0; i < ptm_len; i++)
702 : 0 : fprintf (symtab->dump_file,
703 : : " (base_index: %u, offset: %u, new_index: %i)",
704 : 0 : mod_info->pass_through_map[i].base_index,
705 : 0 : mod_info->pass_through_map[i].unit_offset,
706 : 0 : mod_info->pass_through_map[i].new_index);
707 : 0 : fprintf (symtab->dump_file, "\n Always-copy delta: %i\n",
708 : : mod_info->always_copy_delta);
709 : : }
710 : :
711 : 451609 : unsigned len = vec_safe_length (m_adj_params);
712 : 451609 : auto_vec<tree, 16> vargs (len);
713 : 451609 : unsigned old_nargs = gimple_call_num_args (stmt);
714 : 451609 : unsigned orig_nargs = mod_info ? mod_info->index_map.length () : old_nargs;
715 : 451609 : auto_vec<bool, 16> kept (old_nargs);
716 : 451609 : kept.quick_grow_cleared (old_nargs);
717 : :
718 : 451609 : cgraph_node *current_node = cgraph_node::get (current_function_decl);
719 : 451609 : if (update_references)
720 : 0 : current_node->remove_stmt_references (stmt);
721 : :
722 : 451609 : gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
723 : 451609 : gimple_stmt_iterator prev_gsi = gsi;
724 : 451609 : gsi_prev (&prev_gsi);
725 : 1475403 : for (unsigned i = 0; i < len; i++)
726 : : {
727 : 1023794 : ipa_adjusted_param *apm = &(*m_adj_params)[i];
728 : 1023794 : if (apm->op == IPA_PARAM_OP_COPY)
729 : : {
730 : 697062 : int index = apm->base_index;
731 : 697062 : if ((unsigned) index >= orig_nargs)
732 : : /* Can happen if the original call has argument mismatch,
733 : : ignore. */
734 : 0 : continue;
735 : 697062 : if (mod_info)
736 : : {
737 : 39315 : index = mod_info->index_map[apm->base_index];
738 : 39315 : gcc_assert (index >= 0);
739 : : }
740 : :
741 : 697062 : tree arg = gimple_call_arg (stmt, index);
742 : :
743 : 697062 : vargs.quick_push (arg);
744 : 697062 : kept[index] = true;
745 : 697062 : continue;
746 : 697062 : }
747 : :
748 : : /* At the moment the only user of IPA_PARAM_OP_NEW modifies calls itself.
749 : : If we ever want to support it during WPA IPA stage, we'll need a
750 : : mechanism to call into the IPA passes that introduced them. Currently
751 : : we simply mandate that IPA infrastructure understands all argument
752 : : modifications. Remember, edge redirection/modification is done only
753 : : once, not in steps for each pass modifying the callee like clone
754 : : materialization. */
755 : 326732 : gcc_assert (apm->op == IPA_PARAM_OP_SPLIT);
756 : :
757 : : /* We have to handle pass-through changes differently using the map
758 : : clone materialziation might have left behind. */
759 : 326732 : tree repl = NULL_TREE;
760 : 326732 : unsigned ptm_len = mod_info ? mod_info->pass_through_map.length () : 0;
761 : 349098 : for (unsigned j = 0; j < ptm_len; j++)
762 : 40382 : if (mod_info->pass_through_map[j].base_index == apm->base_index
763 : 40382 : && mod_info->pass_through_map[j].unit_offset == apm->unit_offset)
764 : : {
765 : 18016 : int repl_idx = mod_info->pass_through_map[j].new_index;
766 : 18016 : gcc_assert (repl_idx >= 0);
767 : 18016 : repl = gimple_call_arg (stmt, repl_idx);
768 : 18016 : break;
769 : : }
770 : 326732 : if (repl)
771 : : {
772 : 18016 : if (!useless_type_conversion_p(apm->type, repl->typed.type))
773 : : {
774 : 0 : repl = force_value_to_type (apm->type, repl);
775 : 0 : repl = force_gimple_operand_gsi (&gsi, repl,
776 : : true, NULL, true, GSI_SAME_STMT);
777 : : }
778 : 18016 : vargs.quick_push (repl);
779 : 18016 : continue;
780 : : }
781 : :
782 : 308716 : int index = apm->base_index;
783 : 308716 : if ((unsigned) index >= orig_nargs)
784 : : /* Can happen if the original call has argument mismatch, ignore. */
785 : 1 : continue;
786 : 308715 : if (mod_info)
787 : : {
788 : 4601 : index = mod_info->index_map[apm->base_index];
789 : 4601 : gcc_assert (index >= 0);
790 : : }
791 : 308715 : tree base = gimple_call_arg (stmt, index);
792 : :
793 : : /* We create a new parameter out of the value of the old one, we can
794 : : do the following kind of transformations:
795 : :
796 : : - A scalar passed by reference, potentially as a part of a larger
797 : : aggregate, is converted to a scalar passed by value.
798 : :
799 : : - A part of an aggregate is passed instead of the whole aggregate. */
800 : :
801 : 308715 : location_t loc = gimple_location (stmt);
802 : 308715 : tree off;
803 : 308715 : bool deref_base = false;
804 : 308715 : unsigned int deref_align = 0;
805 : 308715 : if (TREE_CODE (base) != ADDR_EXPR
806 : 308715 : && is_gimple_reg_type (TREE_TYPE (base)))
807 : : {
808 : : /* Detect type mismatches in calls in invalid programs and make a
809 : : poor attempt to gracefully convert them so that we don't ICE. */
810 : 86874 : if (!POINTER_TYPE_P (TREE_TYPE (base)))
811 : 11 : base = force_value_to_type (ptr_type_node, base);
812 : :
813 : 86874 : off = build_int_cst (apm->alias_ptr_type, apm->unit_offset);
814 : : }
815 : : else
816 : : {
817 : 221841 : bool addrof;
818 : 221841 : if (TREE_CODE (base) == ADDR_EXPR)
819 : : {
820 : 184334 : base = TREE_OPERAND (base, 0);
821 : 184334 : addrof = true;
822 : : }
823 : : else
824 : : addrof = false;
825 : :
826 : 221841 : tree prev_base = base;
827 : 221841 : poly_int64 base_offset;
828 : 221841 : base = get_addr_base_and_unit_offset (base, &base_offset);
829 : :
830 : : /* Aggregate arguments can have non-invariant addresses. */
831 : 221841 : if (!base)
832 : : {
833 : 0 : base = build_fold_addr_expr (prev_base);
834 : 0 : off = build_int_cst (apm->alias_ptr_type, apm->unit_offset);
835 : : }
836 : 221841 : else if (TREE_CODE (base) == MEM_REF)
837 : : {
838 : 5140 : if (!addrof)
839 : : {
840 : 5140 : deref_base = true;
841 : 5140 : deref_align = TYPE_ALIGN (TREE_TYPE (base));
842 : : }
843 : 10280 : off = build_int_cst (apm->alias_ptr_type,
844 : 5140 : base_offset + apm->unit_offset);
845 : 5140 : off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1),
846 : : off);
847 : 5140 : base = TREE_OPERAND (base, 0);
848 : : }
849 : : else
850 : : {
851 : 433402 : off = build_int_cst (apm->alias_ptr_type,
852 : 216701 : base_offset + apm->unit_offset);
853 : 216701 : base = build_fold_addr_expr (base);
854 : : }
855 : : }
856 : :
857 : 308715 : tree type = apm->type;
858 : 308715 : unsigned int align;
859 : 308715 : unsigned HOST_WIDE_INT misalign;
860 : :
861 : 308715 : if (deref_base)
862 : : {
863 : 5140 : align = deref_align;
864 : 5140 : misalign = 0;
865 : : }
866 : : else
867 : : {
868 : 303575 : get_pointer_alignment_1 (base, &align, &misalign);
869 : : /* All users must make sure that we can be optimistic when it
870 : : comes to alignment in this case (by inspecting the final users
871 : : of these new parameters). */
872 : 303575 : if (TYPE_ALIGN (type) > align)
873 : 85458 : align = TYPE_ALIGN (type);
874 : : }
875 : 308715 : misalign
876 : 308715 : += (offset_int::from (wi::to_wide (off), SIGNED).to_short_addr ()
877 : 308715 : * BITS_PER_UNIT);
878 : 308715 : misalign = misalign & (align - 1);
879 : 308715 : if (misalign != 0)
880 : 3102 : align = least_bit_hwi (misalign);
881 : 308715 : if (align < TYPE_ALIGN (type))
882 : 0 : type = build_aligned_type (type, align);
883 : 308715 : base = force_gimple_operand_gsi (&gsi, base,
884 : : true, NULL, true, GSI_SAME_STMT);
885 : 308715 : tree expr = fold_build2_loc (loc, MEM_REF, type, base, off);
886 : 308715 : REF_REVERSE_STORAGE_ORDER (expr) = apm->reverse;
887 : : /* If expr is not a valid gimple call argument emit
888 : : a load into a temporary. */
889 : 308715 : if (is_gimple_reg_type (TREE_TYPE (expr)))
890 : : {
891 : 306020 : gimple *tem = gimple_build_assign (NULL_TREE, expr);
892 : 306020 : if (gimple_in_ssa_p (cfun))
893 : : {
894 : 612040 : gimple_set_vuse (tem, gimple_vuse (stmt));
895 : 306020 : expr = make_ssa_name (TREE_TYPE (expr), tem);
896 : : }
897 : : else
898 : 0 : expr = create_tmp_reg (TREE_TYPE (expr));
899 : 306020 : gimple_assign_set_lhs (tem, expr);
900 : 306020 : gsi_insert_before (&gsi, tem, GSI_SAME_STMT);
901 : : }
902 : 308715 : vargs.quick_push (expr);
903 : : }
904 : :
905 : 451609 : if (m_always_copy_start >= 0)
906 : : {
907 : 451609 : int always_copy_start = m_always_copy_start;
908 : 451609 : if (mod_info)
909 : : {
910 : 29249 : always_copy_start += mod_info->always_copy_delta;
911 : 29249 : gcc_assert (always_copy_start >= 0);
912 : : }
913 : 451616 : for (unsigned i = always_copy_start; i < old_nargs; i++)
914 : 7 : vargs.safe_push (gimple_call_arg (stmt, i));
915 : : }
916 : :
917 : : /* For optimized away parameters, add on the caller side
918 : : before the call
919 : : DEBUG D#X => parm_Y(D)
920 : : stmts and associate D#X with parm in decl_debug_args_lookup
921 : : vector to say for debug info that if parameter parm had been passed,
922 : : it would have value parm_Y(D). */
923 : 451609 : tree old_decl = gimple_call_fndecl (stmt);
924 : 451609 : if (MAY_HAVE_DEBUG_BIND_STMTS && old_decl && callee_decl)
925 : : {
926 : 408655 : vec<tree, va_gc> **debug_args = NULL;
927 : 408655 : unsigned i = 0;
928 : 408655 : cgraph_node *callee_node = cgraph_node::get (callee_decl);
929 : :
930 : : /* FIXME: we don't seem to be able to insert debug args before clone
931 : : is materialized. Materializing them early leads to extra memory
932 : : use. */
933 : 408655 : if (callee_node->clone_of)
934 : 0 : callee_node->get_untransformed_body ();
935 : 408655 : for (tree old_parm = DECL_ARGUMENTS (old_decl);
936 : 1305669 : old_parm && i < old_nargs && ((int) i) < m_always_copy_start;
937 : 897014 : old_parm = DECL_CHAIN (old_parm), i++)
938 : : {
939 : 1604207 : if (!is_gimple_reg (old_parm) || kept[i])
940 : 694312 : continue;
941 : 206384 : tree arg;
942 : 206384 : if (mod_info)
943 : : {
944 : 8063 : if (mod_info->index_map[i] < 0)
945 : 3681 : continue;
946 : 4382 : arg = gimple_call_arg (stmt, mod_info->index_map[i]);
947 : : }
948 : : else
949 : 198321 : arg = gimple_call_arg (stmt, i);
950 : :
951 : 202703 : tree origin = DECL_ORIGIN (old_parm);
952 : 202703 : if (!useless_type_conversion_p (TREE_TYPE (origin), TREE_TYPE (arg)))
953 : : {
954 : 8 : if (!fold_convertible_p (TREE_TYPE (origin), arg))
955 : 1 : continue;
956 : 7 : tree rhs1;
957 : 7 : if (TREE_CODE (arg) == SSA_NAME
958 : 0 : && gimple_assign_cast_p (SSA_NAME_DEF_STMT (arg))
959 : 0 : && (rhs1
960 : 0 : = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (arg)))
961 : 7 : && useless_type_conversion_p (TREE_TYPE (origin),
962 : 0 : TREE_TYPE (rhs1)))
963 : : arg = rhs1;
964 : : else
965 : 7 : arg = fold_convert_loc (gimple_location (stmt),
966 : 7 : TREE_TYPE (origin), arg);
967 : : }
968 : 202702 : if (debug_args == NULL)
969 : 160795 : debug_args = decl_debug_args_insert (callee_decl);
970 : 202702 : unsigned int ix;
971 : 202702 : tree ddecl = NULL_TREE;
972 : 260584 : for (ix = 0; vec_safe_iterate (*debug_args, ix, &ddecl); ix += 2)
973 : 254861 : if (ddecl == origin)
974 : : {
975 : 196979 : ddecl = (**debug_args)[ix + 1];
976 : 196979 : break;
977 : : }
978 : 202702 : if (ddecl == NULL)
979 : : {
980 : 5723 : ddecl = build_debug_expr_decl (TREE_TYPE (origin));
981 : : /* FIXME: Is setting the mode really necessary? */
982 : 5723 : SET_DECL_MODE (ddecl, DECL_MODE (origin));
983 : :
984 : 5723 : vec_safe_push (*debug_args, origin);
985 : 5723 : vec_safe_push (*debug_args, ddecl);
986 : : }
987 : 202702 : gimple *def_temp = gimple_build_debug_bind (ddecl,
988 : : unshare_expr (arg), stmt);
989 : 202702 : gsi_insert_before (&gsi, def_temp, GSI_SAME_STMT);
990 : : }
991 : : }
992 : :
993 : 451609 : if (dump_file && (dump_flags & TDF_DETAILS))
994 : : {
995 : 10 : fprintf (dump_file, "replacing stmt:");
996 : 10 : print_gimple_stmt (dump_file, gsi_stmt (gsi), 0);
997 : : }
998 : :
999 : 451609 : gcall *new_stmt = gimple_build_call_vec (callee_decl, vargs);
1000 : :
1001 : 451609 : hash_set <tree> *ssas_to_remove = NULL;
1002 : 451609 : if (tree lhs = gimple_call_lhs (stmt))
1003 : : {
1004 : 174973 : if (!m_skip_return)
1005 : 165177 : gimple_call_set_lhs (new_stmt, lhs);
1006 : 9796 : else if (TREE_CODE (lhs) == SSA_NAME)
1007 : : {
1008 : 9796 : if (!killed_ssas)
1009 : : {
1010 : 412 : ssas_to_remove = new hash_set<tree> (8);
1011 : 412 : killed_ssas = ssas_to_remove;
1012 : : }
1013 : 9796 : killed_ssas->add (lhs);
1014 : 9796 : purge_all_uses (lhs, killed_ssas);
1015 : : }
1016 : : }
1017 : :
1018 : 451609 : gimple_set_block (new_stmt, gimple_block (stmt));
1019 : 451609 : if (gimple_has_location (stmt))
1020 : 766498 : gimple_set_location (new_stmt, gimple_location (stmt));
1021 : 451609 : gimple_call_set_chain (new_stmt, gimple_call_chain (stmt));
1022 : 451609 : gimple_call_copy_flags (new_stmt, stmt);
1023 : 451609 : if (gimple_in_ssa_p (cfun))
1024 : 451609 : gimple_move_vops (new_stmt, stmt);
1025 : :
1026 : 451609 : if (dump_file && (dump_flags & TDF_DETAILS))
1027 : : {
1028 : 10 : fprintf (dump_file, "with stmt:");
1029 : 10 : print_gimple_stmt (dump_file, new_stmt, 0);
1030 : 10 : fprintf (dump_file, "\n");
1031 : : }
1032 : 451609 : gsi_replace (&gsi, new_stmt, true);
1033 : 451609 : if (ssas_to_remove)
1034 : : {
1035 : 412 : ipa_release_ssas_in_hash (ssas_to_remove);
1036 : 412 : delete ssas_to_remove;
1037 : : }
1038 : 451609 : if (update_references)
1039 : 0 : do
1040 : : {
1041 : 0 : current_node->record_stmt_references (gsi_stmt (gsi));
1042 : 0 : gsi_prev (&gsi);
1043 : : }
1044 : 0 : while (gsi_stmt (gsi) != gsi_stmt (prev_gsi));
1045 : :
1046 : 451609 : if (mod_info)
1047 : 29249 : ipa_edge_modifications->remove (cs);
1048 : 451609 : return new_stmt;
1049 : 451609 : }
1050 : :
1051 : : /* Dump information contained in the object in textual form to F. */
1052 : :
1053 : : void
1054 : 9 : ipa_param_adjustments::dump (FILE *f)
1055 : : {
1056 : 9 : fprintf (f, " m_always_copy_start: %i\n", m_always_copy_start);
1057 : 9 : ipa_dump_adjusted_parameters (f, m_adj_params);
1058 : 9 : if (m_skip_return)
1059 : 5 : fprintf (f, " Will SKIP return.\n");
1060 : 9 : }
1061 : :
1062 : : /* Dump information contained in the object in textual form to stderr. */
1063 : :
1064 : : void
1065 : 0 : ipa_param_adjustments::debug ()
1066 : : {
1067 : 0 : dump (stderr);
1068 : 0 : }
1069 : :
1070 : : /* Register a REPLACEMENT for accesses to BASE at UNIT_OFFSET. */
1071 : :
1072 : : void
1073 : 93606 : ipa_param_body_adjustments::register_replacement (tree base,
1074 : : unsigned unit_offset,
1075 : : tree replacement)
1076 : : {
1077 : 93606 : ipa_param_body_replacement psr;
1078 : 93606 : psr.base = base;
1079 : 93606 : psr.repl = replacement;
1080 : 93606 : psr.dummy = NULL_TREE;
1081 : 93606 : psr.unit_offset = unit_offset;
1082 : 93606 : m_replacements.safe_push (psr);
1083 : 93606 : m_sorted_replacements_p = false;
1084 : 93606 : }
1085 : :
1086 : : /* Register that REPLACEMENT should replace parameter described in APM. */
1087 : :
1088 : : void
1089 : 82645 : ipa_param_body_adjustments::register_replacement (ipa_adjusted_param *apm,
1090 : : tree replacement)
1091 : : {
1092 : 82645 : gcc_checking_assert (apm->op == IPA_PARAM_OP_SPLIT
1093 : : || apm->op == IPA_PARAM_OP_NEW);
1094 : 82645 : gcc_checking_assert (!apm->prev_clone_adjustment);
1095 : 82645 : register_replacement (m_oparms[apm->prev_clone_index], apm->unit_offset,
1096 : : replacement);
1097 : 82645 : }
1098 : :
1099 : : /* Comparator for sorting and searching
1100 : : ipa_param_body_adjustments::m_replacements. */
1101 : :
1102 : : static int
1103 : 1576177 : compare_param_body_replacement (const void *va, const void *vb)
1104 : : {
1105 : 1576177 : const ipa_param_body_replacement *a = (const ipa_param_body_replacement *) va;
1106 : 1576177 : const ipa_param_body_replacement *b = (const ipa_param_body_replacement *) vb;
1107 : :
1108 : 1576177 : if (DECL_UID (a->base) < DECL_UID (b->base))
1109 : : return -1;
1110 : 1302250 : if (DECL_UID (a->base) > DECL_UID (b->base))
1111 : : return 1;
1112 : 982539 : if (a->unit_offset < b->unit_offset)
1113 : : return -1;
1114 : 544624 : if (a->unit_offset > b->unit_offset)
1115 : 454158 : return 1;
1116 : : return 0;
1117 : : }
1118 : :
1119 : : /* Sort m_replacements and set m_sorted_replacements_p to true. */
1120 : :
1121 : : void
1122 : 168337 : ipa_param_body_adjustments::sort_replacements ()
1123 : : {
1124 : 168337 : if (m_sorted_replacements_p)
1125 : : return;
1126 : 51835 : m_replacements.qsort (compare_param_body_replacement);
1127 : 51835 : m_sorted_replacements_p = true;
1128 : : }
1129 : :
1130 : : /* Copy or not, as appropriate given m_id and decl context, a pre-existing
1131 : : PARM_DECL T so that it can be included in the parameters of the modified
1132 : : function. */
1133 : :
1134 : : tree
1135 : 236165 : ipa_param_body_adjustments::carry_over_param (tree t)
1136 : : {
1137 : 236165 : tree new_parm;
1138 : 236165 : if (m_id)
1139 : : {
1140 : 232237 : new_parm = remap_decl (t, m_id);
1141 : 232237 : if (TREE_CODE (new_parm) != PARM_DECL)
1142 : 0 : new_parm = m_id->copy_decl (t, m_id);
1143 : : }
1144 : 3928 : else if (DECL_CONTEXT (t) != m_fndecl)
1145 : : {
1146 : 30 : new_parm = copy_node (t);
1147 : 30 : DECL_CONTEXT (new_parm) = m_fndecl;
1148 : : }
1149 : : else
1150 : : new_parm = t;
1151 : 236165 : return new_parm;
1152 : : }
1153 : :
1154 : : /* If DECL is a gimple register that has a default definition SSA name and that
1155 : : has some uses, return the default definition, otherwise return NULL_TREE. */
1156 : :
1157 : : tree
1158 : 149239 : ipa_param_body_adjustments::get_ddef_if_exists_and_is_used (tree decl)
1159 : : {
1160 : 149239 : if (!is_gimple_reg (decl))
1161 : : return NULL_TREE;
1162 : 120924 : tree ddef = ssa_default_def (m_id->src_cfun, decl);
1163 : 120924 : if (!ddef || has_zero_uses (ddef))
1164 : : return NULL_TREE;
1165 : : return ddef;
1166 : : }
1167 : :
1168 : : /* Populate m_dead_stmts given that DEAD_PARAM is going to be removed without
1169 : : any replacement or splitting. REPL is the replacement VAR_SECL to base any
1170 : : remaining uses of a removed parameter on. Push all removed SSA names that
1171 : : are used within debug statements to DEBUGSTACK. */
1172 : :
1173 : : void
1174 : 107591 : ipa_param_body_adjustments::mark_dead_statements (tree dead_param,
1175 : : vec<tree> *debugstack)
1176 : : {
1177 : : /* Current IPA analyses which remove unused parameters never remove a
1178 : : non-gimple register ones which have any use except as parameters in other
1179 : : calls, so we can safely leve them as they are. */
1180 : 107591 : tree parm_ddef = get_ddef_if_exists_and_is_used (dead_param);
1181 : 107591 : if (!parm_ddef)
1182 : 76302 : return;
1183 : :
1184 : 36016 : auto_vec<tree, 4> stack;
1185 : 36016 : hash_set<tree> used_in_debug;
1186 : 36016 : m_dead_ssas.add (parm_ddef);
1187 : 36016 : stack.safe_push (parm_ddef);
1188 : 109838 : while (!stack.is_empty ())
1189 : : {
1190 : 37806 : imm_use_iterator imm_iter;
1191 : 37806 : use_operand_p use_p;
1192 : 37806 : tree t = stack.pop ();
1193 : :
1194 : 37806 : insert_decl_map (m_id, t, error_mark_node);
1195 : 141914 : FOR_EACH_IMM_USE_FAST (use_p, imm_iter, t)
1196 : : {
1197 : 104108 : gimple *stmt = USE_STMT (use_p);
1198 : :
1199 : : /* Calls containing dead arguments cannot be deleted,
1200 : : modify_call_stmt will instead remove just the argument later on.
1201 : : If isra_track_scalar_value_uses in ipa-sra.cc is extended to look
1202 : : through const functions, we will need to do so here too. */
1203 : 104108 : if (is_gimple_call (stmt)
1204 : 104108 : || (m_id->blocks_to_copy
1205 : 72711 : && !bitmap_bit_p (m_id->blocks_to_copy,
1206 : 72711 : gimple_bb (stmt)->index)))
1207 : 94472 : continue;
1208 : :
1209 : 9636 : if (is_gimple_debug (stmt))
1210 : : {
1211 : 7357 : m_dead_stmts.add (stmt);
1212 : 7357 : gcc_assert (gimple_debug_bind_p (stmt));
1213 : 7357 : if (!used_in_debug.contains (t))
1214 : : {
1215 : 3208 : used_in_debug.add (t);
1216 : 3208 : debugstack->safe_push (t);
1217 : : }
1218 : : }
1219 : 2279 : else if (gimple_code (stmt) == GIMPLE_PHI)
1220 : : {
1221 : 393 : gphi *phi = as_a <gphi *> (stmt);
1222 : 393 : int ix = PHI_ARG_INDEX_FROM_USE (use_p);
1223 : :
1224 : 393 : if (!m_id->blocks_to_copy
1225 : 424 : || bitmap_bit_p (m_id->blocks_to_copy,
1226 : 31 : gimple_phi_arg_edge (phi, ix)->src->index))
1227 : : {
1228 : 362 : m_dead_stmts.add (phi);
1229 : 362 : tree res = gimple_phi_result (phi);
1230 : 362 : if (!m_dead_ssas.add (res))
1231 : 246 : stack.safe_push (res);
1232 : : }
1233 : : }
1234 : 1886 : else if (is_gimple_assign (stmt))
1235 : : {
1236 : 1802 : m_dead_stmts.add (stmt);
1237 : 1802 : if (!gimple_clobber_p (stmt))
1238 : : {
1239 : 1786 : tree lhs = gimple_assign_lhs (stmt);
1240 : 1786 : gcc_assert (TREE_CODE (lhs) == SSA_NAME);
1241 : 1786 : if (!m_dead_ssas.add (lhs))
1242 : 1544 : stack.safe_push (lhs);
1243 : : }
1244 : : }
1245 : 84 : else if (gimple_code (stmt) == GIMPLE_RETURN)
1246 : 84 : gcc_assert (m_adjustments && m_adjustments->m_skip_return);
1247 : : else
1248 : : /* IPA-SRA does not analyze other types of statements. */
1249 : 0 : gcc_unreachable ();
1250 : : }
1251 : : }
1252 : :
1253 : 36016 : if (!MAY_HAVE_DEBUG_STMTS)
1254 : : {
1255 : 4727 : gcc_assert (debugstack->is_empty ());
1256 : 4727 : return;
1257 : : }
1258 : :
1259 : 31289 : tree dp_ddecl = build_debug_expr_decl (TREE_TYPE (dead_param));
1260 : : /* FIXME: Is setting the mode really necessary? */
1261 : 31289 : SET_DECL_MODE (dp_ddecl, DECL_MODE (dead_param));
1262 : 31289 : m_dead_ssa_debug_equiv.put (parm_ddef, dp_ddecl);
1263 : 36016 : }
1264 : :
1265 : : /* Put all clobbers of of dereference of default definition of PARAM into
1266 : : m_dead_stmts. If there are returns among uses of the default definition of
1267 : : PARAM, verify they will be stripped off the return value. */
1268 : :
1269 : : void
1270 : 48704 : ipa_param_body_adjustments::mark_clobbers_dead (tree param)
1271 : : {
1272 : 48704 : if (!is_gimple_reg (param))
1273 : 7056 : return;
1274 : 41648 : tree ddef = get_ddef_if_exists_and_is_used (param);
1275 : 41648 : if (!ddef)
1276 : : return;
1277 : :
1278 : 41648 : imm_use_iterator imm_iter;
1279 : 41648 : use_operand_p use_p;
1280 : 188087 : FOR_EACH_IMM_USE_FAST (use_p, imm_iter, ddef)
1281 : : {
1282 : 146439 : gimple *stmt = USE_STMT (use_p);
1283 : 146439 : if (gimple_clobber_p (stmt))
1284 : 298 : m_dead_stmts.add (stmt);
1285 : 146141 : else if (gimple_code (stmt) == GIMPLE_RETURN)
1286 : 171 : gcc_assert (m_adjustments && m_adjustments->m_skip_return);
1287 : : }
1288 : : }
1289 : :
1290 : : /* Callback to walk_tree. If REMAP is an SSA_NAME that is present in hash_map
1291 : : passed in DATA, replace it with unshared version of what it was mapped to.
1292 : : If an SSA argument would be remapped to NULL, the whole operation needs to
1293 : : abort which is signaled by returning error_mark_node. */
1294 : :
1295 : : static tree
1296 : 15182 : replace_with_mapped_expr (tree *remap, int *walk_subtrees, void *data)
1297 : : {
1298 : 15182 : if (TYPE_P (*remap))
1299 : : {
1300 : 0 : *walk_subtrees = 0;
1301 : 0 : return 0;
1302 : : }
1303 : 15182 : if (TREE_CODE (*remap) != SSA_NAME)
1304 : : return 0;
1305 : :
1306 : 2647 : *walk_subtrees = 0;
1307 : :
1308 : 2647 : hash_map<tree, tree> *equivs = (hash_map<tree, tree> *) data;
1309 : 2647 : if (tree *p = equivs->get (*remap))
1310 : : {
1311 : 2594 : if (!*p)
1312 : 1 : return error_mark_node;
1313 : 2593 : *remap = unshare_expr (*p);
1314 : : }
1315 : : return 0;
1316 : : }
1317 : :
1318 : : /* Replace all occurances of SSAs in m_dead_ssa_debug_equiv in t with what they
1319 : : are mapped to. */
1320 : :
1321 : : void
1322 : 8087 : ipa_param_body_adjustments::remap_with_debug_expressions (tree *t)
1323 : : {
1324 : : /* If *t is an SSA_NAME which should have its debug statements reset, it is
1325 : : mapped to NULL in the hash_map.
1326 : :
1327 : : It is perhaps simpler to handle the SSA_NAME cases directly and only
1328 : : invoke walk_tree on more complex expressions. When
1329 : : remap_with_debug_expressions is called from tree-inline.cc, a to-be-reset
1330 : : SSA_NAME can be an operand to such expressions and the entire debug
1331 : : variable we are remapping should be reset. This is signaled by walk_tree
1332 : : returning error_mark_node and done by setting *t to NULL. */
1333 : 8087 : if (TREE_CODE (*t) == SSA_NAME)
1334 : : {
1335 : 5551 : if (tree *p = m_dead_ssa_debug_equiv.get (*t))
1336 : 5551 : *t = *p;
1337 : : }
1338 : 2536 : else if (walk_tree (t, replace_with_mapped_expr,
1339 : 2536 : &m_dead_ssa_debug_equiv, NULL) == error_mark_node)
1340 : 1 : *t = NULL_TREE;
1341 : 8087 : }
1342 : :
1343 : : /* For an SSA_NAME DEAD_SSA which is about to be DCEd because it is based on a
1344 : : useless parameter, prepare an expression that should represent it in
1345 : : debug_binds in the cloned function and add a mapping from DEAD_SSA to
1346 : : m_dead_ssa_debug_equiv. That mapping is to NULL when the associated
1347 : : debug_statement has to be reset instead. In such case return false,
1348 : : ottherwise return true. If DEAD_SSA comes from a basic block which is not
1349 : : about to be copied, ignore it and return true. */
1350 : :
1351 : : bool
1352 : 4230 : ipa_param_body_adjustments::prepare_debug_expressions (tree dead_ssa)
1353 : : {
1354 : 4230 : gcc_checking_assert (m_dead_ssas.contains (dead_ssa));
1355 : 4230 : if (tree *d = m_dead_ssa_debug_equiv.get (dead_ssa))
1356 : 3149 : return (*d != NULL_TREE);
1357 : :
1358 : 1081 : gcc_assert (!SSA_NAME_IS_DEFAULT_DEF (dead_ssa));
1359 : 1081 : gimple *def = SSA_NAME_DEF_STMT (dead_ssa);
1360 : 1081 : if (m_id->blocks_to_copy
1361 : 1081 : && !bitmap_bit_p (m_id->blocks_to_copy, gimple_bb (def)->index))
1362 : : return true;
1363 : :
1364 : 1081 : if (gimple_code (def) == GIMPLE_PHI)
1365 : : {
1366 : : /* In theory, we could ignore all SSAs coming from BBs not in
1367 : : m_id->blocks_to_copy but at the time of the writing this code that
1368 : : should never really be the case because only fnsplit uses that bitmap,
1369 : : so don't bother. */
1370 : 169 : tree value = degenerate_phi_result (as_a <gphi *> (def));
1371 : 169 : if (!value
1372 : 169 : || (m_dead_ssas.contains (value)
1373 : 0 : && !prepare_debug_expressions (value)))
1374 : : {
1375 : 169 : m_dead_ssa_debug_equiv.put (dead_ssa, NULL_TREE);
1376 : 169 : return false;
1377 : : }
1378 : :
1379 : 0 : gcc_assert (TREE_CODE (value) == SSA_NAME);
1380 : 0 : tree *d = m_dead_ssa_debug_equiv.get (value);
1381 : 0 : m_dead_ssa_debug_equiv.put (dead_ssa, *d);
1382 : 0 : return true;
1383 : : }
1384 : :
1385 : 912 : bool lost = false;
1386 : 912 : use_operand_p use_p;
1387 : 912 : ssa_op_iter oi;
1388 : 1829 : FOR_EACH_PHI_OR_STMT_USE (use_p, def, oi, SSA_OP_USE)
1389 : : {
1390 : 1099 : tree use = USE_FROM_PTR (use_p);
1391 : 1099 : if (m_dead_ssas.contains (use)
1392 : 1099 : && !prepare_debug_expressions (use))
1393 : : {
1394 : 182 : lost = true;
1395 : 182 : break;
1396 : : }
1397 : : }
1398 : :
1399 : 912 : if (lost)
1400 : : {
1401 : 182 : m_dead_ssa_debug_equiv.put (dead_ssa, NULL_TREE);
1402 : 182 : return false;
1403 : : }
1404 : :
1405 : 730 : if (is_gimple_assign (def))
1406 : : {
1407 : 730 : gcc_assert (!gimple_clobber_p (def));
1408 : 730 : if (gimple_assign_copy_p (def)
1409 : 730 : && TREE_CODE (gimple_assign_rhs1 (def)) == SSA_NAME)
1410 : : {
1411 : 0 : tree d = *m_dead_ssa_debug_equiv.get (gimple_assign_rhs1 (def));
1412 : 0 : gcc_assert (d);
1413 : 0 : m_dead_ssa_debug_equiv.put (dead_ssa, d);
1414 : 0 : return true;
1415 : : }
1416 : :
1417 : 730 : tree val
1418 : 730 : = unshare_expr_without_location (gimple_assign_rhs_to_tree (def));
1419 : 730 : remap_with_debug_expressions (&val);
1420 : :
1421 : 730 : tree vexpr = build_debug_expr_decl (TREE_TYPE (val));
1422 : 730 : m_dead_stmt_debug_equiv.put (def, val);
1423 : 730 : m_dead_ssa_debug_equiv.put (dead_ssa, vexpr);
1424 : 730 : return true;
1425 : : }
1426 : : else
1427 : 0 : gcc_unreachable ();
1428 : : }
1429 : :
1430 : : /* Common initialization performed by all ipa_param_body_adjustments
1431 : : constructors. OLD_FNDECL is the declaration we take original arguments
1432 : : from, (it may be the same as M_FNDECL). VARS, if non-NULL, is a pointer to
1433 : : a chained list of new local variables. TREE_MAP is the IPA-CP produced
1434 : : mapping of trees to constants.
1435 : :
1436 : : The function is rather long but it really onlu initializes all data members
1437 : : of the class. It creates new param DECLs, finds their new types, */
1438 : :
1439 : : void
1440 : 154167 : ipa_param_body_adjustments::common_initialization (tree old_fndecl,
1441 : : tree *vars,
1442 : : vec<ipa_replace_map *,
1443 : : va_gc> *tree_map)
1444 : : {
1445 : 154167 : push_function_arg_decls (&m_oparms, old_fndecl);
1446 : 154167 : auto_vec<tree,16> otypes;
1447 : 154167 : if (TYPE_ARG_TYPES (TREE_TYPE (old_fndecl)) != NULL_TREE)
1448 : 154001 : push_function_arg_types (&otypes, TREE_TYPE (old_fndecl));
1449 : : else
1450 : : {
1451 : 166 : auto_vec<tree,16> oparms;
1452 : 166 : push_function_arg_decls (&oparms, old_fndecl);
1453 : 166 : unsigned ocount = oparms.length ();
1454 : 166 : otypes.reserve_exact (ocount);
1455 : 444 : for (unsigned i = 0; i < ocount; i++)
1456 : 278 : otypes.quick_push (TREE_TYPE (oparms[i]));
1457 : 166 : }
1458 : 154167 : fill_vector_of_new_param_types (&m_new_types, &otypes, m_adj_params, true);
1459 : :
1460 : 154167 : auto_vec<bool, 16> kept;
1461 : 308334 : kept.reserve_exact (m_oparms.length ());
1462 : 308334 : kept.quick_grow_cleared (m_oparms.length ());
1463 : 154167 : auto_vec<bool, 16> split;
1464 : 154167 : split.reserve_exact (m_oparms.length ());
1465 : 308334 : split.quick_grow_cleared (m_oparms.length ());
1466 : :
1467 : 154167 : unsigned adj_len = vec_safe_length (m_adj_params);
1468 : 154167 : m_method2func = ((TREE_CODE (TREE_TYPE (m_fndecl)) == METHOD_TYPE)
1469 : 154167 : && (adj_len == 0
1470 : 40011 : || (*m_adj_params)[0].op != IPA_PARAM_OP_COPY
1471 : 39891 : || (*m_adj_params)[0].base_index != 0));
1472 : :
1473 : : /* The main job of the this function is to go over the vector of adjusted
1474 : : parameters and create declarations or find corresponding old ones and push
1475 : : them to m_new_decls. For IPA-SRA replacements it also creates
1476 : : corresponding m_id->dst_node->clone.performed_splits entries. */
1477 : :
1478 : 154167 : m_new_decls.reserve_exact (adj_len);
1479 : 477274 : for (unsigned i = 0; i < adj_len ; i++)
1480 : : {
1481 : 323107 : ipa_adjusted_param *apm = &(*m_adj_params)[i];
1482 : 323107 : unsigned prev_index = apm->prev_clone_index;
1483 : 323107 : tree new_parm;
1484 : 323107 : if (apm->op == IPA_PARAM_OP_COPY
1485 : 86942 : || apm->prev_clone_adjustment)
1486 : : {
1487 : 236165 : kept[prev_index] = true;
1488 : 236165 : new_parm = carry_over_param (m_oparms[prev_index]);
1489 : 236165 : m_new_decls.quick_push (new_parm);
1490 : : }
1491 : 86942 : else if (apm->op == IPA_PARAM_OP_NEW
1492 : 86942 : || apm->op == IPA_PARAM_OP_SPLIT)
1493 : : {
1494 : 86942 : tree new_type = m_new_types[i];
1495 : 86942 : gcc_checking_assert (new_type);
1496 : 86942 : new_parm = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL_TREE,
1497 : : new_type);
1498 : 86942 : const char *prefix = ipa_param_prefixes[apm->param_prefix_index];
1499 : 86942 : DECL_NAME (new_parm) = create_tmp_var_name (prefix);
1500 : 86942 : DECL_ARTIFICIAL (new_parm) = 1;
1501 : 86942 : DECL_ARG_TYPE (new_parm) = new_type;
1502 : 86942 : DECL_CONTEXT (new_parm) = m_fndecl;
1503 : 86942 : TREE_USED (new_parm) = 1;
1504 : 86942 : DECL_IGNORED_P (new_parm) = 1;
1505 : 86942 : layout_decl (new_parm, 0);
1506 : 86942 : m_new_decls.quick_push (new_parm);
1507 : :
1508 : 86942 : if (apm->op == IPA_PARAM_OP_SPLIT)
1509 : : {
1510 : 78206 : split[prev_index] = true;
1511 : 78206 : register_replacement (apm, new_parm);
1512 : : }
1513 : : }
1514 : : else
1515 : 0 : gcc_unreachable ();
1516 : : }
1517 : :
1518 : 154167 : auto_vec <int, 16> index_mapping;
1519 : 154167 : bool need_remap = false;
1520 : 154167 : if (m_id)
1521 : : {
1522 : 149691 : clone_info *cinfo = clone_info::get (m_id->src_node);
1523 : 149691 : if (cinfo && cinfo->param_adjustments)
1524 : : {
1525 : 2530 : cinfo->param_adjustments->get_updated_indices (&index_mapping);
1526 : 2530 : need_remap = true;
1527 : : }
1528 : :
1529 : 149691 : if (ipcp_transformation *ipcp_ts
1530 : 149691 : = ipcp_get_transformation_summary (m_id->src_node))
1531 : : {
1532 : 38661 : for (const ipa_argagg_value &av : ipcp_ts->m_agg_values)
1533 : : {
1534 : 14479 : int parm_num = av.index;
1535 : :
1536 : 14479 : if (need_remap)
1537 : : {
1538 : : /* FIXME: We cannot handle the situation when IPA-CP
1539 : : identified that a parameter is a pointer to a global
1540 : : variable and at the same time the variable has some known
1541 : : constant contents (PR 107640). The best place to make
1542 : : sure we don't drop such constants on the floor probably is
1543 : : not here, but we have to make sure that it does not
1544 : : confuse the remapping. */
1545 : 13394 : if (parm_num >= (int) index_mapping.length ())
1546 : 23 : continue;
1547 : 6674 : parm_num = index_mapping[parm_num];
1548 : 6674 : if (parm_num < 0)
1549 : 30 : continue;
1550 : : }
1551 : :
1552 : 14426 : if (!kept[parm_num])
1553 : : {
1554 : : /* IPA-CP has detected an aggregate constant in a parameter
1555 : : that will not be kept, which means that IPA-SRA would have
1556 : : split it if there wasn't a constant. Because we are about
1557 : : to remove the original, this is the last chance where we
1558 : : can substitute the uses with a constant (for values passed
1559 : : by reference) or do the split but initialize the
1560 : : replacement with a constant (for split aggregates passed
1561 : : by value). */
1562 : :
1563 : 10965 : if (split[parm_num])
1564 : : {
1565 : : /* We must be careful not to add a duplicate
1566 : : replacement. */
1567 : 9722 : sort_replacements ();
1568 : 9722 : ipa_param_body_replacement *pbr
1569 : 9722 : = lookup_replacement_1 (m_oparms[parm_num],
1570 : 9722 : av.unit_offset);
1571 : 9722 : if (pbr)
1572 : : {
1573 : : /* Otherwise IPA-SRA should have bailed out. */
1574 : 4 : gcc_assert (AGGREGATE_TYPE_P (TREE_TYPE (pbr->repl)));
1575 : 4 : continue;
1576 : : }
1577 : : }
1578 : :
1579 : 10961 : tree repl;
1580 : 10961 : if (av.by_ref)
1581 : 9646 : repl = av.value;
1582 : : else
1583 : : {
1584 : 1315 : repl = create_tmp_var (TREE_TYPE (av.value),
1585 : : "removed_ipa_cp");
1586 : 1315 : gimple *init_stmt = gimple_build_assign (repl, av.value);
1587 : 1315 : m_split_agg_csts_inits.safe_push (init_stmt);
1588 : : }
1589 : 10961 : register_replacement (m_oparms[parm_num], av.unit_offset,
1590 : : repl);
1591 : 10961 : split[parm_num] = true;
1592 : : }
1593 : : }
1594 : : }
1595 : : }
1596 : 154167 : sort_replacements ();
1597 : :
1598 : 154167 : if (tree_map)
1599 : : {
1600 : : /* Do not treat parameters which were replaced with a constant as
1601 : : completely vanished. */
1602 : 28720 : for (unsigned i = 0; i < tree_map->length (); i++)
1603 : : {
1604 : 17189 : int parm_num = (*tree_map)[i]->parm_num;
1605 : 17189 : gcc_assert (parm_num >= 0);
1606 : 17189 : if (need_remap)
1607 : 0 : parm_num = index_mapping[parm_num];
1608 : 17189 : kept[parm_num] = true;
1609 : : }
1610 : : }
1611 : :
1612 : : /* As part of body modifications, we will also have to replace remaining uses
1613 : : of remaining uses of removed PARM_DECLs (which do not however use the
1614 : : initial value) with their VAR_DECL copies.
1615 : :
1616 : : We do this differently with and without m_id. With m_id, we rely on its
1617 : : mapping and create a replacement straight away. Without it, we have our
1618 : : own mechanism for which we have to populate m_removed_decls vector. Just
1619 : : don't mix them, that is why you should not call
1620 : : replace_removed_params_ssa_names or perform_cfun_body_modifications when
1621 : : you construct with ID not equal to NULL. */
1622 : :
1623 : 154167 : auto_vec<tree, 8> ssas_to_process_debug;
1624 : 154167 : unsigned op_len = m_oparms.length ();
1625 : 568307 : for (unsigned i = 0; i < op_len; i++)
1626 : 414140 : if (!kept[i])
1627 : : {
1628 : 160786 : if (m_id)
1629 : : {
1630 : 156295 : gcc_assert (!m_id->decl_map->get (m_oparms[i]));
1631 : 156295 : tree var = copy_decl_to_var (m_oparms[i], m_id);
1632 : 156295 : insert_decl_map (m_id, m_oparms[i], var);
1633 : : /* Declare this new variable. */
1634 : 156295 : DECL_CHAIN (var) = *vars;
1635 : 156295 : *vars = var;
1636 : :
1637 : : /* If this is not a split but a real removal, init hash sets
1638 : : that will guide what not to copy to the new body. */
1639 : 156295 : if (!split[i])
1640 : 107591 : mark_dead_statements (m_oparms[i], &ssas_to_process_debug);
1641 : : else
1642 : 48704 : mark_clobbers_dead (m_oparms[i]);
1643 : 19438 : if (MAY_HAVE_DEBUG_STMTS
1644 : 156295 : && is_gimple_reg (m_oparms[i]))
1645 : 103460 : m_reset_debug_decls.safe_push (m_oparms[i]);
1646 : : }
1647 : : else
1648 : : {
1649 : 4491 : m_removed_decls.safe_push (m_oparms[i]);
1650 : 8982 : m_removed_map.put (m_oparms[i], m_removed_decls.length () - 1);
1651 : 4218 : if (MAY_HAVE_DEBUG_STMTS
1652 : 273 : && !kept[i]
1653 : 4764 : && is_gimple_reg (m_oparms[i]))
1654 : 233 : m_reset_debug_decls.safe_push (m_oparms[i]);
1655 : : }
1656 : : }
1657 : :
1658 : 311542 : while (!ssas_to_process_debug.is_empty ())
1659 : 3208 : prepare_debug_expressions (ssas_to_process_debug.pop ());
1660 : 154167 : }
1661 : :
1662 : : /* Constructor of ipa_param_body_adjustments from a simple list of
1663 : : modifications to parameters listed in ADJ_PARAMS which will prepare ground
1664 : : for modification of parameters of fndecl. Return value of the function will
1665 : : not be removed and the object will assume it does not run as a part of
1666 : : tree-function_versioning. */
1667 : :
1668 : 4448 : ipa_param_body_adjustments
1669 : : ::ipa_param_body_adjustments (vec<ipa_adjusted_param, va_gc> *adj_params,
1670 : 4448 : tree fndecl)
1671 : 4448 : : m_adj_params (adj_params), m_adjustments (NULL), m_reset_debug_decls (),
1672 : 4448 : m_dead_stmts (), m_dead_ssas (), m_dead_ssa_debug_equiv (),
1673 : 4448 : m_dead_stmt_debug_equiv (), m_fndecl (fndecl), m_id (NULL), m_oparms (),
1674 : 4448 : m_new_decls (), m_new_types (), m_replacements (),
1675 : 4448 : m_split_agg_csts_inits (), m_removed_decls (), m_removed_map (),
1676 : 4448 : m_method2func (false), m_sorted_replacements_p (true)
1677 : : {
1678 : 4448 : common_initialization (fndecl, NULL, NULL);
1679 : 4448 : }
1680 : :
1681 : : /* Constructor of ipa_param_body_adjustments from ipa_param_adjustments in
1682 : : ADJUSTMENTS which will prepare ground for modification of parameters of
1683 : : fndecl. The object will assume it does not run as a part of
1684 : : tree-function_versioning. */
1685 : :
1686 : 28 : ipa_param_body_adjustments
1687 : : ::ipa_param_body_adjustments (ipa_param_adjustments *adjustments,
1688 : 28 : tree fndecl)
1689 : 28 : : m_adj_params (adjustments->m_adj_params), m_adjustments (adjustments),
1690 : 28 : m_reset_debug_decls (), m_dead_stmts (), m_dead_ssas (),
1691 : 28 : m_dead_ssa_debug_equiv (), m_dead_stmt_debug_equiv (), m_fndecl (fndecl),
1692 : 28 : m_id (NULL), m_oparms (), m_new_decls (), m_new_types (), m_replacements (),
1693 : 28 : m_split_agg_csts_inits (), m_removed_decls (), m_removed_map (),
1694 : 28 : m_method2func (false), m_sorted_replacements_p (true)
1695 : : {
1696 : 28 : common_initialization (fndecl, NULL, NULL);
1697 : 28 : }
1698 : :
1699 : : /* Constructor of ipa_param_body_adjustments which sets it up as a part of
1700 : : running tree_function_versioning. Planned modifications to the function are
1701 : : in ADJUSTMENTS. FNDECL designates the new function clone which is being
1702 : : modified. OLD_FNDECL is the function of which FNDECL is a clone (and which
1703 : : at the time of invocation still share DECL_ARGUMENTS). ID is the
1704 : : copy_body_data structure driving the whole body copying process. VARS is a
1705 : : pointer to the head of the list of new local variables, TREE_MAP is the map
1706 : : that drives tree substitution in the cloning process. */
1707 : :
1708 : 149691 : ipa_param_body_adjustments
1709 : : ::ipa_param_body_adjustments (ipa_param_adjustments *adjustments,
1710 : : tree fndecl, tree old_fndecl,
1711 : : copy_body_data *id, tree *vars,
1712 : 149691 : vec<ipa_replace_map *, va_gc> *tree_map)
1713 : 149691 : : m_adj_params (adjustments->m_adj_params), m_adjustments (adjustments),
1714 : 149691 : m_reset_debug_decls (), m_dead_stmts (), m_dead_ssas (),
1715 : 149691 : m_dead_ssa_debug_equiv (), m_dead_stmt_debug_equiv (), m_fndecl (fndecl),
1716 : 149691 : m_id (id), m_oparms (), m_new_decls (), m_new_types (), m_replacements (),
1717 : 149691 : m_split_agg_csts_inits (), m_removed_decls (), m_removed_map (),
1718 : 149691 : m_method2func (false), m_sorted_replacements_p (true)
1719 : : {
1720 : 149691 : common_initialization (old_fndecl, vars, tree_map);
1721 : 149691 : }
1722 : :
1723 : : /* Chain new param decls up and return them. */
1724 : :
1725 : : tree
1726 : 154167 : ipa_param_body_adjustments::get_new_param_chain ()
1727 : : {
1728 : 154167 : tree result;
1729 : 154167 : tree *link = &result;
1730 : :
1731 : 154167 : unsigned len = vec_safe_length (m_adj_params);
1732 : 477274 : for (unsigned i = 0; i < len; i++)
1733 : : {
1734 : 323107 : tree new_decl = m_new_decls[i];
1735 : 323107 : *link = new_decl;
1736 : 323107 : link = &DECL_CHAIN (new_decl);
1737 : : }
1738 : 154167 : *link = NULL_TREE;
1739 : 154167 : return result;
1740 : : }
1741 : :
1742 : : /* Modify the function parameters FNDECL and its type according to the plan in
1743 : : ADJUSTMENTS. This function needs to be called when the decl has not already
1744 : : been processed with ipa_param_adjustments::adjust_decl, otherwise just
1745 : : seting DECL_ARGUMENTS to whatever get_new_param_chain will do is enough. */
1746 : :
1747 : : void
1748 : 4476 : ipa_param_body_adjustments::modify_formal_parameters ()
1749 : : {
1750 : 4476 : tree orig_type = TREE_TYPE (m_fndecl);
1751 : 4476 : DECL_ARGUMENTS (m_fndecl) = get_new_param_chain ();
1752 : :
1753 : : /* When signature changes, we need to clear builtin info. */
1754 : 4476 : if (fndecl_built_in_p (m_fndecl))
1755 : 0 : set_decl_built_in_function (m_fndecl, NOT_BUILT_IN, 0);
1756 : :
1757 : 4476 : bool modified = false;
1758 : 4476 : size_t index = 0;
1759 : 4476 : if (m_adj_params)
1760 : 4116 : for (tree t = TYPE_ARG_TYPES (orig_type);
1761 : 10570 : t && !modified;
1762 : 6454 : t = TREE_CHAIN (t), index++)
1763 : 6454 : if (index >= m_adj_params->length ()
1764 : 5869 : || (*m_adj_params)[index].op != IPA_PARAM_OP_COPY
1765 : 8833 : || (*m_adj_params)[index].base_index != index)
1766 : : modified = true;
1767 : :
1768 : : /* At this point, removing return value is only implemented when going
1769 : : through tree_function_versioning, not when modifying function body
1770 : : directly. */
1771 : 4476 : gcc_assert (!m_adjustments || !m_adjustments->m_skip_return);
1772 : 8952 : tree new_type = build_adjusted_function_type (orig_type, &m_new_types,
1773 : 4476 : m_method2func, false, modified);
1774 : :
1775 : 4476 : TREE_TYPE (m_fndecl) = new_type;
1776 : 4476 : DECL_VIRTUAL_P (m_fndecl) = 0;
1777 : 4476 : DECL_LANG_SPECIFIC (m_fndecl) = NULL;
1778 : 4476 : if (m_method2func)
1779 : 120 : DECL_VINDEX (m_fndecl) = NULL_TREE;
1780 : 4476 : }
1781 : :
1782 : : /* Given BASE and UNIT_OFFSET, find the corresponding record among replacement
1783 : : structures. */
1784 : :
1785 : : ipa_param_body_replacement *
1786 : 169703 : ipa_param_body_adjustments::lookup_replacement_1 (tree base,
1787 : : unsigned unit_offset)
1788 : : {
1789 : 169703 : gcc_assert (m_sorted_replacements_p);
1790 : 169703 : ipa_param_body_replacement key;
1791 : 169703 : key.base = base;
1792 : 169703 : key.unit_offset = unit_offset;
1793 : 169703 : ipa_param_body_replacement *res
1794 : 339406 : = std::lower_bound (m_replacements.begin (), m_replacements.end (), key,
1795 : 328439 : [] (const ipa_param_body_replacement &elt,
1796 : : const ipa_param_body_replacement &val)
1797 : : {
1798 : 328439 : return (compare_param_body_replacement (&elt, &val)
1799 : : < 0);
1800 : : });
1801 : :
1802 : 169703 : if (res == m_replacements.end ()
1803 : 137196 : || res->base != base
1804 : 261352 : || res->unit_offset != unit_offset)
1805 : 79237 : return NULL;
1806 : : return res;
1807 : : }
1808 : :
1809 : : /* Find the first replacement for BASE among m_replacements and return pointer
1810 : : to it, or NULL if there is none. */
1811 : :
1812 : : ipa_param_body_replacement *
1813 : 24678 : ipa_param_body_adjustments::lookup_first_base_replacement (tree base)
1814 : : {
1815 : 24678 : gcc_assert (m_sorted_replacements_p);
1816 : 24678 : ipa_param_body_replacement key;
1817 : 24678 : key.base = base;
1818 : 24678 : ipa_param_body_replacement *res
1819 : 49356 : = std::lower_bound (m_replacements.begin (), m_replacements.end (), key,
1820 : 38437 : [] (const ipa_param_body_replacement &elt,
1821 : : const ipa_param_body_replacement &val)
1822 : : {
1823 : 38437 : if (DECL_UID (elt.base) < DECL_UID (val.base))
1824 : 12393 : return true;
1825 : : return false;
1826 : : });
1827 : :
1828 : 24678 : if (res == m_replacements.end ()
1829 : 24678 : || res->base != base)
1830 : 19636 : return NULL;
1831 : : return res;
1832 : : }
1833 : :
1834 : : /* Given BASE and UNIT_OFFSET, find the corresponding replacement expression
1835 : : and return it, assuming it is known it does not hold value by reference or
1836 : : in reverse storage order. */
1837 : :
1838 : : tree
1839 : 4019 : ipa_param_body_adjustments::lookup_replacement (tree base, unsigned unit_offset)
1840 : : {
1841 : 4019 : ipa_param_body_replacement *pbr = lookup_replacement_1 (base, unit_offset);
1842 : 4019 : if (!pbr)
1843 : : return NULL;
1844 : 4019 : return pbr->repl;
1845 : : }
1846 : :
1847 : : /* If T is an SSA_NAME, return NULL if it is not a default def or
1848 : : return its base variable if it is. If IGNORE_DEFAULT_DEF is true,
1849 : : the base variable is always returned, regardless if it is a default
1850 : : def. Return T if it is not an SSA_NAME. */
1851 : :
1852 : : static tree
1853 : 1013632 : get_ssa_base_param (tree t, bool ignore_default_def)
1854 : : {
1855 : 1013632 : if (TREE_CODE (t) == SSA_NAME)
1856 : : {
1857 : 614590 : if (ignore_default_def || SSA_NAME_IS_DEFAULT_DEF (t))
1858 : 130604 : return SSA_NAME_VAR (t);
1859 : : else
1860 : : return NULL_TREE;
1861 : : }
1862 : : return t;
1863 : : }
1864 : :
1865 : : /* Given an expression, return the structure describing how it should be
1866 : : replaced if it accesses a part of a split parameter or NULL otherwise.
1867 : :
1868 : : Do not free the result, it will be deallocated when the object is destroyed.
1869 : :
1870 : : If IGNORE_DEFAULT_DEF is cleared, consider only SSA_NAMEs of PARM_DECLs
1871 : : which are default definitions, if set, consider all SSA_NAMEs of
1872 : : PARM_DECLs. */
1873 : :
1874 : : ipa_param_body_replacement *
1875 : 1020447 : ipa_param_body_adjustments::get_expr_replacement (tree expr,
1876 : : bool ignore_default_def)
1877 : : {
1878 : 1020447 : tree base;
1879 : 1020447 : unsigned unit_offset;
1880 : :
1881 : 1020447 : if (!isra_get_ref_base_and_offset (expr, &base, &unit_offset))
1882 : : return NULL;
1883 : :
1884 : 1013632 : base = get_ssa_base_param (base, ignore_default_def);
1885 : 1013632 : if (!base || TREE_CODE (base) != PARM_DECL)
1886 : : return NULL;
1887 : 155008 : return lookup_replacement_1 (base, unit_offset);
1888 : : }
1889 : :
1890 : : /* Given OLD_DECL, which is a PARM_DECL of a parameter that is being removed
1891 : : (which includes it being split or replaced), return a new variable that
1892 : : should be used for any SSA names that will remain in the function that
1893 : : previously belonged to OLD_DECL. */
1894 : :
1895 : : tree
1896 : 7905 : ipa_param_body_adjustments::get_replacement_ssa_base (tree old_decl)
1897 : : {
1898 : 7905 : unsigned *idx = m_removed_map.get (old_decl);
1899 : 7905 : if (!idx)
1900 : : return NULL;
1901 : :
1902 : 4451 : tree repl;
1903 : 4451 : if (TREE_CODE (m_removed_decls[*idx]) == PARM_DECL)
1904 : : {
1905 : 4019 : gcc_assert (m_removed_decls[*idx] == old_decl);
1906 : 4019 : repl = copy_var_decl (old_decl, DECL_NAME (old_decl),
1907 : 4019 : TREE_TYPE (old_decl));
1908 : 4019 : m_removed_decls[*idx] = repl;
1909 : : }
1910 : : else
1911 : : repl = m_removed_decls[*idx];
1912 : : return repl;
1913 : : }
1914 : :
1915 : : /* If OLD_NAME, which is being defined by statement STMT, is an SSA_NAME of a
1916 : : parameter which is to be removed because its value is not used, create a new
1917 : : SSA_NAME relating to a replacement VAR_DECL, replace all uses of the
1918 : : original with it and return it. If there is no need to re-map, return NULL.
1919 : : ADJUSTMENTS is a pointer to a vector of IPA-SRA adjustments. */
1920 : :
1921 : : tree
1922 : 0 : ipa_param_body_adjustments::replace_removed_params_ssa_names (tree old_name,
1923 : : gimple *stmt)
1924 : : {
1925 : 0 : gcc_assert (!m_id);
1926 : 0 : if (TREE_CODE (old_name) != SSA_NAME)
1927 : : return NULL;
1928 : :
1929 : 0 : tree decl = SSA_NAME_VAR (old_name);
1930 : 0 : if (decl == NULL_TREE
1931 : 0 : || TREE_CODE (decl) != PARM_DECL)
1932 : : return NULL;
1933 : :
1934 : 0 : tree repl = get_replacement_ssa_base (decl);
1935 : 0 : if (!repl)
1936 : : return NULL;
1937 : :
1938 : 0 : tree new_name = make_ssa_name (repl, stmt);
1939 : 0 : SSA_NAME_OCCURS_IN_ABNORMAL_PHI (new_name)
1940 : 0 : = SSA_NAME_OCCURS_IN_ABNORMAL_PHI (old_name);
1941 : :
1942 : 0 : if (dump_file && (dump_flags & TDF_DETAILS))
1943 : : {
1944 : 0 : fprintf (dump_file, "replacing an SSA name of a removed param ");
1945 : 0 : print_generic_expr (dump_file, old_name);
1946 : 0 : fprintf (dump_file, " with ");
1947 : 0 : print_generic_expr (dump_file, new_name);
1948 : 0 : fprintf (dump_file, "\n");
1949 : : }
1950 : :
1951 : 0 : replace_uses_by (old_name, new_name);
1952 : 0 : return new_name;
1953 : : }
1954 : :
1955 : : /* If the expression *EXPR_P should be replaced, do so. CONVERT specifies
1956 : : whether the function should care about type incompatibility of the current
1957 : : and new expressions. If it is false, the function will leave
1958 : : incompatibility issues to the caller - note that when the function
1959 : : encounters a BIT_FIELD_REF, IMAGPART_EXPR or REALPART_EXPR, it will modify
1960 : : their bases instead of the expressions themselves and then also performs any
1961 : : necessary conversions. */
1962 : :
1963 : : bool
1964 : 2403804 : ipa_param_body_adjustments::modify_expression (tree *expr_p, bool convert,
1965 : : gimple_seq *extra_stmts)
1966 : : {
1967 : 2403804 : tree expr = *expr_p;
1968 : :
1969 : 4723410 : if (m_replacements.is_empty ())
1970 : : return false;
1971 : 1018363 : if (TREE_CODE (expr) == BIT_FIELD_REF
1972 : 1018363 : || TREE_CODE (expr) == IMAGPART_EXPR
1973 : 1017744 : || TREE_CODE (expr) == REALPART_EXPR)
1974 : : {
1975 : : /* For a BIT_FIELD_REF do not bother to VIEW_CONVERT the base,
1976 : : instead reference the replacement directly. */
1977 : 1004 : convert = TREE_CODE (expr) != BIT_FIELD_REF;
1978 : 1004 : expr_p = &TREE_OPERAND (expr, 0);
1979 : 1004 : expr = *expr_p;
1980 : : }
1981 : :
1982 : 1018363 : ipa_param_body_replacement *pbr = get_expr_replacement (expr, false);
1983 : 1018363 : if (!pbr)
1984 : : return false;
1985 : :
1986 : 84198 : tree repl = pbr->repl;
1987 : 84198 : if (dump_file && (dump_flags & TDF_DETAILS))
1988 : : {
1989 : 8 : fprintf (dump_file, "About to replace expr ");
1990 : 8 : print_generic_expr (dump_file, expr);
1991 : 8 : fprintf (dump_file, " with ");
1992 : 8 : print_generic_expr (dump_file, repl);
1993 : 8 : fprintf (dump_file, "\n");
1994 : : }
1995 : :
1996 : 84448 : if (convert && !useless_type_conversion_p (TREE_TYPE (expr),
1997 : 250 : TREE_TYPE (repl)))
1998 : : {
1999 : 8 : gcc_checking_assert (tree_to_shwi (TYPE_SIZE (TREE_TYPE (expr)))
2000 : : == tree_to_shwi (TYPE_SIZE (TREE_TYPE (repl))));
2001 : 8 : tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (expr), repl);
2002 : 8 : if (is_gimple_reg (repl)
2003 : 8 : && is_gimple_reg_type (TREE_TYPE (expr)))
2004 : : {
2005 : 0 : gcc_assert (extra_stmts);
2006 : 0 : vce = force_gimple_operand (vce, extra_stmts, true, NULL_TREE);
2007 : : }
2008 : 8 : *expr_p = vce;
2009 : : }
2010 : : else
2011 : 84190 : *expr_p = repl;
2012 : : return true;
2013 : : }
2014 : :
2015 : : /* If the assignment statement STMT contains any expressions that need to
2016 : : replaced with a different one as noted by ADJUSTMENTS, do so. Handle any
2017 : : potential type incompatibilities. If any conversion sttements have to be
2018 : : pre-pended to STMT, they will be added to EXTRA_STMTS. Return true iff the
2019 : : statement was modified. */
2020 : :
2021 : : bool
2022 : 1859960 : ipa_param_body_adjustments::modify_assignment (gimple *stmt,
2023 : : gimple_seq *extra_stmts)
2024 : : {
2025 : 1859960 : tree *lhs_p, *rhs_p;
2026 : 1859960 : bool any;
2027 : :
2028 : 2415317 : if (m_replacements.is_empty () || !gimple_assign_single_p (stmt))
2029 : : return false;
2030 : :
2031 : 381560 : rhs_p = gimple_assign_rhs1_ptr (stmt);
2032 : 381560 : lhs_p = gimple_assign_lhs_ptr (stmt);
2033 : :
2034 : 381560 : any = modify_expression (lhs_p, false);
2035 : 381560 : any |= modify_expression (rhs_p, false, extra_stmts);
2036 : 381560 : if (any
2037 : 381560 : && !useless_type_conversion_p (TREE_TYPE (*lhs_p), TREE_TYPE (*rhs_p)))
2038 : : {
2039 : 5 : if (TREE_CODE (*rhs_p) == CONSTRUCTOR)
2040 : : {
2041 : : /* V_C_Es of constructors can cause trouble (PR 42714). */
2042 : 0 : if (is_gimple_reg_type (TREE_TYPE (*lhs_p)))
2043 : 0 : *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
2044 : : else
2045 : 0 : *rhs_p = build_constructor (TREE_TYPE (*lhs_p),
2046 : : NULL);
2047 : : }
2048 : : else
2049 : : {
2050 : 5 : gcc_checking_assert (tree_to_shwi (TYPE_SIZE (TREE_TYPE (*lhs_p)))
2051 : : == tree_to_shwi (TYPE_SIZE (TREE_TYPE (*rhs_p))));
2052 : 5 : tree new_rhs = fold_build1_loc (gimple_location (stmt),
2053 : 5 : VIEW_CONVERT_EXPR, TREE_TYPE (*lhs_p),
2054 : : *rhs_p);
2055 : 5 : tree tmp = force_gimple_operand (new_rhs, extra_stmts, true,
2056 : : NULL_TREE);
2057 : 5 : gimple_assign_set_rhs1 (stmt, tmp);
2058 : : }
2059 : 5 : return true;
2060 : : }
2061 : :
2062 : : return any;
2063 : : }
2064 : :
2065 : : /* Record information about what modifications to call arguments have already
2066 : : been done by clone materialization into a summary describing CS. The
2067 : : information is stored in NEW_INDEX_MAP, NEW_PT_MAP and NEW_ALWAYS_COPY_DELTA
2068 : : and correspond to equivalent fields in ipa_edge_modification_info. Return
2069 : : the edge summary. */
2070 : :
2071 : : static ipa_edge_modification_info *
2072 : 11931 : record_argument_state_1 (cgraph_edge *cs, const vec<int> &new_index_map,
2073 : : const vec<pass_through_split_map> &new_pt_map,
2074 : : int new_always_copy_delta)
2075 : :
2076 : : {
2077 : 11931 : ipa_edge_modification_info *sum = ipa_edge_modifications->get_create (cs);
2078 : :
2079 : 11931 : unsigned len = sum->pass_through_map.length ();
2080 : 11931 : for (unsigned i = 0; i < len; i++)
2081 : : {
2082 : 0 : unsigned oldnew = sum->pass_through_map[i].new_index;
2083 : 0 : sum->pass_through_map[i].new_index = new_index_map[oldnew];
2084 : : }
2085 : :
2086 : 11931 : len = sum->index_map.length ();
2087 : 0 : if (len > 0)
2088 : : {
2089 : 0 : unsigned nptlen = new_pt_map.length ();
2090 : 0 : for (unsigned j = 0; j < nptlen; j++)
2091 : : {
2092 : 0 : int inverse = -1;
2093 : 0 : for (unsigned i = 0; i < len ; i++)
2094 : 0 : if ((unsigned) sum->index_map[i] == new_pt_map[j].base_index)
2095 : : {
2096 : 0 : inverse = i;
2097 : 0 : break;
2098 : : }
2099 : 0 : gcc_assert (inverse >= 0);
2100 : 0 : pass_through_split_map ptm_item;
2101 : :
2102 : 0 : ptm_item.base_index = inverse;
2103 : 0 : ptm_item.unit_offset = new_pt_map[j].unit_offset;
2104 : 0 : ptm_item.new_index = new_pt_map[j].new_index;
2105 : 0 : sum->pass_through_map.safe_push (ptm_item);
2106 : : }
2107 : :
2108 : 0 : for (unsigned i = 0; i < len; i++)
2109 : : {
2110 : 0 : int idx = sum->index_map[i];
2111 : 0 : if (idx < 0)
2112 : 0 : continue;
2113 : 0 : sum->index_map[i] = new_index_map[idx];
2114 : : }
2115 : : }
2116 : : else
2117 : : {
2118 : 11931 : sum->pass_through_map.safe_splice (new_pt_map);
2119 : 11931 : sum->index_map.safe_splice (new_index_map);
2120 : : }
2121 : 11931 : sum->always_copy_delta += new_always_copy_delta;
2122 : 11931 : return sum;
2123 : : }
2124 : :
2125 : : /* Record information about what modifications to call arguments have already
2126 : : been done by clone materialization into a summary of an edge describing the
2127 : : call in this clone and all its clones. NEW_INDEX_MAP, NEW_PT_MAP and
2128 : : NEW_ALWAYS_COPY_DELTA have the same meaning as record_argument_state_1.
2129 : :
2130 : : In order to associate the info with the right edge summaries, we need
2131 : : address of the ORIG_STMT in the function from which we are cloning (because
2132 : : the edges have not yet been re-assigned to the new statement that has just
2133 : : been created) and ID, the structure governing function body copying. */
2134 : :
2135 : : static void
2136 : 11931 : record_argument_state (copy_body_data *id, gimple *orig_stmt,
2137 : : const vec<int> &new_index_map,
2138 : : const vec<pass_through_split_map> &new_pt_map,
2139 : : int new_always_copy_delta)
2140 : : {
2141 : 11931 : if (!ipa_edge_modifications)
2142 : 2312 : ipa_edge_modifications = new ipa_edge_modification_sum (symtab);
2143 : :
2144 : 11931 : struct cgraph_node *this_node = id->dst_node;
2145 : 11931 : ipa_edge_modification_info *first_sum = NULL;
2146 : 11931 : cgraph_edge *cs = this_node->get_edge (orig_stmt);
2147 : 11931 : if (cs)
2148 : 11931 : first_sum = record_argument_state_1 (cs, new_index_map, new_pt_map,
2149 : : new_always_copy_delta);
2150 : : else
2151 : 0 : gcc_assert (this_node->clones);
2152 : :
2153 : 11931 : if (!this_node->clones)
2154 : : return;
2155 : 20712 : for (cgraph_node *subclone = this_node->clones; subclone != this_node;)
2156 : : {
2157 : 17348 : cs = subclone->get_edge (orig_stmt);
2158 : 17348 : if (cs)
2159 : : {
2160 : 17348 : if (!first_sum)
2161 : 0 : first_sum = record_argument_state_1 (cs, new_index_map, new_pt_map,
2162 : : new_always_copy_delta);
2163 : : else
2164 : : {
2165 : 17348 : ipa_edge_modification_info *s2
2166 : 17348 : = ipa_edge_modifications->get_create (cs);
2167 : 17348 : s2->index_map.truncate (0);
2168 : 17348 : s2->index_map.safe_splice (first_sum->index_map);
2169 : 17348 : s2->pass_through_map.truncate (0);
2170 : 17348 : s2->pass_through_map.safe_splice (first_sum->pass_through_map);
2171 : 17348 : s2->always_copy_delta = first_sum->always_copy_delta;
2172 : : }
2173 : : }
2174 : : else
2175 : 0 : gcc_assert (subclone->clones);
2176 : :
2177 : 17348 : if (subclone->clones)
2178 : : subclone = subclone->clones;
2179 : 16534 : else if (subclone->next_sibling_clone)
2180 : : subclone = subclone->next_sibling_clone;
2181 : : else
2182 : : {
2183 : 8001 : while (subclone != this_node && !subclone->next_sibling_clone)
2184 : 4178 : subclone = subclone->clone_of;
2185 : 3823 : if (subclone != this_node)
2186 : 459 : subclone = subclone->next_sibling_clone;
2187 : : }
2188 : : }
2189 : : }
2190 : :
2191 : : /* If the call statement pointed at by STMT_P contains any expressions that
2192 : : need to replaced with a different one as noted by ADJUSTMENTS, do so. f the
2193 : : statement needs to be rebuilt, do so. Return true if any modifications have
2194 : : been performed. ORIG_STMT, if not NULL, is the original statement in the
2195 : : function that is being cloned from, which at this point can be used to look
2196 : : up call_graph edges.
2197 : :
2198 : : If the method is invoked as a part of IPA clone materialization and if any
2199 : : parameter split is pass-through, i.e. it applies to the functin that is
2200 : : being modified and also to the callee of the statement, replace the
2201 : : parameter passed to old callee with all of the replacement a callee might
2202 : : possibly want and record the performed argument modifications in
2203 : : ipa_edge_modifications. Likewise if any argument has already been left out
2204 : : because it is not necessary. */
2205 : :
2206 : : bool
2207 : 583465 : ipa_param_body_adjustments::modify_call_stmt (gcall **stmt_p,
2208 : : gimple *orig_stmt)
2209 : : {
2210 : 583465 : auto_vec <unsigned, 4> pass_through_args;
2211 : 583465 : auto_vec <unsigned, 4> pass_through_pbr_indices;
2212 : 583465 : auto_vec <HOST_WIDE_INT, 4> pass_through_offsets;
2213 : 583465 : gcall *stmt = *stmt_p;
2214 : 583465 : unsigned nargs = gimple_call_num_args (stmt);
2215 : 583465 : bool recreate = false;
2216 : 583465 : gcc_assert (m_sorted_replacements_p);
2217 : :
2218 : 1967324 : for (unsigned i = 0; i < gimple_call_num_args (stmt); i++)
2219 : : {
2220 : 1383859 : tree t = gimple_call_arg (stmt, i);
2221 : 1383859 : gcc_assert (TREE_CODE (t) != BIT_FIELD_REF
2222 : : && TREE_CODE (t) != IMAGPART_EXPR
2223 : : && TREE_CODE (t) != REALPART_EXPR);
2224 : :
2225 : 1383859 : if (TREE_CODE (t) == SSA_NAME
2226 : 1383859 : && m_dead_ssas.contains (t))
2227 : : recreate = true;
2228 : :
2229 : 1383859 : if (m_replacements.is_empty ())
2230 : 1378817 : continue;
2231 : :
2232 : 192478 : tree base;
2233 : 192478 : unsigned agg_arg_offset;
2234 : 192478 : if (!isra_get_ref_base_and_offset (t, &base, &agg_arg_offset))
2235 : 1 : continue;
2236 : :
2237 : 192477 : bool by_ref = false;
2238 : 192477 : if (TREE_CODE (base) == SSA_NAME)
2239 : : {
2240 : 98170 : if (!SSA_NAME_IS_DEFAULT_DEF (base))
2241 : 76255 : continue;
2242 : 21915 : base = SSA_NAME_VAR (base);
2243 : 21915 : gcc_checking_assert (base);
2244 : : by_ref = true;
2245 : : }
2246 : 116222 : if (TREE_CODE (base) != PARM_DECL)
2247 : 91544 : continue;
2248 : :
2249 : 24678 : ipa_param_body_replacement *first_rep
2250 : 24678 : = lookup_first_base_replacement (base);
2251 : 24678 : if (!first_rep)
2252 : 19636 : continue;
2253 : 5042 : unsigned first_rep_index = first_rep - m_replacements.begin ();
2254 : :
2255 : : /* We still have to distinguish between an end-use that we have to
2256 : : transform now and a pass-through, which happens in the following
2257 : : two cases. */
2258 : :
2259 : : /* TODO: After we adjust ptr_parm_has_nonarg_uses to also consider
2260 : : &MEM_REF[ssa_name + offset], we will also have to detect that case
2261 : : here. */
2262 : :
2263 : 5042 : if (TREE_CODE (t) == SSA_NAME
2264 : 4078 : && SSA_NAME_IS_DEFAULT_DEF (t)
2265 : 4078 : && SSA_NAME_VAR (t)
2266 : 9120 : && TREE_CODE (SSA_NAME_VAR (t)) == PARM_DECL)
2267 : : {
2268 : : /* This must be a by_reference pass-through. */
2269 : 4078 : recreate = true;
2270 : 4078 : gcc_assert (POINTER_TYPE_P (TREE_TYPE (t)));
2271 : 4078 : pass_through_args.safe_push (i);
2272 : 4078 : pass_through_pbr_indices.safe_push (first_rep_index);
2273 : 4078 : pass_through_offsets.safe_push (agg_arg_offset);
2274 : : }
2275 : 964 : else if (!by_ref && AGGREGATE_TYPE_P (TREE_TYPE (t)))
2276 : : {
2277 : : /* Currently IPA-SRA guarantees the aggregate access type
2278 : : exactly matches in this case. So if it does not match, it is
2279 : : a pass-through argument that will be sorted out at edge
2280 : : redirection time. */
2281 : 954 : ipa_param_body_replacement *pbr
2282 : 954 : = lookup_replacement_1 (base, agg_arg_offset);
2283 : :
2284 : 954 : if (!pbr
2285 : 954 : || (TYPE_MAIN_VARIANT (TREE_TYPE (t))
2286 : 941 : != TYPE_MAIN_VARIANT (TREE_TYPE (pbr->repl))))
2287 : : {
2288 : 933 : recreate = true;
2289 : 933 : pass_through_args.safe_push (i);
2290 : 933 : pass_through_pbr_indices.safe_push (first_rep_index);
2291 : 933 : pass_through_offsets.safe_push (agg_arg_offset);
2292 : : }
2293 : : }
2294 : : }
2295 : :
2296 : 583465 : if (!recreate)
2297 : : {
2298 : : /* No need to rebuild the statement, let's just modify arguments
2299 : : and the LHS if/as appropriate. */
2300 : : bool modified = false;
2301 : 1913207 : for (unsigned i = 0; i < nargs; i++)
2302 : : {
2303 : 1341673 : tree *t = gimple_call_arg_ptr (stmt, i);
2304 : 1341673 : modified |= modify_expression (t, true);
2305 : : }
2306 : 571534 : if (gimple_call_lhs (stmt))
2307 : : {
2308 : 202754 : tree *t = gimple_call_lhs_ptr (stmt);
2309 : 202754 : modified |= modify_expression (t, false);
2310 : : }
2311 : 571534 : return modified;
2312 : : }
2313 : :
2314 : 11931 : auto_vec<int, 16> index_map;
2315 : 11931 : auto_vec<pass_through_split_map, 4> pass_through_map;
2316 : 11931 : auto_vec<tree, 16> vargs;
2317 : 11931 : int always_copy_delta = 0;
2318 : 11931 : unsigned pt_idx = 0;
2319 : 11931 : int new_arg_idx = 0;
2320 : 54117 : for (unsigned i = 0; i < nargs; i++)
2321 : : {
2322 : 42186 : if (pt_idx < pass_through_args.length ()
2323 : 49876 : && i == pass_through_args[pt_idx])
2324 : : {
2325 : 5011 : unsigned j = pass_through_pbr_indices[pt_idx];
2326 : 5011 : unsigned agg_arg_offset = pass_through_offsets[pt_idx];
2327 : 5011 : pt_idx++;
2328 : 5011 : always_copy_delta--;
2329 : 5011 : tree base = m_replacements[j].base;
2330 : :
2331 : : /* In order to be put into SSA form, we have to push all replacements
2332 : : pertaining to this parameter as parameters to the call statement.
2333 : : Edge redirection will need to use edge summary to weed out the
2334 : : unnecessary ones. */
2335 : 5011 : unsigned repl_list_len = m_replacements.length ();
2336 : 14165 : for (; j < repl_list_len; j++)
2337 : : {
2338 : 9851 : if (m_replacements[j].base != base)
2339 : : break;
2340 : 9154 : if (m_replacements[j].unit_offset < agg_arg_offset)
2341 : 1 : continue;
2342 : 9153 : pass_through_split_map pt_map;
2343 : 9153 : pt_map.base_index = i;
2344 : 9153 : pt_map.unit_offset
2345 : 9153 : = m_replacements[j].unit_offset - agg_arg_offset;
2346 : 9153 : pt_map.new_index = new_arg_idx;
2347 : 9153 : pass_through_map.safe_push (pt_map);
2348 : 9153 : vargs.safe_push (m_replacements[j].repl);
2349 : 9153 : new_arg_idx++;
2350 : 9153 : always_copy_delta++;
2351 : : }
2352 : 5011 : index_map.safe_push (-1);
2353 : : }
2354 : : else
2355 : : {
2356 : 37175 : tree t = gimple_call_arg (stmt, i);
2357 : 37175 : if (TREE_CODE (t) == SSA_NAME
2358 : 37175 : && m_dead_ssas.contains (t))
2359 : : {
2360 : 7941 : always_copy_delta--;
2361 : 7941 : index_map.safe_push (-1);
2362 : : }
2363 : : else
2364 : : {
2365 : 29234 : modify_expression (&t, true);
2366 : 29234 : vargs.safe_push (t);
2367 : 29234 : index_map.safe_push (new_arg_idx);
2368 : 29234 : new_arg_idx++;
2369 : : }
2370 : : }
2371 : : }
2372 : :
2373 : 11931 : gcall *new_stmt = gimple_build_call_vec (gimple_call_fn (stmt), vargs);
2374 : 11931 : if (gimple_has_location (stmt))
2375 : 10679 : gimple_set_location (new_stmt, gimple_location (stmt));
2376 : 11931 : gimple_call_set_chain (new_stmt, gimple_call_chain (stmt));
2377 : 11931 : gimple_call_copy_flags (new_stmt, stmt);
2378 : 11931 : if (tree lhs = gimple_call_lhs (stmt))
2379 : : {
2380 : 9237 : modify_expression (&lhs, false);
2381 : : /* Avoid adjusting SSA_NAME_DEF_STMT of a SSA lhs, SSA names
2382 : : have not yet been remapped. */
2383 : 9237 : *gimple_call_lhs_ptr (new_stmt) = lhs;
2384 : : }
2385 : 11931 : *stmt_p = new_stmt;
2386 : :
2387 : 11931 : if (orig_stmt)
2388 : 11931 : record_argument_state (m_id, orig_stmt, index_map, pass_through_map,
2389 : : always_copy_delta);
2390 : 11931 : return true;
2391 : 595396 : }
2392 : :
2393 : : /* If the statement STMT contains any expressions that need to replaced with a
2394 : : different one as noted by ADJUSTMENTS, do so. Handle any potential type
2395 : : incompatibilities. If any conversion sttements have to be pre-pended to
2396 : : STMT, they will be added to EXTRA_STMTS. Return true iff the statement was
2397 : : modified. */
2398 : :
2399 : : bool
2400 : 3099088 : ipa_param_body_adjustments::modify_gimple_stmt (gimple **stmt,
2401 : : gimple_seq *extra_stmts,
2402 : : gimple *orig_stmt)
2403 : : {
2404 : 3099088 : bool modified = false;
2405 : 3099088 : tree *t;
2406 : :
2407 : 3099088 : switch (gimple_code (*stmt))
2408 : : {
2409 : 135769 : case GIMPLE_RETURN:
2410 : 135769 : t = gimple_return_retval_ptr (as_a <greturn *> (*stmt));
2411 : 135769 : if (m_adjustments && m_adjustments->m_skip_return)
2412 : 33150 : *t = NULL_TREE;
2413 : 102619 : else if (*t != NULL_TREE)
2414 : 55230 : modified |= modify_expression (t, true);
2415 : : break;
2416 : :
2417 : 1859960 : case GIMPLE_ASSIGN:
2418 : 1859960 : modified |= modify_assignment (*stmt, extra_stmts);
2419 : 1859960 : break;
2420 : :
2421 : 583465 : case GIMPLE_CALL:
2422 : 583465 : modified |= modify_call_stmt ((gcall **) stmt, orig_stmt);
2423 : 583465 : break;
2424 : :
2425 : 935 : case GIMPLE_ASM:
2426 : 935 : {
2427 : 935 : gasm *asm_stmt = as_a <gasm *> (*stmt);
2428 : 1961 : for (unsigned i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
2429 : : {
2430 : 1026 : t = &TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
2431 : 1026 : modified |= modify_expression (t, true);
2432 : : }
2433 : 2465 : for (unsigned i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
2434 : : {
2435 : 1530 : t = &TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
2436 : 1530 : modified |= modify_expression (t, false);
2437 : : }
2438 : : }
2439 : : break;
2440 : :
2441 : : default:
2442 : : break;
2443 : : }
2444 : 3099088 : return modified;
2445 : : }
2446 : :
2447 : :
2448 : : /* Traverse body of the current function and perform the requested adjustments
2449 : : on its statements. Return true iff the CFG has been changed. */
2450 : :
2451 : : bool
2452 : 0 : ipa_param_body_adjustments::modify_cfun_body ()
2453 : : {
2454 : 0 : bool cfg_changed = false;
2455 : 0 : basic_block bb;
2456 : :
2457 : 0 : FOR_EACH_BB_FN (bb, cfun)
2458 : : {
2459 : 0 : gimple_stmt_iterator gsi;
2460 : :
2461 : 0 : for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
2462 : : {
2463 : 0 : gphi *phi = as_a <gphi *> (gsi_stmt (gsi));
2464 : 0 : tree new_lhs, old_lhs = gimple_phi_result (phi);
2465 : 0 : new_lhs = replace_removed_params_ssa_names (old_lhs, phi);
2466 : 0 : if (new_lhs)
2467 : : {
2468 : 0 : gimple_phi_set_result (phi, new_lhs);
2469 : 0 : release_ssa_name (old_lhs);
2470 : : }
2471 : : }
2472 : :
2473 : 0 : gsi = gsi_start_bb (bb);
2474 : 0 : while (!gsi_end_p (gsi))
2475 : : {
2476 : 0 : gimple *stmt = gsi_stmt (gsi);
2477 : 0 : gimple *stmt_copy = stmt;
2478 : 0 : gimple_seq extra_stmts = NULL;
2479 : 0 : bool modified = modify_gimple_stmt (&stmt, &extra_stmts, NULL);
2480 : 0 : if (stmt != stmt_copy)
2481 : : {
2482 : 0 : gcc_checking_assert (modified);
2483 : 0 : gsi_replace (&gsi, stmt, false);
2484 : : }
2485 : 0 : if (!gimple_seq_empty_p (extra_stmts))
2486 : 0 : gsi_insert_seq_before (&gsi, extra_stmts, GSI_SAME_STMT);
2487 : :
2488 : 0 : def_operand_p defp;
2489 : 0 : ssa_op_iter iter;
2490 : 0 : FOR_EACH_SSA_DEF_OPERAND (defp, stmt, iter, SSA_OP_DEF)
2491 : : {
2492 : 0 : tree old_def = DEF_FROM_PTR (defp);
2493 : 0 : if (tree new_def = replace_removed_params_ssa_names (old_def,
2494 : : stmt))
2495 : : {
2496 : 0 : SET_DEF (defp, new_def);
2497 : 0 : release_ssa_name (old_def);
2498 : 0 : modified = true;
2499 : : }
2500 : : }
2501 : :
2502 : 0 : if (modified)
2503 : : {
2504 : 0 : update_stmt (stmt);
2505 : 0 : if (maybe_clean_eh_stmt (stmt)
2506 : 0 : && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
2507 : : cfg_changed = true;
2508 : : }
2509 : 0 : gsi_next (&gsi);
2510 : : }
2511 : : }
2512 : :
2513 : 0 : return cfg_changed;
2514 : : }
2515 : :
2516 : : /* Call gimple_debug_bind_reset_value on all debug statements describing
2517 : : gimple register parameters that are being removed or replaced. */
2518 : :
2519 : : void
2520 : 0 : ipa_param_body_adjustments::reset_debug_stmts ()
2521 : : {
2522 : 0 : int i, len;
2523 : 0 : gimple_stmt_iterator *gsip = NULL, gsi;
2524 : :
2525 : 0 : if (MAY_HAVE_DEBUG_STMTS && single_succ_p (ENTRY_BLOCK_PTR_FOR_FN (cfun)))
2526 : : {
2527 : 0 : gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
2528 : 0 : gsip = &gsi;
2529 : : }
2530 : 0 : len = m_reset_debug_decls.length ();
2531 : 0 : for (i = 0; i < len; i++)
2532 : : {
2533 : 0 : imm_use_iterator ui;
2534 : 0 : gimple *stmt;
2535 : 0 : gdebug *def_temp;
2536 : 0 : tree name, vexpr, copy = NULL_TREE;
2537 : 0 : use_operand_p use_p;
2538 : 0 : tree decl = m_reset_debug_decls[i];
2539 : :
2540 : 0 : gcc_checking_assert (is_gimple_reg (decl));
2541 : 0 : name = ssa_default_def (cfun, decl);
2542 : 0 : vexpr = NULL;
2543 : 0 : if (name)
2544 : 0 : FOR_EACH_IMM_USE_STMT (stmt, ui, name)
2545 : : {
2546 : 0 : if (gimple_clobber_p (stmt))
2547 : : {
2548 : 0 : gimple_stmt_iterator cgsi = gsi_for_stmt (stmt);
2549 : 0 : unlink_stmt_vdef (stmt);
2550 : 0 : gsi_remove (&cgsi, true);
2551 : 0 : release_defs (stmt);
2552 : 0 : continue;
2553 : 0 : }
2554 : : /* All other users must have been removed by function body
2555 : : modification. */
2556 : 0 : gcc_assert (is_gimple_debug (stmt));
2557 : 0 : if (vexpr == NULL && gsip != NULL)
2558 : : {
2559 : 0 : vexpr = build_debug_expr_decl (TREE_TYPE (name));
2560 : : /* FIXME: Is setting the mode really necessary? */
2561 : 0 : SET_DECL_MODE (vexpr, DECL_MODE (decl));
2562 : 0 : def_temp = gimple_build_debug_source_bind (vexpr, decl, NULL);
2563 : 0 : gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
2564 : : }
2565 : 0 : if (vexpr)
2566 : : {
2567 : 0 : FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
2568 : 0 : SET_USE (use_p, vexpr);
2569 : : }
2570 : : else
2571 : 0 : gimple_debug_bind_reset_value (stmt);
2572 : 0 : update_stmt (stmt);
2573 : 0 : }
2574 : : /* Create a VAR_DECL for debug info purposes. */
2575 : 0 : if (!DECL_IGNORED_P (decl))
2576 : : {
2577 : 0 : copy = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
2578 : 0 : VAR_DECL, DECL_NAME (decl),
2579 : 0 : TREE_TYPE (decl));
2580 : 0 : if (DECL_PT_UID_SET_P (decl))
2581 : 0 : SET_DECL_PT_UID (copy, DECL_PT_UID (decl));
2582 : 0 : TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
2583 : 0 : TREE_READONLY (copy) = TREE_READONLY (decl);
2584 : 0 : TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
2585 : 0 : DECL_NOT_GIMPLE_REG_P (copy) = DECL_NOT_GIMPLE_REG_P (decl);
2586 : 0 : DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (decl);
2587 : 0 : DECL_IGNORED_P (copy) = DECL_IGNORED_P (decl);
2588 : 0 : DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (decl);
2589 : 0 : DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
2590 : 0 : SET_DECL_RTL (copy, 0);
2591 : 0 : TREE_USED (copy) = 1;
2592 : 0 : DECL_CONTEXT (copy) = current_function_decl;
2593 : 0 : add_local_decl (cfun, copy);
2594 : 0 : DECL_CHAIN (copy)
2595 : 0 : = BLOCK_VARS (DECL_INITIAL (current_function_decl));
2596 : 0 : BLOCK_VARS (DECL_INITIAL (current_function_decl)) = copy;
2597 : : }
2598 : 0 : if (gsip != NULL && copy && target_for_debug_bind (decl))
2599 : : {
2600 : 0 : gcc_assert (TREE_CODE (decl) == PARM_DECL);
2601 : 0 : if (vexpr)
2602 : 0 : def_temp = gimple_build_debug_bind (copy, vexpr, NULL);
2603 : : else
2604 : 0 : def_temp = gimple_build_debug_source_bind (copy, decl,
2605 : : NULL);
2606 : 0 : gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
2607 : : }
2608 : : }
2609 : 0 : }
2610 : :
2611 : : /* Perform all necessary body changes to change signature, body and debug info
2612 : : of fun according to adjustments passed at construction. Return true if CFG
2613 : : was changed in any way. The main entry point for modification of standalone
2614 : : functions that is not part of IPA clone materialization. */
2615 : :
2616 : : bool
2617 : 0 : ipa_param_body_adjustments::perform_cfun_body_modifications ()
2618 : : {
2619 : 0 : bool cfg_changed;
2620 : 0 : modify_formal_parameters ();
2621 : 0 : cfg_changed = modify_cfun_body ();
2622 : 0 : reset_debug_stmts ();
2623 : :
2624 : 0 : return cfg_changed;
2625 : : }
2626 : :
2627 : :
2628 : : /* If there are any initialization statements that need to be emitted into
2629 : : the basic block BB right at ther start of the new function, do so. */
2630 : : void
2631 : 149691 : ipa_param_body_adjustments::append_init_stmts (basic_block bb)
2632 : : {
2633 : 149691 : gimple_stmt_iterator si = gsi_last_bb (bb);
2634 : 151006 : while (!m_split_agg_csts_inits.is_empty ())
2635 : 1315 : gsi_insert_after (&si, m_split_agg_csts_inits.pop (), GSI_NEW_STMT);
2636 : 149691 : }
2637 : :
2638 : : /* Deallocate summaries which otherwise stay alive until the end of
2639 : : compilation. */
2640 : :
2641 : : void
2642 : 260181 : ipa_edge_modifications_finalize ()
2643 : : {
2644 : 260181 : if (!ipa_edge_modifications)
2645 : : return;
2646 : 2312 : delete ipa_edge_modifications;
2647 : 2312 : ipa_edge_modifications = NULL;
2648 : : }
2649 : :
2650 : : /* Helper used to sort a vector of SSA_NAMES. */
2651 : :
2652 : : static int
2653 : 20819 : compare_ssa_versions (const void *va, const void *vb)
2654 : : {
2655 : 20819 : const_tree const a = *(const_tree const*)va;
2656 : 20819 : const_tree const b = *(const_tree const*)vb;
2657 : :
2658 : 20819 : if (SSA_NAME_VERSION (a) < SSA_NAME_VERSION (b))
2659 : : return -1;
2660 : 8906 : if (SSA_NAME_VERSION (a) > SSA_NAME_VERSION (b))
2661 : 8906 : return 1;
2662 : : return 0;
2663 : : }
2664 : :
2665 : : /* Call release_ssa_name on all elements in KILLED_SSAS in a defined order. */
2666 : :
2667 : : void
2668 : 2043752 : ipa_release_ssas_in_hash (hash_set <tree> *killed_ssas)
2669 : : {
2670 : 2043752 : auto_vec<tree, 16> ssas_to_release;
2671 : 2056307 : for (tree sn : *killed_ssas)
2672 : 12555 : ssas_to_release.safe_push (sn);
2673 : 2043752 : ssas_to_release.qsort (compare_ssa_versions);
2674 : 6143811 : for (tree sn : ssas_to_release)
2675 : 12555 : release_ssa_name (sn);
2676 : 2043752 : }
|