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