1 /* Scalar Replacement of Aggregates (SRA) converts some structure
2    references into scalar references, exposing them to the scalar
3    optimizers.
4    Copyright (C) 2008-2014 Free Software Foundation, Inc.
5    Contributed by Martin Jambor <mjambor@suse.cz>
6 
7 This file is part of GCC.
8 
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
13 
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17 for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3.  If not see
21 <http://www.gnu.org/licenses/>.  */
22 
23 /* This file implements Scalar Reduction of Aggregates (SRA).  SRA is run
24    twice, once in the early stages of compilation (early SRA) and once in the
25    late stages (late SRA).  The aim of both is to turn references to scalar
26    parts of aggregates into uses of independent scalar variables.
27 
28    The two passes are nearly identical, the only difference is that early SRA
29    does not scalarize unions which are used as the result in a GIMPLE_RETURN
30    statement because together with inlining this can lead to weird type
31    conversions.
32 
33    Both passes operate in four stages:
34 
35    1. The declarations that have properties which make them candidates for
36       scalarization are identified in function find_var_candidates().  The
37       candidates are stored in candidate_bitmap.
38 
39    2. The function body is scanned.  In the process, declarations which are
40       used in a manner that prevent their scalarization are removed from the
41       candidate bitmap.  More importantly, for every access into an aggregate,
42       an access structure (struct access) is created by create_access() and
43       stored in a vector associated with the aggregate.  Among other
44       information, the aggregate declaration, the offset and size of the access
45       and its type are stored in the structure.
46 
47       On a related note, assign_link structures are created for every assign
48       statement between candidate aggregates and attached to the related
49       accesses.
50 
51    3. The vectors of accesses are analyzed.  They are first sorted according to
52       their offset and size and then scanned for partially overlapping accesses
53       (i.e. those which overlap but one is not entirely within another).  Such
54       an access disqualifies the whole aggregate from being scalarized.
55 
56       If there is no such inhibiting overlap, a representative access structure
57       is chosen for every unique combination of offset and size.  Afterwards,
58       the pass builds a set of trees from these structures, in which children
59       of an access are within their parent (in terms of offset and size).
60 
61       Then accesses  are propagated  whenever possible (i.e.  in cases  when it
62       does not create a partially overlapping access) across assign_links from
63       the right hand side to the left hand side.
64 
65       Then the set of trees for each declaration is traversed again and those
66       accesses which should be replaced by a scalar are identified.
67 
68    4. The function is traversed again, and for every reference into an
69       aggregate that has some component which is about to be scalarized,
70       statements are amended and new statements are created as necessary.
71       Finally, if a parameter got scalarized, the scalar replacements are
72       initialized with values from respective parameter aggregates.  */
73 
74 #include "config.h"
75 #include "system.h"
76 #include "coretypes.h"
77 #include "hash-table.h"
78 #include "alloc-pool.h"
79 #include "tm.h"
80 #include "tree.h"
81 #include "pointer-set.h"
82 #include "basic-block.h"
83 #include "tree-ssa-alias.h"
84 #include "internal-fn.h"
85 #include "tree-eh.h"
86 #include "gimple-expr.h"
87 #include "is-a.h"
88 #include "gimple.h"
89 #include "stor-layout.h"
90 #include "gimplify.h"
91 #include "gimple-iterator.h"
92 #include "gimplify-me.h"
93 #include "gimple-walk.h"
94 #include "bitmap.h"
95 #include "gimple-ssa.h"
96 #include "tree-cfg.h"
97 #include "tree-phinodes.h"
98 #include "ssa-iterators.h"
99 #include "stringpool.h"
100 #include "tree-ssanames.h"
101 #include "expr.h"
102 #include "tree-dfa.h"
103 #include "tree-ssa.h"
104 #include "tree-pass.h"
105 #include "ipa-prop.h"
106 #include "statistics.h"
107 #include "params.h"
108 #include "target.h"
109 #include "flags.h"
110 #include "dbgcnt.h"
111 #include "tree-inline.h"
112 #include "gimple-pretty-print.h"
113 #include "ipa-inline.h"
114 #include "ipa-utils.h"
115 
116 /* Enumeration of all aggregate reductions we can do.  */
117 enum sra_mode { SRA_MODE_EARLY_IPA,   /* early call regularization */
118 		SRA_MODE_EARLY_INTRA, /* early intraprocedural SRA */
119 		SRA_MODE_INTRA };     /* late intraprocedural SRA */
120 
121 /* Global variable describing which aggregate reduction we are performing at
122    the moment.  */
123 static enum sra_mode sra_mode;
124 
125 struct assign_link;
126 
127 /* ACCESS represents each access to an aggregate variable (as a whole or a
128    part).  It can also represent a group of accesses that refer to exactly the
129    same fragment of an aggregate (i.e. those that have exactly the same offset
130    and size).  Such representatives for a single aggregate, once determined,
131    are linked in a linked list and have the group fields set.
132 
133    Moreover, when doing intraprocedural SRA, a tree is built from those
134    representatives (by the means of first_child and next_sibling pointers), in
135    which all items in a subtree are "within" the root, i.e. their offset is
136    greater or equal to offset of the root and offset+size is smaller or equal
137    to offset+size of the root.  Children of an access are sorted by offset.
138 
139    Note that accesses to parts of vector and complex number types always
140    represented by an access to the whole complex number or a vector.  It is a
141    duty of the modifying functions to replace them appropriately.  */
142 
143 struct access
144 {
145   /* Values returned by  `get_ref_base_and_extent' for each component reference
146      If EXPR isn't a component reference  just set `BASE = EXPR', `OFFSET = 0',
147      `SIZE = TREE_SIZE (TREE_TYPE (expr))'.  */
148   HOST_WIDE_INT offset;
149   HOST_WIDE_INT size;
150   tree base;
151 
152   /* Expression.  It is context dependent so do not use it to create new
153      expressions to access the original aggregate.  See PR 42154 for a
154      testcase.  */
155   tree expr;
156   /* Type.  */
157   tree type;
158 
159   /* The statement this access belongs to.  */
160   gimple stmt;
161 
162   /* Next group representative for this aggregate. */
163   struct access *next_grp;
164 
165   /* Pointer to the group representative.  Pointer to itself if the struct is
166      the representative.  */
167   struct access *group_representative;
168 
169   /* If this access has any children (in terms of the definition above), this
170      points to the first one.  */
171   struct access *first_child;
172 
173   /* In intraprocedural SRA, pointer to the next sibling in the access tree as
174      described above.  In IPA-SRA this is a pointer to the next access
175      belonging to the same group (having the same representative).  */
176   struct access *next_sibling;
177 
178   /* Pointers to the first and last element in the linked list of assign
179      links.  */
180   struct assign_link *first_link, *last_link;
181 
182   /* Pointer to the next access in the work queue.  */
183   struct access *next_queued;
184 
185   /* Replacement variable for this access "region."  Never to be accessed
186      directly, always only by the means of get_access_replacement() and only
187      when grp_to_be_replaced flag is set.  */
188   tree replacement_decl;
189 
190   /* Is this particular access write access? */
191   unsigned write : 1;
192 
193   /* Is this access an access to a non-addressable field? */
194   unsigned non_addressable : 1;
195 
196   /* Is this access currently in the work queue?  */
197   unsigned grp_queued : 1;
198 
199   /* Does this group contain a write access?  This flag is propagated down the
200      access tree.  */
201   unsigned grp_write : 1;
202 
203   /* Does this group contain a read access?  This flag is propagated down the
204      access tree.  */
205   unsigned grp_read : 1;
206 
207   /* Does this group contain a read access that comes from an assignment
208      statement?  This flag is propagated down the access tree.  */
209   unsigned grp_assignment_read : 1;
210 
211   /* Does this group contain a write access that comes from an assignment
212      statement?  This flag is propagated down the access tree.  */
213   unsigned grp_assignment_write : 1;
214 
215   /* Does this group contain a read access through a scalar type?  This flag is
216      not propagated in the access tree in any direction.  */
217   unsigned grp_scalar_read : 1;
218 
219   /* Does this group contain a write access through a scalar type?  This flag
220      is not propagated in the access tree in any direction.  */
221   unsigned grp_scalar_write : 1;
222 
223   /* Is this access an artificial one created to scalarize some record
224      entirely? */
225   unsigned grp_total_scalarization : 1;
226 
227   /* Other passes of the analysis use this bit to make function
228      analyze_access_subtree create scalar replacements for this group if
229      possible.  */
230   unsigned grp_hint : 1;
231 
232   /* Is the subtree rooted in this access fully covered by scalar
233      replacements?  */
234   unsigned grp_covered : 1;
235 
236   /* If set to true, this access and all below it in an access tree must not be
237      scalarized.  */
238   unsigned grp_unscalarizable_region : 1;
239 
240   /* Whether data have been written to parts of the aggregate covered by this
241      access which is not to be scalarized.  This flag is propagated up in the
242      access tree.  */
243   unsigned grp_unscalarized_data : 1;
244 
245   /* Does this access and/or group contain a write access through a
246      BIT_FIELD_REF?  */
247   unsigned grp_partial_lhs : 1;
248 
249   /* Set when a scalar replacement should be created for this variable.  */
250   unsigned grp_to_be_replaced : 1;
251 
252   /* Set when we want a replacement for the sole purpose of having it in
253      generated debug statements.  */
254   unsigned grp_to_be_debug_replaced : 1;
255 
256   /* Should TREE_NO_WARNING of a replacement be set?  */
257   unsigned grp_no_warning : 1;
258 
259   /* Is it possible that the group refers to data which might be (directly or
260      otherwise) modified?  */
261   unsigned grp_maybe_modified : 1;
262 
263   /* Set when this is a representative of a pointer to scalar (i.e. by
264      reference) parameter which we consider for turning into a plain scalar
265      (i.e. a by value parameter).  */
266   unsigned grp_scalar_ptr : 1;
267 
268   /* Set when we discover that this pointer is not safe to dereference in the
269      caller.  */
270   unsigned grp_not_necessarilly_dereferenced : 1;
271 };
272 
273 typedef struct access *access_p;
274 
275 
276 /* Alloc pool for allocating access structures.  */
277 static alloc_pool access_pool;
278 
279 /* A structure linking lhs and rhs accesses from an aggregate assignment.  They
280    are used to propagate subaccesses from rhs to lhs as long as they don't
281    conflict with what is already there.  */
282 struct assign_link
283 {
284   struct access *lacc, *racc;
285   struct assign_link *next;
286 };
287 
288 /* Alloc pool for allocating assign link structures.  */
289 static alloc_pool link_pool;
290 
291 /* Base (tree) -> Vector (vec<access_p> *) map.  */
292 static struct pointer_map_t *base_access_vec;
293 
294 /* Candidate hash table helpers.  */
295 
296 struct uid_decl_hasher : typed_noop_remove <tree_node>
297 {
298   typedef tree_node value_type;
299   typedef tree_node compare_type;
300   static inline hashval_t hash (const value_type *);
301   static inline bool equal (const value_type *, const compare_type *);
302 };
303 
304 /* Hash a tree in a uid_decl_map.  */
305 
306 inline hashval_t
hash(const value_type * item)307 uid_decl_hasher::hash (const value_type *item)
308 {
309   return item->decl_minimal.uid;
310 }
311 
312 /* Return true if the DECL_UID in both trees are equal.  */
313 
314 inline bool
equal(const value_type * a,const compare_type * b)315 uid_decl_hasher::equal (const value_type *a, const compare_type *b)
316 {
317   return (a->decl_minimal.uid == b->decl_minimal.uid);
318 }
319 
320 /* Set of candidates.  */
321 static bitmap candidate_bitmap;
322 static hash_table <uid_decl_hasher> candidates;
323 
324 /* For a candidate UID return the candidates decl.  */
325 
326 static inline tree
candidate(unsigned uid)327 candidate (unsigned uid)
328 {
329  tree_node t;
330  t.decl_minimal.uid = uid;
331  return candidates.find_with_hash (&t, static_cast <hashval_t> (uid));
332 }
333 
334 /* Bitmap of candidates which we should try to entirely scalarize away and
335    those which cannot be (because they are and need be used as a whole).  */
336 static bitmap should_scalarize_away_bitmap, cannot_scalarize_away_bitmap;
337 
338 /* Obstack for creation of fancy names.  */
339 static struct obstack name_obstack;
340 
341 /* Head of a linked list of accesses that need to have its subaccesses
342    propagated to their assignment counterparts. */
343 static struct access *work_queue_head;
344 
345 /* Number of parameters of the analyzed function when doing early ipa SRA.  */
346 static int func_param_count;
347 
348 /* scan_function sets the following to true if it encounters a call to
349    __builtin_apply_args.  */
350 static bool encountered_apply_args;
351 
352 /* Set by scan_function when it finds a recursive call.  */
353 static bool encountered_recursive_call;
354 
355 /* Set by scan_function when it finds a recursive call with less actual
356    arguments than formal parameters..  */
357 static bool encountered_unchangable_recursive_call;
358 
359 /* This is a table in which for each basic block and parameter there is a
360    distance (offset + size) in that parameter which is dereferenced and
361    accessed in that BB.  */
362 static HOST_WIDE_INT *bb_dereferences;
363 /* Bitmap of BBs that can cause the function to "stop" progressing by
364    returning, throwing externally, looping infinitely or calling a function
365    which might abort etc.. */
366 static bitmap final_bbs;
367 
368 /* Representative of no accesses at all. */
369 static struct access  no_accesses_representant;
370 
371 /* Predicate to test the special value.  */
372 
373 static inline bool
no_accesses_p(struct access * access)374 no_accesses_p (struct access *access)
375 {
376   return access == &no_accesses_representant;
377 }
378 
379 /* Dump contents of ACCESS to file F in a human friendly way.  If GRP is true,
380    representative fields are dumped, otherwise those which only describe the
381    individual access are.  */
382 
383 static struct
384 {
385   /* Number of processed aggregates is readily available in
386      analyze_all_variable_accesses and so is not stored here.  */
387 
388   /* Number of created scalar replacements.  */
389   int replacements;
390 
391   /* Number of times sra_modify_expr or sra_modify_assign themselves changed an
392      expression.  */
393   int exprs;
394 
395   /* Number of statements created by generate_subtree_copies.  */
396   int subtree_copies;
397 
398   /* Number of statements created by load_assign_lhs_subreplacements.  */
399   int subreplacements;
400 
401   /* Number of times sra_modify_assign has deleted a statement.  */
402   int deleted;
403 
404   /* Number of times sra_modify_assign has to deal with subaccesses of LHS and
405      RHS reparately due to type conversions or nonexistent matching
406      references.  */
407   int separate_lhs_rhs_handling;
408 
409   /* Number of parameters that were removed because they were unused.  */
410   int deleted_unused_parameters;
411 
412   /* Number of scalars passed as parameters by reference that have been
413      converted to be passed by value.  */
414   int scalar_by_ref_to_by_val;
415 
416   /* Number of aggregate parameters that were replaced by one or more of their
417      components.  */
418   int aggregate_params_reduced;
419 
420   /* Numbber of components created when splitting aggregate parameters.  */
421   int param_reductions_created;
422 } sra_stats;
423 
424 static void
dump_access(FILE * f,struct access * access,bool grp)425 dump_access (FILE *f, struct access *access, bool grp)
426 {
427   fprintf (f, "access { ");
428   fprintf (f, "base = (%d)'", DECL_UID (access->base));
429   print_generic_expr (f, access->base, 0);
430   fprintf (f, "', offset = " HOST_WIDE_INT_PRINT_DEC, access->offset);
431   fprintf (f, ", size = " HOST_WIDE_INT_PRINT_DEC, access->size);
432   fprintf (f, ", expr = ");
433   print_generic_expr (f, access->expr, 0);
434   fprintf (f, ", type = ");
435   print_generic_expr (f, access->type, 0);
436   if (grp)
437     fprintf (f, ", grp_read = %d, grp_write = %d, grp_assignment_read = %d, "
438 	     "grp_assignment_write = %d, grp_scalar_read = %d, "
439 	     "grp_scalar_write = %d, grp_total_scalarization = %d, "
440 	     "grp_hint = %d, grp_covered = %d, "
441 	     "grp_unscalarizable_region = %d, grp_unscalarized_data = %d, "
442 	     "grp_partial_lhs = %d, grp_to_be_replaced = %d, "
443 	     "grp_to_be_debug_replaced = %d, grp_maybe_modified = %d, "
444 	     "grp_not_necessarilly_dereferenced = %d\n",
445 	     access->grp_read, access->grp_write, access->grp_assignment_read,
446 	     access->grp_assignment_write, access->grp_scalar_read,
447 	     access->grp_scalar_write, access->grp_total_scalarization,
448 	     access->grp_hint, access->grp_covered,
449 	     access->grp_unscalarizable_region, access->grp_unscalarized_data,
450 	     access->grp_partial_lhs, access->grp_to_be_replaced,
451 	     access->grp_to_be_debug_replaced, access->grp_maybe_modified,
452 	     access->grp_not_necessarilly_dereferenced);
453   else
454     fprintf (f, ", write = %d, grp_total_scalarization = %d, "
455 	     "grp_partial_lhs = %d\n",
456 	     access->write, access->grp_total_scalarization,
457 	     access->grp_partial_lhs);
458 }
459 
460 /* Dump a subtree rooted in ACCESS to file F, indent by LEVEL.  */
461 
462 static void
dump_access_tree_1(FILE * f,struct access * access,int level)463 dump_access_tree_1 (FILE *f, struct access *access, int level)
464 {
465   do
466     {
467       int i;
468 
469       for (i = 0; i < level; i++)
470 	fputs ("* ", dump_file);
471 
472       dump_access (f, access, true);
473 
474       if (access->first_child)
475 	dump_access_tree_1 (f, access->first_child, level + 1);
476 
477       access = access->next_sibling;
478     }
479   while (access);
480 }
481 
482 /* Dump all access trees for a variable, given the pointer to the first root in
483    ACCESS.  */
484 
485 static void
dump_access_tree(FILE * f,struct access * access)486 dump_access_tree (FILE *f, struct access *access)
487 {
488   for (; access; access = access->next_grp)
489     dump_access_tree_1 (f, access, 0);
490 }
491 
492 /* Return true iff ACC is non-NULL and has subaccesses.  */
493 
494 static inline bool
access_has_children_p(struct access * acc)495 access_has_children_p (struct access *acc)
496 {
497   return acc && acc->first_child;
498 }
499 
500 /* Return true iff ACC is (partly) covered by at least one replacement.  */
501 
502 static bool
access_has_replacements_p(struct access * acc)503 access_has_replacements_p (struct access *acc)
504 {
505   struct access *child;
506   if (acc->grp_to_be_replaced)
507     return true;
508   for (child = acc->first_child; child; child = child->next_sibling)
509     if (access_has_replacements_p (child))
510       return true;
511   return false;
512 }
513 
514 /* Return a vector of pointers to accesses for the variable given in BASE or
515    NULL if there is none.  */
516 
517 static vec<access_p> *
get_base_access_vector(tree base)518 get_base_access_vector (tree base)
519 {
520   void **slot;
521 
522   slot = pointer_map_contains (base_access_vec, base);
523   if (!slot)
524     return NULL;
525   else
526     return *(vec<access_p> **) slot;
527 }
528 
529 /* Find an access with required OFFSET and SIZE in a subtree of accesses rooted
530    in ACCESS.  Return NULL if it cannot be found.  */
531 
532 static struct access *
find_access_in_subtree(struct access * access,HOST_WIDE_INT offset,HOST_WIDE_INT size)533 find_access_in_subtree (struct access *access, HOST_WIDE_INT offset,
534 			HOST_WIDE_INT size)
535 {
536   while (access && (access->offset != offset || access->size != size))
537     {
538       struct access *child = access->first_child;
539 
540       while (child && (child->offset + child->size <= offset))
541 	child = child->next_sibling;
542       access = child;
543     }
544 
545   return access;
546 }
547 
548 /* Return the first group representative for DECL or NULL if none exists.  */
549 
550 static struct access *
get_first_repr_for_decl(tree base)551 get_first_repr_for_decl (tree base)
552 {
553   vec<access_p> *access_vec;
554 
555   access_vec = get_base_access_vector (base);
556   if (!access_vec)
557     return NULL;
558 
559   return (*access_vec)[0];
560 }
561 
562 /* Find an access representative for the variable BASE and given OFFSET and
563    SIZE.  Requires that access trees have already been built.  Return NULL if
564    it cannot be found.  */
565 
566 static struct access *
get_var_base_offset_size_access(tree base,HOST_WIDE_INT offset,HOST_WIDE_INT size)567 get_var_base_offset_size_access (tree base, HOST_WIDE_INT offset,
568 				 HOST_WIDE_INT size)
569 {
570   struct access *access;
571 
572   access = get_first_repr_for_decl (base);
573   while (access && (access->offset + access->size <= offset))
574     access = access->next_grp;
575   if (!access)
576     return NULL;
577 
578   return find_access_in_subtree (access, offset, size);
579 }
580 
581 /* Add LINK to the linked list of assign links of RACC.  */
582 static void
add_link_to_rhs(struct access * racc,struct assign_link * link)583 add_link_to_rhs (struct access *racc, struct assign_link *link)
584 {
585   gcc_assert (link->racc == racc);
586 
587   if (!racc->first_link)
588     {
589       gcc_assert (!racc->last_link);
590       racc->first_link = link;
591     }
592   else
593     racc->last_link->next = link;
594 
595   racc->last_link = link;
596   link->next = NULL;
597 }
598 
599 /* Move all link structures in their linked list in OLD_RACC to the linked list
600    in NEW_RACC.  */
601 static void
relink_to_new_repr(struct access * new_racc,struct access * old_racc)602 relink_to_new_repr (struct access *new_racc, struct access *old_racc)
603 {
604   if (!old_racc->first_link)
605     {
606       gcc_assert (!old_racc->last_link);
607       return;
608     }
609 
610   if (new_racc->first_link)
611     {
612       gcc_assert (!new_racc->last_link->next);
613       gcc_assert (!old_racc->last_link || !old_racc->last_link->next);
614 
615       new_racc->last_link->next = old_racc->first_link;
616       new_racc->last_link = old_racc->last_link;
617     }
618   else
619     {
620       gcc_assert (!new_racc->last_link);
621 
622       new_racc->first_link = old_racc->first_link;
623       new_racc->last_link = old_racc->last_link;
624     }
625   old_racc->first_link = old_racc->last_link = NULL;
626 }
627 
628 /* Add ACCESS to the work queue (which is actually a stack).  */
629 
630 static void
add_access_to_work_queue(struct access * access)631 add_access_to_work_queue (struct access *access)
632 {
633   if (!access->grp_queued)
634     {
635       gcc_assert (!access->next_queued);
636       access->next_queued = work_queue_head;
637       access->grp_queued = 1;
638       work_queue_head = access;
639     }
640 }
641 
642 /* Pop an access from the work queue, and return it, assuming there is one.  */
643 
644 static struct access *
pop_access_from_work_queue(void)645 pop_access_from_work_queue (void)
646 {
647   struct access *access = work_queue_head;
648 
649   work_queue_head = access->next_queued;
650   access->next_queued = NULL;
651   access->grp_queued = 0;
652   return access;
653 }
654 
655 
656 /* Allocate necessary structures.  */
657 
658 static void
sra_initialize(void)659 sra_initialize (void)
660 {
661   candidate_bitmap = BITMAP_ALLOC (NULL);
662   candidates.create (vec_safe_length (cfun->local_decls) / 2);
663   should_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
664   cannot_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
665   gcc_obstack_init (&name_obstack);
666   access_pool = create_alloc_pool ("SRA accesses", sizeof (struct access), 16);
667   link_pool = create_alloc_pool ("SRA links", sizeof (struct assign_link), 16);
668   base_access_vec = pointer_map_create ();
669   memset (&sra_stats, 0, sizeof (sra_stats));
670   encountered_apply_args = false;
671   encountered_recursive_call = false;
672   encountered_unchangable_recursive_call = false;
673 }
674 
675 /* Hook fed to pointer_map_traverse, deallocate stored vectors.  */
676 
677 static bool
delete_base_accesses(const void * key ATTRIBUTE_UNUSED,void ** value,void * data ATTRIBUTE_UNUSED)678 delete_base_accesses (const void *key ATTRIBUTE_UNUSED, void **value,
679 		     void *data ATTRIBUTE_UNUSED)
680 {
681   vec<access_p> *access_vec = (vec<access_p> *) *value;
682   vec_free (access_vec);
683   return true;
684 }
685 
686 /* Deallocate all general structures.  */
687 
688 static void
sra_deinitialize(void)689 sra_deinitialize (void)
690 {
691   BITMAP_FREE (candidate_bitmap);
692   candidates.dispose ();
693   BITMAP_FREE (should_scalarize_away_bitmap);
694   BITMAP_FREE (cannot_scalarize_away_bitmap);
695   free_alloc_pool (access_pool);
696   free_alloc_pool (link_pool);
697   obstack_free (&name_obstack, NULL);
698 
699   pointer_map_traverse (base_access_vec, delete_base_accesses, NULL);
700   pointer_map_destroy (base_access_vec);
701 }
702 
703 /* Remove DECL from candidates for SRA and write REASON to the dump file if
704    there is one.  */
705 static void
disqualify_candidate(tree decl,const char * reason)706 disqualify_candidate (tree decl, const char *reason)
707 {
708   if (bitmap_clear_bit (candidate_bitmap, DECL_UID (decl)))
709     candidates.clear_slot (candidates.find_slot_with_hash (decl,
710 							   DECL_UID (decl),
711 							   NO_INSERT));
712 
713   if (dump_file && (dump_flags & TDF_DETAILS))
714     {
715       fprintf (dump_file, "! Disqualifying ");
716       print_generic_expr (dump_file, decl, 0);
717       fprintf (dump_file, " - %s\n", reason);
718     }
719 }
720 
721 /* Return true iff the type contains a field or an element which does not allow
722    scalarization.  */
723 
724 static bool
type_internals_preclude_sra_p(tree type,const char ** msg)725 type_internals_preclude_sra_p (tree type, const char **msg)
726 {
727   tree fld;
728   tree et;
729 
730   switch (TREE_CODE (type))
731     {
732     case RECORD_TYPE:
733     case UNION_TYPE:
734     case QUAL_UNION_TYPE:
735       for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
736 	if (TREE_CODE (fld) == FIELD_DECL)
737 	  {
738 	    tree ft = TREE_TYPE (fld);
739 
740 	    if (TREE_THIS_VOLATILE (fld))
741 	      {
742 		*msg = "volatile structure field";
743 		return true;
744 	      }
745 	    if (!DECL_FIELD_OFFSET (fld))
746 	      {
747 		*msg = "no structure field offset";
748 		return true;
749 	      }
750 	    if (!DECL_SIZE (fld))
751 	      {
752 		*msg = "zero structure field size";
753 	        return true;
754 	      }
755 	    if (!tree_fits_uhwi_p (DECL_FIELD_OFFSET (fld)))
756 	      {
757 		*msg = "structure field offset not fixed";
758 		return true;
759 	      }
760 	    if (!tree_fits_uhwi_p (DECL_SIZE (fld)))
761 	      {
762 	        *msg = "structure field size not fixed";
763 		return true;
764 	      }
765 	    if (!tree_fits_shwi_p (bit_position (fld)))
766 	      {
767 	        *msg = "structure field size too big";
768 		return true;
769 	      }
770 	    if (AGGREGATE_TYPE_P (ft)
771 		    && int_bit_position (fld) % BITS_PER_UNIT != 0)
772 	      {
773 		*msg = "structure field is bit field";
774 	        return true;
775 	      }
776 
777 	    if (AGGREGATE_TYPE_P (ft) && type_internals_preclude_sra_p (ft, msg))
778 	      return true;
779 	  }
780 
781       return false;
782 
783     case ARRAY_TYPE:
784       et = TREE_TYPE (type);
785 
786       if (TYPE_VOLATILE (et))
787 	{
788 	  *msg = "element type is volatile";
789 	  return true;
790 	}
791 
792       if (AGGREGATE_TYPE_P (et) && type_internals_preclude_sra_p (et, msg))
793 	return true;
794 
795       return false;
796 
797     default:
798       return false;
799     }
800 }
801 
802 /* If T is an SSA_NAME, return NULL if it is not a default def or return its
803    base variable if it is.  Return T if it is not an SSA_NAME.  */
804 
805 static tree
get_ssa_base_param(tree t)806 get_ssa_base_param (tree t)
807 {
808   if (TREE_CODE (t) == SSA_NAME)
809     {
810       if (SSA_NAME_IS_DEFAULT_DEF (t))
811 	return SSA_NAME_VAR (t);
812       else
813 	return NULL_TREE;
814     }
815   return t;
816 }
817 
818 /* Mark a dereference of BASE of distance DIST in a basic block tht STMT
819    belongs to, unless the BB has already been marked as a potentially
820    final.  */
821 
822 static void
mark_parm_dereference(tree base,HOST_WIDE_INT dist,gimple stmt)823 mark_parm_dereference (tree base, HOST_WIDE_INT dist, gimple stmt)
824 {
825   basic_block bb = gimple_bb (stmt);
826   int idx, parm_index = 0;
827   tree parm;
828 
829   if (bitmap_bit_p (final_bbs, bb->index))
830     return;
831 
832   for (parm = DECL_ARGUMENTS (current_function_decl);
833        parm && parm != base;
834        parm = DECL_CHAIN (parm))
835     parm_index++;
836 
837   gcc_assert (parm_index < func_param_count);
838 
839   idx = bb->index * func_param_count + parm_index;
840   if (bb_dereferences[idx] < dist)
841     bb_dereferences[idx] = dist;
842 }
843 
844 /* Allocate an access structure for BASE, OFFSET and SIZE, clear it, fill in
845    the three fields.  Also add it to the vector of accesses corresponding to
846    the base.  Finally, return the new access.  */
847 
848 static struct access *
create_access_1(tree base,HOST_WIDE_INT offset,HOST_WIDE_INT size)849 create_access_1 (tree base, HOST_WIDE_INT offset, HOST_WIDE_INT size)
850 {
851   vec<access_p> *v;
852   struct access *access;
853   void **slot;
854 
855   access = (struct access *) pool_alloc (access_pool);
856   memset (access, 0, sizeof (struct access));
857   access->base = base;
858   access->offset = offset;
859   access->size = size;
860 
861   slot = pointer_map_contains (base_access_vec, base);
862   if (slot)
863     v = (vec<access_p> *) *slot;
864   else
865     vec_alloc (v, 32);
866 
867   v->safe_push (access);
868 
869   *((vec<access_p> **)
870 	pointer_map_insert (base_access_vec, base)) = v;
871 
872   return access;
873 }
874 
875 /* Create and insert access for EXPR. Return created access, or NULL if it is
876    not possible.  */
877 
878 static struct access *
create_access(tree expr,gimple stmt,bool write)879 create_access (tree expr, gimple stmt, bool write)
880 {
881   struct access *access;
882   HOST_WIDE_INT offset, size, max_size;
883   tree base = expr;
884   bool ptr, unscalarizable_region = false;
885 
886   base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
887 
888   if (sra_mode == SRA_MODE_EARLY_IPA
889       && TREE_CODE (base) == MEM_REF)
890     {
891       base = get_ssa_base_param (TREE_OPERAND (base, 0));
892       if (!base)
893 	return NULL;
894       ptr = true;
895     }
896   else
897     ptr = false;
898 
899   if (!DECL_P (base) || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
900     return NULL;
901 
902   if (sra_mode == SRA_MODE_EARLY_IPA)
903     {
904       if (size < 0 || size != max_size)
905 	{
906 	  disqualify_candidate (base, "Encountered a variable sized access.");
907 	  return NULL;
908 	}
909       if (TREE_CODE (expr) == COMPONENT_REF
910 	  && DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
911 	{
912 	  disqualify_candidate (base, "Encountered a bit-field access.");
913 	  return NULL;
914 	}
915       gcc_checking_assert ((offset % BITS_PER_UNIT) == 0);
916 
917       if (ptr)
918 	mark_parm_dereference (base, offset + size, stmt);
919     }
920   else
921     {
922       if (size != max_size)
923 	{
924 	  size = max_size;
925 	  unscalarizable_region = true;
926 	}
927       if (size < 0)
928 	{
929 	  disqualify_candidate (base, "Encountered an unconstrained access.");
930 	  return NULL;
931 	}
932     }
933 
934   access = create_access_1 (base, offset, size);
935   access->expr = expr;
936   access->type = TREE_TYPE (expr);
937   access->write = write;
938   access->grp_unscalarizable_region = unscalarizable_region;
939   access->stmt = stmt;
940 
941   if (TREE_CODE (expr) == COMPONENT_REF
942       && DECL_NONADDRESSABLE_P (TREE_OPERAND (expr, 1)))
943     access->non_addressable = 1;
944 
945   return access;
946 }
947 
948 
949 /* Return true iff TYPE is a RECORD_TYPE with fields that are either of gimple
950    register types or (recursively) records with only these two kinds of fields.
951    It also returns false if any of these records contains a bit-field.  */
952 
953 static bool
type_consists_of_records_p(tree type)954 type_consists_of_records_p (tree type)
955 {
956   tree fld;
957 
958   if (TREE_CODE (type) != RECORD_TYPE)
959     return false;
960 
961   for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
962     if (TREE_CODE (fld) == FIELD_DECL)
963       {
964 	tree ft = TREE_TYPE (fld);
965 
966 	if (DECL_BIT_FIELD (fld))
967 	  return false;
968 
969 	if (!is_gimple_reg_type (ft)
970 	    && !type_consists_of_records_p (ft))
971 	  return false;
972       }
973 
974   return true;
975 }
976 
977 /* Create total_scalarization accesses for all scalar type fields in DECL that
978    must be of a RECORD_TYPE conforming to type_consists_of_records_p.  BASE
979    must be the top-most VAR_DECL representing the variable, OFFSET must be the
980    offset of DECL within BASE.  REF must be the memory reference expression for
981    the given decl.  */
982 
983 static void
completely_scalarize_record(tree base,tree decl,HOST_WIDE_INT offset,tree ref)984 completely_scalarize_record (tree base, tree decl, HOST_WIDE_INT offset,
985 			     tree ref)
986 {
987   tree fld, decl_type = TREE_TYPE (decl);
988 
989   for (fld = TYPE_FIELDS (decl_type); fld; fld = DECL_CHAIN (fld))
990     if (TREE_CODE (fld) == FIELD_DECL)
991       {
992 	HOST_WIDE_INT pos = offset + int_bit_position (fld);
993 	tree ft = TREE_TYPE (fld);
994 	tree nref = build3 (COMPONENT_REF, TREE_TYPE (fld), ref, fld,
995 			    NULL_TREE);
996 
997 	if (is_gimple_reg_type (ft))
998 	  {
999 	    struct access *access;
1000 	    HOST_WIDE_INT size;
1001 
1002 	    size = tree_to_uhwi (DECL_SIZE (fld));
1003 	    access = create_access_1 (base, pos, size);
1004 	    access->expr = nref;
1005 	    access->type = ft;
1006 	    access->grp_total_scalarization = 1;
1007 	    /* Accesses for intraprocedural SRA can have their stmt NULL.  */
1008 	  }
1009 	else
1010 	  completely_scalarize_record (base, fld, pos, nref);
1011       }
1012 }
1013 
1014 /* Create total_scalarization accesses for all scalar type fields in VAR and
1015    for VAR a a whole.  VAR must be of a RECORD_TYPE conforming to
1016    type_consists_of_records_p.   */
1017 
1018 static void
completely_scalarize_var(tree var)1019 completely_scalarize_var (tree var)
1020 {
1021   HOST_WIDE_INT size = tree_to_uhwi (DECL_SIZE (var));
1022   struct access *access;
1023 
1024   access = create_access_1 (var, 0, size);
1025   access->expr = var;
1026   access->type = TREE_TYPE (var);
1027   access->grp_total_scalarization = 1;
1028 
1029   completely_scalarize_record (var, var, 0, var);
1030 }
1031 
1032 /* Return true if REF has an VIEW_CONVERT_EXPR somewhere in it.  */
1033 
1034 static inline bool
contains_view_convert_expr_p(const_tree ref)1035 contains_view_convert_expr_p (const_tree ref)
1036 {
1037   while (handled_component_p (ref))
1038     {
1039       if (TREE_CODE (ref) == VIEW_CONVERT_EXPR)
1040 	return true;
1041       ref = TREE_OPERAND (ref, 0);
1042     }
1043 
1044   return false;
1045 }
1046 
1047 /* Search the given tree for a declaration by skipping handled components and
1048    exclude it from the candidates.  */
1049 
1050 static void
disqualify_base_of_expr(tree t,const char * reason)1051 disqualify_base_of_expr (tree t, const char *reason)
1052 {
1053   t = get_base_address (t);
1054   if (sra_mode == SRA_MODE_EARLY_IPA
1055       && TREE_CODE (t) == MEM_REF)
1056     t = get_ssa_base_param (TREE_OPERAND (t, 0));
1057 
1058   if (t && DECL_P (t))
1059     disqualify_candidate (t, reason);
1060 }
1061 
1062 /* Scan expression EXPR and create access structures for all accesses to
1063    candidates for scalarization.  Return the created access or NULL if none is
1064    created.  */
1065 
1066 static struct access *
build_access_from_expr_1(tree expr,gimple stmt,bool write)1067 build_access_from_expr_1 (tree expr, gimple stmt, bool write)
1068 {
1069   struct access *ret = NULL;
1070   bool partial_ref;
1071 
1072   if (TREE_CODE (expr) == BIT_FIELD_REF
1073       || TREE_CODE (expr) == IMAGPART_EXPR
1074       || TREE_CODE (expr) == REALPART_EXPR)
1075     {
1076       expr = TREE_OPERAND (expr, 0);
1077       partial_ref = true;
1078     }
1079   else
1080     partial_ref = false;
1081 
1082   /* We need to dive through V_C_Es in order to get the size of its parameter
1083      and not the result type.  Ada produces such statements.  We are also
1084      capable of handling the topmost V_C_E but not any of those buried in other
1085      handled components.  */
1086   if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
1087     expr = TREE_OPERAND (expr, 0);
1088 
1089   if (contains_view_convert_expr_p (expr))
1090     {
1091       disqualify_base_of_expr (expr, "V_C_E under a different handled "
1092 			       "component.");
1093       return NULL;
1094     }
1095   if (TREE_THIS_VOLATILE (expr))
1096     {
1097       disqualify_base_of_expr (expr, "part of a volatile reference.");
1098       return NULL;
1099     }
1100 
1101   switch (TREE_CODE (expr))
1102     {
1103     case MEM_REF:
1104       if (TREE_CODE (TREE_OPERAND (expr, 0)) != ADDR_EXPR
1105 	  && sra_mode != SRA_MODE_EARLY_IPA)
1106 	return NULL;
1107       /* fall through */
1108     case VAR_DECL:
1109     case PARM_DECL:
1110     case RESULT_DECL:
1111     case COMPONENT_REF:
1112     case ARRAY_REF:
1113     case ARRAY_RANGE_REF:
1114       ret = create_access (expr, stmt, write);
1115       break;
1116 
1117     default:
1118       break;
1119     }
1120 
1121   if (write && partial_ref && ret)
1122     ret->grp_partial_lhs = 1;
1123 
1124   return ret;
1125 }
1126 
1127 /* Scan expression EXPR and create access structures for all accesses to
1128    candidates for scalarization.  Return true if any access has been inserted.
1129    STMT must be the statement from which the expression is taken, WRITE must be
1130    true if the expression is a store and false otherwise. */
1131 
1132 static bool
build_access_from_expr(tree expr,gimple stmt,bool write)1133 build_access_from_expr (tree expr, gimple stmt, bool write)
1134 {
1135   struct access *access;
1136 
1137   access = build_access_from_expr_1 (expr, stmt, write);
1138   if (access)
1139     {
1140       /* This means the aggregate is accesses as a whole in a way other than an
1141 	 assign statement and thus cannot be removed even if we had a scalar
1142 	 replacement for everything.  */
1143       if (cannot_scalarize_away_bitmap)
1144 	bitmap_set_bit (cannot_scalarize_away_bitmap, DECL_UID (access->base));
1145       return true;
1146     }
1147   return false;
1148 }
1149 
1150 /* Disqualify LHS and RHS for scalarization if STMT must end its basic block in
1151    modes in which it matters, return true iff they have been disqualified.  RHS
1152    may be NULL, in that case ignore it.  If we scalarize an aggregate in
1153    intra-SRA we may need to add statements after each statement.  This is not
1154    possible if a statement unconditionally has to end the basic block.  */
1155 static bool
disqualify_ops_if_throwing_stmt(gimple stmt,tree lhs,tree rhs)1156 disqualify_ops_if_throwing_stmt (gimple stmt, tree lhs, tree rhs)
1157 {
1158   if ((sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
1159       && (stmt_can_throw_internal (stmt) || stmt_ends_bb_p (stmt)))
1160     {
1161       disqualify_base_of_expr (lhs, "LHS of a throwing stmt.");
1162       if (rhs)
1163 	disqualify_base_of_expr (rhs, "RHS of a throwing stmt.");
1164       return true;
1165     }
1166   return false;
1167 }
1168 
1169 /* Scan expressions occurring in STMT, create access structures for all accesses
1170    to candidates for scalarization and remove those candidates which occur in
1171    statements or expressions that prevent them from being split apart.  Return
1172    true if any access has been inserted.  */
1173 
1174 static bool
build_accesses_from_assign(gimple stmt)1175 build_accesses_from_assign (gimple stmt)
1176 {
1177   tree lhs, rhs;
1178   struct access *lacc, *racc;
1179 
1180   if (!gimple_assign_single_p (stmt)
1181       /* Scope clobbers don't influence scalarization.  */
1182       || gimple_clobber_p (stmt))
1183     return false;
1184 
1185   lhs = gimple_assign_lhs (stmt);
1186   rhs = gimple_assign_rhs1 (stmt);
1187 
1188   if (disqualify_ops_if_throwing_stmt (stmt, lhs, rhs))
1189     return false;
1190 
1191   racc = build_access_from_expr_1 (rhs, stmt, false);
1192   lacc = build_access_from_expr_1 (lhs, stmt, true);
1193 
1194   if (lacc)
1195     lacc->grp_assignment_write = 1;
1196 
1197   if (racc)
1198     {
1199       racc->grp_assignment_read = 1;
1200       if (should_scalarize_away_bitmap && !gimple_has_volatile_ops (stmt)
1201 	  && !is_gimple_reg_type (racc->type))
1202 	bitmap_set_bit (should_scalarize_away_bitmap, DECL_UID (racc->base));
1203     }
1204 
1205   if (lacc && racc
1206       && (sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
1207       && !lacc->grp_unscalarizable_region
1208       && !racc->grp_unscalarizable_region
1209       && AGGREGATE_TYPE_P (TREE_TYPE (lhs))
1210       && lacc->size == racc->size
1211       && useless_type_conversion_p (lacc->type, racc->type))
1212     {
1213       struct assign_link *link;
1214 
1215       link = (struct assign_link *) pool_alloc (link_pool);
1216       memset (link, 0, sizeof (struct assign_link));
1217 
1218       link->lacc = lacc;
1219       link->racc = racc;
1220 
1221       add_link_to_rhs (racc, link);
1222     }
1223 
1224   return lacc || racc;
1225 }
1226 
1227 /* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine
1228    GIMPLE_ASM operands with memory constrains which cannot be scalarized.  */
1229 
1230 static bool
asm_visit_addr(gimple,tree op,tree,void *)1231 asm_visit_addr (gimple, tree op, tree, void *)
1232 {
1233   op = get_base_address (op);
1234   if (op
1235       && DECL_P (op))
1236     disqualify_candidate (op, "Non-scalarizable GIMPLE_ASM operand.");
1237 
1238   return false;
1239 }
1240 
1241 /* Return true iff callsite CALL has at least as many actual arguments as there
1242    are formal parameters of the function currently processed by IPA-SRA and
1243    that their types match.  */
1244 
1245 static inline bool
callsite_arguments_match_p(gimple call)1246 callsite_arguments_match_p (gimple call)
1247 {
1248   if (gimple_call_num_args (call) < (unsigned) func_param_count)
1249     return false;
1250 
1251   tree parm;
1252   int i;
1253   for (parm = DECL_ARGUMENTS (current_function_decl), i = 0;
1254        parm;
1255        parm = DECL_CHAIN (parm), i++)
1256     {
1257       tree arg = gimple_call_arg (call, i);
1258       if (!useless_type_conversion_p (TREE_TYPE (parm), TREE_TYPE (arg)))
1259 	return false;
1260     }
1261   return true;
1262 }
1263 
1264 /* Scan function and look for interesting expressions and create access
1265    structures for them.  Return true iff any access is created.  */
1266 
1267 static bool
scan_function(void)1268 scan_function (void)
1269 {
1270   basic_block bb;
1271   bool ret = false;
1272 
1273   FOR_EACH_BB_FN (bb, cfun)
1274     {
1275       gimple_stmt_iterator gsi;
1276       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1277 	{
1278 	  gimple stmt = gsi_stmt (gsi);
1279 	  tree t;
1280 	  unsigned i;
1281 
1282 	  if (final_bbs && stmt_can_throw_external (stmt))
1283 	    bitmap_set_bit (final_bbs, bb->index);
1284 	  switch (gimple_code (stmt))
1285 	    {
1286 	    case GIMPLE_RETURN:
1287 	      t = gimple_return_retval (stmt);
1288 	      if (t != NULL_TREE)
1289 		ret |= build_access_from_expr (t, stmt, false);
1290 	      if (final_bbs)
1291 		bitmap_set_bit (final_bbs, bb->index);
1292 	      break;
1293 
1294 	    case GIMPLE_ASSIGN:
1295 	      ret |= build_accesses_from_assign (stmt);
1296 	      break;
1297 
1298 	    case GIMPLE_CALL:
1299 	      for (i = 0; i < gimple_call_num_args (stmt); i++)
1300 		ret |= build_access_from_expr (gimple_call_arg (stmt, i),
1301 					       stmt, false);
1302 
1303 	      if (sra_mode == SRA_MODE_EARLY_IPA)
1304 		{
1305 		  tree dest = gimple_call_fndecl (stmt);
1306 		  int flags = gimple_call_flags (stmt);
1307 
1308 		  if (dest)
1309 		    {
1310 		      if (DECL_BUILT_IN_CLASS (dest) == BUILT_IN_NORMAL
1311 			  && DECL_FUNCTION_CODE (dest) == BUILT_IN_APPLY_ARGS)
1312 			encountered_apply_args = true;
1313 		      if (recursive_call_p (current_function_decl, dest))
1314 			{
1315 			  encountered_recursive_call = true;
1316 			  if (!callsite_arguments_match_p (stmt))
1317 			    encountered_unchangable_recursive_call = true;
1318 			}
1319 		    }
1320 
1321 		  if (final_bbs
1322 		      && (flags & (ECF_CONST | ECF_PURE)) == 0)
1323 		    bitmap_set_bit (final_bbs, bb->index);
1324 		}
1325 
1326 	      t = gimple_call_lhs (stmt);
1327 	      if (t && !disqualify_ops_if_throwing_stmt (stmt, t, NULL))
1328 		ret |= build_access_from_expr (t, stmt, true);
1329 	      break;
1330 
1331 	    case GIMPLE_ASM:
1332 	      walk_stmt_load_store_addr_ops (stmt, NULL, NULL, NULL,
1333 					     asm_visit_addr);
1334 	      if (final_bbs)
1335 		bitmap_set_bit (final_bbs, bb->index);
1336 
1337 	      for (i = 0; i < gimple_asm_ninputs (stmt); i++)
1338 		{
1339 		  t = TREE_VALUE (gimple_asm_input_op (stmt, i));
1340 		  ret |= build_access_from_expr (t, stmt, false);
1341 		}
1342 	      for (i = 0; i < gimple_asm_noutputs (stmt); i++)
1343 		{
1344 		  t = TREE_VALUE (gimple_asm_output_op (stmt, i));
1345 		  ret |= build_access_from_expr (t, stmt, true);
1346 		}
1347 	      break;
1348 
1349 	    default:
1350 	      break;
1351 	    }
1352 	}
1353     }
1354 
1355   return ret;
1356 }
1357 
1358 /* Helper of QSORT function. There are pointers to accesses in the array.  An
1359    access is considered smaller than another if it has smaller offset or if the
1360    offsets are the same but is size is bigger. */
1361 
1362 static int
compare_access_positions(const void * a,const void * b)1363 compare_access_positions (const void *a, const void *b)
1364 {
1365   const access_p *fp1 = (const access_p *) a;
1366   const access_p *fp2 = (const access_p *) b;
1367   const access_p f1 = *fp1;
1368   const access_p f2 = *fp2;
1369 
1370   if (f1->offset != f2->offset)
1371     return f1->offset < f2->offset ? -1 : 1;
1372 
1373   if (f1->size == f2->size)
1374     {
1375       if (f1->type == f2->type)
1376 	return 0;
1377       /* Put any non-aggregate type before any aggregate type.  */
1378       else if (!is_gimple_reg_type (f1->type)
1379 	  && is_gimple_reg_type (f2->type))
1380 	return 1;
1381       else if (is_gimple_reg_type (f1->type)
1382 	       && !is_gimple_reg_type (f2->type))
1383 	return -1;
1384       /* Put any complex or vector type before any other scalar type.  */
1385       else if (TREE_CODE (f1->type) != COMPLEX_TYPE
1386 	       && TREE_CODE (f1->type) != VECTOR_TYPE
1387 	       && (TREE_CODE (f2->type) == COMPLEX_TYPE
1388 		   || TREE_CODE (f2->type) == VECTOR_TYPE))
1389 	return 1;
1390       else if ((TREE_CODE (f1->type) == COMPLEX_TYPE
1391 		|| TREE_CODE (f1->type) == VECTOR_TYPE)
1392 	       && TREE_CODE (f2->type) != COMPLEX_TYPE
1393 	       && TREE_CODE (f2->type) != VECTOR_TYPE)
1394 	return -1;
1395       /* Put the integral type with the bigger precision first.  */
1396       else if (INTEGRAL_TYPE_P (f1->type)
1397 	       && INTEGRAL_TYPE_P (f2->type))
1398 	return TYPE_PRECISION (f2->type) - TYPE_PRECISION (f1->type);
1399       /* Put any integral type with non-full precision last.  */
1400       else if (INTEGRAL_TYPE_P (f1->type)
1401 	       && (TREE_INT_CST_LOW (TYPE_SIZE (f1->type))
1402 		   != TYPE_PRECISION (f1->type)))
1403 	return 1;
1404       else if (INTEGRAL_TYPE_P (f2->type)
1405 	       && (TREE_INT_CST_LOW (TYPE_SIZE (f2->type))
1406 		   != TYPE_PRECISION (f2->type)))
1407 	return -1;
1408       /* Stabilize the sort.  */
1409       return TYPE_UID (f1->type) - TYPE_UID (f2->type);
1410     }
1411 
1412   /* We want the bigger accesses first, thus the opposite operator in the next
1413      line: */
1414   return f1->size > f2->size ? -1 : 1;
1415 }
1416 
1417 
1418 /* Append a name of the declaration to the name obstack.  A helper function for
1419    make_fancy_name.  */
1420 
1421 static void
make_fancy_decl_name(tree decl)1422 make_fancy_decl_name (tree decl)
1423 {
1424   char buffer[32];
1425 
1426   tree name = DECL_NAME (decl);
1427   if (name)
1428     obstack_grow (&name_obstack, IDENTIFIER_POINTER (name),
1429 		  IDENTIFIER_LENGTH (name));
1430   else
1431     {
1432       sprintf (buffer, "D%u", DECL_UID (decl));
1433       obstack_grow (&name_obstack, buffer, strlen (buffer));
1434     }
1435 }
1436 
1437 /* Helper for make_fancy_name.  */
1438 
1439 static void
make_fancy_name_1(tree expr)1440 make_fancy_name_1 (tree expr)
1441 {
1442   char buffer[32];
1443   tree index;
1444 
1445   if (DECL_P (expr))
1446     {
1447       make_fancy_decl_name (expr);
1448       return;
1449     }
1450 
1451   switch (TREE_CODE (expr))
1452     {
1453     case COMPONENT_REF:
1454       make_fancy_name_1 (TREE_OPERAND (expr, 0));
1455       obstack_1grow (&name_obstack, '$');
1456       make_fancy_decl_name (TREE_OPERAND (expr, 1));
1457       break;
1458 
1459     case ARRAY_REF:
1460       make_fancy_name_1 (TREE_OPERAND (expr, 0));
1461       obstack_1grow (&name_obstack, '$');
1462       /* Arrays with only one element may not have a constant as their
1463 	 index. */
1464       index = TREE_OPERAND (expr, 1);
1465       if (TREE_CODE (index) != INTEGER_CST)
1466 	break;
1467       sprintf (buffer, HOST_WIDE_INT_PRINT_DEC, TREE_INT_CST_LOW (index));
1468       obstack_grow (&name_obstack, buffer, strlen (buffer));
1469       break;
1470 
1471     case ADDR_EXPR:
1472       make_fancy_name_1 (TREE_OPERAND (expr, 0));
1473       break;
1474 
1475     case MEM_REF:
1476       make_fancy_name_1 (TREE_OPERAND (expr, 0));
1477       if (!integer_zerop (TREE_OPERAND (expr, 1)))
1478 	{
1479 	  obstack_1grow (&name_obstack, '$');
1480 	  sprintf (buffer, HOST_WIDE_INT_PRINT_DEC,
1481 		   TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)));
1482 	  obstack_grow (&name_obstack, buffer, strlen (buffer));
1483 	}
1484       break;
1485 
1486     case BIT_FIELD_REF:
1487     case REALPART_EXPR:
1488     case IMAGPART_EXPR:
1489       gcc_unreachable (); 	/* we treat these as scalars.  */
1490       break;
1491     default:
1492       break;
1493     }
1494 }
1495 
1496 /* Create a human readable name for replacement variable of ACCESS.  */
1497 
1498 static char *
make_fancy_name(tree expr)1499 make_fancy_name (tree expr)
1500 {
1501   make_fancy_name_1 (expr);
1502   obstack_1grow (&name_obstack, '\0');
1503   return XOBFINISH (&name_obstack, char *);
1504 }
1505 
1506 /* Construct a MEM_REF that would reference a part of aggregate BASE of type
1507    EXP_TYPE at the given OFFSET.  If BASE is something for which
1508    get_addr_base_and_unit_offset returns NULL, gsi must be non-NULL and is used
1509    to insert new statements either before or below the current one as specified
1510    by INSERT_AFTER.  This function is not capable of handling bitfields.
1511 
1512    BASE must be either a declaration or a memory reference that has correct
1513    alignment ifformation embeded in it (e.g. a pre-existing one in SRA).  */
1514 
1515 tree
build_ref_for_offset(location_t loc,tree base,HOST_WIDE_INT offset,tree exp_type,gimple_stmt_iterator * gsi,bool insert_after)1516 build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset,
1517 		      tree exp_type, gimple_stmt_iterator *gsi,
1518 		      bool insert_after)
1519 {
1520   tree prev_base = base;
1521   tree off;
1522   tree mem_ref;
1523   HOST_WIDE_INT base_offset;
1524   unsigned HOST_WIDE_INT misalign;
1525   unsigned int align;
1526 
1527   gcc_checking_assert (offset % BITS_PER_UNIT == 0);
1528   get_object_alignment_1 (base, &align, &misalign);
1529   base = get_addr_base_and_unit_offset (base, &base_offset);
1530 
1531   /* get_addr_base_and_unit_offset returns NULL for references with a variable
1532      offset such as array[var_index].  */
1533   if (!base)
1534     {
1535       gimple stmt;
1536       tree tmp, addr;
1537 
1538       gcc_checking_assert (gsi);
1539       tmp = make_ssa_name (build_pointer_type (TREE_TYPE (prev_base)), NULL);
1540       addr = build_fold_addr_expr (unshare_expr (prev_base));
1541       STRIP_USELESS_TYPE_CONVERSION (addr);
1542       stmt = gimple_build_assign (tmp, addr);
1543       gimple_set_location (stmt, loc);
1544       if (insert_after)
1545 	gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
1546       else
1547 	gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
1548 
1549       off = build_int_cst (reference_alias_ptr_type (prev_base),
1550 			   offset / BITS_PER_UNIT);
1551       base = tmp;
1552     }
1553   else if (TREE_CODE (base) == MEM_REF)
1554     {
1555       off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
1556 			   base_offset + offset / BITS_PER_UNIT);
1557       off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
1558       base = unshare_expr (TREE_OPERAND (base, 0));
1559     }
1560   else
1561     {
1562       off = build_int_cst (reference_alias_ptr_type (base),
1563 			   base_offset + offset / BITS_PER_UNIT);
1564       base = build_fold_addr_expr (unshare_expr (base));
1565     }
1566 
1567   misalign = (misalign + offset) & (align - 1);
1568   if (misalign != 0)
1569     align = (misalign & -misalign);
1570   if (align < TYPE_ALIGN (exp_type))
1571     exp_type = build_aligned_type (exp_type, align);
1572 
1573   mem_ref = fold_build2_loc (loc, MEM_REF, exp_type, base, off);
1574   if (TREE_THIS_VOLATILE (prev_base))
1575     TREE_THIS_VOLATILE (mem_ref) = 1;
1576   if (TREE_SIDE_EFFECTS (prev_base))
1577     TREE_SIDE_EFFECTS (mem_ref) = 1;
1578   return mem_ref;
1579 }
1580 
1581 /* Construct a memory reference to a part of an aggregate BASE at the given
1582    OFFSET and of the same type as MODEL.  In case this is a reference to a
1583    bit-field, the function will replicate the last component_ref of model's
1584    expr to access it.  GSI and INSERT_AFTER have the same meaning as in
1585    build_ref_for_offset.  */
1586 
1587 static tree
build_ref_for_model(location_t loc,tree base,HOST_WIDE_INT offset,struct access * model,gimple_stmt_iterator * gsi,bool insert_after)1588 build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
1589 		     struct access *model, gimple_stmt_iterator *gsi,
1590 		     bool insert_after)
1591 {
1592   if (TREE_CODE (model->expr) == COMPONENT_REF
1593       && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
1594     {
1595       /* This access represents a bit-field.  */
1596       tree t, exp_type, fld = TREE_OPERAND (model->expr, 1);
1597 
1598       offset -= int_bit_position (fld);
1599       exp_type = TREE_TYPE (TREE_OPERAND (model->expr, 0));
1600       t = build_ref_for_offset (loc, base, offset, exp_type, gsi, insert_after);
1601       return fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (fld), t, fld,
1602 			      NULL_TREE);
1603     }
1604   else
1605     return build_ref_for_offset (loc, base, offset, model->type,
1606 				 gsi, insert_after);
1607 }
1608 
1609 /* Attempt to build a memory reference that we could but into a gimple
1610    debug_bind statement.  Similar to build_ref_for_model but punts if it has to
1611    create statements and return s NULL instead.  This function also ignores
1612    alignment issues and so its results should never end up in non-debug
1613    statements.  */
1614 
1615 static tree
build_debug_ref_for_model(location_t loc,tree base,HOST_WIDE_INT offset,struct access * model)1616 build_debug_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
1617 			   struct access *model)
1618 {
1619   HOST_WIDE_INT base_offset;
1620   tree off;
1621 
1622   if (TREE_CODE (model->expr) == COMPONENT_REF
1623       && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
1624     return NULL_TREE;
1625 
1626   base = get_addr_base_and_unit_offset (base, &base_offset);
1627   if (!base)
1628     return NULL_TREE;
1629   if (TREE_CODE (base) == MEM_REF)
1630     {
1631       off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
1632 			   base_offset + offset / BITS_PER_UNIT);
1633       off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
1634       base = unshare_expr (TREE_OPERAND (base, 0));
1635     }
1636   else
1637     {
1638       off = build_int_cst (reference_alias_ptr_type (base),
1639 			   base_offset + offset / BITS_PER_UNIT);
1640       base = build_fold_addr_expr (unshare_expr (base));
1641     }
1642 
1643   return fold_build2_loc (loc, MEM_REF, model->type, base, off);
1644 }
1645 
1646 /* Construct a memory reference consisting of component_refs and array_refs to
1647    a part of an aggregate *RES (which is of type TYPE).  The requested part
1648    should have type EXP_TYPE at be the given OFFSET.  This function might not
1649    succeed, it returns true when it does and only then *RES points to something
1650    meaningful.  This function should be used only to build expressions that we
1651    might need to present to user (e.g. in warnings).  In all other situations,
1652    build_ref_for_model or build_ref_for_offset should be used instead.  */
1653 
1654 static bool
build_user_friendly_ref_for_offset(tree * res,tree type,HOST_WIDE_INT offset,tree exp_type)1655 build_user_friendly_ref_for_offset (tree *res, tree type, HOST_WIDE_INT offset,
1656 				    tree exp_type)
1657 {
1658   while (1)
1659     {
1660       tree fld;
1661       tree tr_size, index, minidx;
1662       HOST_WIDE_INT el_size;
1663 
1664       if (offset == 0 && exp_type
1665 	  && types_compatible_p (exp_type, type))
1666 	return true;
1667 
1668       switch (TREE_CODE (type))
1669 	{
1670 	case UNION_TYPE:
1671 	case QUAL_UNION_TYPE:
1672 	case RECORD_TYPE:
1673 	  for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
1674 	    {
1675 	      HOST_WIDE_INT pos, size;
1676 	      tree tr_pos, expr, *expr_ptr;
1677 
1678 	      if (TREE_CODE (fld) != FIELD_DECL)
1679 		continue;
1680 
1681 	      tr_pos = bit_position (fld);
1682 	      if (!tr_pos || !tree_fits_uhwi_p (tr_pos))
1683 		continue;
1684 	      pos = tree_to_uhwi (tr_pos);
1685 	      gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0);
1686 	      tr_size = DECL_SIZE (fld);
1687 	      if (!tr_size || !tree_fits_uhwi_p (tr_size))
1688 		continue;
1689 	      size = tree_to_uhwi (tr_size);
1690 	      if (size == 0)
1691 		{
1692 		  if (pos != offset)
1693 		    continue;
1694 		}
1695 	      else if (pos > offset || (pos + size) <= offset)
1696 		continue;
1697 
1698 	      expr = build3 (COMPONENT_REF, TREE_TYPE (fld), *res, fld,
1699 			     NULL_TREE);
1700 	      expr_ptr = &expr;
1701 	      if (build_user_friendly_ref_for_offset (expr_ptr, TREE_TYPE (fld),
1702 						      offset - pos, exp_type))
1703 		{
1704 		  *res = expr;
1705 		  return true;
1706 		}
1707 	    }
1708 	  return false;
1709 
1710 	case ARRAY_TYPE:
1711 	  tr_size = TYPE_SIZE (TREE_TYPE (type));
1712 	  if (!tr_size || !tree_fits_uhwi_p (tr_size))
1713 	    return false;
1714 	  el_size = tree_to_uhwi (tr_size);
1715 
1716 	  minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
1717 	  if (TREE_CODE (minidx) != INTEGER_CST || el_size == 0)
1718 	    return false;
1719 	  index = build_int_cst (TYPE_DOMAIN (type), offset / el_size);
1720 	  if (!integer_zerop (minidx))
1721 	    index = int_const_binop (PLUS_EXPR, index, minidx);
1722 	  *res = build4 (ARRAY_REF, TREE_TYPE (type), *res, index,
1723 			 NULL_TREE, NULL_TREE);
1724 	  offset = offset % el_size;
1725 	  type = TREE_TYPE (type);
1726 	  break;
1727 
1728 	default:
1729 	  if (offset != 0)
1730 	    return false;
1731 
1732 	  if (exp_type)
1733 	    return false;
1734 	  else
1735 	    return true;
1736 	}
1737     }
1738 }
1739 
1740 /* Return true iff TYPE is stdarg va_list type.  */
1741 
1742 static inline bool
is_va_list_type(tree type)1743 is_va_list_type (tree type)
1744 {
1745   return TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (va_list_type_node);
1746 }
1747 
1748 /* Print message to dump file why a variable was rejected. */
1749 
1750 static void
reject(tree var,const char * msg)1751 reject (tree var, const char *msg)
1752 {
1753   if (dump_file && (dump_flags & TDF_DETAILS))
1754     {
1755       fprintf (dump_file, "Rejected (%d): %s: ", DECL_UID (var), msg);
1756       print_generic_expr (dump_file, var, 0);
1757       fprintf (dump_file, "\n");
1758     }
1759 }
1760 
1761 /* Return true if VAR is a candidate for SRA.  */
1762 
1763 static bool
maybe_add_sra_candidate(tree var)1764 maybe_add_sra_candidate (tree var)
1765 {
1766   tree type = TREE_TYPE (var);
1767   const char *msg;
1768   tree_node **slot;
1769 
1770   if (!AGGREGATE_TYPE_P (type))
1771     {
1772       reject (var, "not aggregate");
1773       return false;
1774     }
1775   if (needs_to_live_in_memory (var))
1776     {
1777       reject (var, "needs to live in memory");
1778       return false;
1779     }
1780   if (TREE_THIS_VOLATILE (var))
1781     {
1782       reject (var, "is volatile");
1783       return false;
1784     }
1785   if (!COMPLETE_TYPE_P (type))
1786     {
1787       reject (var, "has incomplete type");
1788       return false;
1789     }
1790   if (!tree_fits_uhwi_p (TYPE_SIZE (type)))
1791     {
1792       reject (var, "type size not fixed");
1793       return false;
1794     }
1795   if (tree_to_uhwi (TYPE_SIZE (type)) == 0)
1796     {
1797       reject (var, "type size is zero");
1798       return false;
1799     }
1800   if (type_internals_preclude_sra_p (type, &msg))
1801     {
1802       reject (var, msg);
1803       return false;
1804     }
1805   if (/* Fix for PR 41089.  tree-stdarg.c needs to have va_lists intact but
1806 	 we also want to schedule it rather late.  Thus we ignore it in
1807 	 the early pass. */
1808       (sra_mode == SRA_MODE_EARLY_INTRA
1809        && is_va_list_type (type)))
1810     {
1811       reject (var, "is va_list");
1812       return false;
1813     }
1814 
1815   bitmap_set_bit (candidate_bitmap, DECL_UID (var));
1816   slot = candidates.find_slot_with_hash (var, DECL_UID (var), INSERT);
1817   *slot = var;
1818 
1819   if (dump_file && (dump_flags & TDF_DETAILS))
1820     {
1821       fprintf (dump_file, "Candidate (%d): ", DECL_UID (var));
1822       print_generic_expr (dump_file, var, 0);
1823       fprintf (dump_file, "\n");
1824     }
1825 
1826   return true;
1827 }
1828 
1829 /* The very first phase of intraprocedural SRA.  It marks in candidate_bitmap
1830    those with type which is suitable for scalarization.  */
1831 
1832 static bool
find_var_candidates(void)1833 find_var_candidates (void)
1834 {
1835   tree var, parm;
1836   unsigned int i;
1837   bool ret = false;
1838 
1839   for (parm = DECL_ARGUMENTS (current_function_decl);
1840        parm;
1841        parm = DECL_CHAIN (parm))
1842     ret |= maybe_add_sra_candidate (parm);
1843 
1844   FOR_EACH_LOCAL_DECL (cfun, i, var)
1845     {
1846       if (TREE_CODE (var) != VAR_DECL)
1847         continue;
1848 
1849       ret |= maybe_add_sra_candidate (var);
1850     }
1851 
1852   return ret;
1853 }
1854 
1855 /* Sort all accesses for the given variable, check for partial overlaps and
1856    return NULL if there are any.  If there are none, pick a representative for
1857    each combination of offset and size and create a linked list out of them.
1858    Return the pointer to the first representative and make sure it is the first
1859    one in the vector of accesses.  */
1860 
1861 static struct access *
sort_and_splice_var_accesses(tree var)1862 sort_and_splice_var_accesses (tree var)
1863 {
1864   int i, j, access_count;
1865   struct access *res, **prev_acc_ptr = &res;
1866   vec<access_p> *access_vec;
1867   bool first = true;
1868   HOST_WIDE_INT low = -1, high = 0;
1869 
1870   access_vec = get_base_access_vector (var);
1871   if (!access_vec)
1872     return NULL;
1873   access_count = access_vec->length ();
1874 
1875   /* Sort by <OFFSET, SIZE>.  */
1876   access_vec->qsort (compare_access_positions);
1877 
1878   i = 0;
1879   while (i < access_count)
1880     {
1881       struct access *access = (*access_vec)[i];
1882       bool grp_write = access->write;
1883       bool grp_read = !access->write;
1884       bool grp_scalar_write = access->write
1885 	&& is_gimple_reg_type (access->type);
1886       bool grp_scalar_read = !access->write
1887 	&& is_gimple_reg_type (access->type);
1888       bool grp_assignment_read = access->grp_assignment_read;
1889       bool grp_assignment_write = access->grp_assignment_write;
1890       bool multiple_scalar_reads = false;
1891       bool total_scalarization = access->grp_total_scalarization;
1892       bool grp_partial_lhs = access->grp_partial_lhs;
1893       bool first_scalar = is_gimple_reg_type (access->type);
1894       bool unscalarizable_region = access->grp_unscalarizable_region;
1895 
1896       if (first || access->offset >= high)
1897 	{
1898 	  first = false;
1899 	  low = access->offset;
1900 	  high = access->offset + access->size;
1901 	}
1902       else if (access->offset > low && access->offset + access->size > high)
1903 	return NULL;
1904       else
1905 	gcc_assert (access->offset >= low
1906 		    && access->offset + access->size <= high);
1907 
1908       j = i + 1;
1909       while (j < access_count)
1910 	{
1911 	  struct access *ac2 = (*access_vec)[j];
1912 	  if (ac2->offset != access->offset || ac2->size != access->size)
1913 	    break;
1914 	  if (ac2->write)
1915 	    {
1916 	      grp_write = true;
1917 	      grp_scalar_write = (grp_scalar_write
1918 				  || is_gimple_reg_type (ac2->type));
1919 	    }
1920 	  else
1921 	    {
1922 	      grp_read = true;
1923 	      if (is_gimple_reg_type (ac2->type))
1924 		{
1925 		  if (grp_scalar_read)
1926 		    multiple_scalar_reads = true;
1927 		  else
1928 		    grp_scalar_read = true;
1929 		}
1930 	    }
1931 	  grp_assignment_read |= ac2->grp_assignment_read;
1932 	  grp_assignment_write |= ac2->grp_assignment_write;
1933 	  grp_partial_lhs |= ac2->grp_partial_lhs;
1934 	  unscalarizable_region |= ac2->grp_unscalarizable_region;
1935 	  total_scalarization |= ac2->grp_total_scalarization;
1936 	  relink_to_new_repr (access, ac2);
1937 
1938 	  /* If there are both aggregate-type and scalar-type accesses with
1939 	     this combination of size and offset, the comparison function
1940 	     should have put the scalars first.  */
1941 	  gcc_assert (first_scalar || !is_gimple_reg_type (ac2->type));
1942 	  ac2->group_representative = access;
1943 	  j++;
1944 	}
1945 
1946       i = j;
1947 
1948       access->group_representative = access;
1949       access->grp_write = grp_write;
1950       access->grp_read = grp_read;
1951       access->grp_scalar_read = grp_scalar_read;
1952       access->grp_scalar_write = grp_scalar_write;
1953       access->grp_assignment_read = grp_assignment_read;
1954       access->grp_assignment_write = grp_assignment_write;
1955       access->grp_hint = multiple_scalar_reads || total_scalarization;
1956       access->grp_total_scalarization = total_scalarization;
1957       access->grp_partial_lhs = grp_partial_lhs;
1958       access->grp_unscalarizable_region = unscalarizable_region;
1959       if (access->first_link)
1960 	add_access_to_work_queue (access);
1961 
1962       *prev_acc_ptr = access;
1963       prev_acc_ptr = &access->next_grp;
1964     }
1965 
1966   gcc_assert (res == (*access_vec)[0]);
1967   return res;
1968 }
1969 
1970 /* Create a variable for the given ACCESS which determines the type, name and a
1971    few other properties.  Return the variable declaration and store it also to
1972    ACCESS->replacement.  */
1973 
1974 static tree
create_access_replacement(struct access * access)1975 create_access_replacement (struct access *access)
1976 {
1977   tree repl;
1978 
1979   if (access->grp_to_be_debug_replaced)
1980     {
1981       repl = create_tmp_var_raw (access->type, NULL);
1982       DECL_CONTEXT (repl) = current_function_decl;
1983     }
1984   else
1985     repl = create_tmp_var (access->type, "SR");
1986   if (TREE_CODE (access->type) == COMPLEX_TYPE
1987       || TREE_CODE (access->type) == VECTOR_TYPE)
1988     {
1989       if (!access->grp_partial_lhs)
1990 	DECL_GIMPLE_REG_P (repl) = 1;
1991     }
1992   else if (access->grp_partial_lhs
1993 	   && is_gimple_reg_type (access->type))
1994     TREE_ADDRESSABLE (repl) = 1;
1995 
1996   DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base);
1997   DECL_ARTIFICIAL (repl) = 1;
1998   DECL_IGNORED_P (repl) = DECL_IGNORED_P (access->base);
1999 
2000   if (DECL_NAME (access->base)
2001       && !DECL_IGNORED_P (access->base)
2002       && !DECL_ARTIFICIAL (access->base))
2003     {
2004       char *pretty_name = make_fancy_name (access->expr);
2005       tree debug_expr = unshare_expr_without_location (access->expr), d;
2006       bool fail = false;
2007 
2008       DECL_NAME (repl) = get_identifier (pretty_name);
2009       obstack_free (&name_obstack, pretty_name);
2010 
2011       /* Get rid of any SSA_NAMEs embedded in debug_expr,
2012 	 as DECL_DEBUG_EXPR isn't considered when looking for still
2013 	 used SSA_NAMEs and thus they could be freed.  All debug info
2014 	 generation cares is whether something is constant or variable
2015 	 and that get_ref_base_and_extent works properly on the
2016 	 expression.  It cannot handle accesses at a non-constant offset
2017 	 though, so just give up in those cases.  */
2018       for (d = debug_expr;
2019 	   !fail && (handled_component_p (d) || TREE_CODE (d) == MEM_REF);
2020 	   d = TREE_OPERAND (d, 0))
2021 	switch (TREE_CODE (d))
2022 	  {
2023 	  case ARRAY_REF:
2024 	  case ARRAY_RANGE_REF:
2025 	    if (TREE_OPERAND (d, 1)
2026 		&& TREE_CODE (TREE_OPERAND (d, 1)) != INTEGER_CST)
2027 	      fail = true;
2028 	    if (TREE_OPERAND (d, 3)
2029 		&& TREE_CODE (TREE_OPERAND (d, 3)) != INTEGER_CST)
2030 	      fail = true;
2031 	    /* FALLTHRU */
2032 	  case COMPONENT_REF:
2033 	    if (TREE_OPERAND (d, 2)
2034 		&& TREE_CODE (TREE_OPERAND (d, 2)) != INTEGER_CST)
2035 	      fail = true;
2036 	    break;
2037 	  case MEM_REF:
2038 	    if (TREE_CODE (TREE_OPERAND (d, 0)) != ADDR_EXPR)
2039 	      fail = true;
2040 	    else
2041 	      d = TREE_OPERAND (d, 0);
2042 	    break;
2043 	  default:
2044 	    break;
2045 	  }
2046       if (!fail)
2047 	{
2048 	  SET_DECL_DEBUG_EXPR (repl, debug_expr);
2049 	  DECL_HAS_DEBUG_EXPR_P (repl) = 1;
2050 	}
2051       if (access->grp_no_warning)
2052 	TREE_NO_WARNING (repl) = 1;
2053       else
2054 	TREE_NO_WARNING (repl) = TREE_NO_WARNING (access->base);
2055     }
2056   else
2057     TREE_NO_WARNING (repl) = 1;
2058 
2059   if (dump_file)
2060     {
2061       if (access->grp_to_be_debug_replaced)
2062 	{
2063 	  fprintf (dump_file, "Created a debug-only replacement for ");
2064 	  print_generic_expr (dump_file, access->base, 0);
2065 	  fprintf (dump_file, " offset: %u, size: %u\n",
2066 		   (unsigned) access->offset, (unsigned) access->size);
2067 	}
2068       else
2069 	{
2070 	  fprintf (dump_file, "Created a replacement for ");
2071 	  print_generic_expr (dump_file, access->base, 0);
2072 	  fprintf (dump_file, " offset: %u, size: %u: ",
2073 		   (unsigned) access->offset, (unsigned) access->size);
2074 	  print_generic_expr (dump_file, repl, 0);
2075 	  fprintf (dump_file, "\n");
2076 	}
2077     }
2078   sra_stats.replacements++;
2079 
2080   return repl;
2081 }
2082 
2083 /* Return ACCESS scalar replacement, create it if it does not exist yet.  */
2084 
2085 static inline tree
get_access_replacement(struct access * access)2086 get_access_replacement (struct access *access)
2087 {
2088   gcc_checking_assert (access->replacement_decl);
2089   return access->replacement_decl;
2090 }
2091 
2092 
2093 /* Build a subtree of accesses rooted in *ACCESS, and move the pointer in the
2094    linked list along the way.  Stop when *ACCESS is NULL or the access pointed
2095    to it is not "within" the root.  Return false iff some accesses partially
2096    overlap.  */
2097 
2098 static bool
build_access_subtree(struct access ** access)2099 build_access_subtree (struct access **access)
2100 {
2101   struct access *root = *access, *last_child = NULL;
2102   HOST_WIDE_INT limit = root->offset + root->size;
2103 
2104   *access = (*access)->next_grp;
2105   while  (*access && (*access)->offset + (*access)->size <= limit)
2106     {
2107       if (!last_child)
2108 	root->first_child = *access;
2109       else
2110 	last_child->next_sibling = *access;
2111       last_child = *access;
2112 
2113       if (!build_access_subtree (access))
2114 	return false;
2115     }
2116 
2117   if (*access && (*access)->offset < limit)
2118     return false;
2119 
2120   return true;
2121 }
2122 
2123 /* Build a tree of access representatives, ACCESS is the pointer to the first
2124    one, others are linked in a list by the next_grp field.  Return false iff
2125    some accesses partially overlap.  */
2126 
2127 static bool
build_access_trees(struct access * access)2128 build_access_trees (struct access *access)
2129 {
2130   while (access)
2131     {
2132       struct access *root = access;
2133 
2134       if (!build_access_subtree (&access))
2135 	return false;
2136       root->next_grp = access;
2137     }
2138   return true;
2139 }
2140 
2141 /* Return true if expr contains some ARRAY_REFs into a variable bounded
2142    array.  */
2143 
2144 static bool
expr_with_var_bounded_array_refs_p(tree expr)2145 expr_with_var_bounded_array_refs_p (tree expr)
2146 {
2147   while (handled_component_p (expr))
2148     {
2149       if (TREE_CODE (expr) == ARRAY_REF
2150 	  && !tree_fits_shwi_p (array_ref_low_bound (expr)))
2151 	return true;
2152       expr = TREE_OPERAND (expr, 0);
2153     }
2154   return false;
2155 }
2156 
2157 /* Analyze the subtree of accesses rooted in ROOT, scheduling replacements when
2158    both seeming beneficial and when ALLOW_REPLACEMENTS allows it.  Also set all
2159    sorts of access flags appropriately along the way, notably always set
2160    grp_read and grp_assign_read according to MARK_READ and grp_write when
2161    MARK_WRITE is true.
2162 
2163    Creating a replacement for a scalar access is considered beneficial if its
2164    grp_hint is set (this means we are either attempting total scalarization or
2165    there is more than one direct read access) or according to the following
2166    table:
2167 
2168    Access written to through a scalar type (once or more times)
2169    |
2170    |	Written to in an assignment statement
2171    |	|
2172    |	|	Access read as scalar _once_
2173    |	|	|
2174    |   	|	|	Read in an assignment statement
2175    |	|	|	|
2176    |   	|	|	|	Scalarize	Comment
2177 -----------------------------------------------------------------------------
2178    0	0	0	0			No access for the scalar
2179    0	0	0	1			No access for the scalar
2180    0	0	1	0	No		Single read - won't help
2181    0	0	1	1	No		The same case
2182    0	1	0	0			No access for the scalar
2183    0	1	0	1			No access for the scalar
2184    0	1	1	0	Yes		s = *g; return s.i;
2185    0	1	1	1       Yes		The same case as above
2186    1	0	0	0	No		Won't help
2187    1	0	0	1	Yes		s.i = 1; *g = s;
2188    1	0	1	0	Yes		s.i = 5; g = s.i;
2189    1	0	1	1	Yes		The same case as above
2190    1	1	0	0	No		Won't help.
2191    1	1	0	1	Yes		s.i = 1; *g = s;
2192    1	1	1	0	Yes		s = *g; return s.i;
2193    1	1	1	1	Yes		Any of the above yeses  */
2194 
2195 static bool
analyze_access_subtree(struct access * root,struct access * parent,bool allow_replacements)2196 analyze_access_subtree (struct access *root, struct access *parent,
2197 			bool allow_replacements)
2198 {
2199   struct access *child;
2200   HOST_WIDE_INT limit = root->offset + root->size;
2201   HOST_WIDE_INT covered_to = root->offset;
2202   bool scalar = is_gimple_reg_type (root->type);
2203   bool hole = false, sth_created = false;
2204 
2205   if (parent)
2206     {
2207       if (parent->grp_read)
2208 	root->grp_read = 1;
2209       if (parent->grp_assignment_read)
2210 	root->grp_assignment_read = 1;
2211       if (parent->grp_write)
2212 	root->grp_write = 1;
2213       if (parent->grp_assignment_write)
2214 	root->grp_assignment_write = 1;
2215       if (parent->grp_total_scalarization)
2216 	root->grp_total_scalarization = 1;
2217     }
2218 
2219   if (root->grp_unscalarizable_region)
2220     allow_replacements = false;
2221 
2222   if (allow_replacements && expr_with_var_bounded_array_refs_p (root->expr))
2223     allow_replacements = false;
2224 
2225   for (child = root->first_child; child; child = child->next_sibling)
2226     {
2227       hole |= covered_to < child->offset;
2228       sth_created |= analyze_access_subtree (child, root,
2229 					     allow_replacements && !scalar);
2230 
2231       root->grp_unscalarized_data |= child->grp_unscalarized_data;
2232       root->grp_total_scalarization &= child->grp_total_scalarization;
2233       if (child->grp_covered)
2234 	covered_to += child->size;
2235       else
2236 	hole = true;
2237     }
2238 
2239   if (allow_replacements && scalar && !root->first_child
2240       && (root->grp_hint
2241 	  || ((root->grp_scalar_read || root->grp_assignment_read)
2242 	      && (root->grp_scalar_write || root->grp_assignment_write))))
2243     {
2244       /* Always create access replacements that cover the whole access.
2245          For integral types this means the precision has to match.
2246 	 Avoid assumptions based on the integral type kind, too.  */
2247       if (INTEGRAL_TYPE_P (root->type)
2248 	  && (TREE_CODE (root->type) != INTEGER_TYPE
2249 	      || TYPE_PRECISION (root->type) != root->size)
2250 	  /* But leave bitfield accesses alone.  */
2251 	  && (TREE_CODE (root->expr) != COMPONENT_REF
2252 	      || !DECL_BIT_FIELD (TREE_OPERAND (root->expr, 1))))
2253 	{
2254 	  tree rt = root->type;
2255 	  gcc_assert ((root->offset % BITS_PER_UNIT) == 0
2256 		      && (root->size % BITS_PER_UNIT) == 0);
2257 	  root->type = build_nonstandard_integer_type (root->size,
2258 						       TYPE_UNSIGNED (rt));
2259 	  root->expr = build_ref_for_offset (UNKNOWN_LOCATION,
2260 					     root->base, root->offset,
2261 					     root->type, NULL, false);
2262 
2263 	  if (dump_file && (dump_flags & TDF_DETAILS))
2264 	    {
2265 	      fprintf (dump_file, "Changing the type of a replacement for ");
2266 	      print_generic_expr (dump_file, root->base, 0);
2267 	      fprintf (dump_file, " offset: %u, size: %u ",
2268 		       (unsigned) root->offset, (unsigned) root->size);
2269 	      fprintf (dump_file, " to an integer.\n");
2270 	    }
2271 	}
2272 
2273       root->grp_to_be_replaced = 1;
2274       root->replacement_decl = create_access_replacement (root);
2275       sth_created = true;
2276       hole = false;
2277     }
2278   else
2279     {
2280       if (allow_replacements
2281 	  && scalar && !root->first_child
2282 	  && (root->grp_scalar_write || root->grp_assignment_write)
2283 	  && !bitmap_bit_p (cannot_scalarize_away_bitmap,
2284 			    DECL_UID (root->base)))
2285 	{
2286 	  gcc_checking_assert (!root->grp_scalar_read
2287 			       && !root->grp_assignment_read);
2288 	  sth_created = true;
2289 	  if (MAY_HAVE_DEBUG_STMTS)
2290 	    {
2291 	      root->grp_to_be_debug_replaced = 1;
2292 	      root->replacement_decl = create_access_replacement (root);
2293 	    }
2294 	}
2295 
2296       if (covered_to < limit)
2297 	hole = true;
2298       if (scalar)
2299 	root->grp_total_scalarization = 0;
2300     }
2301 
2302   if (!hole || root->grp_total_scalarization)
2303     root->grp_covered = 1;
2304   else if (root->grp_write || TREE_CODE (root->base) == PARM_DECL)
2305     root->grp_unscalarized_data = 1; /* not covered and written to */
2306   return sth_created;
2307 }
2308 
2309 /* Analyze all access trees linked by next_grp by the means of
2310    analyze_access_subtree.  */
2311 static bool
analyze_access_trees(struct access * access)2312 analyze_access_trees (struct access *access)
2313 {
2314   bool ret = false;
2315 
2316   while (access)
2317     {
2318       if (analyze_access_subtree (access, NULL, true))
2319 	ret = true;
2320       access = access->next_grp;
2321     }
2322 
2323   return ret;
2324 }
2325 
2326 /* Return true iff a potential new child of LACC at offset OFFSET and with size
2327    SIZE would conflict with an already existing one.  If exactly such a child
2328    already exists in LACC, store a pointer to it in EXACT_MATCH.  */
2329 
2330 static bool
child_would_conflict_in_lacc(struct access * lacc,HOST_WIDE_INT norm_offset,HOST_WIDE_INT size,struct access ** exact_match)2331 child_would_conflict_in_lacc (struct access *lacc, HOST_WIDE_INT norm_offset,
2332 			      HOST_WIDE_INT size, struct access **exact_match)
2333 {
2334   struct access *child;
2335 
2336   for (child = lacc->first_child; child; child = child->next_sibling)
2337     {
2338       if (child->offset == norm_offset && child->size == size)
2339 	{
2340 	  *exact_match = child;
2341 	  return true;
2342 	}
2343 
2344       if (child->offset < norm_offset + size
2345 	  && child->offset + child->size > norm_offset)
2346 	return true;
2347     }
2348 
2349   return false;
2350 }
2351 
2352 /* Create a new child access of PARENT, with all properties just like MODEL
2353    except for its offset and with its grp_write false and grp_read true.
2354    Return the new access or NULL if it cannot be created.  Note that this access
2355    is created long after all splicing and sorting, it's not located in any
2356    access vector and is automatically a representative of its group.  */
2357 
2358 static struct access *
create_artificial_child_access(struct access * parent,struct access * model,HOST_WIDE_INT new_offset)2359 create_artificial_child_access (struct access *parent, struct access *model,
2360 				HOST_WIDE_INT new_offset)
2361 {
2362   struct access *access;
2363   struct access **child;
2364   tree expr = parent->base;
2365 
2366   gcc_assert (!model->grp_unscalarizable_region);
2367 
2368   access = (struct access *) pool_alloc (access_pool);
2369   memset (access, 0, sizeof (struct access));
2370   if (!build_user_friendly_ref_for_offset (&expr, TREE_TYPE (expr), new_offset,
2371 					   model->type))
2372     {
2373       access->grp_no_warning = true;
2374       expr = build_ref_for_model (EXPR_LOCATION (parent->base), parent->base,
2375 				  new_offset, model, NULL, false);
2376     }
2377 
2378   access->base = parent->base;
2379   access->expr = expr;
2380   access->offset = new_offset;
2381   access->size = model->size;
2382   access->type = model->type;
2383   access->grp_write = true;
2384   access->grp_read = false;
2385 
2386   child = &parent->first_child;
2387   while (*child && (*child)->offset < new_offset)
2388     child = &(*child)->next_sibling;
2389 
2390   access->next_sibling = *child;
2391   *child = access;
2392 
2393   return access;
2394 }
2395 
2396 
2397 /* Propagate all subaccesses of RACC across an assignment link to LACC. Return
2398    true if any new subaccess was created.  Additionally, if RACC is a scalar
2399    access but LACC is not, change the type of the latter, if possible.  */
2400 
2401 static bool
propagate_subaccesses_across_link(struct access * lacc,struct access * racc)2402 propagate_subaccesses_across_link (struct access *lacc, struct access *racc)
2403 {
2404   struct access *rchild;
2405   HOST_WIDE_INT norm_delta = lacc->offset - racc->offset;
2406   bool ret = false;
2407 
2408   if (is_gimple_reg_type (lacc->type)
2409       || lacc->grp_unscalarizable_region
2410       || racc->grp_unscalarizable_region)
2411     return false;
2412 
2413   if (is_gimple_reg_type (racc->type))
2414     {
2415       if (!lacc->first_child && !racc->first_child)
2416 	{
2417 	  tree t = lacc->base;
2418 
2419 	  lacc->type = racc->type;
2420 	  if (build_user_friendly_ref_for_offset (&t, TREE_TYPE (t),
2421 						  lacc->offset, racc->type))
2422 	    lacc->expr = t;
2423 	  else
2424 	    {
2425 	      lacc->expr = build_ref_for_model (EXPR_LOCATION (lacc->base),
2426 						lacc->base, lacc->offset,
2427 						racc, NULL, false);
2428 	      lacc->grp_no_warning = true;
2429 	    }
2430 	}
2431       return false;
2432     }
2433 
2434   for (rchild = racc->first_child; rchild; rchild = rchild->next_sibling)
2435     {
2436       struct access *new_acc = NULL;
2437       HOST_WIDE_INT norm_offset = rchild->offset + norm_delta;
2438 
2439       if (rchild->grp_unscalarizable_region)
2440 	continue;
2441 
2442       if (child_would_conflict_in_lacc (lacc, norm_offset, rchild->size,
2443 					&new_acc))
2444 	{
2445 	  if (new_acc)
2446 	    {
2447 	      rchild->grp_hint = 1;
2448 	      new_acc->grp_hint |= new_acc->grp_read;
2449 	      if (rchild->first_child)
2450 		ret |= propagate_subaccesses_across_link (new_acc, rchild);
2451 	    }
2452 	  continue;
2453 	}
2454 
2455       rchild->grp_hint = 1;
2456       new_acc = create_artificial_child_access (lacc, rchild, norm_offset);
2457       if (new_acc)
2458 	{
2459 	  ret = true;
2460 	  if (racc->first_child)
2461 	    propagate_subaccesses_across_link (new_acc, rchild);
2462 	}
2463     }
2464 
2465   return ret;
2466 }
2467 
2468 /* Propagate all subaccesses across assignment links.  */
2469 
2470 static void
propagate_all_subaccesses(void)2471 propagate_all_subaccesses (void)
2472 {
2473   while (work_queue_head)
2474     {
2475       struct access *racc = pop_access_from_work_queue ();
2476       struct assign_link *link;
2477 
2478       gcc_assert (racc->first_link);
2479 
2480       for (link = racc->first_link; link; link = link->next)
2481 	{
2482 	  struct access *lacc = link->lacc;
2483 
2484 	  if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
2485 	    continue;
2486 	  lacc = lacc->group_representative;
2487 	  if (propagate_subaccesses_across_link (lacc, racc)
2488 	      && lacc->first_link)
2489 	    add_access_to_work_queue (lacc);
2490 	}
2491     }
2492 }
2493 
2494 /* Go through all accesses collected throughout the (intraprocedural) analysis
2495    stage, exclude overlapping ones, identify representatives and build trees
2496    out of them, making decisions about scalarization on the way.  Return true
2497    iff there are any to-be-scalarized variables after this stage. */
2498 
2499 static bool
analyze_all_variable_accesses(void)2500 analyze_all_variable_accesses (void)
2501 {
2502   int res = 0;
2503   bitmap tmp = BITMAP_ALLOC (NULL);
2504   bitmap_iterator bi;
2505   unsigned i, max_total_scalarization_size;
2506 
2507   max_total_scalarization_size = UNITS_PER_WORD * BITS_PER_UNIT
2508     * MOVE_RATIO (optimize_function_for_speed_p (cfun));
2509 
2510   EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
2511     if (bitmap_bit_p (should_scalarize_away_bitmap, i)
2512 	&& !bitmap_bit_p (cannot_scalarize_away_bitmap, i))
2513       {
2514 	tree var = candidate (i);
2515 
2516 	if (TREE_CODE (var) == VAR_DECL
2517 	    && type_consists_of_records_p (TREE_TYPE (var)))
2518 	  {
2519 	    if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (var)))
2520 		<= max_total_scalarization_size)
2521 	      {
2522 		completely_scalarize_var (var);
2523 		if (dump_file && (dump_flags & TDF_DETAILS))
2524 		  {
2525 		    fprintf (dump_file, "Will attempt to totally scalarize ");
2526 		    print_generic_expr (dump_file, var, 0);
2527 		    fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
2528 		  }
2529 	      }
2530 	    else if (dump_file && (dump_flags & TDF_DETAILS))
2531 	      {
2532 		fprintf (dump_file, "Too big to totally scalarize: ");
2533 		print_generic_expr (dump_file, var, 0);
2534 		fprintf (dump_file, " (UID: %u)\n", DECL_UID (var));
2535 	      }
2536 	  }
2537       }
2538 
2539   bitmap_copy (tmp, candidate_bitmap);
2540   EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
2541     {
2542       tree var = candidate (i);
2543       struct access *access;
2544 
2545       access = sort_and_splice_var_accesses (var);
2546       if (!access || !build_access_trees (access))
2547 	disqualify_candidate (var,
2548 			      "No or inhibitingly overlapping accesses.");
2549     }
2550 
2551   propagate_all_subaccesses ();
2552 
2553   bitmap_copy (tmp, candidate_bitmap);
2554   EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
2555     {
2556       tree var = candidate (i);
2557       struct access *access = get_first_repr_for_decl (var);
2558 
2559       if (analyze_access_trees (access))
2560 	{
2561 	  res++;
2562 	  if (dump_file && (dump_flags & TDF_DETAILS))
2563 	    {
2564 	      fprintf (dump_file, "\nAccess trees for ");
2565 	      print_generic_expr (dump_file, var, 0);
2566 	      fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
2567 	      dump_access_tree (dump_file, access);
2568 	      fprintf (dump_file, "\n");
2569 	    }
2570 	}
2571       else
2572 	disqualify_candidate (var, "No scalar replacements to be created.");
2573     }
2574 
2575   BITMAP_FREE (tmp);
2576 
2577   if (res)
2578     {
2579       statistics_counter_event (cfun, "Scalarized aggregates", res);
2580       return true;
2581     }
2582   else
2583     return false;
2584 }
2585 
2586 /* Generate statements copying scalar replacements of accesses within a subtree
2587    into or out of AGG.  ACCESS, all its children, siblings and their children
2588    are to be processed.  AGG is an aggregate type expression (can be a
2589    declaration but does not have to be, it can for example also be a mem_ref or
2590    a series of handled components).  TOP_OFFSET is the offset of the processed
2591    subtree which has to be subtracted from offsets of individual accesses to
2592    get corresponding offsets for AGG.  If CHUNK_SIZE is non-null, copy only
2593    replacements in the interval <start_offset, start_offset + chunk_size>,
2594    otherwise copy all.  GSI is a statement iterator used to place the new
2595    statements.  WRITE should be true when the statements should write from AGG
2596    to the replacement and false if vice versa.  if INSERT_AFTER is true, new
2597    statements will be added after the current statement in GSI, they will be
2598    added before the statement otherwise.  */
2599 
2600 static void
generate_subtree_copies(struct access * access,tree agg,HOST_WIDE_INT top_offset,HOST_WIDE_INT start_offset,HOST_WIDE_INT chunk_size,gimple_stmt_iterator * gsi,bool write,bool insert_after,location_t loc)2601 generate_subtree_copies (struct access *access, tree agg,
2602 			 HOST_WIDE_INT top_offset,
2603 			 HOST_WIDE_INT start_offset, HOST_WIDE_INT chunk_size,
2604 			 gimple_stmt_iterator *gsi, bool write,
2605 			 bool insert_after, location_t loc)
2606 {
2607   do
2608     {
2609       if (chunk_size && access->offset >= start_offset + chunk_size)
2610 	return;
2611 
2612       if (access->grp_to_be_replaced
2613 	  && (chunk_size == 0
2614 	      || access->offset + access->size > start_offset))
2615 	{
2616 	  tree expr, repl = get_access_replacement (access);
2617 	  gimple stmt;
2618 
2619 	  expr = build_ref_for_model (loc, agg, access->offset - top_offset,
2620 				      access, gsi, insert_after);
2621 
2622 	  if (write)
2623 	    {
2624 	      if (access->grp_partial_lhs)
2625 		expr = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
2626 						 !insert_after,
2627 						 insert_after ? GSI_NEW_STMT
2628 						 : GSI_SAME_STMT);
2629 	      stmt = gimple_build_assign (repl, expr);
2630 	    }
2631 	  else
2632 	    {
2633 	      TREE_NO_WARNING (repl) = 1;
2634 	      if (access->grp_partial_lhs)
2635 		repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
2636 						 !insert_after,
2637 						 insert_after ? GSI_NEW_STMT
2638 						 : GSI_SAME_STMT);
2639 	      stmt = gimple_build_assign (expr, repl);
2640 	    }
2641 	  gimple_set_location (stmt, loc);
2642 
2643 	  if (insert_after)
2644 	    gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2645 	  else
2646 	    gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2647 	  update_stmt (stmt);
2648 	  sra_stats.subtree_copies++;
2649 	}
2650       else if (write
2651 	       && access->grp_to_be_debug_replaced
2652 	       && (chunk_size == 0
2653 		   || access->offset + access->size > start_offset))
2654 	{
2655 	  gimple ds;
2656 	  tree drhs = build_debug_ref_for_model (loc, agg,
2657 						 access->offset - top_offset,
2658 						 access);
2659 	  ds = gimple_build_debug_bind (get_access_replacement (access),
2660 					drhs, gsi_stmt (*gsi));
2661 	  if (insert_after)
2662 	    gsi_insert_after (gsi, ds, GSI_NEW_STMT);
2663 	  else
2664 	    gsi_insert_before (gsi, ds, GSI_SAME_STMT);
2665 	}
2666 
2667       if (access->first_child)
2668 	generate_subtree_copies (access->first_child, agg, top_offset,
2669 				 start_offset, chunk_size, gsi,
2670 				 write, insert_after, loc);
2671 
2672       access = access->next_sibling;
2673     }
2674   while (access);
2675 }
2676 
2677 /* Assign zero to all scalar replacements in an access subtree.  ACCESS is the
2678    the root of the subtree to be processed.  GSI is the statement iterator used
2679    for inserting statements which are added after the current statement if
2680    INSERT_AFTER is true or before it otherwise.  */
2681 
2682 static void
init_subtree_with_zero(struct access * access,gimple_stmt_iterator * gsi,bool insert_after,location_t loc)2683 init_subtree_with_zero (struct access *access, gimple_stmt_iterator *gsi,
2684 			bool insert_after, location_t loc)
2685 
2686 {
2687   struct access *child;
2688 
2689   if (access->grp_to_be_replaced)
2690     {
2691       gimple stmt;
2692 
2693       stmt = gimple_build_assign (get_access_replacement (access),
2694 				  build_zero_cst (access->type));
2695       if (insert_after)
2696 	gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2697       else
2698 	gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2699       update_stmt (stmt);
2700       gimple_set_location (stmt, loc);
2701     }
2702   else if (access->grp_to_be_debug_replaced)
2703     {
2704       gimple ds = gimple_build_debug_bind (get_access_replacement (access),
2705 					   build_zero_cst (access->type),
2706 					   gsi_stmt (*gsi));
2707       if (insert_after)
2708 	gsi_insert_after (gsi, ds, GSI_NEW_STMT);
2709       else
2710 	gsi_insert_before (gsi, ds, GSI_SAME_STMT);
2711     }
2712 
2713   for (child = access->first_child; child; child = child->next_sibling)
2714     init_subtree_with_zero (child, gsi, insert_after, loc);
2715 }
2716 
2717 /* Search for an access representative for the given expression EXPR and
2718    return it or NULL if it cannot be found.  */
2719 
2720 static struct access *
get_access_for_expr(tree expr)2721 get_access_for_expr (tree expr)
2722 {
2723   HOST_WIDE_INT offset, size, max_size;
2724   tree base;
2725 
2726   /* FIXME: This should not be necessary but Ada produces V_C_Es with a type of
2727      a different size than the size of its argument and we need the latter
2728      one.  */
2729   if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
2730     expr = TREE_OPERAND (expr, 0);
2731 
2732   base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
2733   if (max_size == -1 || !DECL_P (base))
2734     return NULL;
2735 
2736   if (!bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
2737     return NULL;
2738 
2739   return get_var_base_offset_size_access (base, offset, max_size);
2740 }
2741 
2742 /* Replace the expression EXPR with a scalar replacement if there is one and
2743    generate other statements to do type conversion or subtree copying if
2744    necessary.  GSI is used to place newly created statements, WRITE is true if
2745    the expression is being written to (it is on a LHS of a statement or output
2746    in an assembly statement).  */
2747 
2748 static bool
sra_modify_expr(tree * expr,gimple_stmt_iterator * gsi,bool write)2749 sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
2750 {
2751   location_t loc;
2752   struct access *access;
2753   tree type, bfr;
2754 
2755   if (TREE_CODE (*expr) == BIT_FIELD_REF)
2756     {
2757       bfr = *expr;
2758       expr = &TREE_OPERAND (*expr, 0);
2759     }
2760   else
2761     bfr = NULL_TREE;
2762 
2763   if (TREE_CODE (*expr) == REALPART_EXPR || TREE_CODE (*expr) == IMAGPART_EXPR)
2764     expr = &TREE_OPERAND (*expr, 0);
2765   access = get_access_for_expr (*expr);
2766   if (!access)
2767     return false;
2768   type = TREE_TYPE (*expr);
2769 
2770   loc = gimple_location (gsi_stmt (*gsi));
2771   if (access->grp_to_be_replaced)
2772     {
2773       tree repl = get_access_replacement (access);
2774       /* If we replace a non-register typed access simply use the original
2775          access expression to extract the scalar component afterwards.
2776 	 This happens if scalarizing a function return value or parameter
2777 	 like in gcc.c-torture/execute/20041124-1.c, 20050316-1.c and
2778 	 gcc.c-torture/compile/20011217-1.c.
2779 
2780          We also want to use this when accessing a complex or vector which can
2781          be accessed as a different type too, potentially creating a need for
2782          type conversion (see PR42196) and when scalarized unions are involved
2783          in assembler statements (see PR42398).  */
2784       if (!useless_type_conversion_p (type, access->type))
2785 	{
2786 	  tree ref;
2787 
2788 	  ref = build_ref_for_model (loc, access->base, access->offset, access,
2789 				     NULL, false);
2790 
2791 	  if (write)
2792 	    {
2793 	      gimple stmt;
2794 
2795 	      if (access->grp_partial_lhs)
2796 		ref = force_gimple_operand_gsi (gsi, ref, true, NULL_TREE,
2797 						 false, GSI_NEW_STMT);
2798 	      stmt = gimple_build_assign (repl, ref);
2799 	      gimple_set_location (stmt, loc);
2800 	      gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2801 	    }
2802 	  else
2803 	    {
2804 	      gimple stmt;
2805 
2806 	      if (access->grp_partial_lhs)
2807 		repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
2808 						 true, GSI_SAME_STMT);
2809 	      stmt = gimple_build_assign (ref, repl);
2810 	      gimple_set_location (stmt, loc);
2811 	      gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2812 	    }
2813 	}
2814       else
2815 	*expr = repl;
2816       sra_stats.exprs++;
2817     }
2818   else if (write && access->grp_to_be_debug_replaced)
2819     {
2820       gimple ds = gimple_build_debug_bind (get_access_replacement (access),
2821 					   NULL_TREE,
2822 					   gsi_stmt (*gsi));
2823       gsi_insert_after (gsi, ds, GSI_NEW_STMT);
2824     }
2825 
2826   if (access->first_child)
2827     {
2828       HOST_WIDE_INT start_offset, chunk_size;
2829       if (bfr
2830 	  && tree_fits_uhwi_p (TREE_OPERAND (bfr, 1))
2831 	  && tree_fits_uhwi_p (TREE_OPERAND (bfr, 2)))
2832 	{
2833 	  chunk_size = tree_to_uhwi (TREE_OPERAND (bfr, 1));
2834 	  start_offset = access->offset
2835 	    + tree_to_uhwi (TREE_OPERAND (bfr, 2));
2836 	}
2837       else
2838 	start_offset = chunk_size = 0;
2839 
2840       generate_subtree_copies (access->first_child, access->base, 0,
2841 			       start_offset, chunk_size, gsi, write, write,
2842 			       loc);
2843     }
2844   return true;
2845 }
2846 
2847 /* Where scalar replacements of the RHS have been written to when a replacement
2848    of a LHS of an assigments cannot be direclty loaded from a replacement of
2849    the RHS. */
2850 enum unscalarized_data_handling { SRA_UDH_NONE,  /* Nothing done so far. */
2851 				  SRA_UDH_RIGHT, /* Data flushed to the RHS. */
2852 				  SRA_UDH_LEFT }; /* Data flushed to the LHS. */
2853 
2854 /* Store all replacements in the access tree rooted in TOP_RACC either to their
2855    base aggregate if there are unscalarized data or directly to LHS of the
2856    statement that is pointed to by GSI otherwise.  */
2857 
2858 static enum unscalarized_data_handling
handle_unscalarized_data_in_subtree(struct access * top_racc,gimple_stmt_iterator * gsi)2859 handle_unscalarized_data_in_subtree (struct access *top_racc,
2860 				     gimple_stmt_iterator *gsi)
2861 {
2862   if (top_racc->grp_unscalarized_data)
2863     {
2864       generate_subtree_copies (top_racc->first_child, top_racc->base, 0, 0, 0,
2865 			       gsi, false, false,
2866 			       gimple_location (gsi_stmt (*gsi)));
2867       return SRA_UDH_RIGHT;
2868     }
2869   else
2870     {
2871       tree lhs = gimple_assign_lhs (gsi_stmt (*gsi));
2872       generate_subtree_copies (top_racc->first_child, lhs, top_racc->offset,
2873 			       0, 0, gsi, false, false,
2874 			       gimple_location (gsi_stmt (*gsi)));
2875       return SRA_UDH_LEFT;
2876     }
2877 }
2878 
2879 
2880 /* Try to generate statements to load all sub-replacements in an access subtree
2881    formed by children of LACC from scalar replacements in the TOP_RACC subtree.
2882    If that is not possible, refresh the TOP_RACC base aggregate and load the
2883    accesses from it.  LEFT_OFFSET is the offset of the left whole subtree being
2884    copied. NEW_GSI is stmt iterator used for statement insertions after the
2885    original assignment, OLD_GSI is used to insert statements before the
2886    assignment.  *REFRESHED keeps the information whether we have needed to
2887    refresh replacements of the LHS and from which side of the assignments this
2888    takes place.  */
2889 
2890 static void
load_assign_lhs_subreplacements(struct access * lacc,struct access * top_racc,HOST_WIDE_INT left_offset,gimple_stmt_iterator * old_gsi,gimple_stmt_iterator * new_gsi,enum unscalarized_data_handling * refreshed)2891 load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc,
2892 				 HOST_WIDE_INT left_offset,
2893 				 gimple_stmt_iterator *old_gsi,
2894 				 gimple_stmt_iterator *new_gsi,
2895 				 enum unscalarized_data_handling *refreshed)
2896 {
2897   location_t loc = gimple_location (gsi_stmt (*old_gsi));
2898   for (lacc = lacc->first_child; lacc; lacc = lacc->next_sibling)
2899     {
2900       HOST_WIDE_INT offset = lacc->offset - left_offset + top_racc->offset;
2901 
2902       if (lacc->grp_to_be_replaced)
2903 	{
2904 	  struct access *racc;
2905 	  gimple stmt;
2906 	  tree rhs;
2907 
2908 	  racc = find_access_in_subtree (top_racc, offset, lacc->size);
2909 	  if (racc && racc->grp_to_be_replaced)
2910 	    {
2911 	      rhs = get_access_replacement (racc);
2912 	      if (!useless_type_conversion_p (lacc->type, racc->type))
2913 		rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, lacc->type, rhs);
2914 
2915 	      if (racc->grp_partial_lhs && lacc->grp_partial_lhs)
2916 		rhs = force_gimple_operand_gsi (old_gsi, rhs, true, NULL_TREE,
2917 						true, GSI_SAME_STMT);
2918 	    }
2919 	  else
2920 	    {
2921 	      /* No suitable access on the right hand side, need to load from
2922 		 the aggregate.  See if we have to update it first... */
2923 	      if (*refreshed == SRA_UDH_NONE)
2924 		*refreshed = handle_unscalarized_data_in_subtree (top_racc,
2925 								  old_gsi);
2926 
2927 	      if (*refreshed == SRA_UDH_LEFT)
2928 		rhs = build_ref_for_model (loc, lacc->base, lacc->offset, lacc,
2929 					    new_gsi, true);
2930 	      else
2931 		rhs = build_ref_for_model (loc, top_racc->base, offset, lacc,
2932 					    new_gsi, true);
2933 	      if (lacc->grp_partial_lhs)
2934 		rhs = force_gimple_operand_gsi (new_gsi, rhs, true, NULL_TREE,
2935 						false, GSI_NEW_STMT);
2936 	    }
2937 
2938 	  stmt = gimple_build_assign (get_access_replacement (lacc), rhs);
2939 	  gsi_insert_after (new_gsi, stmt, GSI_NEW_STMT);
2940 	  gimple_set_location (stmt, loc);
2941 	  update_stmt (stmt);
2942 	  sra_stats.subreplacements++;
2943 	}
2944       else
2945 	{
2946 	  if (*refreshed == SRA_UDH_NONE
2947 	      && lacc->grp_read && !lacc->grp_covered)
2948 	    *refreshed = handle_unscalarized_data_in_subtree (top_racc,
2949 							      old_gsi);
2950 	  if (lacc && lacc->grp_to_be_debug_replaced)
2951 	    {
2952 	      gimple ds;
2953 	      tree drhs;
2954 	      struct access *racc = find_access_in_subtree (top_racc, offset,
2955 							    lacc->size);
2956 
2957 	      if (racc && racc->grp_to_be_replaced)
2958 		{
2959 		  if (racc->grp_write)
2960 		    drhs = get_access_replacement (racc);
2961 		  else
2962 		    drhs = NULL;
2963 		}
2964 	      else if (*refreshed == SRA_UDH_LEFT)
2965 		drhs = build_debug_ref_for_model (loc, lacc->base, lacc->offset,
2966 						  lacc);
2967 	      else if (*refreshed == SRA_UDH_RIGHT)
2968 		drhs = build_debug_ref_for_model (loc, top_racc->base, offset,
2969 						  lacc);
2970 	      else
2971 		drhs = NULL_TREE;
2972 	      if (drhs
2973 		  && !useless_type_conversion_p (lacc->type, TREE_TYPE (drhs)))
2974 		drhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
2975 					lacc->type, drhs);
2976 	      ds = gimple_build_debug_bind (get_access_replacement (lacc),
2977 					    drhs, gsi_stmt (*old_gsi));
2978 	      gsi_insert_after (new_gsi, ds, GSI_NEW_STMT);
2979 	    }
2980 	}
2981 
2982       if (lacc->first_child)
2983 	load_assign_lhs_subreplacements (lacc, top_racc, left_offset,
2984 					 old_gsi, new_gsi, refreshed);
2985     }
2986 }
2987 
2988 /* Result code for SRA assignment modification.  */
2989 enum assignment_mod_result { SRA_AM_NONE,       /* nothing done for the stmt */
2990 			     SRA_AM_MODIFIED,  /* stmt changed but not
2991 						  removed */
2992 			     SRA_AM_REMOVED };  /* stmt eliminated */
2993 
2994 /* Modify assignments with a CONSTRUCTOR on their RHS.  STMT contains a pointer
2995    to the assignment and GSI is the statement iterator pointing at it.  Returns
2996    the same values as sra_modify_assign.  */
2997 
2998 static enum assignment_mod_result
sra_modify_constructor_assign(gimple * stmt,gimple_stmt_iterator * gsi)2999 sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
3000 {
3001   tree lhs = gimple_assign_lhs (*stmt);
3002   struct access *acc;
3003   location_t loc;
3004 
3005   acc = get_access_for_expr (lhs);
3006   if (!acc)
3007     return SRA_AM_NONE;
3008 
3009   if (gimple_clobber_p (*stmt))
3010     {
3011       /* Remove clobbers of fully scalarized variables, otherwise
3012 	 do nothing.  */
3013       if (acc->grp_covered)
3014 	{
3015 	  unlink_stmt_vdef (*stmt);
3016 	  gsi_remove (gsi, true);
3017 	  release_defs (*stmt);
3018 	  return SRA_AM_REMOVED;
3019 	}
3020       else
3021 	return SRA_AM_NONE;
3022     }
3023 
3024   loc = gimple_location (*stmt);
3025   if (vec_safe_length (CONSTRUCTOR_ELTS (gimple_assign_rhs1 (*stmt))) > 0)
3026     {
3027       /* I have never seen this code path trigger but if it can happen the
3028 	 following should handle it gracefully.  */
3029       if (access_has_children_p (acc))
3030 	generate_subtree_copies (acc->first_child, acc->base, 0, 0, 0, gsi,
3031 				 true, true, loc);
3032       return SRA_AM_MODIFIED;
3033     }
3034 
3035   if (acc->grp_covered)
3036     {
3037       init_subtree_with_zero (acc, gsi, false, loc);
3038       unlink_stmt_vdef (*stmt);
3039       gsi_remove (gsi, true);
3040       release_defs (*stmt);
3041       return SRA_AM_REMOVED;
3042     }
3043   else
3044     {
3045       init_subtree_with_zero (acc, gsi, true, loc);
3046       return SRA_AM_MODIFIED;
3047     }
3048 }
3049 
3050 /* Create and return a new suitable default definition SSA_NAME for RACC which
3051    is an access describing an uninitialized part of an aggregate that is being
3052    loaded.  */
3053 
3054 static tree
get_repl_default_def_ssa_name(struct access * racc)3055 get_repl_default_def_ssa_name (struct access *racc)
3056 {
3057   gcc_checking_assert (!racc->grp_to_be_replaced
3058 		       && !racc->grp_to_be_debug_replaced);
3059   if (!racc->replacement_decl)
3060     racc->replacement_decl = create_access_replacement (racc);
3061   return get_or_create_ssa_default_def (cfun, racc->replacement_decl);
3062 }
3063 
3064 /* Return true if REF has an VIEW_CONVERT_EXPR or a COMPONENT_REF with a
3065    bit-field field declaration somewhere in it.  */
3066 
3067 static inline bool
contains_vce_or_bfcref_p(const_tree ref)3068 contains_vce_or_bfcref_p (const_tree ref)
3069 {
3070   while (handled_component_p (ref))
3071     {
3072       if (TREE_CODE (ref) == VIEW_CONVERT_EXPR
3073 	  || (TREE_CODE (ref) == COMPONENT_REF
3074 	      && DECL_BIT_FIELD (TREE_OPERAND (ref, 1))))
3075 	return true;
3076       ref = TREE_OPERAND (ref, 0);
3077     }
3078 
3079   return false;
3080 }
3081 
3082 /* Examine both sides of the assignment statement pointed to by STMT, replace
3083    them with a scalare replacement if there is one and generate copying of
3084    replacements if scalarized aggregates have been used in the assignment.  GSI
3085    is used to hold generated statements for type conversions and subtree
3086    copying.  */
3087 
3088 static enum assignment_mod_result
sra_modify_assign(gimple * stmt,gimple_stmt_iterator * gsi)3089 sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi)
3090 {
3091   struct access *lacc, *racc;
3092   tree lhs, rhs;
3093   bool modify_this_stmt = false;
3094   bool force_gimple_rhs = false;
3095   location_t loc;
3096   gimple_stmt_iterator orig_gsi = *gsi;
3097 
3098   if (!gimple_assign_single_p (*stmt))
3099     return SRA_AM_NONE;
3100   lhs = gimple_assign_lhs (*stmt);
3101   rhs = gimple_assign_rhs1 (*stmt);
3102 
3103   if (TREE_CODE (rhs) == CONSTRUCTOR)
3104     return sra_modify_constructor_assign (stmt, gsi);
3105 
3106   if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (lhs) == REALPART_EXPR
3107       || TREE_CODE (rhs) == IMAGPART_EXPR || TREE_CODE (lhs) == IMAGPART_EXPR
3108       || TREE_CODE (rhs) == BIT_FIELD_REF || TREE_CODE (lhs) == BIT_FIELD_REF)
3109     {
3110       modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (*stmt),
3111 					  gsi, false);
3112       modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (*stmt),
3113 					   gsi, true);
3114       return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
3115     }
3116 
3117   lacc = get_access_for_expr (lhs);
3118   racc = get_access_for_expr (rhs);
3119   if (!lacc && !racc)
3120     return SRA_AM_NONE;
3121 
3122   loc = gimple_location (*stmt);
3123   if (lacc && lacc->grp_to_be_replaced)
3124     {
3125       lhs = get_access_replacement (lacc);
3126       gimple_assign_set_lhs (*stmt, lhs);
3127       modify_this_stmt = true;
3128       if (lacc->grp_partial_lhs)
3129 	force_gimple_rhs = true;
3130       sra_stats.exprs++;
3131     }
3132 
3133   if (racc && racc->grp_to_be_replaced)
3134     {
3135       rhs = get_access_replacement (racc);
3136       modify_this_stmt = true;
3137       if (racc->grp_partial_lhs)
3138 	force_gimple_rhs = true;
3139       sra_stats.exprs++;
3140     }
3141   else if (racc
3142 	   && !racc->grp_unscalarized_data
3143 	   && TREE_CODE (lhs) == SSA_NAME
3144 	   && !access_has_replacements_p (racc))
3145     {
3146       rhs = get_repl_default_def_ssa_name (racc);
3147       modify_this_stmt = true;
3148       sra_stats.exprs++;
3149     }
3150 
3151   if (modify_this_stmt)
3152     {
3153       if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
3154 	{
3155 	  /* If we can avoid creating a VIEW_CONVERT_EXPR do so.
3156 	     ???  This should move to fold_stmt which we simply should
3157 	     call after building a VIEW_CONVERT_EXPR here.  */
3158 	  if (AGGREGATE_TYPE_P (TREE_TYPE (lhs))
3159 	      && !contains_bitfld_component_ref_p (lhs))
3160 	    {
3161 	      lhs = build_ref_for_model (loc, lhs, 0, racc, gsi, false);
3162 	      gimple_assign_set_lhs (*stmt, lhs);
3163 	    }
3164 	  else if (AGGREGATE_TYPE_P (TREE_TYPE (rhs))
3165 		   && !contains_vce_or_bfcref_p (rhs))
3166 	    rhs = build_ref_for_model (loc, rhs, 0, lacc, gsi, false);
3167 
3168 	  if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
3169 	    {
3170 	      rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
3171 				     rhs);
3172 	      if (is_gimple_reg_type (TREE_TYPE (lhs))
3173 		  && TREE_CODE (lhs) != SSA_NAME)
3174 		force_gimple_rhs = true;
3175 	    }
3176 	}
3177     }
3178 
3179   if (lacc && lacc->grp_to_be_debug_replaced)
3180     {
3181       tree dlhs = get_access_replacement (lacc);
3182       tree drhs = unshare_expr (rhs);
3183       if (!useless_type_conversion_p (TREE_TYPE (dlhs), TREE_TYPE (drhs)))
3184 	{
3185 	  if (AGGREGATE_TYPE_P (TREE_TYPE (drhs))
3186 	      && !contains_vce_or_bfcref_p (drhs))
3187 	    drhs = build_debug_ref_for_model (loc, drhs, 0, lacc);
3188 	  if (drhs
3189 	      && !useless_type_conversion_p (TREE_TYPE (dlhs),
3190 					     TREE_TYPE (drhs)))
3191 	    drhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
3192 				    TREE_TYPE (dlhs), drhs);
3193 	}
3194       gimple ds = gimple_build_debug_bind (dlhs, drhs, *stmt);
3195       gsi_insert_before (gsi, ds, GSI_SAME_STMT);
3196     }
3197 
3198   /* From this point on, the function deals with assignments in between
3199      aggregates when at least one has scalar reductions of some of its
3200      components.  There are three possible scenarios: Both the LHS and RHS have
3201      to-be-scalarized components, 2) only the RHS has or 3) only the LHS has.
3202 
3203      In the first case, we would like to load the LHS components from RHS
3204      components whenever possible.  If that is not possible, we would like to
3205      read it directly from the RHS (after updating it by storing in it its own
3206      components).  If there are some necessary unscalarized data in the LHS,
3207      those will be loaded by the original assignment too.  If neither of these
3208      cases happen, the original statement can be removed.  Most of this is done
3209      by load_assign_lhs_subreplacements.
3210 
3211      In the second case, we would like to store all RHS scalarized components
3212      directly into LHS and if they cover the aggregate completely, remove the
3213      statement too.  In the third case, we want the LHS components to be loaded
3214      directly from the RHS (DSE will remove the original statement if it
3215      becomes redundant).
3216 
3217      This is a bit complex but manageable when types match and when unions do
3218      not cause confusion in a way that we cannot really load a component of LHS
3219      from the RHS or vice versa (the access representing this level can have
3220      subaccesses that are accessible only through a different union field at a
3221      higher level - different from the one used in the examined expression).
3222      Unions are fun.
3223 
3224      Therefore, I specially handle a fourth case, happening when there is a
3225      specific type cast or it is impossible to locate a scalarized subaccess on
3226      the other side of the expression.  If that happens, I simply "refresh" the
3227      RHS by storing in it is scalarized components leave the original statement
3228      there to do the copying and then load the scalar replacements of the LHS.
3229      This is what the first branch does.  */
3230 
3231   if (modify_this_stmt
3232       || gimple_has_volatile_ops (*stmt)
3233       || contains_vce_or_bfcref_p (rhs)
3234       || contains_vce_or_bfcref_p (lhs))
3235     {
3236       if (access_has_children_p (racc))
3237 	generate_subtree_copies (racc->first_child, racc->base, 0, 0, 0,
3238 				 gsi, false, false, loc);
3239       if (access_has_children_p (lacc))
3240 	generate_subtree_copies (lacc->first_child, lacc->base, 0, 0, 0,
3241 				 gsi, true, true, loc);
3242       sra_stats.separate_lhs_rhs_handling++;
3243 
3244       /* This gimplification must be done after generate_subtree_copies,
3245 	 lest we insert the subtree copies in the middle of the gimplified
3246 	 sequence.  */
3247       if (force_gimple_rhs)
3248 	rhs = force_gimple_operand_gsi (&orig_gsi, rhs, true, NULL_TREE,
3249 					true, GSI_SAME_STMT);
3250       if (gimple_assign_rhs1 (*stmt) != rhs)
3251 	{
3252 	  modify_this_stmt = true;
3253 	  gimple_assign_set_rhs_from_tree (&orig_gsi, rhs);
3254 	  gcc_assert (*stmt == gsi_stmt (orig_gsi));
3255 	}
3256 
3257       return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
3258     }
3259   else
3260     {
3261       if (access_has_children_p (lacc)
3262 	  && access_has_children_p (racc)
3263 	  /* When an access represents an unscalarizable region, it usually
3264 	     represents accesses with variable offset and thus must not be used
3265 	     to generate new memory accesses.  */
3266 	  && !lacc->grp_unscalarizable_region
3267 	  && !racc->grp_unscalarizable_region)
3268 	{
3269 	  gimple_stmt_iterator orig_gsi = *gsi;
3270 	  enum unscalarized_data_handling refreshed;
3271 
3272 	  if (lacc->grp_read && !lacc->grp_covered)
3273 	    refreshed = handle_unscalarized_data_in_subtree (racc, gsi);
3274 	  else
3275 	    refreshed = SRA_UDH_NONE;
3276 
3277 	  load_assign_lhs_subreplacements (lacc, racc, lacc->offset,
3278 					   &orig_gsi, gsi, &refreshed);
3279 	  if (refreshed != SRA_UDH_RIGHT)
3280 	    {
3281 	      gsi_next (gsi);
3282 	      unlink_stmt_vdef (*stmt);
3283 	      gsi_remove (&orig_gsi, true);
3284 	      release_defs (*stmt);
3285 	      sra_stats.deleted++;
3286 	      return SRA_AM_REMOVED;
3287 	    }
3288 	}
3289       else
3290 	{
3291 	  if (access_has_children_p (racc)
3292 	      && !racc->grp_unscalarized_data)
3293 	    {
3294 	      if (dump_file)
3295 		{
3296 		  fprintf (dump_file, "Removing load: ");
3297 		  print_gimple_stmt (dump_file, *stmt, 0, 0);
3298 		}
3299 	      generate_subtree_copies (racc->first_child, lhs,
3300 				       racc->offset, 0, 0, gsi,
3301 				       false, false, loc);
3302 	      gcc_assert (*stmt == gsi_stmt (*gsi));
3303 	      unlink_stmt_vdef (*stmt);
3304 	      gsi_remove (gsi, true);
3305 	      release_defs (*stmt);
3306 	      sra_stats.deleted++;
3307 	      return SRA_AM_REMOVED;
3308 	    }
3309 	  /* Restore the aggregate RHS from its components so the
3310 	     prevailing aggregate copy does the right thing.  */
3311 	  if (access_has_children_p (racc))
3312 	    generate_subtree_copies (racc->first_child, racc->base, 0, 0, 0,
3313 				     gsi, false, false, loc);
3314 	  /* Re-load the components of the aggregate copy destination.
3315 	     But use the RHS aggregate to load from to expose more
3316 	     optimization opportunities.  */
3317 	  if (access_has_children_p (lacc))
3318 	    generate_subtree_copies (lacc->first_child, rhs, lacc->offset,
3319 				     0, 0, gsi, true, true, loc);
3320 	}
3321 
3322       return SRA_AM_NONE;
3323     }
3324 }
3325 
3326 /* Traverse the function body and all modifications as decided in
3327    analyze_all_variable_accesses.  Return true iff the CFG has been
3328    changed.  */
3329 
3330 static bool
sra_modify_function_body(void)3331 sra_modify_function_body (void)
3332 {
3333   bool cfg_changed = false;
3334   basic_block bb;
3335 
3336   FOR_EACH_BB_FN (bb, cfun)
3337     {
3338       gimple_stmt_iterator gsi = gsi_start_bb (bb);
3339       while (!gsi_end_p (gsi))
3340 	{
3341 	  gimple stmt = gsi_stmt (gsi);
3342 	  enum assignment_mod_result assign_result;
3343 	  bool modified = false, deleted = false;
3344 	  tree *t;
3345 	  unsigned i;
3346 
3347 	  switch (gimple_code (stmt))
3348 	    {
3349 	    case GIMPLE_RETURN:
3350 	      t = gimple_return_retval_ptr (stmt);
3351 	      if (*t != NULL_TREE)
3352 		modified |= sra_modify_expr (t, &gsi, false);
3353 	      break;
3354 
3355 	    case GIMPLE_ASSIGN:
3356 	      assign_result = sra_modify_assign (&stmt, &gsi);
3357 	      modified |= assign_result == SRA_AM_MODIFIED;
3358 	      deleted = assign_result == SRA_AM_REMOVED;
3359 	      break;
3360 
3361 	    case GIMPLE_CALL:
3362 	      /* Operands must be processed before the lhs.  */
3363 	      for (i = 0; i < gimple_call_num_args (stmt); i++)
3364 		{
3365 		  t = gimple_call_arg_ptr (stmt, i);
3366 		  modified |= sra_modify_expr (t, &gsi, false);
3367 		}
3368 
3369 	      if (gimple_call_lhs (stmt))
3370 		{
3371 		  t = gimple_call_lhs_ptr (stmt);
3372 		  modified |= sra_modify_expr (t, &gsi, true);
3373 		}
3374 	      break;
3375 
3376 	    case GIMPLE_ASM:
3377 	      for (i = 0; i < gimple_asm_ninputs (stmt); i++)
3378 		{
3379 		  t = &TREE_VALUE (gimple_asm_input_op (stmt, i));
3380 		  modified |= sra_modify_expr (t, &gsi, false);
3381 		}
3382 	      for (i = 0; i < gimple_asm_noutputs (stmt); i++)
3383 		{
3384 		  t = &TREE_VALUE (gimple_asm_output_op (stmt, i));
3385 		  modified |= sra_modify_expr (t, &gsi, true);
3386 		}
3387 	      break;
3388 
3389 	    default:
3390 	      break;
3391 	    }
3392 
3393 	  if (modified)
3394 	    {
3395 	      update_stmt (stmt);
3396 	      if (maybe_clean_eh_stmt (stmt)
3397 		  && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
3398 		cfg_changed = true;
3399 	    }
3400 	  if (!deleted)
3401 	    gsi_next (&gsi);
3402 	}
3403     }
3404 
3405   return cfg_changed;
3406 }
3407 
3408 /* Generate statements initializing scalar replacements of parts of function
3409    parameters.  */
3410 
3411 static void
initialize_parameter_reductions(void)3412 initialize_parameter_reductions (void)
3413 {
3414   gimple_stmt_iterator gsi;
3415   gimple_seq seq = NULL;
3416   tree parm;
3417 
3418   gsi = gsi_start (seq);
3419   for (parm = DECL_ARGUMENTS (current_function_decl);
3420        parm;
3421        parm = DECL_CHAIN (parm))
3422     {
3423       vec<access_p> *access_vec;
3424       struct access *access;
3425 
3426       if (!bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
3427 	continue;
3428       access_vec = get_base_access_vector (parm);
3429       if (!access_vec)
3430 	continue;
3431 
3432       for (access = (*access_vec)[0];
3433 	   access;
3434 	   access = access->next_grp)
3435 	generate_subtree_copies (access, parm, 0, 0, 0, &gsi, true, true,
3436 				 EXPR_LOCATION (parm));
3437     }
3438 
3439   seq = gsi_seq (gsi);
3440   if (seq)
3441     gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
3442 }
3443 
3444 /* The "main" function of intraprocedural SRA passes.  Runs the analysis and if
3445    it reveals there are components of some aggregates to be scalarized, it runs
3446    the required transformations.  */
3447 static unsigned int
perform_intra_sra(void)3448 perform_intra_sra (void)
3449 {
3450   int ret = 0;
3451   sra_initialize ();
3452 
3453   if (!find_var_candidates ())
3454     goto out;
3455 
3456   if (!scan_function ())
3457     goto out;
3458 
3459   if (!analyze_all_variable_accesses ())
3460     goto out;
3461 
3462   if (sra_modify_function_body ())
3463     ret = TODO_update_ssa | TODO_cleanup_cfg;
3464   else
3465     ret = TODO_update_ssa;
3466   initialize_parameter_reductions ();
3467 
3468   statistics_counter_event (cfun, "Scalar replacements created",
3469 			    sra_stats.replacements);
3470   statistics_counter_event (cfun, "Modified expressions", sra_stats.exprs);
3471   statistics_counter_event (cfun, "Subtree copy stmts",
3472 			    sra_stats.subtree_copies);
3473   statistics_counter_event (cfun, "Subreplacement stmts",
3474 			    sra_stats.subreplacements);
3475   statistics_counter_event (cfun, "Deleted stmts", sra_stats.deleted);
3476   statistics_counter_event (cfun, "Separate LHS and RHS handling",
3477 			    sra_stats.separate_lhs_rhs_handling);
3478 
3479  out:
3480   sra_deinitialize ();
3481   return ret;
3482 }
3483 
3484 /* Perform early intraprocedural SRA.  */
3485 static unsigned int
early_intra_sra(void)3486 early_intra_sra (void)
3487 {
3488   sra_mode = SRA_MODE_EARLY_INTRA;
3489   return perform_intra_sra ();
3490 }
3491 
3492 /* Perform "late" intraprocedural SRA.  */
3493 static unsigned int
late_intra_sra(void)3494 late_intra_sra (void)
3495 {
3496   sra_mode = SRA_MODE_INTRA;
3497   return perform_intra_sra ();
3498 }
3499 
3500 
3501 static bool
gate_intra_sra(void)3502 gate_intra_sra (void)
3503 {
3504   return flag_tree_sra != 0 && dbg_cnt (tree_sra);
3505 }
3506 
3507 
3508 namespace {
3509 
3510 const pass_data pass_data_sra_early =
3511 {
3512   GIMPLE_PASS, /* type */
3513   "esra", /* name */
3514   OPTGROUP_NONE, /* optinfo_flags */
3515   true, /* has_gate */
3516   true, /* has_execute */
3517   TV_TREE_SRA, /* tv_id */
3518   ( PROP_cfg | PROP_ssa ), /* properties_required */
3519   0, /* properties_provided */
3520   0, /* properties_destroyed */
3521   0, /* todo_flags_start */
3522   ( TODO_update_ssa | TODO_verify_ssa ), /* todo_flags_finish */
3523 };
3524 
3525 class pass_sra_early : public gimple_opt_pass
3526 {
3527 public:
pass_sra_early(gcc::context * ctxt)3528   pass_sra_early (gcc::context *ctxt)
3529     : gimple_opt_pass (pass_data_sra_early, ctxt)
3530   {}
3531 
3532   /* opt_pass methods: */
gate()3533   bool gate () { return gate_intra_sra (); }
execute()3534   unsigned int execute () { return early_intra_sra (); }
3535 
3536 }; // class pass_sra_early
3537 
3538 } // anon namespace
3539 
3540 gimple_opt_pass *
make_pass_sra_early(gcc::context * ctxt)3541 make_pass_sra_early (gcc::context *ctxt)
3542 {
3543   return new pass_sra_early (ctxt);
3544 }
3545 
3546 namespace {
3547 
3548 const pass_data pass_data_sra =
3549 {
3550   GIMPLE_PASS, /* type */
3551   "sra", /* name */
3552   OPTGROUP_NONE, /* optinfo_flags */
3553   true, /* has_gate */
3554   true, /* has_execute */
3555   TV_TREE_SRA, /* tv_id */
3556   ( PROP_cfg | PROP_ssa ), /* properties_required */
3557   0, /* properties_provided */
3558   0, /* properties_destroyed */
3559   TODO_update_address_taken, /* todo_flags_start */
3560   ( TODO_update_ssa | TODO_verify_ssa ), /* todo_flags_finish */
3561 };
3562 
3563 class pass_sra : public gimple_opt_pass
3564 {
3565 public:
pass_sra(gcc::context * ctxt)3566   pass_sra (gcc::context *ctxt)
3567     : gimple_opt_pass (pass_data_sra, ctxt)
3568   {}
3569 
3570   /* opt_pass methods: */
gate()3571   bool gate () { return gate_intra_sra (); }
execute()3572   unsigned int execute () { return late_intra_sra (); }
3573 
3574 }; // class pass_sra
3575 
3576 } // anon namespace
3577 
3578 gimple_opt_pass *
make_pass_sra(gcc::context * ctxt)3579 make_pass_sra (gcc::context *ctxt)
3580 {
3581   return new pass_sra (ctxt);
3582 }
3583 
3584 
3585 /* Return true iff PARM (which must be a parm_decl) is an unused scalar
3586    parameter.  */
3587 
3588 static bool
is_unused_scalar_param(tree parm)3589 is_unused_scalar_param (tree parm)
3590 {
3591   tree name;
3592   return (is_gimple_reg (parm)
3593 	  && (!(name = ssa_default_def (cfun, parm))
3594 	      || has_zero_uses (name)));
3595 }
3596 
3597 /* Scan immediate uses of a default definition SSA name of a parameter PARM and
3598    examine whether there are any direct or otherwise infeasible ones.  If so,
3599    return true, otherwise return false.  PARM must be a gimple register with a
3600    non-NULL default definition.  */
3601 
3602 static bool
ptr_parm_has_direct_uses(tree parm)3603 ptr_parm_has_direct_uses (tree parm)
3604 {
3605   imm_use_iterator ui;
3606   gimple stmt;
3607   tree name = ssa_default_def (cfun, parm);
3608   bool ret = false;
3609 
3610   FOR_EACH_IMM_USE_STMT (stmt, ui, name)
3611     {
3612       int uses_ok = 0;
3613       use_operand_p use_p;
3614 
3615       if (is_gimple_debug (stmt))
3616 	continue;
3617 
3618       /* Valid uses include dereferences on the lhs and the rhs.  */
3619       if (gimple_has_lhs (stmt))
3620 	{
3621 	  tree lhs = gimple_get_lhs (stmt);
3622 	  while (handled_component_p (lhs))
3623 	    lhs = TREE_OPERAND (lhs, 0);
3624 	  if (TREE_CODE (lhs) == MEM_REF
3625 	      && TREE_OPERAND (lhs, 0) == name
3626 	      && integer_zerop (TREE_OPERAND (lhs, 1))
3627 	      && types_compatible_p (TREE_TYPE (lhs),
3628 				     TREE_TYPE (TREE_TYPE (name)))
3629 	      && !TREE_THIS_VOLATILE (lhs))
3630 	    uses_ok++;
3631 	}
3632       if (gimple_assign_single_p (stmt))
3633 	{
3634 	  tree rhs = gimple_assign_rhs1 (stmt);
3635 	  while (handled_component_p (rhs))
3636 	    rhs = TREE_OPERAND (rhs, 0);
3637 	  if (TREE_CODE (rhs) == MEM_REF
3638 	      && TREE_OPERAND (rhs, 0) == name
3639 	      && integer_zerop (TREE_OPERAND (rhs, 1))
3640 	      && types_compatible_p (TREE_TYPE (rhs),
3641 				     TREE_TYPE (TREE_TYPE (name)))
3642 	      && !TREE_THIS_VOLATILE (rhs))
3643 	    uses_ok++;
3644 	}
3645       else if (is_gimple_call (stmt))
3646 	{
3647 	  unsigned i;
3648 	  for (i = 0; i < gimple_call_num_args (stmt); ++i)
3649 	    {
3650 	      tree arg = gimple_call_arg (stmt, i);
3651 	      while (handled_component_p (arg))
3652 		arg = TREE_OPERAND (arg, 0);
3653 	      if (TREE_CODE (arg) == MEM_REF
3654 		  && TREE_OPERAND (arg, 0) == name
3655 		  && integer_zerop (TREE_OPERAND (arg, 1))
3656 		  && types_compatible_p (TREE_TYPE (arg),
3657 					 TREE_TYPE (TREE_TYPE (name)))
3658 		  && !TREE_THIS_VOLATILE (arg))
3659 		uses_ok++;
3660 	    }
3661 	}
3662 
3663       /* If the number of valid uses does not match the number of
3664          uses in this stmt there is an unhandled use.  */
3665       FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
3666 	--uses_ok;
3667 
3668       if (uses_ok != 0)
3669 	ret = true;
3670 
3671       if (ret)
3672 	BREAK_FROM_IMM_USE_STMT (ui);
3673     }
3674 
3675   return ret;
3676 }
3677 
3678 /* Identify candidates for reduction for IPA-SRA based on their type and mark
3679    them in candidate_bitmap.  Note that these do not necessarily include
3680    parameter which are unused and thus can be removed.  Return true iff any
3681    such candidate has been found.  */
3682 
3683 static bool
find_param_candidates(void)3684 find_param_candidates (void)
3685 {
3686   tree parm;
3687   int count = 0;
3688   bool ret = false;
3689   const char *msg;
3690 
3691   for (parm = DECL_ARGUMENTS (current_function_decl);
3692        parm;
3693        parm = DECL_CHAIN (parm))
3694     {
3695       tree type = TREE_TYPE (parm);
3696       tree_node **slot;
3697 
3698       count++;
3699 
3700       if (TREE_THIS_VOLATILE (parm)
3701 	  || TREE_ADDRESSABLE (parm)
3702 	  || (!is_gimple_reg_type (type) && is_va_list_type (type)))
3703 	continue;
3704 
3705       if (is_unused_scalar_param (parm))
3706 	{
3707 	  ret = true;
3708 	  continue;
3709 	}
3710 
3711       if (POINTER_TYPE_P (type))
3712 	{
3713 	  type = TREE_TYPE (type);
3714 
3715 	  if (TREE_CODE (type) == FUNCTION_TYPE
3716 	      || TYPE_VOLATILE (type)
3717 	      || (TREE_CODE (type) == ARRAY_TYPE
3718 		  && TYPE_NONALIASED_COMPONENT (type))
3719 	      || !is_gimple_reg (parm)
3720 	      || is_va_list_type (type)
3721 	      || ptr_parm_has_direct_uses (parm))
3722 	    continue;
3723 	}
3724       else if (!AGGREGATE_TYPE_P (type))
3725 	continue;
3726 
3727       if (!COMPLETE_TYPE_P (type)
3728 	  || !tree_fits_uhwi_p (TYPE_SIZE (type))
3729           || tree_to_uhwi (TYPE_SIZE (type)) == 0
3730 	  || (AGGREGATE_TYPE_P (type)
3731 	      && type_internals_preclude_sra_p (type, &msg)))
3732 	continue;
3733 
3734       bitmap_set_bit (candidate_bitmap, DECL_UID (parm));
3735       slot = candidates.find_slot_with_hash (parm, DECL_UID (parm), INSERT);
3736       *slot = parm;
3737 
3738       ret = true;
3739       if (dump_file && (dump_flags & TDF_DETAILS))
3740 	{
3741 	  fprintf (dump_file, "Candidate (%d): ", DECL_UID (parm));
3742 	  print_generic_expr (dump_file, parm, 0);
3743 	  fprintf (dump_file, "\n");
3744 	}
3745     }
3746 
3747   func_param_count = count;
3748   return ret;
3749 }
3750 
3751 /* Callback of walk_aliased_vdefs, marks the access passed as DATA as
3752    maybe_modified. */
3753 
3754 static bool
mark_maybe_modified(ao_ref * ao ATTRIBUTE_UNUSED,tree vdef ATTRIBUTE_UNUSED,void * data)3755 mark_maybe_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
3756 		     void *data)
3757 {
3758   struct access *repr = (struct access *) data;
3759 
3760   repr->grp_maybe_modified = 1;
3761   return true;
3762 }
3763 
3764 /* Analyze what representatives (in linked lists accessible from
3765    REPRESENTATIVES) can be modified by side effects of statements in the
3766    current function.  */
3767 
3768 static void
analyze_modified_params(vec<access_p> representatives)3769 analyze_modified_params (vec<access_p> representatives)
3770 {
3771   int i;
3772 
3773   for (i = 0; i < func_param_count; i++)
3774     {
3775       struct access *repr;
3776 
3777       for (repr = representatives[i];
3778 	   repr;
3779 	   repr = repr->next_grp)
3780 	{
3781 	  struct access *access;
3782 	  bitmap visited;
3783 	  ao_ref ar;
3784 
3785 	  if (no_accesses_p (repr))
3786 	    continue;
3787 	  if (!POINTER_TYPE_P (TREE_TYPE (repr->base))
3788 	      || repr->grp_maybe_modified)
3789 	    continue;
3790 
3791 	  ao_ref_init (&ar, repr->expr);
3792 	  visited = BITMAP_ALLOC (NULL);
3793 	  for (access = repr; access; access = access->next_sibling)
3794 	    {
3795 	      /* All accesses are read ones, otherwise grp_maybe_modified would
3796 		 be trivially set.  */
3797 	      walk_aliased_vdefs (&ar, gimple_vuse (access->stmt),
3798 				  mark_maybe_modified, repr, &visited);
3799 	      if (repr->grp_maybe_modified)
3800 		break;
3801 	    }
3802 	  BITMAP_FREE (visited);
3803 	}
3804     }
3805 }
3806 
3807 /* Propagate distances in bb_dereferences in the opposite direction than the
3808    control flow edges, in each step storing the maximum of the current value
3809    and the minimum of all successors.  These steps are repeated until the table
3810    stabilizes.  Note that BBs which might terminate the functions (according to
3811    final_bbs bitmap) never updated in this way.  */
3812 
3813 static void
propagate_dereference_distances(void)3814 propagate_dereference_distances (void)
3815 {
3816   basic_block bb;
3817 
3818   auto_vec<basic_block> queue (last_basic_block_for_fn (cfun));
3819   queue.quick_push (ENTRY_BLOCK_PTR_FOR_FN (cfun));
3820   FOR_EACH_BB_FN (bb, cfun)
3821     {
3822       queue.quick_push (bb);
3823       bb->aux = bb;
3824     }
3825 
3826   while (!queue.is_empty ())
3827     {
3828       edge_iterator ei;
3829       edge e;
3830       bool change = false;
3831       int i;
3832 
3833       bb = queue.pop ();
3834       bb->aux = NULL;
3835 
3836       if (bitmap_bit_p (final_bbs, bb->index))
3837 	continue;
3838 
3839       for (i = 0; i < func_param_count; i++)
3840 	{
3841 	  int idx = bb->index * func_param_count + i;
3842 	  bool first = true;
3843 	  HOST_WIDE_INT inh = 0;
3844 
3845 	  FOR_EACH_EDGE (e, ei, bb->succs)
3846 	  {
3847 	    int succ_idx = e->dest->index * func_param_count + i;
3848 
3849 	    if (e->src == EXIT_BLOCK_PTR_FOR_FN (cfun))
3850 	      continue;
3851 
3852 	    if (first)
3853 	      {
3854 		first = false;
3855 		inh = bb_dereferences [succ_idx];
3856 	      }
3857 	    else if (bb_dereferences [succ_idx] < inh)
3858 	      inh = bb_dereferences [succ_idx];
3859 	  }
3860 
3861 	  if (!first && bb_dereferences[idx] < inh)
3862 	    {
3863 	      bb_dereferences[idx] = inh;
3864 	      change = true;
3865 	    }
3866 	}
3867 
3868       if (change && !bitmap_bit_p (final_bbs, bb->index))
3869 	FOR_EACH_EDGE (e, ei, bb->preds)
3870 	  {
3871 	    if (e->src->aux)
3872 	      continue;
3873 
3874 	    e->src->aux = e->src;
3875 	    queue.quick_push (e->src);
3876 	  }
3877     }
3878 }
3879 
3880 /* Dump a dereferences TABLE with heading STR to file F.  */
3881 
3882 static void
dump_dereferences_table(FILE * f,const char * str,HOST_WIDE_INT * table)3883 dump_dereferences_table (FILE *f, const char *str, HOST_WIDE_INT *table)
3884 {
3885   basic_block bb;
3886 
3887   fprintf (dump_file, str);
3888   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun),
3889 		  EXIT_BLOCK_PTR_FOR_FN (cfun), next_bb)
3890     {
3891       fprintf (f, "%4i  %i   ", bb->index, bitmap_bit_p (final_bbs, bb->index));
3892       if (bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
3893 	{
3894 	  int i;
3895 	  for (i = 0; i < func_param_count; i++)
3896 	    {
3897 	      int idx = bb->index * func_param_count + i;
3898 	      fprintf (f, " %4" HOST_WIDE_INT_PRINT "d", table[idx]);
3899 	    }
3900 	}
3901       fprintf (f, "\n");
3902     }
3903   fprintf (dump_file, "\n");
3904 }
3905 
3906 /* Determine what (parts of) parameters passed by reference that are not
3907    assigned to are not certainly dereferenced in this function and thus the
3908    dereferencing cannot be safely moved to the caller without potentially
3909    introducing a segfault.  Mark such REPRESENTATIVES as
3910    grp_not_necessarilly_dereferenced.
3911 
3912    The dereferenced maximum "distance," i.e. the offset + size of the accessed
3913    part is calculated rather than simple booleans are calculated for each
3914    pointer parameter to handle cases when only a fraction of the whole
3915    aggregate is allocated (see testsuite/gcc.c-torture/execute/ipa-sra-2.c for
3916    an example).
3917 
3918    The maximum dereference distances for each pointer parameter and BB are
3919    already stored in bb_dereference.  This routine simply propagates these
3920    values upwards by propagate_dereference_distances and then compares the
3921    distances of individual parameters in the ENTRY BB to the equivalent
3922    distances of each representative of a (fraction of a) parameter.  */
3923 
3924 static void
analyze_caller_dereference_legality(vec<access_p> representatives)3925 analyze_caller_dereference_legality (vec<access_p> representatives)
3926 {
3927   int i;
3928 
3929   if (dump_file && (dump_flags & TDF_DETAILS))
3930     dump_dereferences_table (dump_file,
3931 			     "Dereference table before propagation:\n",
3932 			     bb_dereferences);
3933 
3934   propagate_dereference_distances ();
3935 
3936   if (dump_file && (dump_flags & TDF_DETAILS))
3937     dump_dereferences_table (dump_file,
3938 			     "Dereference table after propagation:\n",
3939 			     bb_dereferences);
3940 
3941   for (i = 0; i < func_param_count; i++)
3942     {
3943       struct access *repr = representatives[i];
3944       int idx = ENTRY_BLOCK_PTR_FOR_FN (cfun)->index * func_param_count + i;
3945 
3946       if (!repr || no_accesses_p (repr))
3947 	continue;
3948 
3949       do
3950 	{
3951 	  if ((repr->offset + repr->size) > bb_dereferences[idx])
3952 	    repr->grp_not_necessarilly_dereferenced = 1;
3953 	  repr = repr->next_grp;
3954 	}
3955       while (repr);
3956     }
3957 }
3958 
3959 /* Return the representative access for the parameter declaration PARM if it is
3960    a scalar passed by reference which is not written to and the pointer value
3961    is not used directly.  Thus, if it is legal to dereference it in the caller
3962    and we can rule out modifications through aliases, such parameter should be
3963    turned into one passed by value.  Return NULL otherwise.  */
3964 
3965 static struct access *
unmodified_by_ref_scalar_representative(tree parm)3966 unmodified_by_ref_scalar_representative (tree parm)
3967 {
3968   int i, access_count;
3969   struct access *repr;
3970   vec<access_p> *access_vec;
3971 
3972   access_vec = get_base_access_vector (parm);
3973   gcc_assert (access_vec);
3974   repr = (*access_vec)[0];
3975   if (repr->write)
3976     return NULL;
3977   repr->group_representative = repr;
3978 
3979   access_count = access_vec->length ();
3980   for (i = 1; i < access_count; i++)
3981     {
3982       struct access *access = (*access_vec)[i];
3983       if (access->write)
3984 	return NULL;
3985       access->group_representative = repr;
3986       access->next_sibling = repr->next_sibling;
3987       repr->next_sibling = access;
3988     }
3989 
3990   repr->grp_read = 1;
3991   repr->grp_scalar_ptr = 1;
3992   return repr;
3993 }
3994 
3995 /* Return true iff this ACCESS precludes IPA-SRA of the parameter it is
3996    associated with.  REQ_ALIGN is the minimum required alignment.  */
3997 
3998 static bool
access_precludes_ipa_sra_p(struct access * access,unsigned int req_align)3999 access_precludes_ipa_sra_p (struct access *access, unsigned int req_align)
4000 {
4001   unsigned int exp_align;
4002   /* Avoid issues such as the second simple testcase in PR 42025.  The problem
4003      is incompatible assign in a call statement (and possibly even in asm
4004      statements).  This can be relaxed by using a new temporary but only for
4005      non-TREE_ADDRESSABLE types and is probably not worth the complexity. (In
4006      intraprocedural SRA we deal with this by keeping the old aggregate around,
4007      something we cannot do in IPA-SRA.)  */
4008   if (access->write
4009       && (is_gimple_call (access->stmt)
4010 	  || gimple_code (access->stmt) == GIMPLE_ASM))
4011     return true;
4012 
4013   exp_align = get_object_alignment (access->expr);
4014   if (exp_align < req_align)
4015     return true;
4016 
4017   return false;
4018 }
4019 
4020 
4021 /* Sort collected accesses for parameter PARM, identify representatives for
4022    each accessed region and link them together.  Return NULL if there are
4023    different but overlapping accesses, return the special ptr value meaning
4024    there are no accesses for this parameter if that is the case and return the
4025    first representative otherwise.  Set *RO_GRP if there is a group of accesses
4026    with only read (i.e. no write) accesses.  */
4027 
4028 static struct access *
splice_param_accesses(tree parm,bool * ro_grp)4029 splice_param_accesses (tree parm, bool *ro_grp)
4030 {
4031   int i, j, access_count, group_count;
4032   int agg_size, total_size = 0;
4033   struct access *access, *res, **prev_acc_ptr = &res;
4034   vec<access_p> *access_vec;
4035 
4036   access_vec = get_base_access_vector (parm);
4037   if (!access_vec)
4038     return &no_accesses_representant;
4039   access_count = access_vec->length ();
4040 
4041   access_vec->qsort (compare_access_positions);
4042 
4043   i = 0;
4044   total_size = 0;
4045   group_count = 0;
4046   while (i < access_count)
4047     {
4048       bool modification;
4049       tree a1_alias_type;
4050       access = (*access_vec)[i];
4051       modification = access->write;
4052       if (access_precludes_ipa_sra_p (access, TYPE_ALIGN (access->type)))
4053 	return NULL;
4054       a1_alias_type = reference_alias_ptr_type (access->expr);
4055 
4056       /* Access is about to become group representative unless we find some
4057 	 nasty overlap which would preclude us from breaking this parameter
4058 	 apart. */
4059 
4060       j = i + 1;
4061       while (j < access_count)
4062 	{
4063 	  struct access *ac2 = (*access_vec)[j];
4064 	  if (ac2->offset != access->offset)
4065 	    {
4066 	      /* All or nothing law for parameters. */
4067 	      if (access->offset + access->size > ac2->offset)
4068 		return NULL;
4069 	      else
4070 		break;
4071 	    }
4072 	  else if (ac2->size != access->size)
4073 	    return NULL;
4074 
4075 	  if (access_precludes_ipa_sra_p (ac2, TYPE_ALIGN (access->type))
4076 	      || (ac2->type != access->type
4077 		  && (TREE_ADDRESSABLE (ac2->type)
4078 		      || TREE_ADDRESSABLE (access->type)))
4079 	      || (reference_alias_ptr_type (ac2->expr) != a1_alias_type))
4080 	    return NULL;
4081 
4082 	  modification |= ac2->write;
4083 	  ac2->group_representative = access;
4084 	  ac2->next_sibling = access->next_sibling;
4085 	  access->next_sibling = ac2;
4086 	  j++;
4087 	}
4088 
4089       group_count++;
4090       access->grp_maybe_modified = modification;
4091       if (!modification)
4092 	*ro_grp = true;
4093       *prev_acc_ptr = access;
4094       prev_acc_ptr = &access->next_grp;
4095       total_size += access->size;
4096       i = j;
4097     }
4098 
4099   if (POINTER_TYPE_P (TREE_TYPE (parm)))
4100     agg_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))));
4101   else
4102     agg_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (parm)));
4103   if (total_size >= agg_size)
4104     return NULL;
4105 
4106   gcc_assert (group_count > 0);
4107   return res;
4108 }
4109 
4110 /* Decide whether parameters with representative accesses given by REPR should
4111    be reduced into components.  */
4112 
4113 static int
decide_one_param_reduction(struct access * repr)4114 decide_one_param_reduction (struct access *repr)
4115 {
4116   int total_size, cur_parm_size, agg_size, new_param_count, parm_size_limit;
4117   bool by_ref;
4118   tree parm;
4119 
4120   parm = repr->base;
4121   cur_parm_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (parm)));
4122   gcc_assert (cur_parm_size > 0);
4123 
4124   if (POINTER_TYPE_P (TREE_TYPE (parm)))
4125     {
4126       by_ref = true;
4127       agg_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))));
4128     }
4129   else
4130     {
4131       by_ref = false;
4132       agg_size = cur_parm_size;
4133     }
4134 
4135   if (dump_file)
4136     {
4137       struct access *acc;
4138       fprintf (dump_file, "Evaluating PARAM group sizes for ");
4139       print_generic_expr (dump_file, parm, 0);
4140       fprintf (dump_file, " (UID: %u): \n", DECL_UID (parm));
4141       for (acc = repr; acc; acc = acc->next_grp)
4142 	dump_access (dump_file, acc, true);
4143     }
4144 
4145   total_size = 0;
4146   new_param_count = 0;
4147 
4148   for (; repr; repr = repr->next_grp)
4149     {
4150       gcc_assert (parm == repr->base);
4151 
4152       /* Taking the address of a non-addressable field is verboten.  */
4153       if (by_ref && repr->non_addressable)
4154 	return 0;
4155 
4156       /* Do not decompose a non-BLKmode param in a way that would
4157          create BLKmode params.  Especially for by-reference passing
4158 	 (thus, pointer-type param) this is hardly worthwhile.  */
4159       if (DECL_MODE (parm) != BLKmode
4160 	  && TYPE_MODE (repr->type) == BLKmode)
4161 	return 0;
4162 
4163       if (!by_ref || (!repr->grp_maybe_modified
4164 		      && !repr->grp_not_necessarilly_dereferenced))
4165 	total_size += repr->size;
4166       else
4167 	total_size += cur_parm_size;
4168 
4169       new_param_count++;
4170     }
4171 
4172   gcc_assert (new_param_count > 0);
4173 
4174   if (optimize_function_for_size_p (cfun))
4175     parm_size_limit = cur_parm_size;
4176   else
4177     parm_size_limit = (PARAM_VALUE (PARAM_IPA_SRA_PTR_GROWTH_FACTOR)
4178                        * cur_parm_size);
4179 
4180   if (total_size < agg_size
4181       && total_size <= parm_size_limit)
4182     {
4183       if (dump_file)
4184 	fprintf (dump_file, "    ....will be split into %i components\n",
4185 		 new_param_count);
4186       return new_param_count;
4187     }
4188   else
4189     return 0;
4190 }
4191 
4192 /* The order of the following enums is important, we need to do extra work for
4193    UNUSED_PARAMS, BY_VAL_ACCESSES and UNMODIF_BY_REF_ACCESSES.  */
4194 enum ipa_splicing_result { NO_GOOD_ACCESS, UNUSED_PARAMS, BY_VAL_ACCESSES,
4195 			  MODIF_BY_REF_ACCESSES, UNMODIF_BY_REF_ACCESSES };
4196 
4197 /* Identify representatives of all accesses to all candidate parameters for
4198    IPA-SRA.  Return result based on what representatives have been found. */
4199 
4200 static enum ipa_splicing_result
splice_all_param_accesses(vec<access_p> & representatives)4201 splice_all_param_accesses (vec<access_p> &representatives)
4202 {
4203   enum ipa_splicing_result result = NO_GOOD_ACCESS;
4204   tree parm;
4205   struct access *repr;
4206 
4207   representatives.create (func_param_count);
4208 
4209   for (parm = DECL_ARGUMENTS (current_function_decl);
4210        parm;
4211        parm = DECL_CHAIN (parm))
4212     {
4213       if (is_unused_scalar_param (parm))
4214 	{
4215 	  representatives.quick_push (&no_accesses_representant);
4216 	  if (result == NO_GOOD_ACCESS)
4217 	    result = UNUSED_PARAMS;
4218 	}
4219       else if (POINTER_TYPE_P (TREE_TYPE (parm))
4220 	       && is_gimple_reg_type (TREE_TYPE (TREE_TYPE (parm)))
4221 	       && bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
4222 	{
4223 	  repr = unmodified_by_ref_scalar_representative (parm);
4224 	  representatives.quick_push (repr);
4225 	  if (repr)
4226 	    result = UNMODIF_BY_REF_ACCESSES;
4227 	}
4228       else if (bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
4229 	{
4230 	  bool ro_grp = false;
4231 	  repr = splice_param_accesses (parm, &ro_grp);
4232 	  representatives.quick_push (repr);
4233 
4234 	  if (repr && !no_accesses_p (repr))
4235 	    {
4236 	      if (POINTER_TYPE_P (TREE_TYPE (parm)))
4237 		{
4238 		  if (ro_grp)
4239 		    result = UNMODIF_BY_REF_ACCESSES;
4240 		  else if (result < MODIF_BY_REF_ACCESSES)
4241 		    result = MODIF_BY_REF_ACCESSES;
4242 		}
4243 	      else if (result < BY_VAL_ACCESSES)
4244 		result = BY_VAL_ACCESSES;
4245 	    }
4246 	  else if (no_accesses_p (repr) && (result == NO_GOOD_ACCESS))
4247 	    result = UNUSED_PARAMS;
4248 	}
4249       else
4250 	representatives.quick_push (NULL);
4251     }
4252 
4253   if (result == NO_GOOD_ACCESS)
4254     {
4255       representatives.release ();
4256       return NO_GOOD_ACCESS;
4257     }
4258 
4259   return result;
4260 }
4261 
4262 /* Return the index of BASE in PARMS.  Abort if it is not found.  */
4263 
4264 static inline int
get_param_index(tree base,vec<tree> parms)4265 get_param_index (tree base, vec<tree> parms)
4266 {
4267   int i, len;
4268 
4269   len = parms.length ();
4270   for (i = 0; i < len; i++)
4271     if (parms[i] == base)
4272       return i;
4273   gcc_unreachable ();
4274 }
4275 
4276 /* Convert the decisions made at the representative level into compact
4277    parameter adjustments.  REPRESENTATIVES are pointers to first
4278    representatives of each param accesses, ADJUSTMENTS_COUNT is the expected
4279    final number of adjustments.  */
4280 
4281 static ipa_parm_adjustment_vec
turn_representatives_into_adjustments(vec<access_p> representatives,int adjustments_count)4282 turn_representatives_into_adjustments (vec<access_p> representatives,
4283 				       int adjustments_count)
4284 {
4285   vec<tree> parms;
4286   ipa_parm_adjustment_vec adjustments;
4287   tree parm;
4288   int i;
4289 
4290   gcc_assert (adjustments_count > 0);
4291   parms = ipa_get_vector_of_formal_parms (current_function_decl);
4292   adjustments.create (adjustments_count);
4293   parm = DECL_ARGUMENTS (current_function_decl);
4294   for (i = 0; i < func_param_count; i++, parm = DECL_CHAIN (parm))
4295     {
4296       struct access *repr = representatives[i];
4297 
4298       if (!repr || no_accesses_p (repr))
4299 	{
4300 	  struct ipa_parm_adjustment adj;
4301 
4302 	  memset (&adj, 0, sizeof (adj));
4303 	  adj.base_index = get_param_index (parm, parms);
4304 	  adj.base = parm;
4305 	  if (!repr)
4306 	    adj.op = IPA_PARM_OP_COPY;
4307 	  else
4308 	    adj.op = IPA_PARM_OP_REMOVE;
4309 	  adj.arg_prefix = "ISRA";
4310 	  adjustments.quick_push (adj);
4311 	}
4312       else
4313 	{
4314 	  struct ipa_parm_adjustment adj;
4315 	  int index = get_param_index (parm, parms);
4316 
4317 	  for (; repr; repr = repr->next_grp)
4318 	    {
4319 	      memset (&adj, 0, sizeof (adj));
4320 	      gcc_assert (repr->base == parm);
4321 	      adj.base_index = index;
4322 	      adj.base = repr->base;
4323 	      adj.type = repr->type;
4324 	      adj.alias_ptr_type = reference_alias_ptr_type (repr->expr);
4325 	      adj.offset = repr->offset;
4326 	      adj.by_ref = (POINTER_TYPE_P (TREE_TYPE (repr->base))
4327 			    && (repr->grp_maybe_modified
4328 				|| repr->grp_not_necessarilly_dereferenced));
4329 	      adj.arg_prefix = "ISRA";
4330 	      adjustments.quick_push (adj);
4331 	    }
4332 	}
4333     }
4334   parms.release ();
4335   return adjustments;
4336 }
4337 
4338 /* Analyze the collected accesses and produce a plan what to do with the
4339    parameters in the form of adjustments, NULL meaning nothing.  */
4340 
4341 static ipa_parm_adjustment_vec
analyze_all_param_acesses(void)4342 analyze_all_param_acesses (void)
4343 {
4344   enum ipa_splicing_result repr_state;
4345   bool proceed = false;
4346   int i, adjustments_count = 0;
4347   vec<access_p> representatives;
4348   ipa_parm_adjustment_vec adjustments;
4349 
4350   repr_state = splice_all_param_accesses (representatives);
4351   if (repr_state == NO_GOOD_ACCESS)
4352     return ipa_parm_adjustment_vec ();
4353 
4354   /* If there are any parameters passed by reference which are not modified
4355      directly, we need to check whether they can be modified indirectly.  */
4356   if (repr_state == UNMODIF_BY_REF_ACCESSES)
4357     {
4358       analyze_caller_dereference_legality (representatives);
4359       analyze_modified_params (representatives);
4360     }
4361 
4362   for (i = 0; i < func_param_count; i++)
4363     {
4364       struct access *repr = representatives[i];
4365 
4366       if (repr && !no_accesses_p (repr))
4367 	{
4368 	  if (repr->grp_scalar_ptr)
4369 	    {
4370 	      adjustments_count++;
4371 	      if (repr->grp_not_necessarilly_dereferenced
4372 		  || repr->grp_maybe_modified)
4373 		representatives[i] = NULL;
4374 	      else
4375 		{
4376 		  proceed = true;
4377 		  sra_stats.scalar_by_ref_to_by_val++;
4378 		}
4379 	    }
4380 	  else
4381 	    {
4382 	      int new_components = decide_one_param_reduction (repr);
4383 
4384 	      if (new_components == 0)
4385 		{
4386 		  representatives[i] = NULL;
4387 		  adjustments_count++;
4388 		}
4389 	      else
4390 		{
4391 		  adjustments_count += new_components;
4392 		  sra_stats.aggregate_params_reduced++;
4393 		  sra_stats.param_reductions_created += new_components;
4394 		  proceed = true;
4395 		}
4396 	    }
4397 	}
4398       else
4399 	{
4400 	  if (no_accesses_p (repr))
4401 	    {
4402 	      proceed = true;
4403 	      sra_stats.deleted_unused_parameters++;
4404 	    }
4405 	  adjustments_count++;
4406 	}
4407     }
4408 
4409   if (!proceed && dump_file)
4410     fprintf (dump_file, "NOT proceeding to change params.\n");
4411 
4412   if (proceed)
4413     adjustments = turn_representatives_into_adjustments (representatives,
4414 							 adjustments_count);
4415   else
4416     adjustments = ipa_parm_adjustment_vec ();
4417 
4418   representatives.release ();
4419   return adjustments;
4420 }
4421 
4422 /* If a parameter replacement identified by ADJ does not yet exist in the form
4423    of declaration, create it and record it, otherwise return the previously
4424    created one.  */
4425 
4426 static tree
get_replaced_param_substitute(struct ipa_parm_adjustment * adj)4427 get_replaced_param_substitute (struct ipa_parm_adjustment *adj)
4428 {
4429   tree repl;
4430   if (!adj->new_ssa_base)
4431     {
4432       char *pretty_name = make_fancy_name (adj->base);
4433 
4434       repl = create_tmp_reg (TREE_TYPE (adj->base), "ISR");
4435       DECL_NAME (repl) = get_identifier (pretty_name);
4436       obstack_free (&name_obstack, pretty_name);
4437 
4438       adj->new_ssa_base = repl;
4439     }
4440   else
4441     repl = adj->new_ssa_base;
4442   return repl;
4443 }
4444 
4445 /* Find the first adjustment for a particular parameter BASE in a vector of
4446    ADJUSTMENTS which is not a copy_param.  Return NULL if there is no such
4447    adjustment. */
4448 
4449 static struct ipa_parm_adjustment *
get_adjustment_for_base(ipa_parm_adjustment_vec adjustments,tree base)4450 get_adjustment_for_base (ipa_parm_adjustment_vec adjustments, tree base)
4451 {
4452   int i, len;
4453 
4454   len = adjustments.length ();
4455   for (i = 0; i < len; i++)
4456     {
4457       struct ipa_parm_adjustment *adj;
4458 
4459       adj = &adjustments[i];
4460       if (adj->op != IPA_PARM_OP_COPY && adj->base == base)
4461 	return adj;
4462     }
4463 
4464   return NULL;
4465 }
4466 
4467 /* If the statement STMT defines an SSA_NAME of a parameter which is to be
4468    removed because its value is not used, replace the SSA_NAME with a one
4469    relating to a created VAR_DECL together all of its uses and return true.
4470    ADJUSTMENTS is a pointer to an adjustments vector.  */
4471 
4472 static bool
replace_removed_params_ssa_names(gimple stmt,ipa_parm_adjustment_vec adjustments)4473 replace_removed_params_ssa_names (gimple stmt,
4474 				  ipa_parm_adjustment_vec adjustments)
4475 {
4476   struct ipa_parm_adjustment *adj;
4477   tree lhs, decl, repl, name;
4478 
4479   if (gimple_code (stmt) == GIMPLE_PHI)
4480     lhs = gimple_phi_result (stmt);
4481   else if (is_gimple_assign (stmt))
4482     lhs = gimple_assign_lhs (stmt);
4483   else if (is_gimple_call (stmt))
4484     lhs = gimple_call_lhs (stmt);
4485   else
4486     gcc_unreachable ();
4487 
4488   if (TREE_CODE (lhs) != SSA_NAME)
4489     return false;
4490 
4491   decl = SSA_NAME_VAR (lhs);
4492   if (decl == NULL_TREE
4493       || TREE_CODE (decl) != PARM_DECL)
4494     return false;
4495 
4496   adj = get_adjustment_for_base (adjustments, decl);
4497   if (!adj)
4498     return false;
4499 
4500   repl = get_replaced_param_substitute (adj);
4501   name = make_ssa_name (repl, stmt);
4502 
4503   if (dump_file)
4504     {
4505       fprintf (dump_file, "replacing an SSA name of a removed param ");
4506       print_generic_expr (dump_file, lhs, 0);
4507       fprintf (dump_file, " with ");
4508       print_generic_expr (dump_file, name, 0);
4509       fprintf (dump_file, "\n");
4510     }
4511 
4512   if (is_gimple_assign (stmt))
4513     gimple_assign_set_lhs (stmt, name);
4514   else if (is_gimple_call (stmt))
4515     gimple_call_set_lhs (stmt, name);
4516   else
4517     gimple_phi_set_result (stmt, name);
4518 
4519   replace_uses_by (lhs, name);
4520   release_ssa_name (lhs);
4521   return true;
4522 }
4523 
4524 /* If the statement pointed to by STMT_PTR contains any expressions that need
4525    to replaced with a different one as noted by ADJUSTMENTS, do so.  Handle any
4526    potential type incompatibilities (GSI is used to accommodate conversion
4527    statements and must point to the statement).  Return true iff the statement
4528    was modified.  */
4529 
4530 static bool
sra_ipa_modify_assign(gimple * stmt_ptr,gimple_stmt_iterator * gsi,ipa_parm_adjustment_vec adjustments)4531 sra_ipa_modify_assign (gimple *stmt_ptr, gimple_stmt_iterator *gsi,
4532 		       ipa_parm_adjustment_vec adjustments)
4533 {
4534   gimple stmt = *stmt_ptr;
4535   tree *lhs_p, *rhs_p;
4536   bool any;
4537 
4538   if (!gimple_assign_single_p (stmt))
4539     return false;
4540 
4541   rhs_p = gimple_assign_rhs1_ptr (stmt);
4542   lhs_p = gimple_assign_lhs_ptr (stmt);
4543 
4544   any = ipa_modify_expr (rhs_p, false, adjustments);
4545   any |= ipa_modify_expr (lhs_p, false, adjustments);
4546   if (any)
4547     {
4548       tree new_rhs = NULL_TREE;
4549 
4550       if (!useless_type_conversion_p (TREE_TYPE (*lhs_p), TREE_TYPE (*rhs_p)))
4551 	{
4552 	  if (TREE_CODE (*rhs_p) == CONSTRUCTOR)
4553 	    {
4554 	      /* V_C_Es of constructors can cause trouble (PR 42714).  */
4555 	      if (is_gimple_reg_type (TREE_TYPE (*lhs_p)))
4556 		*rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
4557 	      else
4558 		*rhs_p = build_constructor (TREE_TYPE (*lhs_p),
4559 					    NULL);
4560 	    }
4561 	  else
4562 	    new_rhs = fold_build1_loc (gimple_location (stmt),
4563 				       VIEW_CONVERT_EXPR, TREE_TYPE (*lhs_p),
4564 				       *rhs_p);
4565 	}
4566       else if (REFERENCE_CLASS_P (*rhs_p)
4567 	       && is_gimple_reg_type (TREE_TYPE (*lhs_p))
4568 	       && !is_gimple_reg (*lhs_p))
4569 	/* This can happen when an assignment in between two single field
4570 	   structures is turned into an assignment in between two pointers to
4571 	   scalars (PR 42237).  */
4572 	new_rhs = *rhs_p;
4573 
4574       if (new_rhs)
4575 	{
4576 	  tree tmp = force_gimple_operand_gsi (gsi, new_rhs, true, NULL_TREE,
4577 					       true, GSI_SAME_STMT);
4578 
4579 	  gimple_assign_set_rhs_from_tree (gsi, tmp);
4580 	}
4581 
4582       return true;
4583     }
4584 
4585   return false;
4586 }
4587 
4588 /* Traverse the function body and all modifications as described in
4589    ADJUSTMENTS.  Return true iff the CFG has been changed.  */
4590 
4591 bool
ipa_sra_modify_function_body(ipa_parm_adjustment_vec adjustments)4592 ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments)
4593 {
4594   bool cfg_changed = false;
4595   basic_block bb;
4596 
4597   FOR_EACH_BB_FN (bb, cfun)
4598     {
4599       gimple_stmt_iterator gsi;
4600 
4601       for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4602 	replace_removed_params_ssa_names (gsi_stmt (gsi), adjustments);
4603 
4604       gsi = gsi_start_bb (bb);
4605       while (!gsi_end_p (gsi))
4606 	{
4607 	  gimple stmt = gsi_stmt (gsi);
4608 	  bool modified = false;
4609 	  tree *t;
4610 	  unsigned i;
4611 
4612 	  switch (gimple_code (stmt))
4613 	    {
4614 	    case GIMPLE_RETURN:
4615 	      t = gimple_return_retval_ptr (stmt);
4616 	      if (*t != NULL_TREE)
4617 		modified |= ipa_modify_expr (t, true, adjustments);
4618 	      break;
4619 
4620 	    case GIMPLE_ASSIGN:
4621 	      modified |= sra_ipa_modify_assign (&stmt, &gsi, adjustments);
4622 	      modified |= replace_removed_params_ssa_names (stmt, adjustments);
4623 	      break;
4624 
4625 	    case GIMPLE_CALL:
4626 	      /* Operands must be processed before the lhs.  */
4627 	      for (i = 0; i < gimple_call_num_args (stmt); i++)
4628 		{
4629 		  t = gimple_call_arg_ptr (stmt, i);
4630 		  modified |= ipa_modify_expr (t, true, adjustments);
4631 		}
4632 
4633 	      if (gimple_call_lhs (stmt))
4634 		{
4635 		  t = gimple_call_lhs_ptr (stmt);
4636 		  modified |= ipa_modify_expr (t, false, adjustments);
4637 		  modified |= replace_removed_params_ssa_names (stmt,
4638 								adjustments);
4639 		}
4640 	      break;
4641 
4642 	    case GIMPLE_ASM:
4643 	      for (i = 0; i < gimple_asm_ninputs (stmt); i++)
4644 		{
4645 		  t = &TREE_VALUE (gimple_asm_input_op (stmt, i));
4646 		  modified |= ipa_modify_expr (t, true, adjustments);
4647 		}
4648 	      for (i = 0; i < gimple_asm_noutputs (stmt); i++)
4649 		{
4650 		  t = &TREE_VALUE (gimple_asm_output_op (stmt, i));
4651 		  modified |= ipa_modify_expr (t, false, adjustments);
4652 		}
4653 	      break;
4654 
4655 	    default:
4656 	      break;
4657 	    }
4658 
4659 	  if (modified)
4660 	    {
4661 	      update_stmt (stmt);
4662 	      if (maybe_clean_eh_stmt (stmt)
4663 		  && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
4664 		cfg_changed = true;
4665 	    }
4666 	  gsi_next (&gsi);
4667 	}
4668     }
4669 
4670   return cfg_changed;
4671 }
4672 
4673 /* Call gimple_debug_bind_reset_value on all debug statements describing
4674    gimple register parameters that are being removed or replaced.  */
4675 
4676 static void
sra_ipa_reset_debug_stmts(ipa_parm_adjustment_vec adjustments)4677 sra_ipa_reset_debug_stmts (ipa_parm_adjustment_vec adjustments)
4678 {
4679   int i, len;
4680   gimple_stmt_iterator *gsip = NULL, gsi;
4681 
4682   if (MAY_HAVE_DEBUG_STMTS && single_succ_p (ENTRY_BLOCK_PTR_FOR_FN (cfun)))
4683     {
4684       gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
4685       gsip = &gsi;
4686     }
4687   len = adjustments.length ();
4688   for (i = 0; i < len; i++)
4689     {
4690       struct ipa_parm_adjustment *adj;
4691       imm_use_iterator ui;
4692       gimple stmt, def_temp;
4693       tree name, vexpr, copy = NULL_TREE;
4694       use_operand_p use_p;
4695 
4696       adj = &adjustments[i];
4697       if (adj->op == IPA_PARM_OP_COPY || !is_gimple_reg (adj->base))
4698 	continue;
4699       name = ssa_default_def (cfun, adj->base);
4700       vexpr = NULL;
4701       if (name)
4702 	FOR_EACH_IMM_USE_STMT (stmt, ui, name)
4703 	  {
4704 	    if (gimple_clobber_p (stmt))
4705 	      {
4706 		gimple_stmt_iterator cgsi = gsi_for_stmt (stmt);
4707 		unlink_stmt_vdef (stmt);
4708 		gsi_remove (&cgsi, true);
4709 		release_defs (stmt);
4710 		continue;
4711 	      }
4712 	    /* All other users must have been removed by
4713 	       ipa_sra_modify_function_body.  */
4714 	    gcc_assert (is_gimple_debug (stmt));
4715 	    if (vexpr == NULL && gsip != NULL)
4716 	      {
4717 		gcc_assert (TREE_CODE (adj->base) == PARM_DECL);
4718 		vexpr = make_node (DEBUG_EXPR_DECL);
4719 		def_temp = gimple_build_debug_source_bind (vexpr, adj->base,
4720 							   NULL);
4721 		DECL_ARTIFICIAL (vexpr) = 1;
4722 		TREE_TYPE (vexpr) = TREE_TYPE (name);
4723 		DECL_MODE (vexpr) = DECL_MODE (adj->base);
4724 		gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
4725 	      }
4726 	    if (vexpr)
4727 	      {
4728 		FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
4729 		  SET_USE (use_p, vexpr);
4730 	      }
4731 	    else
4732 	      gimple_debug_bind_reset_value (stmt);
4733 	    update_stmt (stmt);
4734 	  }
4735       /* Create a VAR_DECL for debug info purposes.  */
4736       if (!DECL_IGNORED_P (adj->base))
4737 	{
4738 	  copy = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
4739 			     VAR_DECL, DECL_NAME (adj->base),
4740 			     TREE_TYPE (adj->base));
4741 	  if (DECL_PT_UID_SET_P (adj->base))
4742 	    SET_DECL_PT_UID (copy, DECL_PT_UID (adj->base));
4743 	  TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (adj->base);
4744 	  TREE_READONLY (copy) = TREE_READONLY (adj->base);
4745 	  TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (adj->base);
4746 	  DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (adj->base);
4747 	  DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (adj->base);
4748 	  DECL_IGNORED_P (copy) = DECL_IGNORED_P (adj->base);
4749 	  DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (adj->base);
4750 	  DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
4751 	  SET_DECL_RTL (copy, 0);
4752 	  TREE_USED (copy) = 1;
4753 	  DECL_CONTEXT (copy) = current_function_decl;
4754 	  add_local_decl (cfun, copy);
4755 	  DECL_CHAIN (copy) =
4756 	    BLOCK_VARS (DECL_INITIAL (current_function_decl));
4757 	  BLOCK_VARS (DECL_INITIAL (current_function_decl)) = copy;
4758 	}
4759       if (gsip != NULL && copy && target_for_debug_bind (adj->base))
4760 	{
4761 	  gcc_assert (TREE_CODE (adj->base) == PARM_DECL);
4762 	  if (vexpr)
4763 	    def_temp = gimple_build_debug_bind (copy, vexpr, NULL);
4764 	  else
4765 	    def_temp = gimple_build_debug_source_bind (copy, adj->base,
4766 						       NULL);
4767 	  gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
4768 	}
4769     }
4770 }
4771 
4772 /* Return false if all callers have at least as many actual arguments as there
4773    are formal parameters in the current function and that their types
4774    match.  */
4775 
4776 static bool
some_callers_have_mismatched_arguments_p(struct cgraph_node * node,void * data ATTRIBUTE_UNUSED)4777 some_callers_have_mismatched_arguments_p (struct cgraph_node *node,
4778 					  void *data ATTRIBUTE_UNUSED)
4779 {
4780   struct cgraph_edge *cs;
4781   for (cs = node->callers; cs; cs = cs->next_caller)
4782     if (!callsite_arguments_match_p (cs->call_stmt))
4783       return true;
4784 
4785   return false;
4786 }
4787 
4788 /* Convert all callers of NODE.  */
4789 
4790 static bool
convert_callers_for_node(struct cgraph_node * node,void * data)4791 convert_callers_for_node (struct cgraph_node *node,
4792 		          void *data)
4793 {
4794   ipa_parm_adjustment_vec *adjustments = (ipa_parm_adjustment_vec *) data;
4795   bitmap recomputed_callers = BITMAP_ALLOC (NULL);
4796   struct cgraph_edge *cs;
4797 
4798   for (cs = node->callers; cs; cs = cs->next_caller)
4799     {
4800       push_cfun (DECL_STRUCT_FUNCTION (cs->caller->decl));
4801 
4802       if (dump_file)
4803 	fprintf (dump_file, "Adjusting call %s/%i -> %s/%i\n",
4804 		 xstrdup (cs->caller->name ()),
4805 		 cs->caller->order,
4806 		 xstrdup (cs->callee->name ()),
4807 		 cs->callee->order);
4808 
4809       ipa_modify_call_arguments (cs, cs->call_stmt, *adjustments);
4810 
4811       pop_cfun ();
4812     }
4813 
4814   for (cs = node->callers; cs; cs = cs->next_caller)
4815     if (bitmap_set_bit (recomputed_callers, cs->caller->uid)
4816 	&& gimple_in_ssa_p (DECL_STRUCT_FUNCTION (cs->caller->decl)))
4817       compute_inline_parameters (cs->caller, true);
4818   BITMAP_FREE (recomputed_callers);
4819 
4820   return true;
4821 }
4822 
4823 /* Convert all callers of NODE to pass parameters as given in ADJUSTMENTS.  */
4824 
4825 static void
convert_callers(struct cgraph_node * node,tree old_decl,ipa_parm_adjustment_vec adjustments)4826 convert_callers (struct cgraph_node *node, tree old_decl,
4827 		 ipa_parm_adjustment_vec adjustments)
4828 {
4829   basic_block this_block;
4830 
4831   cgraph_for_node_and_aliases (node, convert_callers_for_node,
4832 			       &adjustments, false);
4833 
4834   if (!encountered_recursive_call)
4835     return;
4836 
4837   FOR_EACH_BB_FN (this_block, cfun)
4838     {
4839       gimple_stmt_iterator gsi;
4840 
4841       for (gsi = gsi_start_bb (this_block); !gsi_end_p (gsi); gsi_next (&gsi))
4842         {
4843 	  gimple stmt = gsi_stmt (gsi);
4844 	  tree call_fndecl;
4845 	  if (gimple_code (stmt) != GIMPLE_CALL)
4846 	    continue;
4847 	  call_fndecl = gimple_call_fndecl (stmt);
4848 	  if (call_fndecl == old_decl)
4849 	    {
4850 	      if (dump_file)
4851 		fprintf (dump_file, "Adjusting recursive call");
4852 	      gimple_call_set_fndecl (stmt, node->decl);
4853 	      ipa_modify_call_arguments (NULL, stmt, adjustments);
4854 	    }
4855 	}
4856     }
4857 
4858   return;
4859 }
4860 
4861 /* Perform all the modification required in IPA-SRA for NODE to have parameters
4862    as given in ADJUSTMENTS.  Return true iff the CFG has been changed.  */
4863 
4864 static bool
modify_function(struct cgraph_node * node,ipa_parm_adjustment_vec adjustments)4865 modify_function (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments)
4866 {
4867   struct cgraph_node *new_node;
4868   bool cfg_changed;
4869   vec<cgraph_edge_p> redirect_callers = collect_callers_of_node (node);
4870 
4871   rebuild_cgraph_edges ();
4872   free_dominance_info (CDI_DOMINATORS);
4873   pop_cfun ();
4874 
4875   new_node = cgraph_function_versioning (node, redirect_callers,
4876 					 NULL,
4877 					 NULL, false, NULL, NULL, "isra");
4878   redirect_callers.release ();
4879 
4880   push_cfun (DECL_STRUCT_FUNCTION (new_node->decl));
4881   ipa_modify_formal_parameters (current_function_decl, adjustments);
4882   cfg_changed = ipa_sra_modify_function_body (adjustments);
4883   sra_ipa_reset_debug_stmts (adjustments);
4884   convert_callers (new_node, node->decl, adjustments);
4885   cgraph_make_node_local (new_node);
4886   return cfg_changed;
4887 }
4888 
4889 /* If NODE has a caller, return true.  */
4890 
4891 static bool
has_caller_p(struct cgraph_node * node,void * data ATTRIBUTE_UNUSED)4892 has_caller_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
4893 {
4894   if (node->callers)
4895     return true;
4896   return false;
4897 }
4898 
4899 /* Return false the function is apparently unsuitable for IPA-SRA based on it's
4900    attributes, return true otherwise.  NODE is the cgraph node of the current
4901    function.  */
4902 
4903 static bool
ipa_sra_preliminary_function_checks(struct cgraph_node * node)4904 ipa_sra_preliminary_function_checks (struct cgraph_node *node)
4905 {
4906   if (!cgraph_node_can_be_local_p (node))
4907     {
4908       if (dump_file)
4909 	fprintf (dump_file, "Function not local to this compilation unit.\n");
4910       return false;
4911     }
4912 
4913   if (!node->local.can_change_signature)
4914     {
4915       if (dump_file)
4916 	fprintf (dump_file, "Function can not change signature.\n");
4917       return false;
4918     }
4919 
4920   if (!tree_versionable_function_p (node->decl))
4921     {
4922       if (dump_file)
4923 	fprintf (dump_file, "Function is not versionable.\n");
4924       return false;
4925     }
4926 
4927   if (!opt_for_fn (node->decl, optimize)
4928       || !opt_for_fn (node->decl, flag_ipa_sra))
4929     {
4930       if (dump_file)
4931 	fprintf (dump_file, "Function not optimized.\n");
4932       return false;
4933     }
4934 
4935   if (DECL_VIRTUAL_P (current_function_decl))
4936     {
4937       if (dump_file)
4938 	fprintf (dump_file, "Function is a virtual method.\n");
4939       return false;
4940     }
4941 
4942   if ((DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl))
4943       && inline_summary (node)->size >= MAX_INLINE_INSNS_AUTO)
4944     {
4945       if (dump_file)
4946 	fprintf (dump_file, "Function too big to be made truly local.\n");
4947       return false;
4948     }
4949 
4950   if (!cgraph_for_node_and_aliases (node, has_caller_p, NULL, true))
4951     {
4952       if (dump_file)
4953 	fprintf (dump_file,
4954 		 "Function has no callers in this compilation unit.\n");
4955       return false;
4956     }
4957 
4958   if (cfun->stdarg)
4959     {
4960       if (dump_file)
4961 	fprintf (dump_file, "Function uses stdarg. \n");
4962       return false;
4963     }
4964 
4965   if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl)))
4966     return false;
4967 
4968   return true;
4969 }
4970 
4971 /* Perform early interprocedural SRA.  */
4972 
4973 static unsigned int
ipa_early_sra(void)4974 ipa_early_sra (void)
4975 {
4976   struct cgraph_node *node = cgraph_get_node (current_function_decl);
4977   ipa_parm_adjustment_vec adjustments;
4978   int ret = 0;
4979 
4980   if (!ipa_sra_preliminary_function_checks (node))
4981     return 0;
4982 
4983   sra_initialize ();
4984   sra_mode = SRA_MODE_EARLY_IPA;
4985 
4986   if (!find_param_candidates ())
4987     {
4988       if (dump_file)
4989 	fprintf (dump_file, "Function has no IPA-SRA candidates.\n");
4990       goto simple_out;
4991     }
4992 
4993   if (cgraph_for_node_and_aliases (node,
4994 				   some_callers_have_mismatched_arguments_p,
4995 				   NULL, true))
4996     {
4997       if (dump_file)
4998 	fprintf (dump_file, "There are callers with insufficient number of "
4999 		 "arguments or arguments with type mismatches.\n");
5000       goto simple_out;
5001     }
5002 
5003   bb_dereferences = XCNEWVEC (HOST_WIDE_INT,
5004 				 func_param_count
5005 				 * last_basic_block_for_fn (cfun));
5006   final_bbs = BITMAP_ALLOC (NULL);
5007 
5008   scan_function ();
5009   if (encountered_apply_args)
5010     {
5011       if (dump_file)
5012 	fprintf (dump_file, "Function calls  __builtin_apply_args().\n");
5013       goto out;
5014     }
5015 
5016   if (encountered_unchangable_recursive_call)
5017     {
5018       if (dump_file)
5019 	fprintf (dump_file, "Function calls itself with insufficient "
5020 		 "number of arguments.\n");
5021       goto out;
5022     }
5023 
5024   adjustments = analyze_all_param_acesses ();
5025   if (!adjustments.exists ())
5026     goto out;
5027   if (dump_file)
5028     ipa_dump_param_adjustments (dump_file, adjustments, current_function_decl);
5029 
5030   if (modify_function (node, adjustments))
5031     ret = TODO_update_ssa | TODO_cleanup_cfg;
5032   else
5033     ret = TODO_update_ssa;
5034   adjustments.release ();
5035 
5036   statistics_counter_event (cfun, "Unused parameters deleted",
5037 			    sra_stats.deleted_unused_parameters);
5038   statistics_counter_event (cfun, "Scalar parameters converted to by-value",
5039 			    sra_stats.scalar_by_ref_to_by_val);
5040   statistics_counter_event (cfun, "Aggregate parameters broken up",
5041 			    sra_stats.aggregate_params_reduced);
5042   statistics_counter_event (cfun, "Aggregate parameter components created",
5043 			    sra_stats.param_reductions_created);
5044 
5045  out:
5046   BITMAP_FREE (final_bbs);
5047   free (bb_dereferences);
5048  simple_out:
5049   sra_deinitialize ();
5050   return ret;
5051 }
5052 
5053 /* Return if early ipa sra shall be performed.  */
5054 static bool
ipa_early_sra_gate(void)5055 ipa_early_sra_gate (void)
5056 {
5057   return flag_ipa_sra && dbg_cnt (eipa_sra);
5058 }
5059 
5060 namespace {
5061 
5062 const pass_data pass_data_early_ipa_sra =
5063 {
5064   GIMPLE_PASS, /* type */
5065   "eipa_sra", /* name */
5066   OPTGROUP_NONE, /* optinfo_flags */
5067   true, /* has_gate */
5068   true, /* has_execute */
5069   TV_IPA_SRA, /* tv_id */
5070   0, /* properties_required */
5071   0, /* properties_provided */
5072   0, /* properties_destroyed */
5073   0, /* todo_flags_start */
5074   TODO_dump_symtab, /* todo_flags_finish */
5075 };
5076 
5077 class pass_early_ipa_sra : public gimple_opt_pass
5078 {
5079 public:
pass_early_ipa_sra(gcc::context * ctxt)5080   pass_early_ipa_sra (gcc::context *ctxt)
5081     : gimple_opt_pass (pass_data_early_ipa_sra, ctxt)
5082   {}
5083 
5084   /* opt_pass methods: */
gate()5085   bool gate () { return ipa_early_sra_gate (); }
execute()5086   unsigned int execute () { return ipa_early_sra (); }
5087 
5088 }; // class pass_early_ipa_sra
5089 
5090 } // anon namespace
5091 
5092 gimple_opt_pass *
make_pass_early_ipa_sra(gcc::context * ctxt)5093 make_pass_early_ipa_sra (gcc::context *ctxt)
5094 {
5095   return new pass_early_ipa_sra (ctxt);
5096 }
5097