Line data Source code
1 : /* Interprocedural scalar replacement of aggregates
2 : Copyright (C) 2019-2026 Free Software Foundation, Inc.
3 : Contributed by Martin Jambor <mjambor@suse.cz>
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 : /* IPA-SRA is an interprocedural pass that removes unused function return
22 : values (turning functions returning a value which is never used into void
23 : functions) and removes unused function parameters. It can also replace an
24 : aggregate parameter by a set of other parameters representing part of the
25 : original, turning those passed by reference into new ones which pass the
26 : value directly.
27 :
28 : The pass is a true IPA one, which means that it works in three stages in
29 : order to be able to take advantage of LTO. First, summaries about functions
30 : and each calls are generated. Function summaries (often called call graph
31 : node summaries) contain mainly information about which parameters are
32 : potential transformation candidates and which bits of candidates are
33 : accessed. We differentiate between accesses done as a part of a call
34 : statement (which might be not necessary if the callee is also transformed)
35 : and others (which are mandatory). Call summaries (often called call graph
36 : edge summaries) contain information about which function formal parameters
37 : feed into which actual call arguments so that if two parameters are only
38 : used in a sum which is then passed to another function which then however
39 : does not use this parameter, all three parameters of the two functions can
40 : be eliminated. Edge summaries also have flags whether the return value is
41 : used or if it is only returned in the caller too. In LTO mode these
42 : summaries are then streamed to the object file in the compilation phase and
43 : streamed back in in the WPA analysis stage.
44 :
45 : The interprocedural analysis phase traverses the graph in topological order
46 : in two sweeps, one in each direction. First, from callees to callers for
47 : parameter removal and splitting. Each strongly-connected component is
48 : processed iteratively until the situation in it stabilizes. The pass from
49 : callers to callees is then carried out to remove unused return values in a
50 : very similar fashion.
51 :
52 : Because parameter manipulation has big implications for call redirection
53 : which is done only after all call graph nodes materialize, the
54 : transformation phase is not part of this patch but is carried out by the
55 : clone materialization and edge redirection itself, see comments in
56 : ipa-param-manipulation.h for more details. */
57 :
58 :
59 : #include "config.h"
60 : #include "system.h"
61 : #include "coretypes.h"
62 : #include "backend.h"
63 : #include "tree.h"
64 : #include "gimple.h"
65 : #include "predict.h"
66 : #include "tree-pass.h"
67 : #include "ssa.h"
68 : #include "cgraph.h"
69 : #include "gimple-pretty-print.h"
70 : #include "alias.h"
71 : #include "tree-eh.h"
72 : #include "gimple-iterator.h"
73 : #include "gimple-walk.h"
74 : #include "tree-dfa.h"
75 : #include "tree-sra.h"
76 : #include "alloc-pool.h"
77 : #include "symbol-summary.h"
78 : #include "dbgcnt.h"
79 : #include "tree-inline.h"
80 : #include "ipa-utils.h"
81 : #include "builtins.h"
82 : #include "cfganal.h"
83 : #include "tree-streamer.h"
84 : #include "internal-fn.h"
85 : #include "symtab-clones.h"
86 : #include "attribs.h"
87 : #include "sreal.h"
88 : #include "ipa-cp.h"
89 : #include "ipa-prop.h"
90 :
91 : static void ipa_sra_summarize_function (cgraph_node *);
92 :
93 : /* Bits used to track size of an aggregate in bytes interprocedurally. */
94 : #define ISRA_ARG_SIZE_LIMIT_BITS 16
95 : #define ISRA_ARG_SIZE_LIMIT (1 << ISRA_ARG_SIZE_LIMIT_BITS)
96 : /* How many parameters can feed into a call actual argument and still be
97 : tracked. */
98 : #define IPA_SRA_MAX_PARAM_FLOW_LEN 7
99 :
100 : /* Structure describing accesses to a specific portion of an aggregate
101 : parameter, as given by the offset and size. Any smaller accesses that occur
102 : within a function that fall within another access form a tree. The pass
103 : cannot analyze parameters with only partially overlapping accesses. */
104 :
105 : struct GTY(()) param_access
106 : {
107 : /* Type that a potential replacement should have. This field only has
108 : meaning in the summary building and transformation phases, when it is
109 : reconstructed from the body. Must not be touched in IPA analysis
110 : stage. */
111 : tree type;
112 :
113 : /* Alias reference type to be used in MEM_REFs when adjusting caller
114 : arguments. */
115 : tree alias_ptr_type;
116 :
117 : /* Values returned by get_ref_base_and_extent but converted to bytes and
118 : stored as unsigned ints. */
119 : unsigned unit_offset;
120 : unsigned unit_size : ISRA_ARG_SIZE_LIMIT_BITS;
121 :
122 : /* Set once we are sure that the access will really end up in a potentially
123 : transformed function - initially not set for portions of formal parameters
124 : that are only used as actual function arguments passed to callees. */
125 : unsigned certain : 1;
126 : /* Set if the access has reverse scalar storage order. */
127 : unsigned reverse : 1;
128 : };
129 :
130 : /* This structure has the same purpose as the one above and additionally it
131 : contains some fields that are only necessary in the summary generation
132 : phase. */
133 :
134 : struct gensum_param_access
135 : {
136 : /* Values returned by get_ref_base_and_extent. */
137 : HOST_WIDE_INT offset;
138 : HOST_WIDE_INT size;
139 :
140 : /* if this access has any children (in terms of the definition above), this
141 : points to the first one. */
142 : struct gensum_param_access *first_child;
143 : /* In intraprocedural SRA, pointer to the next sibling in the access tree as
144 : described above. */
145 : struct gensum_param_access *next_sibling;
146 :
147 : /* Type that a potential replacement should have. This field only has
148 : meaning in the summary building and transformation phases, when it is
149 : reconstructed from the body. Must not be touched in IPA analysis
150 : stage. */
151 : tree type;
152 : /* Alias reference type to be used in MEM_REFs when adjusting caller
153 : arguments. */
154 : tree alias_ptr_type;
155 :
156 : /* Cumulative count of all loads. */
157 : profile_count load_count;
158 : /* Have there been writes to or reads from this exact location except for as
159 : arguments to a function call that can be tracked. */
160 : bool nonarg;
161 :
162 : /* Set if the access has reverse scalar storage order. */
163 : bool reverse;
164 : };
165 :
166 : /* Summary describing a parameter in the IPA stages. */
167 :
168 : struct GTY(()) isra_param_desc
169 : {
170 : /* List of access representatives to the parameters, sorted according to
171 : their offset. */
172 : vec <param_access *, va_gc> *accesses;
173 :
174 : /* Unit size limit of total size of all replacements. */
175 : unsigned param_size_limit : ISRA_ARG_SIZE_LIMIT_BITS;
176 : /* Sum of unit sizes of all certain replacements. */
177 : unsigned size_reached : ISRA_ARG_SIZE_LIMIT_BITS;
178 : /* Minimum offset that is known to be safe to dereference because of callers
179 : pass pointers to DECLs of at least this size or because of dereferences in
180 : callers. */
181 : unsigned safe_size : ISRA_ARG_SIZE_LIMIT_BITS;
182 :
183 : /* A parameter that is used only in call arguments and can be removed if all
184 : concerned actual arguments are removed. */
185 : unsigned locally_unused : 1;
186 : /* An aggregate that is a candidate for breaking up or complete removal. */
187 : unsigned split_candidate : 1;
188 : /* Is this a parameter passing stuff by reference? */
189 : unsigned by_ref : 1;
190 : /* If set, this parameter can only be a candidate for removal if the function
191 : is going to loose its return value. */
192 : unsigned remove_only_when_retval_removed : 1;
193 : /* If set, this parameter can only be a candidate for splitting if the
194 : function is going to loose its return value. Can only be meaningfully set
195 : for by_ref parameters. */
196 : unsigned split_only_when_retval_removed : 1;
197 : /* Parameter hint set during IPA analysis when there is a caller which does
198 : not construct the argument just to pass it to calls. Only meaningful for
199 : by_ref parameters. */
200 : unsigned not_specially_constructed : 1;
201 : /* Only meaningful for by_ref parameters. If set, this parameter can only be
202 : a split candidate if all callers pass pointers that are known to point to
203 : a chunk of memory large enough to contain all accesses. */
204 : unsigned conditionally_dereferenceable : 1;
205 : /* Set when safe_size has been updated from at least one caller. */
206 : unsigned safe_size_set : 1;
207 : };
208 :
209 : /* Structure used when generating summaries that describes a parameter. */
210 :
211 : struct gensum_param_desc
212 : {
213 : /* Roots of param_accesses. */
214 : gensum_param_access *accesses;
215 : /* Number of accesses in the access tree rooted in field accesses. */
216 : unsigned access_count;
217 :
218 : /* If the below is non-zero, this is the number of uses as actual
219 : arguments. */
220 : int call_uses;
221 : /* Number of times this parameter has been directly passed to. */
222 : unsigned ptr_pt_count;
223 :
224 : /* Size limit of total size of all replacements. */
225 : unsigned param_size_limit;
226 : /* Sum of sizes of nonarg accesses. */
227 : unsigned nonarg_acc_size;
228 :
229 : /* A parameter that is used only in call arguments and can be removed if all
230 : concerned actual arguments are removed. */
231 : bool locally_unused;
232 : /* An aggregate that is a candidate for breaking up or a pointer passing data
233 : by reference that is a candidate for being converted to a set of
234 : parameters passing those data by value. */
235 : bool split_candidate;
236 : /* Is this a parameter passing stuff by reference (either a pointer or a
237 : source language reference type)? */
238 : bool by_ref;
239 : /* If this parameter passes stuff by reference, can it be safely dereferenced
240 : without performing further checks (for example because it is a
241 : REFERENCE_TYPE)? */
242 : bool safe_ref;
243 : /* If set, this parameter can only be a candidate for removal if the function
244 : is going to loose its return value. */
245 : bool remove_only_when_retval_removed;
246 : /* If set, this parameter can only be a candidate for splitting if the
247 : function is going to loose its return value. Can only be meaningfully set
248 : for by_ref parameters. */
249 : bool split_only_when_retval_removed;
250 : /* Only meaningful for by_ref parameters. If set, this parameter can only be
251 : a split candidate if all callers pass pointers that are known to point to
252 : a chunk of memory large enough to contain all accesses. */
253 : bool conditionally_dereferenceable;
254 :
255 : /* The number of this parameter as they are ordered in function decl. */
256 : int param_number;
257 : /* For parameters passing data by reference, this is parameter index to
258 : compute indices to bb_dereferences. */
259 : int deref_index;
260 : };
261 :
262 : /* Properly deallocate accesses of DESC. TODO: Since this data structure is
263 : allocated in GC memory, this is not necessary and we can consider removing
264 : the function. */
265 :
266 : static void
267 2779601 : free_param_decl_accesses (isra_param_desc *desc)
268 : {
269 2779601 : unsigned len = vec_safe_length (desc->accesses);
270 3371511 : for (unsigned i = 0; i < len; ++i)
271 591910 : ggc_free ((*desc->accesses)[i]);
272 2779601 : vec_free (desc->accesses);
273 2779601 : }
274 :
275 : /* Class used to convey information about functions from the
276 : intra-procedural analysis stage to inter-procedural one. */
277 :
278 : class GTY((for_user)) isra_func_summary
279 : {
280 : public:
281 : /* initialize the object. */
282 :
283 1195460 : isra_func_summary ()
284 1195460 : : m_parameters (NULL), m_candidate (false), m_returns_value (false),
285 1195460 : m_return_ignored (false), m_queued (false)
286 : {}
287 :
288 : /* Destroy m_parameters. */
289 :
290 : ~isra_func_summary ();
291 :
292 : /* Mark the function as not a candidate for any IPA-SRA transformation.
293 : Return true if it was a candidate until now. */
294 :
295 : bool zap ();
296 :
297 : /* Vector of parameter descriptors corresponding to the function being
298 : analyzed. */
299 : vec<isra_param_desc, va_gc> *m_parameters;
300 :
301 : /* Whether the node is even a candidate for any IPA-SRA transformation at
302 : all. */
303 : unsigned m_candidate : 1;
304 :
305 : /* Whether the original function returns any value. */
306 : unsigned m_returns_value : 1;
307 :
308 : /* Set to true if all call statements do not actually use the returned
309 : value. */
310 :
311 : unsigned m_return_ignored : 1;
312 :
313 : /* Whether the node is already queued in IPA SRA stack during processing of
314 : call graphs SCCs. */
315 :
316 : unsigned m_queued : 1;
317 : };
318 :
319 : /* Deallocate the memory pointed to by isra_func_summary. TODO: Since this
320 : data structure is allocated in GC memory, this is not necessary and we can
321 : consider removing the destructor. */
322 :
323 1195459 : isra_func_summary::~isra_func_summary ()
324 : {
325 1195459 : unsigned len = vec_safe_length (m_parameters);
326 2463722 : for (unsigned i = 0; i < len; ++i)
327 1268263 : free_param_decl_accesses (&(*m_parameters)[i]);
328 1195459 : vec_free (m_parameters);
329 1195459 : }
330 :
331 : /* Mark the function as not a candidate for any IPA-SRA transformation. Return
332 : true if it was a candidate until now. */
333 :
334 : bool
335 656940 : isra_func_summary::zap ()
336 : {
337 656940 : bool ret = m_candidate;
338 656940 : m_candidate = false;
339 :
340 : /* TODO: see the destructor above. */
341 656940 : unsigned len = vec_safe_length (m_parameters);
342 2168278 : for (unsigned i = 0; i < len; ++i)
343 1511338 : free_param_decl_accesses (&(*m_parameters)[i]);
344 656940 : vec_free (m_parameters);
345 :
346 656940 : return ret;
347 : }
348 :
349 : /* Structure to describe which formal parameters feed into a particular actual
350 : argument. */
351 :
352 : struct isra_param_flow
353 : {
354 : /* Number of elements in array inputs that contain valid data. */
355 : char length;
356 : /* Indices of formal parameters that feed into the described actual argument.
357 : If aggregate_pass_through or pointer_pass_through below are true, it must
358 : contain exactly one element which is passed through from a formal
359 : parameter if the given number. Otherwise, the array contains indices of
360 : callee's formal parameters which are used to calculate value of this
361 : actual argument. */
362 : unsigned char inputs[IPA_SRA_MAX_PARAM_FLOW_LEN];
363 :
364 : /* Offset within the formal parameter. */
365 : unsigned unit_offset;
366 : /* When aggregate_pass_through is set, this is the size of the portion of an
367 : aggregate formal parameter that is being passed. Otherwise, this is size
368 : of pointed to memory that is known to be valid be dereferenced. */
369 : unsigned unit_size : ISRA_ARG_SIZE_LIMIT_BITS;
370 :
371 : /* True when the value of this actual argument is a portion of a formal
372 : parameter. */
373 : unsigned aggregate_pass_through : 1;
374 : /* True when the value of this actual copy is a verbatim pass through of an
375 : obtained pointer. */
376 : unsigned pointer_pass_through : 1;
377 : /* True when it is safe to copy access candidates here from the callee, which
378 : would mean introducing dereferences into callers of the caller. */
379 : unsigned safe_to_import_accesses : 1;
380 : /* True when the passed value is an address of a structure that has been
381 : constructed in the caller just to be passed by reference to functions
382 : (i.e. is never read). */
383 : unsigned constructed_for_calls : 1;
384 : };
385 :
386 : /* Structure used to convey information about calls from the intra-procedural
387 : analysis stage to inter-procedural one. */
388 :
389 6022617 : class isra_call_summary
390 : {
391 : public:
392 6022617 : isra_call_summary ()
393 0 : : m_arg_flow (), m_return_ignored (false), m_return_returned (false),
394 0 : m_bit_aligned_arg (false), m_before_any_store (false)
395 : {}
396 :
397 : void init_inputs (unsigned arg_count);
398 : void dump (FILE *f);
399 :
400 : /* Information about what formal parameters of the caller are used to compute
401 : individual actual arguments of this call. */
402 : auto_vec <isra_param_flow> m_arg_flow;
403 :
404 : /* Set to true if the call statement does not have a LHS. */
405 : unsigned m_return_ignored : 1;
406 :
407 : /* Set to true if the LHS of call statement is only used to construct the
408 : return value of the caller. */
409 : unsigned m_return_returned : 1;
410 :
411 : /* Set when any of the call arguments are not byte-aligned. */
412 : unsigned m_bit_aligned_arg : 1;
413 :
414 : /* Set to true if the call happend before any (other) store to memory in the
415 : caller. */
416 : unsigned m_before_any_store : 1;
417 : };
418 :
419 : /* Class to manage function summaries. */
420 :
421 : class GTY((user)) ipa_sra_function_summaries
422 : : public function_summary <isra_func_summary *>
423 : {
424 : public:
425 134950 : ipa_sra_function_summaries (symbol_table *table, bool ggc):
426 269900 : function_summary<isra_func_summary *> (table, ggc) { }
427 :
428 : void duplicate (cgraph_node *, cgraph_node *,
429 : isra_func_summary *old_sum,
430 : isra_func_summary *new_sum) final override;
431 : void insert (cgraph_node *, isra_func_summary *) final override;
432 : };
433 :
434 : /* Hook that is called by summary when a node is duplicated. */
435 :
436 : void
437 128870 : ipa_sra_function_summaries::duplicate (cgraph_node *, cgraph_node *,
438 : isra_func_summary *old_sum,
439 : isra_func_summary *new_sum)
440 : {
441 : /* TODO: Somehow stop copying when ISRA is doing the cloning, it is
442 : useless. */
443 128870 : new_sum->m_candidate = old_sum->m_candidate;
444 128870 : new_sum->m_returns_value = old_sum->m_returns_value;
445 128870 : new_sum->m_return_ignored = old_sum->m_return_ignored;
446 128870 : gcc_assert (!old_sum->m_queued);
447 128870 : new_sum->m_queued = false;
448 :
449 128870 : unsigned param_count = vec_safe_length (old_sum->m_parameters);
450 128010 : if (!param_count)
451 : return;
452 128010 : vec_safe_reserve_exact (new_sum->m_parameters, param_count);
453 128010 : new_sum->m_parameters->quick_grow_cleared (param_count);
454 494266 : for (unsigned i = 0; i < param_count; i++)
455 : {
456 366256 : isra_param_desc *s = &(*old_sum->m_parameters)[i];
457 366256 : isra_param_desc *d = &(*new_sum->m_parameters)[i];
458 :
459 366256 : d->param_size_limit = s->param_size_limit;
460 366256 : d->size_reached = s->size_reached;
461 366256 : d->safe_size = s->safe_size;
462 366256 : d->locally_unused = s->locally_unused;
463 366256 : d->split_candidate = s->split_candidate;
464 366256 : d->by_ref = s->by_ref;
465 366256 : d->remove_only_when_retval_removed = s->remove_only_when_retval_removed;
466 366256 : d->split_only_when_retval_removed = s->split_only_when_retval_removed;
467 366256 : d->not_specially_constructed = s->not_specially_constructed;
468 366256 : d->conditionally_dereferenceable = s->conditionally_dereferenceable;
469 366256 : d->safe_size_set = s->safe_size_set;
470 :
471 366256 : unsigned acc_count = vec_safe_length (s->accesses);
472 366256 : vec_safe_reserve_exact (d->accesses, acc_count);
473 517167 : for (unsigned j = 0; j < acc_count; j++)
474 : {
475 150911 : param_access *from = (*s->accesses)[j];
476 150911 : param_access *to = ggc_cleared_alloc<param_access> ();
477 150911 : to->type = from->type;
478 150911 : to->alias_ptr_type = from->alias_ptr_type;
479 150911 : to->unit_offset = from->unit_offset;
480 150911 : to->unit_size = from->unit_size;
481 150911 : to->certain = from->certain;
482 150911 : to->reverse = from->reverse;
483 150911 : d->accesses->quick_push (to);
484 : }
485 : }
486 : }
487 :
488 : /* Pointer to the pass function summary holder. */
489 :
490 : static GTY(()) ipa_sra_function_summaries *func_sums;
491 :
492 : /* Hook that is called by summary when new node appears. */
493 :
494 : void
495 18046 : ipa_sra_function_summaries::insert (cgraph_node *node, isra_func_summary *)
496 : {
497 18046 : if (opt_for_fn (node->decl, flag_ipa_sra))
498 : {
499 18046 : push_cfun (DECL_STRUCT_FUNCTION (node->decl));
500 18046 : ipa_sra_summarize_function (node);
501 18046 : pop_cfun ();
502 : }
503 : else
504 0 : func_sums->remove (node);
505 18046 : }
506 :
507 : /* Class to manage call summaries. */
508 :
509 : class ipa_sra_call_summaries: public call_summary <isra_call_summary *>
510 : {
511 : public:
512 134950 : ipa_sra_call_summaries (symbol_table *table):
513 269900 : call_summary<isra_call_summary *> (table) { }
514 :
515 : /* Duplicate info when an edge is cloned. */
516 : void duplicate (cgraph_edge *, cgraph_edge *,
517 : isra_call_summary *old_sum,
518 : isra_call_summary *new_sum) final override;
519 : };
520 :
521 : static ipa_sra_call_summaries *call_sums;
522 :
523 :
524 : /* Initialize m_arg_flow of a particular instance of isra_call_summary.
525 : ARG_COUNT is the number of actual arguments passed. */
526 :
527 : void
528 6925963 : isra_call_summary::init_inputs (unsigned arg_count)
529 : {
530 6925963 : if (arg_count == 0)
531 : {
532 352354 : gcc_checking_assert (m_arg_flow.length () == 0);
533 : return;
534 : }
535 6573609 : if (m_arg_flow.length () == 0)
536 : {
537 3238191 : m_arg_flow.reserve_exact (arg_count);
538 3238191 : m_arg_flow.quick_grow_cleared (arg_count);
539 : }
540 : else
541 3335418 : gcc_checking_assert (arg_count == m_arg_flow.length ());
542 : }
543 :
544 : /* Dump all information in call summary to F. */
545 :
546 : void
547 180 : isra_call_summary::dump (FILE *f)
548 : {
549 180 : if (m_return_ignored)
550 128 : fprintf (f, " return value ignored\n");
551 180 : if (m_return_returned)
552 38 : fprintf (f, " return value used only to compute caller return value\n");
553 180 : if (m_before_any_store)
554 17 : fprintf (f, " happens before any store to memory\n");
555 409 : for (unsigned i = 0; i < m_arg_flow.length (); i++)
556 : {
557 229 : fprintf (f, " Parameter %u:\n", i);
558 229 : isra_param_flow *ipf = &m_arg_flow[i];
559 :
560 229 : if (ipf->length)
561 : {
562 158 : bool first = true;
563 158 : fprintf (f, " Scalar param sources: ");
564 319 : for (int j = 0; j < ipf->length; j++)
565 : {
566 161 : if (!first)
567 3 : fprintf (f, ", ");
568 : else
569 : first = false;
570 161 : fprintf (f, "%i", (int) ipf->inputs[j]);
571 : }
572 158 : fprintf (f, "\n");
573 : }
574 229 : if (ipf->aggregate_pass_through)
575 12 : fprintf (f, " Aggregate pass through from the param given above, "
576 : "unit offset: %u , unit size: %u\n",
577 12 : ipf->unit_offset, ipf->unit_size);
578 217 : else if (ipf->unit_size > 0)
579 52 : fprintf (f, " Known dereferenceable size: %u\n", ipf->unit_size);
580 229 : if (ipf->pointer_pass_through)
581 19 : fprintf (f, " Pointer pass through from the param given above, "
582 19 : "safe_to_import_accesses: %u\n", ipf->safe_to_import_accesses);
583 229 : if (ipf->constructed_for_calls)
584 28 : fprintf (f, " Variable constructed just to be passed to "
585 : "calls.\n");
586 : }
587 180 : }
588 :
589 : /* Duplicate edge summary when an edge is cloned. */
590 :
591 : void
592 628968 : ipa_sra_call_summaries::duplicate (cgraph_edge *, cgraph_edge *,
593 : isra_call_summary *old_sum,
594 : isra_call_summary *new_sum)
595 : {
596 628968 : unsigned arg_count = old_sum->m_arg_flow.length ();
597 628968 : new_sum->init_inputs (arg_count);
598 1824708 : for (unsigned i = 0; i < arg_count; i++)
599 1195740 : new_sum->m_arg_flow[i] = old_sum->m_arg_flow[i];
600 :
601 628968 : new_sum->m_return_ignored = old_sum->m_return_ignored;
602 628968 : new_sum->m_return_returned = old_sum->m_return_returned;
603 628968 : new_sum->m_bit_aligned_arg = old_sum->m_bit_aligned_arg;
604 628968 : new_sum->m_before_any_store = old_sum->m_before_any_store;
605 628968 : }
606 :
607 :
608 : /* With all GTY stuff done, we can move to anonymous namespace. */
609 : namespace {
610 : /* Quick mapping from a decl to its param descriptor. */
611 :
612 : hash_map<tree, gensum_param_desc *> *decl2desc;
613 :
614 : /* All local DECLs ever loaded from of and of those that have their address
615 : assigned to a variable. */
616 :
617 : hash_set <tree> *loaded_decls;
618 :
619 : /* Countdown of allowed Alias Analysis steps during summary building. */
620 :
621 : int aa_walking_limit;
622 :
623 : /* This is a table in which for each basic block and parameter there is a
624 : distance (offset + size) in that parameter which is dereferenced and
625 : accessed in that BB. */
626 : HOST_WIDE_INT *bb_dereferences = NULL;
627 : /* How many by-reference parameters there are in the current function. */
628 : int unsafe_by_ref_count;
629 :
630 : /* Bitmap of BBs that can cause the function to "stop" progressing by
631 : returning, throwing externally, looping infinitely or calling a function
632 : which might abort etc.. */
633 : bitmap final_bbs;
634 :
635 : /* Obstack to allocate various small structures required only when generating
636 : summary for a function. */
637 : struct obstack gensum_obstack;
638 :
639 : /* Return false the function is apparently unsuitable for IPA-SRA based on it's
640 : attributes, return true otherwise. NODE is the cgraph node of the current
641 : function. */
642 :
643 : static bool
644 1264063 : ipa_sra_preliminary_function_checks (cgraph_node *node)
645 : {
646 1264063 : if (!node->can_change_signature)
647 : {
648 35643 : if (dump_file)
649 0 : fprintf (dump_file, "Function cannot change signature.\n");
650 35643 : return false;
651 : }
652 :
653 1228420 : if (!tree_versionable_function_p (node->decl))
654 : {
655 118092 : if (dump_file)
656 7 : fprintf (dump_file, "Function is not versionable.\n");
657 118092 : return false;
658 : }
659 :
660 1110328 : if (!opt_for_fn (node->decl, optimize)
661 1110328 : || !opt_for_fn (node->decl, flag_ipa_sra))
662 : {
663 192 : if (dump_file)
664 0 : fprintf (dump_file, "Not optimizing or IPA-SRA turned off for this "
665 : "function.\n");
666 192 : return false;
667 : }
668 :
669 1110136 : if (DECL_VIRTUAL_P (node->decl))
670 : {
671 31794 : if (dump_file)
672 0 : fprintf (dump_file, "Function is a virtual method.\n");
673 31794 : return false;
674 : }
675 :
676 1078342 : struct function *fun = DECL_STRUCT_FUNCTION (node->decl);
677 1078342 : if (fun->stdarg)
678 : {
679 124 : if (dump_file)
680 0 : fprintf (dump_file, "Function uses stdarg. \n");
681 124 : return false;
682 : }
683 :
684 1078218 : if (DECL_DISREGARD_INLINE_LIMITS (node->decl))
685 : {
686 49191 : if (dump_file)
687 0 : fprintf (dump_file, "Always inline function will be inlined "
688 : "anyway. \n");
689 49191 : return false;
690 : }
691 :
692 : return true;
693 : }
694 :
695 : /* Print access tree starting at ACCESS to F. */
696 :
697 : static void
698 69 : dump_gensum_access (FILE *f, gensum_param_access *access, unsigned indent)
699 : {
700 69 : fprintf (f, " ");
701 211 : for (unsigned i = 0; i < indent; i++)
702 142 : fprintf (f, " ");
703 69 : fprintf (f, " * Access to offset: " HOST_WIDE_INT_PRINT_DEC,
704 : access->offset);
705 69 : fprintf (f, ", size: " HOST_WIDE_INT_PRINT_DEC, access->size);
706 69 : fprintf (f, ", type: ");
707 69 : print_generic_expr (f, access->type);
708 69 : fprintf (f, ", alias_ptr_type: ");
709 69 : print_generic_expr (f, access->alias_ptr_type);
710 69 : fprintf (f, ", load_count: ");
711 69 : access->load_count.dump (f);
712 69 : fprintf (f, ", nonarg: %u, reverse: %u\n", access->nonarg, access->reverse);
713 69 : for (gensum_param_access *ch = access->first_child;
714 71 : ch;
715 2 : ch = ch->next_sibling)
716 2 : dump_gensum_access (f, ch, indent + 2);
717 69 : }
718 :
719 :
720 : /* Print access tree starting at ACCESS to F. */
721 :
722 : static void
723 152 : dump_isra_access (FILE *f, param_access *access)
724 : {
725 152 : fprintf (f, " * Access to unit offset: %u", access->unit_offset);
726 152 : fprintf (f, ", unit size: %u", access->unit_size);
727 152 : fprintf (f, ", type: ");
728 152 : print_generic_expr (f, access->type);
729 152 : fprintf (f, ", alias_ptr_type: ");
730 152 : print_generic_expr (f, access->alias_ptr_type);
731 152 : if (access->certain)
732 130 : fprintf (f, ", certain");
733 : else
734 22 : fprintf (f, ", not certain");
735 152 : if (access->reverse)
736 0 : fprintf (f, ", reverse");
737 152 : fprintf (f, "\n");
738 152 : }
739 :
740 : /* Dump access tree starting at ACCESS to stderr. */
741 :
742 : DEBUG_FUNCTION void
743 0 : debug_isra_access (param_access *access)
744 : {
745 0 : dump_isra_access (stderr, access);
746 0 : }
747 :
748 : /* Dump DESC to F. */
749 :
750 : static void
751 332 : dump_gensum_param_descriptor (FILE *f, gensum_param_desc *desc)
752 : {
753 332 : if (desc->locally_unused)
754 166 : fprintf (f, " unused with %i call_uses%s\n", desc->call_uses,
755 166 : desc->remove_only_when_retval_removed ?
756 : " remove_only_when_retval_removed" : "");
757 332 : if (!desc->split_candidate)
758 : {
759 244 : fprintf (f, " not a candidate\n");
760 244 : return;
761 : }
762 88 : if (desc->by_ref)
763 73 : fprintf (f, " %s%s%s by_ref with %u pass throughs\n",
764 73 : desc->safe_ref ? "safe" : "unsafe",
765 73 : desc->conditionally_dereferenceable
766 : ? " conditionally_dereferenceable" : "",
767 73 : desc->split_only_when_retval_removed
768 : ? " split_only_when_retval_removed" : "",
769 : desc->ptr_pt_count);
770 :
771 155 : for (gensum_param_access *acc = desc->accesses; acc; acc = acc->next_sibling)
772 67 : dump_gensum_access (f, acc, 2);
773 : }
774 :
775 : /* Dump all parameter descriptors in IFS, assuming it describes FNDECL, to
776 : F. */
777 :
778 : static void
779 135 : dump_gensum_param_descriptors (FILE *f, tree fndecl,
780 : vec<gensum_param_desc> *param_descriptions)
781 : {
782 135 : tree parm = DECL_ARGUMENTS (fndecl);
783 135 : for (unsigned i = 0;
784 467 : i < param_descriptions->length ();
785 332 : ++i, parm = DECL_CHAIN (parm))
786 : {
787 332 : fprintf (f, " Descriptor for parameter %i ", i);
788 332 : print_generic_expr (f, parm, TDF_UID);
789 332 : fprintf (f, "\n");
790 332 : dump_gensum_param_descriptor (f, &(*param_descriptions)[i]);
791 : }
792 135 : }
793 :
794 :
795 : /* Dump DESC to F. If HINTS is true, also dump IPA-analysis computed
796 : hints. */
797 :
798 : static void
799 646 : dump_isra_param_descriptor (FILE *f, isra_param_desc *desc, bool hints)
800 : {
801 646 : if (desc->locally_unused)
802 : {
803 335 : fprintf (f, " (locally) unused\n");
804 : }
805 646 : if (!desc->split_candidate)
806 : {
807 471 : fprintf (f, " not a candidate for splitting");
808 471 : if (hints && desc->by_ref && desc->safe_size_set)
809 9 : fprintf (f, ", safe_size: %u", (unsigned) desc->safe_size);
810 471 : fprintf (f, "\n");
811 471 : return;
812 : }
813 350 : fprintf (f, " param_size_limit: %u, size_reached: %u%s",
814 175 : desc->param_size_limit, desc->size_reached,
815 175 : desc->by_ref ? ", by_ref" : "");
816 175 : if (desc->remove_only_when_retval_removed)
817 12 : fprintf (f, ", remove_only_when_retval_removed");
818 175 : if (desc->split_only_when_retval_removed)
819 4 : fprintf (f, ", split_only_when_retval_removed");
820 175 : if (desc->by_ref && desc->conditionally_dereferenceable)
821 33 : fprintf (f, ", conditionally_dereferenceable");
822 175 : if (hints)
823 : {
824 6 : if (desc->by_ref && !desc->not_specially_constructed)
825 3 : fprintf (f, ", args_specially_constructed");
826 6 : if (desc->by_ref && desc->safe_size_set)
827 5 : fprintf (f, ", safe_size: %u", (unsigned) desc->safe_size);
828 : }
829 175 : fprintf (f, "\n");
830 :
831 327 : for (unsigned i = 0; i < vec_safe_length (desc->accesses); ++i)
832 : {
833 152 : param_access *access = (*desc->accesses)[i];
834 152 : dump_isra_access (f, access);
835 : }
836 : }
837 :
838 : /* Dump all parameter descriptors in IFS, assuming it describes FNDECL, to F.
839 : If HINTS is true, also dump IPA-analysis computed hints. */
840 :
841 : static void
842 135 : dump_isra_param_descriptors (FILE *f, tree fndecl, isra_func_summary *ifs,
843 : bool hints)
844 : {
845 135 : tree parm = DECL_ARGUMENTS (fndecl);
846 135 : if (!ifs->m_parameters)
847 : {
848 0 : fprintf (f, " parameter descriptors not available\n");
849 0 : return;
850 : }
851 :
852 : for (unsigned i = 0;
853 467 : i < ifs->m_parameters->length ();
854 332 : ++i, parm = DECL_CHAIN (parm))
855 : {
856 332 : fprintf (f, " Descriptor for parameter %i ", i);
857 332 : print_generic_expr (f, parm, TDF_UID);
858 332 : fprintf (f, "\n");
859 332 : dump_isra_param_descriptor (f, &(*ifs->m_parameters)[i], hints);
860 : }
861 : }
862 :
863 : /* Add SRC to inputs of PARAM_FLOW, unless it would exceed storage. If the
864 : function fails return false, otherwise return true. SRC must fit into an
865 : unsigned char. Used for purposes of transitive unused parameter
866 : removal. */
867 :
868 : static bool
869 1321225 : add_src_to_param_flow (isra_param_flow *param_flow, int src)
870 : {
871 1321225 : gcc_checking_assert (src >= 0 && src <= UCHAR_MAX);
872 1321225 : if (param_flow->length == IPA_SRA_MAX_PARAM_FLOW_LEN)
873 : return false;
874 :
875 1321222 : param_flow->inputs[(int) param_flow->length] = src;
876 1321222 : param_flow->length++;
877 1321222 : return true;
878 : }
879 :
880 : /* Add a SRC to the inputs of PARAM_FLOW unless it is already there and assert
881 : it is the only input. Used for purposes of transitive parameter
882 : splitting. */
883 :
884 : static void
885 787611 : set_single_param_flow_source (isra_param_flow *param_flow, int src)
886 : {
887 787611 : gcc_checking_assert (src >= 0 && src <= UCHAR_MAX);
888 787611 : if (param_flow->length == 0)
889 : {
890 122202 : param_flow->inputs[0] = src;
891 122202 : param_flow->length = 1;
892 : }
893 665409 : else if (param_flow->length == 1)
894 665409 : gcc_assert (param_flow->inputs[0] == src);
895 : else
896 0 : gcc_unreachable ();
897 787611 : }
898 :
899 : /* Assert that there is only a single value in PARAM_FLOW's inputs and return
900 : it. */
901 :
902 : static unsigned
903 1287590 : get_single_param_flow_source (const isra_param_flow *param_flow)
904 : {
905 1287590 : gcc_assert (param_flow->length == 1);
906 1287590 : return param_flow->inputs[0];
907 : }
908 :
909 : /* Inspect all uses of NAME and simple arithmetic calculations involving NAME
910 : in FUN represented with NODE and return a negative number if any of them is
911 : used for something else than either an actual call argument, simple return,
912 : simple arithmetic operation or debug statement. If there are no such uses,
913 : return the number of actual arguments that this parameter eventually feeds
914 : to (or zero if there is none). If there are any simple return uses, set
915 : DESC->remove_only_when_retval_removed. For any such parameter, mark
916 : PARM_NUM as one of its sources. ANALYZED is a bitmap that tracks which SSA
917 : names we have already started investigating. */
918 :
919 : static int
920 3387351 : isra_track_scalar_value_uses (function *fun, cgraph_node *node, tree name,
921 : int parm_num, bitmap analyzed,
922 : gensum_param_desc *desc)
923 : {
924 3387351 : int res = 0;
925 3387351 : imm_use_iterator imm_iter;
926 3387351 : gimple *stmt;
927 :
928 10348651 : FOR_EACH_IMM_USE_STMT (stmt, imm_iter, name)
929 : {
930 5206080 : if (is_gimple_debug (stmt)
931 5206080 : || gimple_clobber_p (stmt))
932 864953 : continue;
933 :
934 : /* TODO: We could handle at least const builtin functions like arithmetic
935 : operations below. */
936 4341127 : if (is_gimple_call (stmt))
937 : {
938 1333871 : int all_uses = 0;
939 1333871 : use_operand_p use_p;
940 2681265 : FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
941 1347394 : all_uses++;
942 :
943 1333871 : gcall *call = as_a <gcall *> (stmt);
944 1333871 : unsigned arg_count;
945 1333871 : if (gimple_call_internal_p (call)
946 1333871 : || (arg_count = gimple_call_num_args (call)) == 0)
947 : {
948 : res = -1;
949 : break;
950 : }
951 :
952 1329133 : cgraph_edge *cs = node->get_edge (stmt);
953 1329133 : gcc_checking_assert (cs);
954 1329133 : isra_call_summary *csum = call_sums->get_create (cs);
955 1329133 : csum->init_inputs (arg_count);
956 :
957 1329133 : int simple_uses = 0;
958 6048543 : for (unsigned i = 0; i < arg_count; i++)
959 4719413 : if (gimple_call_arg (call, i) == name)
960 : {
961 1321225 : if (!add_src_to_param_flow (&csum->m_arg_flow[i], parm_num))
962 : {
963 : simple_uses = -1;
964 : break;
965 : }
966 1321222 : simple_uses++;
967 : }
968 :
969 1329133 : if (simple_uses < 0
970 1329133 : || all_uses != simple_uses)
971 : {
972 : res = -1;
973 : break;
974 : }
975 1307946 : res += all_uses;
976 : }
977 3007256 : else if (!stmt_unremovable_because_of_non_call_eh_p (fun, stmt)
978 3007256 : && ((is_gimple_assign (stmt) && !gimple_has_volatile_ops (stmt))
979 677663 : || gimple_code (stmt) == GIMPLE_PHI))
980 : {
981 2398890 : tree lhs;
982 2398890 : if (gimple_code (stmt) == GIMPLE_PHI)
983 176584 : lhs = gimple_phi_result (stmt);
984 : else
985 2222306 : lhs = gimple_assign_lhs (stmt);
986 :
987 2398890 : if (TREE_CODE (lhs) != SSA_NAME)
988 : {
989 : res = -1;
990 : break;
991 : }
992 2001621 : gcc_assert (!gimple_vdef (stmt));
993 2001621 : if (bitmap_set_bit (analyzed, SSA_NAME_VERSION (lhs)))
994 : {
995 1908041 : int tmp = isra_track_scalar_value_uses (fun, node, lhs, parm_num,
996 : analyzed, desc);
997 1908041 : if (tmp < 0)
998 : {
999 : res = tmp;
1000 : break;
1001 : }
1002 1139674 : res += tmp;
1003 : }
1004 : }
1005 608366 : else if (greturn *gr = dyn_cast<greturn *>(stmt))
1006 : {
1007 167796 : tree rv = gimple_return_retval (gr);
1008 167796 : if (rv != name)
1009 : {
1010 : res = -1;
1011 : break;
1012 : }
1013 167796 : desc->remove_only_when_retval_removed = true;
1014 : }
1015 : else
1016 : {
1017 : res = -1;
1018 : break;
1019 : }
1020 3387351 : }
1021 3387351 : return res;
1022 : }
1023 :
1024 : /* Inspect all uses of PARM, which must be a gimple register, in FUN (which is
1025 : also described by NODE) and simple arithmetic calculations involving PARM
1026 : and return false if any of them is used for something else than either an
1027 : actual call argument, simple return, simple arithmetic operation or debug
1028 : statement. If there are no such uses, return true and store the number of
1029 : actual arguments that this parameter eventually feeds to (or zero if there
1030 : is none) to DESC->call_uses and set DESC->remove_only_when_retval_removed if
1031 : there are any uses in return statemens. For any such parameter, mark
1032 : PARM_NUM as one of its sources.
1033 :
1034 : This function is similar to ptr_parm_has_nonarg_uses but its results are
1035 : meant for unused parameter removal, as opposed to splitting of parameters
1036 : passed by reference or converting them to passed by value. */
1037 :
1038 : static bool
1039 2173458 : isra_track_scalar_param_local_uses (function *fun, cgraph_node *node, tree parm,
1040 : int parm_num, gensum_param_desc *desc)
1041 : {
1042 2173458 : gcc_checking_assert (is_gimple_reg (parm));
1043 :
1044 2173458 : tree name = ssa_default_def (fun, parm);
1045 2173458 : if (!name || has_zero_uses (name))
1046 : {
1047 694148 : desc->call_uses = 0;
1048 694148 : return false;
1049 : }
1050 :
1051 : /* Edge summaries can only handle callers with fewer than 256 parameters. */
1052 1479310 : if (parm_num > UCHAR_MAX)
1053 : return true;
1054 :
1055 1479310 : bitmap analyzed = BITMAP_ALLOC (NULL);
1056 1479310 : int call_uses = isra_track_scalar_value_uses (fun, node, name, parm_num,
1057 : analyzed, desc);
1058 1479310 : BITMAP_FREE (analyzed);
1059 1479310 : if (call_uses < 0)
1060 : return true;
1061 615546 : desc->call_uses = call_uses;
1062 615546 : return false;
1063 : }
1064 :
1065 : /* Scan immediate uses of a default definition SSA name of a parameter PARM and
1066 : examine whether there are any nonarg uses that are not actual arguments or
1067 : otherwise infeasible uses. If so, return true, otherwise return false.
1068 : Create pass-through IPA flow records for any direct uses as argument calls
1069 : and if returning false, store their number into DESC->ptr_pt_count. If
1070 : removal of return value would still allow splitting, return true but set
1071 : DESC->split_only_when_retval_removed. NODE and FUN must represent the
1072 : function that is currently analyzed, PARM_NUM must be the index of the
1073 : analyzed parameter.
1074 :
1075 : This function is similar to isra_track_scalar_param_local_uses but its
1076 : results are meant for splitting of parameters passed by reference or turning
1077 : them into bits passed by value, as opposed to generic unused parameter
1078 : removal. */
1079 :
1080 : static bool
1081 1145368 : ptr_parm_has_nonarg_uses (cgraph_node *node, function *fun, tree parm,
1082 : int parm_num, gensum_param_desc *desc)
1083 : {
1084 1145368 : imm_use_iterator ui;
1085 1145368 : gimple *stmt;
1086 1145368 : tree name = ssa_default_def (fun, parm);
1087 1145368 : bool ret = false;
1088 1145368 : unsigned pt_count = 0;
1089 :
1090 1145368 : if (!name || has_zero_uses (name))
1091 : return false;
1092 :
1093 : /* Edge summaries can only handle callers with fewer than 256 parameters. */
1094 1034494 : if (parm_num > UCHAR_MAX)
1095 : return true;
1096 :
1097 3872405 : FOR_EACH_IMM_USE_STMT (stmt, ui, name)
1098 : {
1099 2337863 : unsigned uses_ok = 0;
1100 2337863 : use_operand_p use_p;
1101 :
1102 2337863 : if (is_gimple_debug (stmt)
1103 2337863 : || gimple_clobber_p (stmt))
1104 586442 : continue;
1105 :
1106 1751421 : if (gimple_assign_single_p (stmt))
1107 : {
1108 886746 : tree rhs = gimple_assign_rhs1 (stmt);
1109 886746 : if (!TREE_THIS_VOLATILE (rhs))
1110 : {
1111 1673963 : while (handled_component_p (rhs))
1112 787293 : rhs = TREE_OPERAND (rhs, 0);
1113 886670 : if (TREE_CODE (rhs) == MEM_REF
1114 611011 : && TREE_OPERAND (rhs, 0) == name
1115 607211 : && integer_zerop (TREE_OPERAND (rhs, 1))
1116 1450914 : && types_compatible_p (TREE_TYPE (rhs),
1117 564244 : TREE_TYPE (TREE_TYPE (name))))
1118 : uses_ok++;
1119 : }
1120 : }
1121 864675 : else if (is_gimple_call (stmt))
1122 : {
1123 715750 : gcall *call = as_a <gcall *> (stmt);
1124 715750 : unsigned arg_count;
1125 715750 : if (gimple_call_internal_p (call)
1126 715750 : || (arg_count = gimple_call_num_args (call)) == 0)
1127 : {
1128 : ret = true;
1129 : break;
1130 : }
1131 :
1132 714977 : cgraph_edge *cs = node->get_edge (stmt);
1133 714977 : gcc_checking_assert (cs);
1134 714977 : isra_call_summary *csum = call_sums->get_create (cs);
1135 714977 : csum->init_inputs (arg_count);
1136 :
1137 2736342 : for (unsigned i = 0; i < arg_count; ++i)
1138 : {
1139 2021365 : tree arg = gimple_call_arg (stmt, i);
1140 :
1141 2021365 : if (arg == name)
1142 : {
1143 : /* TODO: Allow &MEM_REF[name + offset] here,
1144 : ipa_param_body_adjustments::modify_call_stmt has to be
1145 : adjusted too. */
1146 703325 : csum->m_arg_flow[i].pointer_pass_through = true;
1147 703325 : set_single_param_flow_source (&csum->m_arg_flow[i], parm_num);
1148 703325 : pt_count++;
1149 703325 : uses_ok++;
1150 703325 : continue;
1151 : }
1152 :
1153 1318040 : if (!TREE_THIS_VOLATILE (arg))
1154 : {
1155 1345319 : while (handled_component_p (arg))
1156 27279 : arg = TREE_OPERAND (arg, 0);
1157 1318040 : if (TREE_CODE (arg) == MEM_REF
1158 20977 : && TREE_OPERAND (arg, 0) == name
1159 11514 : && integer_zerop (TREE_OPERAND (arg, 1))
1160 1329552 : && types_compatible_p (TREE_TYPE (arg),
1161 11512 : TREE_TYPE (TREE_TYPE (name))))
1162 8681 : uses_ok++;
1163 : }
1164 : }
1165 : }
1166 148925 : else if (greturn *gr = dyn_cast<greturn *>(stmt))
1167 : {
1168 9384 : tree rv = gimple_return_retval (gr);
1169 9384 : if (rv == name)
1170 : {
1171 9384 : uses_ok++;
1172 : /* Analysis for feasibility of removal must have already reached
1173 : the conclusion that the flag must be set if it completed. */
1174 9384 : gcc_assert (!desc->locally_unused
1175 : || desc->remove_only_when_retval_removed);
1176 9384 : desc->split_only_when_retval_removed = true;
1177 : }
1178 : }
1179 :
1180 : /* If the number of valid uses does not match the number of
1181 : uses in this stmt there is an unhandled use. */
1182 1750648 : unsigned all_uses = 0;
1183 3508619 : FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
1184 1757971 : all_uses++;
1185 :
1186 1750648 : gcc_checking_assert (uses_ok <= all_uses);
1187 1750648 : if (uses_ok != all_uses)
1188 : {
1189 : ret = true;
1190 : break;
1191 : }
1192 1034494 : }
1193 :
1194 1034494 : desc->ptr_pt_count = pt_count;
1195 1034494 : return ret;
1196 : }
1197 :
1198 : /* Initialize vector of parameter descriptors of NODE. Return true if there
1199 : are any candidates for splitting or unused aggregate parameter removal (the
1200 : function may return false if there are candidates for removal of register
1201 : parameters). */
1202 :
1203 : static bool
1204 835709 : create_parameter_descriptors (cgraph_node *node,
1205 : vec<gensum_param_desc> *param_descriptions)
1206 : {
1207 835709 : function *fun = DECL_STRUCT_FUNCTION (node->decl);
1208 835709 : bool ret = false;
1209 :
1210 835709 : int num = 0;
1211 835709 : for (tree parm = DECL_ARGUMENTS (node->decl);
1212 3221354 : parm;
1213 2385645 : parm = DECL_CHAIN (parm), num++)
1214 : {
1215 2385645 : const char *msg;
1216 2385645 : gensum_param_desc *desc = &(*param_descriptions)[num];
1217 : /* param_descriptions vector is grown cleared in the caller. */
1218 2385645 : desc->param_number = num;
1219 2385645 : decl2desc->put (parm, desc);
1220 :
1221 2385645 : if (dump_file && (dump_flags & TDF_DETAILS))
1222 39 : print_generic_expr (dump_file, parm, TDF_UID);
1223 :
1224 2385645 : tree type = TREE_TYPE (parm);
1225 2385645 : if (TREE_THIS_VOLATILE (parm))
1226 : {
1227 51 : if (dump_file && (dump_flags & TDF_DETAILS))
1228 0 : fprintf (dump_file, " not a candidate, is volatile\n");
1229 1783339 : continue;
1230 : }
1231 2385594 : if (!is_gimple_reg_type (type) && is_va_list_type (type))
1232 : {
1233 0 : if (dump_file && (dump_flags & TDF_DETAILS))
1234 0 : fprintf (dump_file, " not a candidate, is a va_list type\n");
1235 0 : continue;
1236 : }
1237 2385594 : if (TREE_ADDRESSABLE (parm))
1238 : {
1239 36562 : if (dump_file && (dump_flags & TDF_DETAILS))
1240 0 : fprintf (dump_file, " not a candidate, is addressable\n");
1241 36562 : continue;
1242 : }
1243 2349032 : if (TREE_ADDRESSABLE (type))
1244 : {
1245 0 : if (dump_file && (dump_flags & TDF_DETAILS))
1246 0 : fprintf (dump_file, " not a candidate, type cannot be split\n");
1247 0 : continue;
1248 : }
1249 :
1250 2349032 : if (is_gimple_reg (parm)
1251 2349032 : && !isra_track_scalar_param_local_uses (fun, node, parm, num, desc))
1252 : {
1253 1309694 : desc->locally_unused = true;
1254 :
1255 1309694 : if (dump_file && (dump_flags & TDF_DETAILS))
1256 19 : fprintf (dump_file, " is a scalar with only %i call uses%s\n",
1257 : desc->call_uses,
1258 19 : desc->remove_only_when_retval_removed
1259 : ? " and return uses" : "");
1260 : }
1261 :
1262 2349032 : if (POINTER_TYPE_P (type))
1263 : {
1264 1151906 : desc->by_ref = true;
1265 1151906 : if (TREE_CODE (type) == REFERENCE_TYPE
1266 1151906 : || (num == 0
1267 558975 : && TREE_CODE (TREE_TYPE (node->decl)) == METHOD_TYPE))
1268 489886 : desc->safe_ref = true;
1269 : else
1270 662020 : desc->safe_ref = false;
1271 1151906 : type = TREE_TYPE (type);
1272 :
1273 1156925 : if (TREE_CODE (type) == FUNCTION_TYPE
1274 1151906 : || TREE_CODE (type) == METHOD_TYPE)
1275 : {
1276 5019 : if (dump_file && (dump_flags & TDF_DETAILS))
1277 0 : fprintf (dump_file, " not a candidate, reference to "
1278 : "a function\n");
1279 5019 : continue;
1280 : }
1281 1146887 : if (TYPE_VOLATILE (type))
1282 : {
1283 1128 : if (dump_file && (dump_flags & TDF_DETAILS))
1284 0 : fprintf (dump_file, " not a candidate, reference to "
1285 : "a volatile type\n");
1286 1128 : continue;
1287 : }
1288 1145759 : if (TREE_CODE (type) == ARRAY_TYPE
1289 1145759 : && TYPE_NONALIASED_COMPONENT (type))
1290 : {
1291 0 : if (dump_file && (dump_flags & TDF_DETAILS))
1292 0 : fprintf (dump_file, " not a candidate, reference to "
1293 : "a nonaliased component array\n");
1294 0 : continue;
1295 : }
1296 1145759 : if (!is_gimple_reg (parm))
1297 : {
1298 6 : if (dump_file && (dump_flags & TDF_DETAILS))
1299 0 : fprintf (dump_file, " not a candidate, a reference which is "
1300 : "not a gimple register (probably addressable)\n");
1301 6 : continue;
1302 : }
1303 1145753 : if (is_va_list_type (type))
1304 : {
1305 385 : if (dump_file && (dump_flags & TDF_DETAILS))
1306 0 : fprintf (dump_file, " not a candidate, reference to "
1307 : "a va list\n");
1308 385 : continue;
1309 : }
1310 1145368 : if (ptr_parm_has_nonarg_uses (node, fun, parm, num, desc))
1311 : {
1312 534446 : if (dump_file && (dump_flags & TDF_DETAILS))
1313 7 : fprintf (dump_file, " not a candidate, reference has "
1314 : "nonarg uses\n");
1315 534446 : continue;
1316 : }
1317 : }
1318 1197126 : else if (!AGGREGATE_TYPE_P (type))
1319 : {
1320 : /* This is in an else branch because scalars passed by reference are
1321 : still candidates to be passed by value. */
1322 1021752 : if (dump_file && (dump_flags & TDF_DETAILS))
1323 17 : fprintf (dump_file, " not a candidate, not an aggregate\n");
1324 1021752 : continue;
1325 : }
1326 :
1327 786296 : if (!COMPLETE_TYPE_P (type))
1328 : {
1329 170657 : if (dump_file && (dump_flags & TDF_DETAILS))
1330 0 : fprintf (dump_file, " not a candidate, not a complete type\n");
1331 170657 : continue;
1332 : }
1333 615639 : if (!tree_fits_uhwi_p (TYPE_SIZE (type)))
1334 : {
1335 2 : if (dump_file && (dump_flags & TDF_DETAILS))
1336 0 : fprintf (dump_file, " not a candidate, size not representable\n");
1337 2 : continue;
1338 : }
1339 615637 : unsigned HOST_WIDE_INT type_size
1340 615637 : = tree_to_uhwi (TYPE_SIZE (type)) / BITS_PER_UNIT;
1341 619876 : if (type_size == 0
1342 615637 : || type_size >= ISRA_ARG_SIZE_LIMIT)
1343 : {
1344 4239 : if (dump_file && (dump_flags & TDF_DETAILS))
1345 0 : fprintf (dump_file, " not a candidate, has zero or huge size\n");
1346 4239 : continue;
1347 : }
1348 611398 : if (type_internals_preclude_sra_p (type, &msg))
1349 : {
1350 9092 : if (dump_file && (dump_flags & TDF_DETAILS))
1351 0 : fprintf (dump_file, " not a candidate, %s\n", msg);
1352 9092 : continue;
1353 : }
1354 :
1355 602306 : if (dump_file && (dump_flags & TDF_DETAILS))
1356 15 : fprintf (dump_file, " is a candidate\n");
1357 :
1358 602306 : ret = true;
1359 602306 : desc->split_candidate = true;
1360 602306 : if (desc->by_ref && !desc->safe_ref)
1361 194837 : desc->deref_index = unsafe_by_ref_count++;
1362 : }
1363 835709 : return ret;
1364 : }
1365 :
1366 : /* Return pointer to descriptor of parameter DECL or NULL if it cannot be
1367 : found, which happens if DECL is for a static chain. */
1368 :
1369 : static gensum_param_desc *
1370 2444431 : get_gensum_param_desc (tree decl)
1371 : {
1372 2444431 : if (!decl2desc)
1373 : return NULL;
1374 2272363 : gcc_checking_assert (TREE_CODE (decl) == PARM_DECL);
1375 2272363 : gensum_param_desc **slot = decl2desc->get (decl);
1376 2272363 : if (!slot)
1377 : /* This can happen for static chains which we cannot handle so far. */
1378 : return NULL;
1379 2246970 : gcc_checking_assert (*slot);
1380 : return *slot;
1381 : }
1382 :
1383 :
1384 : /* Remove parameter described by DESC from candidates for IPA-SRA splitting and
1385 : write REASON to the dump file if there is one. */
1386 :
1387 : static void
1388 163977 : disqualify_split_candidate (gensum_param_desc *desc, const char *reason)
1389 : {
1390 163977 : if (!desc->split_candidate)
1391 : return;
1392 :
1393 163948 : if (dump_file && (dump_flags & TDF_DETAILS))
1394 0 : fprintf (dump_file, "! Disqualifying parameter number %i - %s\n",
1395 : desc->param_number, reason);
1396 :
1397 163948 : desc->split_candidate = false;
1398 : }
1399 :
1400 : /* Remove DECL from candidates for IPA-SRA and write REASON to the dump file if
1401 : there is one. */
1402 :
1403 : static void
1404 177 : disqualify_split_candidate (tree decl, const char *reason)
1405 : {
1406 177 : gensum_param_desc *desc = get_gensum_param_desc (decl);
1407 177 : if (desc)
1408 29 : disqualify_split_candidate (desc, reason);
1409 177 : }
1410 :
1411 : /* Allocate a new access to DESC and fill it in with OFFSET and SIZE. But
1412 : first, check that there are not too many of them already. If so, do not
1413 : allocate anything and return NULL. */
1414 :
1415 : static gensum_param_access *
1416 434769 : allocate_access (gensum_param_desc *desc,
1417 : HOST_WIDE_INT offset, HOST_WIDE_INT size)
1418 : {
1419 434769 : if (desc->access_count
1420 434769 : == (unsigned) param_ipa_sra_max_replacements)
1421 : {
1422 0 : disqualify_split_candidate (desc, "Too many replacement candidates");
1423 0 : return NULL;
1424 : }
1425 :
1426 434769 : gensum_param_access *access
1427 434769 : = (gensum_param_access *) obstack_alloc (&gensum_obstack,
1428 : sizeof (gensum_param_access));
1429 434769 : memset (access, 0, sizeof (*access));
1430 434769 : access->offset = offset;
1431 434769 : access->size = size;
1432 434769 : access->load_count = profile_count::zero ();
1433 434769 : return access;
1434 : }
1435 :
1436 : /* In what context scan_expr_access has been called, whether it deals with a
1437 : load, a function argument, or a store. Please note that in rare
1438 : circumstances when it is not clear if the access is a load or store,
1439 : ISRA_CTX_STORE is used too. */
1440 :
1441 : enum isra_scan_context {ISRA_CTX_LOAD, ISRA_CTX_ARG, ISRA_CTX_STORE};
1442 :
1443 : /* Return an access describing memory access to the variable described by DESC
1444 : at OFFSET with SIZE in context CTX, starting at pointer to the linked list
1445 : at a certain tree level FIRST. Attempt to create it and put into the
1446 : appropriate place in the access tree if does not exist, but fail and return
1447 : NULL if there are already too many accesses, if it would create a partially
1448 : overlapping access or if an access would end up within a pre-existing
1449 : non-call access. */
1450 :
1451 : static gensum_param_access *
1452 511186 : get_access_1 (gensum_param_desc *desc, gensum_param_access **first,
1453 : HOST_WIDE_INT offset, HOST_WIDE_INT size, isra_scan_context ctx)
1454 : {
1455 521321 : gensum_param_access *access = *first, **ptr = first;
1456 :
1457 521321 : if (!access)
1458 : {
1459 : /* No pre-existing access at this level, just create it. */
1460 281760 : gensum_param_access *a = allocate_access (desc, offset, size);
1461 281760 : if (!a)
1462 : return NULL;
1463 281760 : *first = a;
1464 281760 : return *first;
1465 : }
1466 :
1467 239561 : if (access->offset >= offset + size)
1468 : {
1469 : /* We want to squeeze it in front of the very first access, just do
1470 : it. */
1471 44650 : gensum_param_access *r = allocate_access (desc, offset, size);
1472 44650 : if (!r)
1473 : return NULL;
1474 44650 : r->next_sibling = access;
1475 44650 : *first = r;
1476 44650 : return r;
1477 : }
1478 :
1479 : /* Skip all accesses that have to come before us until the next sibling is
1480 : already too far. */
1481 285519 : while (offset >= access->offset + access->size
1482 187436 : && access->next_sibling
1483 386881 : && access->next_sibling->offset < offset + size)
1484 : {
1485 90608 : ptr = &access->next_sibling;
1486 90608 : access = access->next_sibling;
1487 : }
1488 :
1489 : /* At this point we know we do not belong before access. */
1490 194911 : gcc_assert (access->offset < offset + size);
1491 :
1492 194911 : if (access->offset == offset && access->size == size)
1493 : /* We found what we were looking for. */
1494 : return access;
1495 :
1496 123241 : if (access->offset <= offset
1497 120110 : && access->offset + access->size >= offset + size)
1498 : {
1499 : /* We fit into access which is larger than us. We need to find/create
1500 : something below access. But we only allow nesting in call
1501 : arguments. */
1502 11593 : if (access->nonarg)
1503 : return NULL;
1504 :
1505 10135 : return get_access_1 (desc, &access->first_child, offset, size, ctx);
1506 : }
1507 :
1508 111648 : if (offset <= access->offset
1509 14820 : && offset + size >= access->offset + access->size)
1510 : /* We are actually bigger than access, which fully fits into us, take its
1511 : place and make all accesses fitting into it its children. */
1512 : {
1513 : /* But first, we only allow nesting in call arguments so check if that is
1514 : what we are trying to represent. */
1515 14820 : if (ctx != ISRA_CTX_ARG)
1516 : return NULL;
1517 :
1518 11531 : gensum_param_access *r = allocate_access (desc, offset, size);
1519 11531 : if (!r)
1520 : return NULL;
1521 11531 : r->first_child = access;
1522 :
1523 11531 : while (access->next_sibling
1524 20169 : && access->next_sibling->offset < offset + size)
1525 : access = access->next_sibling;
1526 11531 : if (access->offset + access->size > offset + size)
1527 : {
1528 : /* This must be a different access, which are sorted, so the
1529 : following must be true and this signals a partial overlap. */
1530 0 : gcc_assert (access->offset > offset);
1531 : return NULL;
1532 : }
1533 :
1534 11531 : r->next_sibling = access->next_sibling;
1535 11531 : access->next_sibling = NULL;
1536 11531 : *ptr = r;
1537 11531 : return r;
1538 : }
1539 :
1540 96828 : if (offset >= access->offset + access->size)
1541 : {
1542 : /* We belong after access. */
1543 96828 : gensum_param_access *r = allocate_access (desc, offset, size);
1544 96828 : if (!r)
1545 : return NULL;
1546 96828 : r->next_sibling = access->next_sibling;
1547 96828 : access->next_sibling = r;
1548 96828 : return r;
1549 : }
1550 :
1551 0 : if (offset < access->offset)
1552 : {
1553 : /* We know the following, otherwise we would have created a
1554 : super-access. */
1555 0 : gcc_checking_assert (offset + size < access->offset + access->size);
1556 : return NULL;
1557 : }
1558 :
1559 0 : if (offset + size > access->offset + access->size)
1560 : {
1561 : /* Likewise. */
1562 0 : gcc_checking_assert (offset > access->offset);
1563 : return NULL;
1564 : }
1565 :
1566 0 : gcc_unreachable ();
1567 : }
1568 :
1569 : /* Return an access describing memory access to the variable described by DESC
1570 : at OFFSET with SIZE in context CTX, mark it as used in context CTX. Attempt
1571 : to create if it does not exist, but fail and return NULL if there are
1572 : already too many accesses, if it would create a partially overlapping access
1573 : or if an access would end up in a non-call access. */
1574 :
1575 : static gensum_param_access *
1576 511186 : get_access (gensum_param_desc *desc, HOST_WIDE_INT offset, HOST_WIDE_INT size,
1577 : isra_scan_context ctx)
1578 : {
1579 511186 : gcc_checking_assert (desc->split_candidate);
1580 :
1581 511186 : gensum_param_access *access = get_access_1 (desc, &desc->accesses, offset,
1582 : size, ctx);
1583 511186 : if (!access)
1584 : {
1585 4747 : disqualify_split_candidate (desc,
1586 : "Bad access overlap or too many accesses");
1587 4747 : return NULL;
1588 : }
1589 :
1590 506439 : switch (ctx)
1591 : {
1592 13484 : case ISRA_CTX_STORE:
1593 13484 : gcc_assert (!desc->by_ref);
1594 : /* Fall-through */
1595 419232 : case ISRA_CTX_LOAD:
1596 419232 : access->nonarg = true;
1597 419232 : break;
1598 : case ISRA_CTX_ARG:
1599 : break;
1600 : }
1601 :
1602 : return access;
1603 : }
1604 :
1605 : /* Verify that parameter access tree starting with ACCESS is in good shape.
1606 : PARENT_OFFSET and PARENT_SIZE are the corresponding fields of parent of
1607 : ACCESS or zero if there is none. */
1608 :
1609 : static bool
1610 904487 : verify_access_tree_1 (gensum_param_access *access, HOST_WIDE_INT parent_offset,
1611 : HOST_WIDE_INT parent_size)
1612 : {
1613 1289673 : while (access)
1614 : {
1615 385186 : gcc_assert (access->offset >= 0 && access->size >= 0);
1616 :
1617 385186 : if (parent_size != 0)
1618 : {
1619 22806 : if (access->offset < parent_offset)
1620 : {
1621 0 : error ("Access offset before parent offset");
1622 0 : return true;
1623 : }
1624 22806 : if (access->size >= parent_size)
1625 : {
1626 0 : error ("Access size greater or equal to its parent size");
1627 0 : return true;
1628 : }
1629 22806 : if (access->offset + access->size > parent_offset + parent_size)
1630 : {
1631 0 : error ("Access terminates outside of its parent");
1632 0 : return true;
1633 : }
1634 : }
1635 :
1636 385186 : if (verify_access_tree_1 (access->first_child, access->offset,
1637 : access->size))
1638 : return true;
1639 :
1640 385186 : if (access->next_sibling
1641 129235 : && (access->next_sibling->offset < access->offset + access->size))
1642 : {
1643 0 : error ("Access overlaps with its sibling");
1644 0 : return true;
1645 : }
1646 :
1647 : access = access->next_sibling;
1648 : }
1649 : return false;
1650 : }
1651 :
1652 : /* Verify that parameter access tree starting with ACCESS is in good shape,
1653 : halt compilation and dump the tree to stderr if not. */
1654 :
1655 : DEBUG_FUNCTION void
1656 519301 : isra_verify_access_tree (gensum_param_access *access)
1657 : {
1658 519301 : if (verify_access_tree_1 (access, 0, 0))
1659 : {
1660 0 : for (; access; access = access->next_sibling)
1661 0 : dump_gensum_access (stderr, access, 2);
1662 0 : internal_error ("IPA-SRA access verification failed");
1663 : }
1664 519301 : }
1665 :
1666 :
1667 : /* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine
1668 : GIMPLE_ASM operands with memory constrains which cannot be scalarized. */
1669 :
1670 : static bool
1671 7937 : asm_visit_addr (gimple *, tree op, tree, void *)
1672 : {
1673 7937 : op = get_base_address (op);
1674 7937 : if (op
1675 7937 : && TREE_CODE (op) == PARM_DECL)
1676 177 : disqualify_split_candidate (op, "Non-scalarizable GIMPLE_ASM operand.");
1677 :
1678 7937 : return false;
1679 : }
1680 :
1681 : /* Mark a dereference of parameter identified by DESC of distance DIST in a
1682 : basic block BB, unless the BB has already been marked as a potentially
1683 : final. */
1684 :
1685 : static void
1686 240135 : mark_param_dereference (gensum_param_desc *desc, HOST_WIDE_INT dist,
1687 : basic_block bb)
1688 : {
1689 240135 : gcc_assert (desc->by_ref);
1690 240135 : gcc_checking_assert (desc->split_candidate);
1691 :
1692 240135 : if (desc->safe_ref
1693 240135 : || bitmap_bit_p (final_bbs, bb->index))
1694 214380 : return;
1695 :
1696 25755 : int idx = bb->index * unsafe_by_ref_count + desc->deref_index;
1697 25755 : if (bb_dereferences[idx] < dist)
1698 24466 : bb_dereferences[idx] = dist;
1699 : }
1700 :
1701 : /* Return true, if any potential replacements should use NEW_TYPE as opposed to
1702 : previously recorded OLD_TYPE. */
1703 :
1704 : static bool
1705 61562 : type_prevails_p (tree old_type, tree new_type)
1706 : {
1707 61562 : if (old_type == new_type)
1708 : return false;
1709 :
1710 : /* Non-aggregates are always better. */
1711 253 : if (!is_gimple_reg_type (old_type)
1712 253 : && is_gimple_reg_type (new_type))
1713 : return true;
1714 253 : if (is_gimple_reg_type (old_type)
1715 253 : && !is_gimple_reg_type (new_type))
1716 : return false;
1717 :
1718 : /* Prefer any complex or vector type over any other scalar type. */
1719 243 : if (TREE_CODE (old_type) != COMPLEX_TYPE
1720 243 : && TREE_CODE (old_type) != VECTOR_TYPE
1721 230 : && (TREE_CODE (new_type) == COMPLEX_TYPE
1722 230 : || VECTOR_TYPE_P (new_type)))
1723 : return true;
1724 243 : if ((TREE_CODE (old_type) == COMPLEX_TYPE
1725 : || VECTOR_TYPE_P (old_type))
1726 13 : && TREE_CODE (new_type) != COMPLEX_TYPE
1727 0 : && TREE_CODE (new_type) != VECTOR_TYPE)
1728 : return false;
1729 :
1730 : /* Use the integral type with the bigger precision. */
1731 243 : if (INTEGRAL_TYPE_P (old_type)
1732 12 : && INTEGRAL_TYPE_P (new_type))
1733 12 : return (TYPE_PRECISION (new_type) > TYPE_PRECISION (old_type));
1734 :
1735 : /* Attempt to disregard any integral type with non-full precision. */
1736 231 : if (INTEGRAL_TYPE_P (old_type)
1737 231 : && (TREE_INT_CST_LOW (TYPE_SIZE (old_type))
1738 0 : != TYPE_PRECISION (old_type)))
1739 : return true;
1740 231 : if (INTEGRAL_TYPE_P (new_type)
1741 231 : && (TREE_INT_CST_LOW (TYPE_SIZE (new_type))
1742 6 : != TYPE_PRECISION (new_type)))
1743 : return false;
1744 : /* Stabilize the selection. */
1745 231 : return TYPE_UID (old_type) < TYPE_UID (new_type);
1746 : }
1747 :
1748 : /* When scanning an expression which is a call argument, this structure
1749 : specifies the call and the position of the argument. */
1750 :
1751 : struct scan_call_info
1752 : {
1753 : /* Call graph edge representing the call. */
1754 : cgraph_edge *cs;
1755 : /* Total number of arguments in the call. */
1756 : unsigned argument_count;
1757 : /* Number of the actual argument being scanned. */
1758 : unsigned arg_idx;
1759 : };
1760 :
1761 : /* Record use of ACCESS which belongs to a parameter described by DESC in a
1762 : call argument described by CALL_INFO. */
1763 :
1764 : static void
1765 84286 : record_nonregister_call_use (gensum_param_desc *desc,
1766 : scan_call_info *call_info,
1767 : unsigned unit_offset, unsigned unit_size)
1768 : {
1769 84286 : isra_call_summary *csum = call_sums->get_create (call_info->cs);
1770 84286 : csum->init_inputs (call_info->argument_count);
1771 :
1772 84286 : isra_param_flow *param_flow = &csum->m_arg_flow[call_info->arg_idx];
1773 84286 : param_flow->aggregate_pass_through = true;
1774 84286 : set_single_param_flow_source (param_flow, desc->param_number);
1775 84286 : param_flow->unit_offset = unit_offset;
1776 84286 : param_flow->unit_size = unit_size;
1777 84286 : desc->call_uses++;
1778 84286 : }
1779 :
1780 : /* Callback of walk_aliased_vdefs, just mark that there was a possible
1781 : modification. */
1782 :
1783 : static bool
1784 66856 : mark_maybe_modified (ao_ref *, tree, void *data)
1785 : {
1786 66856 : bool *maybe_modified = (bool *) data;
1787 66856 : *maybe_modified = true;
1788 66856 : return true;
1789 : }
1790 :
1791 : /* Analyze expression EXPR from GIMPLE for accesses to parameters. CTX
1792 : specifies whether EXPR is used in a load, store or as an argument call. BB
1793 : must be the basic block in which expr resides. If CTX specifies call
1794 : argument context, CALL_INFO must describe that call and argument position,
1795 : otherwise it is ignored. */
1796 :
1797 : static void
1798 35699227 : scan_expr_access (tree expr, gimple *stmt, isra_scan_context ctx,
1799 : basic_block bb, scan_call_info *call_info = NULL)
1800 : {
1801 35699227 : poly_int64 poffset, psize, pmax_size;
1802 35699227 : HOST_WIDE_INT offset, size, max_size;
1803 35699227 : tree base;
1804 35699227 : bool deref = false;
1805 35699227 : bool reverse;
1806 :
1807 35699227 : if (TREE_CODE (expr) == ADDR_EXPR)
1808 : {
1809 4376821 : if (ctx == ISRA_CTX_ARG)
1810 : return;
1811 1206345 : tree t = get_base_address (TREE_OPERAND (expr, 0));
1812 1206345 : if (VAR_P (t) && !TREE_STATIC (t))
1813 239766 : loaded_decls->add (t);
1814 1206345 : return;
1815 : }
1816 31322406 : if (TREE_CODE (expr) == SSA_NAME
1817 17353078 : || CONSTANT_CLASS_P (expr))
1818 : return;
1819 :
1820 12445575 : if (TREE_CODE (expr) == BIT_FIELD_REF
1821 12445575 : || TREE_CODE (expr) == IMAGPART_EXPR
1822 12343118 : || TREE_CODE (expr) == REALPART_EXPR)
1823 155008 : expr = TREE_OPERAND (expr, 0);
1824 :
1825 12445575 : base = get_ref_base_and_extent (expr, &poffset, &psize, &pmax_size, &reverse);
1826 :
1827 12445575 : if (TREE_CODE (base) == MEM_REF)
1828 : {
1829 3947221 : tree op = TREE_OPERAND (base, 0);
1830 3947221 : if (TREE_CODE (op) != SSA_NAME
1831 3947221 : || !SSA_NAME_IS_DEFAULT_DEF (op))
1832 : return;
1833 2077237 : base = SSA_NAME_VAR (op);
1834 2077237 : if (!base)
1835 : return;
1836 : deref = true;
1837 : }
1838 8498354 : else if (VAR_P (base)
1839 7366246 : && !TREE_STATIC (base)
1840 6393953 : && (ctx == ISRA_CTX_ARG
1841 : || ctx == ISRA_CTX_LOAD))
1842 2393653 : loaded_decls->add (base);
1843 :
1844 10575591 : if (TREE_CODE (base) != PARM_DECL)
1845 : return;
1846 :
1847 2444254 : gensum_param_desc *desc = get_gensum_param_desc (base);
1848 2444254 : if (!desc || !desc->split_candidate)
1849 : return;
1850 :
1851 579330 : if (storage_order_barrier_p (expr))
1852 : {
1853 0 : disqualify_split_candidate (desc, "Encountered a storage order barrier.");
1854 0 : return;
1855 : }
1856 :
1857 579330 : if (!poffset.is_constant (&offset)
1858 579330 : || !psize.is_constant (&size)
1859 579330 : || !pmax_size.is_constant (&max_size))
1860 : {
1861 : disqualify_split_candidate (desc, "Encountered a polynomial-sized "
1862 : "access.");
1863 : return;
1864 : }
1865 579330 : if (size < 0 || size != max_size)
1866 : {
1867 6273 : disqualify_split_candidate (desc, "Encountered a variable sized access.");
1868 6273 : return;
1869 : }
1870 573057 : if (TREE_CODE (expr) == COMPONENT_REF
1871 573057 : && DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
1872 : {
1873 1354 : disqualify_split_candidate (desc, "Encountered a bit-field access.");
1874 1354 : return;
1875 : }
1876 571703 : if (offset < 0)
1877 : {
1878 4 : disqualify_split_candidate (desc, "Encountered an access at a "
1879 : "negative offset.");
1880 4 : return;
1881 : }
1882 571699 : gcc_assert ((offset % BITS_PER_UNIT) == 0);
1883 571699 : gcc_assert ((size % BITS_PER_UNIT) == 0);
1884 571699 : if ((offset / BITS_PER_UNIT) >= (UINT_MAX - ISRA_ARG_SIZE_LIMIT)
1885 571699 : || (size / BITS_PER_UNIT) >= ISRA_ARG_SIZE_LIMIT)
1886 : {
1887 0 : disqualify_split_candidate (desc, "Encountered an access with too big "
1888 : "offset or size");
1889 0 : return;
1890 : }
1891 :
1892 571699 : tree type = TREE_TYPE (expr);
1893 571699 : unsigned int exp_align = get_object_alignment (expr);
1894 :
1895 571699 : if (exp_align < TYPE_ALIGN (type))
1896 : {
1897 1356 : disqualify_split_candidate (desc, "Underaligned access.");
1898 1356 : return;
1899 : }
1900 :
1901 570343 : if (deref)
1902 : {
1903 299292 : if (!desc->by_ref)
1904 : {
1905 0 : disqualify_split_candidate (desc, "Dereferencing a non-reference.");
1906 59157 : return;
1907 : }
1908 299292 : else if (ctx == ISRA_CTX_STORE)
1909 : {
1910 0 : disqualify_split_candidate (desc, "Storing to data passed by "
1911 : "reference.");
1912 0 : return;
1913 : }
1914 :
1915 299292 : if (!aa_walking_limit)
1916 : {
1917 0 : disqualify_split_candidate (desc, "Out of alias analysis step "
1918 : "limit.");
1919 0 : return;
1920 : }
1921 :
1922 598584 : gcc_checking_assert (gimple_vuse (stmt));
1923 299292 : bool maybe_modified = false;
1924 299292 : ao_ref ar;
1925 :
1926 299292 : ao_ref_init (&ar, expr);
1927 299292 : bitmap visited = BITMAP_ALLOC (NULL);
1928 598584 : int walked = walk_aliased_vdefs (&ar, gimple_vuse (stmt),
1929 : mark_maybe_modified, &maybe_modified,
1930 : &visited, NULL, aa_walking_limit);
1931 299292 : BITMAP_FREE (visited);
1932 299292 : if (walked > 0)
1933 : {
1934 102341 : gcc_assert (aa_walking_limit > walked);
1935 102341 : aa_walking_limit = aa_walking_limit - walked;
1936 : }
1937 299292 : if (walked < 0)
1938 0 : aa_walking_limit = 0;
1939 299292 : if (maybe_modified || walked < 0)
1940 : {
1941 59157 : disqualify_split_candidate (desc, "Data passed by reference possibly "
1942 : "modified through an alias.");
1943 59157 : return;
1944 : }
1945 : else
1946 240135 : mark_param_dereference (desc, offset + size, bb);
1947 : }
1948 : else
1949 : /* Pointer parameters with direct uses should have been ruled out by
1950 : analyzing SSA default def when looking at the parameters. */
1951 271051 : gcc_assert (!desc->by_ref);
1952 :
1953 511186 : gensum_param_access *access = get_access (desc, offset, size, ctx);
1954 511186 : if (!access)
1955 : return;
1956 :
1957 506439 : if (ctx == ISRA_CTX_ARG)
1958 : {
1959 87207 : gcc_checking_assert (call_info);
1960 :
1961 87207 : if (!deref)
1962 84286 : record_nonregister_call_use (desc, call_info, offset / BITS_PER_UNIT,
1963 84286 : size / BITS_PER_UNIT);
1964 : else
1965 : /* This is not a pass-through of a pointer, this is a use like any
1966 : other. */
1967 2921 : access->nonarg = true;
1968 : }
1969 419232 : else if (ctx == ISRA_CTX_LOAD && bb->count.initialized_p ())
1970 405660 : access->load_count += bb->count;
1971 :
1972 506439 : if (!access->type)
1973 : {
1974 434769 : access->type = type;
1975 434769 : access->alias_ptr_type = reference_alias_ptr_type (expr);
1976 434769 : access->reverse = reverse;
1977 : }
1978 : else
1979 : {
1980 71670 : if (exp_align < TYPE_ALIGN (access->type))
1981 : {
1982 0 : disqualify_split_candidate (desc, "Reference has lower alignment "
1983 : "than a previous one.");
1984 0 : return;
1985 : }
1986 71670 : if (access->alias_ptr_type != reference_alias_ptr_type (expr))
1987 : {
1988 4716 : disqualify_split_candidate (desc, "Multiple alias pointer types.");
1989 4716 : return;
1990 : }
1991 66954 : if (access->reverse != reverse)
1992 : {
1993 0 : disqualify_split_candidate (desc, "Both normal and reverse "
1994 : "scalar storage order.");
1995 0 : return;
1996 : }
1997 66954 : if (!deref
1998 52134 : && (AGGREGATE_TYPE_P (type) || AGGREGATE_TYPE_P (access->type))
1999 105301 : && (TYPE_MAIN_VARIANT (access->type) != TYPE_MAIN_VARIANT (type)))
2000 : {
2001 : /* We need the same aggregate type on all accesses to be able to
2002 : distinguish transformation spots from pass-through arguments in
2003 : the transformation phase. */
2004 5392 : disqualify_split_candidate (desc, "We do not support aggregate "
2005 : "type punning.");
2006 5392 : return;
2007 : }
2008 :
2009 61562 : if (type_prevails_p (access->type, type))
2010 87 : access->type = type;
2011 : }
2012 : }
2013 :
2014 : /* Scan body function described by NODE and FUN and create access trees for
2015 : parameters. */
2016 :
2017 : static void
2018 1264063 : scan_function (cgraph_node *node, struct function *fun)
2019 : {
2020 1264063 : basic_block bb;
2021 :
2022 10228544 : FOR_EACH_BB_FN (bb, fun)
2023 : {
2024 8964481 : gimple_stmt_iterator gsi;
2025 69621368 : for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
2026 : {
2027 51692406 : gimple *stmt = gsi_stmt (gsi);
2028 :
2029 51692406 : if (final_bbs && stmt_can_throw_external (fun, stmt))
2030 1345638 : bitmap_set_bit (final_bbs, bb->index);
2031 51692406 : switch (gimple_code (stmt))
2032 : {
2033 1232824 : case GIMPLE_RETURN:
2034 1232824 : {
2035 1232824 : tree t = gimple_return_retval (as_a <greturn *> (stmt));
2036 1232824 : if (t != NULL_TREE)
2037 679094 : scan_expr_access (t, stmt, ISRA_CTX_LOAD, bb);
2038 1232824 : if (final_bbs)
2039 408997 : bitmap_set_bit (final_bbs, bb->index);
2040 : }
2041 : break;
2042 :
2043 18082026 : case GIMPLE_ASSIGN:
2044 18082026 : if (gimple_assign_single_p (stmt)
2045 18082026 : && !gimple_clobber_p (stmt))
2046 : {
2047 11030259 : tree rhs = gimple_assign_rhs1 (stmt);
2048 11030259 : scan_expr_access (rhs, stmt, ISRA_CTX_LOAD, bb);
2049 11030259 : tree lhs = gimple_assign_lhs (stmt);
2050 11030259 : scan_expr_access (lhs, stmt, ISRA_CTX_STORE, bb);
2051 : }
2052 : break;
2053 :
2054 5304979 : case GIMPLE_CALL:
2055 5304979 : {
2056 5304979 : unsigned argument_count = gimple_call_num_args (stmt);
2057 5304979 : isra_scan_context ctx = ISRA_CTX_ARG;
2058 5304979 : scan_call_info call_info, *call_info_p = &call_info;
2059 5304979 : if (gimple_call_internal_p (stmt))
2060 : {
2061 177584 : call_info_p = NULL;
2062 177584 : ctx = ISRA_CTX_LOAD;
2063 177584 : internal_fn ifn = gimple_call_internal_fn (stmt);
2064 177584 : if (internal_store_fn_p (ifn))
2065 0 : ctx = ISRA_CTX_STORE;
2066 : }
2067 : else
2068 : {
2069 5127395 : call_info.cs = node->get_edge (stmt);
2070 5127395 : call_info.argument_count = argument_count;
2071 : }
2072 :
2073 16040480 : for (unsigned i = 0; i < argument_count; i++)
2074 : {
2075 10735501 : call_info.arg_idx = i;
2076 10735501 : scan_expr_access (gimple_call_arg (stmt, i), stmt,
2077 : ctx, bb, call_info_p);
2078 : }
2079 :
2080 5304979 : tree lhs = gimple_call_lhs (stmt);
2081 5304979 : if (lhs)
2082 2136544 : scan_expr_access (lhs, stmt, ISRA_CTX_STORE, bb);
2083 5304979 : int flags = gimple_call_flags (stmt);
2084 5304979 : if (final_bbs
2085 2053149 : && (((flags & (ECF_CONST | ECF_PURE)) == 0)
2086 325424 : || (flags & ECF_LOOPING_CONST_OR_PURE)))
2087 1783733 : bitmap_set_bit (final_bbs, bb->index);
2088 : }
2089 5304979 : break;
2090 :
2091 49630 : case GIMPLE_ASM:
2092 49630 : {
2093 49630 : gasm *asm_stmt = as_a <gasm *> (stmt);
2094 49630 : walk_stmt_load_store_addr_ops (asm_stmt, NULL, NULL, NULL,
2095 : asm_visit_addr);
2096 49630 : if (final_bbs)
2097 1935 : bitmap_set_bit (final_bbs, bb->index);
2098 :
2099 85721 : for (unsigned i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
2100 : {
2101 36091 : tree t = TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
2102 36091 : scan_expr_access (t, stmt, ISRA_CTX_LOAD, bb);
2103 : }
2104 101109 : for (unsigned i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
2105 : {
2106 51479 : tree t = TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
2107 51479 : scan_expr_access (t, stmt, ISRA_CTX_STORE, bb);
2108 : }
2109 : }
2110 : break;
2111 :
2112 : default:
2113 : break;
2114 : }
2115 : }
2116 : }
2117 1264063 : }
2118 :
2119 : /* Return true if SSA_NAME NAME of function described by FUN is only used in
2120 : return statements, or if results of any operations it is involved in are
2121 : only used in return statements. ANALYZED is a bitmap that tracks which SSA
2122 : names we have already started investigating. */
2123 :
2124 : static bool
2125 2427298 : ssa_name_only_returned_p (function *fun, tree name, bitmap analyzed)
2126 : {
2127 2427298 : bool res = true;
2128 2427298 : imm_use_iterator imm_iter;
2129 2427298 : gimple *stmt;
2130 :
2131 5499212 : FOR_EACH_IMM_USE_STMT (stmt, imm_iter, name)
2132 : {
2133 2650186 : if (is_gimple_debug (stmt))
2134 180492 : continue;
2135 :
2136 2469694 : if (gimple_code (stmt) == GIMPLE_RETURN)
2137 : {
2138 254129 : tree t = gimple_return_retval (as_a <greturn *> (stmt));
2139 254129 : if (t != name)
2140 : {
2141 : res = false;
2142 : break;
2143 : }
2144 : }
2145 2215565 : else if (!stmt_unremovable_because_of_non_call_eh_p (fun, stmt)
2146 2215565 : && ((is_gimple_assign (stmt) && !gimple_has_volatile_ops (stmt))
2147 1157996 : || gimple_code (stmt) == GIMPLE_PHI))
2148 : {
2149 : /* TODO: And perhaps for const function calls too? */
2150 1176151 : tree lhs;
2151 1176151 : if (gimple_code (stmt) == GIMPLE_PHI)
2152 214845 : lhs = gimple_phi_result (stmt);
2153 : else
2154 961306 : lhs = gimple_assign_lhs (stmt);
2155 :
2156 1176151 : if (TREE_CODE (lhs) != SSA_NAME)
2157 : {
2158 : res = false;
2159 : break;
2160 : }
2161 828547 : gcc_assert (!gimple_vdef (stmt));
2162 828547 : if (bitmap_set_bit (analyzed, SSA_NAME_VERSION (lhs))
2163 828547 : && !ssa_name_only_returned_p (fun, lhs, analyzed))
2164 : {
2165 : res = false;
2166 : break;
2167 : }
2168 : }
2169 : else
2170 : {
2171 : res = false;
2172 : break;
2173 : }
2174 2427298 : }
2175 2427298 : return res;
2176 : }
2177 :
2178 : /* Inspect the uses of the return value of the call associated with CS, and if
2179 : it is not used or if it is only used to construct the return value of the
2180 : caller, mark it as such in call or caller summary. Also check for
2181 : misaligned arguments. */
2182 :
2183 : static void
2184 5140883 : isra_analyze_call (cgraph_edge *cs)
2185 : {
2186 5140883 : gcall *call_stmt = cs->call_stmt;
2187 5140883 : unsigned count = gimple_call_num_args (call_stmt);
2188 5140883 : isra_call_summary *csum = call_sums->get_create (cs);
2189 :
2190 15356604 : for (unsigned i = 0; i < count; i++)
2191 : {
2192 10215721 : tree arg = gimple_call_arg (call_stmt, i);
2193 10215721 : if (TREE_CODE (arg) == ADDR_EXPR)
2194 : {
2195 3195444 : poly_int64 poffset, psize, pmax_size;
2196 3195444 : bool reverse;
2197 3195444 : tree base = get_ref_base_and_extent (TREE_OPERAND (arg, 0), &poffset,
2198 3195444 : &psize, &pmax_size, &reverse);
2199 3195444 : HOST_WIDE_INT offset;
2200 3195444 : unsigned HOST_WIDE_INT ds;
2201 3195444 : if (DECL_P (base)
2202 2289956 : && (poffset.is_constant (&offset))
2203 2289956 : && tree_fits_uhwi_p (DECL_SIZE (base))
2204 5344327 : && ((ds = tree_to_uhwi (DECL_SIZE (base)) - offset)
2205 : < ISRA_ARG_SIZE_LIMIT * BITS_PER_UNIT))
2206 : {
2207 2015660 : csum->init_inputs (count);
2208 2015660 : gcc_assert (!csum->m_arg_flow[i].aggregate_pass_through);
2209 2015660 : csum->m_arg_flow[i].unit_size = ds / BITS_PER_UNIT;
2210 : }
2211 :
2212 3195444 : if (TREE_CODE (base) == VAR_DECL
2213 2110483 : && !TREE_STATIC (base)
2214 4561661 : && !loaded_decls->contains (base))
2215 : {
2216 894984 : csum->init_inputs (count);
2217 894984 : csum->m_arg_flow[i].constructed_for_calls = true;
2218 : }
2219 : }
2220 :
2221 10215721 : if (is_gimple_reg (arg))
2222 4031129 : continue;
2223 :
2224 6184592 : tree offset;
2225 6184592 : poly_int64 bitsize, bitpos;
2226 6184592 : machine_mode mode;
2227 6184592 : int unsignedp, reversep, volatilep = 0;
2228 6184592 : get_inner_reference (arg, &bitsize, &bitpos, &offset, &mode,
2229 : &unsignedp, &reversep, &volatilep);
2230 12369184 : if (!multiple_p (bitpos, BITS_PER_UNIT))
2231 : {
2232 0 : csum->m_bit_aligned_arg = true;
2233 0 : break;
2234 : }
2235 : }
2236 :
2237 5140883 : tree lhs = gimple_call_lhs (call_stmt);
2238 5140883 : if (lhs)
2239 : {
2240 : /* TODO: Also detect aggregates on a LHS of a call that are only returned
2241 : from this function (without being read anywhere). */
2242 1976997 : if (TREE_CODE (lhs) == SSA_NAME)
2243 : {
2244 1619759 : bitmap analyzed = BITMAP_ALLOC (NULL);
2245 1619759 : if (ssa_name_only_returned_p (DECL_STRUCT_FUNCTION (cs->caller->decl),
2246 : lhs, analyzed))
2247 232741 : csum->m_return_returned = true;
2248 1619759 : BITMAP_FREE (analyzed);
2249 : }
2250 : }
2251 : /* Don't set m_return_ignored for musttail calls. The tailc/musttail passes
2252 : compare the returned value against the IPA-VRP return value range if
2253 : it is a singleton, but if the call is changed to something which doesn't
2254 : return anything, it will always fail. */
2255 3163886 : else if (!gimple_call_must_tail_p (call_stmt))
2256 3163785 : csum->m_return_ignored = true;
2257 5140883 : }
2258 :
2259 : /* Look at all calls going out of NODE, described also by IFS and perform all
2260 : analyses necessary for IPA-SRA that are not done at body scan time or done
2261 : even when body is not scanned because the function is not a candidate. */
2262 :
2263 : static void
2264 1264063 : isra_analyze_all_outgoing_calls (cgraph_node *node)
2265 : {
2266 6268931 : for (cgraph_edge *cs = node->callees; cs; cs = cs->next_callee)
2267 5004868 : isra_analyze_call (cs);
2268 1400078 : for (cgraph_edge *cs = node->indirect_calls; cs; cs = cs->next_callee)
2269 136015 : isra_analyze_call (cs);
2270 1264063 : }
2271 :
2272 : /* Dump a dereferences table with heading STR to file F. */
2273 :
2274 : static void
2275 10 : dump_dereferences_table (FILE *f, struct function *fun, const char *str)
2276 : {
2277 10 : basic_block bb;
2278 :
2279 10 : fprintf (dump_file, "%s", str);
2280 52 : FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (fun),
2281 : EXIT_BLOCK_PTR_FOR_FN (fun), next_bb)
2282 : {
2283 42 : fprintf (f, "%4i %i ", bb->index, bitmap_bit_p (final_bbs, bb->index));
2284 42 : if (bb != EXIT_BLOCK_PTR_FOR_FN (fun))
2285 : {
2286 : int i;
2287 104 : for (i = 0; i < unsafe_by_ref_count; i++)
2288 : {
2289 62 : int idx = bb->index * unsafe_by_ref_count + i;
2290 62 : fprintf (f, " %4" HOST_WIDE_INT_PRINT "d", bb_dereferences[idx]);
2291 : }
2292 : }
2293 42 : fprintf (f, "\n");
2294 : }
2295 10 : fprintf (dump_file, "\n");
2296 10 : }
2297 :
2298 : /* Propagate distances in bb_dereferences in the opposite direction than the
2299 : control flow edges, in each step storing the maximum of the current value
2300 : and the minimum of all successors. These steps are repeated until the table
2301 : stabilizes. Note that BBs which might terminate the functions (according to
2302 : final_bbs bitmap) never updated in this way. */
2303 :
2304 : static void
2305 26948 : propagate_dereference_distances (struct function *fun)
2306 : {
2307 26948 : basic_block bb;
2308 :
2309 26948 : if (dump_file && (dump_flags & TDF_DETAILS))
2310 5 : dump_dereferences_table (dump_file, fun,
2311 : "Dereference table before propagation:\n");
2312 :
2313 26948 : auto_vec<basic_block> queue (last_basic_block_for_fn (fun));
2314 26948 : queue.quick_push (ENTRY_BLOCK_PTR_FOR_FN (fun));
2315 233642 : FOR_EACH_BB_FN (bb, fun)
2316 : {
2317 206694 : queue.quick_push (bb);
2318 206694 : bb->aux = bb;
2319 : }
2320 :
2321 261466 : while (!queue.is_empty ())
2322 : {
2323 234518 : edge_iterator ei;
2324 234518 : edge e;
2325 234518 : bool change = false;
2326 234518 : int i;
2327 :
2328 234518 : bb = queue.pop ();
2329 234518 : bb->aux = NULL;
2330 :
2331 234518 : if (bitmap_bit_p (final_bbs, bb->index))
2332 72984 : continue;
2333 :
2334 6221378 : for (i = 0; i < unsafe_by_ref_count; i++)
2335 : {
2336 6059844 : int idx = bb->index * unsafe_by_ref_count + i;
2337 6059844 : bool first = true;
2338 6059844 : HOST_WIDE_INT inh = 0;
2339 :
2340 14282802 : FOR_EACH_EDGE (e, ei, bb->succs)
2341 : {
2342 8222958 : int succ_idx = e->dest->index * unsafe_by_ref_count + i;
2343 :
2344 8222958 : if (e->dest == EXIT_BLOCK_PTR_FOR_FN (fun))
2345 0 : continue;
2346 :
2347 8222958 : if (first)
2348 : {
2349 6059839 : first = false;
2350 6059839 : inh = bb_dereferences [succ_idx];
2351 : }
2352 2163119 : else if (bb_dereferences [succ_idx] < inh)
2353 : inh = bb_dereferences [succ_idx];
2354 : }
2355 :
2356 6059844 : if (!first && bb_dereferences[idx] < inh)
2357 : {
2358 10805 : bb_dereferences[idx] = inh;
2359 10805 : change = true;
2360 : }
2361 : }
2362 :
2363 161534 : if (change)
2364 11769 : FOR_EACH_EDGE (e, ei, bb->preds)
2365 : {
2366 1877 : if (e->src->aux)
2367 1001 : continue;
2368 :
2369 876 : e->src->aux = e->src;
2370 876 : queue.quick_push (e->src);
2371 : }
2372 : }
2373 :
2374 26948 : if (dump_file && (dump_flags & TDF_DETAILS))
2375 5 : dump_dereferences_table (dump_file, fun,
2376 : "Dereference table after propagation:\n");
2377 26948 : }
2378 :
2379 : /* Return true if the ACCESS loads happen frequently enough in FUN to risk
2380 : moving them to the caller and only pass the result. */
2381 :
2382 : static bool
2383 171580 : dereference_probable_p (struct function *fun, gensum_param_access *access)
2384 : {
2385 171580 : int threshold = opt_for_fn (fun->decl, param_ipa_sra_deref_prob_threshold);
2386 171580 : return access->load_count
2387 171580 : >= ENTRY_BLOCK_PTR_FOR_FN (fun)->count.apply_scale (threshold, 100);
2388 : }
2389 :
2390 : /* Perform basic checks on ACCESS to PARM (of FUN) described by DESC and all
2391 : its children, return true if the parameter cannot be split, otherwise return
2392 : false and update *NONARG_ACC_SIZE and *ONLY_CALLS. ENTRY_BB_INDEX must be
2393 : the index of the entry BB in the function of PARM. */
2394 :
2395 : static bool
2396 377744 : check_gensum_access (struct function *fun, tree parm, gensum_param_desc *desc,
2397 : gensum_param_access *access,
2398 : HOST_WIDE_INT *nonarg_acc_size, bool *only_calls,
2399 : int entry_bb_index)
2400 : {
2401 377744 : if (access->nonarg)
2402 : {
2403 326628 : *only_calls = false;
2404 326628 : *nonarg_acc_size += access->size;
2405 :
2406 326628 : if (access->first_child)
2407 : {
2408 379 : disqualify_split_candidate (desc, "Overlapping non-call uses.");
2409 379 : return true;
2410 : }
2411 : }
2412 : /* Do not decompose a non-BLKmode param in a way that would create
2413 : BLKmode params. Especially for by-reference passing (thus,
2414 : pointer-type param) this is hardly worthwhile. */
2415 377365 : if (DECL_MODE (parm) != BLKmode
2416 377365 : && TYPE_MODE (access->type) == BLKmode)
2417 : {
2418 3039 : disqualify_split_candidate (desc, "Would convert a non-BLK to a BLK.");
2419 3039 : return true;
2420 : }
2421 :
2422 374326 : if (desc->by_ref)
2423 : {
2424 182225 : if (desc->safe_ref)
2425 : {
2426 146723 : if (!dereference_probable_p (fun, access))
2427 : {
2428 6612 : disqualify_split_candidate (desc, "Dereferences in callers "
2429 : "would happen much more frequently.");
2430 6612 : return true;
2431 : }
2432 : }
2433 : else
2434 : {
2435 35502 : int idx = (entry_bb_index * unsafe_by_ref_count + desc->deref_index);
2436 35502 : if ((access->offset + access->size) > bb_dereferences[idx])
2437 : {
2438 24857 : if (!dereference_probable_p (fun, access))
2439 : {
2440 2153 : disqualify_split_candidate (desc, "Would create a possibly "
2441 : "illegal dereference in a "
2442 : "caller.");
2443 2153 : return true;
2444 : }
2445 22704 : desc->conditionally_dereferenceable = true;
2446 : }
2447 : }
2448 : }
2449 :
2450 365561 : for (gensum_param_access *ch = access->first_child;
2451 387654 : ch;
2452 22093 : ch = ch->next_sibling)
2453 22095 : if (check_gensum_access (fun, parm, desc, ch, nonarg_acc_size, only_calls,
2454 : entry_bb_index))
2455 : return true;
2456 :
2457 : return false;
2458 : }
2459 :
2460 : /* Copy data from FROM and all of its children to a vector of accesses in IPA
2461 : descriptor DESC. */
2462 :
2463 : static void
2464 434769 : copy_accesses_to_ipa_desc (gensum_param_access *from, isra_param_desc *desc)
2465 : {
2466 434769 : param_access *to = ggc_cleared_alloc<param_access> ();
2467 434769 : gcc_checking_assert ((from->offset % BITS_PER_UNIT) == 0);
2468 434769 : gcc_checking_assert ((from->size % BITS_PER_UNIT) == 0);
2469 434769 : to->unit_offset = from->offset / BITS_PER_UNIT;
2470 434769 : to->unit_size = from->size / BITS_PER_UNIT;
2471 434769 : to->type = from->type;
2472 434769 : to->alias_ptr_type = from->alias_ptr_type;
2473 434769 : to->certain = from->nonarg;
2474 434769 : to->reverse = from->reverse;
2475 434769 : vec_safe_push (desc->accesses, to);
2476 :
2477 434769 : for (gensum_param_access *ch = from->first_child;
2478 458977 : ch;
2479 24208 : ch = ch->next_sibling)
2480 24208 : copy_accesses_to_ipa_desc (ch, desc);
2481 434769 : }
2482 :
2483 : /* Analyze function body scan results stored in param_accesses and
2484 : param_accesses, detect possible transformations and store information of
2485 : those in function summary. NODE, FUN and IFS are all various structures
2486 : describing the currently analyzed function. */
2487 :
2488 : static void
2489 835709 : process_scan_results (cgraph_node *node, struct function *fun,
2490 : isra_func_summary *ifs,
2491 : vec<gensum_param_desc> *param_descriptions)
2492 : {
2493 835709 : bool check_pass_throughs = false;
2494 835709 : bool dereferences_propagated = false;
2495 835709 : tree parm = DECL_ARGUMENTS (node->decl);
2496 835709 : unsigned param_count = param_descriptions->length();
2497 :
2498 835709 : for (unsigned desc_index = 0;
2499 3221354 : desc_index < param_count;
2500 2385645 : desc_index++, parm = DECL_CHAIN (parm))
2501 : {
2502 2385645 : gensum_param_desc *desc = &(*param_descriptions)[desc_index];
2503 2385645 : if (!desc->split_candidate)
2504 1878521 : continue;
2505 :
2506 519307 : if (flag_checking)
2507 519301 : isra_verify_access_tree (desc->accesses);
2508 :
2509 519307 : if (!dereferences_propagated
2510 513544 : && desc->by_ref
2511 357611 : && !desc->safe_ref
2512 164317 : && desc->accesses)
2513 : {
2514 26948 : propagate_dereference_distances (fun);
2515 26948 : dereferences_propagated = true;
2516 : }
2517 :
2518 519307 : HOST_WIDE_INT nonarg_acc_size = 0;
2519 519307 : bool only_calls = true;
2520 519307 : bool check_failed = false;
2521 :
2522 519307 : int entry_bb_index = ENTRY_BLOCK_PTR_FOR_FN (fun)->index;
2523 519307 : for (gensum_param_access *acc = desc->accesses;
2524 862773 : acc;
2525 343466 : acc = acc->next_sibling)
2526 355649 : if (check_gensum_access (fun, parm, desc, acc, &nonarg_acc_size,
2527 : &only_calls, entry_bb_index))
2528 : {
2529 : check_failed = true;
2530 : break;
2531 : }
2532 519307 : if (check_failed)
2533 12183 : continue;
2534 :
2535 507124 : if (only_calls)
2536 314733 : desc->locally_unused = true;
2537 :
2538 507124 : HOST_WIDE_INT cur_param_size
2539 507124 : = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (parm)));
2540 507124 : HOST_WIDE_INT param_size_limit, optimistic_limit;
2541 507124 : if (!desc->by_ref || optimize_function_for_size_p (fun))
2542 : {
2543 : param_size_limit = cur_param_size;
2544 : optimistic_limit = cur_param_size;
2545 : }
2546 : else
2547 : {
2548 329020 : param_size_limit
2549 329020 : = opt_for_fn (node->decl,
2550 : param_ipa_sra_ptr_growth_factor) * cur_param_size;
2551 329020 : optimistic_limit
2552 329020 : = (opt_for_fn (node->decl, param_ipa_sra_ptrwrap_growth_factor)
2553 : * param_size_limit);
2554 : }
2555 :
2556 507124 : if (nonarg_acc_size > optimistic_limit
2557 504772 : || (!desc->by_ref && nonarg_acc_size == param_size_limit))
2558 : {
2559 68766 : disqualify_split_candidate (desc, "Would result into a too big set "
2560 : "of replacements even in best "
2561 : "scenarios.");
2562 : }
2563 : else
2564 : {
2565 : /* create_parameter_descriptors makes sure unit sizes of all
2566 : candidate parameters fit unsigned integers restricted to
2567 : ISRA_ARG_SIZE_LIMIT. */
2568 438358 : desc->param_size_limit = param_size_limit / BITS_PER_UNIT;
2569 438358 : desc->nonarg_acc_size = nonarg_acc_size / BITS_PER_UNIT;
2570 438358 : if (desc->split_candidate && desc->ptr_pt_count)
2571 : {
2572 184298 : gcc_assert (desc->by_ref);
2573 : check_pass_throughs = true;
2574 : }
2575 : }
2576 : }
2577 :
2578 : /* When a pointer parameter is passed-through to a callee, in which it is
2579 : only used to read only one or a few items, we can attempt to transform it
2580 : to obtaining and passing through the items instead of the pointer. But we
2581 : must take extra care that 1) we do not introduce any segfault by moving
2582 : dereferences above control flow and that 2) the data is not modified
2583 : through an alias in this function. The IPA analysis must not introduce
2584 : any accesses candidates unless it can prove both.
2585 :
2586 : The current solution is very crude as it consists of ensuring that the
2587 : call postdominates entry BB and that the definition of VUSE of the call is
2588 : default definition. TODO: For non-recursive callees in the same
2589 : compilation unit we could do better by doing analysis in topological order
2590 : an looking into access candidates of callees, using their alias_ptr_types
2591 : to attempt real AA. We could also use the maximum known dereferenced
2592 : offset in this function at IPA level.
2593 :
2594 : TODO: Measure the overhead and the effect of just being pessimistic.
2595 : Maybe this is only -O3 material? */
2596 :
2597 835709 : hash_map<gimple *, bool> analyzed_stmts;
2598 835709 : bitmap always_executed_bbs = NULL;
2599 835709 : if (check_pass_throughs)
2600 1153806 : for (cgraph_edge *cs = node->callees; cs; cs = cs->next_callee)
2601 : {
2602 1005189 : gcall *call_stmt = cs->call_stmt;
2603 1005189 : tree vuse = gimple_vuse (call_stmt);
2604 :
2605 : /* If the callee is a const function, we don't get a VUSE. In such
2606 : case there will be no memory accesses in the called function (or the
2607 : const attribute is wrong) and then we just don't care. */
2608 1980249 : bool uses_memory_as_obtained = vuse && SSA_NAME_IS_DEFAULT_DEF (vuse);
2609 :
2610 1005189 : unsigned count = gimple_call_num_args (call_stmt);
2611 1005189 : isra_call_summary *csum = call_sums->get_create (cs);
2612 1005189 : csum->init_inputs (count);
2613 1005189 : csum->m_before_any_store = uses_memory_as_obtained;
2614 3245916 : for (unsigned argidx = 0; argidx < count; argidx++)
2615 : {
2616 2240727 : if (!csum->m_arg_flow[argidx].pointer_pass_through)
2617 4061609 : continue;
2618 419845 : unsigned pidx
2619 419845 : = get_single_param_flow_source (&csum->m_arg_flow[argidx]);
2620 419845 : gensum_param_desc *desc = &(*param_descriptions)[pidx];
2621 419845 : if (!desc->split_candidate)
2622 : {
2623 35804 : csum->m_arg_flow[argidx].pointer_pass_through = false;
2624 35804 : continue;
2625 : }
2626 384041 : if (!uses_memory_as_obtained)
2627 138130 : continue;
2628 :
2629 245911 : if (desc->safe_ref)
2630 : {
2631 45885 : csum->m_arg_flow[argidx].safe_to_import_accesses = true;
2632 45885 : continue;
2633 : }
2634 :
2635 : /* Walk basic block and see if its execution can terminate earlier.
2636 : Keep the info for later re-use to avoid quadratic behavoiur here. */
2637 200026 : gimple_stmt_iterator gsi = gsi_for_stmt (call_stmt);
2638 200026 : bool safe = true;
2639 200026 : int n = 0;
2640 625160 : for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
2641 : {
2642 126726 : bool *b = analyzed_stmts.get (gsi_stmt (gsi));
2643 126726 : if (b)
2644 : {
2645 10043 : safe = *b;
2646 10043 : gsi_next (&gsi);
2647 10043 : break;
2648 : }
2649 116683 : n++;
2650 116683 : if (stmt_may_terminate_function_p (fun, gsi_stmt (gsi), false))
2651 : {
2652 : safe = false;
2653 : break;
2654 : }
2655 : }
2656 200026 : if (n)
2657 : {
2658 33573 : if (gsi_end_p (gsi))
2659 58888 : gsi = gsi_start_bb (gimple_bb (call_stmt));
2660 150256 : for (; gsi_stmt (gsi) != call_stmt; gsi_next (&gsi))
2661 116683 : analyzed_stmts.get_or_insert (gsi_stmt (gsi)) = safe;
2662 : }
2663 :
2664 200026 : if (safe && !always_executed_bbs)
2665 : {
2666 56763 : mark_dfs_back_edges ();
2667 56763 : always_executed_bbs = find_always_executed_bbs (fun, false);
2668 : }
2669 200026 : if (safe && bitmap_bit_p (always_executed_bbs, gimple_bb (call_stmt)->index))
2670 45467 : csum->m_arg_flow[argidx].safe_to_import_accesses = true;
2671 : }
2672 :
2673 : }
2674 835709 : BITMAP_FREE (always_executed_bbs);
2675 :
2676 : /* TODO: Add early exit if we disqualified everything. This also requires
2677 : that we either relax the restriction that
2678 : ipa_param_adjustments.m_always_copy_start must be the number of PARM_DECLs
2679 : or store the number of parameters to IPA-SRA function summary and use that
2680 : when just removing params. */
2681 :
2682 835709 : vec_safe_reserve_exact (ifs->m_parameters, param_count);
2683 835709 : ifs->m_parameters->quick_grow_cleared (param_count);
2684 3221354 : for (unsigned desc_index = 0; desc_index < param_count; desc_index++)
2685 : {
2686 2385645 : gensum_param_desc *s = &(*param_descriptions)[desc_index];
2687 2385645 : isra_param_desc *d = &(*ifs->m_parameters)[desc_index];
2688 :
2689 2385645 : d->param_size_limit = s->param_size_limit;
2690 2385645 : d->size_reached = s->nonarg_acc_size;
2691 2385645 : d->locally_unused = s->locally_unused;
2692 2385645 : d->split_candidate = s->split_candidate;
2693 2385645 : d->by_ref = s->by_ref;
2694 2385645 : d->remove_only_when_retval_removed = s->remove_only_when_retval_removed;
2695 2385645 : d->split_only_when_retval_removed = s->split_only_when_retval_removed;
2696 2385645 : d->conditionally_dereferenceable = s->conditionally_dereferenceable;
2697 :
2698 2385645 : for (gensum_param_access *acc = s->accesses;
2699 2796206 : acc;
2700 410561 : acc = acc->next_sibling)
2701 410561 : copy_accesses_to_ipa_desc (acc, d);
2702 : }
2703 :
2704 835709 : if (dump_file)
2705 135 : dump_isra_param_descriptors (dump_file, node->decl, ifs, false);
2706 835709 : }
2707 :
2708 : /* Return true if there are any overlaps among certain accesses of DESC. If
2709 : non-NULL, set *CERTAIN_ACCESS_PRESENT_P upon encountering a certain access
2710 : too. DESC is assumed to be a split candidate that is not locally
2711 : unused. */
2712 :
2713 : static bool
2714 166805 : overlapping_certain_accesses_p (isra_param_desc *desc,
2715 : bool *certain_access_present_p)
2716 : {
2717 166805 : unsigned pclen = vec_safe_length (desc->accesses);
2718 440506 : for (unsigned i = 0; i < pclen; i++)
2719 : {
2720 276029 : param_access *a1 = (*desc->accesses)[i];
2721 :
2722 276029 : if (!a1->certain)
2723 6359 : continue;
2724 269670 : if (certain_access_present_p)
2725 254669 : *certain_access_present_p = true;
2726 440281 : for (unsigned j = i + 1; j < pclen; j++)
2727 : {
2728 172939 : param_access *a2 = (*desc->accesses)[j];
2729 172939 : if (a2->certain
2730 172865 : && a1->unit_offset < a2->unit_offset + a2->unit_size
2731 172527 : && a1->unit_offset + a1->unit_size > a2->unit_offset)
2732 : return true;
2733 : }
2734 : }
2735 : return false;
2736 : }
2737 :
2738 : /* Check for any overlaps of certain param accesses among splitting candidates
2739 : and signal an ICE if there are any. If CERTAIN_MUST_EXIST is set, also
2740 : check that used splitting candidates have at least one certain access. */
2741 :
2742 : static void
2743 2605831 : verify_splitting_accesses (cgraph_node *node, bool certain_must_exist)
2744 : {
2745 2605831 : isra_func_summary *ifs = func_sums->get (node);
2746 2605831 : if (!ifs || !ifs->m_candidate)
2747 : return;
2748 1397278 : unsigned param_count = vec_safe_length (ifs->m_parameters);
2749 4546316 : for (unsigned pidx = 0; pidx < param_count; pidx++)
2750 : {
2751 3149038 : isra_param_desc *desc = &(*ifs->m_parameters)[pidx];
2752 3149038 : if (!desc->split_candidate || desc->locally_unused)
2753 2997165 : continue;
2754 :
2755 151873 : bool certain_access_present = !certain_must_exist;
2756 151873 : if (overlapping_certain_accesses_p (desc, &certain_access_present))
2757 0 : internal_error ("function %qs, parameter %u, has IPA-SRA accesses "
2758 : "which overlap", node->dump_name (), pidx);
2759 151873 : if (!certain_access_present)
2760 0 : internal_error ("function %qs, parameter %u, is used but does not "
2761 : "have any certain IPA-SRA access",
2762 : node->dump_name (), pidx);
2763 : }
2764 : }
2765 :
2766 : /* Intraprocedural part of IPA-SRA analysis. Scan bodies of all functions in
2767 : this compilation unit and create summary structures describing IPA-SRA
2768 : opportunities and constraints in them. */
2769 :
2770 : static void
2771 124827 : ipa_sra_generate_summary (void)
2772 : {
2773 124827 : struct cgraph_node *node;
2774 :
2775 124827 : gcc_checking_assert (!func_sums);
2776 124827 : gcc_checking_assert (!call_sums);
2777 124827 : func_sums
2778 124827 : = (new (ggc_alloc_no_dtor <ipa_sra_function_summaries> ())
2779 124827 : ipa_sra_function_summaries (symtab, true));
2780 124827 : call_sums = new ipa_sra_call_summaries (symtab);
2781 :
2782 1370844 : FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
2783 1246017 : ipa_sra_summarize_function (node);
2784 124827 : return;
2785 : }
2786 :
2787 : /* Write intraprocedural analysis information about E and all of its outgoing
2788 : edges into a stream for LTO WPA. */
2789 :
2790 : static void
2791 280899 : isra_write_edge_summary (output_block *ob, cgraph_edge *e)
2792 : {
2793 280899 : isra_call_summary *csum = call_sums->get (e);
2794 280899 : unsigned input_count = csum->m_arg_flow.length ();
2795 280899 : streamer_write_uhwi (ob, input_count);
2796 753010 : for (unsigned i = 0; i < input_count; i++)
2797 : {
2798 472111 : isra_param_flow *ipf = &csum->m_arg_flow[i];
2799 472111 : streamer_write_hwi (ob, ipf->length);
2800 472111 : bitpack_d bp = bitpack_create (ob->main_stream);
2801 546745 : for (int j = 0; j < ipf->length; j++)
2802 74634 : bp_pack_value (&bp, ipf->inputs[j], 8);
2803 472111 : bp_pack_value (&bp, ipf->aggregate_pass_through, 1);
2804 472111 : bp_pack_value (&bp, ipf->pointer_pass_through, 1);
2805 472111 : bp_pack_value (&bp, ipf->safe_to_import_accesses, 1);
2806 472111 : bp_pack_value (&bp, ipf->constructed_for_calls, 1);
2807 472111 : streamer_write_bitpack (&bp);
2808 472111 : streamer_write_uhwi (ob, ipf->unit_offset);
2809 472111 : streamer_write_uhwi (ob, ipf->unit_size);
2810 : }
2811 280899 : bitpack_d bp = bitpack_create (ob->main_stream);
2812 280899 : bp_pack_value (&bp, csum->m_return_ignored, 1);
2813 280899 : bp_pack_value (&bp, csum->m_return_returned, 1);
2814 280899 : bp_pack_value (&bp, csum->m_bit_aligned_arg, 1);
2815 280899 : bp_pack_value (&bp, csum->m_before_any_store, 1);
2816 280899 : streamer_write_bitpack (&bp);
2817 280899 : }
2818 :
2819 : /* Write intraprocedural analysis information about NODE and all of its outgoing
2820 : edges into a stream for LTO WPA. */
2821 :
2822 : static void
2823 48921 : isra_write_node_summary (output_block *ob, cgraph_node *node)
2824 : {
2825 48921 : isra_func_summary *ifs = func_sums->get (node);
2826 48921 : lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
2827 48921 : int node_ref = lto_symtab_encoder_encode (encoder, node);
2828 48921 : streamer_write_uhwi (ob, node_ref);
2829 :
2830 48921 : unsigned param_desc_count = vec_safe_length (ifs->m_parameters);
2831 48921 : streamer_write_uhwi (ob, param_desc_count);
2832 298369 : for (unsigned i = 0; i < param_desc_count; i++)
2833 : {
2834 249448 : isra_param_desc *desc = &(*ifs->m_parameters)[i];
2835 249448 : unsigned access_count = vec_safe_length (desc->accesses);
2836 249448 : streamer_write_uhwi (ob, access_count);
2837 252664 : for (unsigned j = 0; j < access_count; j++)
2838 : {
2839 3216 : param_access *acc = (*desc->accesses)[j];
2840 3216 : stream_write_tree (ob, acc->type, true);
2841 3216 : stream_write_tree (ob, acc->alias_ptr_type, true);
2842 3216 : streamer_write_uhwi (ob, acc->unit_offset);
2843 3216 : streamer_write_uhwi (ob, acc->unit_size);
2844 3216 : bitpack_d bp = bitpack_create (ob->main_stream);
2845 3216 : bp_pack_value (&bp, acc->certain, 1);
2846 3216 : bp_pack_value (&bp, acc->reverse, 1);
2847 3216 : streamer_write_bitpack (&bp);
2848 : }
2849 249448 : streamer_write_uhwi (ob, desc->param_size_limit);
2850 249448 : streamer_write_uhwi (ob, desc->size_reached);
2851 249448 : gcc_assert (desc->safe_size == 0);
2852 249448 : bitpack_d bp = bitpack_create (ob->main_stream);
2853 249448 : bp_pack_value (&bp, desc->locally_unused, 1);
2854 249448 : bp_pack_value (&bp, desc->split_candidate, 1);
2855 249448 : bp_pack_value (&bp, desc->by_ref, 1);
2856 249448 : gcc_assert (!desc->not_specially_constructed);
2857 249448 : bp_pack_value (&bp, desc->remove_only_when_retval_removed, 1);
2858 249448 : bp_pack_value (&bp, desc->split_only_when_retval_removed, 1);
2859 249448 : bp_pack_value (&bp, desc->conditionally_dereferenceable, 1);
2860 249448 : gcc_assert (!desc->safe_size_set);
2861 249448 : streamer_write_bitpack (&bp);
2862 : }
2863 48921 : bitpack_d bp = bitpack_create (ob->main_stream);
2864 48921 : bp_pack_value (&bp, ifs->m_candidate, 1);
2865 48921 : bp_pack_value (&bp, ifs->m_returns_value, 1);
2866 48921 : bp_pack_value (&bp, ifs->m_return_ignored, 1);
2867 48921 : gcc_assert (!ifs->m_queued);
2868 48921 : streamer_write_bitpack (&bp);
2869 :
2870 327379 : for (cgraph_edge *e = node->callees; e; e = e->next_callee)
2871 278458 : isra_write_edge_summary (ob, e);
2872 51362 : for (cgraph_edge *e = node->indirect_calls; e; e = e->next_callee)
2873 2441 : isra_write_edge_summary (ob, e);
2874 48921 : }
2875 :
2876 : /* Write intraprocedural analysis information into a stream for LTO WPA. */
2877 :
2878 : static void
2879 19765 : ipa_sra_write_summary (void)
2880 : {
2881 19765 : if (!func_sums || !call_sums)
2882 0 : return;
2883 :
2884 19765 : struct output_block *ob = create_output_block (LTO_section_ipa_sra);
2885 19765 : lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
2886 19765 : ob->symbol = NULL;
2887 :
2888 19765 : unsigned int count = 0;
2889 19765 : lto_symtab_encoder_iterator lsei;
2890 19765 : for (lsei = lsei_start_function_in_partition (encoder);
2891 112835 : !lsei_end_p (lsei);
2892 93070 : lsei_next_function_in_partition (&lsei))
2893 : {
2894 93070 : cgraph_node *node = lsei_cgraph_node (lsei);
2895 93070 : if (node->has_gimple_body_p ()
2896 93070 : && func_sums->get (node) != NULL)
2897 48921 : count++;
2898 : }
2899 19765 : streamer_write_uhwi (ob, count);
2900 :
2901 : /* Process all of the functions. */
2902 112835 : for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
2903 93070 : lsei_next_function_in_partition (&lsei))
2904 : {
2905 93070 : cgraph_node *node = lsei_cgraph_node (lsei);
2906 93070 : if (node->has_gimple_body_p ()
2907 93070 : && func_sums->get (node) != NULL)
2908 48921 : isra_write_node_summary (ob, node);
2909 : }
2910 19765 : streamer_write_char_stream (ob->main_stream, 0);
2911 19765 : produce_asm (ob);
2912 19765 : destroy_output_block (ob);
2913 : }
2914 :
2915 : /* Read intraprocedural analysis information about E and all of its outgoing
2916 : edges into a stream for LTO WPA. */
2917 :
2918 : static void
2919 252766 : isra_read_edge_summary (struct lto_input_block *ib, cgraph_edge *cs)
2920 : {
2921 252766 : isra_call_summary *csum = call_sums->get_create (cs);
2922 252766 : unsigned input_count = streamer_read_uhwi (ib);
2923 252766 : csum->init_inputs (input_count);
2924 699099 : for (unsigned i = 0; i < input_count; i++)
2925 : {
2926 446333 : isra_param_flow *ipf = &csum->m_arg_flow[i];
2927 446333 : ipf->length = streamer_read_hwi (ib);
2928 446333 : bitpack_d bp = streamer_read_bitpack (ib);
2929 513536 : for (int j = 0; j < ipf->length; j++)
2930 67203 : ipf->inputs[j] = bp_unpack_value (&bp, 8);
2931 446333 : ipf->aggregate_pass_through = bp_unpack_value (&bp, 1);
2932 446333 : ipf->pointer_pass_through = bp_unpack_value (&bp, 1);
2933 446333 : ipf->safe_to_import_accesses = bp_unpack_value (&bp, 1);
2934 446333 : ipf->constructed_for_calls = bp_unpack_value (&bp, 1);
2935 446333 : ipf->unit_offset = streamer_read_uhwi (ib);
2936 446333 : ipf->unit_size = streamer_read_uhwi (ib);
2937 : }
2938 252766 : bitpack_d bp = streamer_read_bitpack (ib);
2939 252766 : csum->m_return_ignored = bp_unpack_value (&bp, 1);
2940 252766 : csum->m_return_returned = bp_unpack_value (&bp, 1);
2941 252766 : csum->m_bit_aligned_arg = bp_unpack_value (&bp, 1);
2942 252766 : csum->m_before_any_store = bp_unpack_value (&bp, 1);
2943 252766 : }
2944 :
2945 : /* Read intraprocedural analysis information about NODE and all of its outgoing
2946 : edges into a stream for LTO WPA. */
2947 :
2948 : static void
2949 34561 : isra_read_node_info (struct lto_input_block *ib, cgraph_node *node,
2950 : struct data_in *data_in)
2951 : {
2952 34561 : isra_func_summary *ifs = func_sums->get_create (node);
2953 34561 : unsigned param_desc_count = streamer_read_uhwi (ib);
2954 34561 : if (param_desc_count > 0)
2955 : {
2956 17585 : vec_safe_reserve_exact (ifs->m_parameters, param_desc_count);
2957 17585 : ifs->m_parameters->quick_grow_cleared (param_desc_count);
2958 : }
2959 62262 : for (unsigned i = 0; i < param_desc_count; i++)
2960 : {
2961 27701 : isra_param_desc *desc = &(*ifs->m_parameters)[i];
2962 27701 : unsigned access_count = streamer_read_uhwi (ib);
2963 29403 : for (unsigned j = 0; j < access_count; j++)
2964 : {
2965 1702 : param_access *acc = ggc_cleared_alloc<param_access> ();
2966 1702 : acc->type = stream_read_tree (ib, data_in);
2967 1702 : acc->alias_ptr_type = stream_read_tree (ib, data_in);
2968 1702 : acc->unit_offset = streamer_read_uhwi (ib);
2969 1702 : acc->unit_size = streamer_read_uhwi (ib);
2970 1702 : bitpack_d bp = streamer_read_bitpack (ib);
2971 1702 : acc->certain = bp_unpack_value (&bp, 1);
2972 1702 : acc->reverse = bp_unpack_value (&bp, 1);
2973 1702 : vec_safe_push (desc->accesses, acc);
2974 : }
2975 27701 : desc->param_size_limit = streamer_read_uhwi (ib);
2976 27701 : desc->size_reached = streamer_read_uhwi (ib);
2977 27701 : desc->safe_size = 0;
2978 27701 : bitpack_d bp = streamer_read_bitpack (ib);
2979 27701 : desc->locally_unused = bp_unpack_value (&bp, 1);
2980 27701 : desc->split_candidate = bp_unpack_value (&bp, 1);
2981 27701 : desc->by_ref = bp_unpack_value (&bp, 1);
2982 27701 : desc->not_specially_constructed = 0;
2983 27701 : desc->remove_only_when_retval_removed = bp_unpack_value (&bp, 1);
2984 27701 : desc->split_only_when_retval_removed = bp_unpack_value (&bp, 1);
2985 27701 : desc->conditionally_dereferenceable = bp_unpack_value (&bp, 1);
2986 27701 : desc->safe_size_set = 0;
2987 : }
2988 34561 : bitpack_d bp = streamer_read_bitpack (ib);
2989 34561 : ifs->m_candidate = bp_unpack_value (&bp, 1);
2990 34561 : ifs->m_returns_value = bp_unpack_value (&bp, 1);
2991 34561 : ifs->m_return_ignored = bp_unpack_value (&bp, 1);
2992 34561 : ifs->m_queued = 0;
2993 :
2994 286012 : for (cgraph_edge *e = node->callees; e; e = e->next_callee)
2995 251451 : isra_read_edge_summary (ib, e);
2996 35876 : for (cgraph_edge *e = node->indirect_calls; e; e = e->next_callee)
2997 1315 : isra_read_edge_summary (ib, e);
2998 34561 : }
2999 :
3000 : /* Read IPA-SRA summaries from a section in file FILE_DATA of length LEN with
3001 : data DATA. TODO: This function was copied almost verbatim from ipa-prop.cc,
3002 : it should be possible to unify them somehow. */
3003 :
3004 : static void
3005 10798 : isra_read_summary_section (struct lto_file_decl_data *file_data,
3006 : const char *data, size_t len)
3007 : {
3008 10798 : const struct lto_function_header *header =
3009 : (const struct lto_function_header *) data;
3010 10798 : const int cfg_offset = sizeof (struct lto_function_header);
3011 10798 : const int main_offset = cfg_offset + header->cfg_size;
3012 10798 : const int string_offset = main_offset + header->main_size;
3013 10798 : struct data_in *data_in;
3014 10798 : unsigned int i;
3015 10798 : unsigned int count;
3016 :
3017 10798 : lto_input_block ib_main ((const char *) data + main_offset,
3018 10798 : header->main_size, file_data);
3019 :
3020 10798 : data_in =
3021 21596 : lto_data_in_create (file_data, (const char *) data + string_offset,
3022 10798 : header->string_size, vNULL);
3023 10798 : count = streamer_read_uhwi (&ib_main);
3024 :
3025 45359 : for (i = 0; i < count; i++)
3026 : {
3027 34561 : unsigned int index;
3028 34561 : struct cgraph_node *node;
3029 34561 : lto_symtab_encoder_t encoder;
3030 :
3031 34561 : index = streamer_read_uhwi (&ib_main);
3032 34561 : encoder = file_data->symtab_node_encoder;
3033 34561 : node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref (encoder,
3034 : index));
3035 34561 : gcc_assert (node->definition);
3036 34561 : isra_read_node_info (&ib_main, node, data_in);
3037 : }
3038 10798 : lto_free_section_data (file_data, LTO_section_ipa_sra, NULL, data,
3039 : len);
3040 10798 : lto_data_in_delete (data_in);
3041 10798 : }
3042 :
3043 : /* Read intraprocedural analysis information into a stream for LTO WPA. */
3044 :
3045 : static void
3046 10123 : ipa_sra_read_summary (void)
3047 : {
3048 10123 : struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
3049 10123 : struct lto_file_decl_data *file_data;
3050 10123 : unsigned int j = 0;
3051 :
3052 10123 : gcc_checking_assert (!func_sums);
3053 10123 : gcc_checking_assert (!call_sums);
3054 10123 : func_sums
3055 10123 : = (new (ggc_alloc_no_dtor <ipa_sra_function_summaries> ())
3056 10123 : ipa_sra_function_summaries (symtab, true));
3057 10123 : call_sums = new ipa_sra_call_summaries (symtab);
3058 :
3059 20932 : while ((file_data = file_data_vec[j++]))
3060 : {
3061 10809 : size_t len;
3062 10809 : const char *data
3063 10809 : = lto_get_summary_section_data (file_data, LTO_section_ipa_sra, &len);
3064 10809 : if (data)
3065 10798 : isra_read_summary_section (file_data, data, len);
3066 : }
3067 10123 : }
3068 :
3069 : /* Dump all IPA-SRA summary data for all cgraph nodes and edges to file F. If
3070 : HINTS is true, also dump IPA-analysis computed hints. */
3071 :
3072 : static void
3073 63 : ipa_sra_dump_all_summaries (FILE *f, bool hints)
3074 : {
3075 63 : cgraph_node *node;
3076 258 : FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
3077 : {
3078 195 : fprintf (f, "\nSummary for node %s:\n", node->dump_name ());
3079 :
3080 195 : isra_func_summary *ifs = func_sums->get (node);
3081 195 : if (!ifs)
3082 10 : fprintf (f, " Function does not have any associated IPA-SRA "
3083 : "summary\n");
3084 185 : else if (!ifs->m_candidate)
3085 12 : fprintf (f, " Not a candidate function\n");
3086 : else
3087 : {
3088 173 : if (ifs->m_returns_value)
3089 95 : fprintf (f, " Returns value\n");
3090 173 : if (vec_safe_is_empty (ifs->m_parameters))
3091 41 : fprintf (f, " No parameter information. \n");
3092 : else
3093 446 : for (unsigned i = 0; i < ifs->m_parameters->length (); ++i)
3094 : {
3095 314 : fprintf (f, " Descriptor for parameter %i:\n", i);
3096 314 : dump_isra_param_descriptor (f, &(*ifs->m_parameters)[i], hints);
3097 : }
3098 173 : fprintf (f, "\n");
3099 : }
3100 :
3101 195 : struct cgraph_edge *cs;
3102 375 : for (cs = node->callees; cs; cs = cs->next_callee)
3103 : {
3104 180 : fprintf (f, " Summary for edge %s->%s:\n", cs->caller->dump_name (),
3105 180 : cs->callee->dump_name ());
3106 180 : isra_call_summary *csum = call_sums->get (cs);
3107 180 : if (csum)
3108 180 : csum->dump (f);
3109 : else
3110 0 : fprintf (f, " Call summary is MISSING!\n");
3111 : }
3112 :
3113 : }
3114 63 : fprintf (f, "\n\n");
3115 63 : }
3116 :
3117 : /* Perform function-scope viability tests that can be only made at IPA level
3118 : and return false if the function is deemed unsuitable for IPA-SRA. */
3119 :
3120 : static bool
3121 1025209 : ipa_sra_ipa_function_checks (cgraph_node *node)
3122 : {
3123 1025209 : if (!node->can_be_local_p ())
3124 : {
3125 656731 : if (dump_file)
3126 87 : fprintf (dump_file, "Function %s disqualified because it cannot be "
3127 : "made local.\n", node->dump_name ());
3128 656731 : return false;
3129 : }
3130 368478 : if (!node->can_change_signature)
3131 : {
3132 0 : if (dump_file)
3133 0 : fprintf (dump_file, "Function can not change signature.\n");
3134 0 : return false;
3135 : }
3136 :
3137 : return true;
3138 : }
3139 :
3140 : /* Issues found out by check_callers_for_issues. */
3141 :
3142 : struct caller_issues
3143 : {
3144 : /* The candidate being considered. */
3145 : cgraph_node *candidate;
3146 : /* There is a thunk among callers. */
3147 : bool thunk;
3148 : /* Set if there is at least one caller that is OK. */
3149 : bool there_is_one;
3150 : /* Call site with no available information. */
3151 : bool unknown_callsite;
3152 : /* Call from outside the candidate's comdat group. */
3153 : bool call_from_outside_comdat;
3154 : /* There is a bit-aligned load into one of non-gimple-typed arguments. */
3155 : bool bit_aligned_aggregate_argument;
3156 : };
3157 :
3158 : /* Worker for call_for_symbol_and_aliases, set any flags of passed caller_issues
3159 : that apply. */
3160 :
3161 : static bool
3162 372551 : check_for_caller_issues (struct cgraph_node *node, void *data)
3163 : {
3164 372551 : struct caller_issues *issues = (struct caller_issues *) data;
3165 :
3166 1424036 : for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
3167 : {
3168 1051693 : if (cs->caller->thunk)
3169 : {
3170 0 : issues->thunk = true;
3171 : /* TODO: We should be able to process at least some types of
3172 : thunks. */
3173 0 : return true;
3174 : }
3175 1051693 : if (issues->candidate->calls_comdat_local
3176 10 : && issues->candidate->same_comdat_group
3177 1051703 : && !issues->candidate->in_same_comdat_group_p (cs->caller))
3178 : {
3179 0 : issues->call_from_outside_comdat = true;
3180 0 : return true;
3181 : }
3182 :
3183 1051693 : isra_call_summary *csum = call_sums->get (cs);
3184 1051693 : if (!csum)
3185 : {
3186 208 : issues->unknown_callsite = true;
3187 208 : return true;
3188 : }
3189 :
3190 1051485 : if (csum->m_bit_aligned_arg)
3191 0 : issues->bit_aligned_aggregate_argument = true;
3192 :
3193 1051485 : issues->there_is_one = true;
3194 : }
3195 : return false;
3196 : }
3197 :
3198 : /* Look at all incoming edges to NODE, including aliases and thunks and look
3199 : for problems. Return true if NODE type should not be modified at all. */
3200 :
3201 : static bool
3202 368478 : check_all_callers_for_issues (cgraph_node *node)
3203 : {
3204 368478 : struct caller_issues issues;
3205 368478 : memset (&issues, 0, sizeof (issues));
3206 368478 : issues.candidate = node;
3207 :
3208 368478 : node->call_for_symbol_and_aliases (check_for_caller_issues, &issues, true);
3209 368478 : if (issues.unknown_callsite)
3210 : {
3211 208 : if (dump_file && (dump_flags & TDF_DETAILS))
3212 0 : fprintf (dump_file, "A call of %s has not been analyzed. Disabling "
3213 : "all modifications.\n", node->dump_name ());
3214 208 : return true;
3215 : }
3216 : /* TODO: We should be able to process at least some types of thunks. */
3217 368270 : if (issues.thunk)
3218 : {
3219 0 : if (dump_file && (dump_flags & TDF_DETAILS))
3220 0 : fprintf (dump_file, "A call of %s is through thunk, which are not"
3221 : " handled yet. Disabling all modifications.\n",
3222 : node->dump_name ());
3223 0 : return true;
3224 : }
3225 368270 : if (issues.call_from_outside_comdat)
3226 : {
3227 0 : if (dump_file)
3228 0 : fprintf (dump_file, "Function would become private comdat called "
3229 : "outside of its comdat group.\n");
3230 0 : return true;
3231 : }
3232 :
3233 368270 : if (issues.bit_aligned_aggregate_argument)
3234 : {
3235 : /* Let's only remove parameters/return values from such functions.
3236 : TODO: We could only prevent splitting the problematic parameters if
3237 : anybody thinks it is worth it. */
3238 0 : if (dump_file && (dump_flags & TDF_DETAILS))
3239 0 : fprintf (dump_file, "A call of %s has bit-aligned aggregate argument,"
3240 : " disabling parameter splitting.\n", node->dump_name ());
3241 :
3242 0 : isra_func_summary *ifs = func_sums->get (node);
3243 0 : gcc_checking_assert (ifs);
3244 0 : unsigned param_count = vec_safe_length (ifs->m_parameters);
3245 0 : for (unsigned i = 0; i < param_count; i++)
3246 0 : (*ifs->m_parameters)[i].split_candidate = false;
3247 : }
3248 368270 : if (!issues.there_is_one)
3249 : {
3250 1 : if (dump_file && (dump_flags & TDF_DETAILS))
3251 0 : fprintf (dump_file, "There is no call to %s that we can modify. "
3252 : "Disabling all modifications.\n", node->dump_name ());
3253 1 : return true;
3254 : }
3255 : return false;
3256 : }
3257 :
3258 : /* Find the access with corresponding OFFSET and SIZE among accesses in
3259 : PARAM_DESC and return it or NULL if such an access is not there. */
3260 :
3261 : static param_access *
3262 16076 : find_param_access (isra_param_desc *param_desc, unsigned offset, unsigned size)
3263 : {
3264 16076 : unsigned pclen = vec_safe_length (param_desc->accesses);
3265 :
3266 : /* The search is linear but the number of stored accesses is bound by
3267 : PARAM_IPA_SRA_MAX_REPLACEMENTS, so most probably 8. */
3268 :
3269 16153 : for (unsigned i = 0; i < pclen; i++)
3270 16108 : if ((*param_desc->accesses)[i]->unit_offset == offset
3271 16108 : && (*param_desc->accesses)[i]->unit_size == size)
3272 : return (*param_desc->accesses)[i];
3273 :
3274 : return NULL;
3275 : }
3276 :
3277 : /* Return iff the total size of definite replacement SIZE would violate the
3278 : limit set for it in PARAM. */
3279 :
3280 : static bool
3281 212235 : size_would_violate_limit_p (isra_param_desc *desc, unsigned size)
3282 : {
3283 212235 : unsigned limit = desc->param_size_limit;
3284 0 : if (size > limit
3285 208958 : || (!desc->by_ref && size == limit))
3286 0 : return true;
3287 : return false;
3288 : }
3289 :
3290 : /* Increase reached size of DESC by SIZE or disqualify it if it would violate
3291 : the set limit. IDX is the parameter number which is dumped when
3292 : disqualifying. */
3293 :
3294 : static void
3295 12604 : bump_reached_size (isra_param_desc *desc, unsigned size, unsigned idx)
3296 : {
3297 12604 : unsigned after = desc->size_reached + size;
3298 12604 : if (size_would_violate_limit_p (desc, after))
3299 : {
3300 12572 : if (dump_file && (dump_flags & TDF_DETAILS))
3301 0 : fprintf (dump_file, " ...size limit reached, disqualifying "
3302 : "candidate parameter %u\n", idx);
3303 12572 : desc->split_candidate = false;
3304 12572 : return;
3305 : }
3306 32 : desc->size_reached = after;
3307 : }
3308 :
3309 : /* Take all actions required to deal with an edge CS that represents a call to
3310 : an unknown or un-analyzed function, for both parameter removal and
3311 : splitting. */
3312 :
3313 : static void
3314 496009 : process_edge_to_unknown_caller (cgraph_edge *cs)
3315 : {
3316 496009 : isra_func_summary *from_ifs = func_sums->get (cs->caller);
3317 496009 : gcc_checking_assert (from_ifs);
3318 496009 : isra_call_summary *csum = call_sums->get (cs);
3319 :
3320 496009 : if (dump_file && (dump_flags & TDF_DETAILS))
3321 4 : fprintf (dump_file, "Processing an edge to an unknown caller from %s:\n",
3322 : cs->caller->dump_name ());
3323 :
3324 496009 : unsigned args_count = csum->m_arg_flow.length ();
3325 1214005 : for (unsigned i = 0; i < args_count; i++)
3326 : {
3327 717996 : isra_param_flow *ipf = &csum->m_arg_flow[i];
3328 :
3329 717996 : if (ipf->pointer_pass_through)
3330 : {
3331 193085 : isra_param_desc *param_desc
3332 193085 : = &(*from_ifs->m_parameters)[get_single_param_flow_source (ipf)];
3333 193085 : param_desc->locally_unused = false;
3334 193085 : param_desc->split_candidate = false;
3335 193085 : continue;
3336 193085 : }
3337 524911 : if (ipf->aggregate_pass_through)
3338 : {
3339 5584 : unsigned idx = get_single_param_flow_source (ipf);
3340 5584 : isra_param_desc *param_desc = &(*from_ifs->m_parameters)[idx];
3341 :
3342 5584 : param_desc->locally_unused = false;
3343 5584 : if (!param_desc->split_candidate)
3344 1708 : continue;
3345 3876 : gcc_assert (!param_desc->by_ref);
3346 7752 : param_access *pacc = find_param_access (param_desc, ipf->unit_offset,
3347 3876 : ipf->unit_size);
3348 3876 : gcc_checking_assert (pacc);
3349 3876 : pacc->certain = true;
3350 3876 : if (overlapping_certain_accesses_p (param_desc, NULL))
3351 : {
3352 628 : if (dump_file && (dump_flags & TDF_DETAILS))
3353 0 : fprintf (dump_file, " ...leading to overlap, "
3354 : " disqualifying candidate parameter %u\n",
3355 : idx);
3356 628 : param_desc->split_candidate = false;
3357 : }
3358 : else
3359 3248 : bump_reached_size (param_desc, pacc->unit_size, idx);
3360 3876 : ipf->aggregate_pass_through = false;
3361 3876 : continue;
3362 3876 : }
3363 :
3364 618149 : for (int j = 0; j < ipf->length; j++)
3365 : {
3366 98822 : int input_idx = ipf->inputs[j];
3367 98822 : (*from_ifs->m_parameters)[input_idx].locally_unused = false;
3368 : }
3369 : }
3370 496009 : }
3371 :
3372 : /* Propagate parameter removal information through cross-SCC edge CS,
3373 : i.e. decrease the use count in the caller parameter descriptor for each use
3374 : in this call. */
3375 :
3376 : static void
3377 807404 : param_removal_cross_scc_edge (cgraph_edge *cs)
3378 : {
3379 807404 : enum availability availability;
3380 807404 : cgraph_node *callee = cs->callee->function_symbol (&availability);
3381 807404 : isra_func_summary *to_ifs = func_sums->get (callee);
3382 382443 : if (!to_ifs || !to_ifs->m_candidate
3383 335773 : || (availability < AVAIL_AVAILABLE)
3384 1143177 : || vec_safe_is_empty (to_ifs->m_parameters))
3385 : {
3386 481344 : process_edge_to_unknown_caller (cs);
3387 481344 : return;
3388 : }
3389 326060 : isra_func_summary *from_ifs = func_sums->get (cs->caller);
3390 326060 : gcc_checking_assert (from_ifs);
3391 :
3392 326060 : isra_call_summary *csum = call_sums->get (cs);
3393 326060 : unsigned args_count = csum->m_arg_flow.length ();
3394 326060 : unsigned param_count = vec_safe_length (to_ifs->m_parameters);
3395 :
3396 1142736 : for (unsigned i = 0; i < args_count; i++)
3397 : {
3398 816676 : bool unused_in_callee;
3399 816676 : if (i < param_count)
3400 816672 : unused_in_callee = (*to_ifs->m_parameters)[i].locally_unused;
3401 : else
3402 : unused_in_callee = false;
3403 :
3404 816672 : if (!unused_in_callee)
3405 : {
3406 769172 : isra_param_flow *ipf = &csum->m_arg_flow[i];
3407 1005708 : for (int j = 0; j < ipf->length; j++)
3408 : {
3409 236536 : int input_idx = ipf->inputs[j];
3410 236536 : (*from_ifs->m_parameters)[input_idx].locally_unused = false;
3411 : }
3412 : }
3413 : }
3414 : }
3415 :
3416 : /* Unless it is already there, push NODE which is also described by IFS to
3417 : STACK. */
3418 :
3419 : static void
3420 154439 : isra_push_node_to_stack (cgraph_node *node, isra_func_summary *ifs,
3421 : vec<cgraph_node *> *stack)
3422 : {
3423 0 : if (!ifs->m_queued)
3424 : {
3425 154055 : ifs->m_queued = true;
3426 154055 : stack->safe_push (node);
3427 : }
3428 0 : }
3429 :
3430 : /* If parameter with index INPUT_IDX is marked as locally unused, mark it as
3431 : used and push CALLER on STACK. */
3432 :
3433 : static void
3434 11411 : isra_mark_caller_param_used (isra_func_summary *from_ifs, int input_idx,
3435 : cgraph_node *caller, vec<cgraph_node *> *stack)
3436 : {
3437 11411 : if ((*from_ifs->m_parameters)[input_idx].locally_unused)
3438 : {
3439 1095 : (*from_ifs->m_parameters)[input_idx].locally_unused = false;
3440 1853 : isra_push_node_to_stack (caller, from_ifs, stack);
3441 : }
3442 11411 : }
3443 :
3444 : /* Combine safe_size of DESC with SIZE and return true if it has changed. */
3445 :
3446 : static bool
3447 2371231 : update_safe_size (isra_param_desc *desc, unsigned size)
3448 : {
3449 0 : if (!desc->safe_size_set)
3450 : {
3451 761083 : desc->safe_size_set = 1;
3452 761083 : desc->safe_size = size;
3453 761083 : return true;
3454 : }
3455 1610148 : if (desc->safe_size <= size)
3456 : return false;
3457 20657 : desc->safe_size = size;
3458 20657 : return true;
3459 : }
3460 :
3461 : /* Set all param hints in DESC to the pessimistic values. Return true if any
3462 : hints that need to potentially trigger further propagation have changed. */
3463 :
3464 : static bool
3465 715717 : flip_all_hints_pessimistic (isra_param_desc *desc)
3466 : {
3467 715717 : desc->not_specially_constructed = true;
3468 0 : return update_safe_size (desc, 0);
3469 : }
3470 :
3471 : /* Because we have not analyzed or otherwise problematic caller, go over all
3472 : parameter int flags of IFS describing a call graph node of a calllee and
3473 : turn them pessimistic. Return true if any hints that need to potentially
3474 : trigger further propagation have changed. */
3475 :
3476 : static bool
3477 424838 : flip_all_param_hints_pessimistic (isra_func_summary *ifs)
3478 : {
3479 424838 : if (!ifs || !ifs->m_candidate)
3480 : return false;
3481 :
3482 25453 : bool ret = false;
3483 25453 : unsigned param_count = vec_safe_length (ifs->m_parameters);
3484 :
3485 71554 : for (unsigned i = 0; i < param_count; i++)
3486 92202 : ret |= flip_all_hints_pessimistic (&(*ifs->m_parameters)[i]);
3487 :
3488 : return ret;
3489 : }
3490 :
3491 : /* Propagate hints accross edge CS which ultimately leads to a node described
3492 : by TO_IFS. Return true if any hints of the callee which should potentially
3493 : trigger further propagation have changed. */
3494 :
3495 : static bool
3496 4823277 : propagate_param_hints_accross_call (cgraph_edge *cs, isra_func_summary *to_ifs)
3497 : {
3498 4823277 : if (!to_ifs || !to_ifs->m_candidate)
3499 : return false;
3500 :
3501 1604482 : isra_call_summary *csum = call_sums->get (cs);
3502 1604482 : bool ret = false;
3503 1604482 : unsigned args_count = csum->m_arg_flow.length ();
3504 1604482 : unsigned param_count = vec_safe_length (to_ifs->m_parameters);
3505 :
3506 5131764 : for (unsigned i = 0; i < param_count; i++)
3507 : {
3508 3527282 : isra_param_desc *desc = &(*to_ifs->m_parameters)[i];
3509 3527282 : if (i >= args_count)
3510 : {
3511 669616 : ret |= flip_all_hints_pessimistic (desc);
3512 669616 : continue;
3513 : }
3514 :
3515 2857666 : if (desc->by_ref)
3516 : {
3517 1655532 : isra_param_flow *ipf = &csum->m_arg_flow[i];
3518 :
3519 1655532 : if (!ipf->constructed_for_calls)
3520 1245210 : desc->not_specially_constructed = true;
3521 :
3522 1655532 : if (ipf->pointer_pass_through)
3523 : {
3524 270399 : isra_func_summary *from_ifs = func_sums->get (cs->caller);
3525 270399 : int srcidx = get_single_param_flow_source (ipf);
3526 270399 : if (vec_safe_length (from_ifs->m_parameters) > (unsigned) srcidx)
3527 : {
3528 162419 : isra_param_desc *src_d = &(*from_ifs->m_parameters)[srcidx];
3529 162419 : if (src_d->safe_size_set)
3530 324802 : ret |= update_safe_size (desc, src_d->safe_size);
3531 : }
3532 : else
3533 215960 : ret |= update_safe_size (desc, 0);
3534 : }
3535 1385133 : else if (!ipf->aggregate_pass_through)
3536 2770264 : ret |= update_safe_size (desc, ipf->unit_size);
3537 : else
3538 : /* LTOing type-mismatched programs can end up here. */
3539 2 : ret |= update_safe_size (desc, 0);
3540 : }
3541 : }
3542 : return ret;
3543 : }
3544 :
3545 : /* Propagate hints from NODE described by FROM_IFS to all its (dorect) callees,
3546 : push those that may need re-visiting onto STACK. */
3547 :
3548 : static void
3549 1344204 : propagate_hints_to_all_callees (cgraph_node *node, isra_func_summary *from_ifs,
3550 : vec<cgraph_node *> *stack)
3551 : {
3552 6592319 : for (cgraph_edge *cs = node->callees; cs; cs = cs->next_callee)
3553 : {
3554 5248115 : enum availability availability;
3555 5248115 : cgraph_node *callee = cs->callee->function_symbol (&availability);
3556 5248115 : isra_func_summary *to_ifs = func_sums->get (callee);
3557 5248115 : if (!from_ifs)
3558 : {
3559 424838 : if (flip_all_param_hints_pessimistic (to_ifs)
3560 424838 : && ipa_edge_within_scc (cs))
3561 56 : isra_push_node_to_stack (callee, to_ifs, stack);
3562 : }
3563 4823277 : else if (propagate_param_hints_accross_call (cs, to_ifs)
3564 4823277 : && ipa_edge_within_scc (cs))
3565 4793 : isra_push_node_to_stack (callee, to_ifs, stack);
3566 : }
3567 1344204 : }
3568 :
3569 : /* Propagate information that any parameter is not used only locally within a
3570 : SCC across CS to the caller, which must be in the same SCC as the
3571 : callee. Push any callers that need to be re-processed to STACK. */
3572 :
3573 : static void
3574 27855 : propagate_used_across_scc_edge (cgraph_edge *cs, vec<cgraph_node *> *stack)
3575 : {
3576 27855 : isra_func_summary *from_ifs = func_sums->get (cs->caller);
3577 27855 : if (!from_ifs || vec_safe_is_empty (from_ifs->m_parameters))
3578 15265 : return;
3579 :
3580 12590 : isra_call_summary *csum = call_sums->get (cs);
3581 12590 : gcc_checking_assert (csum);
3582 12590 : unsigned args_count = csum->m_arg_flow.length ();
3583 12590 : enum availability availability;
3584 12590 : cgraph_node *callee = cs->callee->function_symbol (&availability);
3585 12590 : isra_func_summary *to_ifs = func_sums->get (callee);
3586 :
3587 12590 : unsigned param_count
3588 12473 : = (to_ifs && (availability >= AVAIL_AVAILABLE))
3589 24797 : ? vec_safe_length (to_ifs->m_parameters) : 0;
3590 36178 : for (unsigned i = 0; i < args_count; i++)
3591 : {
3592 26894 : if (i < param_count
3593 23588 : && (*to_ifs->m_parameters)[i].locally_unused)
3594 3306 : continue;
3595 :
3596 : /* The argument is needed in the callee it, we must mark the parameter as
3597 : used also in the caller and its callers within this SCC. */
3598 20282 : isra_param_flow *ipf = &csum->m_arg_flow[i];
3599 31693 : for (int j = 0; j < ipf->length; j++)
3600 : {
3601 11411 : int input_idx = ipf->inputs[j];
3602 11411 : isra_mark_caller_param_used (from_ifs, input_idx, cs->caller, stack);
3603 : }
3604 : }
3605 : }
3606 :
3607 : /* Propagate information that any parameter is not used only locally within a
3608 : SCC (i.e. is used also elsewhere) to all callers of NODE that are in the
3609 : same SCC. Push any callers that need to be re-processed to STACK. */
3610 :
3611 : static bool
3612 1418339 : propagate_used_to_scc_callers (cgraph_node *node, void *data)
3613 : {
3614 1418339 : vec<cgraph_node *> *stack = (vec<cgraph_node *> *) data;
3615 1418339 : cgraph_edge *cs;
3616 3445324 : for (cs = node->callers; cs; cs = cs->next_caller)
3617 2026985 : if (ipa_edge_within_scc (cs))
3618 27855 : propagate_used_across_scc_edge (cs, stack);
3619 1418339 : return false;
3620 : }
3621 :
3622 : /* Return true iff all certain accesses in ARG_DESC are also present as
3623 : certain accesses in PARAM_DESC. */
3624 :
3625 : static bool
3626 70 : all_callee_accesses_present_p (isra_param_desc *param_desc,
3627 : isra_param_desc *arg_desc)
3628 : {
3629 70 : unsigned aclen = vec_safe_length (arg_desc->accesses);
3630 74 : for (unsigned j = 0; j < aclen; j++)
3631 : {
3632 50 : param_access *argacc = (*arg_desc->accesses)[j];
3633 50 : if (!argacc->certain)
3634 0 : continue;
3635 100 : param_access *pacc = find_param_access (param_desc, argacc->unit_offset,
3636 50 : argacc->unit_size);
3637 50 : if (!pacc
3638 5 : || !pacc->certain
3639 55 : || !types_compatible_p (argacc->type, pacc->type))
3640 46 : return false;
3641 : }
3642 : return true;
3643 : }
3644 :
3645 : /* Type internal to function pull_accesses_from_callee. Unfortunately gcc 4.8
3646 : does not allow instantiating an auto_vec with a type defined within a
3647 : function so it is a global type. */
3648 : enum acc_prop_kind {ACC_PROP_DONT, ACC_PROP_COPY, ACC_PROP_CERTAIN};
3649 :
3650 :
3651 : /* Attempt to propagate all definite accesses from ARG_DESC to PARAM_DESC,
3652 : (which belongs to CALLER) if they would not violate some constraint there.
3653 : CALLER_IPCP_TS describes the caller, PARAM_IDX is the index of the parameter
3654 : described by PARAM_DESC. If successful, return NULL, otherwise return the
3655 : string reason for failure (which can be written to the dump file).
3656 : DELTA_OFFSET is the known offset of the actual argument withing the formal
3657 : parameter (so of ARG_DESCS within PARAM_DESCS), ARG_SIZE is the size of the
3658 : actual argument or zero, if not known. In case of success, set *CHANGE_P to
3659 : true if propagation actually changed anything. */
3660 :
3661 : static const char *
3662 5320 : pull_accesses_from_callee (cgraph_node *caller,
3663 : ipcp_transformation *caller_ipcp_ts,
3664 : int param_idx,
3665 : isra_param_desc *param_desc,
3666 : isra_param_desc *arg_desc,
3667 : unsigned delta_offset, unsigned arg_size,
3668 : bool *change_p)
3669 : {
3670 5320 : unsigned pclen = vec_safe_length (param_desc->accesses);
3671 5320 : unsigned aclen = vec_safe_length (arg_desc->accesses);
3672 5320 : unsigned prop_count = 0;
3673 5320 : unsigned prop_size = 0;
3674 5320 : bool change = false;
3675 :
3676 5320 : auto_vec <enum acc_prop_kind, 8> prop_kinds (aclen);
3677 13117 : for (unsigned j = 0; j < aclen; j++)
3678 : {
3679 7999 : param_access *argacc = (*arg_desc->accesses)[j];
3680 7999 : prop_kinds.safe_push (ACC_PROP_DONT);
3681 :
3682 7999 : if (arg_size > 0
3683 2700 : && argacc->unit_offset + argacc->unit_size > arg_size)
3684 : return "callee access outsize size boundary";
3685 :
3686 7999 : if (!argacc->certain)
3687 382 : continue;
3688 :
3689 7617 : unsigned offset = argacc->unit_offset + delta_offset;
3690 :
3691 7617 : if (caller_ipcp_ts && !AGGREGATE_TYPE_P (argacc->type))
3692 : {
3693 399 : ipa_argagg_value_list avl (caller_ipcp_ts);
3694 399 : tree value = avl.get_value (param_idx, offset);
3695 399 : if (value && ((tree_to_uhwi (TYPE_SIZE (TREE_TYPE (value)))
3696 48 : / BITS_PER_UNIT)
3697 48 : != argacc->unit_size))
3698 1 : return " propagated access would conflict with an IPA-CP constant";
3699 : }
3700 :
3701 : /* Given that accesses are initially stored according to increasing
3702 : offset and decreasing size in case of equal offsets, the following
3703 : searches could be written more efficiently if we kept the ordering
3704 : when copying. But the number of accesses is capped at
3705 : PARAM_IPA_SRA_MAX_REPLACEMENTS (so most likely 8) and the code gets
3706 : messy quickly, so let's improve on that only if necessary. */
3707 :
3708 : bool exact_match = false;
3709 16241 : for (unsigned i = 0; i < pclen; i++)
3710 : {
3711 : /* Check for overlaps. */
3712 8826 : param_access *pacc = (*param_desc->accesses)[i];
3713 8826 : if (pacc->unit_offset == offset
3714 4213 : && pacc->unit_size == argacc->unit_size)
3715 : {
3716 3058 : if (argacc->alias_ptr_type != pacc->alias_ptr_type
3717 2858 : || !types_compatible_p (argacc->type, pacc->type)
3718 5916 : || argacc->reverse != pacc->reverse)
3719 200 : return "propagated access types would not match existing ones";
3720 :
3721 2858 : exact_match = true;
3722 2858 : if (!pacc->certain)
3723 : {
3724 0 : prop_kinds[j] = ACC_PROP_CERTAIN;
3725 0 : prop_size += argacc->unit_size;
3726 0 : change = true;
3727 : }
3728 2858 : continue;
3729 : }
3730 :
3731 5768 : if (offset < pacc->unit_offset + pacc->unit_size
3732 3614 : && offset + argacc->unit_size > pacc->unit_offset)
3733 : {
3734 : /* None permissible with load accesses, possible to fit into
3735 : argument ones. */
3736 2319 : if (pacc->certain
3737 2318 : || offset < pacc->unit_offset
3738 2318 : || (offset + argacc->unit_size
3739 : > pacc->unit_offset + pacc->unit_size))
3740 : return "a propagated access would conflict in caller";
3741 : }
3742 : }
3743 :
3744 7415 : if (!exact_match)
3745 : {
3746 4557 : prop_kinds[j] = ACC_PROP_COPY;
3747 4557 : prop_count++;
3748 4557 : prop_size += argacc->unit_size;
3749 4557 : change = true;
3750 : }
3751 : }
3752 :
3753 5118 : if (!change)
3754 : return NULL;
3755 :
3756 3020 : if ((prop_count + pclen
3757 3020 : > (unsigned) opt_for_fn (caller->decl, param_ipa_sra_max_replacements))
3758 8340 : || size_would_violate_limit_p (param_desc,
3759 3020 : param_desc->size_reached + prop_size))
3760 : return "propagating accesses would violate the count or size limit";
3761 :
3762 3001 : *change_p = true;
3763 7923 : for (unsigned j = 0; j < aclen; j++)
3764 : {
3765 4922 : if (prop_kinds[j] == ACC_PROP_COPY)
3766 : {
3767 4528 : param_access *argacc = (*arg_desc->accesses)[j];
3768 :
3769 4528 : param_access *copy = ggc_cleared_alloc<param_access> ();
3770 4528 : copy->unit_offset = argacc->unit_offset + delta_offset;
3771 4528 : copy->unit_size = argacc->unit_size;
3772 4528 : copy->type = argacc->type;
3773 4528 : copy->alias_ptr_type = argacc->alias_ptr_type;
3774 4528 : copy->certain = true;
3775 4528 : copy->reverse = argacc->reverse;
3776 4528 : vec_safe_push (param_desc->accesses, copy);
3777 : }
3778 394 : else if (prop_kinds[j] == ACC_PROP_CERTAIN)
3779 : {
3780 0 : param_access *argacc = (*arg_desc->accesses)[j];
3781 0 : param_access *csp
3782 0 : = find_param_access (param_desc, argacc->unit_offset + delta_offset,
3783 0 : argacc->unit_size);
3784 0 : csp->certain = true;
3785 : }
3786 : }
3787 :
3788 3001 : param_desc->size_reached += prop_size;
3789 :
3790 3001 : return NULL;
3791 5320 : }
3792 :
3793 : /* Propagate parameter splitting information through call graph edge CS.
3794 : Return true if any changes that might need to be propagated within SCCs have
3795 : been made. The function also clears the aggregate_pass_through and
3796 : pointer_pass_through in call summaries which do not need to be processed
3797 : again if this CS is revisited when iterating while changes are propagated
3798 : within an SCC. */
3799 :
3800 : static bool
3801 1514017 : param_splitting_across_edge (cgraph_edge *cs)
3802 : {
3803 1514017 : bool res = false;
3804 1514017 : bool cross_scc = !ipa_edge_within_scc (cs);
3805 1514017 : enum availability availability;
3806 1514017 : cgraph_node *callee = cs->callee->function_symbol (&availability);
3807 1514017 : isra_func_summary *from_ifs = func_sums->get (cs->caller);
3808 1514017 : gcc_checking_assert (from_ifs && from_ifs->m_parameters);
3809 1514017 : ipcp_transformation *caller_ipcp_ts
3810 1514017 : = ipcp_get_transformation_summary (cs->caller);
3811 :
3812 1514017 : isra_call_summary *csum = call_sums->get (cs);
3813 1514017 : gcc_checking_assert (csum);
3814 1514017 : unsigned args_count = csum->m_arg_flow.length ();
3815 1514017 : isra_func_summary *to_ifs = func_sums->get (callee);
3816 1514017 : unsigned param_count
3817 797682 : = ((to_ifs && to_ifs->m_candidate && (availability >= AVAIL_AVAILABLE))
3818 2217452 : ? vec_safe_length (to_ifs->m_parameters)
3819 : : 0);
3820 :
3821 1514017 : if (dump_file && (dump_flags & TDF_DETAILS))
3822 18 : fprintf (dump_file, "Splitting across %s->%s:\n",
3823 9 : cs->caller->dump_name (), callee->dump_name ());
3824 :
3825 : unsigned i;
3826 2946575 : for (i = 0; (i < args_count) && (i < param_count); i++)
3827 : {
3828 1432558 : isra_param_desc *arg_desc = &(*to_ifs->m_parameters)[i];
3829 1432558 : isra_param_flow *ipf = &csum->m_arg_flow[i];
3830 :
3831 1432558 : if (arg_desc->locally_unused)
3832 : {
3833 84044 : if (dump_file && (dump_flags & TDF_DETAILS))
3834 0 : fprintf (dump_file, " ->%u: unused in callee\n", i);
3835 84044 : ipf->pointer_pass_through = false;
3836 84044 : continue;
3837 : }
3838 :
3839 1348514 : if (ipf->pointer_pass_through)
3840 : {
3841 164259 : int idx = get_single_param_flow_source (ipf);
3842 164259 : isra_param_desc *param_desc = &(*from_ifs->m_parameters)[idx];
3843 164259 : if (!param_desc->split_candidate)
3844 115992 : continue;
3845 48267 : gcc_assert (param_desc->by_ref);
3846 :
3847 48267 : if (!arg_desc->split_candidate || !arg_desc->by_ref)
3848 : {
3849 42398 : if (dump_file && (dump_flags & TDF_DETAILS))
3850 2 : fprintf (dump_file, " %u->%u: not candidate or not by "
3851 : "reference in callee\n", idx, i);
3852 42398 : param_desc->split_candidate = false;
3853 42398 : ipf->pointer_pass_through = false;
3854 42398 : res = true;
3855 : }
3856 5869 : else if (!ipf->safe_to_import_accesses)
3857 : {
3858 1850 : if (!csum->m_before_any_store
3859 1850 : || !all_callee_accesses_present_p (param_desc, arg_desc))
3860 : {
3861 1826 : if (dump_file && (dump_flags & TDF_DETAILS))
3862 0 : fprintf (dump_file, " %u->%u: cannot import accesses.\n",
3863 : idx, i);
3864 1826 : param_desc->split_candidate = false;
3865 1826 : ipf->pointer_pass_through = false;
3866 1826 : res = true;
3867 :
3868 : }
3869 : else
3870 : {
3871 24 : if (dump_file && (dump_flags & TDF_DETAILS))
3872 0 : fprintf (dump_file, " %u->%u: verified callee accesses "
3873 : "present.\n", idx, i);
3874 24 : if (cross_scc)
3875 0 : ipf->pointer_pass_through = false;
3876 : }
3877 : }
3878 : else
3879 : {
3880 4019 : const char *pull_failure
3881 4019 : = pull_accesses_from_callee (cs->caller, caller_ipcp_ts, idx,
3882 : param_desc, arg_desc, 0, 0, &res);
3883 4019 : if (pull_failure)
3884 : {
3885 13 : if (dump_file && (dump_flags & TDF_DETAILS))
3886 0 : fprintf (dump_file, " %u->%u: by_ref access pull "
3887 : "failed: %s.\n", idx, i, pull_failure);
3888 13 : param_desc->split_candidate = false;
3889 13 : ipf->pointer_pass_through = false;
3890 13 : res = true;
3891 : }
3892 : else
3893 : {
3894 4006 : if (dump_file && (dump_flags & TDF_DETAILS))
3895 1 : fprintf (dump_file, " %u->%u: by_ref access pull "
3896 : "succeeded.\n", idx, i);
3897 4006 : if (cross_scc)
3898 3931 : ipf->pointer_pass_through = false;
3899 : }
3900 : }
3901 : }
3902 1184255 : else if (ipf->aggregate_pass_through)
3903 : {
3904 33923 : int idx = get_single_param_flow_source (ipf);
3905 33923 : isra_param_desc *param_desc = &(*from_ifs->m_parameters)[idx];
3906 33923 : if (!param_desc->split_candidate)
3907 21773 : continue;
3908 12150 : gcc_assert (!param_desc->by_ref);
3909 24300 : param_access *pacc = find_param_access (param_desc, ipf->unit_offset,
3910 12150 : ipf->unit_size);
3911 12150 : gcc_checking_assert (pacc);
3912 :
3913 12150 : if (pacc->certain)
3914 : {
3915 1 : if (dump_file && (dump_flags & TDF_DETAILS))
3916 0 : fprintf (dump_file, " %u->%u: already certain\n", idx, i);
3917 1 : ipf->aggregate_pass_through = false;
3918 : }
3919 12149 : else if (!arg_desc->split_candidate || arg_desc->by_ref)
3920 : {
3921 10848 : if (dump_file && (dump_flags & TDF_DETAILS))
3922 0 : fprintf (dump_file, " %u->%u: not candidate or by "
3923 : "reference in callee\n", idx, i);
3924 :
3925 10848 : pacc->certain = true;
3926 10848 : if (overlapping_certain_accesses_p (param_desc, NULL))
3927 : {
3928 1492 : if (dump_file && (dump_flags & TDF_DETAILS))
3929 0 : fprintf (dump_file, " ...leading to overlap, "
3930 : " disqualifying candidate parameter %u\n",
3931 : idx);
3932 1492 : param_desc->split_candidate = false;
3933 : }
3934 : else
3935 9356 : bump_reached_size (param_desc, pacc->unit_size, idx);
3936 :
3937 10848 : ipf->aggregate_pass_through = false;
3938 10848 : res = true;
3939 : }
3940 : else
3941 : {
3942 1301 : const char *pull_failure
3943 1301 : = pull_accesses_from_callee (cs->caller, caller_ipcp_ts, idx,
3944 : param_desc, arg_desc,
3945 : ipf->unit_offset,
3946 : ipf->unit_size, &res);
3947 1301 : if (pull_failure)
3948 : {
3949 208 : if (dump_file && (dump_flags & TDF_DETAILS))
3950 0 : fprintf (dump_file, " %u->%u: arg access pull "
3951 : "failed: %s.\n", idx, i, pull_failure);
3952 :
3953 208 : ipf->aggregate_pass_through = false;
3954 208 : pacc->certain = true;
3955 :
3956 208 : if (overlapping_certain_accesses_p (param_desc, NULL))
3957 : {
3958 208 : if (dump_file && (dump_flags & TDF_DETAILS))
3959 0 : fprintf (dump_file, " ...leading to overlap, "
3960 : " disqualifying candidate parameter %u\n",
3961 : idx);
3962 208 : param_desc->split_candidate = false;
3963 : }
3964 : else
3965 0 : bump_reached_size (param_desc, pacc->unit_size, idx);
3966 :
3967 208 : res = true;
3968 : }
3969 : else
3970 : {
3971 1093 : if (dump_file && (dump_flags & TDF_DETAILS))
3972 0 : fprintf (dump_file, " %u->%u: arg access pull "
3973 : "succeeded.\n", idx, i);
3974 1093 : if (cross_scc)
3975 954 : ipf->aggregate_pass_through = false;
3976 : }
3977 : }
3978 : }
3979 : }
3980 :
3981 : /* Handle argument-parameter count mismatches. */
3982 2460032 : for (; (i < args_count); i++)
3983 : {
3984 946015 : isra_param_flow *ipf = &csum->m_arg_flow[i];
3985 :
3986 946015 : if (ipf->pointer_pass_through || ipf->aggregate_pass_through)
3987 : {
3988 200495 : int idx = get_single_param_flow_source (ipf);
3989 200495 : ipf->pointer_pass_through = false;
3990 200495 : ipf->aggregate_pass_through = false;
3991 200495 : isra_param_desc *param_desc = &(*from_ifs->m_parameters)[idx];
3992 200495 : if (!param_desc->split_candidate)
3993 200412 : continue;
3994 :
3995 83 : if (dump_file && (dump_flags & TDF_DETAILS))
3996 0 : fprintf (dump_file, " %u->%u: no corresponding formal parameter\n",
3997 : idx, i);
3998 83 : param_desc->split_candidate = false;
3999 83 : res = true;
4000 : }
4001 : }
4002 1514017 : return res;
4003 : }
4004 :
4005 : /* Worker for call_for_symbol_and_aliases, look at all callers and if all their
4006 : callers ignore the return value, or come from the same SCC and use the
4007 : return value only to compute their return value, return false, otherwise
4008 : return true. */
4009 :
4010 : static bool
4011 182062 : retval_used_p (cgraph_node *node, void *)
4012 : {
4013 270798 : for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
4014 : {
4015 239129 : isra_call_summary *csum = call_sums->get (cs);
4016 239129 : gcc_checking_assert (csum);
4017 239129 : if (csum->m_return_ignored)
4018 82918 : continue;
4019 156211 : if (!csum->m_return_returned)
4020 : return true;
4021 :
4022 28444 : isra_func_summary *from_ifs = func_sums->get (cs->caller);
4023 28444 : if (!from_ifs || !from_ifs->m_candidate)
4024 : return true;
4025 :
4026 21757 : if (!ipa_edge_within_scc (cs)
4027 21757 : && !from_ifs->m_return_ignored)
4028 : return true;
4029 : }
4030 :
4031 : return false;
4032 : }
4033 :
4034 : /* Push into NEW_PARAMS all required parameter adjustment entries to copy or
4035 : modify parameter which originally had index BASE_INDEX, in the adjustment
4036 : vector of parent clone (if any) had PREV_CLONE_INDEX and was described by
4037 : PREV_ADJUSTMENT. If IPA-CP has created a transformation summary for the
4038 : original node, it needs to be passed in IPCP_TS, otherwise it should be
4039 : NULL. If the parent clone is the original function, PREV_ADJUSTMENT is NULL
4040 : and PREV_CLONE_INDEX is equal to BASE_INDEX. */
4041 :
4042 : static void
4043 307291 : push_param_adjustments_for_index (isra_func_summary *ifs, unsigned base_index,
4044 : unsigned prev_clone_index,
4045 : ipa_adjusted_param *prev_adjustment,
4046 : ipcp_transformation *ipcp_ts,
4047 : vec<ipa_adjusted_param, va_gc> **new_params)
4048 : {
4049 307291 : isra_param_desc *desc = &(*ifs->m_parameters)[base_index];
4050 307291 : if (desc->locally_unused)
4051 : {
4052 62503 : if (dump_file)
4053 27 : fprintf (dump_file, " Will remove parameter %u\n", base_index);
4054 62503 : return;
4055 : }
4056 :
4057 244788 : if (!desc->split_candidate)
4058 : {
4059 198765 : ipa_adjusted_param adj;
4060 198765 : if (prev_adjustment)
4061 : {
4062 1893 : adj = *prev_adjustment;
4063 1893 : adj.prev_clone_adjustment = true;
4064 1893 : adj.prev_clone_index = prev_clone_index;
4065 : }
4066 : else
4067 : {
4068 196872 : memset (&adj, 0, sizeof (adj));
4069 196872 : adj.op = IPA_PARAM_OP_COPY;
4070 196872 : adj.base_index = base_index;
4071 196872 : adj.prev_clone_index = prev_clone_index;
4072 : }
4073 198765 : vec_safe_push ((*new_params), adj);
4074 198765 : return;
4075 : }
4076 :
4077 46023 : if (dump_file)
4078 39 : fprintf (dump_file, " Will split parameter %u\n", base_index);
4079 :
4080 46023 : gcc_assert (!prev_adjustment || prev_adjustment->op == IPA_PARAM_OP_COPY);
4081 46023 : unsigned aclen = vec_safe_length (desc->accesses);
4082 129634 : for (unsigned j = 0; j < aclen; j++)
4083 : {
4084 83611 : param_access *pa = (*desc->accesses)[j];
4085 83611 : if (!pa->certain)
4086 7632 : continue;
4087 :
4088 82755 : if (ipcp_ts)
4089 : {
4090 14787 : ipa_argagg_value_list avl (ipcp_ts);
4091 14787 : tree value = avl.get_value (base_index, pa->unit_offset);
4092 14787 : if (value && !AGGREGATE_TYPE_P (pa->type))
4093 : {
4094 6776 : if (dump_file)
4095 20 : fprintf (dump_file, " - omitting component at byte "
4096 : "offset %u which is known to have a constant value\n ",
4097 : pa->unit_offset);
4098 6776 : continue;
4099 : }
4100 : }
4101 :
4102 75979 : if (dump_file)
4103 38 : fprintf (dump_file, " - component at byte offset %u, "
4104 38 : "size %u\n", pa->unit_offset, pa->unit_size);
4105 :
4106 75979 : ipa_adjusted_param adj;
4107 75979 : memset (&adj, 0, sizeof (adj));
4108 75979 : adj.op = IPA_PARAM_OP_SPLIT;
4109 75979 : adj.base_index = base_index;
4110 75979 : adj.prev_clone_index = prev_clone_index;
4111 75979 : adj.param_prefix_index = IPA_PARAM_PREFIX_ISRA;
4112 75979 : adj.reverse = pa->reverse;
4113 75979 : adj.type = pa->type;
4114 75979 : adj.alias_ptr_type = pa->alias_ptr_type;
4115 75979 : adj.unit_offset = pa->unit_offset;
4116 75979 : vec_safe_push ((*new_params), adj);
4117 : }
4118 : }
4119 :
4120 : /* Worker for all call_for_symbol_thunks_and_aliases. Set calls_comdat_local
4121 : flag of all callers of NODE. */
4122 :
4123 : static bool
4124 0 : mark_callers_calls_comdat_local (struct cgraph_node *node, void *)
4125 : {
4126 0 : for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
4127 0 : cs->caller->calls_comdat_local = true;
4128 0 : return false;
4129 : }
4130 :
4131 : /* Remove any IPA-CP results stored in TS that are associated with removed
4132 : parameters as marked in IFS. */
4133 :
4134 : static void
4135 8381 : zap_useless_ipcp_results (const isra_func_summary *ifs, ipcp_transformation *ts)
4136 : {
4137 8381 : ts->remove_argaggs_if ([ifs](const ipa_argagg_value &v)
4138 : {
4139 15335 : return (*ifs->m_parameters)[v.index].locally_unused;
4140 : });
4141 :
4142 8381 : bool useful_vr = false;
4143 8381 : unsigned count = vec_safe_length (ts->m_vr);
4144 29766 : for (unsigned i = 0; i < count; i++)
4145 21385 : if ((*ts->m_vr)[i].known_p ())
4146 : {
4147 14840 : const isra_param_desc *desc = &(*ifs->m_parameters)[i];
4148 14840 : if (desc->locally_unused)
4149 1948 : (*ts->m_vr)[i].set_unknown ();
4150 : else
4151 : useful_vr = true;
4152 : }
4153 8381 : if (!useful_vr)
4154 1261 : ts->m_vr = NULL;
4155 8381 : }
4156 :
4157 : /* Do final processing of results of IPA propagation regarding NODE, clone it
4158 : if appropriate. */
4159 :
4160 : static void
4161 1267183 : process_isra_node_results (cgraph_node *node,
4162 : hash_map<const char *, unsigned> *clone_num_suffixes)
4163 : {
4164 1267183 : isra_func_summary *ifs = func_sums->get (node);
4165 1267183 : if (!ifs || !ifs->m_candidate)
4166 1158550 : return;
4167 :
4168 368269 : auto_vec<bool, 16> surviving_params;
4169 368269 : bool check_surviving = false;
4170 368269 : clone_info *cinfo = clone_info::get (node);
4171 368269 : if (cinfo && cinfo->param_adjustments)
4172 : {
4173 15406 : check_surviving = true;
4174 15406 : cinfo->param_adjustments->get_surviving_params (&surviving_params);
4175 : }
4176 :
4177 368269 : unsigned param_count = vec_safe_length (ifs->m_parameters);
4178 368269 : bool will_change_function = false;
4179 368269 : if (ifs->m_returns_value && ifs->m_return_ignored)
4180 : will_change_function = true;
4181 : else
4182 860298 : for (unsigned i = 0; i < param_count; i++)
4183 : {
4184 600662 : isra_param_desc *desc = &(*ifs->m_parameters)[i];
4185 548343 : if ((desc->locally_unused || desc->split_candidate)
4186 : /* Make sure we do not clone just to attempt to remove an already
4187 : removed unused argument. */
4188 634031 : && (!check_surviving
4189 525768 : || (i < surviving_params.length ()
4190 2590 : && surviving_params[i])))
4191 : {
4192 : will_change_function = true;
4193 : break;
4194 : }
4195 : }
4196 337120 : if (!will_change_function)
4197 259636 : return;
4198 :
4199 108633 : if (dump_file)
4200 : {
4201 61 : fprintf (dump_file, "\nEvaluating analysis results for %s\n",
4202 : node->dump_name ());
4203 61 : if (ifs->m_returns_value && ifs->m_return_ignored)
4204 15 : fprintf (dump_file, " Will remove return value.\n");
4205 : }
4206 :
4207 108633 : ipcp_transformation *ipcp_ts = ipcp_get_transformation_summary (node);
4208 108633 : if (ipcp_ts)
4209 8381 : zap_useless_ipcp_results (ifs, ipcp_ts);
4210 108633 : vec<ipa_adjusted_param, va_gc> *new_params = NULL;
4211 108633 : if (ipa_param_adjustments *old_adjustments
4212 108633 : = cinfo ? cinfo->param_adjustments : NULL)
4213 : {
4214 2616 : unsigned old_adj_len = vec_safe_length (old_adjustments->m_adj_params);
4215 6397 : for (unsigned i = 0; i < old_adj_len; i++)
4216 : {
4217 3781 : ipa_adjusted_param *old_adj = &(*old_adjustments->m_adj_params)[i];
4218 3781 : push_param_adjustments_for_index (ifs, old_adj->base_index, i,
4219 : old_adj, ipcp_ts, &new_params);
4220 : }
4221 : }
4222 : else
4223 409527 : for (unsigned i = 0; i < param_count; i++)
4224 303510 : push_param_adjustments_for_index (ifs, i, i, NULL, ipcp_ts, &new_params);
4225 :
4226 108633 : ipa_param_adjustments *new_adjustments
4227 108633 : = (new (ggc_alloc <ipa_param_adjustments> ())
4228 : ipa_param_adjustments (new_params, param_count,
4229 186117 : ifs->m_returns_value && ifs->m_return_ignored));
4230 :
4231 108633 : if (dump_file && (dump_flags & TDF_DETAILS))
4232 : {
4233 9 : fprintf (dump_file, "\n Created adjustments:\n");
4234 9 : new_adjustments->dump (dump_file);
4235 : }
4236 :
4237 325899 : unsigned &suffix_counter = clone_num_suffixes->get_or_insert (
4238 108633 : IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (
4239 : node->decl)));
4240 108633 : auto_vec<cgraph_edge *> callers = node->collect_callers ();
4241 108633 : cgraph_node *new_node
4242 108633 : = node->create_virtual_clone (callers, NULL, new_adjustments, "isra",
4243 : suffix_counter);
4244 108633 : suffix_counter++;
4245 108633 : if (node->calls_comdat_local && node->same_comdat_group)
4246 : {
4247 0 : new_node->add_to_same_comdat_group (node);
4248 0 : new_node->call_for_symbol_and_aliases (mark_callers_calls_comdat_local,
4249 : NULL, true);
4250 : }
4251 108633 : new_node->calls_comdat_local = node->calls_comdat_local;
4252 :
4253 108633 : if (dump_file)
4254 61 : fprintf (dump_file, " Created new node %s\n", new_node->dump_name ());
4255 108633 : callers.release ();
4256 368269 : }
4257 :
4258 : /* If INDICES is not empty, dump a combination of NODE's dump_name and MSG
4259 : followed by the list of numbers in INDICES. */
4260 :
4261 : static void
4262 630122 : dump_list_of_param_indices (const cgraph_node *node, const char* msg,
4263 : const vec<unsigned> &indices)
4264 : {
4265 630122 : if (indices.is_empty ())
4266 : return;
4267 1 : fprintf (dump_file, "The following parameters of %s %s:", node->dump_name (),
4268 : msg);
4269 4 : for (unsigned i : indices)
4270 1 : fprintf (dump_file, " %u", i);
4271 1 : fprintf (dump_file, "\n");
4272 : }
4273 :
4274 : /* Check which parameters of NODE described by IFS have survived until IPA-SRA
4275 : and disable transformations for those which have not or which should not
4276 : transformed because the associated debug counter reached its limit. Return
4277 : true if none survived or if there were no candidates to begin with.
4278 : Additionally, also adjust parameter descriptions based on debug counters and
4279 : hints propagated earlier. */
4280 :
4281 : static bool
4282 368269 : adjust_parameter_descriptions (cgraph_node *node, isra_func_summary *ifs)
4283 : {
4284 368269 : bool ret = true;
4285 368269 : unsigned len = vec_safe_length (ifs->m_parameters);
4286 315061 : if (!len)
4287 : return true;
4288 :
4289 315061 : auto_vec<bool, 16> surviving_params;
4290 315061 : bool check_surviving = false;
4291 315061 : clone_info *cinfo = clone_info::get (node);
4292 315061 : if (cinfo && cinfo->param_adjustments)
4293 : {
4294 15406 : check_surviving = true;
4295 15406 : cinfo->param_adjustments->get_surviving_params (&surviving_params);
4296 : }
4297 315061 : ipcp_transformation *ipcp_ts = ipcp_get_transformation_summary (node);
4298 315061 : auto_vec <unsigned> dump_dead_indices;
4299 315061 : auto_vec <unsigned> dump_bad_cond_indices;
4300 1078469 : for (unsigned i = 0; i < len; i++)
4301 : {
4302 763408 : isra_param_desc *desc = &(*ifs->m_parameters)[i];
4303 763408 : if (!dbg_cnt (ipa_sra_params))
4304 : {
4305 0 : desc->locally_unused = false;
4306 0 : desc->split_candidate = false;
4307 0 : continue;
4308 : }
4309 :
4310 763408 : if (desc->split_only_when_retval_removed
4311 6951 : && !ifs->m_return_ignored)
4312 : {
4313 0 : if (dump_file && (dump_flags & TDF_DETAILS)
4314 1704 : && (desc->locally_unused || desc->split_candidate))
4315 0 : dump_bad_cond_indices.safe_push (i);
4316 :
4317 1704 : gcc_checking_assert (!desc->locally_unused
4318 : || desc->remove_only_when_retval_removed);
4319 1704 : desc->locally_unused = false;
4320 1704 : desc->split_candidate = false;
4321 1704 : continue;
4322 : }
4323 761704 : if (desc->remove_only_when_retval_removed
4324 43531 : && !ifs->m_return_ignored)
4325 : {
4326 6 : if (dump_file && (dump_flags & TDF_DETAILS)
4327 34490 : && (desc->locally_unused || desc->split_candidate))
4328 0 : dump_bad_cond_indices.safe_push (i);
4329 :
4330 34490 : desc->locally_unused = false;
4331 : }
4332 761704 : if (check_surviving
4333 806583 : && (i >= surviving_params.length ()
4334 21052 : || !surviving_params[i]))
4335 : {
4336 : /* Even if the parameter was removed by a previous IPA pass, we do
4337 : not clear locally_unused because if it really is unused, this
4338 : information might be useful in callers. */
4339 28379 : desc->split_candidate = false;
4340 :
4341 28379 : if (dump_file && (dump_flags & TDF_DETAILS))
4342 0 : dump_dead_indices.safe_push (i);
4343 : }
4344 :
4345 761704 : if (desc->split_candidate && desc->conditionally_dereferenceable)
4346 : {
4347 914 : gcc_assert (desc->safe_size_set);
4348 1535 : for (param_access *pa : *desc->accesses)
4349 1376 : if ((pa->unit_offset + pa->unit_size) > desc->safe_size)
4350 : {
4351 755 : if (dump_file && (dump_flags & TDF_DETAILS))
4352 1 : dump_bad_cond_indices.safe_push (i);
4353 755 : desc->split_candidate = false;
4354 755 : break;
4355 : }
4356 : }
4357 :
4358 761704 : if (desc->split_candidate)
4359 : {
4360 196611 : if (desc->by_ref && !desc->not_specially_constructed)
4361 : {
4362 28703 : int extra_factor
4363 28703 : = opt_for_fn (node->decl,
4364 : param_ipa_sra_ptrwrap_growth_factor);
4365 28703 : desc->param_size_limit = extra_factor * desc->param_size_limit;
4366 : }
4367 196611 : if (size_would_violate_limit_p (desc, desc->size_reached))
4368 3266 : desc->split_candidate = false;
4369 : }
4370 :
4371 : /* Avoid ICEs on size-mismatched VIEW_CONVERT_EXPRs when callers and
4372 : callees don't agree on types in aggregates and we try to do both
4373 : IPA-CP and IPA-SRA. */
4374 761704 : if (ipcp_ts && desc->split_candidate)
4375 : {
4376 22488 : ipa_argagg_value_list avl (ipcp_ts);
4377 55429 : for (const param_access *pa : desc->accesses)
4378 : {
4379 16394 : if (!pa->certain)
4380 1009 : continue;
4381 15385 : tree value = avl.get_value (i, pa->unit_offset);
4382 15385 : if (value
4383 15385 : && ((tree_to_uhwi (TYPE_SIZE (TREE_TYPE (value)))
4384 6879 : / BITS_PER_UNIT)
4385 6879 : != pa->unit_size))
4386 : {
4387 43 : desc->split_candidate = false;
4388 43 : if (dump_file && (dump_flags & TDF_DETAILS))
4389 0 : dump_dead_indices.safe_push (i);
4390 : break;
4391 : }
4392 : }
4393 : }
4394 :
4395 761704 : if (desc->locally_unused || desc->split_candidate)
4396 763408 : ret = false;
4397 : }
4398 :
4399 315061 : dump_list_of_param_indices (node, "are dead on arrival or have a type "
4400 : "mismatch with IPA-CP", dump_dead_indices);
4401 315061 : dump_list_of_param_indices (node, "fail additional requirements ",
4402 : dump_bad_cond_indices);
4403 :
4404 315061 : return ret;
4405 315061 : }
4406 :
4407 :
4408 : /* Run the interprocedural part of IPA-SRA. */
4409 :
4410 : static unsigned int
4411 125936 : ipa_sra_analysis (void)
4412 : {
4413 125936 : if (dump_file)
4414 : {
4415 54 : fprintf (dump_file, "\n========== IPA-SRA IPA stage ==========\n");
4416 54 : ipa_sra_dump_all_summaries (dump_file, false);
4417 : }
4418 :
4419 125936 : gcc_checking_assert (func_sums);
4420 125936 : gcc_checking_assert (call_sums);
4421 125936 : cgraph_node **order = XCNEWVEC (cgraph_node *, symtab->cgraph_count);
4422 125936 : auto_vec <cgraph_node *, 16> stack;
4423 125936 : int node_scc_count = ipa_reduced_postorder (order, true, NULL);
4424 :
4425 : /* One sweep from callers to callees for return value removal. */
4426 1462426 : for (int i = node_scc_count - 1; i >= 0 ; i--)
4427 : {
4428 1336490 : cgraph_node *scc_rep = order[i];
4429 1336490 : vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (scc_rep);
4430 :
4431 : /* Preliminary IPA function level checks. */
4432 5351273 : for (cgraph_node *v : cycle_nodes)
4433 : {
4434 1341803 : isra_func_summary *ifs = func_sums->get (v);
4435 1341803 : if (!ifs || !ifs->m_candidate)
4436 316594 : continue;
4437 1025209 : if (!ipa_sra_ipa_function_checks (v)
4438 1025209 : || check_all_callers_for_issues (v))
4439 656940 : ifs->zap ();
4440 : }
4441 :
4442 4014783 : for (cgraph_node *v : cycle_nodes)
4443 : {
4444 1341803 : isra_func_summary *ifs = func_sums->get (v);
4445 1341803 : if (!ifs || !ifs->m_candidate)
4446 973534 : continue;
4447 368269 : bool return_needed
4448 368269 : = (ifs->m_returns_value
4449 368269 : && (!dbg_cnt (ipa_sra_retvalues)
4450 182045 : || v->call_for_symbol_and_aliases (retval_used_p,
4451 368269 : NULL, true)));
4452 368269 : ifs->m_return_ignored = !return_needed;
4453 368269 : if (return_needed)
4454 300786 : isra_push_node_to_stack (v, ifs, &stack);
4455 : }
4456 :
4457 1487386 : while (!stack.is_empty ())
4458 : {
4459 150896 : cgraph_node *node = stack.pop ();
4460 150896 : isra_func_summary *ifs = func_sums->get (node);
4461 150896 : gcc_checking_assert (ifs && ifs->m_queued);
4462 150896 : ifs->m_queued = false;
4463 :
4464 848200 : for (cgraph_edge *cs = node->callees; cs; cs = cs->next_callee)
4465 697304 : if (ipa_edge_within_scc (cs)
4466 697304 : && call_sums->get (cs)->m_return_returned)
4467 : {
4468 1039 : enum availability av;
4469 1039 : cgraph_node *callee = cs->callee->function_symbol (&av);
4470 1039 : isra_func_summary *to_ifs = func_sums->get (callee);
4471 1039 : if (to_ifs && to_ifs->m_return_ignored)
4472 : {
4473 503 : to_ifs->m_return_ignored = false;
4474 1006 : isra_push_node_to_stack (callee, to_ifs, &stack);
4475 : }
4476 : }
4477 : }
4478 :
4479 : /* Parameter hint propagation. */
4480 4014783 : for (cgraph_node *v : cycle_nodes)
4481 : {
4482 1341803 : isra_func_summary *ifs = func_sums->get (v);
4483 1341803 : propagate_hints_to_all_callees (v, ifs, &stack);
4484 : }
4485 :
4486 1338891 : while (!stack.is_empty ())
4487 : {
4488 2401 : cgraph_node *node = stack.pop ();
4489 2401 : isra_func_summary *ifs = func_sums->get (node);
4490 2401 : gcc_checking_assert (ifs && ifs->m_queued);
4491 2401 : ifs->m_queued = false;
4492 2401 : propagate_hints_to_all_callees (node, ifs, &stack);
4493 : }
4494 :
4495 1336490 : cycle_nodes.release ();
4496 : }
4497 :
4498 : /* One sweep from callees to callers for parameter removal and splitting. */
4499 1462426 : for (int i = 0; i < node_scc_count; i++)
4500 : {
4501 1336490 : cgraph_node *scc_rep = order[i];
4502 1336490 : vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (scc_rep);
4503 :
4504 : /* First step of parameter removal. */
4505 5351273 : for (cgraph_node *v : cycle_nodes)
4506 : {
4507 1341803 : isra_func_summary *ifs = func_sums->get (v);
4508 1341803 : if (!ifs || !ifs->m_candidate)
4509 973534 : continue;
4510 368269 : if (adjust_parameter_descriptions (v, ifs))
4511 193023 : continue;
4512 189911 : for (cgraph_edge *cs = v->indirect_calls; cs; cs = cs->next_callee)
4513 14665 : process_edge_to_unknown_caller (cs);
4514 987883 : for (cgraph_edge *cs = v->callees; cs; cs = cs->next_callee)
4515 812637 : if (!ipa_edge_within_scc (cs))
4516 807404 : param_removal_cross_scc_edge (cs);
4517 : }
4518 :
4519 : /* Look at edges within the current SCC and propagate used-ness across
4520 : them, pushing onto the stack all notes which might need to be
4521 : revisited. */
4522 4014783 : for (cgraph_node *v : cycle_nodes)
4523 1341803 : v->call_for_symbol_thunks_and_aliases (propagate_used_to_scc_callers,
4524 : &stack, true);
4525 :
4526 : /* Keep revisiting and pushing until nothing changes. */
4527 1337248 : while (!stack.is_empty ())
4528 : {
4529 758 : cgraph_node *v = stack.pop ();
4530 758 : isra_func_summary *ifs = func_sums->get (v);
4531 758 : gcc_checking_assert (ifs && ifs->m_queued);
4532 758 : ifs->m_queued = false;
4533 :
4534 758 : v->call_for_symbol_thunks_and_aliases (propagate_used_to_scc_callers,
4535 : &stack, true);
4536 : }
4537 :
4538 : /* Parameter splitting. */
4539 1381941 : bool repeat_scc_access_propagation;
4540 1381941 : do
4541 : {
4542 1381941 : repeat_scc_access_propagation = false;
4543 4153831 : for (cgraph_node *v : cycle_nodes)
4544 : {
4545 1389949 : isra_func_summary *ifs = func_sums->get (v);
4546 2417319 : if (!ifs
4547 1076347 : || !ifs->m_candidate
4548 1805736 : || vec_safe_is_empty (ifs->m_parameters))
4549 1027370 : continue;
4550 1876596 : for (cgraph_edge *cs = v->callees; cs; cs = cs->next_callee)
4551 1514017 : if (param_splitting_across_edge (cs))
4552 48596 : repeat_scc_access_propagation = true;
4553 : }
4554 : }
4555 : while (repeat_scc_access_propagation);
4556 :
4557 1336490 : if (flag_checking)
4558 4014732 : for (cgraph_node *v : cycle_nodes)
4559 1341786 : verify_splitting_accesses (v, true);
4560 :
4561 1336490 : cycle_nodes.release ();
4562 : }
4563 :
4564 125936 : ipa_free_postorder_info ();
4565 125936 : free (order);
4566 :
4567 125936 : if (dump_file)
4568 : {
4569 54 : if (dump_flags & TDF_DETAILS)
4570 : {
4571 9 : fprintf (dump_file, "\n========== IPA-SRA propagation final state "
4572 : " ==========\n");
4573 9 : ipa_sra_dump_all_summaries (dump_file, true);
4574 : }
4575 54 : fprintf (dump_file, "\n========== IPA-SRA decisions ==========\n");
4576 : }
4577 :
4578 125936 : hash_map<const char *, unsigned> *clone_num_suffixes
4579 125936 : = new hash_map<const char *, unsigned>;
4580 :
4581 125936 : cgraph_node *node;
4582 1393119 : FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4583 1267183 : process_isra_node_results (node, clone_num_suffixes);
4584 :
4585 125936 : delete clone_num_suffixes;
4586 125936 : ggc_delete (func_sums);
4587 125936 : func_sums = NULL;
4588 125936 : delete call_sums;
4589 125936 : call_sums = NULL;
4590 :
4591 125936 : if (dump_file)
4592 54 : fprintf (dump_file, "\n========== IPA SRA IPA analysis done "
4593 : "==========\n\n");
4594 125936 : return 0;
4595 125936 : }
4596 :
4597 :
4598 : const pass_data pass_data_ipa_sra =
4599 : {
4600 : IPA_PASS, /* type */
4601 : "sra", /* name */
4602 : OPTGROUP_NONE, /* optinfo_flags */
4603 : TV_IPA_SRA, /* tv_id */
4604 : 0, /* properties_required */
4605 : 0, /* properties_provided */
4606 : 0, /* properties_destroyed */
4607 : 0, /* todo_flags_start */
4608 : ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
4609 : };
4610 :
4611 : class pass_ipa_sra : public ipa_opt_pass_d
4612 : {
4613 : public:
4614 285722 : pass_ipa_sra (gcc::context *ctxt)
4615 : : ipa_opt_pass_d (pass_data_ipa_sra, ctxt,
4616 : ipa_sra_generate_summary, /* generate_summary */
4617 : ipa_sra_write_summary, /* write_summary */
4618 : ipa_sra_read_summary, /* read_summary */
4619 : NULL , /* write_optimization_summary */
4620 : NULL, /* read_optimization_summary */
4621 : NULL, /* stmt_fixup */
4622 : 0, /* function_transform_todo_flags_start */
4623 : NULL, /* function_transform */
4624 285722 : NULL) /* variable_transform */
4625 285722 : {}
4626 :
4627 : /* opt_pass methods: */
4628 586755 : bool gate (function *) final override
4629 : {
4630 : /* TODO: We should remove the optimize check after we ensure we never run
4631 : IPA passes when not optimizing. */
4632 586755 : return (flag_ipa_sra && optimize);
4633 : }
4634 :
4635 125936 : unsigned int execute (function *) final override
4636 : {
4637 125936 : return ipa_sra_analysis ();
4638 : }
4639 :
4640 : }; // class pass_ipa_sra
4641 :
4642 : } // anon namespace
4643 :
4644 : /* Intraprocedural part of IPA-SRA analysis. Scan function body of NODE and
4645 : create a summary structure describing IPA-SRA opportunities and constraints
4646 : in it. */
4647 :
4648 : static void
4649 1264063 : ipa_sra_summarize_function (cgraph_node *node)
4650 : {
4651 1264063 : if (dump_file)
4652 187 : fprintf (dump_file, "Creating summary for %s/%i:\n", node->name (),
4653 : node->get_uid ());
4654 1264063 : gcc_obstack_init (&gensum_obstack);
4655 1264063 : loaded_decls = new hash_set<tree>;
4656 :
4657 1264063 : isra_func_summary *ifs = NULL;
4658 1264063 : unsigned count = 0;
4659 1264063 : if (ipa_sra_preliminary_function_checks (node))
4660 : {
4661 1029027 : ifs = func_sums->get_create (node);
4662 1029027 : ifs->m_candidate = true;
4663 1029027 : tree ret = TREE_TYPE (TREE_TYPE (node->decl));
4664 1029027 : ifs->m_returns_value = (TREE_CODE (ret) != VOID_TYPE);
4665 1029027 : for (tree parm = DECL_ARGUMENTS (node->decl);
4666 3414672 : parm;
4667 2385645 : parm = DECL_CHAIN (parm))
4668 2385645 : count++;
4669 : }
4670 1264063 : auto_vec<gensum_param_desc, 16> param_descriptions (count);
4671 :
4672 1264063 : struct function *fun = DECL_STRUCT_FUNCTION (node->decl);
4673 1264063 : bool cfun_pushed = false;
4674 1264063 : if (count > 0)
4675 : {
4676 835709 : decl2desc = new hash_map<tree, gensum_param_desc *>;
4677 835709 : param_descriptions.reserve_exact (count);
4678 835709 : param_descriptions.quick_grow_cleared (count);
4679 :
4680 835709 : if (create_parameter_descriptors (node, ¶m_descriptions))
4681 : {
4682 412478 : push_cfun (fun);
4683 412478 : cfun_pushed = true;
4684 412478 : final_bbs = BITMAP_ALLOC (NULL);
4685 412478 : bb_dereferences = XCNEWVEC (HOST_WIDE_INT,
4686 : unsafe_by_ref_count
4687 : * last_basic_block_for_fn (fun));
4688 412478 : aa_walking_limit = opt_for_fn (node->decl, param_ipa_max_aa_steps);
4689 : }
4690 : }
4691 : /* Scan function is run even when there are no removal or splitting
4692 : candidates so that we can calculate hints on call edges which can be
4693 : useful in callees. */
4694 1264063 : scan_function (node, fun);
4695 :
4696 1264063 : if (count > 0)
4697 : {
4698 835709 : if (dump_file)
4699 : {
4700 135 : dump_gensum_param_descriptors (dump_file, node->decl,
4701 : ¶m_descriptions);
4702 135 : fprintf (dump_file, "----------------------------------------\n");
4703 : }
4704 :
4705 835709 : process_scan_results (node, fun, ifs, ¶m_descriptions);
4706 :
4707 835709 : if (cfun_pushed)
4708 412478 : pop_cfun ();
4709 835709 : if (bb_dereferences)
4710 : {
4711 412478 : free (bb_dereferences);
4712 412478 : bb_dereferences = NULL;
4713 412478 : BITMAP_FREE (final_bbs);
4714 412478 : final_bbs = NULL;
4715 : }
4716 : }
4717 1264063 : isra_analyze_all_outgoing_calls (node);
4718 :
4719 2528126 : delete loaded_decls;
4720 1264063 : loaded_decls = NULL;
4721 1264063 : if (decl2desc)
4722 : {
4723 835709 : delete decl2desc;
4724 835709 : decl2desc = NULL;
4725 : }
4726 1264063 : obstack_free (&gensum_obstack, NULL);
4727 1264063 : if (dump_file)
4728 187 : fprintf (dump_file, "\n\n");
4729 1264063 : if (flag_checking)
4730 1264045 : verify_splitting_accesses (node, false);
4731 1264063 : return;
4732 1264063 : }
4733 :
4734 : ipa_opt_pass_d *
4735 285722 : make_pass_ipa_sra (gcc::context *ctxt)
4736 : {
4737 285722 : return new pass_ipa_sra (ctxt);
4738 : }
4739 :
4740 : /* Reset all state within ipa-sra.cc so that we can rerun the compiler
4741 : within the same process. For use by toplev::finalize. */
4742 :
4743 : void
4744 256621 : ipa_sra_cc_finalize (void)
4745 : {
4746 256621 : if (func_sums)
4747 9013 : ggc_delete (func_sums);
4748 256621 : func_sums = NULL;
4749 256621 : delete call_sums;
4750 256621 : call_sums = NULL;
4751 256621 : }
4752 :
4753 : #include "gt-ipa-sra.h"
|