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 2766375 : free_param_decl_accesses (isra_param_desc *desc)
268 : {
269 2766375 : unsigned len = vec_safe_length (desc->accesses);
270 3353528 : for (unsigned i = 0; i < len; ++i)
271 587153 : ggc_free ((*desc->accesses)[i]);
272 2766375 : vec_free (desc->accesses);
273 2766375 : }
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 1189068 : isra_func_summary ()
284 1189068 : : m_parameters (NULL), m_candidate (false), m_returns_value (false),
285 1189068 : 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 1189067 : isra_func_summary::~isra_func_summary ()
324 : {
325 1189067 : unsigned len = vec_safe_length (m_parameters);
326 2446986 : for (unsigned i = 0; i < len; ++i)
327 1257919 : free_param_decl_accesses (&(*m_parameters)[i]);
328 1189067 : vec_free (m_parameters);
329 1189067 : }
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 655510 : isra_func_summary::zap ()
336 : {
337 655510 : bool ret = m_candidate;
338 655510 : m_candidate = false;
339 :
340 : /* TODO: see the destructor above. */
341 655510 : unsigned len = vec_safe_length (m_parameters);
342 2163966 : for (unsigned i = 0; i < len; ++i)
343 1508456 : free_param_decl_accesses (&(*m_parameters)[i]);
344 655510 : vec_free (m_parameters);
345 :
346 655510 : 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 6041847 : class isra_call_summary
390 : {
391 : public:
392 6041847 : 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 134742 : ipa_sra_function_summaries (symbol_table *table, bool ggc):
426 269484 : 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 127742 : 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 127742 : new_sum->m_candidate = old_sum->m_candidate;
444 127742 : new_sum->m_returns_value = old_sum->m_returns_value;
445 127742 : new_sum->m_return_ignored = old_sum->m_return_ignored;
446 127742 : gcc_assert (!old_sum->m_queued);
447 127742 : new_sum->m_queued = false;
448 :
449 127742 : unsigned param_count = vec_safe_length (old_sum->m_parameters);
450 126877 : if (!param_count)
451 : return;
452 126877 : vec_safe_reserve_exact (new_sum->m_parameters, param_count);
453 126877 : new_sum->m_parameters->quick_grow_cleared (param_count);
454 490755 : for (unsigned i = 0; i < param_count; i++)
455 : {
456 363878 : isra_param_desc *s = &(*old_sum->m_parameters)[i];
457 363878 : isra_param_desc *d = &(*new_sum->m_parameters)[i];
458 :
459 363878 : d->param_size_limit = s->param_size_limit;
460 363878 : d->size_reached = s->size_reached;
461 363878 : d->safe_size = s->safe_size;
462 363878 : d->locally_unused = s->locally_unused;
463 363878 : d->split_candidate = s->split_candidate;
464 363878 : d->by_ref = s->by_ref;
465 363878 : d->remove_only_when_retval_removed = s->remove_only_when_retval_removed;
466 363878 : d->split_only_when_retval_removed = s->split_only_when_retval_removed;
467 363878 : d->not_specially_constructed = s->not_specially_constructed;
468 363878 : d->conditionally_dereferenceable = s->conditionally_dereferenceable;
469 363878 : d->safe_size_set = s->safe_size_set;
470 :
471 363878 : unsigned acc_count = vec_safe_length (s->accesses);
472 363878 : vec_safe_reserve_exact (d->accesses, acc_count);
473 513048 : for (unsigned j = 0; j < acc_count; j++)
474 : {
475 149170 : param_access *from = (*s->accesses)[j];
476 149170 : param_access *to = ggc_cleared_alloc<param_access> ();
477 149170 : to->type = from->type;
478 149170 : to->alias_ptr_type = from->alias_ptr_type;
479 149170 : to->unit_offset = from->unit_offset;
480 149170 : to->unit_size = from->unit_size;
481 149170 : to->certain = from->certain;
482 149170 : to->reverse = from->reverse;
483 149170 : 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 18049 : ipa_sra_function_summaries::insert (cgraph_node *node, isra_func_summary *)
496 : {
497 18049 : if (opt_for_fn (node->decl, flag_ipa_sra))
498 : {
499 18049 : push_cfun (DECL_STRUCT_FUNCTION (node->decl));
500 18049 : ipa_sra_summarize_function (node);
501 18049 : pop_cfun ();
502 : }
503 : else
504 0 : func_sums->remove (node);
505 18049 : }
506 :
507 : /* Class to manage call summaries. */
508 :
509 : class ipa_sra_call_summaries: public call_summary <isra_call_summary *>
510 : {
511 : public:
512 134742 : ipa_sra_call_summaries (symbol_table *table):
513 269484 : 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 6954232 : isra_call_summary::init_inputs (unsigned arg_count)
529 : {
530 6954232 : if (arg_count == 0)
531 : {
532 350344 : gcc_checking_assert (m_arg_flow.length () == 0);
533 : return;
534 : }
535 6603888 : if (m_arg_flow.length () == 0)
536 : {
537 3263132 : m_arg_flow.reserve_exact (arg_count);
538 3263132 : m_arg_flow.quick_grow_cleared (arg_count);
539 : }
540 : else
541 3340756 : 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 646785 : ipa_sra_call_summaries::duplicate (cgraph_edge *, cgraph_edge *,
593 : isra_call_summary *old_sum,
594 : isra_call_summary *new_sum)
595 : {
596 646785 : unsigned arg_count = old_sum->m_arg_flow.length ();
597 646785 : new_sum->init_inputs (arg_count);
598 1879559 : for (unsigned i = 0; i < arg_count; i++)
599 1232774 : new_sum->m_arg_flow[i] = old_sum->m_arg_flow[i];
600 :
601 646785 : new_sum->m_return_ignored = old_sum->m_return_ignored;
602 646785 : new_sum->m_return_returned = old_sum->m_return_returned;
603 646785 : new_sum->m_bit_aligned_arg = old_sum->m_bit_aligned_arg;
604 646785 : new_sum->m_before_any_store = old_sum->m_before_any_store;
605 646785 : }
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 1258180 : ipa_sra_preliminary_function_checks (cgraph_node *node)
645 : {
646 1258180 : if (!node->can_change_signature)
647 : {
648 35594 : if (dump_file)
649 0 : fprintf (dump_file, "Function cannot change signature.\n");
650 35594 : return false;
651 : }
652 :
653 1222586 : if (!tree_versionable_function_p (node->decl))
654 : {
655 118438 : if (dump_file)
656 7 : fprintf (dump_file, "Function is not versionable.\n");
657 118438 : return false;
658 : }
659 :
660 1104148 : if (!opt_for_fn (node->decl, optimize)
661 1104148 : || !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 1103956 : if (DECL_VIRTUAL_P (node->decl))
670 : {
671 30859 : if (dump_file)
672 0 : fprintf (dump_file, "Function is a virtual method.\n");
673 30859 : return false;
674 : }
675 :
676 1073097 : struct function *fun = DECL_STRUCT_FUNCTION (node->decl);
677 1073097 : 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 1072973 : if (DECL_DISREGARD_INLINE_LIMITS (node->decl))
685 : {
686 49328 : if (dump_file)
687 0 : fprintf (dump_file, "Always inline function will be inlined "
688 : "anyway. \n");
689 49328 : 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 1317004 : add_src_to_param_flow (isra_param_flow *param_flow, int src)
870 : {
871 1317004 : gcc_checking_assert (src >= 0 && src <= UCHAR_MAX);
872 1317004 : if (param_flow->length == IPA_SRA_MAX_PARAM_FLOW_LEN)
873 : return false;
874 :
875 1317001 : param_flow->inputs[(int) param_flow->length] = src;
876 1317001 : param_flow->length++;
877 1317001 : 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 784732 : set_single_param_flow_source (isra_param_flow *param_flow, int src)
886 : {
887 784732 : gcc_checking_assert (src >= 0 && src <= UCHAR_MAX);
888 784732 : if (param_flow->length == 0)
889 : {
890 120926 : param_flow->inputs[0] = src;
891 120926 : param_flow->length = 1;
892 : }
893 663806 : else if (param_flow->length == 1)
894 663806 : gcc_assert (param_flow->inputs[0] == src);
895 : else
896 0 : gcc_unreachable ();
897 784732 : }
898 :
899 : /* Assert that there is only a single value in PARAM_FLOW's inputs and return
900 : it. */
901 :
902 : static unsigned
903 1284939 : get_single_param_flow_source (const isra_param_flow *param_flow)
904 : {
905 1284939 : gcc_assert (param_flow->length == 1);
906 1284939 : 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 3373127 : 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 3373127 : int res = 0;
925 3373127 : imm_use_iterator imm_iter;
926 3373127 : gimple *stmt;
927 :
928 10310215 : FOR_EACH_IMM_USE_STMT (stmt, imm_iter, name)
929 : {
930 5186630 : if (is_gimple_debug (stmt)
931 5186630 : || gimple_clobber_p (stmt))
932 861661 : continue;
933 :
934 : /* TODO: We could handle at least const builtin functions like arithmetic
935 : operations below. */
936 4324969 : if (is_gimple_call (stmt))
937 : {
938 1329866 : int all_uses = 0;
939 1329866 : use_operand_p use_p;
940 2673096 : FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
941 1343230 : all_uses++;
942 :
943 1329866 : gcall *call = as_a <gcall *> (stmt);
944 1329866 : unsigned arg_count;
945 1329866 : if (gimple_call_internal_p (call)
946 1329866 : || (arg_count = gimple_call_num_args (call)) == 0)
947 : {
948 : res = -1;
949 : break;
950 : }
951 :
952 1325120 : cgraph_edge *cs = node->get_edge (stmt);
953 1325120 : gcc_checking_assert (cs);
954 1325120 : isra_call_summary *csum = call_sums->get_create (cs);
955 1325120 : csum->init_inputs (arg_count);
956 :
957 1325120 : int simple_uses = 0;
958 6043288 : for (unsigned i = 0; i < arg_count; i++)
959 4718171 : if (gimple_call_arg (call, i) == name)
960 : {
961 1317004 : if (!add_src_to_param_flow (&csum->m_arg_flow[i], parm_num))
962 : {
963 : simple_uses = -1;
964 : break;
965 : }
966 1317001 : simple_uses++;
967 : }
968 :
969 1325120 : if (simple_uses < 0
970 1325120 : || all_uses != simple_uses)
971 : {
972 : res = -1;
973 : break;
974 : }
975 1303884 : res += all_uses;
976 : }
977 2995103 : else if (!stmt_unremovable_because_of_non_call_eh_p (fun, stmt)
978 2995103 : && ((is_gimple_assign (stmt) && !gimple_has_volatile_ops (stmt))
979 670117 : || gimple_code (stmt) == GIMPLE_PHI))
980 : {
981 2393133 : tree lhs;
982 2393133 : if (gimple_code (stmt) == GIMPLE_PHI)
983 175434 : lhs = gimple_phi_result (stmt);
984 : else
985 2217699 : lhs = gimple_assign_lhs (stmt);
986 :
987 2393133 : if (TREE_CODE (lhs) != SSA_NAME)
988 : {
989 : res = -1;
990 : break;
991 : }
992 1997359 : gcc_assert (!gimple_vdef (stmt));
993 1997359 : if (bitmap_set_bit (analyzed, SSA_NAME_VERSION (lhs)))
994 : {
995 1903939 : int tmp = isra_track_scalar_value_uses (fun, node, lhs, parm_num,
996 : analyzed, desc);
997 1903939 : if (tmp < 0)
998 : {
999 : res = tmp;
1000 : break;
1001 : }
1002 1138296 : res += tmp;
1003 : }
1004 : }
1005 601970 : else if (greturn *gr = dyn_cast<greturn *>(stmt))
1006 : {
1007 166700 : tree rv = gimple_return_retval (gr);
1008 166700 : if (rv != name)
1009 : {
1010 : res = -1;
1011 : break;
1012 : }
1013 166700 : desc->remove_only_when_retval_removed = true;
1014 : }
1015 : else
1016 : {
1017 : res = -1;
1018 : break;
1019 : }
1020 3373127 : }
1021 3373127 : 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 2162800 : isra_track_scalar_param_local_uses (function *fun, cgraph_node *node, tree parm,
1040 : int parm_num, gensum_param_desc *desc)
1041 : {
1042 2162800 : gcc_checking_assert (is_gimple_reg (parm));
1043 :
1044 2162800 : tree name = ssa_default_def (fun, parm);
1045 2162800 : if (!name || has_zero_uses (name))
1046 : {
1047 693612 : desc->call_uses = 0;
1048 693612 : return false;
1049 : }
1050 :
1051 : /* Edge summaries can only handle callers with fewer than 256 parameters. */
1052 1469188 : if (parm_num > UCHAR_MAX)
1053 : return true;
1054 :
1055 1469188 : bitmap analyzed = BITMAP_ALLOC (NULL);
1056 1469188 : int call_uses = isra_track_scalar_value_uses (fun, node, name, parm_num,
1057 : analyzed, desc);
1058 1469188 : BITMAP_FREE (analyzed);
1059 1469188 : if (call_uses < 0)
1060 : return true;
1061 612162 : desc->call_uses = call_uses;
1062 612162 : 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 1137055 : ptr_parm_has_nonarg_uses (cgraph_node *node, function *fun, tree parm,
1082 : int parm_num, gensum_param_desc *desc)
1083 : {
1084 1137055 : imm_use_iterator ui;
1085 1137055 : gimple *stmt;
1086 1137055 : tree name = ssa_default_def (fun, parm);
1087 1137055 : bool ret = false;
1088 1137055 : unsigned pt_count = 0;
1089 :
1090 1137055 : if (!name || has_zero_uses (name))
1091 : return false;
1092 :
1093 : /* Edge summaries can only handle callers with fewer than 256 parameters. */
1094 1026639 : if (parm_num > UCHAR_MAX)
1095 : return true;
1096 :
1097 3848295 : FOR_EACH_IMM_USE_STMT (stmt, ui, name)
1098 : {
1099 2323989 : unsigned uses_ok = 0;
1100 2323989 : use_operand_p use_p;
1101 :
1102 2323989 : if (is_gimple_debug (stmt)
1103 2323989 : || gimple_clobber_p (stmt))
1104 581321 : continue;
1105 :
1106 1742668 : if (gimple_assign_single_p (stmt))
1107 : {
1108 884596 : tree rhs = gimple_assign_rhs1 (stmt);
1109 884596 : if (!TREE_THIS_VOLATILE (rhs))
1110 : {
1111 1672412 : while (handled_component_p (rhs))
1112 787892 : rhs = TREE_OPERAND (rhs, 0);
1113 884520 : if (TREE_CODE (rhs) == MEM_REF
1114 610650 : && TREE_OPERAND (rhs, 0) == name
1115 606847 : && integer_zerop (TREE_OPERAND (rhs, 1))
1116 1447902 : && types_compatible_p (TREE_TYPE (rhs),
1117 563382 : TREE_TYPE (TREE_TYPE (name))))
1118 : uses_ok++;
1119 : }
1120 : }
1121 858072 : else if (is_gimple_call (stmt))
1122 : {
1123 713472 : gcall *call = as_a <gcall *> (stmt);
1124 713472 : unsigned arg_count;
1125 713472 : if (gimple_call_internal_p (call)
1126 713472 : || (arg_count = gimple_call_num_args (call)) == 0)
1127 : {
1128 : ret = true;
1129 : break;
1130 : }
1131 :
1132 712699 : cgraph_edge *cs = node->get_edge (stmt);
1133 712699 : gcc_checking_assert (cs);
1134 712699 : isra_call_summary *csum = call_sums->get_create (cs);
1135 712699 : csum->init_inputs (arg_count);
1136 :
1137 2736784 : for (unsigned i = 0; i < arg_count; ++i)
1138 : {
1139 2024085 : tree arg = gimple_call_arg (stmt, i);
1140 :
1141 2024085 : 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 701039 : csum->m_arg_flow[i].pointer_pass_through = true;
1147 701039 : set_single_param_flow_source (&csum->m_arg_flow[i], parm_num);
1148 701039 : pt_count++;
1149 701039 : uses_ok++;
1150 701039 : continue;
1151 : }
1152 :
1153 1323046 : if (!TREE_THIS_VOLATILE (arg))
1154 : {
1155 1350379 : while (handled_component_p (arg))
1156 27333 : arg = TREE_OPERAND (arg, 0);
1157 1323046 : if (TREE_CODE (arg) == MEM_REF
1158 20874 : && TREE_OPERAND (arg, 0) == name
1159 11514 : && integer_zerop (TREE_OPERAND (arg, 1))
1160 1334558 : && types_compatible_p (TREE_TYPE (arg),
1161 11512 : TREE_TYPE (TREE_TYPE (name))))
1162 8681 : uses_ok++;
1163 : }
1164 : }
1165 : }
1166 144600 : else if (greturn *gr = dyn_cast<greturn *>(stmt))
1167 : {
1168 9173 : tree rv = gimple_return_retval (gr);
1169 9173 : if (rv == name)
1170 : {
1171 9173 : 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 9173 : gcc_assert (!desc->locally_unused
1175 : || desc->remove_only_when_retval_removed);
1176 9173 : 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 1741895 : unsigned all_uses = 0;
1183 3491048 : FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
1184 1749153 : all_uses++;
1185 :
1186 1741895 : gcc_checking_assert (uses_ok <= all_uses);
1187 1741895 : if (uses_ok != all_uses)
1188 : {
1189 : ret = true;
1190 : break;
1191 : }
1192 1026639 : }
1193 :
1194 1026639 : desc->ptr_pt_count = pt_count;
1195 1026639 : 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 830098 : create_parameter_descriptors (cgraph_node *node,
1205 : vec<gensum_param_desc> *param_descriptions)
1206 : {
1207 830098 : function *fun = DECL_STRUCT_FUNCTION (node->decl);
1208 830098 : bool ret = false;
1209 :
1210 830098 : int num = 0;
1211 830098 : for (tree parm = DECL_ARGUMENTS (node->decl);
1212 3204727 : parm;
1213 2374629 : parm = DECL_CHAIN (parm), num++)
1214 : {
1215 2374629 : const char *msg;
1216 2374629 : gensum_param_desc *desc = &(*param_descriptions)[num];
1217 : /* param_descriptions vector is grown cleared in the caller. */
1218 2374629 : desc->param_number = num;
1219 2374629 : decl2desc->put (parm, desc);
1220 :
1221 2374629 : if (dump_file && (dump_flags & TDF_DETAILS))
1222 39 : print_generic_expr (dump_file, parm, TDF_UID);
1223 :
1224 2374629 : tree type = TREE_TYPE (parm);
1225 2374629 : 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 1775645 : continue;
1230 : }
1231 2374578 : 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 2374578 : if (TREE_ADDRESSABLE (parm))
1238 : {
1239 36787 : if (dump_file && (dump_flags & TDF_DETAILS))
1240 0 : fprintf (dump_file, " not a candidate, is addressable\n");
1241 36787 : continue;
1242 : }
1243 2337791 : 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 2337791 : if (is_gimple_reg (parm)
1251 2337791 : && !isra_track_scalar_param_local_uses (fun, node, parm, num, desc))
1252 : {
1253 1305774 : desc->locally_unused = true;
1254 :
1255 1305774 : 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 2337791 : if (POINTER_TYPE_P (type))
1263 : {
1264 1143596 : desc->by_ref = true;
1265 1143596 : if (TREE_CODE (type) == REFERENCE_TYPE
1266 1143596 : || (num == 0
1267 553805 : && TREE_CODE (TREE_TYPE (node->decl)) == METHOD_TYPE))
1268 484889 : desc->safe_ref = true;
1269 : else
1270 658707 : desc->safe_ref = false;
1271 1143596 : type = TREE_TYPE (type);
1272 :
1273 1148618 : if (TREE_CODE (type) == FUNCTION_TYPE
1274 1143596 : || TREE_CODE (type) == METHOD_TYPE)
1275 : {
1276 5022 : if (dump_file && (dump_flags & TDF_DETAILS))
1277 0 : fprintf (dump_file, " not a candidate, reference to "
1278 : "a function\n");
1279 5022 : continue;
1280 : }
1281 1138574 : 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 1137446 : if (TREE_CODE (type) == ARRAY_TYPE
1289 1137446 : && 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 1137446 : 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 1137440 : 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 1137055 : if (ptr_parm_has_nonarg_uses (node, fun, parm, num, desc))
1311 : {
1312 528972 : if (dump_file && (dump_flags & TDF_DETAILS))
1313 7 : fprintf (dump_file, " not a candidate, reference has "
1314 : "nonarg uses\n");
1315 528972 : continue;
1316 : }
1317 : }
1318 1194195 : 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 1019405 : if (dump_file && (dump_flags & TDF_DETAILS))
1323 17 : fprintf (dump_file, " not a candidate, not an aggregate\n");
1324 1019405 : continue;
1325 : }
1326 :
1327 782873 : if (!COMPLETE_TYPE_P (type))
1328 : {
1329 170548 : if (dump_file && (dump_flags & TDF_DETAILS))
1330 0 : fprintf (dump_file, " not a candidate, not a complete type\n");
1331 170548 : continue;
1332 : }
1333 612325 : 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 612323 : unsigned HOST_WIDE_INT type_size
1340 612323 : = tree_to_uhwi (TYPE_SIZE (type)) / BITS_PER_UNIT;
1341 616570 : if (type_size == 0
1342 612323 : || type_size >= ISRA_ARG_SIZE_LIMIT)
1343 : {
1344 4247 : if (dump_file && (dump_flags & TDF_DETAILS))
1345 0 : fprintf (dump_file, " not a candidate, has zero or huge size\n");
1346 4247 : continue;
1347 : }
1348 608076 : 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 598984 : if (dump_file && (dump_flags & TDF_DETAILS))
1356 15 : fprintf (dump_file, " is a candidate\n");
1357 :
1358 598984 : ret = true;
1359 598984 : desc->split_candidate = true;
1360 598984 : if (desc->by_ref && !desc->safe_ref)
1361 193446 : desc->deref_index = unsafe_by_ref_count++;
1362 : }
1363 830098 : 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 2444126 : get_gensum_param_desc (tree decl)
1371 : {
1372 2444126 : if (!decl2desc)
1373 : return NULL;
1374 2272453 : gcc_checking_assert (TREE_CODE (decl) == PARM_DECL);
1375 2272453 : gensum_param_desc **slot = decl2desc->get (decl);
1376 2272453 : if (!slot)
1377 : /* This can happen for static chains which we cannot handle so far. */
1378 : return NULL;
1379 2247052 : 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 164272 : disqualify_split_candidate (gensum_param_desc *desc, const char *reason)
1389 : {
1390 164272 : if (!desc->split_candidate)
1391 : return;
1392 :
1393 164243 : 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 164243 : 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 431844 : allocate_access (gensum_param_desc *desc,
1417 : HOST_WIDE_INT offset, HOST_WIDE_INT size)
1418 : {
1419 431844 : if (desc->access_count
1420 431844 : == (unsigned) param_ipa_sra_max_replacements)
1421 : {
1422 0 : disqualify_split_candidate (desc, "Too many replacement candidates");
1423 0 : return NULL;
1424 : }
1425 :
1426 431844 : gensum_param_access *access
1427 431844 : = (gensum_param_access *) obstack_alloc (&gensum_obstack,
1428 : sizeof (gensum_param_access));
1429 431844 : memset (access, 0, sizeof (*access));
1430 431844 : access->offset = offset;
1431 431844 : access->size = size;
1432 431844 : access->load_count = profile_count::zero ();
1433 431844 : 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 508463 : 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 518598 : gensum_param_access *access = *first, **ptr = first;
1456 :
1457 518598 : if (!access)
1458 : {
1459 : /* No pre-existing access at this level, just create it. */
1460 280110 : gensum_param_access *a = allocate_access (desc, offset, size);
1461 280110 : if (!a)
1462 : return NULL;
1463 280110 : *first = a;
1464 280110 : return *first;
1465 : }
1466 :
1467 238488 : if (access->offset >= offset + size)
1468 : {
1469 : /* We want to squeeze it in front of the very first access, just do
1470 : it. */
1471 44222 : gensum_param_access *r = allocate_access (desc, offset, size);
1472 44222 : if (!r)
1473 : return NULL;
1474 44222 : r->next_sibling = access;
1475 44222 : *first = r;
1476 44222 : return r;
1477 : }
1478 :
1479 : /* Skip all accesses that have to come before us until the next sibling is
1480 : already too far. */
1481 283687 : while (offset >= access->offset + access->size
1482 185401 : && access->next_sibling
1483 383870 : && access->next_sibling->offset < offset + size)
1484 : {
1485 89421 : ptr = &access->next_sibling;
1486 89421 : access = access->next_sibling;
1487 : }
1488 :
1489 : /* At this point we know we do not belong before access. */
1490 194266 : gcc_assert (access->offset < offset + size);
1491 :
1492 194266 : if (access->offset == offset && access->size == size)
1493 : /* We found what we were looking for. */
1494 : return access;
1495 :
1496 122556 : if (access->offset <= offset
1497 119425 : && 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 11754 : if (access->nonarg)
1503 : return NULL;
1504 :
1505 10135 : return get_access_1 (desc, &access->first_child, offset, size, ctx);
1506 : }
1507 :
1508 110802 : if (offset <= access->offset
1509 14822 : && 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 14822 : if (ctx != ISRA_CTX_ARG)
1516 : return NULL;
1517 :
1518 11532 : gensum_param_access *r = allocate_access (desc, offset, size);
1519 11532 : if (!r)
1520 : return NULL;
1521 11532 : r->first_child = access;
1522 :
1523 11532 : while (access->next_sibling
1524 20170 : && access->next_sibling->offset < offset + size)
1525 : access = access->next_sibling;
1526 11532 : 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 11532 : r->next_sibling = access->next_sibling;
1535 11532 : access->next_sibling = NULL;
1536 11532 : *ptr = r;
1537 11532 : return r;
1538 : }
1539 :
1540 95980 : if (offset >= access->offset + access->size)
1541 : {
1542 : /* We belong after access. */
1543 95980 : gensum_param_access *r = allocate_access (desc, offset, size);
1544 95980 : if (!r)
1545 : return NULL;
1546 95980 : r->next_sibling = access->next_sibling;
1547 95980 : access->next_sibling = r;
1548 95980 : 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 508463 : get_access (gensum_param_desc *desc, HOST_WIDE_INT offset, HOST_WIDE_INT size,
1577 : isra_scan_context ctx)
1578 : {
1579 508463 : gcc_checking_assert (desc->split_candidate);
1580 :
1581 508463 : gensum_param_access *access = get_access_1 (desc, &desc->accesses, offset,
1582 : size, ctx);
1583 508463 : if (!access)
1584 : {
1585 4909 : disqualify_split_candidate (desc,
1586 : "Bad access overlap or too many accesses");
1587 4909 : return NULL;
1588 : }
1589 :
1590 503554 : switch (ctx)
1591 : {
1592 13490 : case ISRA_CTX_STORE:
1593 13490 : gcc_assert (!desc->by_ref);
1594 : /* Fall-through */
1595 416940 : case ISRA_CTX_LOAD:
1596 416940 : access->nonarg = true;
1597 416940 : 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 897909 : verify_access_tree_1 (gensum_param_access *access, HOST_WIDE_INT parent_offset,
1611 : HOST_WIDE_INT parent_size)
1612 : {
1613 1280091 : while (access)
1614 : {
1615 382182 : gcc_assert (access->offset >= 0 && access->size >= 0);
1616 :
1617 382182 : if (parent_size != 0)
1618 : {
1619 22807 : if (access->offset < parent_offset)
1620 : {
1621 0 : error ("Access offset before parent offset");
1622 0 : return true;
1623 : }
1624 22807 : if (access->size >= parent_size)
1625 : {
1626 0 : error ("Access size greater or equal to its parent size");
1627 0 : return true;
1628 : }
1629 22807 : 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 382182 : if (verify_access_tree_1 (access->first_child, access->offset,
1637 : access->size))
1638 : return true;
1639 :
1640 382182 : if (access->next_sibling
1641 127984 : && (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 515727 : isra_verify_access_tree (gensum_param_access *access)
1657 : {
1658 515727 : 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 515727 : }
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 9133 : asm_visit_addr (gimple *, tree op, tree, void *)
1672 : {
1673 9133 : op = get_base_address (op);
1674 9133 : if (op
1675 9133 : && TREE_CODE (op) == PARM_DECL)
1676 177 : disqualify_split_candidate (op, "Non-scalarizable GIMPLE_ASM operand.");
1677 :
1678 9133 : 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 237867 : mark_param_dereference (gensum_param_desc *desc, HOST_WIDE_INT dist,
1687 : basic_block bb)
1688 : {
1689 237867 : gcc_assert (desc->by_ref);
1690 237867 : gcc_checking_assert (desc->split_candidate);
1691 :
1692 237867 : if (desc->safe_ref
1693 237867 : || bitmap_bit_p (final_bbs, bb->index))
1694 212319 : return;
1695 :
1696 25548 : int idx = bb->index * unsafe_by_ref_count + desc->deref_index;
1697 25548 : if (bb_dereferences[idx] < dist)
1698 24259 : 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 61704 : type_prevails_p (tree old_type, tree new_type)
1706 : {
1707 61704 : if (old_type == new_type)
1708 : return false;
1709 :
1710 : /* Non-aggregates are always better. */
1711 281 : if (!is_gimple_reg_type (old_type)
1712 281 : && is_gimple_reg_type (new_type))
1713 : return true;
1714 269 : if (is_gimple_reg_type (old_type)
1715 269 : && !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 83693 : record_nonregister_call_use (gensum_param_desc *desc,
1766 : scan_call_info *call_info,
1767 : unsigned unit_offset, unsigned unit_size)
1768 : {
1769 83693 : isra_call_summary *csum = call_sums->get_create (call_info->cs);
1770 83693 : csum->init_inputs (call_info->argument_count);
1771 :
1772 83693 : isra_param_flow *param_flow = &csum->m_arg_flow[call_info->arg_idx];
1773 83693 : param_flow->aggregate_pass_through = true;
1774 83693 : set_single_param_flow_source (param_flow, desc->param_number);
1775 83693 : param_flow->unit_offset = unit_offset;
1776 83693 : param_flow->unit_size = unit_size;
1777 83693 : desc->call_uses++;
1778 83693 : }
1779 :
1780 : /* Callback of walk_aliased_vdefs, just mark that there was a possible
1781 : modification. */
1782 :
1783 : static bool
1784 66954 : mark_maybe_modified (ao_ref *, tree, void *data)
1785 : {
1786 66954 : bool *maybe_modified = (bool *) data;
1787 66954 : *maybe_modified = true;
1788 66954 : 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 35815319 : scan_expr_access (tree expr, gimple *stmt, isra_scan_context ctx,
1799 : basic_block bb, scan_call_info *call_info = NULL)
1800 : {
1801 35815319 : poly_int64 poffset, psize, pmax_size;
1802 35815319 : HOST_WIDE_INT offset, size, max_size;
1803 35815319 : tree base;
1804 35815319 : bool deref = false;
1805 35815319 : bool reverse;
1806 :
1807 35815319 : if (TREE_CODE (expr) == ADDR_EXPR)
1808 : {
1809 4389384 : if (ctx == ISRA_CTX_ARG)
1810 : return;
1811 1212589 : tree t = get_base_address (TREE_OPERAND (expr, 0));
1812 1212589 : if (VAR_P (t) && !TREE_STATIC (t))
1813 239737 : loaded_decls->add (t);
1814 1212589 : return;
1815 : }
1816 31425935 : if (TREE_CODE (expr) == SSA_NAME
1817 17421696 : || CONSTANT_CLASS_P (expr))
1818 : return;
1819 :
1820 12497838 : if (TREE_CODE (expr) == BIT_FIELD_REF
1821 12497838 : || TREE_CODE (expr) == IMAGPART_EXPR
1822 12380569 : || TREE_CODE (expr) == REALPART_EXPR)
1823 169821 : expr = TREE_OPERAND (expr, 0);
1824 :
1825 12497838 : base = get_ref_base_and_extent (expr, &poffset, &psize, &pmax_size, &reverse);
1826 :
1827 12497838 : if (TREE_CODE (base) == MEM_REF)
1828 : {
1829 3951158 : tree op = TREE_OPERAND (base, 0);
1830 3951158 : if (TREE_CODE (op) != SSA_NAME
1831 3951158 : || !SSA_NAME_IS_DEFAULT_DEF (op))
1832 : return;
1833 2073644 : base = SSA_NAME_VAR (op);
1834 2073644 : if (!base)
1835 : return;
1836 : deref = true;
1837 : }
1838 8546680 : else if (VAR_P (base)
1839 7393987 : && !TREE_STATIC (base)
1840 6414808 : && (ctx == ISRA_CTX_ARG
1841 : || ctx == ISRA_CTX_LOAD))
1842 2400295 : loaded_decls->add (base);
1843 :
1844 10620324 : if (TREE_CODE (base) != PARM_DECL)
1845 : return;
1846 :
1847 2443949 : gensum_param_desc *desc = get_gensum_param_desc (base);
1848 2443949 : if (!desc || !desc->split_candidate)
1849 : return;
1850 :
1851 576799 : if (storage_order_barrier_p (expr))
1852 : {
1853 0 : disqualify_split_candidate (desc, "Encountered a storage order barrier.");
1854 0 : return;
1855 : }
1856 :
1857 576799 : if (!poffset.is_constant (&offset)
1858 576799 : || !psize.is_constant (&size)
1859 576799 : || !pmax_size.is_constant (&max_size))
1860 : {
1861 : disqualify_split_candidate (desc, "Encountered a polynomial-sized "
1862 : "access.");
1863 : return;
1864 : }
1865 576799 : if (size < 0 || size != max_size)
1866 : {
1867 6245 : disqualify_split_candidate (desc, "Encountered a variable sized access.");
1868 6245 : return;
1869 : }
1870 570554 : if (TREE_CODE (expr) == COMPONENT_REF
1871 570554 : && DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
1872 : {
1873 1482 : disqualify_split_candidate (desc, "Encountered a bit-field access.");
1874 1482 : return;
1875 : }
1876 569072 : if (offset < 0)
1877 : {
1878 4 : disqualify_split_candidate (desc, "Encountered an access at a "
1879 : "negative offset.");
1880 4 : return;
1881 : }
1882 569068 : gcc_assert ((offset % BITS_PER_UNIT) == 0);
1883 569068 : gcc_assert ((size % BITS_PER_UNIT) == 0);
1884 569068 : if ((offset / BITS_PER_UNIT) >= (UINT_MAX - ISRA_ARG_SIZE_LIMIT)
1885 569068 : || (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 569068 : tree type = TREE_TYPE (expr);
1893 569068 : unsigned int exp_align = get_object_alignment (expr);
1894 :
1895 569068 : if (exp_align < TYPE_ALIGN (type))
1896 : {
1897 1356 : disqualify_split_candidate (desc, "Underaligned access.");
1898 1356 : return;
1899 : }
1900 :
1901 567712 : if (deref)
1902 : {
1903 297116 : if (!desc->by_ref)
1904 : {
1905 0 : disqualify_split_candidate (desc, "Dereferencing a non-reference.");
1906 59249 : return;
1907 : }
1908 297116 : 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 297116 : if (!aa_walking_limit)
1916 : {
1917 0 : disqualify_split_candidate (desc, "Out of alias analysis step "
1918 : "limit.");
1919 0 : return;
1920 : }
1921 :
1922 594232 : gcc_checking_assert (gimple_vuse (stmt));
1923 297116 : bool maybe_modified = false;
1924 297116 : ao_ref ar;
1925 :
1926 297116 : ao_ref_init (&ar, expr);
1927 297116 : bitmap visited = BITMAP_ALLOC (NULL);
1928 594232 : int walked = walk_aliased_vdefs (&ar, gimple_vuse (stmt),
1929 : mark_maybe_modified, &maybe_modified,
1930 : &visited, NULL, aa_walking_limit);
1931 297116 : BITMAP_FREE (visited);
1932 297116 : if (walked > 0)
1933 : {
1934 101367 : gcc_assert (aa_walking_limit > walked);
1935 101367 : aa_walking_limit = aa_walking_limit - walked;
1936 : }
1937 297116 : if (walked < 0)
1938 0 : aa_walking_limit = 0;
1939 297116 : if (maybe_modified || walked < 0)
1940 : {
1941 59249 : disqualify_split_candidate (desc, "Data passed by reference possibly "
1942 : "modified through an alias.");
1943 59249 : return;
1944 : }
1945 : else
1946 237867 : 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 270596 : gcc_assert (!desc->by_ref);
1952 :
1953 508463 : gensum_param_access *access = get_access (desc, offset, size, ctx);
1954 508463 : if (!access)
1955 : return;
1956 :
1957 503554 : if (ctx == ISRA_CTX_ARG)
1958 : {
1959 86614 : gcc_checking_assert (call_info);
1960 :
1961 86614 : if (!deref)
1962 83693 : record_nonregister_call_use (desc, call_info, offset / BITS_PER_UNIT,
1963 83693 : 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 416940 : else if (ctx == ISRA_CTX_LOAD && bb->count.initialized_p ())
1970 403362 : access->load_count += bb->count;
1971 :
1972 503554 : if (!access->type)
1973 : {
1974 431844 : access->type = type;
1975 431844 : access->alias_ptr_type = reference_alias_ptr_type (expr);
1976 431844 : access->reverse = reverse;
1977 : }
1978 : else
1979 : {
1980 71710 : 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 71710 : if (access->alias_ptr_type != reference_alias_ptr_type (expr))
1987 : {
1988 4603 : disqualify_split_candidate (desc, "Multiple alias pointer types.");
1989 4603 : return;
1990 : }
1991 67107 : if (access->reverse != reverse)
1992 : {
1993 0 : disqualify_split_candidate (desc, "Both normal and reverse "
1994 : "scalar storage order.");
1995 0 : return;
1996 : }
1997 67107 : if (!deref
1998 52264 : && (AGGREGATE_TYPE_P (type) || AGGREGATE_TYPE_P (access->type))
1999 105501 : && (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 5403 : disqualify_split_candidate (desc, "We do not support aggregate "
2005 : "type punning.");
2006 5403 : return;
2007 : }
2008 :
2009 61704 : if (type_prevails_p (access->type, type))
2010 99 : 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 1258180 : scan_function (cgraph_node *node, struct function *fun)
2019 : {
2020 1258180 : basic_block bb;
2021 :
2022 10232919 : FOR_EACH_BB_FN (bb, fun)
2023 : {
2024 8974739 : gimple_stmt_iterator gsi;
2025 69927973 : for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
2026 : {
2027 51978495 : gimple *stmt = gsi_stmt (gsi);
2028 :
2029 51978495 : if (final_bbs && stmt_can_throw_external (fun, stmt))
2030 1350750 : bitmap_set_bit (final_bbs, bb->index);
2031 51978495 : switch (gimple_code (stmt))
2032 : {
2033 1226971 : case GIMPLE_RETURN:
2034 1226971 : {
2035 1226971 : tree t = gimple_return_retval (as_a <greturn *> (stmt));
2036 1226971 : if (t != NULL_TREE)
2037 675734 : scan_expr_access (t, stmt, ISRA_CTX_LOAD, bb);
2038 1226971 : if (final_bbs)
2039 405868 : bitmap_set_bit (final_bbs, bb->index);
2040 : }
2041 : break;
2042 :
2043 18146310 : case GIMPLE_ASSIGN:
2044 18146310 : if (gimple_assign_single_p (stmt)
2045 18146310 : && !gimple_clobber_p (stmt))
2046 : {
2047 11071922 : tree rhs = gimple_assign_rhs1 (stmt);
2048 11071922 : scan_expr_access (rhs, stmt, ISRA_CTX_LOAD, bb);
2049 11071922 : tree lhs = gimple_assign_lhs (stmt);
2050 11071922 : scan_expr_access (lhs, stmt, ISRA_CTX_STORE, bb);
2051 : }
2052 : break;
2053 :
2054 5308180 : case GIMPLE_CALL:
2055 5308180 : {
2056 5308180 : unsigned argument_count = gimple_call_num_args (stmt);
2057 5308180 : isra_scan_context ctx = ISRA_CTX_ARG;
2058 5308180 : scan_call_info call_info, *call_info_p = &call_info;
2059 5308180 : if (gimple_call_internal_p (stmt))
2060 : {
2061 179707 : call_info_p = NULL;
2062 179707 : ctx = ISRA_CTX_LOAD;
2063 179707 : internal_fn ifn = gimple_call_internal_fn (stmt);
2064 179707 : if (internal_store_fn_p (ifn))
2065 0 : ctx = ISRA_CTX_STORE;
2066 : }
2067 : else
2068 : {
2069 5128473 : call_info.cs = node->get_edge (stmt);
2070 5128473 : call_info.argument_count = argument_count;
2071 : }
2072 :
2073 16064331 : for (unsigned i = 0; i < argument_count; i++)
2074 : {
2075 10756151 : call_info.arg_idx = i;
2076 10756151 : scan_expr_access (gimple_call_arg (stmt, i), stmt,
2077 : ctx, bb, call_info_p);
2078 : }
2079 :
2080 5308180 : tree lhs = gimple_call_lhs (stmt);
2081 5308180 : if (lhs)
2082 2149774 : scan_expr_access (lhs, stmt, ISRA_CTX_STORE, bb);
2083 5308180 : int flags = gimple_call_flags (stmt);
2084 5308180 : if (final_bbs
2085 2062653 : && (((flags & (ECF_CONST | ECF_PURE)) == 0)
2086 335044 : || (flags & ECF_LOOPING_CONST_OR_PURE)))
2087 1782199 : bitmap_set_bit (final_bbs, bb->index);
2088 : }
2089 5308180 : break;
2090 :
2091 50157 : case GIMPLE_ASM:
2092 50157 : {
2093 50157 : gasm *asm_stmt = as_a <gasm *> (stmt);
2094 50157 : walk_stmt_load_store_addr_ops (asm_stmt, NULL, NULL, NULL,
2095 : asm_visit_addr);
2096 50157 : if (final_bbs)
2097 1943 : bitmap_set_bit (final_bbs, bb->index);
2098 :
2099 87410 : for (unsigned i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
2100 : {
2101 37253 : tree t = TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
2102 37253 : scan_expr_access (t, stmt, ISRA_CTX_LOAD, bb);
2103 : }
2104 102720 : for (unsigned i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
2105 : {
2106 52563 : tree t = TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
2107 52563 : scan_expr_access (t, stmt, ISRA_CTX_STORE, bb);
2108 : }
2109 : }
2110 : break;
2111 :
2112 : default:
2113 : break;
2114 : }
2115 : }
2116 : }
2117 1258180 : }
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 2442379 : ssa_name_only_returned_p (function *fun, tree name, bitmap analyzed)
2126 : {
2127 2442379 : bool res = true;
2128 2442379 : imm_use_iterator imm_iter;
2129 2442379 : gimple *stmt;
2130 :
2131 5531576 : FOR_EACH_IMM_USE_STMT (stmt, imm_iter, name)
2132 : {
2133 2669317 : if (is_gimple_debug (stmt))
2134 184574 : continue;
2135 :
2136 2484743 : if (gimple_code (stmt) == GIMPLE_RETURN)
2137 : {
2138 252896 : tree t = gimple_return_retval (as_a <greturn *> (stmt));
2139 252896 : if (t != name)
2140 : {
2141 : res = false;
2142 : break;
2143 : }
2144 : }
2145 2231847 : else if (!stmt_unremovable_because_of_non_call_eh_p (fun, stmt)
2146 2231847 : && ((is_gimple_assign (stmt) && !gimple_has_volatile_ops (stmt))
2147 1170551 : || gimple_code (stmt) == GIMPLE_PHI))
2148 : {
2149 : /* TODO: And perhaps for const function calls too? */
2150 1180493 : tree lhs;
2151 1180493 : if (gimple_code (stmt) == GIMPLE_PHI)
2152 215460 : lhs = gimple_phi_result (stmt);
2153 : else
2154 965033 : lhs = gimple_assign_lhs (stmt);
2155 :
2156 1180493 : if (TREE_CODE (lhs) != SSA_NAME)
2157 : {
2158 : res = false;
2159 : break;
2160 : }
2161 833355 : gcc_assert (!gimple_vdef (stmt));
2162 833355 : if (bitmap_set_bit (analyzed, SSA_NAME_VERSION (lhs))
2163 833355 : && !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 2442379 : }
2175 2442379 : 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 5141969 : isra_analyze_call (cgraph_edge *cs)
2185 : {
2186 5141969 : gcall *call_stmt = cs->call_stmt;
2187 5141969 : unsigned count = gimple_call_num_args (call_stmt);
2188 5141969 : isra_call_summary *csum = call_sums->get_create (cs);
2189 :
2190 15372686 : for (unsigned i = 0; i < count; i++)
2191 : {
2192 10230717 : tree arg = gimple_call_arg (call_stmt, i);
2193 10230717 : if (TREE_CODE (arg) == ADDR_EXPR)
2194 : {
2195 3201775 : poly_int64 poffset, psize, pmax_size;
2196 3201775 : bool reverse;
2197 3201775 : tree base = get_ref_base_and_extent (TREE_OPERAND (arg, 0), &poffset,
2198 3201775 : &psize, &pmax_size, &reverse);
2199 3201775 : HOST_WIDE_INT offset;
2200 3201775 : unsigned HOST_WIDE_INT ds;
2201 3201775 : if (DECL_P (base)
2202 2293322 : && (poffset.is_constant (&offset))
2203 2293322 : && tree_fits_uhwi_p (DECL_SIZE (base))
2204 5353964 : && ((ds = tree_to_uhwi (DECL_SIZE (base)) - offset)
2205 : < ISRA_ARG_SIZE_LIMIT * BITS_PER_UNIT))
2206 : {
2207 2018966 : csum->init_inputs (count);
2208 2018966 : gcc_assert (!csum->m_arg_flow[i].aggregate_pass_through);
2209 2018966 : csum->m_arg_flow[i].unit_size = ds / BITS_PER_UNIT;
2210 : }
2211 :
2212 3201775 : if (TREE_CODE (base) == VAR_DECL
2213 2112570 : && !TREE_STATIC (base)
2214 4569904 : && !loaded_decls->contains (base))
2215 : {
2216 897449 : csum->init_inputs (count);
2217 897449 : csum->m_arg_flow[i].constructed_for_calls = true;
2218 : }
2219 : }
2220 :
2221 10230717 : if (is_gimple_reg (arg))
2222 4032100 : continue;
2223 :
2224 6198617 : tree offset;
2225 6198617 : poly_int64 bitsize, bitpos;
2226 6198617 : machine_mode mode;
2227 6198617 : int unsignedp, reversep, volatilep = 0;
2228 6198617 : get_inner_reference (arg, &bitsize, &bitpos, &offset, &mode,
2229 : &unsignedp, &reversep, &volatilep);
2230 12397234 : if (!multiple_p (bitpos, BITS_PER_UNIT))
2231 : {
2232 0 : csum->m_bit_aligned_arg = true;
2233 0 : break;
2234 : }
2235 : }
2236 :
2237 5141969 : tree lhs = gimple_call_lhs (call_stmt);
2238 5141969 : 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 1988180 : if (TREE_CODE (lhs) == SSA_NAME)
2243 : {
2244 1630033 : bitmap analyzed = BITMAP_ALLOC (NULL);
2245 1630033 : if (ssa_name_only_returned_p (DECL_STRUCT_FUNCTION (cs->caller->decl),
2246 : lhs, analyzed))
2247 231541 : csum->m_return_returned = true;
2248 1630033 : 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 3153789 : else if (!gimple_call_must_tail_p (call_stmt))
2256 3153688 : csum->m_return_ignored = true;
2257 5141969 : }
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 1258180 : isra_analyze_all_outgoing_calls (cgraph_node *node)
2265 : {
2266 6264336 : for (cgraph_edge *cs = node->callees; cs; cs = cs->next_callee)
2267 5006156 : isra_analyze_call (cs);
2268 1393993 : for (cgraph_edge *cs = node->indirect_calls; cs; cs = cs->next_callee)
2269 135813 : isra_analyze_call (cs);
2270 1258180 : }
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 26801 : propagate_dereference_distances (struct function *fun)
2306 : {
2307 26801 : basic_block bb;
2308 :
2309 26801 : if (dump_file && (dump_flags & TDF_DETAILS))
2310 5 : dump_dereferences_table (dump_file, fun,
2311 : "Dereference table before propagation:\n");
2312 :
2313 26801 : auto_vec<basic_block> queue (last_basic_block_for_fn (fun));
2314 26801 : queue.quick_push (ENTRY_BLOCK_PTR_FOR_FN (fun));
2315 232515 : FOR_EACH_BB_FN (bb, fun)
2316 : {
2317 205714 : queue.quick_push (bb);
2318 205714 : bb->aux = bb;
2319 : }
2320 :
2321 260182 : while (!queue.is_empty ())
2322 : {
2323 233381 : edge_iterator ei;
2324 233381 : edge e;
2325 233381 : bool change = false;
2326 233381 : int i;
2327 :
2328 233381 : bb = queue.pop ();
2329 233381 : bb->aux = NULL;
2330 :
2331 233381 : if (bitmap_bit_p (final_bbs, bb->index))
2332 72707 : continue;
2333 :
2334 6210285 : for (i = 0; i < unsafe_by_ref_count; i++)
2335 : {
2336 6049611 : int idx = bb->index * unsafe_by_ref_count + i;
2337 6049611 : bool first = true;
2338 6049611 : HOST_WIDE_INT inh = 0;
2339 :
2340 14256753 : FOR_EACH_EDGE (e, ei, bb->succs)
2341 : {
2342 8207142 : int succ_idx = e->dest->index * unsafe_by_ref_count + i;
2343 :
2344 8207142 : if (e->dest == EXIT_BLOCK_PTR_FOR_FN (fun))
2345 0 : continue;
2346 :
2347 8207142 : if (first)
2348 : {
2349 6049606 : first = false;
2350 6049606 : inh = bb_dereferences [succ_idx];
2351 : }
2352 2157536 : else if (bb_dereferences [succ_idx] < inh)
2353 : inh = bb_dereferences [succ_idx];
2354 : }
2355 :
2356 6049611 : if (!first && bb_dereferences[idx] < inh)
2357 : {
2358 10678 : bb_dereferences[idx] = inh;
2359 10678 : change = true;
2360 : }
2361 : }
2362 :
2363 160674 : if (change)
2364 11622 : FOR_EACH_EDGE (e, ei, bb->preds)
2365 : {
2366 1857 : if (e->src->aux)
2367 991 : continue;
2368 :
2369 866 : e->src->aux = e->src;
2370 866 : queue.quick_push (e->src);
2371 : }
2372 : }
2373 :
2374 26801 : if (dump_file && (dump_flags & TDF_DETAILS))
2375 5 : dump_dereferences_table (dump_file, fun,
2376 : "Dereference table after propagation:\n");
2377 26801 : }
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 169092 : dereference_probable_p (struct function *fun, gensum_param_access *access)
2384 : {
2385 169092 : int threshold = opt_for_fn (fun->decl, param_ipa_sra_deref_prob_threshold);
2386 169092 : return access->load_count
2387 169092 : >= 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 374905 : 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 374905 : if (access->nonarg)
2402 : {
2403 324396 : *only_calls = false;
2404 324396 : *nonarg_acc_size += access->size;
2405 :
2406 324396 : 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 374526 : if (DECL_MODE (parm) != BLKmode
2416 374526 : && TYPE_MODE (access->type) == BLKmode)
2417 : {
2418 3231 : disqualify_split_candidate (desc, "Would convert a non-BLK to a BLK.");
2419 3231 : return true;
2420 : }
2421 :
2422 371295 : if (desc->by_ref)
2423 : {
2424 179570 : if (desc->safe_ref)
2425 : {
2426 144275 : if (!dereference_probable_p (fun, access))
2427 : {
2428 6395 : disqualify_split_candidate (desc, "Dereferences in callers "
2429 : "would happen much more frequently.");
2430 6395 : return true;
2431 : }
2432 : }
2433 : else
2434 : {
2435 35295 : int idx = (entry_bb_index * unsafe_by_ref_count + desc->deref_index);
2436 35295 : if ((access->offset + access->size) > bb_dereferences[idx])
2437 : {
2438 24817 : if (!dereference_probable_p (fun, access))
2439 : {
2440 2134 : disqualify_split_candidate (desc, "Would create a possibly "
2441 : "illegal dereference in a "
2442 : "caller.");
2443 2134 : return true;
2444 : }
2445 22683 : desc->conditionally_dereferenceable = true;
2446 : }
2447 : }
2448 : }
2449 :
2450 362766 : for (gensum_param_access *ch = access->first_child;
2451 384860 : ch;
2452 22094 : ch = ch->next_sibling)
2453 22096 : 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 431844 : copy_accesses_to_ipa_desc (gensum_param_access *from, isra_param_desc *desc)
2465 : {
2466 431844 : param_access *to = ggc_cleared_alloc<param_access> ();
2467 431844 : gcc_checking_assert ((from->offset % BITS_PER_UNIT) == 0);
2468 431844 : gcc_checking_assert ((from->size % BITS_PER_UNIT) == 0);
2469 431844 : to->unit_offset = from->offset / BITS_PER_UNIT;
2470 431844 : to->unit_size = from->size / BITS_PER_UNIT;
2471 431844 : to->type = from->type;
2472 431844 : to->alias_ptr_type = from->alias_ptr_type;
2473 431844 : to->certain = from->nonarg;
2474 431844 : to->reverse = from->reverse;
2475 431844 : vec_safe_push (desc->accesses, to);
2476 :
2477 431844 : for (gensum_param_access *ch = from->first_child;
2478 456053 : ch;
2479 24209 : ch = ch->next_sibling)
2480 24209 : copy_accesses_to_ipa_desc (ch, desc);
2481 431844 : }
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 830098 : process_scan_results (cgraph_node *node, struct function *fun,
2490 : isra_func_summary *ifs,
2491 : vec<gensum_param_desc> *param_descriptions)
2492 : {
2493 830098 : bool check_pass_throughs = false;
2494 830098 : bool dereferences_propagated = false;
2495 830098 : tree parm = DECL_ARGUMENTS (node->decl);
2496 830098 : unsigned param_count = param_descriptions->length();
2497 :
2498 830098 : for (unsigned desc_index = 0;
2499 3204727 : desc_index < param_count;
2500 2374629 : desc_index++, parm = DECL_CHAIN (parm))
2501 : {
2502 2374629 : gensum_param_desc *desc = &(*param_descriptions)[desc_index];
2503 2374629 : if (!desc->split_candidate)
2504 1871035 : continue;
2505 :
2506 515733 : if (flag_checking)
2507 515727 : isra_verify_access_tree (desc->accesses);
2508 :
2509 515733 : if (!dereferences_propagated
2510 509970 : && desc->by_ref
2511 354520 : && !desc->safe_ref
2512 162932 : && desc->accesses)
2513 : {
2514 26801 : propagate_dereference_distances (fun);
2515 26801 : dereferences_propagated = true;
2516 : }
2517 :
2518 515733 : HOST_WIDE_INT nonarg_acc_size = 0;
2519 515733 : bool only_calls = true;
2520 515733 : bool check_failed = false;
2521 :
2522 515733 : int entry_bb_index = ENTRY_BLOCK_PTR_FOR_FN (fun)->index;
2523 515733 : for (gensum_param_access *acc = desc->accesses;
2524 856403 : acc;
2525 340670 : acc = acc->next_sibling)
2526 352809 : 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 515733 : if (check_failed)
2533 12139 : continue;
2534 :
2535 503594 : if (only_calls)
2536 312305 : desc->locally_unused = true;
2537 :
2538 503594 : HOST_WIDE_INT cur_param_size
2539 503594 : = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (parm)));
2540 503594 : HOST_WIDE_INT param_size_limit, optimistic_limit;
2541 503594 : 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 325874 : param_size_limit
2549 325874 : = opt_for_fn (node->decl,
2550 : param_ipa_sra_ptr_growth_factor) * cur_param_size;
2551 325874 : optimistic_limit
2552 325874 : = (opt_for_fn (node->decl, param_ipa_sra_ptrwrap_growth_factor)
2553 : * param_size_limit);
2554 : }
2555 :
2556 503594 : if (nonarg_acc_size > optimistic_limit
2557 501220 : || (!desc->by_ref && nonarg_acc_size == param_size_limit))
2558 : {
2559 68853 : 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 434741 : desc->param_size_limit = param_size_limit / BITS_PER_UNIT;
2569 434741 : desc->nonarg_acc_size = nonarg_acc_size / BITS_PER_UNIT;
2570 434741 : if (desc->split_candidate && desc->ptr_pt_count)
2571 : {
2572 182664 : 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 830098 : hash_map<gimple *, bool> analyzed_stmts;
2598 830098 : bitmap always_executed_bbs = NULL;
2599 830098 : if (check_pass_throughs)
2600 1163791 : for (cgraph_edge *cs = node->callees; cs; cs = cs->next_callee)
2601 : {
2602 1016427 : gcall *call_stmt = cs->call_stmt;
2603 1016427 : 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 1992974 : bool uses_memory_as_obtained = vuse && SSA_NAME_IS_DEFAULT_DEF (vuse);
2609 :
2610 1016427 : unsigned count = gimple_call_num_args (call_stmt);
2611 1016427 : isra_call_summary *csum = call_sums->get_create (cs);
2612 1016427 : csum->init_inputs (count);
2613 1016427 : csum->m_before_any_store = uses_memory_as_obtained;
2614 3285221 : for (unsigned argidx = 0; argidx < count; argidx++)
2615 : {
2616 2268794 : if (!csum->m_arg_flow[argidx].pointer_pass_through)
2617 4118455 : continue;
2618 419133 : unsigned pidx
2619 419133 : = get_single_param_flow_source (&csum->m_arg_flow[argidx]);
2620 419133 : gensum_param_desc *desc = &(*param_descriptions)[pidx];
2621 419133 : if (!desc->split_candidate)
2622 : {
2623 35827 : csum->m_arg_flow[argidx].pointer_pass_through = false;
2624 35827 : continue;
2625 : }
2626 383306 : if (!uses_memory_as_obtained)
2627 139576 : continue;
2628 :
2629 243730 : if (desc->safe_ref)
2630 : {
2631 44907 : csum->m_arg_flow[argidx].safe_to_import_accesses = true;
2632 44907 : 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 198823 : gimple_stmt_iterator gsi = gsi_for_stmt (call_stmt);
2638 198823 : bool safe = true;
2639 198823 : int n = 0;
2640 616180 : for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
2641 : {
2642 123194 : bool *b = analyzed_stmts.get (gsi_stmt (gsi));
2643 123194 : if (b)
2644 : {
2645 9895 : safe = *b;
2646 9895 : gsi_next (&gsi);
2647 9895 : break;
2648 : }
2649 113299 : n++;
2650 113299 : if (stmt_may_terminate_function_p (fun, gsi_stmt (gsi), false))
2651 : {
2652 : safe = false;
2653 : break;
2654 : }
2655 : }
2656 198823 : if (n)
2657 : {
2658 32919 : if (gsi_end_p (gsi))
2659 57774 : gsi = gsi_start_bb (gimple_bb (call_stmt));
2660 146218 : for (; gsi_stmt (gsi) != call_stmt; gsi_next (&gsi))
2661 113299 : analyzed_stmts.get_or_insert (gsi_stmt (gsi)) = safe;
2662 : }
2663 :
2664 198823 : if (safe && !always_executed_bbs)
2665 : {
2666 55997 : mark_dfs_back_edges ();
2667 55997 : always_executed_bbs = find_always_executed_bbs (fun, false);
2668 : }
2669 198823 : if (safe && bitmap_bit_p (always_executed_bbs, gimple_bb (call_stmt)->index))
2670 45033 : csum->m_arg_flow[argidx].safe_to_import_accesses = true;
2671 : }
2672 :
2673 : }
2674 830098 : 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 830098 : vec_safe_reserve_exact (ifs->m_parameters, param_count);
2683 830098 : ifs->m_parameters->quick_grow_cleared (param_count);
2684 3204727 : for (unsigned desc_index = 0; desc_index < param_count; desc_index++)
2685 : {
2686 2374629 : gensum_param_desc *s = &(*param_descriptions)[desc_index];
2687 2374629 : isra_param_desc *d = &(*ifs->m_parameters)[desc_index];
2688 :
2689 2374629 : d->param_size_limit = s->param_size_limit;
2690 2374629 : d->size_reached = s->nonarg_acc_size;
2691 2374629 : d->locally_unused = s->locally_unused;
2692 2374629 : d->split_candidate = s->split_candidate;
2693 2374629 : d->by_ref = s->by_ref;
2694 2374629 : d->remove_only_when_retval_removed = s->remove_only_when_retval_removed;
2695 2374629 : d->split_only_when_retval_removed = s->split_only_when_retval_removed;
2696 2374629 : d->conditionally_dereferenceable = s->conditionally_dereferenceable;
2697 :
2698 2374629 : for (gensum_param_access *acc = s->accesses;
2699 2782264 : acc;
2700 407635 : acc = acc->next_sibling)
2701 407635 : copy_accesses_to_ipa_desc (acc, d);
2702 : }
2703 :
2704 830098 : if (dump_file)
2705 135 : dump_isra_param_descriptors (dump_file, node->decl, ifs, false);
2706 830098 : }
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 164490 : overlapping_certain_accesses_p (isra_param_desc *desc,
2715 : bool *certain_access_present_p)
2716 : {
2717 164490 : unsigned pclen = vec_safe_length (desc->accesses);
2718 433586 : for (unsigned i = 0; i < pclen; i++)
2719 : {
2720 271425 : param_access *a1 = (*desc->accesses)[i];
2721 :
2722 271425 : if (!a1->certain)
2723 6364 : continue;
2724 265061 : if (certain_access_present_p)
2725 250674 : *certain_access_present_p = true;
2726 431309 : for (unsigned j = i + 1; j < pclen; j++)
2727 : {
2728 168577 : param_access *a2 = (*desc->accesses)[j];
2729 168577 : if (a2->certain
2730 168503 : && a1->unit_offset < a2->unit_offset + a2->unit_size
2731 168165 : && 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 2593242 : verify_splitting_accesses (cgraph_node *node, bool certain_must_exist)
2744 : {
2745 2593242 : isra_func_summary *ifs = func_sums->get (node);
2746 2593242 : if (!ifs || !ifs->m_candidate)
2747 : return;
2748 1387990 : unsigned param_count = vec_safe_length (ifs->m_parameters);
2749 4517960 : for (unsigned pidx = 0; pidx < param_count; pidx++)
2750 : {
2751 3129970 : isra_param_desc *desc = &(*ifs->m_parameters)[pidx];
2752 3129970 : if (!desc->split_candidate || desc->locally_unused)
2753 2979798 : continue;
2754 :
2755 150172 : bool certain_access_present = !certain_must_exist;
2756 150172 : 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 150172 : 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 124591 : ipa_sra_generate_summary (void)
2772 : {
2773 124591 : struct cgraph_node *node;
2774 :
2775 124591 : gcc_checking_assert (!func_sums);
2776 124591 : gcc_checking_assert (!call_sums);
2777 124591 : func_sums
2778 124591 : = (new (ggc_alloc_no_dtor <ipa_sra_function_summaries> ())
2779 124591 : ipa_sra_function_summaries (symtab, true));
2780 124591 : call_sums = new ipa_sra_call_summaries (symtab);
2781 :
2782 1364722 : FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
2783 1240131 : ipa_sra_summarize_function (node);
2784 124591 : 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 281252 : isra_write_edge_summary (output_block *ob, cgraph_edge *e)
2792 : {
2793 281252 : isra_call_summary *csum = call_sums->get (e);
2794 281252 : unsigned input_count = csum->m_arg_flow.length ();
2795 281252 : streamer_write_uhwi (ob, input_count);
2796 753915 : for (unsigned i = 0; i < input_count; i++)
2797 : {
2798 472663 : isra_param_flow *ipf = &csum->m_arg_flow[i];
2799 472663 : streamer_write_hwi (ob, ipf->length);
2800 472663 : bitpack_d bp = bitpack_create (ob->main_stream);
2801 547424 : for (int j = 0; j < ipf->length; j++)
2802 74761 : bp_pack_value (&bp, ipf->inputs[j], 8);
2803 472663 : bp_pack_value (&bp, ipf->aggregate_pass_through, 1);
2804 472663 : bp_pack_value (&bp, ipf->pointer_pass_through, 1);
2805 472663 : bp_pack_value (&bp, ipf->safe_to_import_accesses, 1);
2806 472663 : bp_pack_value (&bp, ipf->constructed_for_calls, 1);
2807 472663 : streamer_write_bitpack (&bp);
2808 472663 : streamer_write_uhwi (ob, ipf->unit_offset);
2809 472663 : streamer_write_uhwi (ob, ipf->unit_size);
2810 : }
2811 281252 : bitpack_d bp = bitpack_create (ob->main_stream);
2812 281252 : bp_pack_value (&bp, csum->m_return_ignored, 1);
2813 281252 : bp_pack_value (&bp, csum->m_return_returned, 1);
2814 281252 : bp_pack_value (&bp, csum->m_bit_aligned_arg, 1);
2815 281252 : bp_pack_value (&bp, csum->m_before_any_store, 1);
2816 281252 : streamer_write_bitpack (&bp);
2817 281252 : }
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 49047 : isra_write_node_summary (output_block *ob, cgraph_node *node)
2824 : {
2825 49047 : isra_func_summary *ifs = func_sums->get (node);
2826 49047 : lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
2827 49047 : int node_ref = lto_symtab_encoder_encode (encoder, node);
2828 49047 : streamer_write_uhwi (ob, node_ref);
2829 :
2830 49047 : unsigned param_desc_count = vec_safe_length (ifs->m_parameters);
2831 49047 : streamer_write_uhwi (ob, param_desc_count);
2832 298677 : for (unsigned i = 0; i < param_desc_count; i++)
2833 : {
2834 249630 : isra_param_desc *desc = &(*ifs->m_parameters)[i];
2835 249630 : unsigned access_count = vec_safe_length (desc->accesses);
2836 249630 : streamer_write_uhwi (ob, access_count);
2837 252873 : for (unsigned j = 0; j < access_count; j++)
2838 : {
2839 3243 : param_access *acc = (*desc->accesses)[j];
2840 3243 : stream_write_tree (ob, acc->type, true);
2841 3243 : stream_write_tree (ob, acc->alias_ptr_type, true);
2842 3243 : streamer_write_uhwi (ob, acc->unit_offset);
2843 3243 : streamer_write_uhwi (ob, acc->unit_size);
2844 3243 : bitpack_d bp = bitpack_create (ob->main_stream);
2845 3243 : bp_pack_value (&bp, acc->certain, 1);
2846 3243 : bp_pack_value (&bp, acc->reverse, 1);
2847 3243 : streamer_write_bitpack (&bp);
2848 : }
2849 249630 : streamer_write_uhwi (ob, desc->param_size_limit);
2850 249630 : streamer_write_uhwi (ob, desc->size_reached);
2851 249630 : gcc_assert (desc->safe_size == 0);
2852 249630 : bitpack_d bp = bitpack_create (ob->main_stream);
2853 249630 : bp_pack_value (&bp, desc->locally_unused, 1);
2854 249630 : bp_pack_value (&bp, desc->split_candidate, 1);
2855 249630 : bp_pack_value (&bp, desc->by_ref, 1);
2856 249630 : gcc_assert (!desc->not_specially_constructed);
2857 249630 : bp_pack_value (&bp, desc->remove_only_when_retval_removed, 1);
2858 249630 : bp_pack_value (&bp, desc->split_only_when_retval_removed, 1);
2859 249630 : bp_pack_value (&bp, desc->conditionally_dereferenceable, 1);
2860 249630 : gcc_assert (!desc->safe_size_set);
2861 249630 : streamer_write_bitpack (&bp);
2862 : }
2863 49047 : bitpack_d bp = bitpack_create (ob->main_stream);
2864 49047 : bp_pack_value (&bp, ifs->m_candidate, 1);
2865 49047 : bp_pack_value (&bp, ifs->m_returns_value, 1);
2866 49047 : bp_pack_value (&bp, ifs->m_return_ignored, 1);
2867 49047 : gcc_assert (!ifs->m_queued);
2868 49047 : streamer_write_bitpack (&bp);
2869 :
2870 327850 : for (cgraph_edge *e = node->callees; e; e = e->next_callee)
2871 278803 : isra_write_edge_summary (ob, e);
2872 51496 : for (cgraph_edge *e = node->indirect_calls; e; e = e->next_callee)
2873 2449 : isra_write_edge_summary (ob, e);
2874 49047 : }
2875 :
2876 : /* Write intraprocedural analysis information into a stream for LTO WPA. */
2877 :
2878 : static void
2879 19791 : ipa_sra_write_summary (void)
2880 : {
2881 19791 : if (!func_sums || !call_sums)
2882 0 : return;
2883 :
2884 19791 : struct output_block *ob = create_output_block (LTO_section_ipa_sra);
2885 19791 : lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
2886 19791 : ob->symbol = NULL;
2887 :
2888 19791 : unsigned int count = 0;
2889 19791 : lto_symtab_encoder_iterator lsei;
2890 19791 : for (lsei = lsei_start_function_in_partition (encoder);
2891 113041 : !lsei_end_p (lsei);
2892 93250 : lsei_next_function_in_partition (&lsei))
2893 : {
2894 93250 : cgraph_node *node = lsei_cgraph_node (lsei);
2895 93250 : if (node->has_gimple_body_p ()
2896 93250 : && func_sums->get (node) != NULL)
2897 49047 : count++;
2898 : }
2899 19791 : streamer_write_uhwi (ob, count);
2900 :
2901 : /* Process all of the functions. */
2902 113041 : for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
2903 93250 : lsei_next_function_in_partition (&lsei))
2904 : {
2905 93250 : cgraph_node *node = lsei_cgraph_node (lsei);
2906 93250 : if (node->has_gimple_body_p ()
2907 93250 : && func_sums->get (node) != NULL)
2908 49047 : isra_write_node_summary (ob, node);
2909 : }
2910 19791 : streamer_write_char_stream (ob->main_stream, 0);
2911 19791 : produce_asm (ob);
2912 19791 : 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 253093 : isra_read_edge_summary (struct lto_input_block *ib, cgraph_edge *cs)
2920 : {
2921 253093 : isra_call_summary *csum = call_sums->get_create (cs);
2922 253093 : unsigned input_count = streamer_read_uhwi (ib);
2923 253093 : csum->init_inputs (input_count);
2924 699961 : for (unsigned i = 0; i < input_count; i++)
2925 : {
2926 446868 : isra_param_flow *ipf = &csum->m_arg_flow[i];
2927 446868 : ipf->length = streamer_read_hwi (ib);
2928 446868 : bitpack_d bp = streamer_read_bitpack (ib);
2929 514198 : for (int j = 0; j < ipf->length; j++)
2930 67330 : ipf->inputs[j] = bp_unpack_value (&bp, 8);
2931 446868 : ipf->aggregate_pass_through = bp_unpack_value (&bp, 1);
2932 446868 : ipf->pointer_pass_through = bp_unpack_value (&bp, 1);
2933 446868 : ipf->safe_to_import_accesses = bp_unpack_value (&bp, 1);
2934 446868 : ipf->constructed_for_calls = bp_unpack_value (&bp, 1);
2935 446868 : ipf->unit_offset = streamer_read_uhwi (ib);
2936 446868 : ipf->unit_size = streamer_read_uhwi (ib);
2937 : }
2938 253093 : bitpack_d bp = streamer_read_bitpack (ib);
2939 253093 : csum->m_return_ignored = bp_unpack_value (&bp, 1);
2940 253093 : csum->m_return_returned = bp_unpack_value (&bp, 1);
2941 253093 : csum->m_bit_aligned_arg = bp_unpack_value (&bp, 1);
2942 253093 : csum->m_before_any_store = bp_unpack_value (&bp, 1);
2943 253093 : }
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 34679 : isra_read_node_info (struct lto_input_block *ib, cgraph_node *node,
2950 : struct data_in *data_in)
2951 : {
2952 34679 : isra_func_summary *ifs = func_sums->get_create (node);
2953 34679 : unsigned param_desc_count = streamer_read_uhwi (ib);
2954 34679 : if (param_desc_count > 0)
2955 : {
2956 17675 : vec_safe_reserve_exact (ifs->m_parameters, param_desc_count);
2957 17675 : ifs->m_parameters->quick_grow_cleared (param_desc_count);
2958 : }
2959 62548 : for (unsigned i = 0; i < param_desc_count; i++)
2960 : {
2961 27869 : isra_param_desc *desc = &(*ifs->m_parameters)[i];
2962 27869 : unsigned access_count = streamer_read_uhwi (ib);
2963 29598 : for (unsigned j = 0; j < access_count; j++)
2964 : {
2965 1729 : param_access *acc = ggc_cleared_alloc<param_access> ();
2966 1729 : acc->type = stream_read_tree (ib, data_in);
2967 1729 : acc->alias_ptr_type = stream_read_tree (ib, data_in);
2968 1729 : acc->unit_offset = streamer_read_uhwi (ib);
2969 1729 : acc->unit_size = streamer_read_uhwi (ib);
2970 1729 : bitpack_d bp = streamer_read_bitpack (ib);
2971 1729 : acc->certain = bp_unpack_value (&bp, 1);
2972 1729 : acc->reverse = bp_unpack_value (&bp, 1);
2973 1729 : vec_safe_push (desc->accesses, acc);
2974 : }
2975 27869 : desc->param_size_limit = streamer_read_uhwi (ib);
2976 27869 : desc->size_reached = streamer_read_uhwi (ib);
2977 27869 : desc->safe_size = 0;
2978 27869 : bitpack_d bp = streamer_read_bitpack (ib);
2979 27869 : desc->locally_unused = bp_unpack_value (&bp, 1);
2980 27869 : desc->split_candidate = bp_unpack_value (&bp, 1);
2981 27869 : desc->by_ref = bp_unpack_value (&bp, 1);
2982 27869 : desc->not_specially_constructed = 0;
2983 27869 : desc->remove_only_when_retval_removed = bp_unpack_value (&bp, 1);
2984 27869 : desc->split_only_when_retval_removed = bp_unpack_value (&bp, 1);
2985 27869 : desc->conditionally_dereferenceable = bp_unpack_value (&bp, 1);
2986 27869 : desc->safe_size_set = 0;
2987 : }
2988 34679 : bitpack_d bp = streamer_read_bitpack (ib);
2989 34679 : ifs->m_candidate = bp_unpack_value (&bp, 1);
2990 34679 : ifs->m_returns_value = bp_unpack_value (&bp, 1);
2991 34679 : ifs->m_return_ignored = bp_unpack_value (&bp, 1);
2992 34679 : ifs->m_queued = 0;
2993 :
2994 286449 : for (cgraph_edge *e = node->callees; e; e = e->next_callee)
2995 251770 : isra_read_edge_summary (ib, e);
2996 36002 : for (cgraph_edge *e = node->indirect_calls; e; e = e->next_callee)
2997 1323 : isra_read_edge_summary (ib, e);
2998 34679 : }
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 10826 : isra_read_summary_section (struct lto_file_decl_data *file_data,
3006 : const char *data, size_t len)
3007 : {
3008 10826 : const struct lto_function_header *header =
3009 : (const struct lto_function_header *) data;
3010 10826 : const int cfg_offset = sizeof (struct lto_function_header);
3011 10826 : const int main_offset = cfg_offset + header->cfg_size;
3012 10826 : const int string_offset = main_offset + header->main_size;
3013 10826 : struct data_in *data_in;
3014 10826 : unsigned int i;
3015 10826 : unsigned int count;
3016 :
3017 10826 : lto_input_block ib_main ((const char *) data + main_offset,
3018 10826 : header->main_size, file_data);
3019 :
3020 10826 : data_in =
3021 21652 : lto_data_in_create (file_data, (const char *) data + string_offset,
3022 10826 : header->string_size, vNULL);
3023 10826 : count = streamer_read_uhwi (&ib_main);
3024 :
3025 45505 : for (i = 0; i < count; i++)
3026 : {
3027 34679 : unsigned int index;
3028 34679 : struct cgraph_node *node;
3029 34679 : lto_symtab_encoder_t encoder;
3030 :
3031 34679 : index = streamer_read_uhwi (&ib_main);
3032 34679 : encoder = file_data->symtab_node_encoder;
3033 34679 : node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref (encoder,
3034 : index));
3035 34679 : gcc_assert (node->definition);
3036 34679 : isra_read_node_info (&ib_main, node, data_in);
3037 : }
3038 10826 : lto_free_section_data (file_data, LTO_section_ipa_sra, NULL, data,
3039 : len);
3040 10826 : lto_data_in_delete (data_in);
3041 10826 : }
3042 :
3043 : /* Read intraprocedural analysis information into a stream for LTO WPA. */
3044 :
3045 : static void
3046 10151 : ipa_sra_read_summary (void)
3047 : {
3048 10151 : struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
3049 10151 : struct lto_file_decl_data *file_data;
3050 10151 : unsigned int j = 0;
3051 :
3052 10151 : gcc_checking_assert (!func_sums);
3053 10151 : gcc_checking_assert (!call_sums);
3054 10151 : func_sums
3055 10151 : = (new (ggc_alloc_no_dtor <ipa_sra_function_summaries> ())
3056 10151 : ipa_sra_function_summaries (symtab, true));
3057 10151 : call_sums = new ipa_sra_call_summaries (symtab);
3058 :
3059 20988 : while ((file_data = file_data_vec[j++]))
3060 : {
3061 10837 : size_t len;
3062 10837 : const char *data
3063 10837 : = lto_get_summary_section_data (file_data, LTO_section_ipa_sra, &len);
3064 10837 : if (data)
3065 10826 : isra_read_summary_section (file_data, data, len);
3066 : }
3067 10151 : }
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 1019873 : ipa_sra_ipa_function_checks (cgraph_node *node)
3122 : {
3123 1019873 : if (!node->can_be_local_p ())
3124 : {
3125 655283 : if (dump_file)
3126 87 : fprintf (dump_file, "Function %s disqualified because it cannot be "
3127 : "made local.\n", node->dump_name ());
3128 655283 : return false;
3129 : }
3130 364590 : 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 368610 : check_for_caller_issues (struct cgraph_node *node, void *data)
3163 : {
3164 368610 : struct caller_issues *issues = (struct caller_issues *) data;
3165 :
3166 1414031 : for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
3167 : {
3168 1045647 : 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 1045647 : if (issues->candidate->calls_comdat_local
3176 10 : && issues->candidate->same_comdat_group
3177 1045657 : && !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 1045647 : isra_call_summary *csum = call_sums->get (cs);
3184 1045647 : if (!csum)
3185 : {
3186 226 : issues->unknown_callsite = true;
3187 226 : return true;
3188 : }
3189 :
3190 1045421 : if (csum->m_bit_aligned_arg)
3191 0 : issues->bit_aligned_aggregate_argument = true;
3192 :
3193 1045421 : 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 364590 : check_all_callers_for_issues (cgraph_node *node)
3203 : {
3204 364590 : struct caller_issues issues;
3205 364590 : memset (&issues, 0, sizeof (issues));
3206 364590 : issues.candidate = node;
3207 :
3208 364590 : node->call_for_symbol_and_aliases (check_for_caller_issues, &issues, true);
3209 364590 : if (issues.unknown_callsite)
3210 : {
3211 226 : 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 226 : return true;
3215 : }
3216 : /* TODO: We should be able to process at least some types of thunks. */
3217 364364 : 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 364364 : 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 364364 : 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 364364 : 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 15466 : find_param_access (isra_param_desc *param_desc, unsigned offset, unsigned size)
3263 : {
3264 15466 : 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 15543 : for (unsigned i = 0; i < pclen; i++)
3270 15498 : if ((*param_desc->accesses)[i]->unit_offset == offset
3271 15498 : && (*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 208885 : size_would_violate_limit_p (isra_param_desc *desc, unsigned size)
3282 : {
3283 208885 : unsigned limit = desc->param_size_limit;
3284 0 : if (size > limit
3285 205606 : || (!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 11989 : bump_reached_size (isra_param_desc *desc, unsigned size, unsigned idx)
3296 : {
3297 11989 : unsigned after = desc->size_reached + size;
3298 11989 : if (size_would_violate_limit_p (desc, after))
3299 : {
3300 11957 : if (dump_file && (dump_flags & TDF_DETAILS))
3301 0 : fprintf (dump_file, " ...size limit reached, disqualifying "
3302 : "candidate parameter %u\n", idx);
3303 11957 : desc->split_candidate = false;
3304 11957 : 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 507534 : process_edge_to_unknown_caller (cgraph_edge *cs)
3315 : {
3316 507534 : isra_func_summary *from_ifs = func_sums->get (cs->caller);
3317 507534 : gcc_checking_assert (from_ifs);
3318 507534 : isra_call_summary *csum = call_sums->get (cs);
3319 :
3320 507534 : 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 507534 : unsigned args_count = csum->m_arg_flow.length ();
3325 1243087 : for (unsigned i = 0; i < args_count; i++)
3326 : {
3327 735553 : isra_param_flow *ipf = &csum->m_arg_flow[i];
3328 :
3329 735553 : if (ipf->pointer_pass_through)
3330 : {
3331 191948 : isra_param_desc *param_desc
3332 191948 : = &(*from_ifs->m_parameters)[get_single_param_flow_source (ipf)];
3333 191948 : param_desc->locally_unused = false;
3334 191948 : param_desc->split_candidate = false;
3335 191948 : continue;
3336 191948 : }
3337 543605 : 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 636093 : for (int j = 0; j < ipf->length; j++)
3365 : {
3366 98072 : int input_idx = ipf->inputs[j];
3367 98072 : (*from_ifs->m_parameters)[input_idx].locally_unused = false;
3368 : }
3369 : }
3370 507534 : }
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 822513 : param_removal_cross_scc_edge (cgraph_edge *cs)
3378 : {
3379 822513 : enum availability availability;
3380 822513 : cgraph_node *callee = cs->callee->function_symbol (&availability);
3381 822513 : isra_func_summary *to_ifs = func_sums->get (callee);
3382 385179 : if (!to_ifs || !to_ifs->m_candidate
3383 339174 : || (availability < AVAIL_AVAILABLE)
3384 1161687 : || vec_safe_is_empty (to_ifs->m_parameters))
3385 : {
3386 492995 : process_edge_to_unknown_caller (cs);
3387 492995 : return;
3388 : }
3389 329518 : isra_func_summary *from_ifs = func_sums->get (cs->caller);
3390 329518 : gcc_checking_assert (from_ifs);
3391 :
3392 329518 : isra_call_summary *csum = call_sums->get (cs);
3393 329518 : unsigned args_count = csum->m_arg_flow.length ();
3394 329518 : unsigned param_count = vec_safe_length (to_ifs->m_parameters);
3395 :
3396 1162525 : for (unsigned i = 0; i < args_count; i++)
3397 : {
3398 833007 : bool unused_in_callee;
3399 833007 : if (i < param_count)
3400 833003 : unused_in_callee = (*to_ifs->m_parameters)[i].locally_unused;
3401 : else
3402 : unused_in_callee = false;
3403 :
3404 833003 : if (!unused_in_callee)
3405 : {
3406 785860 : isra_param_flow *ipf = &csum->m_arg_flow[i];
3407 1021762 : for (int j = 0; j < ipf->length; j++)
3408 : {
3409 235902 : int input_idx = ipf->inputs[j];
3410 235902 : (*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 152135 : 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 151751 : ifs->m_queued = true;
3426 151751 : 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 11582 : isra_mark_caller_param_used (isra_func_summary *from_ifs, int input_idx,
3435 : cgraph_node *caller, vec<cgraph_node *> *stack)
3436 : {
3437 11582 : 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 11582 : }
3443 :
3444 : /* Combine safe_size of DESC with SIZE and return true if it has changed. */
3445 :
3446 : static bool
3447 2363294 : update_safe_size (isra_param_desc *desc, unsigned size)
3448 : {
3449 0 : if (!desc->safe_size_set)
3450 : {
3451 754259 : desc->safe_size_set = 1;
3452 754259 : desc->safe_size = size;
3453 754259 : return true;
3454 : }
3455 1609035 : if (desc->safe_size <= size)
3456 : return false;
3457 19821 : desc->safe_size = size;
3458 19821 : 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 712333 : flip_all_hints_pessimistic (isra_param_desc *desc)
3466 : {
3467 712333 : 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 424663 : flip_all_param_hints_pessimistic (isra_func_summary *ifs)
3478 : {
3479 424663 : if (!ifs || !ifs->m_candidate)
3480 : return false;
3481 :
3482 25318 : bool ret = false;
3483 25318 : unsigned param_count = vec_safe_length (ifs->m_parameters);
3484 :
3485 71523 : for (unsigned i = 0; i < param_count; i++)
3486 92410 : 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 4825397 : propagate_param_hints_accross_call (cgraph_edge *cs, isra_func_summary *to_ifs)
3497 : {
3498 4825397 : if (!to_ifs || !to_ifs->m_candidate)
3499 : return false;
3500 :
3501 1595642 : isra_call_summary *csum = call_sums->get (cs);
3502 1595642 : bool ret = false;
3503 1595642 : unsigned args_count = csum->m_arg_flow.length ();
3504 1595642 : unsigned param_count = vec_safe_length (to_ifs->m_parameters);
3505 :
3506 5117189 : for (unsigned i = 0; i < param_count; i++)
3507 : {
3508 3521547 : isra_param_desc *desc = &(*to_ifs->m_parameters)[i];
3509 3521547 : if (i >= args_count)
3510 : {
3511 666128 : ret |= flip_all_hints_pessimistic (desc);
3512 666128 : continue;
3513 : }
3514 :
3515 2855419 : if (desc->by_ref)
3516 : {
3517 1650979 : isra_param_flow *ipf = &csum->m_arg_flow[i];
3518 :
3519 1650979 : if (!ipf->constructed_for_calls)
3520 1238409 : desc->not_specially_constructed = true;
3521 :
3522 1650979 : if (ipf->pointer_pass_through)
3523 : {
3524 269141 : isra_func_summary *from_ifs = func_sums->get (cs->caller);
3525 269141 : int srcidx = get_single_param_flow_source (ipf);
3526 269141 : if (vec_safe_length (from_ifs->m_parameters) > (unsigned) srcidx)
3527 : {
3528 162458 : isra_param_desc *src_d = &(*from_ifs->m_parameters)[srcidx];
3529 162458 : if (src_d->safe_size_set)
3530 324880 : ret |= update_safe_size (desc, src_d->safe_size);
3531 : }
3532 : else
3533 213366 : ret |= update_safe_size (desc, 0);
3534 : }
3535 1381838 : else if (!ipf->aggregate_pass_through)
3536 2763674 : 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 1337583 : propagate_hints_to_all_callees (cgraph_node *node, isra_func_summary *from_ifs,
3550 : vec<cgraph_node *> *stack)
3551 : {
3552 6587643 : for (cgraph_edge *cs = node->callees; cs; cs = cs->next_callee)
3553 : {
3554 5250060 : enum availability availability;
3555 5250060 : cgraph_node *callee = cs->callee->function_symbol (&availability);
3556 5250060 : isra_func_summary *to_ifs = func_sums->get (callee);
3557 5250060 : if (!from_ifs)
3558 : {
3559 424663 : if (flip_all_param_hints_pessimistic (to_ifs)
3560 424663 : && ipa_edge_within_scc (cs))
3561 220 : isra_push_node_to_stack (callee, to_ifs, stack);
3562 : }
3563 4825397 : else if (propagate_param_hints_accross_call (cs, to_ifs)
3564 4825397 : && ipa_edge_within_scc (cs))
3565 4799 : isra_push_node_to_stack (callee, to_ifs, stack);
3566 : }
3567 1337583 : }
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 28376 : propagate_used_across_scc_edge (cgraph_edge *cs, vec<cgraph_node *> *stack)
3575 : {
3576 28376 : isra_func_summary *from_ifs = func_sums->get (cs->caller);
3577 28376 : if (!from_ifs || vec_safe_is_empty (from_ifs->m_parameters))
3578 15428 : return;
3579 :
3580 12948 : isra_call_summary *csum = call_sums->get (cs);
3581 12948 : gcc_checking_assert (csum);
3582 12948 : unsigned args_count = csum->m_arg_flow.length ();
3583 12948 : enum availability availability;
3584 12948 : cgraph_node *callee = cs->callee->function_symbol (&availability);
3585 12948 : isra_func_summary *to_ifs = func_sums->get (callee);
3586 :
3587 12948 : unsigned param_count
3588 12750 : = (to_ifs && (availability >= AVAIL_AVAILABLE))
3589 25432 : ? vec_safe_length (to_ifs->m_parameters) : 0;
3590 36633 : for (unsigned i = 0; i < args_count; i++)
3591 : {
3592 26991 : if (i < param_count
3593 23685 : && (*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 20379 : isra_param_flow *ipf = &csum->m_arg_flow[i];
3599 31961 : for (int j = 0; j < ipf->length; j++)
3600 : {
3601 11582 : int input_idx = ipf->inputs[j];
3602 11582 : 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 1410636 : propagate_used_to_scc_callers (cgraph_node *node, void *data)
3613 : {
3614 1410636 : vec<cgraph_node *> *stack = (vec<cgraph_node *> *) data;
3615 1410636 : cgraph_edge *cs;
3616 3426447 : for (cs = node->callers; cs; cs = cs->next_caller)
3617 2015811 : if (ipa_edge_within_scc (cs))
3618 28376 : propagate_used_across_scc_edge (cs, stack);
3619 1410636 : 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 5241 : 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 5241 : unsigned pclen = vec_safe_length (param_desc->accesses);
3671 5241 : unsigned aclen = vec_safe_length (arg_desc->accesses);
3672 5241 : unsigned prop_count = 0;
3673 5241 : unsigned prop_size = 0;
3674 5241 : bool change = false;
3675 :
3676 5241 : auto_vec <enum acc_prop_kind, 8> prop_kinds (aclen);
3677 12927 : for (unsigned j = 0; j < aclen; j++)
3678 : {
3679 7888 : param_access *argacc = (*arg_desc->accesses)[j];
3680 7888 : prop_kinds.safe_push (ACC_PROP_DONT);
3681 :
3682 7888 : if (arg_size > 0
3683 2712 : && argacc->unit_offset + argacc->unit_size > arg_size)
3684 : return "callee access outsize size boundary";
3685 :
3686 7888 : if (!argacc->certain)
3687 382 : continue;
3688 :
3689 7506 : unsigned offset = argacc->unit_offset + delta_offset;
3690 :
3691 7506 : 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 16159 : for (unsigned i = 0; i < pclen; i++)
3710 : {
3711 : /* Check for overlaps. */
3712 8855 : param_access *pacc = (*param_desc->accesses)[i];
3713 8855 : if (pacc->unit_offset == offset
3714 4224 : && pacc->unit_size == argacc->unit_size)
3715 : {
3716 3065 : if (argacc->alias_ptr_type != pacc->alias_ptr_type
3717 2865 : || !types_compatible_p (argacc->type, pacc->type)
3718 5930 : || argacc->reverse != pacc->reverse)
3719 200 : return "propagated access types would not match existing ones";
3720 :
3721 2865 : exact_match = true;
3722 2865 : 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 2865 : continue;
3729 : }
3730 :
3731 5790 : if (offset < pacc->unit_offset + pacc->unit_size
3732 3628 : && offset + argacc->unit_size > pacc->unit_offset)
3733 : {
3734 : /* None permissible with load accesses, possible to fit into
3735 : argument ones. */
3736 2331 : if (pacc->certain
3737 2330 : || offset < pacc->unit_offset
3738 2330 : || (offset + argacc->unit_size
3739 : > pacc->unit_offset + pacc->unit_size))
3740 : return "a propagated access would conflict in caller";
3741 : }
3742 : }
3743 :
3744 7304 : if (!exact_match)
3745 : {
3746 4439 : prop_kinds[j] = ACC_PROP_COPY;
3747 4439 : prop_count++;
3748 4439 : prop_size += argacc->unit_size;
3749 4439 : change = true;
3750 : }
3751 : }
3752 :
3753 5039 : if (!change)
3754 : return NULL;
3755 :
3756 2936 : if ((prop_count + pclen
3757 2936 : > (unsigned) opt_for_fn (caller->decl, param_ipa_sra_max_replacements))
3758 8177 : || size_would_violate_limit_p (param_desc,
3759 2936 : param_desc->size_reached + prop_size))
3760 : return "propagating accesses would violate the count or size limit";
3761 :
3762 2917 : *change_p = true;
3763 7721 : for (unsigned j = 0; j < aclen; j++)
3764 : {
3765 4804 : if (prop_kinds[j] == ACC_PROP_COPY)
3766 : {
3767 4410 : param_access *argacc = (*arg_desc->accesses)[j];
3768 :
3769 4410 : param_access *copy = ggc_cleared_alloc<param_access> ();
3770 4410 : copy->unit_offset = argacc->unit_offset + delta_offset;
3771 4410 : copy->unit_size = argacc->unit_size;
3772 4410 : copy->type = argacc->type;
3773 4410 : copy->alias_ptr_type = argacc->alias_ptr_type;
3774 4410 : copy->certain = true;
3775 4410 : copy->reverse = argacc->reverse;
3776 4410 : 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 2917 : param_desc->size_reached += prop_size;
3789 :
3790 2917 : return NULL;
3791 5241 : }
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 1548131 : param_splitting_across_edge (cgraph_edge *cs)
3802 : {
3803 1548131 : bool res = false;
3804 1548131 : bool cross_scc = !ipa_edge_within_scc (cs);
3805 1548131 : enum availability availability;
3806 1548131 : cgraph_node *callee = cs->callee->function_symbol (&availability);
3807 1548131 : isra_func_summary *from_ifs = func_sums->get (cs->caller);
3808 1548131 : gcc_checking_assert (from_ifs && from_ifs->m_parameters);
3809 1548131 : ipcp_transformation *caller_ipcp_ts
3810 1548131 : = ipcp_get_transformation_summary (cs->caller);
3811 :
3812 1548131 : isra_call_summary *csum = call_sums->get (cs);
3813 1548131 : gcc_checking_assert (csum);
3814 1548131 : unsigned args_count = csum->m_arg_flow.length ();
3815 1548131 : isra_func_summary *to_ifs = func_sums->get (callee);
3816 1548131 : unsigned param_count
3817 805401 : = ((to_ifs && to_ifs->m_candidate && (availability >= AVAIL_AVAILABLE))
3818 2260498 : ? vec_safe_length (to_ifs->m_parameters)
3819 : : 0);
3820 :
3821 1548131 : 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 3017159 : for (i = 0; (i < args_count) && (i < param_count); i++)
3827 : {
3828 1469028 : isra_param_desc *arg_desc = &(*to_ifs->m_parameters)[i];
3829 1469028 : isra_param_flow *ipf = &csum->m_arg_flow[i];
3830 :
3831 1469028 : if (arg_desc->locally_unused)
3832 : {
3833 83742 : if (dump_file && (dump_flags & TDF_DETAILS))
3834 0 : fprintf (dump_file, " ->%u: unused in callee\n", i);
3835 83742 : ipf->pointer_pass_through = false;
3836 83742 : continue;
3837 : }
3838 :
3839 1385286 : if (ipf->pointer_pass_through)
3840 : {
3841 166114 : int idx = get_single_param_flow_source (ipf);
3842 166114 : isra_param_desc *param_desc = &(*from_ifs->m_parameters)[idx];
3843 166114 : if (!param_desc->split_candidate)
3844 118024 : continue;
3845 48090 : gcc_assert (param_desc->by_ref);
3846 :
3847 48090 : if (!arg_desc->split_candidate || !arg_desc->by_ref)
3848 : {
3849 42284 : 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 42284 : param_desc->split_candidate = false;
3853 42284 : ipf->pointer_pass_through = false;
3854 42284 : res = true;
3855 : }
3856 5806 : else if (!ipf->safe_to_import_accesses)
3857 : {
3858 1870 : if (!csum->m_before_any_store
3859 1870 : || !all_callee_accesses_present_p (param_desc, arg_desc))
3860 : {
3861 1846 : if (dump_file && (dump_flags & TDF_DETAILS))
3862 0 : fprintf (dump_file, " %u->%u: cannot import accesses.\n",
3863 : idx, i);
3864 1846 : param_desc->split_candidate = false;
3865 1846 : ipf->pointer_pass_through = false;
3866 1846 : 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 3936 : const char *pull_failure
3881 3936 : = pull_accesses_from_callee (cs->caller, caller_ipcp_ts, idx,
3882 : param_desc, arg_desc, 0, 0, &res);
3883 3936 : 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 3923 : if (dump_file && (dump_flags & TDF_DETAILS))
3895 1 : fprintf (dump_file, " %u->%u: by_ref access pull "
3896 : "succeeded.\n", idx, i);
3897 3923 : if (cross_scc)
3898 3848 : ipf->pointer_pass_through = false;
3899 : }
3900 : }
3901 : }
3902 1219172 : else if (ipf->aggregate_pass_through)
3903 : {
3904 33414 : int idx = get_single_param_flow_source (ipf);
3905 33414 : isra_param_desc *param_desc = &(*from_ifs->m_parameters)[idx];
3906 33414 : if (!param_desc->split_candidate)
3907 21874 : continue;
3908 11540 : gcc_assert (!param_desc->by_ref);
3909 23080 : param_access *pacc = find_param_access (param_desc, ipf->unit_offset,
3910 11540 : ipf->unit_size);
3911 11540 : gcc_checking_assert (pacc);
3912 :
3913 11540 : 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 11539 : else if (!arg_desc->split_candidate || arg_desc->by_ref)
3920 : {
3921 10234 : 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 10234 : pacc->certain = true;
3926 10234 : if (overlapping_certain_accesses_p (param_desc, NULL))
3927 : {
3928 1493 : if (dump_file && (dump_flags & TDF_DETAILS))
3929 0 : fprintf (dump_file, " ...leading to overlap, "
3930 : " disqualifying candidate parameter %u\n",
3931 : idx);
3932 1493 : param_desc->split_candidate = false;
3933 : }
3934 : else
3935 8741 : bump_reached_size (param_desc, pacc->unit_size, idx);
3936 :
3937 10234 : ipf->aggregate_pass_through = false;
3938 10234 : res = true;
3939 : }
3940 : else
3941 : {
3942 1305 : const char *pull_failure
3943 1305 : = 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 1305 : 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 1097 : if (dump_file && (dump_flags & TDF_DETAILS))
3972 0 : fprintf (dump_file, " %u->%u: arg access pull "
3973 : "succeeded.\n", idx, i);
3974 1097 : if (cross_scc)
3975 958 : ipf->aggregate_pass_through = false;
3976 : }
3977 : }
3978 : }
3979 : }
3980 :
3981 : /* Handle argument-parameter count mismatches. */
3982 2530794 : for (; (i < args_count); i++)
3983 : {
3984 982663 : isra_param_flow *ipf = &csum->m_arg_flow[i];
3985 :
3986 982663 : if (ipf->pointer_pass_through || ipf->aggregate_pass_through)
3987 : {
3988 199605 : int idx = get_single_param_flow_source (ipf);
3989 199605 : ipf->pointer_pass_through = false;
3990 199605 : ipf->aggregate_pass_through = false;
3991 199605 : isra_param_desc *param_desc = &(*from_ifs->m_parameters)[idx];
3992 199605 : if (!param_desc->split_candidate)
3993 199522 : 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 1548131 : 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 179562 : retval_used_p (cgraph_node *node, void *)
4012 : {
4013 267364 : for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
4014 : {
4015 235805 : isra_call_summary *csum = call_sums->get (cs);
4016 235805 : gcc_checking_assert (csum);
4017 235805 : if (csum->m_return_ignored)
4018 82110 : continue;
4019 153695 : if (!csum->m_return_returned)
4020 : return true;
4021 :
4022 27997 : isra_func_summary *from_ifs = func_sums->get (cs->caller);
4023 27997 : if (!from_ifs || !from_ifs->m_candidate)
4024 : return true;
4025 :
4026 21308 : if (!ipa_edge_within_scc (cs)
4027 21308 : && !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 304908 : 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 304908 : isra_param_desc *desc = &(*ifs->m_parameters)[base_index];
4050 304908 : if (desc->locally_unused)
4051 : {
4052 62153 : if (dump_file)
4053 27 : fprintf (dump_file, " Will remove parameter %u\n", base_index);
4054 62153 : return;
4055 : }
4056 :
4057 242755 : if (!desc->split_candidate)
4058 : {
4059 197729 : ipa_adjusted_param adj;
4060 197729 : if (prev_adjustment)
4061 : {
4062 1895 : adj = *prev_adjustment;
4063 1895 : adj.prev_clone_adjustment = true;
4064 1895 : adj.prev_clone_index = prev_clone_index;
4065 : }
4066 : else
4067 : {
4068 195834 : memset (&adj, 0, sizeof (adj));
4069 195834 : adj.op = IPA_PARAM_OP_COPY;
4070 195834 : adj.base_index = base_index;
4071 195834 : adj.prev_clone_index = prev_clone_index;
4072 : }
4073 197729 : vec_safe_push ((*new_params), adj);
4074 197729 : return;
4075 : }
4076 :
4077 45026 : if (dump_file)
4078 39 : fprintf (dump_file, " Will split parameter %u\n", base_index);
4079 :
4080 45026 : gcc_assert (!prev_adjustment || prev_adjustment->op == IPA_PARAM_OP_COPY);
4081 45026 : unsigned aclen = vec_safe_length (desc->accesses);
4082 126582 : for (unsigned j = 0; j < aclen; j++)
4083 : {
4084 81556 : param_access *pa = (*desc->accesses)[j];
4085 81556 : if (!pa->certain)
4086 7642 : continue;
4087 :
4088 80696 : if (ipcp_ts)
4089 : {
4090 14815 : ipa_argagg_value_list avl (ipcp_ts);
4091 14815 : tree value = avl.get_value (base_index, pa->unit_offset);
4092 14815 : if (value && !AGGREGATE_TYPE_P (pa->type))
4093 : {
4094 6782 : 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 6782 : continue;
4099 : }
4100 : }
4101 :
4102 73914 : 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 73914 : ipa_adjusted_param adj;
4107 73914 : memset (&adj, 0, sizeof (adj));
4108 73914 : adj.op = IPA_PARAM_OP_SPLIT;
4109 73914 : adj.base_index = base_index;
4110 73914 : adj.prev_clone_index = prev_clone_index;
4111 73914 : adj.param_prefix_index = IPA_PARAM_PREFIX_ISRA;
4112 73914 : adj.reverse = pa->reverse;
4113 73914 : adj.type = pa->type;
4114 73914 : adj.alias_ptr_type = pa->alias_ptr_type;
4115 73914 : adj.unit_offset = pa->unit_offset;
4116 73914 : 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 8402 : zap_useless_ipcp_results (const isra_func_summary *ifs, ipcp_transformation *ts)
4136 : {
4137 8402 : ts->remove_argaggs_if ([ifs](const ipa_argagg_value &v)
4138 : {
4139 15380 : return (*ifs->m_parameters)[v.index].locally_unused;
4140 : });
4141 :
4142 8402 : bool useful_vr = false;
4143 8402 : unsigned count = vec_safe_length (ts->m_vr);
4144 29825 : for (unsigned i = 0; i < count; i++)
4145 21423 : if ((*ts->m_vr)[i].known_p ())
4146 : {
4147 14882 : const isra_param_desc *desc = &(*ifs->m_parameters)[i];
4148 14882 : if (desc->locally_unused)
4149 1956 : (*ts->m_vr)[i].set_unknown ();
4150 : else
4151 : useful_vr = true;
4152 : }
4153 8402 : if (!useful_vr)
4154 1261 : ts->m_vr = NULL;
4155 8402 : }
4156 :
4157 : /* Do final processing of results of IPA propagation regarding NODE, clone it
4158 : if appropriate. */
4159 :
4160 : static void
4161 1261474 : process_isra_node_results (cgraph_node *node,
4162 : hash_map<const char *, unsigned> *clone_num_suffixes)
4163 : {
4164 1261474 : isra_func_summary *ifs = func_sums->get (node);
4165 1261474 : if (!ifs || !ifs->m_candidate)
4166 1153969 : return;
4167 :
4168 364363 : auto_vec<bool, 16> surviving_params;
4169 364363 : bool check_surviving = false;
4170 364363 : clone_info *cinfo = clone_info::get (node);
4171 364363 : if (cinfo && cinfo->param_adjustments)
4172 : {
4173 15407 : check_surviving = true;
4174 15407 : cinfo->param_adjustments->get_surviving_params (&surviving_params);
4175 : }
4176 :
4177 364363 : unsigned param_count = vec_safe_length (ifs->m_parameters);
4178 364363 : bool will_change_function = false;
4179 364363 : if (ifs->m_returns_value && ifs->m_return_ignored)
4180 : will_change_function = true;
4181 : else
4182 850312 : for (unsigned i = 0; i < param_count; i++)
4183 : {
4184 593454 : isra_param_desc *desc = &(*ifs->m_parameters)[i];
4185 541310 : 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 625977 : && (!check_surviving
4189 519581 : || (i < surviving_params.length ()
4190 2594 : && surviving_params[i])))
4191 : {
4192 : will_change_function = true;
4193 : break;
4194 : }
4195 : }
4196 333325 : if (!will_change_function)
4197 256858 : return;
4198 :
4199 107505 : 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 107505 : ipcp_transformation *ipcp_ts = ipcp_get_transformation_summary (node);
4208 107505 : if (ipcp_ts)
4209 8402 : zap_useless_ipcp_results (ifs, ipcp_ts);
4210 107505 : vec<ipa_adjusted_param, va_gc> *new_params = NULL;
4211 107505 : if (ipa_param_adjustments *old_adjustments
4212 107505 : = cinfo ? cinfo->param_adjustments : NULL)
4213 : {
4214 2618 : unsigned old_adj_len = vec_safe_length (old_adjustments->m_adj_params);
4215 6401 : for (unsigned i = 0; i < old_adj_len; i++)
4216 : {
4217 3783 : ipa_adjusted_param *old_adj = &(*old_adjustments->m_adj_params)[i];
4218 3783 : push_param_adjustments_for_index (ifs, old_adj->base_index, i,
4219 : old_adj, ipcp_ts, &new_params);
4220 : }
4221 : }
4222 : else
4223 406012 : for (unsigned i = 0; i < param_count; i++)
4224 301125 : push_param_adjustments_for_index (ifs, i, i, NULL, ipcp_ts, &new_params);
4225 :
4226 107505 : ipa_param_adjustments *new_adjustments
4227 107505 : = (new (ggc_alloc <ipa_param_adjustments> ())
4228 : ipa_param_adjustments (new_params, param_count,
4229 183972 : ifs->m_returns_value && ifs->m_return_ignored));
4230 :
4231 107505 : 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 322515 : unsigned &suffix_counter = clone_num_suffixes->get_or_insert (
4238 107505 : IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (
4239 : node->decl)));
4240 107505 : auto_vec<cgraph_edge *> callers = node->collect_callers ();
4241 107505 : cgraph_node *new_node
4242 107505 : = node->create_virtual_clone (callers, NULL, new_adjustments, "isra",
4243 : suffix_counter);
4244 107505 : suffix_counter++;
4245 107505 : 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 107505 : new_node->calls_comdat_local = node->calls_comdat_local;
4252 :
4253 107505 : if (dump_file)
4254 61 : fprintf (dump_file, " Created new node %s\n", new_node->dump_name ());
4255 107505 : callers.release ();
4256 364363 : }
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 622366 : dump_list_of_param_indices (const cgraph_node *node, const char* msg,
4263 : const vec<unsigned> &indices)
4264 : {
4265 622366 : 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 364363 : adjust_parameter_descriptions (cgraph_node *node, isra_func_summary *ifs)
4283 : {
4284 364363 : bool ret = true;
4285 364363 : unsigned len = vec_safe_length (ifs->m_parameters);
4286 311183 : if (!len)
4287 : return true;
4288 :
4289 311183 : auto_vec<bool, 16> surviving_params;
4290 311183 : bool check_surviving = false;
4291 311183 : clone_info *cinfo = clone_info::get (node);
4292 311183 : if (cinfo && cinfo->param_adjustments)
4293 : {
4294 15407 : check_surviving = true;
4295 15407 : cinfo->param_adjustments->get_surviving_params (&surviving_params);
4296 : }
4297 311183 : ipcp_transformation *ipcp_ts = ipcp_get_transformation_summary (node);
4298 311183 : auto_vec <unsigned> dump_dead_indices;
4299 311183 : auto_vec <unsigned> dump_bad_cond_indices;
4300 1066539 : for (unsigned i = 0; i < len; i++)
4301 : {
4302 755356 : isra_param_desc *desc = &(*ifs->m_parameters)[i];
4303 755356 : 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 755356 : if (desc->split_only_when_retval_removed
4311 6735 : && !ifs->m_return_ignored)
4312 : {
4313 0 : if (dump_file && (dump_flags & TDF_DETAILS)
4314 1536 : && (desc->locally_unused || desc->split_candidate))
4315 0 : dump_bad_cond_indices.safe_push (i);
4316 :
4317 1536 : gcc_checking_assert (!desc->locally_unused
4318 : || desc->remove_only_when_retval_removed);
4319 1536 : desc->locally_unused = false;
4320 1536 : desc->split_candidate = false;
4321 1536 : continue;
4322 : }
4323 753820 : if (desc->remove_only_when_retval_removed
4324 42622 : && !ifs->m_return_ignored)
4325 : {
4326 6 : if (dump_file && (dump_flags & TDF_DETAILS)
4327 33612 : && (desc->locally_unused || desc->split_candidate))
4328 0 : dump_bad_cond_indices.safe_push (i);
4329 :
4330 33612 : desc->locally_unused = false;
4331 : }
4332 753820 : if (check_surviving
4333 798689 : && (i >= surviving_params.length ()
4334 21040 : || !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 28387 : desc->split_candidate = false;
4340 :
4341 28387 : if (dump_file && (dump_flags & TDF_DETAILS))
4342 0 : dump_dead_indices.safe_push (i);
4343 : }
4344 :
4345 753820 : if (desc->split_candidate && desc->conditionally_dereferenceable)
4346 : {
4347 893 : gcc_assert (desc->safe_size_set);
4348 1518 : for (param_access *pa : *desc->accesses)
4349 1355 : if ((pa->unit_offset + pa->unit_size) > desc->safe_size)
4350 : {
4351 730 : if (dump_file && (dump_flags & TDF_DETAILS))
4352 1 : dump_bad_cond_indices.safe_push (i);
4353 730 : desc->split_candidate = false;
4354 730 : break;
4355 : }
4356 : }
4357 :
4358 753820 : if (desc->split_candidate)
4359 : {
4360 193960 : if (desc->by_ref && !desc->not_specially_constructed)
4361 : {
4362 28693 : int extra_factor
4363 28693 : = opt_for_fn (node->decl,
4364 : param_ipa_sra_ptrwrap_growth_factor);
4365 28693 : desc->param_size_limit = extra_factor * desc->param_size_limit;
4366 : }
4367 193960 : if (size_would_violate_limit_p (desc, desc->size_reached))
4368 3268 : 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 753820 : if (ipcp_ts && desc->split_candidate)
4375 : {
4376 22268 : ipa_argagg_value_list avl (ipcp_ts);
4377 55255 : for (const param_access *pa : desc->accesses)
4378 : {
4379 16422 : if (!pa->certain)
4380 1009 : continue;
4381 15413 : tree value = avl.get_value (i, pa->unit_offset);
4382 15413 : if (value
4383 15413 : && ((tree_to_uhwi (TYPE_SIZE (TREE_TYPE (value)))
4384 6885 : / BITS_PER_UNIT)
4385 6885 : != 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 753820 : if (desc->locally_unused || desc->split_candidate)
4396 755356 : ret = false;
4397 : }
4398 :
4399 311183 : dump_list_of_param_indices (node, "are dead on arrival or have a type "
4400 : "mismatch with IPA-CP", dump_dead_indices);
4401 311183 : dump_list_of_param_indices (node, "fail additional requirements ",
4402 : dump_bad_cond_indices);
4403 :
4404 311183 : return ret;
4405 311183 : }
4406 :
4407 :
4408 : /* Run the interprocedural part of IPA-SRA. */
4409 :
4410 : static unsigned int
4411 125721 : ipa_sra_analysis (void)
4412 : {
4413 125721 : 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 125721 : gcc_checking_assert (func_sums);
4420 125721 : gcc_checking_assert (call_sums);
4421 125721 : cgraph_node **order = XCNEWVEC (cgraph_node *, symtab->cgraph_count);
4422 125721 : auto_vec <cgraph_node *, 16> stack;
4423 125721 : int node_scc_count = ipa_reduced_postorder (order, true, NULL);
4424 :
4425 : /* One sweep from callers to callees for return value removal. */
4426 1455101 : for (int i = node_scc_count - 1; i >= 0 ; i--)
4427 : {
4428 1329380 : cgraph_node *scc_rep = order[i];
4429 1329380 : vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (scc_rep);
4430 :
4431 : /* Preliminary IPA function level checks. */
4432 5323237 : for (cgraph_node *v : cycle_nodes)
4433 : {
4434 1335097 : isra_func_summary *ifs = func_sums->get (v);
4435 1335097 : if (!ifs || !ifs->m_candidate)
4436 315224 : continue;
4437 1019873 : if (!ipa_sra_ipa_function_checks (v)
4438 1019873 : || check_all_callers_for_issues (v))
4439 655510 : ifs->zap ();
4440 : }
4441 :
4442 3993857 : for (cgraph_node *v : cycle_nodes)
4443 : {
4444 1335097 : isra_func_summary *ifs = func_sums->get (v);
4445 1335097 : if (!ifs || !ifs->m_candidate)
4446 970734 : continue;
4447 364363 : bool return_needed
4448 364363 : = (ifs->m_returns_value
4449 364363 : && (!dbg_cnt (ipa_sra_retvalues)
4450 179545 : || v->call_for_symbol_and_aliases (retval_used_p,
4451 364363 : NULL, true)));
4452 364363 : ifs->m_return_ignored = !return_needed;
4453 364363 : if (return_needed)
4454 296006 : isra_push_node_to_stack (v, ifs, &stack);
4455 : }
4456 :
4457 1477887 : while (!stack.is_empty ())
4458 : {
4459 148507 : cgraph_node *node = stack.pop ();
4460 148507 : isra_func_summary *ifs = func_sums->get (node);
4461 148507 : gcc_checking_assert (ifs && ifs->m_queued);
4462 148507 : ifs->m_queued = false;
4463 :
4464 843338 : for (cgraph_edge *cs = node->callees; cs; cs = cs->next_callee)
4465 694831 : if (ipa_edge_within_scc (cs)
4466 694831 : && call_sums->get (cs)->m_return_returned)
4467 : {
4468 1120 : enum availability av;
4469 1120 : cgraph_node *callee = cs->callee->function_symbol (&av);
4470 1120 : isra_func_summary *to_ifs = func_sums->get (callee);
4471 1120 : if (to_ifs && to_ifs->m_return_ignored)
4472 : {
4473 504 : to_ifs->m_return_ignored = false;
4474 1008 : isra_push_node_to_stack (callee, to_ifs, &stack);
4475 : }
4476 : }
4477 : }
4478 :
4479 : /* Parameter hint propagation. */
4480 3993857 : for (cgraph_node *v : cycle_nodes)
4481 : {
4482 1335097 : isra_func_summary *ifs = func_sums->get (v);
4483 1335097 : propagate_hints_to_all_callees (v, ifs, &stack);
4484 : }
4485 :
4486 1331866 : while (!stack.is_empty ())
4487 : {
4488 2486 : cgraph_node *node = stack.pop ();
4489 2486 : isra_func_summary *ifs = func_sums->get (node);
4490 2486 : gcc_checking_assert (ifs && ifs->m_queued);
4491 2486 : ifs->m_queued = false;
4492 2486 : propagate_hints_to_all_callees (node, ifs, &stack);
4493 : }
4494 :
4495 1329380 : cycle_nodes.release ();
4496 : }
4497 :
4498 : /* One sweep from callees to callers for parameter removal and splitting. */
4499 1455101 : for (int i = 0; i < node_scc_count; i++)
4500 : {
4501 1329380 : cgraph_node *scc_rep = order[i];
4502 1329380 : vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (scc_rep);
4503 :
4504 : /* First step of parameter removal. */
4505 5323237 : for (cgraph_node *v : cycle_nodes)
4506 : {
4507 1335097 : isra_func_summary *ifs = func_sums->get (v);
4508 1335097 : if (!ifs || !ifs->m_candidate)
4509 970734 : continue;
4510 364363 : if (adjust_parameter_descriptions (v, ifs))
4511 191760 : continue;
4512 187142 : for (cgraph_edge *cs = v->indirect_calls; cs; cs = cs->next_callee)
4513 14539 : process_edge_to_unknown_caller (cs);
4514 1000383 : for (cgraph_edge *cs = v->callees; cs; cs = cs->next_callee)
4515 827780 : if (!ipa_edge_within_scc (cs))
4516 822513 : 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 3993857 : for (cgraph_node *v : cycle_nodes)
4523 1335097 : 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 1330138 : 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 1374313 : bool repeat_scc_access_propagation;
4540 1374313 : do
4541 : {
4542 1374313 : repeat_scc_access_propagation = false;
4543 4131351 : for (cgraph_node *v : cycle_nodes)
4544 : {
4545 1382725 : isra_func_summary *ifs = func_sums->get (v);
4546 2407267 : if (!ifs
4547 1070493 : || !ifs->m_candidate
4548 1794088 : || vec_safe_is_empty (ifs->m_parameters))
4549 1024542 : continue;
4550 1906314 : for (cgraph_edge *cs = v->callees; cs; cs = cs->next_callee)
4551 1548131 : if (param_splitting_across_edge (cs))
4552 48124 : repeat_scc_access_propagation = true;
4553 : }
4554 : }
4555 : while (repeat_scc_access_propagation);
4556 :
4557 1329380 : if (flag_checking)
4558 3993806 : for (cgraph_node *v : cycle_nodes)
4559 1335080 : verify_splitting_accesses (v, true);
4560 :
4561 1329380 : cycle_nodes.release ();
4562 : }
4563 :
4564 125721 : ipa_free_postorder_info ();
4565 125721 : free (order);
4566 :
4567 125721 : 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 125721 : hash_map<const char *, unsigned> *clone_num_suffixes
4579 125721 : = new hash_map<const char *, unsigned>;
4580 :
4581 125721 : cgraph_node *node;
4582 1387195 : FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
4583 1261474 : process_isra_node_results (node, clone_num_suffixes);
4584 :
4585 125721 : delete clone_num_suffixes;
4586 125721 : ggc_delete (func_sums);
4587 125721 : func_sums = NULL;
4588 125721 : delete call_sums;
4589 125721 : call_sums = NULL;
4590 :
4591 125721 : if (dump_file)
4592 54 : fprintf (dump_file, "\n========== IPA SRA IPA analysis done "
4593 : "==========\n\n");
4594 125721 : return 0;
4595 125721 : }
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 287872 : 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 287872 : NULL) /* variable_transform */
4625 287872 : {}
4626 :
4627 : /* opt_pass methods: */
4628 591225 : 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 591225 : return (flag_ipa_sra && optimize);
4633 : }
4634 :
4635 125721 : unsigned int execute (function *) final override
4636 : {
4637 125721 : 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 1258180 : ipa_sra_summarize_function (cgraph_node *node)
4650 : {
4651 1258180 : if (dump_file)
4652 187 : fprintf (dump_file, "Creating summary for %s/%i:\n", node->name (),
4653 : node->get_uid ());
4654 1258180 : gcc_obstack_init (&gensum_obstack);
4655 1258180 : loaded_decls = new hash_set<tree>;
4656 :
4657 1258180 : isra_func_summary *ifs = NULL;
4658 1258180 : unsigned count = 0;
4659 1258180 : if (ipa_sra_preliminary_function_checks (node))
4660 : {
4661 1023645 : ifs = func_sums->get_create (node);
4662 1023645 : ifs->m_candidate = true;
4663 1023645 : tree ret = TREE_TYPE (TREE_TYPE (node->decl));
4664 1023645 : ifs->m_returns_value = (TREE_CODE (ret) != VOID_TYPE);
4665 1023645 : for (tree parm = DECL_ARGUMENTS (node->decl);
4666 3398274 : parm;
4667 2374629 : parm = DECL_CHAIN (parm))
4668 2374629 : count++;
4669 : }
4670 1258180 : auto_vec<gensum_param_desc, 16> param_descriptions (count);
4671 :
4672 1258180 : struct function *fun = DECL_STRUCT_FUNCTION (node->decl);
4673 1258180 : bool cfun_pushed = false;
4674 1258180 : if (count > 0)
4675 : {
4676 830098 : decl2desc = new hash_map<tree, gensum_param_desc *>;
4677 830098 : param_descriptions.reserve_exact (count);
4678 830098 : param_descriptions.quick_grow_cleared (count);
4679 :
4680 830098 : if (create_parameter_descriptors (node, ¶m_descriptions))
4681 : {
4682 409350 : push_cfun (fun);
4683 409350 : cfun_pushed = true;
4684 409350 : final_bbs = BITMAP_ALLOC (NULL);
4685 409350 : bb_dereferences = XCNEWVEC (HOST_WIDE_INT,
4686 : unsafe_by_ref_count
4687 : * last_basic_block_for_fn (fun));
4688 409350 : 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 1258180 : scan_function (node, fun);
4695 :
4696 1258180 : if (count > 0)
4697 : {
4698 830098 : 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 830098 : process_scan_results (node, fun, ifs, ¶m_descriptions);
4706 :
4707 830098 : if (cfun_pushed)
4708 409350 : pop_cfun ();
4709 830098 : if (bb_dereferences)
4710 : {
4711 409350 : free (bb_dereferences);
4712 409350 : bb_dereferences = NULL;
4713 409350 : BITMAP_FREE (final_bbs);
4714 409350 : final_bbs = NULL;
4715 : }
4716 : }
4717 1258180 : isra_analyze_all_outgoing_calls (node);
4718 :
4719 2516360 : delete loaded_decls;
4720 1258180 : loaded_decls = NULL;
4721 1258180 : if (decl2desc)
4722 : {
4723 830098 : delete decl2desc;
4724 830098 : decl2desc = NULL;
4725 : }
4726 1258180 : obstack_free (&gensum_obstack, NULL);
4727 1258180 : if (dump_file)
4728 187 : fprintf (dump_file, "\n\n");
4729 1258180 : if (flag_checking)
4730 1258162 : verify_splitting_accesses (node, false);
4731 1258180 : return;
4732 1258180 : }
4733 :
4734 : ipa_opt_pass_d *
4735 287872 : make_pass_ipa_sra (gcc::context *ctxt)
4736 : {
4737 287872 : 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 258766 : ipa_sra_cc_finalize (void)
4745 : {
4746 258766 : if (func_sums)
4747 9020 : ggc_delete (func_sums);
4748 258766 : func_sums = NULL;
4749 258766 : delete call_sums;
4750 258766 : call_sums = NULL;
4751 258766 : }
4752 :
4753 : #include "gt-ipa-sra.h"
|