]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/ipa-sra.c
tree-ssa-sccvn.c (vn_reference_lookup_3): Valueize MEM_REF base.
[thirdparty/gcc.git] / gcc / ipa-sra.c
CommitLineData
ff6686d2
MJ
1/* Interprocedural scalar replacement of aggregates
2 Copyright (C) 2008-2019 Free Software Foundation, Inc.
3
4 Contributed by Martin Jambor <mjambor@suse.cz>
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 3, or (at your option) any later
11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
21
22/* IPA-SRA is an interprocedural pass that removes unused function return
23 values (turning functions returning a value which is never used into void
24 functions), removes unused function parameters. It can also replace an
25 aggregate parameter by a set of other parameters representing part of the
26 original, turning those passed by reference into new ones which pass the
27 value directly.
28
29 The pass is a true IPA one, which means that it works in three stages in
30 order to be able to take advantage of LTO. First, summaries about functions
31 and each calls are generated. Function summaries (often called call graph
32 node summaries) contain mainly information about which parameters are
33 potential transformation candidates and which bits of candidates are
34 accessed. We differentiate between accesses done as a part of a call
35 statement (which might be not necessary if the callee is also transformed)
36 and others (which are mandatory). Call summaries (often called call graph
37 edge summaries) contain information about which function formal parameters
38 feed into which actual call arguments so that if two parameters are only
39 used in a sum which is then passed to another function which then however
40 does not use this parameter, all three parameters of the two functions can
41 be eliminated. Edge summaries also have flags whether the return value is
42 used or if it is only returned in the caller too. In LTO mode these
43 summaries are then streamed to the object file in the compilation phase and
44 streamed back in in the WPA analysis stage.
45
46 The interprocedural analysis phase traverses the graph in topological order
47 in two sweeps, one in each direction. First, from callees to callers for
48 parameter removal and splitting. Each strongly-connected component is
49 processed iteratively until the situation in it stabilizes. The pass from
50 callers to callees is then carried out to remove unused return values in a
51 very similar fashion.
52
53 Because parameter manipulation has big implications for call redirection
54 which is done only after all call graph nodes materialize, the
55 transformation phase is not part of this patch but is carried out by the
56 clone materialization and edge redirection itself, see comments in
57 ipa-param-manipulation.h for more details. */
58
59
60
61#include "config.h"
62#include "system.h"
63#include "coretypes.h"
64#include "backend.h"
65#include "tree.h"
66#include "gimple.h"
67#include "predict.h"
68#include "tree-pass.h"
69#include "ssa.h"
70#include "cgraph.h"
71#include "gimple-pretty-print.h"
72#include "alias.h"
73#include "tree-eh.h"
74#include "gimple-iterator.h"
75#include "gimple-walk.h"
76#include "tree-dfa.h"
77#include "tree-sra.h"
78#include "symbol-summary.h"
79#include "params.h"
80#include "dbgcnt.h"
81#include "tree-inline.h"
82#include "ipa-utils.h"
83#include "builtins.h"
84#include "cfganal.h"
85#include "tree-streamer.h"
86
87
88/* Bits used to track size of an aggregate in bytes interprocedurally. */
89#define ISRA_ARG_SIZE_LIMIT_BITS 16
90#define ISRA_ARG_SIZE_LIMIT (1 << ISRA_ARG_SIZE_LIMIT_BITS)
91/* How many parameters can feed into a call actual argument and still be
92 tracked. */
93#define IPA_SRA_MAX_PARAM_FLOW_LEN 7
94
95/* Structure describing accesses to a specific portion of an aggregate
96 parameter, as given by the offset and size. Any smaller accesses that occur
97 within a function that fall within another access form a tree. The pass
98 cannot analyze parameters with only partially overlapping accesses. */
99
100struct GTY(()) param_access
101{
102 /* Type that a potential replacement should have. This field only has
103 meaning in the summary building and transformation phases, when it is
104 reconstructoed from the body. Must not be touched in IPA analysys
105 stage. */
106 tree type;
107
108 /* Alias reference type to be used in MEM_REFs when adjusting caller
109 arguments. */
110 tree alias_ptr_type;
111
112 /* Values returned by get_ref_base_and_extent but converted to bytes and
113 stored as unsigned ints. */
114 unsigned unit_offset;
115 unsigned unit_size : ISRA_ARG_SIZE_LIMIT_BITS;
116
117 /* Set once we are sure that the access will really end up in a potentially
118 transformed function - initially not set for portions of formal parameters
119 that are only used as actual function arguments passed to callees. */
120 unsigned certain : 1;
121 /* Set if the access has a reversed scalar storage order. */
122 unsigned reverse : 1;
123};
124
125/* This structure has the same purpose as the one above and additoonally it
126 contains some fields that are only necessary in the summary generation
127 phase. */
128
129struct gensum_param_access
130{
131 /* Values returned by get_ref_base_and_extent. */
132 HOST_WIDE_INT offset;
133 HOST_WIDE_INT size;
134
135 /* if this access has any children (in terms of the definition above), this
136 points to the first one. */
137 struct gensum_param_access *first_child;
138 /* In intraprocedural SRA, pointer to the next sibling in the access tree as
139 described above. */
140 struct gensum_param_access *next_sibling;
141
142 /* Type that a potential replacement should have. This field only has
143 meaning in the summary building and transformation phases, when it is
144 reconstructoed from the body. Must not be touched in IPA analysys
145 stage. */
146 tree type;
147 /* Alias refrerence type to be used in MEM_REFs when adjusting caller
148 arguments. */
149 tree alias_ptr_type;
150
151 /* Have there been writes to or reads from this exact location except for as
152 arguments to a function call that can be tracked. */
153 bool nonarg;
154
155 /* Set if the access has a reversed scalar storage order. */
156 bool reverse;
157};
158
159/* Summary describing a parameter in the IPA stages. */
160
161struct GTY(()) isra_param_desc
162{
163 /* List of access representatives to the parameters, sorted according to
164 their offset. */
165 vec <param_access *, va_gc> *accesses;
166
167 /* Unit size limit of total size of all replacements. */
168 unsigned param_size_limit : ISRA_ARG_SIZE_LIMIT_BITS;
169 /* Sum of unit sizes of all certain replacements. */
170 unsigned size_reached : ISRA_ARG_SIZE_LIMIT_BITS;
171
172 /* A parameter that is used only in call arguments and can be removed if all
173 concerned actual arguments are removed. */
174 unsigned locally_unused : 1;
175 /* An aggregate that is a candidate for breaking up or complete removal. */
176 unsigned split_candidate : 1;
177 /* Is this a parameter passing stuff by reference? */
178 unsigned by_ref : 1;
179};
180
181/* Structure used when generating summaries that describes a parameter. */
182
183struct gensum_param_desc
184{
185 /* Roots of param_accesses. */
186 gensum_param_access *accesses;
187 /* Number of accesses in the access tree rooted in field accesses. */
188 unsigned access_count;
189
190 /* If the below is non-zero, this is the nuber of uses as actual arguents. */
191 int call_uses;
192 /* Number of times this parameter has been directly passed to. */
193 unsigned ptr_pt_count;
194
195 /* Size limit of total size of all replacements. */
196 unsigned param_size_limit;
197 /* Sum of sizes of nonarg accesses. */
198 unsigned nonarg_acc_size;
199
200 /* A parameter that is used only in call arguments and can be removed if all
201 concerned actual arguments are removed. */
202 bool locally_unused;
203 /* An aggregate that is a candidate for breaking up or a pointer passing data
204 by reference that is a candidate for being converted to a set of
205 parameters passing thosa data by value. */
206 bool split_candidate;
207 /* Is this a parameter passing stuff by reference? */
208 bool by_ref;
209
210 /* The number of this parameter as they are ordered in function decl. */
211 int param_number;
212 /* For parameters passing data by reference, this is parameter index to
213 compute indices to bb_dereferences. */
214 int deref_index;
215};
216
217/* Properly deallocate accesses of DESC. TODO: Since this data strucutre is
218 not in GC memory, this is not necessary and we can consider removing the
219 function. */
220
221static void
222free_param_decl_accesses (isra_param_desc *desc)
223{
224 unsigned len = vec_safe_length (desc->accesses);
225 for (unsigned i = 0; i < len; ++i)
226 ggc_free ((*desc->accesses)[i]);
227 vec_free (desc->accesses);
228}
229
230/* Class used to convey information about functions from the
231 intra-procedurwl analysis stage to inter-procedural one. */
232
233class GTY((for_user)) isra_func_summary
234{
235public:
236 /* initialize the object. */
237
238 isra_func_summary ()
239 : m_parameters (NULL), m_candidate (false), m_returns_value (false),
240 m_return_ignored (false), m_queued (false)
241 {}
242
243 /* Destroy m_parameters. */
244
245 ~isra_func_summary ();
246
247 /* Mark the function as not a candidate for any IPA-SRA transofrmation.
248 Return true if it was a candidate until now. */
249
250 bool zap ();
251
252 /* Vector of parameter descriptors corresponding to the function being
253 analyzed. */
254 vec<isra_param_desc, va_gc> *m_parameters;
255
256 /* Whether the node is even a candidate for any IPA-SRA transformation at
257 all. */
258 unsigned m_candidate : 1;
259
260 /* Whether the original function returns any value. */
261 unsigned m_returns_value : 1;
262
263 /* Set to true if all call statements do not actually use the returned
264 value. */
265
266 unsigned m_return_ignored : 1;
267
268 /* Whether the node is already queued in IPA SRA stack during processing of
269 call graphs SCCs. */
270
271 unsigned m_queued : 1;
272};
273
274/* Claen up and deallocate isra_func_summary points to. TODO: Since this data
275 strucutre is not in GC memory, this is not necessary and we can consider
276 removing the destructor. */
277
278isra_func_summary::~isra_func_summary ()
279{
280 unsigned len = vec_safe_length (m_parameters);
281 for (unsigned i = 0; i < len; ++i)
282 free_param_decl_accesses (&(*m_parameters)[i]);
283 vec_free (m_parameters);
284}
285
286
287/* Mark the function as not a candidate for any IPA-SRA transofrmation. Return
288 true if it was a candidate until now. */
289
290bool
291isra_func_summary::zap ()
292{
293 bool ret = m_candidate;
294 m_candidate = false;
295
296 unsigned len = vec_safe_length (m_parameters);
297 for (unsigned i = 0; i < len; ++i)
298 free_param_decl_accesses (&(*m_parameters)[i]);
299 vec_free (m_parameters);
300
301 return ret;
302}
303
304/* Structure to describe which formal parameters feed into a particular actual
305 arguments. */
306
307struct isra_param_flow
308{
309 /* Number of elements in array inputs that contain valid data. */
310 char length;
311 /* Indices of formal parameters that feed into the described actual argument.
312 If aggregate_pass_through or pointer_pass_through below are true, it must
313 contain exactly one element which is passed through from a formal
314 parameter if the given number. Otherwise, the array contains indices of
315 collee's formal parameters which are used to calculate value of this
316 actual argument. */
317 unsigned char inputs[IPA_SRA_MAX_PARAM_FLOW_LEN];
318
319 /* Offset within the formal parameter. */
320 unsigned unit_offset;
321 /* Size of the portion of the formal parameter that is being passed. */
322 unsigned unit_size : ISRA_ARG_SIZE_LIMIT_BITS;
323
324 /* True when the value of this actual copy is a portion of a formal
325 parameter. */
326 unsigned aggregate_pass_through : 1;
327 /* True when the value of this actual copy is a verbatim pass through of an
328 obtained pointer. */
329 unsigned pointer_pass_through : 1;
330 /* True when it is safe to copy access candidates here from the callee, which
331 would mean introducing dereferences into callers of the caller. */
332 unsigned safe_to_import_accesses : 1;
333};
334
335/* Strucutre used to convey information about calls from the intra-procedurwl
336 analysis stage to inter-procedural one. */
337
338class isra_call_summary
339{
340public:
341 isra_call_summary ()
342 : m_arg_flow (), m_return_ignored (false), m_return_returned (false),
343 m_bit_aligned_arg (false)
344 {}
345
346 void init_inputs (unsigned arg_count);
347 void dump (FILE *f);
348
349 /* Information about what formal parameters of the caller are used to compute
350 indivisual actual arguments of this call. */
351 auto_vec <isra_param_flow> m_arg_flow;
352
353 /* Set to true if the call statement does not have a LHS. */
354 unsigned m_return_ignored : 1;
355
356 /* Set to true if the LHS of call statement is only used to construct the
357 return value of the caller. */
358 unsigned m_return_returned : 1;
359
360 /* Set when any of the call arguments are not byte-aligned. */
361 unsigned m_bit_aligned_arg : 1;
362};
363
364/* Class to manage function summaries. */
365
366class GTY((user)) ipa_sra_function_summaries
367 : public function_summary <isra_func_summary *>
368{
369public:
370 ipa_sra_function_summaries (symbol_table *table, bool ggc):
371 function_summary<isra_func_summary *> (table, ggc) { }
372
373 virtual void duplicate (cgraph_node *, cgraph_node *,
374 isra_func_summary *old_sum,
375 isra_func_summary *new_sum);
376};
377
378/* Hook that is called by summary when a node is duplicated. */
379
380void
381ipa_sra_function_summaries::duplicate (cgraph_node *, cgraph_node *,
382 isra_func_summary *old_sum,
383 isra_func_summary *new_sum)
384{
385 /* TODO: Somehow stop copying when ISRA is doing the cloning, it is
386 useless. */
387 new_sum->m_candidate = old_sum->m_candidate;
388 new_sum->m_returns_value = old_sum->m_returns_value;
389 new_sum->m_return_ignored = old_sum->m_return_ignored;
390 gcc_assert (!old_sum->m_queued);
391 new_sum->m_queued = false;
392
393 unsigned param_count = vec_safe_length (old_sum->m_parameters);
394 if (!param_count)
395 return;
396 vec_safe_reserve_exact (new_sum->m_parameters, param_count);
397 new_sum->m_parameters->quick_grow_cleared (param_count);
398 for (unsigned i = 0; i < param_count; i++)
399 {
400 isra_param_desc *s = &(*old_sum->m_parameters)[i];
401 isra_param_desc *d = &(*new_sum->m_parameters)[i];
402
403 d->param_size_limit = s->param_size_limit;
404 d->size_reached = s->size_reached;
405 d->locally_unused = s->locally_unused;
406 d->split_candidate = s->split_candidate;
407 d->by_ref = s->by_ref;
408
409 unsigned acc_count = vec_safe_length (s->accesses);
410 vec_safe_reserve_exact (d->accesses, acc_count);
411 for (unsigned j = 0; j < acc_count; j++)
412 {
413 param_access *from = (*s->accesses)[j];
414 param_access *to = ggc_cleared_alloc<param_access> ();
415 to->type = from->type;
416 to->alias_ptr_type = from->alias_ptr_type;
417 to->unit_offset = from->unit_offset;
418 to->unit_size = from->unit_size;
419 to->certain = from->certain;
420 d->accesses->quick_push (to);
421 }
422 }
423}
424
425/* Pointer to the pass function summary holder. */
426
427static GTY(()) ipa_sra_function_summaries *func_sums;
428
429/* Class to manage call summaries. */
430
431class ipa_sra_call_summaries: public call_summary <isra_call_summary *>
432{
433public:
434 ipa_sra_call_summaries (symbol_table *table):
435 call_summary<isra_call_summary *> (table) { }
436
437 /* Duplicate info when an edge is cloned. */
438 virtual void duplicate (cgraph_edge *, cgraph_edge *,
439 isra_call_summary *old_sum,
440 isra_call_summary *new_sum);
441};
442
443static ipa_sra_call_summaries *call_sums;
444
445
446/* Initialize m_arg_flow of a particular instance of isra_call_summary.
447 ARG_COUNT is the number of actual arguments passed. */
448
449void
450isra_call_summary::init_inputs (unsigned arg_count)
451{
452 if (arg_count == 0)
453 {
454 gcc_checking_assert (m_arg_flow.length () == 0);
455 return;
456 }
457 if (m_arg_flow.length () == 0)
458 {
459 m_arg_flow.reserve_exact (arg_count);
460 m_arg_flow.quick_grow_cleared (arg_count);
461 }
462 else
463 gcc_checking_assert (arg_count == m_arg_flow.length ());
464}
465
466/* Dump all information in call summary to F. */
467
468void
469isra_call_summary::dump (FILE *f)
470{
471 if (m_return_ignored)
472 fprintf (f, " return value ignored\n");
473 if (m_return_returned)
474 fprintf (f, " return value used only to compute caller return value\n");
475 for (unsigned i = 0; i < m_arg_flow.length (); i++)
476 {
477 fprintf (f, " Parameter %u:\n", i);
478 isra_param_flow *ipf = &m_arg_flow[i];
479
480 if (ipf->length)
481 {
482 bool first = true;
483 fprintf (f, " Scalar param sources: ");
484 for (int j = 0; j < ipf->length; j++)
485 {
486 if (!first)
487 fprintf (f, ", ");
488 else
489 first = false;
490 fprintf (f, "%i", (int) ipf->inputs[j]);
491 }
492 fprintf (f, "\n");
493 }
494 if (ipf->aggregate_pass_through)
495 fprintf (f, " Aggregate pass through from the param given above, "
496 "unit offset: %u , unit size: %u\n",
497 ipf->unit_offset, ipf->unit_size);
498 if (ipf->pointer_pass_through)
499 fprintf (f, " Pointer pass through from the param given above, "
500 "safe_to_import_accesses: %u\n", ipf->safe_to_import_accesses);
501 }
502}
503
504/* Duplicate edge summare when an edge is cloned. */
505
506void
507ipa_sra_call_summaries::duplicate (cgraph_edge *, cgraph_edge *,
508 isra_call_summary *old_sum,
509 isra_call_summary *new_sum)
510{
511 unsigned arg_count = old_sum->m_arg_flow.length ();
512 new_sum->init_inputs (arg_count);
513 for (unsigned i = 0; i < arg_count; i++)
514 new_sum->m_arg_flow[i] = old_sum->m_arg_flow[i];
515
516 new_sum->m_return_ignored = old_sum->m_return_ignored;
517 new_sum->m_return_returned = old_sum->m_return_returned;
518 new_sum->m_bit_aligned_arg = old_sum->m_bit_aligned_arg;
519}
520
521
522/* With all GTY stuff done, we can move to anonymous namespace. */
523namespace {
524/* Quick mapping from a decl to its param descriptor. */
525
526hash_map<tree, gensum_param_desc *> *decl2desc;
527
528/* Countdown of allowe Alias analysis steps during summary building. */
529
530int aa_walking_limit;
531
532/* This is a table in which for each basic block and parameter there is a
533 distance (offset + size) in that parameter which is dereferenced and
534 accessed in that BB. */
535HOST_WIDE_INT *bb_dereferences = NULL;
536/* How many by-reference parameters there are in the current function. */
537int by_ref_count;
538
539/* Bitmap of BBs that can cause the function to "stop" progressing by
540 returning, throwing externally, looping infinitely or calling a function
541 which might abort etc.. */
542bitmap final_bbs;
543
544/* Obstack to allocate various small structures required only when generating
545 summary for a function. */
546struct obstack gensum_obstack;
547
548/* Return false the function is apparently unsuitable for IPA-SRA based on it's
549 attributes, return true otherwise. NODE is the cgraph node of the current
550 function. */
551
552static bool
553ipa_sra_preliminary_function_checks (cgraph_node *node)
554{
555 if (!node->local.can_change_signature)
556 {
557 if (dump_file)
558 fprintf (dump_file, "Function cannot change signature.\n");
559 return false;
560 }
561
562 if (!tree_versionable_function_p (node->decl))
563 {
564 if (dump_file)
565 fprintf (dump_file, "Function is not versionable.\n");
566 return false;
567 }
568
569 if (!opt_for_fn (node->decl, optimize)
570 || !opt_for_fn (node->decl, flag_ipa_sra))
571 {
572 if (dump_file)
573 fprintf (dump_file, "Not optimizing or IPA-SRA turned off for this "
574 "function.\n");
575 return false;
576 }
577
578 if (DECL_VIRTUAL_P (node->decl))
579 {
580 if (dump_file)
581 fprintf (dump_file, "Function is a virtual method.\n");
582 return false;
583 }
584
585 struct function *fun = DECL_STRUCT_FUNCTION (node->decl);
586 if (fun->stdarg)
587 {
588 if (dump_file)
589 fprintf (dump_file, "Function uses stdarg. \n");
590 return false;
591 }
592
593 if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl)))
594 {
595 if (dump_file)
596 fprintf (dump_file, "Function type has attributes. \n");
597 return false;
598 }
599
600 if (DECL_DISREGARD_INLINE_LIMITS (node->decl))
601 {
602 if (dump_file)
603 fprintf (dump_file, "Always inline function will be inlined "
604 "anyway. \n");
605 return false;
606 }
607
608 return true;
609}
610
611/* Print access tree starting at ACCESS to F. */
612
613static void
614dump_gensum_access (FILE *f, gensum_param_access *access, unsigned indent)
615{
616 fprintf (f, " ");
617 for (unsigned i = 0; i < indent; i++)
618 fprintf (f, " ");
619 fprintf (f, " * Access to offset: " HOST_WIDE_INT_PRINT_DEC,
620 access->offset);
621 fprintf (f, ", size: " HOST_WIDE_INT_PRINT_DEC, access->size);
622 fprintf (f, ", type: ");
623 print_generic_expr (f, access->type);
624 fprintf (f, ", alias_ptr_type: ");
625 print_generic_expr (f, access->alias_ptr_type);
626 fprintf (f, ", nonarg: %u, reverse: %u\n", access->nonarg, access->reverse);
627 for (gensum_param_access *ch = access->first_child;
628 ch;
629 ch = ch->next_sibling)
630 dump_gensum_access (f, ch, indent + 2);
631}
632
633
634/* Print access tree starting at ACCESS to F. */
635
636static void
637dump_isra_access (FILE *f, param_access *access)
638{
639 fprintf (f, " * Access to unit offset: %u", access->unit_offset);
640 fprintf (f, ", unit size: %u", access->unit_size);
641 fprintf (f, ", type: ");
642 print_generic_expr (f, access->type);
643 fprintf (f, ", alias_ptr_type: ");
644 print_generic_expr (f, access->alias_ptr_type);
645 if (access->certain)
646 fprintf (f, ", certain");
647 else
648 fprintf (f, ", not-certain");
649 if (access->reverse)
650 fprintf (f, ", reverse");
651 fprintf (f, "\n");
652}
653
654/* Dump access tree starting at ACCESS to stderr. */
655
656DEBUG_FUNCTION void
657debug_isra_access (param_access *access)
658{
659 dump_isra_access (stderr, access);
660}
661
662/* Dump DESC to F. */
663
664static void
665dump_gensum_param_descriptor (FILE *f, gensum_param_desc *desc)
666{
667 if (desc->locally_unused)
668 fprintf (f, " unused with %i call_uses\n", desc->call_uses);
669 if (!desc->split_candidate)
670 {
671 fprintf (f, " not a candidate\n");
672 return;
673 }
674 if (desc->by_ref)
675 fprintf (f, " by_ref with %u pass throughs\n", desc->ptr_pt_count);
676
677 for (gensum_param_access *acc = desc->accesses; acc; acc = acc->next_sibling)
678 dump_gensum_access (f, acc, 2);
679}
680
681/* Dump all parameter descriptors in IFS, assuming it describes FNDECl, to
682 F. */
683
684static void
685dump_gensum_param_descriptors (FILE *f, tree fndecl,
686 vec<gensum_param_desc> *param_descriptions)
687{
688 tree parm = DECL_ARGUMENTS (fndecl);
689 for (unsigned i = 0;
690 i < param_descriptions->length ();
691 ++i, parm = DECL_CHAIN (parm))
692 {
693 fprintf (f, " Descriptor for parameter %i ", i);
694 print_generic_expr (f, parm, TDF_UID);
695 fprintf (f, "\n");
696 dump_gensum_param_descriptor (f, &(*param_descriptions)[i]);
697 }
698}
699
700
701/* Dump DESC to F. */
702
703static void
704dump_isra_param_descriptor (FILE *f, isra_param_desc *desc)
705{
706 if (desc->locally_unused)
707 {
708 fprintf (f, " (locally) unused\n");
709 }
710 if (!desc->split_candidate)
711 {
712 fprintf (f, " not a candidate for splitting\n");
713 return;
714 }
715 fprintf (f, " param_size_limit: %u, size_reached: %u%s\n",
716 desc->param_size_limit, desc->size_reached,
717 desc->by_ref ? ", by_ref" : "");
718
719 for (unsigned i = 0; i < vec_safe_length (desc->accesses); ++i)
720 {
721 param_access *access = (*desc->accesses)[i];
722 dump_isra_access (f, access);
723 }
724}
725
726/* Dump all parameter descriptors in IFS, assuming it describes FNDECl, to
727 F. */
728
729static void
730dump_isra_param_descriptors (FILE *f, tree fndecl,
731 isra_func_summary *ifs)
732{
733 tree parm = DECL_ARGUMENTS (fndecl);
734 if (!ifs->m_parameters)
735 {
736 fprintf (f, " parameter descriptors not available\n");
737 return;
738 }
739
740 for (unsigned i = 0;
741 i < ifs->m_parameters->length ();
742 ++i, parm = DECL_CHAIN (parm))
743 {
744 fprintf (f, " Descriptor for parameter %i ", i);
745 print_generic_expr (f, parm, TDF_UID);
746 fprintf (f, "\n");
747 dump_isra_param_descriptor (f, &(*ifs->m_parameters)[i]);
748 }
749}
750
751/* Add SRC to inputs of PARAM_FLOW, unless it would exceed storage. If the
752 function fails return false, otherwise return true. SRC must fit into an
753 unsigned char. Used for purposes of transitive unused parameter
754 removal. */
755
756static bool
757add_src_to_param_flow (isra_param_flow *param_flow, int src)
758{
759 gcc_checking_assert (src >= 0 && src <= UCHAR_MAX);
760 if (param_flow->length == IPA_SRA_MAX_PARAM_FLOW_LEN)
761 return false;
762
763 param_flow->inputs[(int) param_flow->length] = src;
764 param_flow->length++;
765 return true;
766}
767
768/* Add a SRC to the inputs of PARAM_FLOW unless it is already there and assert
769 it is the only input. Used for purposes of transitive parameter
770 splitting. */
771
772static void
773set_single_param_flow_source (isra_param_flow *param_flow, int src)
774{
775 gcc_checking_assert (src >= 0 && src <= UCHAR_MAX);
776 if (param_flow->length == 0)
777 {
778 param_flow->inputs[0] = src;
779 param_flow->length = 1;
780 }
781 else if (param_flow->length == 1)
782 gcc_assert (param_flow->inputs[0] == src);
783 else
784 gcc_unreachable ();
785}
786
787/* Assert that there is only a single value in PARAM_FLOW's inputs and return
788 it. */
789
790static unsigned
791get_single_param_flow_source (const isra_param_flow *param_flow)
792{
793 gcc_assert (param_flow->length == 1);
794 return param_flow->inputs[0];
795}
796
797/* Inspect all uses of NAME and simple arithmetic calculations involving NAME
798 in NODE and return a negative number if any of them is used for something
799 else than either an actual call argument, simple arithmetic operation or
800 debug statement. If there are no such uses, return the number of actual
801 arguments that this parameter eventually feeds to (or zero if there is none).
802 For any such parameter, mark PARM_NUM as one of its sources. ANALYZED is a
803 bitmap that tracks which SSA names we have already started
804 investigating. */
805
806static int
807isra_track_scalar_value_uses (cgraph_node *node, tree name, int parm_num,
808 bitmap analyzed)
809{
810 int res = 0;
811 imm_use_iterator imm_iter;
812 gimple *stmt;
813
814 FOR_EACH_IMM_USE_STMT (stmt, imm_iter, name)
815 {
816 if (is_gimple_debug (stmt))
817 continue;
818
819 /* TODO: We could handle at least const builtin functions like arithmetic
820 operations below. */
821 if (is_gimple_call (stmt))
822 {
823 int all_uses = 0;
824 use_operand_p use_p;
825 FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
826 all_uses++;
827
828 gcall *call = as_a <gcall *> (stmt);
829 unsigned arg_count;
830 if (gimple_call_internal_p (call)
831 || (arg_count = gimple_call_num_args (call)) == 0)
832 {
833 res = -1;
834 BREAK_FROM_IMM_USE_STMT (imm_iter);
835 }
836
837 cgraph_edge *cs = node->get_edge (stmt);
838 gcc_checking_assert (cs);
839 isra_call_summary *csum = call_sums->get_create (cs);
840 csum->init_inputs (arg_count);
841
842 int simple_uses = 0;
843 for (unsigned i = 0; i < arg_count; i++)
844 if (gimple_call_arg (call, i) == name)
845 {
846 if (!add_src_to_param_flow (&csum->m_arg_flow[i], parm_num))
847 {
848 simple_uses = -1;
849 break;
850 }
851 simple_uses++;
852 }
853
854 if (simple_uses < 0
855 || all_uses != simple_uses)
856 {
857 res = -1;
858 BREAK_FROM_IMM_USE_STMT (imm_iter);
859 }
860 res += all_uses;
861 }
862 else if ((is_gimple_assign (stmt) && !gimple_has_volatile_ops (stmt))
863 || gimple_code (stmt) == GIMPLE_PHI)
864 {
865 tree lhs;
866 if (gimple_code (stmt) == GIMPLE_PHI)
867 lhs = gimple_phi_result (stmt);
868 else
869 lhs = gimple_assign_lhs (stmt);
870
871 if (TREE_CODE (lhs) != SSA_NAME)
872 {
873 res = -1;
874 BREAK_FROM_IMM_USE_STMT (imm_iter);
875 }
876 gcc_assert (!gimple_vdef (stmt));
877 if (bitmap_set_bit (analyzed, SSA_NAME_VERSION (lhs)))
878 {
879 int tmp = isra_track_scalar_value_uses (node, lhs, parm_num,
880 analyzed);
881 if (tmp < 0)
882 {
883 res = tmp;
884 BREAK_FROM_IMM_USE_STMT (imm_iter);
885 }
886 res += tmp;
887 }
888 }
889 else
890 {
891 res = -1;
892 BREAK_FROM_IMM_USE_STMT (imm_iter);
893 }
894 }
895 return res;
896}
897
898/* Inspect all uses of PARM, which must be a gimple register, in FUN (which is
899 also described by NODE) and simple arithmetic calculations involving PARM
900 and return false if any of them is used for something else than either an
901 actual call argument, simple arithmetic operation or debug statement. If
902 there are no such uses, return true and store the number of actual arguments
903 that this parameter eventually feeds to (or zero if there is none) to
904 *CALL_USES_P. For any such parameter, mark PARM_NUM as one of its
905 sources.
906
907 This function is similar to ptr_parm_has_nonarg_uses but its results are
908 meant for unused parameter removal, as opposed to splitting of parameters
909 passed by reference or converting them to passed by value.
910 */
911
912static bool
913isra_track_scalar_param_local_uses (function *fun, cgraph_node *node, tree parm,
914 int parm_num, int *call_uses_p)
915{
916 gcc_checking_assert (is_gimple_reg (parm));
917
918 tree name = ssa_default_def (fun, parm);
919 if (!name || has_zero_uses (name))
920 {
921 *call_uses_p = 0;
922 return false;
923 }
924
925 /* Edge summaries can only handle callers with fewer than 256 parameters. */
926 if (parm_num > UCHAR_MAX)
927 return true;
928
929 bitmap analyzed = BITMAP_ALLOC (NULL);
930 int call_uses = isra_track_scalar_value_uses (node, name, parm_num, analyzed);
931 BITMAP_FREE (analyzed);
932 if (call_uses < 0)
933 return true;
934 *call_uses_p = call_uses;
935 return false;
936}
937
938/* Scan immediate uses of a default definition SSA name of a parameter PARM and
939 examine whether there are any nonarg uses that are not actual arguments or
940 otherwise infeasible uses. If so, return true, otherwise return false.
941 Create pass-through IPA flow records for any direct uses as argument calls
942 and if returning false, store their number into *PT_COUNT_P. NODE and FUN
943 must represent the function that is currently analyzed, PARM_NUM must be the
944 index of the analyzed parameter.
945
946 This function is similar to isra_track_scalar_param_local_uses but its
947 results are meant for splitting of parameters passed by reference or turning
948 them into bits passed by value, as opposed to generic unused parameter
949 removal.
950 */
951
952static bool
953ptr_parm_has_nonarg_uses (cgraph_node *node, function *fun, tree parm,
954 int parm_num, unsigned *pt_count_p)
955{
956 imm_use_iterator ui;
957 gimple *stmt;
958 tree name = ssa_default_def (fun, parm);
959 bool ret = false;
960 unsigned pt_count = 0;
961
962 if (!name || has_zero_uses (name))
963 return false;
964
965 /* Edge summaries can only handle callers with fewer than 256 parameters. */
966 if (parm_num > UCHAR_MAX)
967 return true;
968
969 FOR_EACH_IMM_USE_STMT (stmt, ui, name)
970 {
971 unsigned uses_ok = 0;
972 use_operand_p use_p;
973
974 if (is_gimple_debug (stmt))
975 continue;
976
977 if (gimple_assign_single_p (stmt))
978 {
979 tree rhs = gimple_assign_rhs1 (stmt);
980 while (handled_component_p (rhs))
981 rhs = TREE_OPERAND (rhs, 0);
982 if (TREE_CODE (rhs) == MEM_REF
983 && TREE_OPERAND (rhs, 0) == name
984 && integer_zerop (TREE_OPERAND (rhs, 1))
985 && types_compatible_p (TREE_TYPE (rhs),
986 TREE_TYPE (TREE_TYPE (name)))
987 && !TREE_THIS_VOLATILE (rhs))
988 uses_ok++;
989 }
990 else if (is_gimple_call (stmt))
991 {
992 gcall *call = as_a <gcall *> (stmt);
993 unsigned arg_count;
994 if (gimple_call_internal_p (call)
995 || (arg_count = gimple_call_num_args (call)) == 0)
996 {
997 ret = true;
998 BREAK_FROM_IMM_USE_STMT (ui);
999 }
1000
1001 cgraph_edge *cs = node->get_edge (stmt);
1002 gcc_checking_assert (cs);
1003 isra_call_summary *csum = call_sums->get_create (cs);
1004 csum->init_inputs (arg_count);
1005
1006 for (unsigned i = 0; i < arg_count; ++i)
1007 {
1008 tree arg = gimple_call_arg (stmt, i);
1009
1010 if (arg == name)
1011 {
1012 /* TODO: Allow &MEM_REF[name + offset] here,
1013 ipa_param_body_adjustments::modify_call_stmt has to be
1014 adjusted too. */
1015 csum->m_arg_flow[i].pointer_pass_through = true;
1016 set_single_param_flow_source (&csum->m_arg_flow[i], parm_num);
1017 pt_count++;
1018 uses_ok++;
1019 continue;
1020 }
1021
1022 while (handled_component_p (arg))
1023 arg = TREE_OPERAND (arg, 0);
1024 if (TREE_CODE (arg) == MEM_REF
1025 && TREE_OPERAND (arg, 0) == name
1026 && integer_zerop (TREE_OPERAND (arg, 1))
1027 && types_compatible_p (TREE_TYPE (arg),
1028 TREE_TYPE (TREE_TYPE (name)))
1029 && !TREE_THIS_VOLATILE (arg))
1030 uses_ok++;
1031 }
1032 }
1033
1034 /* If the number of valid uses does not match the number of
1035 uses in this stmt there is an unhandled use. */
1036 unsigned all_uses = 0;
1037 FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
1038 all_uses++;
1039
1040 gcc_checking_assert (uses_ok <= all_uses);
1041 if (uses_ok != all_uses)
1042 {
1043 ret = true;
1044 BREAK_FROM_IMM_USE_STMT (ui);
1045 }
1046 }
1047
1048 *pt_count_p = pt_count;
1049 return ret;
1050}
1051
1052/* Initialize vector of parameter descriptors of NODE. Return true if there
1053 are any candidates for splitting or unused aggregate parameter removal (the
1054 function may return false if there are candidates for removal of register
1055 parameters) and function body must be scanned. */
1056
1057static bool
1058create_parameter_descriptors (cgraph_node *node,
1059 vec<gensum_param_desc> *param_descriptions)
1060{
1061 function *fun = DECL_STRUCT_FUNCTION (node->decl);
1062 bool ret = false;
1063
1064 int num = 0;
1065 for (tree parm = DECL_ARGUMENTS (node->decl);
1066 parm;
1067 parm = DECL_CHAIN (parm), num++)
1068 {
1069 const char *msg;
1070 gensum_param_desc *desc = &(*param_descriptions)[num];
1071 /* param_descriptions vector is grown cleared in the caller. */
1072 desc->param_number = num;
1073 decl2desc->put (parm, desc);
1074
1075 if (dump_file && (dump_flags & TDF_DETAILS))
1076 print_generic_expr (dump_file, parm, TDF_UID);
1077
1078 int scalar_call_uses;
1079 tree type = TREE_TYPE (parm);
1080 if (TREE_THIS_VOLATILE (parm))
1081 {
1082 if (dump_file && (dump_flags & TDF_DETAILS))
1083 fprintf (dump_file, " not a candidate, is volatile\n");
1084 continue;
1085 }
1086 if (!is_gimple_reg_type (type) && is_va_list_type (type))
1087 {
1088 if (dump_file && (dump_flags & TDF_DETAILS))
1089 fprintf (dump_file, " not a candidate, is a va_list type\n");
1090 continue;
1091 }
1092 if (TREE_ADDRESSABLE (parm))
1093 {
1094 if (dump_file && (dump_flags & TDF_DETAILS))
1095 fprintf (dump_file, " not a candidate, is addressable\n");
1096 continue;
1097 }
1098 if (TREE_ADDRESSABLE (type))
1099 {
1100 if (dump_file && (dump_flags & TDF_DETAILS))
1101 fprintf (dump_file, " not a candidate, type cannot be split\n");
1102 continue;
1103 }
1104
1105 if (is_gimple_reg (parm)
1106 && !isra_track_scalar_param_local_uses (fun, node, parm, num,
1107 &scalar_call_uses))
1108 {
1109 if (dump_file && (dump_flags & TDF_DETAILS))
1110 fprintf (dump_file, " is a scalar with only %i call uses\n",
1111 scalar_call_uses);
1112
1113 desc->locally_unused = true;
1114 desc->call_uses = scalar_call_uses;
1115 }
1116
1117 if (POINTER_TYPE_P (type))
1118 {
1119 type = TREE_TYPE (type);
1120
1121 if (TREE_CODE (type) == FUNCTION_TYPE
1122 || TREE_CODE (type) == METHOD_TYPE)
1123 {
1124 if (dump_file && (dump_flags & TDF_DETAILS))
1125 fprintf (dump_file, " not a candidate, reference to "
1126 "a function\n");
1127 continue;
1128 }
1129 if (TYPE_VOLATILE (type))
1130 {
1131 if (dump_file && (dump_flags & TDF_DETAILS))
1132 fprintf (dump_file, " not a candidate, reference to "
1133 "a volatile type\n");
1134 continue;
1135 }
1136 if (TREE_CODE (type) == ARRAY_TYPE
1137 && TYPE_NONALIASED_COMPONENT (type))
1138 {
1139 if (dump_file && (dump_flags & TDF_DETAILS))
1140 fprintf (dump_file, " not a candidate, reference to a"
1141 "nonaliased component array\n");
1142 continue;
1143 }
1144 if (!is_gimple_reg (parm))
1145 {
1146 if (dump_file && (dump_flags & TDF_DETAILS))
1147 fprintf (dump_file, " not a candidate, a reference which is "
1148 "not a gimple register (probably addressable)\n");
1149 continue;
1150 }
1151 if (is_va_list_type (type))
1152 {
1153 if (dump_file && (dump_flags & TDF_DETAILS))
1154 fprintf (dump_file, " not a candidate, reference to "
1155 "a va list\n");
1156 continue;
1157 }
1158 if (ptr_parm_has_nonarg_uses (node, fun, parm, num,
1159 &desc->ptr_pt_count))
1160 {
1161 if (dump_file && (dump_flags & TDF_DETAILS))
1162 fprintf (dump_file, " not a candidate, reference has "
1163 "nonarg uses\n");
1164 continue;
1165 }
1166 desc->by_ref = true;
1167 }
1168 else if (!AGGREGATE_TYPE_P (type))
1169 {
1170 /* This is in an else branch because scalars passed by reference are
1171 still candidates to be passed by value. */
1172 if (dump_file && (dump_flags & TDF_DETAILS))
1173 fprintf (dump_file, " not a candidate, not an aggregate\n");
1174 continue;
1175 }
1176
1177 if (!COMPLETE_TYPE_P (type))
1178 {
1179 if (dump_file && (dump_flags & TDF_DETAILS))
1180 fprintf (dump_file, " not a candidate, not a complete type\n");
1181 continue;
1182 }
1183 if (!tree_fits_uhwi_p (TYPE_SIZE (type)))
1184 {
1185 if (dump_file && (dump_flags & TDF_DETAILS))
1186 fprintf (dump_file, " not a candidate, size not representable\n");
1187 continue;
1188 }
1189 unsigned HOST_WIDE_INT type_size
1190 = tree_to_uhwi (TYPE_SIZE (type)) / BITS_PER_UNIT;
1191 if (type_size == 0
1192 || type_size >= ISRA_ARG_SIZE_LIMIT)
1193 {
1194 if (dump_file && (dump_flags & TDF_DETAILS))
1195 fprintf (dump_file, " not a candidate, has zero or huge size\n");
1196 continue;
1197 }
1198 if (type_internals_preclude_sra_p (type, &msg))
1199 {
1200 if (dump_file && (dump_flags & TDF_DETAILS))
1201 fprintf (dump_file, " not a candidate, %s\n", msg);
1202 continue;
1203 }
1204
1205 if (dump_file && (dump_flags & TDF_DETAILS))
1206 fprintf (dump_file, " is a candidate\n");
1207
1208 ret = true;
1209 desc->split_candidate = true;
1210 if (desc->by_ref)
1211 desc->deref_index = by_ref_count++;
1212 }
1213 return ret;
1214}
1215
1216/* Return pointer to descriptor of parameter DECL or NULL if it cannot be
1217 found, which happens if DECL is for a static chain. */
1218
1219static gensum_param_desc *
1220get_gensum_param_desc (tree decl)
1221{
1222 gcc_checking_assert (TREE_CODE (decl) == PARM_DECL);
1223 gensum_param_desc **slot = decl2desc->get (decl);
1224 if (!slot)
1225 /* This can happen for static chains which we cannot handle so far. */
1226 return NULL;
1227 gcc_checking_assert (*slot);
1228 return *slot;
1229}
1230
1231
1232/* Remove parameter described by DESC from candidates for IPA-SRA splitting and
1233 write REASON to the dump file if there is one. */
1234
1235static void
1236disqualify_split_candidate (gensum_param_desc *desc, const char *reason)
1237{
1238 if (!desc->split_candidate)
1239 return;
1240
1241 if (dump_file && (dump_flags & TDF_DETAILS))
1242 fprintf (dump_file, "! Disqualifying parameter number %i - %s\n",
1243 desc->param_number, reason);
1244
1245 desc->split_candidate = false;
1246}
1247
1248/* Remove DECL from candidates for IPA-SRA and write REASON to the dump file if
1249 there is one. */
1250
1251static void
1252disqualify_split_candidate (tree decl, const char *reason)
1253{
1254 gensum_param_desc *desc = get_gensum_param_desc (decl);
1255 if (desc)
1256 disqualify_split_candidate (desc, reason);
1257}
1258
1259/* Allocate a new access to DESC and fill it in with OFFSET and SIZE. But
1260 first, check that there are not too many of them already. If so, do not
1261 allocate anything and return NULL. */
1262
1263static gensum_param_access *
1264allocate_access (gensum_param_desc *desc,
1265 HOST_WIDE_INT offset, HOST_WIDE_INT size)
1266{
1267 if (desc->access_count
1268 == (unsigned) PARAM_VALUE (PARAM_IPA_SRA_MAX_REPLACEMENTS))
1269 {
1270 disqualify_split_candidate (desc, "Too many replacement candidates");
1271 return NULL;
1272 }
1273
1274 gensum_param_access *access
1275 = (gensum_param_access *) obstack_alloc (&gensum_obstack,
1276 sizeof (gensum_param_access));
1277 memset (access, 0, sizeof (*access));
1278 access->offset = offset;
1279 access->size = size;
1280 return access;
1281}
1282
1283/* In what context scan_expr_access has been called, whether it deals with a
1284 load, a function argument, or a store. */
1285
1286enum isra_scan_context {ISRA_CTX_LOAD, ISRA_CTX_ARG, ISRA_CTX_STORE};
1287
1288/* Return an access describing memory access to the variable described by DESC
1289 at OFFSET with SIZE in context CTX, starting at pointer to the linked list
1290 at a certaint tree level FIRST. Attempt to create it and put into the
1291 appropriate place in the access tree if does not exist, but fail and return
1292 NULL if there are already too many accesses, if it would create a partially
1293 overlapping access or if an access would end up withiin a pre-existing
1294 non-call access. */
1295
1296static gensum_param_access *
1297get_access_1 (gensum_param_desc *desc, gensum_param_access **first,
1298 HOST_WIDE_INT offset, HOST_WIDE_INT size, isra_scan_context ctx)
1299{
1300 gensum_param_access *access = *first, **ptr = first;
1301
1302 if (!access)
1303 {
1304 /* No pre-existing access at this level, just create it. */
1305 gensum_param_access *a = allocate_access (desc, offset, size);
1306 if (!a)
1307 return NULL;
1308 *first = a;
1309 return *first;
1310 }
1311
1312 if (access->offset >= offset + size)
1313 {
1314 /* We want to squeeze it in front of the very first access, just do
1315 it. */
1316 gensum_param_access *r = allocate_access (desc, offset, size);
1317 if (!r)
1318 return NULL;
1319 r->next_sibling = access;
1320 *first = r;
1321 return r;
1322 }
1323
1324 /* Skip all accesses that have to come before us until the next sibling is
1325 already too far. */
1326 while (offset >= access->offset + access->size
1327 && access->next_sibling
1328 && access->next_sibling->offset < offset + size)
1329 {
1330 ptr = &access->next_sibling;
1331 access = access->next_sibling;
1332 }
1333
1334 /* At this point we know we do not belong before access. */
1335 gcc_assert (access->offset < offset + size);
1336
1337 if (access->offset == offset && access->size == size)
1338 /* We found what we were looking for. */
1339 return access;
1340
1341 if (access->offset <= offset
1342 && access->offset + access->size >= offset + size)
1343 {
1344 /* We fit into access which is larger than us. We need to find/create
1345 something below access. But we only allow nesting in call
1346 arguments. */
1347 if (access->nonarg)
1348 return NULL;
1349
1350 return get_access_1 (desc, &access->first_child, offset, size, ctx);
1351 }
1352
1353 if (offset <= access->offset
1354 && offset + size >= access->offset + access->size)
1355 /* We are actually bigger than access, which fully fits into us, take its
1356 place and make all accesses fitting into it its children. */
1357 {
1358 /* But first, we only allow nesting in call arguments so check if that is
1359 what we are trying to represent. */
1360 if (ctx != ISRA_CTX_ARG)
1361 return NULL;
1362
1363 gensum_param_access *r = allocate_access (desc, offset, size);
1364 if (!r)
1365 return NULL;
1366 r->first_child = access;
1367
1368 while (access->next_sibling
1369 && access->next_sibling->offset < offset + size)
1370 access = access->next_sibling;
1371 if (access->offset + access->size > offset + size)
1372 {
1373 /* This must be a different access, which are sorted, so the
1374 following must be true and this signals a partial overlap. */
1375 gcc_assert (access->offset > offset);
1376 return NULL;
1377 }
1378
1379 r->next_sibling = access->next_sibling;
1380 access->next_sibling = NULL;
1381 *ptr = r;
1382 return r;
1383 }
1384
1385 if (offset >= access->offset + access->size)
1386 {
1387 /* We belong after access. */
1388 gensum_param_access *r = allocate_access (desc, offset, size);
1389 if (!r)
1390 return NULL;
1391 r->next_sibling = access->next_sibling;
1392 access->next_sibling = r;
1393 return r;
1394 }
1395
1396 if (offset < access->offset)
1397 {
1398 /* We know the following, otherwise we would have created a
1399 super-access. */
1400 gcc_checking_assert (offset + size < access->offset + access->size);
1401 return NULL;
1402 }
1403
1404 if (offset + size > access->offset + access->size)
1405 {
1406 /* Likewise. */
1407 gcc_checking_assert (offset > access->offset);
1408 return NULL;
1409 }
1410
1411 gcc_unreachable ();
1412}
1413
1414/* Return an access describing memory access to the variable described by DESC
1415 at OFFSET with SIZE in context CTX, mark it as used in context CTX. Attempt
1416 to create if it does not exist, but fail and return NULL if there are
1417 already too many accesses, if it would create a partially overlapping access
1418 or if an access woule end up in a non-call access. */
1419
1420static gensum_param_access *
1421get_access (gensum_param_desc *desc, HOST_WIDE_INT offset, HOST_WIDE_INT size,
1422 isra_scan_context ctx)
1423{
1424 gcc_checking_assert (desc->split_candidate);
1425
1426 gensum_param_access *access = get_access_1 (desc, &desc->accesses, offset,
1427 size, ctx);
1428 if (!access)
1429 {
1430 disqualify_split_candidate (desc,
1431 "Bad access overlap or too many accesses");
1432 return NULL;
1433 }
1434
1435 switch (ctx)
1436 {
1437 case ISRA_CTX_STORE:
1438 gcc_assert (!desc->by_ref);
1439 /* Fall-through */
1440 case ISRA_CTX_LOAD:
1441 access->nonarg = true;
1442 break;
1443 case ISRA_CTX_ARG:
1444 break;
1445 }
1446
1447 return access;
1448}
1449
1450/* Verify that parameter access tree starting with ACCESS is in good shape.
1451 PARENT_OFFSET and PARENT_SIZE are the ciorresponding fields of parent of
1452 ACCESS or zero if there is none. */
1453
1454static bool
1455verify_access_tree_1 (gensum_param_access *access, HOST_WIDE_INT parent_offset,
1456 HOST_WIDE_INT parent_size)
1457{
1458 while (access)
1459 {
1460 gcc_assert (access->offset >= 0 && access->size > 0);
1461
1462 if (parent_size != 0)
1463 {
1464 if (access->offset < parent_offset)
1465 {
1466 error ("Access offset before parent offset");
1467 return true;
1468 }
1469 if (access->size >= parent_size)
1470 {
1471 error ("Access size greater or equal to its parent size");
1472 return true;
1473 }
1474 if (access->offset + access->size > parent_offset + parent_size)
1475 {
1476 error ("Access terminates outside of its parent");
1477 return true;
1478 }
1479 }
1480
1481 if (verify_access_tree_1 (access->first_child, access->offset,
1482 access->size))
1483 return true;
1484
1485 if (access->next_sibling
1486 && (access->next_sibling->offset < access->offset + access->size))
1487 {
1488 error ("Access overlaps with its sibling");
1489 return true;
1490 }
1491
1492 access = access->next_sibling;
1493 }
1494 return false;
1495}
1496
1497/* Verify that parameter access tree starting with ACCESS is in good shape,
1498 halt compilation and dump the tree to stderr if not. */
1499
1500DEBUG_FUNCTION void
1501isra_verify_access_tree (gensum_param_access *access)
1502{
1503 if (verify_access_tree_1 (access, 0, 0))
1504 {
1505 for (; access; access = access->next_sibling)
1506 dump_gensum_access (stderr, access, 2);
1507 internal_error ("IPA-SRA access verification failed");
1508 }
1509}
1510
1511
1512/* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine
1513 GIMPLE_ASM operands with memory constrains which cannot be scalarized. */
1514
1515static bool
1516asm_visit_addr (gimple *, tree op, tree, void *)
1517{
1518 op = get_base_address (op);
1519 if (op
1520 && TREE_CODE (op) == PARM_DECL)
1521 disqualify_split_candidate (op, "Non-scalarizable GIMPLE_ASM operand.");
1522
1523 return false;
1524}
1525
1526/* Mark a dereference of parameter identified by DESC of distance DIST in a
1527 basic block BB, unless the BB has already been marked as a potentially
1528 final. */
1529
1530static void
1531mark_param_dereference (gensum_param_desc *desc, HOST_WIDE_INT dist,
1532 basic_block bb)
1533{
1534 gcc_assert (desc->by_ref);
1535 gcc_checking_assert (desc->split_candidate);
1536
1537 if (bitmap_bit_p (final_bbs, bb->index))
1538 return;
1539
1540 int idx = bb->index * by_ref_count + desc->deref_index;
1541 if (bb_dereferences[idx] < dist)
1542 bb_dereferences[idx] = dist;
1543}
1544
1545/* Return true, if any potential replacements should use NEW_TYPE as opposed to
1546 previously recorded OLD_TYPE. */
1547
1548static bool
1549type_prevails_p (tree old_type, tree new_type)
1550{
1551 if (old_type == new_type)
1552 return false;
1553
1554 /* Non-aggregates are always better. */
1555 if (!is_gimple_reg_type (old_type)
1556 && is_gimple_reg_type (new_type))
1557 return true;
1558 if (is_gimple_reg_type (old_type)
1559 && !is_gimple_reg_type (new_type))
1560 return false;
1561
1562 /* Prefer any complex or vector type over any other scalar type. */
1563 if (TREE_CODE (old_type) != COMPLEX_TYPE
1564 && TREE_CODE (old_type) != VECTOR_TYPE
1565 && (TREE_CODE (new_type) == COMPLEX_TYPE
1566 || TREE_CODE (new_type) == VECTOR_TYPE))
1567 return true;
1568 if ((TREE_CODE (old_type) == COMPLEX_TYPE
1569 || TREE_CODE (old_type) == VECTOR_TYPE)
1570 && TREE_CODE (new_type) != COMPLEX_TYPE
1571 && TREE_CODE (new_type) != VECTOR_TYPE)
1572 return false;
1573
1574 /* Use the integral type with the bigger precision. */
1575 if (INTEGRAL_TYPE_P (old_type)
1576 && INTEGRAL_TYPE_P (new_type))
1577 return (TYPE_PRECISION (new_type) > TYPE_PRECISION (old_type));
1578
1579 /* Attempt to disregard any integral type with non-full precision. */
1580 if (INTEGRAL_TYPE_P (old_type)
1581 && (TREE_INT_CST_LOW (TYPE_SIZE (old_type))
1582 != TYPE_PRECISION (old_type)))
1583 return true;
1584 if (INTEGRAL_TYPE_P (new_type)
1585 && (TREE_INT_CST_LOW (TYPE_SIZE (new_type))
1586 != TYPE_PRECISION (new_type)))
1587 return false;
1588 /* Stabilize the selection. */
1589 return TYPE_UID (old_type) < TYPE_UID (new_type);
1590}
1591
1592/* When scanning an expression which is a call argument, this structure
1593 specifies the call and the position of the agrument. */
1594
1595struct scan_call_info
1596{
1597 /* Call graph edge representing the call. */
1598 cgraph_edge *cs;
1599 /* Total number of arguments in the call. */
1600 unsigned argument_count;
1601 /* Number of the actual argument being scanned. */
1602 unsigned arg_idx;
1603};
1604
1605/* Record use of ACCESS which belongs to a parameter described by DESC in a
1606 call argument described by CALL_INFO. */
1607
1608static void
1609record_nonregister_call_use (gensum_param_desc *desc,
1610 scan_call_info *call_info,
1611 unsigned unit_offset, unsigned unit_size)
1612{
1613 isra_call_summary *csum = call_sums->get_create (call_info->cs);
1614 csum->init_inputs (call_info->argument_count);
1615
1616 isra_param_flow *param_flow = &csum->m_arg_flow[call_info->arg_idx];
1617 param_flow->aggregate_pass_through = true;
1618 set_single_param_flow_source (param_flow, desc->param_number);
1619 param_flow->unit_offset = unit_offset;
1620 param_flow->unit_size = unit_size;
1621 desc->call_uses++;
1622}
1623
1624/* Callback of walk_aliased_vdefs, just mark that there was a possible
1625 modification. */
1626
1627static bool
1628mark_maybe_modified (ao_ref *, tree, void *data)
1629{
1630 bool *maybe_modified = (bool *) data;
1631 *maybe_modified = true;
1632 return true;
1633}
1634
1635/* Analyze expression EXPR from GIMPLE for accesses to parameters. CTX
1636 specifies whether EXPR is used in a load, store or as an argument call. BB
1637 must be the basic block in which expr resides. If CTX specifies call
1638 arguemnt context, CALL_INFO must describe tha call and argument position,
1639 otherwise it is ignored. */
1640
1641static void
1642scan_expr_access (tree expr, gimple *stmt, isra_scan_context ctx,
1643 basic_block bb, scan_call_info *call_info = NULL)
1644{
1645 poly_int64 poffset, psize, pmax_size;
1646 HOST_WIDE_INT offset, size, max_size;
1647 tree base;
1648 bool deref = false;
1649 bool reverse;
1650
1651 if (TREE_CODE (expr) == BIT_FIELD_REF
1652 || TREE_CODE (expr) == IMAGPART_EXPR
1653 || TREE_CODE (expr) == REALPART_EXPR)
1654 expr = TREE_OPERAND (expr, 0);
1655
1656 base = get_ref_base_and_extent (expr, &poffset, &psize, &pmax_size, &reverse);
1657
1658 if (TREE_CODE (base) == MEM_REF)
1659 {
1660 tree op = TREE_OPERAND (base, 0);
1661 if (TREE_CODE (op) != SSA_NAME
1662 || !SSA_NAME_IS_DEFAULT_DEF (op))
1663 return;
1664 base = SSA_NAME_VAR (op);
1665 if (!base)
1666 return;
1667 deref = true;
1668 }
1669 if (TREE_CODE (base) != PARM_DECL)
1670 return;
1671
1672 gensum_param_desc *desc = get_gensum_param_desc (base);
1673 if (!desc || !desc->split_candidate)
1674 return;
1675
1676 if (!poffset.is_constant (&offset)
1677 || !psize.is_constant (&size)
1678 || !pmax_size.is_constant (&max_size))
1679 {
1680 disqualify_split_candidate (desc, "Encountered a polynomial-sized "
1681 "access.");
1682 return;
1683 }
1684 if (size < 0 || size != max_size)
1685 {
1686 disqualify_split_candidate (desc, "Encountered a variable sized access.");
1687 return;
1688 }
1689 if (TREE_CODE (expr) == COMPONENT_REF
1690 && DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
1691 {
1692 disqualify_split_candidate (desc, "Encountered a bit-field access.");
1693 return;
1694 }
1695 gcc_assert (offset >= 0);
1696 gcc_assert ((offset % BITS_PER_UNIT) == 0);
1697 gcc_assert ((size % BITS_PER_UNIT) == 0);
1698 if ((offset / BITS_PER_UNIT) >= (UINT_MAX - ISRA_ARG_SIZE_LIMIT)
1699 || (size / BITS_PER_UNIT) >= ISRA_ARG_SIZE_LIMIT)
1700 {
1701 disqualify_split_candidate (desc, "Encountered an access with too big "
1702 "offset or size");
1703 return;
1704 }
1705
1706 tree type = TREE_TYPE (expr);
1707 unsigned int exp_align = get_object_alignment (expr);
1708
1709 if (exp_align < TYPE_ALIGN (type))
1710 {
1711 disqualify_split_candidate (desc, "Underaligned access.");
1712 return;
1713 }
1714
1715 if (deref)
1716 {
1717 if (!desc->by_ref)
1718 {
1719 disqualify_split_candidate (desc, "Dereferencing a non-reference.");
1720 return;
1721 }
1722 else if (ctx == ISRA_CTX_STORE)
1723 {
1724 disqualify_split_candidate (desc, "Storing to data passed by "
1725 "reference.");
1726 return;
1727 }
1728
1729 if (!aa_walking_limit)
1730 {
1731 disqualify_split_candidate (desc, "Out of alias analysis step "
1732 "limit.");
1733 return;
1734 }
1735
1736 gcc_checking_assert (gimple_vuse (stmt));
1737 bool maybe_modified = false;
1738 ao_ref ar;
1739
1740 ao_ref_init (&ar, expr);
1741 bitmap visited = BITMAP_ALLOC (NULL);
1742 int walked = walk_aliased_vdefs (&ar, gimple_vuse (stmt),
1743 mark_maybe_modified, &maybe_modified,
1744 &visited, NULL, aa_walking_limit);
1745 BITMAP_FREE (visited);
1746 if (walked > 0)
1747 {
1748 gcc_assert (aa_walking_limit > walked);
1749 aa_walking_limit = aa_walking_limit - walked;
1750 }
1751 if (walked < 0)
1752 aa_walking_limit = 0;
1753 if (maybe_modified || walked < 0)
1754 {
1755 disqualify_split_candidate (desc, "Data passed by reference possibly "
1756 "modified through an alias.");
1757 return;
1758 }
1759 else
1760 mark_param_dereference (desc, offset + size, bb);
1761 }
1762 else
1763 /* Pointer parameters with direct uses should have been ruled out by
1764 analyzing SSA default def when looking at the paremeters. */
1765 gcc_assert (!desc->by_ref);
1766
1767 gensum_param_access *access = get_access (desc, offset, size, ctx);
1768 if (!access)
1769 return;
1770
1771 if (ctx == ISRA_CTX_ARG)
1772 {
1773 gcc_checking_assert (call_info);
1774
1775 if (!deref)
1776 record_nonregister_call_use (desc, call_info, offset / BITS_PER_UNIT,
1777 size / BITS_PER_UNIT);
1778 else
1779 /* This is not a pass-through of a pointer, this is a use like any
1780 other. */
1781 access->nonarg = true;
1782 }
1783
1784 if (!access->type)
1785 {
1786 access->type = type;
1787 access->alias_ptr_type = reference_alias_ptr_type (expr);
1788 access->reverse = reverse;
1789 }
1790 else
1791 {
1792 if (exp_align < TYPE_ALIGN (access->type))
1793 {
1794 disqualify_split_candidate (desc, "Reference has lower alignment "
1795 "than a previous one.");
1796 return;
1797 }
1798 if (access->alias_ptr_type != reference_alias_ptr_type (expr))
1799 {
1800 disqualify_split_candidate (desc, "Multiple alias pointer types.");
1801 return;
1802 }
1803 if (access->reverse != reverse)
1804 {
1805 disqualify_split_candidate (desc, "Both normal and reverse "
1806 "scalar storage order.");
1807 return;
1808 }
1809 if (!deref
1810 && (AGGREGATE_TYPE_P (type) || AGGREGATE_TYPE_P (access->type))
1811 && (TYPE_MAIN_VARIANT (access->type) != TYPE_MAIN_VARIANT (type)))
1812 {
1813 /* We need the same aggregate type on all accesses to be able to
1814 distinguish transformation spots from pass-through arguments in
1815 the transofrmation phase. */
1816 disqualify_split_candidate (desc, "We do not support aggegate "
1817 "type punning.");
1818 return;
1819 }
1820
1821 if (type_prevails_p (access->type, type))
1822 access->type = type;
1823 }
1824}
1825
1826/* Scan body function described by NODE and FUN and create access trees for
1827 parameters. */
1828
1829static void
1830scan_function (cgraph_node *node, struct function *fun)
1831{
1832 basic_block bb;
1833
1834 FOR_EACH_BB_FN (bb, fun)
1835 {
1836 gimple_stmt_iterator gsi;
1837 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1838 {
1839 gimple *stmt = gsi_stmt (gsi);
1840
1841 if (stmt_can_throw_external (fun, stmt))
1842 bitmap_set_bit (final_bbs, bb->index);
1843 switch (gimple_code (stmt))
1844 {
1845 case GIMPLE_RETURN:
1846 {
1847 tree t = gimple_return_retval (as_a <greturn *> (stmt));
1848 if (t != NULL_TREE)
1849 scan_expr_access (t, stmt, ISRA_CTX_LOAD, bb);
1850 bitmap_set_bit (final_bbs, bb->index);
1851 }
1852 break;
1853
1854 case GIMPLE_ASSIGN:
1855 if (gimple_assign_single_p (stmt)
1856 && !gimple_clobber_p (stmt))
1857 {
1858 tree rhs = gimple_assign_rhs1 (stmt);
1859 scan_expr_access (rhs, stmt, ISRA_CTX_LOAD, bb);
1860 tree lhs = gimple_assign_lhs (stmt);
1861 scan_expr_access (lhs, stmt, ISRA_CTX_STORE, bb);
1862 }
1863 break;
1864
1865 case GIMPLE_CALL:
1866 {
1867 unsigned argument_count = gimple_call_num_args (stmt);
1868 scan_call_info call_info;
1869 call_info.cs = node->get_edge (stmt);
1870 call_info.argument_count = argument_count;
1871
1872 for (unsigned i = 0; i < argument_count; i++)
1873 {
1874 call_info.arg_idx = i;
1875 scan_expr_access (gimple_call_arg (stmt, i), stmt,
1876 ISRA_CTX_ARG, bb, &call_info);
1877 }
1878
1879 tree lhs = gimple_call_lhs (stmt);
1880 if (lhs)
1881 scan_expr_access (lhs, stmt, ISRA_CTX_STORE, bb);
1882 int flags = gimple_call_flags (stmt);
1883 if ((flags & (ECF_CONST | ECF_PURE)) == 0)
1884 bitmap_set_bit (final_bbs, bb->index);
1885 }
1886 break;
1887
1888 case GIMPLE_ASM:
1889 {
1890 gasm *asm_stmt = as_a <gasm *> (stmt);
1891 walk_stmt_load_store_addr_ops (asm_stmt, NULL, NULL, NULL,
1892 asm_visit_addr);
1893 bitmap_set_bit (final_bbs, bb->index);
1894
1895 for (unsigned i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
1896 {
1897 tree t = TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
1898 scan_expr_access (t, stmt, ISRA_CTX_LOAD, bb);
1899 }
1900 for (unsigned i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
1901 {
1902 tree t = TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
1903 scan_expr_access (t, stmt, ISRA_CTX_STORE, bb);
1904 }
1905 }
1906 break;
1907
1908 default:
1909 break;
1910 }
1911 }
1912 }
1913}
1914
1915/* Return true if SSA_NAME NAME is only used in return statements, or if
1916 results of any operations it is involved in are only used in return
1917 statements. ANALYZED is a bitmap that tracks which SSA names we have
1918 already started investigating. */
1919
1920static bool
1921ssa_name_only_returned_p (tree name, bitmap analyzed)
1922{
1923 bool res = true;
1924 imm_use_iterator imm_iter;
1925 gimple *stmt;
1926
1927 FOR_EACH_IMM_USE_STMT (stmt, imm_iter, name)
1928 {
1929 if (is_gimple_debug (stmt))
1930 continue;
1931
1932 if (gimple_code (stmt) == GIMPLE_RETURN)
1933 {
1934 tree t = gimple_return_retval (as_a <greturn *> (stmt));
1935 if (t != name)
1936 {
1937 res = false;
1938 BREAK_FROM_IMM_USE_STMT (imm_iter);
1939 }
1940 }
1941 else if ((is_gimple_assign (stmt) && !gimple_has_volatile_ops (stmt))
1942 || gimple_code (stmt) == GIMPLE_PHI)
1943 {
1944 /* TODO: And perhaps for const function calls too? */
1945 tree lhs;
1946 if (gimple_code (stmt) == GIMPLE_PHI)
1947 lhs = gimple_phi_result (stmt);
1948 else
1949 lhs = gimple_assign_lhs (stmt);
1950
1951 if (TREE_CODE (lhs) != SSA_NAME)
1952 {
1953 res = false;
1954 BREAK_FROM_IMM_USE_STMT (imm_iter);
1955 }
1956 gcc_assert (!gimple_vdef (stmt));
1957 if (bitmap_set_bit (analyzed, SSA_NAME_VERSION (lhs))
1958 && !ssa_name_only_returned_p (lhs, analyzed))
1959 {
1960 res = false;
1961 BREAK_FROM_IMM_USE_STMT (imm_iter);
1962 }
1963 }
1964 else
1965 {
1966 res = false;
1967 BREAK_FROM_IMM_USE_STMT (imm_iter);
1968 }
1969 }
1970 return res;
1971}
1972
1973/* Inspect the uses of the return value of the call associated with CS, and if
1974 it is not used or if it is only used to construct the return value of the
1975 caller, mark it as such in call or caller summary. Also check for
1976 misaligned arguments. */
1977
1978static void
1979isra_analyze_call (cgraph_edge *cs)
1980{
1981 gcall *call_stmt = cs->call_stmt;
1982 unsigned count = gimple_call_num_args (call_stmt);
1983 isra_call_summary *csum = call_sums->get_create (cs);
1984
1985 for (unsigned i = 0; i < count; i++)
1986 {
1987 tree arg = gimple_call_arg (call_stmt, i);
1988 if (is_gimple_reg (arg))
1989 continue;
1990
1991 tree offset;
1992 poly_int64 bitsize, bitpos;
1993 machine_mode mode;
1994 int unsignedp, reversep, volatilep = 0;
1995 get_inner_reference (arg, &bitsize, &bitpos, &offset, &mode,
1996 &unsignedp, &reversep, &volatilep);
1997 if (!multiple_p (bitpos, BITS_PER_UNIT))
1998 {
1999 csum->m_bit_aligned_arg = true;
2000 break;
2001 }
2002 }
2003
2004 tree lhs = gimple_call_lhs (call_stmt);
2005 if (lhs)
2006 {
2007 /* TODO: Also detect aggregates on a LHS of a call that are only returned
2008 from this function (without being read anywhere). */
2009 if (TREE_CODE (lhs) == SSA_NAME)
2010 {
2011 bitmap analyzed = BITMAP_ALLOC (NULL);
2012 if (ssa_name_only_returned_p (lhs, analyzed))
2013 csum->m_return_returned = true;
2014 BITMAP_FREE (analyzed);
2015 }
2016 }
2017 else
2018 csum->m_return_ignored = true;
2019}
2020
2021/* Look at all calls going out of NODE, described also by IFS and perform all
2022 analyses necessary for IPA-SRA that are not done at body scan time or done
2023 even when body is not scanned because the function is not a candidate. */
2024
2025static void
2026isra_analyze_all_outgoing_calls (cgraph_node *node)
2027{
2028 for (cgraph_edge *cs = node->callees; cs; cs = cs->next_callee)
2029 isra_analyze_call (cs);
2030 for (cgraph_edge *cs = node->indirect_calls; cs; cs = cs->next_callee)
2031 isra_analyze_call (cs);
2032}
2033
2034/* Dump a dereferences table with heading STR to file F. */
2035
2036static void
2037dump_dereferences_table (FILE *f, struct function *fun, const char *str)
2038{
2039 basic_block bb;
2040
2041 fprintf (dump_file, "%s", str);
2042 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (fun),
2043 EXIT_BLOCK_PTR_FOR_FN (fun), next_bb)
2044 {
2045 fprintf (f, "%4i %i ", bb->index, bitmap_bit_p (final_bbs, bb->index));
2046 if (bb != EXIT_BLOCK_PTR_FOR_FN (fun))
2047 {
2048 int i;
2049 for (i = 0; i < by_ref_count; i++)
2050 {
2051 int idx = bb->index * by_ref_count + i;
2052 fprintf (f, " %4" HOST_WIDE_INT_PRINT "d", bb_dereferences[idx]);
2053 }
2054 }
2055 fprintf (f, "\n");
2056 }
2057 fprintf (dump_file, "\n");
2058}
2059
2060/* Propagate distances in bb_dereferences in the opposite direction than the
2061 control flow edges, in each step storing the maximum of the current value
2062 and the minimum of all successors. These steps are repeated until the table
2063 stabilizes. Note that BBs which might terminate the functions (according to
2064 final_bbs bitmap) never updated in this way. */
2065
2066static void
2067propagate_dereference_distances (struct function *fun)
2068{
2069 basic_block bb;
2070
2071 if (dump_file && (dump_flags & TDF_DETAILS))
2072 dump_dereferences_table (dump_file, fun,
2073 "Dereference table before propagation:\n");
2074
2075 auto_vec<basic_block> queue (last_basic_block_for_fn (fun));
2076 queue.quick_push (ENTRY_BLOCK_PTR_FOR_FN (fun));
2077 FOR_EACH_BB_FN (bb, fun)
2078 {
2079 queue.quick_push (bb);
2080 bb->aux = bb;
2081 }
2082
2083 while (!queue.is_empty ())
2084 {
2085 edge_iterator ei;
2086 edge e;
2087 bool change = false;
2088 int i;
2089
2090 bb = queue.pop ();
2091 bb->aux = NULL;
2092
2093 if (bitmap_bit_p (final_bbs, bb->index))
2094 continue;
2095
2096 for (i = 0; i < by_ref_count; i++)
2097 {
2098 int idx = bb->index * by_ref_count + i;
2099 bool first = true;
2100 HOST_WIDE_INT inh = 0;
2101
2102 FOR_EACH_EDGE (e, ei, bb->succs)
2103 {
2104 int succ_idx = e->dest->index * by_ref_count + i;
2105
2106 if (e->dest == EXIT_BLOCK_PTR_FOR_FN (fun))
2107 continue;
2108
2109 if (first)
2110 {
2111 first = false;
2112 inh = bb_dereferences [succ_idx];
2113 }
2114 else if (bb_dereferences [succ_idx] < inh)
2115 inh = bb_dereferences [succ_idx];
2116 }
2117
2118 if (!first && bb_dereferences[idx] < inh)
2119 {
2120 bb_dereferences[idx] = inh;
2121 change = true;
2122 }
2123 }
2124
2125 if (change)
2126 FOR_EACH_EDGE (e, ei, bb->preds)
2127 {
2128 if (e->src->aux)
2129 continue;
2130
2131 e->src->aux = e->src;
2132 queue.quick_push (e->src);
2133 }
2134 }
2135
2136 if (dump_file && (dump_flags & TDF_DETAILS))
2137 dump_dereferences_table (dump_file, fun,
2138 "Dereference table after propagation:\n");
2139}
2140
2141/* Perform basic checks on ACCESS to PARM described by DESC and all its
2142 children, return true if the parameter cannot be split, otherwise return
2143 true and update *TOTAL_SIZE and *ONLY_CALLS. ENTRY_BB_INDEX must be the
2144 index of the entry BB in the function of PARM. */
2145
2146static bool
2147check_gensum_access (tree parm, gensum_param_desc *desc,
2148 gensum_param_access *access,
2149 HOST_WIDE_INT *nonarg_acc_size, bool *only_calls,
2150 int entry_bb_index)
2151{
2152 if (access->nonarg)
2153 {
2154 *only_calls = false;
2155 *nonarg_acc_size += access->size;
2156
2157 if (access->first_child)
2158 {
2159 disqualify_split_candidate (desc, "Overlapping non-call uses.");
2160 return true;
2161 }
2162 }
2163 /* Do not decompose a non-BLKmode param in a way that would create
2164 BLKmode params. Especially for by-reference passing (thus,
2165 pointer-type param) this is hardly worthwhile. */
2166 if (DECL_MODE (parm) != BLKmode
2167 && TYPE_MODE (access->type) == BLKmode)
2168 {
2169 disqualify_split_candidate (desc, "Would convert a non-BLK to a BLK.");
2170 return true;
2171 }
2172
2173 if (desc->by_ref)
2174 {
2175 int idx = (entry_bb_index * by_ref_count + desc->deref_index);
2176 if ((access->offset + access->size) > bb_dereferences[idx])
2177 {
2178 disqualify_split_candidate (desc, "Would create a possibly "
2179 "illegal dereference in a caller.");
2180 return true;
2181 }
2182 }
2183
2184 for (gensum_param_access *ch = access->first_child;
2185 ch;
2186 ch = ch->next_sibling)
2187 if (check_gensum_access (parm, desc, ch, nonarg_acc_size, only_calls,
2188 entry_bb_index))
2189 return true;
2190
2191 return false;
2192}
2193
2194/* Copy data from FROM and all of its children to a vector of accesses in IPA
2195 descriptor DESC. */
2196
2197static void
2198copy_accesses_to_ipa_desc (gensum_param_access *from, isra_param_desc *desc)
2199{
2200 param_access *to = ggc_cleared_alloc<param_access> ();
2201 gcc_checking_assert ((from->offset % BITS_PER_UNIT) == 0);
2202 gcc_checking_assert ((from->size % BITS_PER_UNIT) == 0);
2203 to->unit_offset = from->offset / BITS_PER_UNIT;
2204 to->unit_size = from->size / BITS_PER_UNIT;
2205 to->type = from->type;
2206 to->alias_ptr_type = from->alias_ptr_type;
2207 to->certain = from->nonarg;
2208 to->reverse = from->reverse;
2209 vec_safe_push (desc->accesses, to);
2210
2211 for (gensum_param_access *ch = from->first_child;
2212 ch;
2213 ch = ch->next_sibling)
2214 copy_accesses_to_ipa_desc (ch, desc);
2215}
2216
2217/* Analyze function body scan results stored in param_accesses and
2218 param_accesses, detect possible transformations and store information of
2219 those in function summary. NODE, FUN and IFS are all various structures
2220 describing the currently analyzed function. */
2221
2222static void
2223process_scan_results (cgraph_node *node, struct function *fun,
2224 isra_func_summary *ifs,
2225 vec<gensum_param_desc> *param_descriptions)
2226{
2227 bool check_pass_throughs = false;
2228 bool dereferences_propagated = false;
2229 tree parm = DECL_ARGUMENTS (node->decl);
2230 unsigned param_count = param_descriptions->length();
2231
2232 for (unsigned desc_index = 0;
2233 desc_index < param_count;
2234 desc_index++, parm = DECL_CHAIN (parm))
2235 {
2236 gensum_param_desc *desc = &(*param_descriptions)[desc_index];
2237 if (!desc->locally_unused && !desc->split_candidate)
2238 continue;
2239
2240 if (flag_checking)
2241 isra_verify_access_tree (desc->accesses);
2242
2243 if (!dereferences_propagated
2244 && desc->by_ref
2245 && desc->accesses)
2246 {
2247 propagate_dereference_distances (fun);
2248 dereferences_propagated = true;
2249 }
2250
2251 HOST_WIDE_INT nonarg_acc_size = 0;
2252 bool only_calls = true;
2253 bool check_failed = false;
2254
2255 int entry_bb_index = ENTRY_BLOCK_PTR_FOR_FN (fun)->index;
2256 for (gensum_param_access *acc = desc->accesses;
2257 acc;
2258 acc = acc->next_sibling)
2259 if (check_gensum_access (parm, desc, acc, &nonarg_acc_size, &only_calls,
2260 entry_bb_index))
2261 {
2262 check_failed = true;
2263 break;
2264 }
2265 if (check_failed)
2266 continue;
2267
2268 if (only_calls)
2269 desc->locally_unused = true;
2270
2271 HOST_WIDE_INT cur_param_size
2272 = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (parm)));
2273 HOST_WIDE_INT param_size_limit;
2274 if (!desc->by_ref || optimize_function_for_size_p (fun))
2275 param_size_limit = cur_param_size;
2276 else
2277 param_size_limit = (PARAM_VALUE (PARAM_IPA_SRA_PTR_GROWTH_FACTOR)
2278 * cur_param_size);
2279 if (nonarg_acc_size > param_size_limit
2280 || (!desc->by_ref && nonarg_acc_size == param_size_limit))
2281 {
2282 disqualify_split_candidate (desc, "Would result into a too big set of"
2283 "replacements.");
2284 }
2285 else
2286 {
2287 /* create_parameter_descriptors makes sure unit sizes of all
2288 candidate parameters fit unsigned integers restricted to
2289 ISRA_ARG_SIZE_LIMIT. */
2290 desc->param_size_limit = param_size_limit / BITS_PER_UNIT;
2291 desc->nonarg_acc_size = nonarg_acc_size / BITS_PER_UNIT;
2292 if (desc->split_candidate && desc->ptr_pt_count)
2293 {
2294 gcc_assert (desc->by_ref);
2295 check_pass_throughs = true;
2296 }
2297 }
2298 }
2299
2300 /* When a pointer parameter is passed-through to a callee, in which it is
2301 only used to read only one or a few items, we can attempt to transform it
2302 to obtaining and passing through the items instead of the pointer. But we
2303 must take extra care that 1) we do not introduce any segfault by moving
2304 dereferences above control flow and that 2) the data is not modified
2305 through an alias in this function. The IPA analysis must not introduce
2306 any accesses candidates unless it can prove both.
2307
2308 The current solution is very crude as it consists of ensuring that the
2309 call postdominates entry BB and that the definition of VUSE of the call is
2310 default definition. TODO: For non-recursive callees in the same
2311 compilation unit we could do better by doing analysis in topological order
2312 an looking into access candidates of callees, using their alias_ptr_types
2313 to attempt real AA. We could also use the maximum known dereferenced
2314 offset in this function at IPA level.
2315
2316 TODO: Measure the overhead and the effect of just being pessimistic.
2317 Maybe this is ony -O3 material?
2318 */
2319 bool pdoms_calculated = false;
2320 if (check_pass_throughs)
2321 for (cgraph_edge *cs = node->callees; cs; cs = cs->next_callee)
2322 {
2323 gcall *call_stmt = cs->call_stmt;
2324 tree vuse = gimple_vuse (call_stmt);
2325
2326 /* If the callee is a const function, we don't get a VUSE. In such
2327 case there will be no memory accesses in the called function (or the
2328 const attribute is wrong) and then we just don't care. */
2329 bool uses_memory_as_obtained = vuse && SSA_NAME_IS_DEFAULT_DEF (vuse);
2330
2331 unsigned count = gimple_call_num_args (call_stmt);
2332 isra_call_summary *csum = call_sums->get_create (cs);
2333 csum->init_inputs (count);
2334 for (unsigned argidx = 0; argidx < count; argidx++)
2335 {
2336 if (!csum->m_arg_flow[argidx].pointer_pass_through)
2337 continue;
2338 unsigned pidx
2339 = get_single_param_flow_source (&csum->m_arg_flow[argidx]);
2340 gensum_param_desc *desc = &(*param_descriptions)[pidx];
2341 if (!desc->split_candidate)
2342 {
2343 csum->m_arg_flow[argidx].pointer_pass_through = false;
2344 continue;
2345 }
2346 if (!uses_memory_as_obtained)
2347 continue;
2348
2349 /* Post-dominator check placed last, hoping that it usually won't
2350 be needed. */
2351 if (!pdoms_calculated)
2352 {
2353 gcc_checking_assert (cfun);
2354 add_noreturn_fake_exit_edges ();
2355 connect_infinite_loops_to_exit ();
2356 calculate_dominance_info (CDI_POST_DOMINATORS);
2357 pdoms_calculated = true;
2358 }
2359 if (dominated_by_p (CDI_POST_DOMINATORS,
2360 gimple_bb (call_stmt),
2361 single_succ (ENTRY_BLOCK_PTR_FOR_FN (fun))))
2362 csum->m_arg_flow[argidx].safe_to_import_accesses = true;
2363 }
2364
2365 }
2366 if (pdoms_calculated)
2367 {
2368 free_dominance_info (CDI_POST_DOMINATORS);
2369 remove_fake_exit_edges ();
2370 }
2371
2372 /* TODO: Add early exit if we disqualified everything. This also requires
2373 that we either relax the restriction that
2374 ipa_param_adjustments.m_always_copy_start mut be the number of PARM_DECLs
2375 or store the number of parameters to IPA-SRA function summary and use that
2376 when just removing params. */
2377
2378 vec_safe_reserve_exact (ifs->m_parameters, param_count);
2379 ifs->m_parameters->quick_grow_cleared (param_count);
2380 for (unsigned desc_index = 0; desc_index < param_count; desc_index++)
2381 {
2382 gensum_param_desc *s = &(*param_descriptions)[desc_index];
2383 isra_param_desc *d = &(*ifs->m_parameters)[desc_index];
2384
2385 d->param_size_limit = s->param_size_limit;
2386 d->size_reached = s->nonarg_acc_size;
2387 d->locally_unused = s->locally_unused;
2388 d->split_candidate = s->split_candidate;
2389 d->by_ref = s->by_ref;
2390
2391 for (gensum_param_access *acc = s->accesses;
2392 acc;
2393 acc = acc->next_sibling)
2394 copy_accesses_to_ipa_desc (acc, d);
2395 }
2396
2397 if (dump_file)
2398 dump_isra_param_descriptors (dump_file, node->decl, ifs);
2399}
2400
2401/* Return true if there are any overlaps among certain accesses of DESC. If
2402 non-NULL, set *CERTAIN_ACCESS_PRESENT_P upon encountering a certain accesss
2403 too. DESC is assumed to be a split candidate that is not locally
2404 unused. */
2405
2406static bool
2407overlapping_certain_accesses_p (isra_param_desc *desc,
2408 bool *certain_access_present_p)
2409{
2410 unsigned pclen = vec_safe_length (desc->accesses);
2411 for (unsigned i = 0; i < pclen; i++)
2412 {
2413 param_access *a1 = (*desc->accesses)[i];
2414
2415 if (!a1->certain)
2416 continue;
2417 if (certain_access_present_p)
2418 *certain_access_present_p = true;
2419 for (unsigned j = i + 1; j < pclen; j++)
2420 {
2421 param_access *a2 = (*desc->accesses)[j];
2422 if (a2->certain
2423 && a1->unit_offset < a2->unit_offset + a2->unit_size
2424 && a1->unit_offset + a1->unit_size > a2->unit_offset)
2425 return true;
2426 }
2427 }
2428 return false;
2429}
2430
2431/* Check for any overlaps of certain param accesses among splitting candidates
2432 and signal an ICE if there are any. If CERTAIN_MUST_EXIST is set, also
2433 check that used splitting candidates have at least one certain access. */
2434
2435static void
2436verify_splitting_accesses (cgraph_node *node, bool certain_must_exist)
2437{
2438 isra_func_summary *ifs = func_sums->get (node);
2439 if (!ifs || !ifs->m_candidate)
2440 return;
2441 unsigned param_count = vec_safe_length (ifs->m_parameters);
2442 for (unsigned pidx = 0; pidx < param_count; pidx++)
2443 {
2444 isra_param_desc *desc = &(*ifs->m_parameters)[pidx];
2445 if (!desc->split_candidate || desc->locally_unused)
2446 continue;
2447
2448 bool certain_access_present = !certain_must_exist;
2449 if (overlapping_certain_accesses_p (desc, &certain_access_present))
2450 internal_error ("Function %s, parameter %u, has IPA_SRA accesses "
2451 "which overlap", node->dump_name (), pidx);
2452 if (!certain_access_present)
2453 internal_error ("Function %s, parameter %u, is used but does not "
2454 "have any certain IPA-SRA access",
2455 node->dump_name (), pidx);
2456 }
2457}
2458
2459/* Intraprocedural part of IPA-SRA analysis. Scan function body of NODE and
2460 create a summary structure describing IPA-SRA opportunities and constraints
2461 in it. */
2462
2463static void
2464ipa_sra_summarize_function (cgraph_node *node)
2465{
2466 if (dump_file)
2467 fprintf (dump_file, "Creating summary for %s/%i:\n", node->name (),
2468 node->order);
2469 if (!ipa_sra_preliminary_function_checks (node))
2470 return;
2471 gcc_obstack_init (&gensum_obstack);
2472 isra_func_summary *ifs = func_sums->get_create (node);
2473 ifs->m_candidate = true;
2474 tree ret = TREE_TYPE (TREE_TYPE (node->decl));
2475 ifs->m_returns_value = (TREE_CODE (ret) != VOID_TYPE);
2476
2477 decl2desc = new hash_map<tree, gensum_param_desc *>;
2478 unsigned count = 0;
2479 for (tree parm = DECL_ARGUMENTS (node->decl); parm; parm = DECL_CHAIN (parm))
2480 count++;
2481
2482 if (count > 0)
2483 {
2484 auto_vec<gensum_param_desc, 16> param_descriptions (count);
2485 param_descriptions.reserve_exact (count);
2486 param_descriptions.quick_grow_cleared (count);
2487
2488 bool cfun_pushed = false;
2489 struct function *fun = DECL_STRUCT_FUNCTION (node->decl);
2490 if (create_parameter_descriptors (node, &param_descriptions))
2491 {
2492 push_cfun (fun);
2493 cfun_pushed = true;
2494 final_bbs = BITMAP_ALLOC (NULL);
2495 bb_dereferences = XCNEWVEC (HOST_WIDE_INT,
2496 by_ref_count
2497 * last_basic_block_for_fn (fun));
2498 aa_walking_limit = PARAM_VALUE (PARAM_IPA_MAX_AA_STEPS);
2499 scan_function (node, fun);
2500
2501 if (dump_file)
2502 {
2503 dump_gensum_param_descriptors (dump_file, node->decl,
2504 &param_descriptions);
2505 fprintf (dump_file, "----------------------------------------\n");
2506 }
2507 }
2508 process_scan_results (node, fun, ifs, &param_descriptions);
2509
2510 if (cfun_pushed)
2511 pop_cfun ();
2512 if (bb_dereferences)
2513 {
2514 free (bb_dereferences);
2515 bb_dereferences = NULL;
2516 BITMAP_FREE (final_bbs);
2517 final_bbs = NULL;
2518 }
2519 }
2520 isra_analyze_all_outgoing_calls (node);
2521
2522 delete decl2desc;
2523 decl2desc = NULL;
2524 obstack_free (&gensum_obstack, NULL);
2525 if (dump_file)
2526 fprintf (dump_file, "\n\n");
2527 if (flag_checking)
2528 verify_splitting_accesses (node, false);
2529 return;
2530}
2531
2532/* Intraprocedural part of IPA-SRA analysis. Scan bodies of all functions in
2533 this compilation unit and create summary structures describing IPA-SRA
2534 opportunities and constraints in them. */
2535
2536static void
2537ipa_sra_generate_summary (void)
2538{
2539 struct cgraph_node *node;
2540
2541 gcc_checking_assert (!func_sums);
2542 gcc_checking_assert (!call_sums);
2543 func_sums
2544 = (new (ggc_cleared_alloc <ipa_sra_function_summaries> ())
2545 ipa_sra_function_summaries (symtab, true));
2546 call_sums = new ipa_sra_call_summaries (symtab);
2547
2548 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
2549 ipa_sra_summarize_function (node);
2550 return;
2551}
2552
2553/* Write intraproceural analysis information about E and all of its outgoing
2554 edges into a stream for LTO WPA. */
2555
2556static void
2557isra_write_edge_summary (output_block *ob, cgraph_edge *e)
2558{
2559 isra_call_summary *csum = call_sums->get (e);
2560 unsigned input_count = csum->m_arg_flow.length ();
2561 streamer_write_uhwi (ob, input_count);
2562 for (unsigned i = 0; i < input_count; i++)
2563 {
2564 isra_param_flow *ipf = &csum->m_arg_flow[i];
2565 streamer_write_hwi (ob, ipf->length);
2566 bitpack_d bp = bitpack_create (ob->main_stream);
2567 for (int j = 0; j < ipf->length; j++)
2568 bp_pack_value (&bp, ipf->inputs[j], 8);
2569 bp_pack_value (&bp, ipf->aggregate_pass_through, 1);
2570 bp_pack_value (&bp, ipf->pointer_pass_through, 1);
2571 bp_pack_value (&bp, ipf->safe_to_import_accesses, 1);
2572 streamer_write_bitpack (&bp);
2573 streamer_write_uhwi (ob, ipf->unit_offset);
2574 streamer_write_uhwi (ob, ipf->unit_size);
2575 }
2576 bitpack_d bp = bitpack_create (ob->main_stream);
2577 bp_pack_value (&bp, csum->m_return_ignored, 1);
2578 bp_pack_value (&bp, csum->m_return_returned, 1);
2579 bp_pack_value (&bp, csum->m_bit_aligned_arg, 1);
2580 streamer_write_bitpack (&bp);
2581}
2582
2583/* Write intraproceural analysis information about NODE and all of its outgoing
2584 edges into a stream for LTO WPA. */
2585
2586static void
2587isra_write_node_summary (output_block *ob, cgraph_node *node)
2588{
2589 isra_func_summary *ifs = func_sums->get (node);
2590 lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
2591 int node_ref = lto_symtab_encoder_encode (encoder, node);
2592 streamer_write_uhwi (ob, node_ref);
2593
2594 unsigned param_desc_count = vec_safe_length (ifs->m_parameters);
2595 streamer_write_uhwi (ob, param_desc_count);
2596 for (unsigned i = 0; i < param_desc_count; i++)
2597 {
2598 isra_param_desc *desc = &(*ifs->m_parameters)[i];
2599 unsigned access_count = vec_safe_length (desc->accesses);
2600 streamer_write_uhwi (ob, access_count);
2601 for (unsigned j = 0; j < access_count; j++)
2602 {
2603 param_access *acc = (*desc->accesses)[j];
2604 stream_write_tree (ob, acc->type, true);
2605 stream_write_tree (ob, acc->alias_ptr_type, true);
2606 streamer_write_uhwi (ob, acc->unit_offset);
2607 streamer_write_uhwi (ob, acc->unit_size);
2608 bitpack_d bp = bitpack_create (ob->main_stream);
2609 bp_pack_value (&bp, acc->certain, 1);
2610 streamer_write_bitpack (&bp);
2611 }
2612 streamer_write_uhwi (ob, desc->param_size_limit);
2613 streamer_write_uhwi (ob, desc->size_reached);
2614 bitpack_d bp = bitpack_create (ob->main_stream);
2615 bp_pack_value (&bp, desc->locally_unused, 1);
2616 bp_pack_value (&bp, desc->split_candidate, 1);
2617 bp_pack_value (&bp, desc->by_ref, 1);
2618 streamer_write_bitpack (&bp);
2619 }
2620 bitpack_d bp = bitpack_create (ob->main_stream);
2621 bp_pack_value (&bp, ifs->m_candidate, 1);
2622 bp_pack_value (&bp, ifs->m_returns_value, 1);
2623 bp_pack_value (&bp, ifs->m_return_ignored, 1);
2624 gcc_assert (!ifs->m_queued);
2625 streamer_write_bitpack (&bp);
2626
2627 for (cgraph_edge *e = node->callees; e; e = e->next_callee)
2628 isra_write_edge_summary (ob, e);
2629 for (cgraph_edge *e = node->indirect_calls; e; e = e->next_callee)
2630 isra_write_edge_summary (ob, e);
2631}
2632
2633/* Write intraproceural analysis information into a stream for LTO WPA. */
2634
2635static void
2636ipa_sra_write_summary (void)
2637{
2638 if (!func_sums || !call_sums)
2639 return;
2640
2641 struct output_block *ob = create_output_block (LTO_section_ipa_sra);
2642 lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
2643 ob->symbol = NULL;
2644
2645 unsigned int count = 0;
2646 lto_symtab_encoder_iterator lsei;
2647 for (lsei = lsei_start_function_in_partition (encoder);
2648 !lsei_end_p (lsei);
2649 lsei_next_function_in_partition (&lsei))
2650 {
2651 cgraph_node *node = lsei_cgraph_node (lsei);
2652 if (node->has_gimple_body_p ()
2653 && func_sums->get (node) != NULL)
2654 count++;
2655 }
2656 streamer_write_uhwi (ob, count);
2657
2658 /* Process all of the functions. */
2659 for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
2660 lsei_next_function_in_partition (&lsei))
2661 {
2662 cgraph_node *node = lsei_cgraph_node (lsei);
2663 if (node->has_gimple_body_p ()
2664 && func_sums->get (node) != NULL)
2665 isra_write_node_summary (ob, node);
2666 }
2667 streamer_write_char_stream (ob->main_stream, 0);
2668 produce_asm (ob, NULL);
2669 destroy_output_block (ob);
2670}
2671
2672/* Read intraproceural analysis information about E and all of its outgoing
2673 edges into a stream for LTO WPA. */
2674
2675static void
2676isra_read_edge_summary (struct lto_input_block *ib, cgraph_edge *cs)
2677{
2678 isra_call_summary *csum = call_sums->get_create (cs);
2679 unsigned input_count = streamer_read_uhwi (ib);
2680 csum->init_inputs (input_count);
2681 for (unsigned i = 0; i < input_count; i++)
2682 {
2683 isra_param_flow *ipf = &csum->m_arg_flow[i];
2684 ipf->length = streamer_read_hwi (ib);
2685 bitpack_d bp = streamer_read_bitpack (ib);
2686 for (int j = 0; j < ipf->length; j++)
2687 ipf->inputs[j] = bp_unpack_value (&bp, 8);
2688 ipf->aggregate_pass_through = bp_unpack_value (&bp, 1);
2689 ipf->pointer_pass_through = bp_unpack_value (&bp, 1);
2690 ipf->safe_to_import_accesses = bp_unpack_value (&bp, 1);
2691 ipf->unit_offset = streamer_read_uhwi (ib);
2692 ipf->unit_size = streamer_read_uhwi (ib);
2693 }
2694 bitpack_d bp = streamer_read_bitpack (ib);
2695 csum->m_return_ignored = bp_unpack_value (&bp, 1);
2696 csum->m_return_returned = bp_unpack_value (&bp, 1);
2697 csum->m_bit_aligned_arg = bp_unpack_value (&bp, 1);
2698}
2699
2700/* Read intraproceural analysis information about NODE and all of its outgoing
2701 edges into a stream for LTO WPA. */
2702
2703static void
2704isra_read_node_info (struct lto_input_block *ib, cgraph_node *node,
2705 struct data_in *data_in)
2706{
2707 isra_func_summary *ifs = func_sums->get_create (node);
2708 unsigned param_desc_count = streamer_read_uhwi (ib);
2709 if (param_desc_count > 0)
2710 {
2711 vec_safe_reserve_exact (ifs->m_parameters, param_desc_count);
2712 ifs->m_parameters->quick_grow_cleared (param_desc_count);
2713 }
2714 for (unsigned i = 0; i < param_desc_count; i++)
2715 {
2716 isra_param_desc *desc = &(*ifs->m_parameters)[i];
2717 unsigned access_count = streamer_read_uhwi (ib);
2718 for (unsigned j = 0; j < access_count; j++)
2719 {
2720 param_access *acc = ggc_cleared_alloc<param_access> ();
2721 acc->type = stream_read_tree (ib, data_in);
2722 acc->alias_ptr_type = stream_read_tree (ib, data_in);
2723 acc->unit_offset = streamer_read_uhwi (ib);
2724 acc->unit_size = streamer_read_uhwi (ib);
2725 bitpack_d bp = streamer_read_bitpack (ib);
2726 acc->certain = bp_unpack_value (&bp, 1);
2727 vec_safe_push (desc->accesses, acc);
2728 }
2729 desc->param_size_limit = streamer_read_uhwi (ib);
2730 desc->size_reached = streamer_read_uhwi (ib);
2731 bitpack_d bp = streamer_read_bitpack (ib);
2732 desc->locally_unused = bp_unpack_value (&bp, 1);
2733 desc->split_candidate = bp_unpack_value (&bp, 1);
2734 desc->by_ref = bp_unpack_value (&bp, 1);
2735 }
2736 bitpack_d bp = streamer_read_bitpack (ib);
2737 ifs->m_candidate = bp_unpack_value (&bp, 1);
2738 ifs->m_returns_value = bp_unpack_value (&bp, 1);
2739 ifs->m_return_ignored = bp_unpack_value (&bp, 1);
2740 ifs->m_queued = 0;
2741
2742 for (cgraph_edge *e = node->callees; e; e = e->next_callee)
2743 isra_read_edge_summary (ib, e);
2744 for (cgraph_edge *e = node->indirect_calls; e; e = e->next_callee)
2745 isra_read_edge_summary (ib, e);
2746}
2747
2748/* Read IPA-SRA summaries from a section in file FILE_DATA of length LEN with
2749 data DATA. TODO: This function was copied almost verbatim from ipa-prop.c,
2750 it should be possible to unify them somehow. */
2751
2752static void
2753isra_read_summary_section (struct lto_file_decl_data *file_data,
2754 const char *data, size_t len)
2755{
2756 const struct lto_function_header *header =
2757 (const struct lto_function_header *) data;
2758 const int cfg_offset = sizeof (struct lto_function_header);
2759 const int main_offset = cfg_offset + header->cfg_size;
2760 const int string_offset = main_offset + header->main_size;
2761 struct data_in *data_in;
2762 unsigned int i;
2763 unsigned int count;
2764
2765 lto_input_block ib_main ((const char *) data + main_offset,
2766 header->main_size, file_data->mode_table);
2767
2768 data_in =
2769 lto_data_in_create (file_data, (const char *) data + string_offset,
2770 header->string_size, vNULL);
2771 count = streamer_read_uhwi (&ib_main);
2772
2773 for (i = 0; i < count; i++)
2774 {
2775 unsigned int index;
2776 struct cgraph_node *node;
2777 lto_symtab_encoder_t encoder;
2778
2779 index = streamer_read_uhwi (&ib_main);
2780 encoder = file_data->symtab_node_encoder;
2781 node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref (encoder,
2782 index));
2783 gcc_assert (node->definition);
2784 isra_read_node_info (&ib_main, node, data_in);
2785 }
2786 lto_free_section_data (file_data, LTO_section_ipa_sra, NULL, data,
2787 len);
2788 lto_data_in_delete (data_in);
2789}
2790
2791/* Read intraproceural analysis information into a stream for LTO WPA. */
2792
2793static void
2794ipa_sra_read_summary (void)
2795{
2796 struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
2797 struct lto_file_decl_data *file_data;
2798 unsigned int j = 0;
2799
2800 gcc_checking_assert (!func_sums);
2801 gcc_checking_assert (!call_sums);
2802 func_sums
2803 = (new (ggc_cleared_alloc <ipa_sra_function_summaries> ())
2804 ipa_sra_function_summaries (symtab, true));
2805 call_sums = new ipa_sra_call_summaries (symtab);
2806
2807 while ((file_data = file_data_vec[j++]))
2808 {
2809 size_t len;
2810 const char *data = lto_get_section_data (file_data, LTO_section_ipa_sra,
2811 NULL, &len);
2812 if (data)
2813 isra_read_summary_section (file_data, data, len);
2814 }
2815}
2816
2817/* Dump all IPA-SRA summary data for all cgraph nodes and edges to file F. */
2818
2819static void
2820ipa_sra_dump_all_summaries (FILE *f)
2821{
2822 cgraph_node *node;
2823 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
2824 {
2825 fprintf (f, "\nSummary for node %s:\n", node->dump_name ());
2826
2827 isra_func_summary *ifs = func_sums->get (node);
2828 if (!ifs)
2829 {
2830 fprintf (f, " Function does not have any associated IPA-SRA "
2831 "summary\n");
2832 continue;
2833 }
2834 if (!ifs->m_candidate)
2835 {
2836 fprintf (f, " Not a candidate function\n");
2837 continue;
2838 }
2839 if (ifs->m_returns_value)
2840 fprintf (f, " Returns value\n");
2841 if (vec_safe_is_empty (ifs->m_parameters))
2842 fprintf (f, " No parameter information. \n");
2843 else
2844 for (unsigned i = 0; i < ifs->m_parameters->length (); ++i)
2845 {
2846 fprintf (f, " Descriptor for parameter %i:\n", i);
2847 dump_isra_param_descriptor (f, &(*ifs->m_parameters)[i]);
2848 }
2849 fprintf (f, "\n");
2850
2851 struct cgraph_edge *cs;
2852 for (cs = node->callees; cs; cs = cs->next_callee)
2853 {
2854 fprintf (f, " Summary for edge %s->%s:\n", cs->caller->dump_name (),
2855 cs->callee->dump_name ());
2856 isra_call_summary *csum = call_sums->get (cs);
2857 if (csum)
2858 csum->dump (f);
2859 else
2860 fprintf (f, " Call summary is MISSING!\n");
2861 }
2862
2863 }
2864 fprintf (f, "\n\n");
2865}
2866
2867/* Perform function-scope viability tests that can be only made at IPA level
2868 and return false if the function is deemed unsuitable for IPA-SRA. */
2869
2870static bool
2871ipa_sra_ipa_function_checks (cgraph_node *node)
2872{
2873 if (!node->can_be_local_p ())
2874 {
2875 if (dump_file)
2876 fprintf (dump_file, "Function %s disqualified because it cannot be "
2877 "made local.\n", node->dump_name ());
2878 return false;
2879 }
2880 if (!node->local.can_change_signature)
2881 {
2882 if (dump_file)
2883 fprintf (dump_file, "Function can not change signature.\n");
2884 return false;
2885 }
2886
2887 return true;
2888}
2889
2890/* Issues found out by check_callers_for_issues. */
2891
2892struct caller_issues
2893{
2894 /* There is a thunk among callers. */
2895 bool thunk;
2896 /* Call site with no available information. */
2897 bool unknown_callsite;
2898 /* There is a bit-aligned load into one of non-gimple-typed arguments. */
2899 bool bit_aligned_aggregate_argument;
2900};
2901
2902/* Worker for call_for_symbol_and_aliases, set any flags of passed caller_issues
2903 that apply. */
2904
2905static bool
2906check_for_caller_issues (struct cgraph_node *node, void *data)
2907{
2908 struct caller_issues *issues = (struct caller_issues *) data;
2909
2910 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
2911 {
2912 if (cs->caller->thunk.thunk_p)
2913 {
2914 issues->thunk = true;
2915 /* TODO: We should be able to process at least some types of
2916 thunks. */
2917 return true;
2918 }
2919
2920 isra_call_summary *csum = call_sums->get (cs);
2921 if (!csum)
2922 {
2923 issues->unknown_callsite = true;
2924 return true;
2925 }
2926
2927 if (csum->m_bit_aligned_arg)
2928 issues->bit_aligned_aggregate_argument = true;
2929 }
2930 return false;
2931}
2932
2933/* Look at all incoming edges to NODE, including aliases and thunks and look
2934 for problems. Return true if NODE type should not be modified at all. */
2935
2936static bool
2937check_all_callers_for_issues (cgraph_node *node)
2938{
2939 struct caller_issues issues;
2940 memset (&issues, 0, sizeof (issues));
2941
2942 node->call_for_symbol_and_aliases (check_for_caller_issues, &issues, true);
2943 if (issues.unknown_callsite)
2944 {
2945 if (dump_file && (dump_flags & TDF_DETAILS))
2946 fprintf (dump_file, "A call of %s has not been analyzed. Disabling "
2947 "all modifications.\n", node->dump_name ());
2948 return true;
2949 }
2950 /* TODO: We should be able to process at least some types of thunks. */
2951 if (issues.thunk)
2952 {
2953 if (dump_file && (dump_flags & TDF_DETAILS))
2954 fprintf (dump_file, "A call of %s is through thunk, which are not"
2955 " handled yet. Disabling all modifications.\n",
2956 node->dump_name ());
2957 return true;
2958 }
2959
2960 if (issues.bit_aligned_aggregate_argument)
2961 {
2962 /* Let's only remove parameters/return values from such functions.
2963 TODO: We could only prevent splitting the problematic parameters if
2964 anybody thinks it is worth it. */
2965 if (dump_file && (dump_flags & TDF_DETAILS))
2966 fprintf (dump_file, "A call of %s has bit-alinged aggregate argument,"
2967 " disabling parameter splitting.\n", node->dump_name ());
2968
2969 isra_func_summary *ifs = func_sums->get (node);
2970 gcc_checking_assert (ifs);
2971 unsigned param_count = vec_safe_length (ifs->m_parameters);
2972 for (unsigned i = 0; i < param_count; i++)
2973 (*ifs->m_parameters)[i].split_candidate = false;
2974 }
2975 return false;
2976}
2977
2978/* Find the access with corresponding OFFSET and SIZE among accesses in
2979 PARAM_DESC and return it or NULL if such an access is not there. */
2980
2981static param_access *
2982find_param_access (isra_param_desc *param_desc, unsigned offset, unsigned size)
2983{
2984 unsigned pclen = vec_safe_length (param_desc->accesses);
2985
2986 /* The search is linear but the number of stored accesses is bound by
2987 PARAM_IPA_SRA_MAX_REPLACEMENTS, so most probably 8. */
2988
2989 for (unsigned i = 0; i < pclen; i++)
2990 if ((*param_desc->accesses)[i]->unit_offset == offset
2991 && (*param_desc->accesses)[i]->unit_size == size)
2992 return (*param_desc->accesses)[i];
2993
2994 return NULL;
2995}
2996
2997/* Return iff the total size of definite replacement SIZE would violate the
2998 limit set for it in PARAM. */
2999
3000static bool
3001size_would_violate_limit_p (isra_param_desc *desc, unsigned size)
3002{
3003 unsigned limit = desc->param_size_limit;
3004 if (size > limit
3005 || (!desc->by_ref && size == limit))
3006 return true;
3007 return false;
3008}
3009
3010/* Increase reached size of DESC by SIZE or disqualify it if it would violate
3011 the set limit. IDX is the parameter number which is dumped when
3012 disqualifying. */
3013
3014static void
3015bump_reached_size (isra_param_desc *desc, unsigned size, unsigned idx)
3016{
3017 unsigned after = desc->size_reached + size;
3018 if (size_would_violate_limit_p (desc, after))
3019 {
3020 if (dump_file && (dump_flags & TDF_DETAILS))
3021 fprintf (dump_file, " ...size limit reached, disqualifying "
3022 "candidate parameter %u\n", idx);
3023 desc->split_candidate = false;
3024 return;
3025 }
3026 desc->size_reached = after;
3027}
3028
3029/* Take all actions required to deal with an edge CS that represents a call to
3030 an unknown or un-analyzed function, for both parameter removal and
3031 splitting. */
3032
3033static void
3034process_edge_to_unknown_caller (cgraph_edge *cs)
3035{
3036 isra_func_summary *from_ifs = func_sums->get (cs->caller);
3037 gcc_checking_assert (from_ifs);
3038 isra_call_summary *csum = call_sums->get (cs);
3039
3040 if (dump_file && (dump_flags & TDF_DETAILS))
3041 fprintf (dump_file, "Processing an edge to an unknown caller from %s:\n",
3042 cs->caller->dump_name ());
3043
3044 unsigned args_count = csum->m_arg_flow.length ();
3045 for (unsigned i = 0; i < args_count; i++)
3046 {
3047 isra_param_flow *ipf = &csum->m_arg_flow[i];
3048
3049 if (ipf->pointer_pass_through)
3050 {
3051 isra_param_desc *param_desc
3052 = &(*from_ifs->m_parameters)[get_single_param_flow_source (ipf)];
3053 param_desc->locally_unused = false;
3054 param_desc->split_candidate = false;
3055 continue;
3056 }
3057 if (ipf->aggregate_pass_through)
3058 {
3059 unsigned idx = get_single_param_flow_source (ipf);
3060 isra_param_desc *param_desc = &(*from_ifs->m_parameters)[idx];
3061
3062 param_desc->locally_unused = false;
3063 if (!param_desc->split_candidate)
3064 continue;
3065 gcc_assert (!param_desc->by_ref);
3066 param_access *pacc = find_param_access (param_desc, ipf->unit_offset,
3067 ipf->unit_size);
3068 gcc_checking_assert (pacc);
3069 pacc->certain = true;
3070 if (overlapping_certain_accesses_p (param_desc, NULL))
3071 {
3072 if (dump_file && (dump_flags & TDF_DETAILS))
3073 fprintf (dump_file, " ...leading to overlap, "
3074 " disqualifying candidate parameter %u\n",
3075 idx);
3076 param_desc->split_candidate = false;
3077 }
3078 else
3079 bump_reached_size (param_desc, pacc->unit_size, idx);
3080 ipf->aggregate_pass_through = false;
3081 continue;
3082 }
3083
3084 for (int j = 0; j < ipf->length; j++)
3085 {
3086 int input_idx = ipf->inputs[j];
3087 (*from_ifs->m_parameters)[input_idx].locally_unused = false;
3088 }
3089 }
3090}
3091
3092/* Propagate parameter removal information through cross-SCC edge CS,
3093 i.e. decrease the use count in the caller parameter descriptor for each use
3094 in this call. */
3095
3096static void
3097param_removal_cross_scc_edge (cgraph_edge *cs)
3098{
3099 enum availability availability;
3100 cgraph_node *callee = cs->callee->function_symbol (&availability);
3101 isra_func_summary *to_ifs = func_sums->get (callee);
3102 if (!to_ifs || !to_ifs->m_candidate
3103 || (availability < AVAIL_AVAILABLE)
3104 || vec_safe_is_empty (to_ifs->m_parameters))
3105 {
3106 process_edge_to_unknown_caller (cs);
3107 return;
3108 }
3109 isra_func_summary *from_ifs = func_sums->get (cs->caller);
3110 gcc_checking_assert (from_ifs);
3111
3112 isra_call_summary *csum = call_sums->get (cs);
3113 unsigned args_count = csum->m_arg_flow.length ();
3114 unsigned param_count = vec_safe_length (to_ifs->m_parameters);
3115
3116 for (unsigned i = 0; i < args_count; i++)
3117 {
3118 bool unused_in_callee;
3119 if (i < param_count)
3120 unused_in_callee = (*to_ifs->m_parameters)[i].locally_unused;
3121 else
3122 unused_in_callee = false;
3123
3124 if (!unused_in_callee)
3125 {
3126 isra_param_flow *ipf = &csum->m_arg_flow[i];
3127 for (int j = 0; j < ipf->length; j++)
3128 {
3129 int input_idx = ipf->inputs[j];
3130 (*from_ifs->m_parameters)[input_idx].locally_unused = false;
3131 }
3132 }
3133 }
3134}
3135
3136/* Unless it is already there, push NODE which is also described by IFS to
3137 STACK. */
3138
3139static void
3140isra_push_node_to_stack (cgraph_node *node, isra_func_summary *ifs,
3141 vec<cgraph_node *> *stack)
3142{
3143 if (!ifs->m_queued)
3144 {
3145 ifs->m_queued = true;
3146 stack->safe_push (node);
3147 }
3148}
3149
3150/* If parameter with index INPUT_IDX is marked as locally unused, mark it as
3151 used and push CALLER on STACK. */
3152
3153static void
3154isra_mark_caller_param_used (isra_func_summary *from_ifs, int input_idx,
3155 cgraph_node *caller, vec<cgraph_node *> *stack)
3156{
3157 if ((*from_ifs->m_parameters)[input_idx].locally_unused)
3158 {
3159 (*from_ifs->m_parameters)[input_idx].locally_unused = false;
3160 isra_push_node_to_stack (caller, from_ifs, stack);
3161 }
3162}
3163
3164
3165/* Propagate information that any parameter is not used only locally within a
3166 SCC accross CS to the caller, which must be in the same SCC as the
3167 callee. Push any callers that need to be re-processed to STACK. */
3168
3169static void
3170propagate_used_across_scc_edge (cgraph_edge *cs, vec<cgraph_node *> *stack)
3171{
3172 isra_func_summary *from_ifs = func_sums->get (cs->caller);
3173 if (!from_ifs || vec_safe_is_empty (from_ifs->m_parameters))
3174 return;
3175
3176 isra_call_summary *csum = call_sums->get (cs);
3177 gcc_checking_assert (csum);
3178 unsigned args_count = csum->m_arg_flow.length ();
3179 enum availability availability;
3180 cgraph_node *callee = cs->callee->function_symbol (&availability);
3181 isra_func_summary *to_ifs = func_sums->get (callee);
3182
3183 unsigned param_count
3184 = (to_ifs && (availability >= AVAIL_AVAILABLE))
3185 ? vec_safe_length (to_ifs->m_parameters) : 0;
3186 for (unsigned i = 0; i < args_count; i++)
3187 {
3188 if (i < param_count
3189 && (*to_ifs->m_parameters)[i].locally_unused)
3190 continue;
3191
3192 /* The argument is needed in the callee it, we must mark the parameter as
3193 used also in the caller and its callers within this SCC. */
3194 isra_param_flow *ipf = &csum->m_arg_flow[i];
3195 for (int j = 0; j < ipf->length; j++)
3196 {
3197 int input_idx = ipf->inputs[j];
3198 isra_mark_caller_param_used (from_ifs, input_idx, cs->caller, stack);
3199 }
3200 }
3201}
3202
3203/* Propagate information that any parameter is not used only locally within a
3204 SCC (i.e. is used also elsewhere) to all callers of NODE that are in the
3205 same SCC. Push any callers that need to be re-processed to STACK. */
3206
3207static bool
3208propagate_used_to_scc_callers (cgraph_node *node, void *data)
3209{
3210 vec<cgraph_node *> *stack = (vec<cgraph_node *> *) data;
3211 cgraph_edge *cs;
3212 for (cs = node->callers; cs; cs = cs->next_caller)
3213 if (ipa_edge_within_scc (cs))
3214 propagate_used_across_scc_edge (cs, stack);
3215 return false;
3216}
3217
3218/* Return true iff all certain accesses in ARG_DESC are also present as
3219 certain accesses in PARAM_DESC. */
3220
3221static bool
3222all_callee_accesses_present_p (isra_param_desc *param_desc,
3223 isra_param_desc *arg_desc)
3224{
3225 unsigned aclen = vec_safe_length (arg_desc->accesses);
3226 for (unsigned j = 0; j < aclen; j++)
3227 {
3228 param_access *argacc = (*arg_desc->accesses)[j];
3229 if (!argacc->certain)
3230 continue;
3231 param_access *pacc = find_param_access (param_desc, argacc->unit_offset,
3232 argacc->unit_size);
3233 if (!pacc || !pacc->certain)
3234 return false;
3235 }
3236 return true;
3237}
3238
3239/* Type internal to function pull_accesses_from_callee. Unfortunately gcc 4.8
3240 does not allow instantiating an auto_vec with a type defined within a
3241 function so it is a global type. */
3242enum acc_prop_kind {ACC_PROP_DONT, ACC_PROP_COPY, ACC_PROP_CERTAIN};
3243
3244
3245/* Attempt to propagate all definite accesses from ARG_DESC to PARAM_DESC, if
3246 they would not violate some constraint there. If successful, return NULL,
3247 otherwise return the string reason for failure (which can be written to the
3248 dump file). DELTA_OFFSET is the known offset of the actual argument withing
3249 the formal parameter (so of ARG_DESCS within PARAM_DESCS), ARG_SIZE is the
3250 size of the actual argument or zero, if not known. In case of success, set
3251 *CHANGE_P to true if propagation actually changed anything. */
3252
3253static const char *
3254pull_accesses_from_callee (isra_param_desc *param_desc,
3255 isra_param_desc *arg_desc,
3256 unsigned delta_offset, unsigned arg_size,
3257 bool *change_p)
3258{
3259 unsigned pclen = vec_safe_length (param_desc->accesses);
3260 unsigned aclen = vec_safe_length (arg_desc->accesses);
3261 unsigned prop_count = 0;
3262 unsigned prop_size = 0;
3263 bool change = false;
3264
3265 auto_vec <enum acc_prop_kind, 8> prop_kinds (aclen);
3266 for (unsigned j = 0; j < aclen; j++)
3267 {
3268 param_access *argacc = (*arg_desc->accesses)[j];
3269 prop_kinds.safe_push (ACC_PROP_DONT);
3270
3271 if (arg_size > 0
3272 && argacc->unit_offset + argacc->unit_size > arg_size)
3273 return "callee access outsize size boundary";
3274
3275 if (!argacc->certain)
3276 continue;
3277
3278 unsigned offset = argacc->unit_offset + delta_offset;
3279 /* Given that accesses are initially stored according to increasing
3280 offset and decreasing size in case of equal offsets, the following
3281 searches could be written more efficiently if we kept the ordering
3282 when copying. But the number of accesses is capped at
3283 PARAM_IPA_SRA_MAX_REPLACEMENTS (so most likely 8) and the code gets
3284 messy quickly, so let's improve on that only if necessary. */
3285
3286 bool exact_match = false;
3287 for (unsigned i = 0; i < pclen; i++)
3288 {
3289 /* Check for overlaps. */
3290 param_access *pacc = (*param_desc->accesses)[i];
3291 if (pacc->unit_offset == offset
3292 && pacc->unit_size == argacc->unit_size)
3293 {
3294 if (argacc->alias_ptr_type != pacc->alias_ptr_type
3295 || !types_compatible_p (argacc->type, pacc->type))
3296 return "propagated access types would not match existing ones";
3297
3298 exact_match = true;
3299 if (!pacc->certain)
3300 {
3301 prop_kinds[j] = ACC_PROP_CERTAIN;
3302 prop_size += argacc->unit_size;
3303 change = true;
3304 }
3305 continue;
3306 }
3307
3308 if (offset < pacc->unit_offset + pacc->unit_size
3309 && offset + argacc->unit_size > pacc->unit_offset)
3310 {
3311 /* None permissible with load accesses, possible to fit into
3312 argument ones. */
3313 if (pacc->certain
3314 || offset < pacc->unit_offset
3315 || (offset + argacc->unit_size
3316 > pacc->unit_offset + pacc->unit_size))
3317 return "a propagated access would conflict in caller";
3318 }
3319 }
3320
3321 if (!exact_match)
3322 {
3323 prop_kinds[j] = ACC_PROP_COPY;
3324 prop_count++;
3325 prop_size += argacc->unit_size;
3326 change = true;
3327 }
3328 }
3329
3330 if (!change)
3331 return NULL;
3332
3333 if ((prop_count + pclen
3334 > (unsigned) PARAM_VALUE (PARAM_IPA_SRA_MAX_REPLACEMENTS))
3335 || size_would_violate_limit_p (param_desc,
3336 param_desc->size_reached + prop_size))
3337 return "propagating accesses would violate the count or size limit";
3338
3339 *change_p = true;
3340 for (unsigned j = 0; j < aclen; j++)
3341 {
3342 if (prop_kinds[j] == ACC_PROP_COPY)
3343 {
3344 param_access *argacc = (*arg_desc->accesses)[j];
3345
3346 param_access *copy = ggc_cleared_alloc<param_access> ();
3347 copy->unit_offset = argacc->unit_offset + delta_offset;
3348 copy->unit_size = argacc->unit_size;
3349 copy->type = argacc->type;
3350 copy->alias_ptr_type = argacc->alias_ptr_type;
3351 copy->certain = true;
3352 vec_safe_push (param_desc->accesses, copy);
3353 }
3354 else if (prop_kinds[j] == ACC_PROP_CERTAIN)
3355 {
3356 param_access *argacc = (*arg_desc->accesses)[j];
3357 param_access *csp
3358 = find_param_access (param_desc, argacc->unit_offset + delta_offset,
3359 argacc->unit_size);
3360 csp->certain = true;
3361 }
3362 }
3363
3364 param_desc->size_reached += prop_size;
3365
3366 return NULL;
3367}
3368
3369/* Propagate parameter splitting information through call graph edge CS.
3370 Return true if any changes that might need to be propagated within SCCs have
3371 been made. The function also clears the aggregate_pass_through and
3372 pointer_pass_through in call summarries which do not need to be processed
3373 again if this CS is revisited when iterating while changes are propagated
3374 within an SCC. */
3375
3376static bool
3377param_splitting_across_edge (cgraph_edge *cs)
3378{
3379 bool res = false;
3380 bool cross_scc = !ipa_edge_within_scc (cs);
3381 enum availability availability;
3382 cgraph_node *callee = cs->callee->function_symbol (&availability);
3383 isra_func_summary *from_ifs = func_sums->get (cs->caller);
3384 gcc_checking_assert (from_ifs && from_ifs->m_parameters);
3385
3386 isra_call_summary *csum = call_sums->get (cs);
3387 gcc_checking_assert (csum);
3388 unsigned args_count = csum->m_arg_flow.length ();
3389 isra_func_summary *to_ifs = func_sums->get (callee);
3390 unsigned param_count
3391 = ((to_ifs && to_ifs->m_candidate && (availability >= AVAIL_AVAILABLE))
3392 ? vec_safe_length (to_ifs->m_parameters)
3393 : 0);
3394
3395 if (dump_file && (dump_flags & TDF_DETAILS))
3396 fprintf (dump_file, "Splitting accross %s->%s:\n",
3397 cs->caller->dump_name (), callee->dump_name ());
3398
3399 unsigned i;
3400 for (i = 0; (i < args_count) && (i < param_count); i++)
3401 {
3402 isra_param_desc *arg_desc = &(*to_ifs->m_parameters)[i];
3403 isra_param_flow *ipf = &csum->m_arg_flow[i];
3404
3405 if (arg_desc->locally_unused)
3406 {
3407 if (dump_file && (dump_flags & TDF_DETAILS))
3408 fprintf (dump_file, " ->%u: unused in callee\n", i);
3409 ipf->pointer_pass_through = false;
3410 continue;
3411 }
3412
3413 if (ipf->pointer_pass_through)
3414 {
3415 int idx = get_single_param_flow_source (ipf);
3416 isra_param_desc *param_desc = &(*from_ifs->m_parameters)[idx];
3417 if (!param_desc->split_candidate)
3418 continue;
3419 gcc_assert (param_desc->by_ref);
3420
3421 if (!arg_desc->split_candidate || !arg_desc->by_ref)
3422 {
3423 if (dump_file && (dump_flags & TDF_DETAILS))
3424 fprintf (dump_file, " %u->%u: not candidate or not by "
3425 "reference in callee\n", idx, i);
3426 param_desc->split_candidate = false;
3427 ipf->pointer_pass_through = false;
3428 res = true;
3429 }
3430 else if (!ipf->safe_to_import_accesses)
3431 {
3432 if (!all_callee_accesses_present_p (param_desc, arg_desc))
3433 {
3434 if (dump_file && (dump_flags & TDF_DETAILS))
3435 fprintf (dump_file, " %u->%u: cannot import accesses.\n",
3436 idx, i);
3437 param_desc->split_candidate = false;
3438 ipf->pointer_pass_through = false;
3439 res = true;
3440
3441 }
3442 else
3443 {
3444 if (dump_file && (dump_flags & TDF_DETAILS))
3445 fprintf (dump_file, " %u->%u: verified callee accesses "
3446 "present.\n", idx, i);
3447 if (cross_scc)
3448 ipf->pointer_pass_through = false;
3449 }
3450 }
3451 else
3452 {
3453 const char *pull_failure
3454 = pull_accesses_from_callee (param_desc, arg_desc, 0, 0, &res);
3455 if (pull_failure)
3456 {
3457 if (dump_file && (dump_flags & TDF_DETAILS))
3458 fprintf (dump_file, " %u->%u: by_ref access pull "
3459 "failed: %s.\n", idx, i, pull_failure);
3460 param_desc->split_candidate = false;
3461 ipf->pointer_pass_through = false;
3462 res = true;
3463 }
3464 else
3465 {
3466 if (dump_file && (dump_flags & TDF_DETAILS))
3467 fprintf (dump_file, " %u->%u: by_ref access pull "
3468 "succeeded.\n", idx, i);
3469 if (cross_scc)
3470 ipf->pointer_pass_through = false;
3471 }
3472 }
3473 }
3474 else if (ipf->aggregate_pass_through)
3475 {
3476 int idx = get_single_param_flow_source (ipf);
3477 isra_param_desc *param_desc = &(*from_ifs->m_parameters)[idx];
3478 if (!param_desc->split_candidate)
3479 continue;
3480 gcc_assert (!param_desc->by_ref);
3481 param_access *pacc = find_param_access (param_desc, ipf->unit_offset,
3482 ipf->unit_size);
3483 gcc_checking_assert (pacc);
3484
3485 if (pacc->certain)
3486 {
3487 if (dump_file && (dump_flags & TDF_DETAILS))
3488 fprintf (dump_file, " %u->%u: already certain\n", idx, i);
3489 ipf->aggregate_pass_through = false;
3490 }
3491 else if (!arg_desc->split_candidate || arg_desc->by_ref)
3492 {
3493 if (dump_file && (dump_flags & TDF_DETAILS))
3494 fprintf (dump_file, " %u->%u: not candidate or by "
3495 "reference in callee\n", idx, i);
3496
3497 pacc->certain = true;
3498 if (overlapping_certain_accesses_p (param_desc, NULL))
3499 {
3500 if (dump_file && (dump_flags & TDF_DETAILS))
3501 fprintf (dump_file, " ...leading to overlap, "
3502 " disqualifying candidate parameter %u\n",
3503 idx);
3504 param_desc->split_candidate = false;
3505 }
3506 else
3507 bump_reached_size (param_desc, pacc->unit_size, idx);
3508
3509 ipf->aggregate_pass_through = false;
3510 res = true;
3511 }
3512 else
3513 {
3514 const char *pull_failure
3515 = pull_accesses_from_callee (param_desc, arg_desc,
3516 ipf->unit_offset,
3517 ipf->unit_size, &res);
3518 if (pull_failure)
3519 {
3520 if (dump_file && (dump_flags & TDF_DETAILS))
3521 fprintf (dump_file, " %u->%u: arg access pull "
3522 "failed: %s.\n", idx, i, pull_failure);
3523
3524 ipf->aggregate_pass_through = false;
3525 pacc->certain = true;
3526
3527 if (overlapping_certain_accesses_p (param_desc, NULL))
3528 {
3529 if (dump_file && (dump_flags & TDF_DETAILS))
3530 fprintf (dump_file, " ...leading to overlap, "
3531 " disqualifying candidate parameter %u\n",
3532 idx);
3533 param_desc->split_candidate = false;
3534 }
3535 else
3536 bump_reached_size (param_desc, pacc->unit_size, idx);
3537
3538 res = true;
3539 }
3540 else
3541 {
3542 if (dump_file && (dump_flags & TDF_DETAILS))
3543 fprintf (dump_file, " %u->%u: arg access pull "
3544 "succeeded.\n", idx, i);
3545 if (cross_scc)
3546 ipf->aggregate_pass_through = false;
3547 }
3548 }
3549 }
3550 }
3551
3552 /* Handle argument-parameter count mismatches. */
3553 for (; (i < args_count); i++)
3554 {
3555 isra_param_flow *ipf = &csum->m_arg_flow[i];
3556
3557 if (ipf->pointer_pass_through || ipf->aggregate_pass_through)
3558 {
3559 int idx = get_single_param_flow_source (ipf);
3560 ipf->pointer_pass_through = false;
3561 ipf->aggregate_pass_through = false;
3562 isra_param_desc *param_desc = &(*from_ifs->m_parameters)[idx];
3563 if (!param_desc->split_candidate)
3564 continue;
3565
3566 if (dump_file && (dump_flags & TDF_DETAILS))
3567 fprintf (dump_file, " %u->%u: no corresponding formal parameter\n",
3568 idx, i);
3569 param_desc->split_candidate = false;
3570 res = true;
3571 }
3572 }
3573 return res;
3574}
3575
3576/* Worker for call_for_symbol_and_aliases, look at all callers and if all their
3577 callers ignore the return value, or come from the same SCC and use the
3578 return value only to compute their return value, return false, otherwise
3579 return true. */
3580
3581static bool
3582retval_used_p (cgraph_node *node, void *)
3583{
3584 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
3585 {
3586 isra_call_summary *csum = call_sums->get (cs);
3587 gcc_checking_assert (csum);
3588 if (csum->m_return_ignored)
3589 continue;
3590 if (!csum->m_return_returned)
3591 return true;
3592
3593 isra_func_summary *from_ifs = func_sums->get (cs->caller);
3594 if (!from_ifs || !from_ifs->m_candidate)
3595 return true;
3596
3597 if (!ipa_edge_within_scc (cs)
3598 && !from_ifs->m_return_ignored)
3599 return true;
3600 }
3601
3602 return false;
3603}
3604
3605/* Push into NEW_PARAMS all required parameter adjustment entries to copy or
3606 modify parameter which originally had index BASE_INDEX, in the adjustment
3607 vector of parent clone (if any) had PREV_CLONE_INDEX and was described by
3608 PREV_ADJUSTMENT. If the parent clone is the original function,
3609 PREV_ADJUSTMENT is NULL and PREV_CLONE_INDEX is equal to BASE_INDEX. */
3610
3611
3612static void
3613push_param_adjustments_for_index (isra_func_summary *ifs, unsigned base_index,
3614 unsigned prev_clone_index,
3615 ipa_adjusted_param *prev_adjustment,
3616 vec<ipa_adjusted_param, va_gc> **new_params)
3617{
3618 isra_param_desc *desc = &(*ifs->m_parameters)[base_index];
3619 if (desc->locally_unused)
3620 {
3621 if (dump_file)
3622 fprintf (dump_file, " Will remove parameter %u\n", base_index);
3623 return;
3624 }
3625
3626 if (!desc->split_candidate)
3627 {
3628 ipa_adjusted_param adj;
3629 if (prev_adjustment)
3630 {
3631 adj = *prev_adjustment;
3632 adj.prev_clone_adjustment = true;
3633 adj.prev_clone_index = prev_clone_index;
3634 }
3635 else
3636 {
3637 memset (&adj, 0, sizeof (adj));
3638 adj.op = IPA_PARAM_OP_COPY;
3639 adj.base_index = base_index;
3640 adj.prev_clone_index = prev_clone_index;
3641 }
3642 vec_safe_push ((*new_params), adj);
3643 return;
3644 }
3645
3646 if (dump_file)
3647 fprintf (dump_file, " Will split parameter %u\n", base_index);
3648
3649 gcc_assert (!prev_adjustment || prev_adjustment->op == IPA_PARAM_OP_COPY);
3650 unsigned aclen = vec_safe_length (desc->accesses);
3651 for (unsigned j = 0; j < aclen; j++)
3652 {
3653 param_access *pa = (*desc->accesses)[j];
3654 if (!pa->certain)
3655 continue;
3656 if (dump_file)
3657 fprintf (dump_file, " - component at byte offset %u, "
3658 "size %u\n", pa->unit_offset, pa->unit_size);
3659
3660 ipa_adjusted_param adj;
3661 memset (&adj, 0, sizeof (adj));
3662 adj.op = IPA_PARAM_OP_SPLIT;
3663 adj.base_index = base_index;
3664 adj.prev_clone_index = prev_clone_index;
3665 adj.param_prefix_index = IPA_PARAM_PREFIX_ISRA;
3666 adj.reverse = pa->reverse;
3667 adj.type = pa->type;
3668 adj.alias_ptr_type = pa->alias_ptr_type;
3669 adj.unit_offset = pa->unit_offset;
3670 vec_safe_push ((*new_params), adj);
3671 }
3672}
3673
3674
3675/* Do finall processing of results of IPA propagation regarding NODE, clone it
3676 if appropriate. */
3677
3678static void
3679process_isra_node_results (cgraph_node *node,
3680 hash_map<const char *, unsigned> *clone_num_suffixes)
3681{
3682 isra_func_summary *ifs = func_sums->get (node);
3683 if (!ifs || !ifs->m_candidate)
3684 return;
3685
3686 auto_vec<bool, 16> surviving_params;
3687 bool check_surviving = false;
3688 if (node->clone.param_adjustments)
3689 {
3690 check_surviving = true;
3691 node->clone.param_adjustments->get_surviving_params (&surviving_params);
3692 }
3693
3694 unsigned param_count = vec_safe_length (ifs->m_parameters);
3695 bool will_change_function = false;
3696 if (ifs->m_returns_value && ifs->m_return_ignored)
3697 will_change_function = true;
3698 else
3699 for (unsigned i = 0; i < param_count; i++)
3700 {
3701 isra_param_desc *desc = &(*ifs->m_parameters)[i];
3702 if ((desc->locally_unused || desc->split_candidate)
3703 /* Make sure we do not clone just to attempt to remove an already
3704 removed unused argument. */
3705 && (!check_surviving
3706 || (i < surviving_params.length ()
3707 && surviving_params[i])))
3708 {
3709 will_change_function = true;
3710 break;
3711 }
3712 }
3713 if (!will_change_function)
3714 return;
3715
3716 if (dump_file)
3717 {
3718 fprintf (dump_file, "\nEvaluating analysis results for %s\n",
3719 node->dump_name ());
3720 if (ifs->m_returns_value && ifs->m_return_ignored)
3721 fprintf (dump_file, " Will remove return value.\n");
3722 }
3723
3724 vec<ipa_adjusted_param, va_gc> *new_params = NULL;
3725 if (ipa_param_adjustments *old_adjustments = node->clone.param_adjustments)
3726 {
3727 unsigned old_adj_len = vec_safe_length (old_adjustments->m_adj_params);
3728 for (unsigned i = 0; i < old_adj_len; i++)
3729 {
3730 ipa_adjusted_param *old_adj = &(*old_adjustments->m_adj_params)[i];
3731 push_param_adjustments_for_index (ifs, old_adj->base_index, i,
3732 old_adj, &new_params);
3733 }
3734 }
3735 else
3736 for (unsigned i = 0; i < param_count; i++)
3737 push_param_adjustments_for_index (ifs, i, i, NULL, &new_params);
3738
3739 ipa_param_adjustments *new_adjustments
3740 = (new (ggc_alloc <ipa_param_adjustments> ())
3741 ipa_param_adjustments (new_params, param_count,
3742 ifs->m_returns_value && ifs->m_return_ignored));
3743
3744 if (dump_file && (dump_flags & TDF_DETAILS))
3745 {
3746 fprintf (dump_file, "\n Created adjustments:\n");
3747 new_adjustments->dump (dump_file);
3748 }
3749
3750 unsigned &suffix_counter = clone_num_suffixes->get_or_insert (
3751 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (
3752 node->decl)));
3753 vec<cgraph_edge *> callers = node->collect_callers ();
3754 cgraph_node *new_node
3755 = node->create_virtual_clone (callers, NULL, new_adjustments, "isra",
3756 suffix_counter);
3757 suffix_counter++;
3758
3759 if (dump_file)
3760 fprintf (dump_file, " Created new node %s\n", new_node->dump_name ());
3761 callers.release ();
3762}
3763
3764/* Check which parameters of NODE described by IFS have survived until IPA-SRA
3765 and disable transformations for those which have not or which should not
3766 transformed because the associated debug counter reached its limit. Return
3767 true if none survived or if there were no candidates to begin with. */
3768
3769static bool
3770disable_unavailable_parameters (cgraph_node *node, isra_func_summary *ifs)
3771{
3772 bool ret = true;
3773 unsigned len = vec_safe_length (ifs->m_parameters);
3774 if (!len)
3775 return true;
3776
3777 auto_vec<bool, 16> surviving_params;
3778 bool check_surviving = false;
3779 if (node->clone.param_adjustments)
3780 {
3781 check_surviving = true;
3782 node->clone.param_adjustments->get_surviving_params (&surviving_params);
3783 }
3784 bool dumped_first = false;
3785 for (unsigned i = 0; i < len; i++)
3786 {
3787 isra_param_desc *desc = &(*ifs->m_parameters)[i];
3788 if (!dbg_cnt (ipa_sra_params))
3789 {
3790 desc->locally_unused = false;
3791 desc->split_candidate = false;
3792 }
3793 else if (check_surviving
3794 && (i >= surviving_params.length ()
3795 || !surviving_params[i]))
3796 {
3797 /* Even if the parameter was removed by a previous IPA pass, we do
3798 not clear locally_unused because if it really is unused, this
3799 information might be useful in callers. */
3800 desc->split_candidate = false;
3801
3802 if (dump_file && (dump_flags & TDF_DETAILS))
3803 {
3804 if (!dumped_first)
3805 {
3806 fprintf (dump_file,
3807 "The following parameters of %s are dead on "
3808 "arrival:", node->dump_name ());
3809 dumped_first = true;
3810 }
3811 fprintf (dump_file, " %u", i);
3812 }
3813 }
3814 else if (desc->locally_unused || desc->split_candidate)
3815 ret = false;
3816 }
3817
3818 if (dumped_first)
3819 fprintf (dump_file, "\n");
3820
3821 return ret;
3822}
3823
3824
3825/* Run the interprocedural part of IPA-SRA. */
3826
3827static unsigned int
3828ipa_sra_analysis (void)
3829{
3830 if (dump_file)
3831 {
3832 fprintf (dump_file, "\n========== IPA-SRA IPA stage ==========\n");
3833 ipa_sra_dump_all_summaries (dump_file);
3834 }
3835
3836 gcc_checking_assert (func_sums);
3837 gcc_checking_assert (call_sums);
3838 cgraph_node **order = XCNEWVEC (cgraph_node *, symtab->cgraph_count);
3839 auto_vec <cgraph_node *, 16> stack;
3840 int node_scc_count = ipa_reduced_postorder (order, true, NULL);
3841
3842 /* One sweep from callees to callers for parameter removal and splitting. */
3843 for (int i = 0; i < node_scc_count; i++)
3844 {
3845 cgraph_node *scc_rep = order[i];
3846 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (scc_rep);
3847 unsigned j;
3848
3849 /* Preliminary IPA function level checks and first step of parameter
3850 removal. */
3851 cgraph_node *v;
3852 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3853 {
3854 isra_func_summary *ifs = func_sums->get (v);
3855 if (!ifs || !ifs->m_candidate)
3856 continue;
3857 if (!ipa_sra_ipa_function_checks (v)
3858 || check_all_callers_for_issues (v))
3859 {
3860 ifs->zap ();
3861 continue;
3862 }
3863 if (disable_unavailable_parameters (v, ifs))
3864 continue;
3865 for (cgraph_edge *cs = v->indirect_calls; cs; cs = cs->next_callee)
3866 process_edge_to_unknown_caller (cs);
3867 for (cgraph_edge *cs = v->callees; cs; cs = cs->next_callee)
3868 if (!ipa_edge_within_scc (cs))
3869 param_removal_cross_scc_edge (cs);
3870 }
3871
3872 /* Look at edges within the current SCC and propagate used-ness accross
3873 them, pushing onto the stack all notes which might need to be
3874 revisited. */
3875 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3876 v->call_for_symbol_thunks_and_aliases (propagate_used_to_scc_callers,
3877 &stack, true);
3878
3879 /* Keep revisiting and pushing until nothing changes. */
3880 while (!stack.is_empty ())
3881 {
3882 cgraph_node *v = stack.pop ();
3883 isra_func_summary *ifs = func_sums->get (v);
3884 gcc_checking_assert (ifs && ifs->m_queued);
3885 ifs->m_queued = false;
3886
3887 v->call_for_symbol_thunks_and_aliases (propagate_used_to_scc_callers,
3888 &stack, true);
3889 }
3890
3891 /* Parameter splitting. */
3892 bool repeat_scc_access_propagation;
3893 do
3894 {
3895 repeat_scc_access_propagation = false;
3896 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3897 {
3898 isra_func_summary *ifs = func_sums->get (v);
3899 if (!ifs
3900 || !ifs->m_candidate
3901 || vec_safe_is_empty (ifs->m_parameters))
3902 continue;
3903 for (cgraph_edge *cs = v->callees; cs; cs = cs->next_callee)
3904 if (param_splitting_across_edge (cs))
3905 repeat_scc_access_propagation = true;
3906 }
3907 }
3908 while (repeat_scc_access_propagation);
3909
3910 if (flag_checking)
3911 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3912 verify_splitting_accesses (v, true);
3913
3914 cycle_nodes.release ();
3915 }
3916
3917 /* One sweep from caller to callees for result removal. */
3918 for (int i = node_scc_count - 1; i >= 0 ; i--)
3919 {
3920 cgraph_node *scc_rep = order[i];
3921 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (scc_rep);
3922 unsigned j;
3923
3924 cgraph_node *v;
3925 FOR_EACH_VEC_ELT (cycle_nodes, j, v)
3926 {
3927 isra_func_summary *ifs = func_sums->get (v);
3928 if (!ifs || !ifs->m_candidate)
3929 continue;
3930
3931 bool return_needed
3932 = (ifs->m_returns_value
3933 && (!dbg_cnt (ipa_sra_retvalues)
3934 || v->call_for_symbol_and_aliases (retval_used_p,
3935 NULL, true)));
3936 ifs->m_return_ignored = !return_needed;
3937 if (return_needed)
3938 isra_push_node_to_stack (v, ifs, &stack);
3939 }
3940
3941 while (!stack.is_empty ())
3942 {
3943 cgraph_node *node = stack.pop ();
3944 isra_func_summary *ifs = func_sums->get (node);
3945 gcc_checking_assert (ifs && ifs->m_queued);
3946 ifs->m_queued = false;
3947
3948 for (cgraph_edge *cs = node->callees; cs; cs = cs->next_callee)
3949 if (ipa_edge_within_scc (cs)
3950 && call_sums->get (cs)->m_return_returned)
3951 {
3952 enum availability av;
3953 cgraph_node *callee = cs->callee->function_symbol (&av);
3954 isra_func_summary *to_ifs = func_sums->get (callee);
3955 if (to_ifs && to_ifs->m_return_ignored)
3956 {
3957 to_ifs->m_return_ignored = false;
3958 isra_push_node_to_stack (callee, to_ifs, &stack);
3959 }
3960 }
3961 }
3962 cycle_nodes.release ();
3963 }
3964
3965 ipa_free_postorder_info ();
3966 free (order);
3967
3968 if (dump_file)
3969 {
3970 if (dump_flags & TDF_DETAILS)
3971 {
3972 fprintf (dump_file, "\n========== IPA-SRA propagation final state "
3973 " ==========\n");
3974 ipa_sra_dump_all_summaries (dump_file);
3975 }
3976 fprintf (dump_file, "\n========== IPA-SRA decisions ==========\n");
3977 }
3978
3979 hash_map<const char *, unsigned> *clone_num_suffixes
3980 = new hash_map<const char *, unsigned>;
3981
3982 cgraph_node *node;
3983 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
3984 process_isra_node_results (node, clone_num_suffixes);
3985
3986 delete clone_num_suffixes;
3987 func_sums->release ();
3988 func_sums = NULL;
3989 call_sums->release ();
3990 call_sums = NULL;
3991
3992 if (dump_file)
3993 fprintf (dump_file, "\n========== IPA SRA IPA analysis done "
3994 "==========\n\n");
3995 return 0;
3996}
3997
3998
3999const pass_data pass_data_ipa_sra =
4000{
4001 IPA_PASS, /* type */
4002 "sra", /* name */
4003 OPTGROUP_NONE, /* optinfo_flags */
4004 TV_IPA_SRA, /* tv_id */
4005 0, /* properties_required */
4006 0, /* properties_provided */
4007 0, /* properties_destroyed */
4008 0, /* todo_flags_start */
4009 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
4010};
4011
4012class pass_ipa_sra : public ipa_opt_pass_d
4013{
4014public:
4015 pass_ipa_sra (gcc::context *ctxt)
4016 : ipa_opt_pass_d (pass_data_ipa_sra, ctxt,
4017 ipa_sra_generate_summary, /* generate_summary */
4018 ipa_sra_write_summary, /* write_summary */
4019 ipa_sra_read_summary, /* read_summary */
4020 NULL , /* write_optimization_summary */
4021 NULL, /* read_optimization_summary */
4022 NULL, /* stmt_fixup */
4023 0, /* function_transform_todo_flags_start */
4024 NULL, /* function_transform */
4025 NULL) /* variable_transform */
4026 {}
4027
4028 /* opt_pass methods: */
4029 virtual bool gate (function *)
4030 {
4031 /* TODO: We should remove the optimize check after we ensure we never run
4032 IPA passes when not optimizing. */
4033 return (flag_ipa_sra && optimize);
4034 }
4035
4036 virtual unsigned int execute (function *) { return ipa_sra_analysis (); }
4037
4038}; // class pass_ipa_sra
4039
4040} // anon namespace
4041
4042ipa_opt_pass_d *
4043make_pass_ipa_sra (gcc::context *ctxt)
4044{
4045 return new pass_ipa_sra (ctxt);
4046}
4047
4048
4049#include "gt-ipa-sra.h"