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-2021 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 "backend.h"
78 #include "target.h"
79 #include "rtl.h"
80 #include "tree.h"
81 #include "gimple.h"
82 #include "predict.h"
83 #include "alloc-pool.h"
84 #include "tree-pass.h"
85 #include "ssa.h"
86 #include "cgraph.h"
87 #include "gimple-pretty-print.h"
88 #include "alias.h"
89 #include "fold-const.h"
90 #include "tree-eh.h"
91 #include "stor-layout.h"
92 #include "gimplify.h"
93 #include "gimple-iterator.h"
94 #include "gimplify-me.h"
95 #include "gimple-walk.h"
96 #include "tree-cfg.h"
97 #include "tree-dfa.h"
98 #include "tree-ssa.h"
99 #include "dbgcnt.h"
100 #include "builtins.h"
101 #include "tree-sra.h"
102 
103 
104 /* Enumeration of all aggregate reductions we can do.  */
105 enum sra_mode { SRA_MODE_EARLY_IPA,   /* early call regularization */
106 		SRA_MODE_EARLY_INTRA, /* early intraprocedural SRA */
107 		SRA_MODE_INTRA };     /* late intraprocedural SRA */
108 
109 /* Global variable describing which aggregate reduction we are performing at
110    the moment.  */
111 static enum sra_mode sra_mode;
112 
113 struct assign_link;
114 
115 /* ACCESS represents each access to an aggregate variable (as a whole or a
116    part).  It can also represent a group of accesses that refer to exactly the
117    same fragment of an aggregate (i.e. those that have exactly the same offset
118    and size).  Such representatives for a single aggregate, once determined,
119    are linked in a linked list and have the group fields set.
120 
121    Moreover, when doing intraprocedural SRA, a tree is built from those
122    representatives (by the means of first_child and next_sibling pointers), in
123    which all items in a subtree are "within" the root, i.e. their offset is
124    greater or equal to offset of the root and offset+size is smaller or equal
125    to offset+size of the root.  Children of an access are sorted by offset.
126 
127    Note that accesses to parts of vector and complex number types always
128    represented by an access to the whole complex number or a vector.  It is a
129    duty of the modifying functions to replace them appropriately.  */
130 
131 struct access
132 {
133   /* Values returned by  `get_ref_base_and_extent' for each component reference
134      If EXPR isn't a component reference  just set `BASE = EXPR', `OFFSET = 0',
135      `SIZE = TREE_SIZE (TREE_TYPE (expr))'.  */
136   HOST_WIDE_INT offset;
137   HOST_WIDE_INT size;
138   tree base;
139 
140   /* Expression.  It is context dependent so do not use it to create new
141      expressions to access the original aggregate.  See PR 42154 for a
142      testcase.  */
143   tree expr;
144   /* Type.  */
145   tree type;
146 
147   /* The statement this access belongs to.  */
148   gimple *stmt;
149 
150   /* Next group representative for this aggregate. */
151   struct access *next_grp;
152 
153   /* Pointer to the group representative.  Pointer to itself if the struct is
154      the representative.  */
155   struct access *group_representative;
156 
157   /* After access tree has been constructed, this points to the parent of the
158      current access, if there is one.  NULL for roots.  */
159   struct access *parent;
160 
161   /* If this access has any children (in terms of the definition above), this
162      points to the first one.  */
163   struct access *first_child;
164 
165   /* In intraprocedural SRA, pointer to the next sibling in the access tree as
166      described above.  */
167   struct access *next_sibling;
168 
169   /* Pointers to the first and last element in the linked list of assign
170      links for propagation from LHS to RHS.  */
171   struct assign_link *first_rhs_link, *last_rhs_link;
172 
173   /* Pointers to the first and last element in the linked list of assign
174      links for propagation from LHS to RHS.  */
175   struct assign_link *first_lhs_link, *last_lhs_link;
176 
177   /* Pointer to the next access in the work queues.  */
178   struct access *next_rhs_queued, *next_lhs_queued;
179 
180   /* Replacement variable for this access "region."  Never to be accessed
181      directly, always only by the means of get_access_replacement() and only
182      when grp_to_be_replaced flag is set.  */
183   tree replacement_decl;
184 
185   /* Is this access made in reverse storage order? */
186   unsigned reverse : 1;
187 
188   /* Is this particular access write access? */
189   unsigned write : 1;
190 
191   /* Is this access currently in the rhs work queue?  */
192   unsigned grp_rhs_queued : 1;
193 
194   /* Is this access currently in the lhs work queue?  */
195   unsigned grp_lhs_queued : 1;
196 
197   /* Does this group contain a write access?  This flag is propagated down the
198      access tree.  */
199   unsigned grp_write : 1;
200 
201   /* Does this group contain a read access?  This flag is propagated down the
202      access tree.  */
203   unsigned grp_read : 1;
204 
205   /* Does this group contain a read access that comes from an assignment
206      statement?  This flag is propagated down the access tree.  */
207   unsigned grp_assignment_read : 1;
208 
209   /* Does this group contain a write access that comes from an assignment
210      statement?  This flag is propagated down the access tree.  */
211   unsigned grp_assignment_write : 1;
212 
213   /* Does this group contain a read access through a scalar type?  This flag is
214      not propagated in the access tree in any direction.  */
215   unsigned grp_scalar_read : 1;
216 
217   /* Does this group contain a write access through a scalar type?  This flag
218      is not propagated in the access tree in any direction.  */
219   unsigned grp_scalar_write : 1;
220 
221   /* In a root of an access tree, true means that the entire tree should be
222      totally scalarized - that all scalar leafs should be scalarized and
223      non-root grp_total_scalarization accesses should be honored.  Otherwise,
224      non-root accesses with grp_total_scalarization should never get scalar
225      replacements.  */
226   unsigned grp_total_scalarization : 1;
227 
228   /* Other passes of the analysis use this bit to make function
229      analyze_access_subtree create scalar replacements for this group if
230      possible.  */
231   unsigned grp_hint : 1;
232 
233   /* Is the subtree rooted in this access fully covered by scalar
234      replacements?  */
235   unsigned grp_covered : 1;
236 
237   /* If set to true, this access and all below it in an access tree must not be
238      scalarized.  */
239   unsigned grp_unscalarizable_region : 1;
240 
241   /* Whether data have been written to parts of the aggregate covered by this
242      access which is not to be scalarized.  This flag is propagated up in the
243      access tree.  */
244   unsigned grp_unscalarized_data : 1;
245 
246   /* Set if all accesses in the group consist of the same chain of
247      COMPONENT_REFs and ARRAY_REFs.  */
248   unsigned grp_same_access_path : 1;
249 
250   /* Does this access and/or group contain a write access through a
251      BIT_FIELD_REF?  */
252   unsigned grp_partial_lhs : 1;
253 
254   /* Set when a scalar replacement should be created for this variable.  */
255   unsigned grp_to_be_replaced : 1;
256 
257   /* Set when we want a replacement for the sole purpose of having it in
258      generated debug statements.  */
259   unsigned grp_to_be_debug_replaced : 1;
260 
261   /* Should TREE_NO_WARNING of a replacement be set?  */
262   unsigned grp_no_warning : 1;
263 };
264 
265 typedef struct access *access_p;
266 
267 
268 /* Alloc pool for allocating access structures.  */
269 static object_allocator<struct access> access_pool ("SRA accesses");
270 
271 /* A structure linking lhs and rhs accesses from an aggregate assignment.  They
272    are used to propagate subaccesses from rhs to lhs and vice versa as long as
273    they don't conflict with what is already there.  In the RHS->LHS direction,
274    we also propagate grp_write flag to lazily mark that the access contains any
275    meaningful data.  */
276 struct assign_link
277 {
278   struct access *lacc, *racc;
279   struct assign_link *next_rhs, *next_lhs;
280 };
281 
282 /* Alloc pool for allocating assign link structures.  */
283 static object_allocator<assign_link> assign_link_pool ("SRA links");
284 
285 /* Base (tree) -> Vector (vec<access_p> *) map.  */
286 static hash_map<tree, auto_vec<access_p> > *base_access_vec;
287 
288 /* Hash to limit creation of artificial accesses */
289 static hash_map<tree, unsigned> *propagation_budget;
290 
291 /* Candidate hash table helpers.  */
292 
293 struct uid_decl_hasher : nofree_ptr_hash <tree_node>
294 {
295   static inline hashval_t hash (const tree_node *);
296   static inline bool equal (const tree_node *, const tree_node *);
297 };
298 
299 /* Hash a tree in a uid_decl_map.  */
300 
301 inline hashval_t
hash(const tree_node * item)302 uid_decl_hasher::hash (const tree_node *item)
303 {
304   return item->decl_minimal.uid;
305 }
306 
307 /* Return true if the DECL_UID in both trees are equal.  */
308 
309 inline bool
equal(const tree_node * a,const tree_node * b)310 uid_decl_hasher::equal (const tree_node *a, const tree_node *b)
311 {
312   return (a->decl_minimal.uid == b->decl_minimal.uid);
313 }
314 
315 /* Set of candidates.  */
316 static bitmap candidate_bitmap;
317 static hash_table<uid_decl_hasher> *candidates;
318 
319 /* For a candidate UID return the candidates decl.  */
320 
321 static inline tree
candidate(unsigned uid)322 candidate (unsigned uid)
323 {
324  tree_node t;
325  t.decl_minimal.uid = uid;
326  return candidates->find_with_hash (&t, static_cast <hashval_t> (uid));
327 }
328 
329 /* Bitmap of candidates which we should try to entirely scalarize away and
330    those which cannot be (because they are and need be used as a whole).  */
331 static bitmap should_scalarize_away_bitmap, cannot_scalarize_away_bitmap;
332 
333 /* Bitmap of candidates in the constant pool, which cannot be scalarized
334    because this would produce non-constant expressions (e.g. Ada).  */
335 static bitmap disqualified_constants;
336 
337 /* Obstack for creation of fancy names.  */
338 static struct obstack name_obstack;
339 
340 /* Head of a linked list of accesses that need to have its subaccesses
341    propagated to their assignment counterparts. */
342 static struct access *rhs_work_queue_head, *lhs_work_queue_head;
343 
344 /* Dump contents of ACCESS to file F in a human friendly way.  If GRP is true,
345    representative fields are dumped, otherwise those which only describe the
346    individual access are.  */
347 
348 static struct
349 {
350   /* Number of processed aggregates is readily available in
351      analyze_all_variable_accesses and so is not stored here.  */
352 
353   /* Number of created scalar replacements.  */
354   int replacements;
355 
356   /* Number of times sra_modify_expr or sra_modify_assign themselves changed an
357      expression.  */
358   int exprs;
359 
360   /* Number of statements created by generate_subtree_copies.  */
361   int subtree_copies;
362 
363   /* Number of statements created by load_assign_lhs_subreplacements.  */
364   int subreplacements;
365 
366   /* Number of times sra_modify_assign has deleted a statement.  */
367   int deleted;
368 
369   /* Number of times sra_modify_assign has to deal with subaccesses of LHS and
370      RHS reparately due to type conversions or nonexistent matching
371      references.  */
372   int separate_lhs_rhs_handling;
373 
374   /* Number of parameters that were removed because they were unused.  */
375   int deleted_unused_parameters;
376 
377   /* Number of scalars passed as parameters by reference that have been
378      converted to be passed by value.  */
379   int scalar_by_ref_to_by_val;
380 
381   /* Number of aggregate parameters that were replaced by one or more of their
382      components.  */
383   int aggregate_params_reduced;
384 
385   /* Numbber of components created when splitting aggregate parameters.  */
386   int param_reductions_created;
387 } sra_stats;
388 
389 static void
dump_access(FILE * f,struct access * access,bool grp)390 dump_access (FILE *f, struct access *access, bool grp)
391 {
392   fprintf (f, "access { ");
393   fprintf (f, "base = (%d)'", DECL_UID (access->base));
394   print_generic_expr (f, access->base);
395   fprintf (f, "', offset = " HOST_WIDE_INT_PRINT_DEC, access->offset);
396   fprintf (f, ", size = " HOST_WIDE_INT_PRINT_DEC, access->size);
397   fprintf (f, ", expr = ");
398   print_generic_expr (f, access->expr);
399   fprintf (f, ", type = ");
400   print_generic_expr (f, access->type);
401   fprintf (f, ", reverse = %d", access->reverse);
402   if (grp)
403     fprintf (f, ", grp_read = %d, grp_write = %d, grp_assignment_read = %d, "
404 	     "grp_assignment_write = %d, grp_scalar_read = %d, "
405 	     "grp_scalar_write = %d, grp_total_scalarization = %d, "
406 	     "grp_hint = %d, grp_covered = %d, "
407 	     "grp_unscalarizable_region = %d, grp_unscalarized_data = %d, "
408 	     "grp_same_access_path = %d, grp_partial_lhs = %d, "
409 	     "grp_to_be_replaced = %d, grp_to_be_debug_replaced = %d}\n",
410 	     access->grp_read, access->grp_write, access->grp_assignment_read,
411 	     access->grp_assignment_write, access->grp_scalar_read,
412 	     access->grp_scalar_write, access->grp_total_scalarization,
413 	     access->grp_hint, access->grp_covered,
414 	     access->grp_unscalarizable_region, access->grp_unscalarized_data,
415 	     access->grp_same_access_path, access->grp_partial_lhs,
416 	     access->grp_to_be_replaced, access->grp_to_be_debug_replaced);
417   else
418     fprintf (f, ", write = %d, grp_total_scalarization = %d, "
419 	     "grp_partial_lhs = %d}\n",
420 	     access->write, access->grp_total_scalarization,
421 	     access->grp_partial_lhs);
422 }
423 
424 /* Dump a subtree rooted in ACCESS to file F, indent by LEVEL.  */
425 
426 static void
dump_access_tree_1(FILE * f,struct access * access,int level)427 dump_access_tree_1 (FILE *f, struct access *access, int level)
428 {
429   do
430     {
431       int i;
432 
433       for (i = 0; i < level; i++)
434 	fputs ("* ", f);
435 
436       dump_access (f, access, true);
437 
438       if (access->first_child)
439 	dump_access_tree_1 (f, access->first_child, level + 1);
440 
441       access = access->next_sibling;
442     }
443   while (access);
444 }
445 
446 /* Dump all access trees for a variable, given the pointer to the first root in
447    ACCESS.  */
448 
449 static void
dump_access_tree(FILE * f,struct access * access)450 dump_access_tree (FILE *f, struct access *access)
451 {
452   for (; access; access = access->next_grp)
453     dump_access_tree_1 (f, access, 0);
454 }
455 
456 /* Return true iff ACC is non-NULL and has subaccesses.  */
457 
458 static inline bool
access_has_children_p(struct access * acc)459 access_has_children_p (struct access *acc)
460 {
461   return acc && acc->first_child;
462 }
463 
464 /* Return true iff ACC is (partly) covered by at least one replacement.  */
465 
466 static bool
access_has_replacements_p(struct access * acc)467 access_has_replacements_p (struct access *acc)
468 {
469   struct access *child;
470   if (acc->grp_to_be_replaced)
471     return true;
472   for (child = acc->first_child; child; child = child->next_sibling)
473     if (access_has_replacements_p (child))
474       return true;
475   return false;
476 }
477 
478 /* Return a vector of pointers to accesses for the variable given in BASE or
479    NULL if there is none.  */
480 
481 static vec<access_p> *
get_base_access_vector(tree base)482 get_base_access_vector (tree base)
483 {
484   return base_access_vec->get (base);
485 }
486 
487 /* Find an access with required OFFSET and SIZE in a subtree of accesses rooted
488    in ACCESS.  Return NULL if it cannot be found.  */
489 
490 static struct access *
find_access_in_subtree(struct access * access,HOST_WIDE_INT offset,HOST_WIDE_INT size)491 find_access_in_subtree (struct access *access, HOST_WIDE_INT offset,
492 			HOST_WIDE_INT size)
493 {
494   while (access && (access->offset != offset || access->size != size))
495     {
496       struct access *child = access->first_child;
497 
498       while (child && (child->offset + child->size <= offset))
499 	child = child->next_sibling;
500       access = child;
501     }
502 
503   /* Total scalarization does not replace single field structures with their
504      single field but rather creates an access for them underneath.  Look for
505      it.  */
506   if (access)
507     while (access->first_child
508 	   && access->first_child->offset == offset
509 	   && access->first_child->size == size)
510       access = access->first_child;
511 
512   return access;
513 }
514 
515 /* Return the first group representative for DECL or NULL if none exists.  */
516 
517 static struct access *
get_first_repr_for_decl(tree base)518 get_first_repr_for_decl (tree base)
519 {
520   vec<access_p> *access_vec;
521 
522   access_vec = get_base_access_vector (base);
523   if (!access_vec)
524     return NULL;
525 
526   return (*access_vec)[0];
527 }
528 
529 /* Find an access representative for the variable BASE and given OFFSET and
530    SIZE.  Requires that access trees have already been built.  Return NULL if
531    it cannot be found.  */
532 
533 static struct access *
get_var_base_offset_size_access(tree base,HOST_WIDE_INT offset,HOST_WIDE_INT size)534 get_var_base_offset_size_access (tree base, HOST_WIDE_INT offset,
535 				 HOST_WIDE_INT size)
536 {
537   struct access *access;
538 
539   access = get_first_repr_for_decl (base);
540   while (access && (access->offset + access->size <= offset))
541     access = access->next_grp;
542   if (!access)
543     return NULL;
544 
545   return find_access_in_subtree (access, offset, size);
546 }
547 
548 /* Add LINK to the linked list of assign links of RACC.  */
549 
550 static void
add_link_to_rhs(struct access * racc,struct assign_link * link)551 add_link_to_rhs (struct access *racc, struct assign_link *link)
552 {
553   gcc_assert (link->racc == racc);
554 
555   if (!racc->first_rhs_link)
556     {
557       gcc_assert (!racc->last_rhs_link);
558       racc->first_rhs_link = link;
559     }
560   else
561     racc->last_rhs_link->next_rhs = link;
562 
563   racc->last_rhs_link = link;
564   link->next_rhs = NULL;
565 }
566 
567 /* Add LINK to the linked list of lhs assign links of LACC.  */
568 
569 static void
add_link_to_lhs(struct access * lacc,struct assign_link * link)570 add_link_to_lhs (struct access *lacc, struct assign_link *link)
571 {
572   gcc_assert (link->lacc == lacc);
573 
574   if (!lacc->first_lhs_link)
575     {
576       gcc_assert (!lacc->last_lhs_link);
577       lacc->first_lhs_link = link;
578     }
579   else
580     lacc->last_lhs_link->next_lhs = link;
581 
582   lacc->last_lhs_link = link;
583   link->next_lhs = NULL;
584 }
585 
586 /* Move all link structures in their linked list in OLD_ACC to the linked list
587    in NEW_ACC.  */
588 static void
relink_to_new_repr(struct access * new_acc,struct access * old_acc)589 relink_to_new_repr (struct access *new_acc, struct access *old_acc)
590 {
591   if (old_acc->first_rhs_link)
592     {
593 
594       if (new_acc->first_rhs_link)
595 	{
596 	  gcc_assert (!new_acc->last_rhs_link->next_rhs);
597 	  gcc_assert (!old_acc->last_rhs_link
598 		      || !old_acc->last_rhs_link->next_rhs);
599 
600 	  new_acc->last_rhs_link->next_rhs = old_acc->first_rhs_link;
601 	  new_acc->last_rhs_link = old_acc->last_rhs_link;
602 	}
603       else
604 	{
605 	  gcc_assert (!new_acc->last_rhs_link);
606 
607 	  new_acc->first_rhs_link = old_acc->first_rhs_link;
608 	  new_acc->last_rhs_link = old_acc->last_rhs_link;
609 	}
610       old_acc->first_rhs_link = old_acc->last_rhs_link = NULL;
611     }
612   else
613     gcc_assert (!old_acc->last_rhs_link);
614 
615   if (old_acc->first_lhs_link)
616     {
617 
618       if (new_acc->first_lhs_link)
619 	{
620 	  gcc_assert (!new_acc->last_lhs_link->next_lhs);
621 	  gcc_assert (!old_acc->last_lhs_link
622 		      || !old_acc->last_lhs_link->next_lhs);
623 
624 	  new_acc->last_lhs_link->next_lhs = old_acc->first_lhs_link;
625 	  new_acc->last_lhs_link = old_acc->last_lhs_link;
626 	}
627       else
628 	{
629 	  gcc_assert (!new_acc->last_lhs_link);
630 
631 	  new_acc->first_lhs_link = old_acc->first_lhs_link;
632 	  new_acc->last_lhs_link = old_acc->last_lhs_link;
633 	}
634       old_acc->first_lhs_link = old_acc->last_lhs_link = NULL;
635     }
636   else
637     gcc_assert (!old_acc->last_lhs_link);
638 
639 }
640 
641 /* Add ACCESS to the work to queue for propagation of subaccesses from RHS to
642    LHS (which is actually a stack).  */
643 
644 static void
add_access_to_rhs_work_queue(struct access * access)645 add_access_to_rhs_work_queue (struct access *access)
646 {
647   if (access->first_rhs_link && !access->grp_rhs_queued)
648     {
649       gcc_assert (!access->next_rhs_queued);
650       access->next_rhs_queued = rhs_work_queue_head;
651       access->grp_rhs_queued = 1;
652       rhs_work_queue_head = access;
653     }
654 }
655 
656 /* Add ACCESS to the work to queue for propagation of subaccesses from LHS to
657    RHS (which is actually a stack).  */
658 
659 static void
add_access_to_lhs_work_queue(struct access * access)660 add_access_to_lhs_work_queue (struct access *access)
661 {
662   if (access->first_lhs_link && !access->grp_lhs_queued)
663     {
664       gcc_assert (!access->next_lhs_queued);
665       access->next_lhs_queued = lhs_work_queue_head;
666       access->grp_lhs_queued = 1;
667       lhs_work_queue_head = access;
668     }
669 }
670 
671 /* Pop an access from the work queue for propagating from RHS to LHS, and
672    return it, assuming there is one.  */
673 
674 static struct access *
pop_access_from_rhs_work_queue(void)675 pop_access_from_rhs_work_queue (void)
676 {
677   struct access *access = rhs_work_queue_head;
678 
679   rhs_work_queue_head = access->next_rhs_queued;
680   access->next_rhs_queued = NULL;
681   access->grp_rhs_queued = 0;
682   return access;
683 }
684 
685 /* Pop an access from the work queue for propagating from LHS to RHS, and
686    return it, assuming there is one.  */
687 
688 static struct access *
pop_access_from_lhs_work_queue(void)689 pop_access_from_lhs_work_queue (void)
690 {
691   struct access *access = lhs_work_queue_head;
692 
693   lhs_work_queue_head = access->next_lhs_queued;
694   access->next_lhs_queued = NULL;
695   access->grp_lhs_queued = 0;
696   return access;
697 }
698 
699 /* Allocate necessary structures.  */
700 
701 static void
sra_initialize(void)702 sra_initialize (void)
703 {
704   candidate_bitmap = BITMAP_ALLOC (NULL);
705   candidates = new hash_table<uid_decl_hasher>
706     (vec_safe_length (cfun->local_decls) / 2);
707   should_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
708   cannot_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
709   disqualified_constants = BITMAP_ALLOC (NULL);
710   gcc_obstack_init (&name_obstack);
711   base_access_vec = new hash_map<tree, auto_vec<access_p> >;
712   memset (&sra_stats, 0, sizeof (sra_stats));
713 }
714 
715 /* Deallocate all general structures.  */
716 
717 static void
sra_deinitialize(void)718 sra_deinitialize (void)
719 {
720   BITMAP_FREE (candidate_bitmap);
721   delete candidates;
722   candidates = NULL;
723   BITMAP_FREE (should_scalarize_away_bitmap);
724   BITMAP_FREE (cannot_scalarize_away_bitmap);
725   BITMAP_FREE (disqualified_constants);
726   access_pool.release ();
727   assign_link_pool.release ();
728   obstack_free (&name_obstack, NULL);
729 
730   delete base_access_vec;
731 }
732 
733 /* Return true if DECL is a VAR_DECL in the constant pool, false otherwise.  */
734 
constant_decl_p(tree decl)735 static bool constant_decl_p (tree decl)
736 {
737   return VAR_P (decl) && DECL_IN_CONSTANT_POOL (decl);
738 }
739 
740 /* Remove DECL from candidates for SRA and write REASON to the dump file if
741    there is one.  */
742 
743 static void
disqualify_candidate(tree decl,const char * reason)744 disqualify_candidate (tree decl, const char *reason)
745 {
746   if (bitmap_clear_bit (candidate_bitmap, DECL_UID (decl)))
747     candidates->remove_elt_with_hash (decl, DECL_UID (decl));
748   if (constant_decl_p (decl))
749     bitmap_set_bit (disqualified_constants, DECL_UID (decl));
750 
751   if (dump_file && (dump_flags & TDF_DETAILS))
752     {
753       fprintf (dump_file, "! Disqualifying ");
754       print_generic_expr (dump_file, decl);
755       fprintf (dump_file, " - %s\n", reason);
756     }
757 }
758 
759 /* Return true iff the type contains a field or an element which does not allow
760    scalarization.  Use VISITED_TYPES to avoid re-checking already checked
761    (sub-)types.  */
762 
763 static bool
type_internals_preclude_sra_p_1(tree type,const char ** msg,hash_set<tree> * visited_types)764 type_internals_preclude_sra_p_1 (tree type, const char **msg,
765 				 hash_set<tree> *visited_types)
766 {
767   tree fld;
768   tree et;
769 
770   if (visited_types->contains (type))
771     return false;
772   visited_types->add (type);
773 
774   switch (TREE_CODE (type))
775     {
776     case RECORD_TYPE:
777     case UNION_TYPE:
778     case QUAL_UNION_TYPE:
779       for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
780 	if (TREE_CODE (fld) == FIELD_DECL)
781 	  {
782 	    if (TREE_CODE (fld) == FUNCTION_DECL)
783 	      continue;
784 	    tree ft = TREE_TYPE (fld);
785 
786 	    if (TREE_THIS_VOLATILE (fld))
787 	      {
788 		*msg = "volatile structure field";
789 		return true;
790 	      }
791 	    if (!DECL_FIELD_OFFSET (fld))
792 	      {
793 		*msg = "no structure field offset";
794 		return true;
795 	      }
796 	    if (!DECL_SIZE (fld))
797 	      {
798 		*msg = "zero structure field size";
799 	        return true;
800 	      }
801 	    if (!tree_fits_uhwi_p (DECL_FIELD_OFFSET (fld)))
802 	      {
803 		*msg = "structure field offset not fixed";
804 		return true;
805 	      }
806 	    if (!tree_fits_uhwi_p (DECL_SIZE (fld)))
807 	      {
808 	        *msg = "structure field size not fixed";
809 		return true;
810 	      }
811 	    if (!tree_fits_shwi_p (bit_position (fld)))
812 	      {
813 	        *msg = "structure field size too big";
814 		return true;
815 	      }
816 	    if (AGGREGATE_TYPE_P (ft)
817 		    && int_bit_position (fld) % BITS_PER_UNIT != 0)
818 	      {
819 		*msg = "structure field is bit field";
820 	        return true;
821 	      }
822 
823 	    if (AGGREGATE_TYPE_P (ft)
824 	      && type_internals_preclude_sra_p_1 (ft, msg, visited_types))
825 	      return true;
826 	  }
827 
828       return false;
829 
830     case ARRAY_TYPE:
831       et = TREE_TYPE (type);
832 
833       if (TYPE_VOLATILE (et))
834 	{
835 	  *msg = "element type is volatile";
836 	  return true;
837 	}
838 
839       if (AGGREGATE_TYPE_P (et)
840 	  && type_internals_preclude_sra_p_1 (et, msg, visited_types))
841 	return true;
842 
843       return false;
844 
845     default:
846       return false;
847     }
848 }
849 
850 /* Return true iff the type contains a field or an element which does not allow
851    scalarization.  */
852 
853 bool
type_internals_preclude_sra_p(tree type,const char ** msg)854 type_internals_preclude_sra_p (tree type, const char **msg)
855 {
856   hash_set<tree> visited_types;
857   return type_internals_preclude_sra_p_1 (type, msg, &visited_types);
858 }
859 
860 
861 /* Allocate an access structure for BASE, OFFSET and SIZE, clear it, fill in
862    the three fields.  Also add it to the vector of accesses corresponding to
863    the base.  Finally, return the new access.  */
864 
865 static struct access *
create_access_1(tree base,HOST_WIDE_INT offset,HOST_WIDE_INT size)866 create_access_1 (tree base, HOST_WIDE_INT offset, HOST_WIDE_INT size)
867 {
868   struct access *access = access_pool.allocate ();
869 
870   memset (access, 0, sizeof (struct access));
871   access->base = base;
872   access->offset = offset;
873   access->size = size;
874 
875   base_access_vec->get_or_insert (base).safe_push (access);
876 
877   return access;
878 }
879 
880 static bool maybe_add_sra_candidate (tree);
881 
882 /* Create and insert access for EXPR. Return created access, or NULL if it is
883    not possible.  Also scan for uses of constant pool as we go along and add
884    to candidates.  */
885 
886 static struct access *
create_access(tree expr,gimple * stmt,bool write)887 create_access (tree expr, gimple *stmt, bool write)
888 {
889   struct access *access;
890   poly_int64 poffset, psize, pmax_size;
891   tree base = expr;
892   bool reverse, unscalarizable_region = false;
893 
894   base = get_ref_base_and_extent (expr, &poffset, &psize, &pmax_size,
895 				  &reverse);
896 
897   /* For constant-pool entries, check we can substitute the constant value.  */
898   if (constant_decl_p (base))
899     {
900       gcc_assert (!bitmap_bit_p (disqualified_constants, DECL_UID (base)));
901       if (expr != base
902 	  && !is_gimple_reg_type (TREE_TYPE (expr))
903 	  && dump_file && (dump_flags & TDF_DETAILS))
904 	{
905 	  /* This occurs in Ada with accesses to ARRAY_RANGE_REFs,
906 	     and elements of multidimensional arrays (which are
907 	     multi-element arrays in their own right).  */
908 	  fprintf (dump_file, "Allowing non-reg-type load of part"
909 			      " of constant-pool entry: ");
910 	  print_generic_expr (dump_file, expr);
911 	}
912       maybe_add_sra_candidate (base);
913     }
914 
915   if (!DECL_P (base) || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
916     return NULL;
917 
918   HOST_WIDE_INT offset, size, max_size;
919   if (!poffset.is_constant (&offset)
920       || !psize.is_constant (&size)
921       || !pmax_size.is_constant (&max_size))
922     {
923       disqualify_candidate (base, "Encountered a polynomial-sized access.");
924       return NULL;
925     }
926 
927   if (size != max_size)
928     {
929       size = max_size;
930       unscalarizable_region = true;
931     }
932   if (size == 0)
933     return NULL;
934   if (offset < 0)
935     {
936       disqualify_candidate (base, "Encountered a negative offset access.");
937       return NULL;
938     }
939   if (size < 0)
940     {
941       disqualify_candidate (base, "Encountered an unconstrained access.");
942       return NULL;
943     }
944   if (offset + size > tree_to_shwi (DECL_SIZE (base)))
945     {
946       disqualify_candidate (base, "Encountered an access beyond the base.");
947       return NULL;
948     }
949 
950   access = create_access_1 (base, offset, size);
951   access->expr = expr;
952   access->type = TREE_TYPE (expr);
953   access->write = write;
954   access->grp_unscalarizable_region = unscalarizable_region;
955   access->stmt = stmt;
956   access->reverse = reverse;
957 
958   return access;
959 }
960 
961 
962 /* Return true iff TYPE is scalarizable - i.e. a RECORD_TYPE or fixed-length
963    ARRAY_TYPE with fields that are either of gimple register types (excluding
964    bit-fields) or (recursively) scalarizable types.  CONST_DECL must be true if
965    we are considering a decl from constant pool.  If it is false, char arrays
966    will be refused.  */
967 
968 static bool
scalarizable_type_p(tree type,bool const_decl)969 scalarizable_type_p (tree type, bool const_decl)
970 {
971   if (is_gimple_reg_type (type))
972     return true;
973   if (type_contains_placeholder_p (type))
974     return false;
975 
976   bool have_predecessor_field = false;
977   HOST_WIDE_INT prev_pos = 0;
978 
979   switch (TREE_CODE (type))
980   {
981   case RECORD_TYPE:
982     for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
983       if (TREE_CODE (fld) == FIELD_DECL)
984 	{
985 	  tree ft = TREE_TYPE (fld);
986 
987 	  if (zerop (DECL_SIZE (fld)))
988 	    continue;
989 
990 	  HOST_WIDE_INT pos = int_bit_position (fld);
991 	  if (have_predecessor_field
992 	      && pos <= prev_pos)
993 	    return false;
994 
995 	  have_predecessor_field = true;
996 	  prev_pos = pos;
997 
998 	  if (DECL_BIT_FIELD (fld))
999 	    return false;
1000 
1001 	  if (!scalarizable_type_p (ft, const_decl))
1002 	    return false;
1003 	}
1004 
1005     return true;
1006 
1007   case ARRAY_TYPE:
1008     {
1009       HOST_WIDE_INT min_elem_size;
1010       if (const_decl)
1011 	min_elem_size = 0;
1012       else
1013 	min_elem_size = BITS_PER_UNIT;
1014 
1015       if (TYPE_DOMAIN (type) == NULL_TREE
1016 	  || !tree_fits_shwi_p (TYPE_SIZE (type))
1017 	  || !tree_fits_shwi_p (TYPE_SIZE (TREE_TYPE (type)))
1018 	  || (tree_to_shwi (TYPE_SIZE (TREE_TYPE (type))) <= min_elem_size)
1019 	  || !tree_fits_shwi_p (TYPE_MIN_VALUE (TYPE_DOMAIN (type))))
1020 	return false;
1021       if (tree_to_shwi (TYPE_SIZE (type)) == 0
1022 	  && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE)
1023 	/* Zero-element array, should not prevent scalarization.  */
1024 	;
1025       else if ((tree_to_shwi (TYPE_SIZE (type)) <= 0)
1026 	       || !tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
1027 	/* Variable-length array, do not allow scalarization.  */
1028 	return false;
1029 
1030       tree elem = TREE_TYPE (type);
1031       if (!scalarizable_type_p (elem, const_decl))
1032 	return false;
1033       return true;
1034     }
1035   default:
1036     return false;
1037   }
1038 }
1039 
1040 /* Return true if REF has an VIEW_CONVERT_EXPR somewhere in it.  */
1041 
1042 static inline bool
contains_view_convert_expr_p(const_tree ref)1043 contains_view_convert_expr_p (const_tree ref)
1044 {
1045   while (handled_component_p (ref))
1046     {
1047       if (TREE_CODE (ref) == VIEW_CONVERT_EXPR)
1048 	return true;
1049       ref = TREE_OPERAND (ref, 0);
1050     }
1051 
1052   return false;
1053 }
1054 
1055 /* Return true if REF contains a VIEW_CONVERT_EXPR or a COMPONENT_REF with a
1056    bit-field field declaration.  If TYPE_CHANGING_P is non-NULL, set the bool
1057    it points to will be set if REF contains any of the above or a MEM_REF
1058    expression that effectively performs type conversion.  */
1059 
1060 static bool
1061 contains_vce_or_bfcref_p (const_tree ref, bool *type_changing_p = NULL)
1062 {
1063   while (handled_component_p (ref))
1064     {
1065       if (TREE_CODE (ref) == VIEW_CONVERT_EXPR
1066 	  || (TREE_CODE (ref) == COMPONENT_REF
1067 	      && DECL_BIT_FIELD (TREE_OPERAND (ref, 1))))
1068 	{
1069 	  if (type_changing_p)
1070 	    *type_changing_p = true;
1071 	  return true;
1072 	}
1073       ref = TREE_OPERAND (ref, 0);
1074     }
1075 
1076   if (!type_changing_p
1077       || TREE_CODE (ref) != MEM_REF
1078       || TREE_CODE (TREE_OPERAND (ref, 0)) != ADDR_EXPR)
1079     return false;
1080 
1081   tree mem = TREE_OPERAND (TREE_OPERAND (ref, 0), 0);
1082   if (TYPE_MAIN_VARIANT (TREE_TYPE (ref))
1083       != TYPE_MAIN_VARIANT (TREE_TYPE (mem)))
1084     *type_changing_p = true;
1085 
1086   return false;
1087 }
1088 
1089 /* Search the given tree for a declaration by skipping handled components and
1090    exclude it from the candidates.  */
1091 
1092 static void
disqualify_base_of_expr(tree t,const char * reason)1093 disqualify_base_of_expr (tree t, const char *reason)
1094 {
1095   t = get_base_address (t);
1096   if (t && DECL_P (t))
1097     disqualify_candidate (t, reason);
1098 }
1099 
1100 /* Scan expression EXPR and create access structures for all accesses to
1101    candidates for scalarization.  Return the created access or NULL if none is
1102    created.  */
1103 
1104 static struct access *
build_access_from_expr_1(tree expr,gimple * stmt,bool write)1105 build_access_from_expr_1 (tree expr, gimple *stmt, bool write)
1106 {
1107   struct access *ret = NULL;
1108   bool partial_ref;
1109 
1110   if (TREE_CODE (expr) == BIT_FIELD_REF
1111       || TREE_CODE (expr) == IMAGPART_EXPR
1112       || TREE_CODE (expr) == REALPART_EXPR)
1113     {
1114       expr = TREE_OPERAND (expr, 0);
1115       partial_ref = true;
1116     }
1117   else
1118     partial_ref = false;
1119 
1120   if (storage_order_barrier_p (expr))
1121     {
1122       disqualify_base_of_expr (expr, "storage order barrier.");
1123       return NULL;
1124     }
1125 
1126   /* We need to dive through V_C_Es in order to get the size of its parameter
1127      and not the result type.  Ada produces such statements.  We are also
1128      capable of handling the topmost V_C_E but not any of those buried in other
1129      handled components.  */
1130   if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
1131     expr = TREE_OPERAND (expr, 0);
1132 
1133   if (contains_view_convert_expr_p (expr))
1134     {
1135       disqualify_base_of_expr (expr, "V_C_E under a different handled "
1136 			       "component.");
1137       return NULL;
1138     }
1139   if (TREE_THIS_VOLATILE (expr))
1140     {
1141       disqualify_base_of_expr (expr, "part of a volatile reference.");
1142       return NULL;
1143     }
1144 
1145   switch (TREE_CODE (expr))
1146     {
1147     case MEM_REF:
1148       if (TREE_CODE (TREE_OPERAND (expr, 0)) != ADDR_EXPR)
1149 	return NULL;
1150       /* fall through */
1151     case VAR_DECL:
1152     case PARM_DECL:
1153     case RESULT_DECL:
1154     case COMPONENT_REF:
1155     case ARRAY_REF:
1156     case ARRAY_RANGE_REF:
1157       ret = create_access (expr, stmt, write);
1158       break;
1159 
1160     default:
1161       break;
1162     }
1163 
1164   if (write && partial_ref && ret)
1165     ret->grp_partial_lhs = 1;
1166 
1167   return ret;
1168 }
1169 
1170 /* Scan expression EXPR and create access structures for all accesses to
1171    candidates for scalarization.  Return true if any access has been inserted.
1172    STMT must be the statement from which the expression is taken, WRITE must be
1173    true if the expression is a store and false otherwise. */
1174 
1175 static bool
build_access_from_expr(tree expr,gimple * stmt,bool write)1176 build_access_from_expr (tree expr, gimple *stmt, bool write)
1177 {
1178   struct access *access;
1179 
1180   access = build_access_from_expr_1 (expr, stmt, write);
1181   if (access)
1182     {
1183       /* This means the aggregate is accesses as a whole in a way other than an
1184 	 assign statement and thus cannot be removed even if we had a scalar
1185 	 replacement for everything.  */
1186       if (cannot_scalarize_away_bitmap)
1187 	bitmap_set_bit (cannot_scalarize_away_bitmap, DECL_UID (access->base));
1188       return true;
1189     }
1190   return false;
1191 }
1192 
1193 /* Return the single non-EH successor edge of BB or NULL if there is none or
1194    more than one.  */
1195 
1196 static edge
single_non_eh_succ(basic_block bb)1197 single_non_eh_succ (basic_block bb)
1198 {
1199   edge e, res = NULL;
1200   edge_iterator ei;
1201 
1202   FOR_EACH_EDGE (e, ei, bb->succs)
1203     if (!(e->flags & EDGE_EH))
1204       {
1205 	if (res)
1206 	  return NULL;
1207 	res = e;
1208       }
1209 
1210   return res;
1211 }
1212 
1213 /* Disqualify LHS and RHS for scalarization if STMT has to terminate its BB and
1214    there is no alternative spot where to put statements SRA might need to
1215    generate after it.  The spot we are looking for is an edge leading to a
1216    single non-EH successor, if it exists and is indeed single.  RHS may be
1217    NULL, in that case ignore it.  */
1218 
1219 static bool
disqualify_if_bad_bb_terminating_stmt(gimple * stmt,tree lhs,tree rhs)1220 disqualify_if_bad_bb_terminating_stmt (gimple *stmt, tree lhs, tree rhs)
1221 {
1222   if (stmt_ends_bb_p (stmt))
1223     {
1224       if (single_non_eh_succ (gimple_bb (stmt)))
1225 	return false;
1226 
1227       disqualify_base_of_expr (lhs, "LHS of a throwing stmt.");
1228       if (rhs)
1229 	disqualify_base_of_expr (rhs, "RHS of a throwing stmt.");
1230       return true;
1231     }
1232   return false;
1233 }
1234 
1235 /* Return true if the nature of BASE is such that it contains data even if
1236    there is no write to it in the function.  */
1237 
1238 static bool
comes_initialized_p(tree base)1239 comes_initialized_p (tree base)
1240 {
1241   return TREE_CODE (base) == PARM_DECL || constant_decl_p (base);
1242 }
1243 
1244 /* Scan expressions occurring in STMT, create access structures for all accesses
1245    to candidates for scalarization and remove those candidates which occur in
1246    statements or expressions that prevent them from being split apart.  Return
1247    true if any access has been inserted.  */
1248 
1249 static bool
build_accesses_from_assign(gimple * stmt)1250 build_accesses_from_assign (gimple *stmt)
1251 {
1252   tree lhs, rhs;
1253   struct access *lacc, *racc;
1254 
1255   if (!gimple_assign_single_p (stmt)
1256       /* Scope clobbers don't influence scalarization.  */
1257       || gimple_clobber_p (stmt))
1258     return false;
1259 
1260   lhs = gimple_assign_lhs (stmt);
1261   rhs = gimple_assign_rhs1 (stmt);
1262 
1263   if (disqualify_if_bad_bb_terminating_stmt (stmt, lhs, rhs))
1264     return false;
1265 
1266   racc = build_access_from_expr_1 (rhs, stmt, false);
1267   lacc = build_access_from_expr_1 (lhs, stmt, true);
1268 
1269   if (lacc)
1270     {
1271       lacc->grp_assignment_write = 1;
1272       if (storage_order_barrier_p (rhs))
1273 	lacc->grp_unscalarizable_region = 1;
1274 
1275       if (should_scalarize_away_bitmap && !is_gimple_reg_type (lacc->type))
1276 	{
1277 	  bool type_changing_p = false;
1278 	  contains_vce_or_bfcref_p (lhs, &type_changing_p);
1279 	  if (type_changing_p)
1280 	    bitmap_set_bit (cannot_scalarize_away_bitmap,
1281 			    DECL_UID (lacc->base));
1282 	}
1283     }
1284 
1285   if (racc)
1286     {
1287       racc->grp_assignment_read = 1;
1288       if (should_scalarize_away_bitmap && !is_gimple_reg_type (racc->type))
1289 	{
1290 	  bool type_changing_p = false;
1291 	  contains_vce_or_bfcref_p (rhs, &type_changing_p);
1292 
1293 	  if (type_changing_p || gimple_has_volatile_ops (stmt))
1294 	    bitmap_set_bit (cannot_scalarize_away_bitmap,
1295 			    DECL_UID (racc->base));
1296 	  else
1297 	    bitmap_set_bit (should_scalarize_away_bitmap,
1298 			    DECL_UID (racc->base));
1299 	}
1300       if (storage_order_barrier_p (lhs))
1301 	racc->grp_unscalarizable_region = 1;
1302     }
1303 
1304   if (lacc && racc
1305       && (sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
1306       && !lacc->grp_unscalarizable_region
1307       && !racc->grp_unscalarizable_region
1308       && AGGREGATE_TYPE_P (TREE_TYPE (lhs))
1309       && lacc->size == racc->size
1310       && useless_type_conversion_p (lacc->type, racc->type))
1311     {
1312       struct assign_link *link;
1313 
1314       link = assign_link_pool.allocate ();
1315       memset (link, 0, sizeof (struct assign_link));
1316 
1317       link->lacc = lacc;
1318       link->racc = racc;
1319       add_link_to_rhs (racc, link);
1320       add_link_to_lhs (lacc, link);
1321       add_access_to_rhs_work_queue (racc);
1322       add_access_to_lhs_work_queue (lacc);
1323 
1324       /* Let's delay marking the areas as written until propagation of accesses
1325 	 across link, unless the nature of rhs tells us that its data comes
1326 	 from elsewhere.  */
1327       if (!comes_initialized_p (racc->base))
1328 	lacc->write = false;
1329     }
1330 
1331   return lacc || racc;
1332 }
1333 
1334 /* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine
1335    GIMPLE_ASM operands with memory constrains which cannot be scalarized.  */
1336 
1337 static bool
asm_visit_addr(gimple *,tree op,tree,void *)1338 asm_visit_addr (gimple *, tree op, tree, void *)
1339 {
1340   op = get_base_address (op);
1341   if (op
1342       && DECL_P (op))
1343     disqualify_candidate (op, "Non-scalarizable GIMPLE_ASM operand.");
1344 
1345   return false;
1346 }
1347 
1348 /* Scan function and look for interesting expressions and create access
1349    structures for them.  Return true iff any access is created.  */
1350 
1351 static bool
scan_function(void)1352 scan_function (void)
1353 {
1354   basic_block bb;
1355   bool ret = false;
1356 
1357   FOR_EACH_BB_FN (bb, cfun)
1358     {
1359       gimple_stmt_iterator gsi;
1360       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1361 	{
1362 	  gimple *stmt = gsi_stmt (gsi);
1363 	  tree t;
1364 	  unsigned i;
1365 
1366 	  switch (gimple_code (stmt))
1367 	    {
1368 	    case GIMPLE_RETURN:
1369 	      t = gimple_return_retval (as_a <greturn *> (stmt));
1370 	      if (t != NULL_TREE)
1371 		ret |= build_access_from_expr (t, stmt, false);
1372 	      break;
1373 
1374 	    case GIMPLE_ASSIGN:
1375 	      ret |= build_accesses_from_assign (stmt);
1376 	      break;
1377 
1378 	    case GIMPLE_CALL:
1379 	      for (i = 0; i < gimple_call_num_args (stmt); i++)
1380 		ret |= build_access_from_expr (gimple_call_arg (stmt, i),
1381 					       stmt, false);
1382 
1383 	      t = gimple_call_lhs (stmt);
1384 	      if (t && !disqualify_if_bad_bb_terminating_stmt (stmt, t, NULL))
1385 		ret |= build_access_from_expr (t, stmt, true);
1386 	      break;
1387 
1388 	    case GIMPLE_ASM:
1389 	      {
1390 		gasm *asm_stmt = as_a <gasm *> (stmt);
1391 		walk_stmt_load_store_addr_ops (asm_stmt, NULL, NULL, NULL,
1392 					       asm_visit_addr);
1393 		for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
1394 		  {
1395 		    t = TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
1396 		    ret |= build_access_from_expr (t, asm_stmt, false);
1397 		  }
1398 		for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
1399 		  {
1400 		    t = TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
1401 		    ret |= build_access_from_expr (t, asm_stmt, true);
1402 		  }
1403 	      }
1404 	      break;
1405 
1406 	    default:
1407 	      break;
1408 	    }
1409 	}
1410     }
1411 
1412   return ret;
1413 }
1414 
1415 /* Helper of QSORT function. There are pointers to accesses in the array.  An
1416    access is considered smaller than another if it has smaller offset or if the
1417    offsets are the same but is size is bigger. */
1418 
1419 static int
compare_access_positions(const void * a,const void * b)1420 compare_access_positions (const void *a, const void *b)
1421 {
1422   const access_p *fp1 = (const access_p *) a;
1423   const access_p *fp2 = (const access_p *) b;
1424   const access_p f1 = *fp1;
1425   const access_p f2 = *fp2;
1426 
1427   if (f1->offset != f2->offset)
1428     return f1->offset < f2->offset ? -1 : 1;
1429 
1430   if (f1->size == f2->size)
1431     {
1432       if (f1->type == f2->type)
1433 	return 0;
1434       /* Put any non-aggregate type before any aggregate type.  */
1435       else if (!is_gimple_reg_type (f1->type)
1436 	  && is_gimple_reg_type (f2->type))
1437 	return 1;
1438       else if (is_gimple_reg_type (f1->type)
1439 	       && !is_gimple_reg_type (f2->type))
1440 	return -1;
1441       /* Put any complex or vector type before any other scalar type.  */
1442       else if (TREE_CODE (f1->type) != COMPLEX_TYPE
1443 	       && TREE_CODE (f1->type) != VECTOR_TYPE
1444 	       && (TREE_CODE (f2->type) == COMPLEX_TYPE
1445 		   || TREE_CODE (f2->type) == VECTOR_TYPE))
1446 	return 1;
1447       else if ((TREE_CODE (f1->type) == COMPLEX_TYPE
1448 		|| TREE_CODE (f1->type) == VECTOR_TYPE)
1449 	       && TREE_CODE (f2->type) != COMPLEX_TYPE
1450 	       && TREE_CODE (f2->type) != VECTOR_TYPE)
1451 	return -1;
1452       /* Put any integral type before any non-integral type.  When splicing, we
1453 	 make sure that those with insufficient precision and occupying the
1454 	 same space are not scalarized.  */
1455       else if (INTEGRAL_TYPE_P (f1->type)
1456 	       && !INTEGRAL_TYPE_P (f2->type))
1457 	return -1;
1458       else if (!INTEGRAL_TYPE_P (f1->type)
1459 	       && INTEGRAL_TYPE_P (f2->type))
1460 	return 1;
1461       /* Put the integral type with the bigger precision first.  */
1462       else if (INTEGRAL_TYPE_P (f1->type)
1463 	       && INTEGRAL_TYPE_P (f2->type)
1464 	       && (TYPE_PRECISION (f2->type) != TYPE_PRECISION (f1->type)))
1465 	return TYPE_PRECISION (f2->type) - TYPE_PRECISION (f1->type);
1466       /* Stabilize the sort.  */
1467       return TYPE_UID (f1->type) - TYPE_UID (f2->type);
1468     }
1469 
1470   /* We want the bigger accesses first, thus the opposite operator in the next
1471      line: */
1472   return f1->size > f2->size ? -1 : 1;
1473 }
1474 
1475 
1476 /* Append a name of the declaration to the name obstack.  A helper function for
1477    make_fancy_name.  */
1478 
1479 static void
make_fancy_decl_name(tree decl)1480 make_fancy_decl_name (tree decl)
1481 {
1482   char buffer[32];
1483 
1484   tree name = DECL_NAME (decl);
1485   if (name)
1486     obstack_grow (&name_obstack, IDENTIFIER_POINTER (name),
1487 		  IDENTIFIER_LENGTH (name));
1488   else
1489     {
1490       sprintf (buffer, "D%u", DECL_UID (decl));
1491       obstack_grow (&name_obstack, buffer, strlen (buffer));
1492     }
1493 }
1494 
1495 /* Helper for make_fancy_name.  */
1496 
1497 static void
make_fancy_name_1(tree expr)1498 make_fancy_name_1 (tree expr)
1499 {
1500   char buffer[32];
1501   tree index;
1502 
1503   if (DECL_P (expr))
1504     {
1505       make_fancy_decl_name (expr);
1506       return;
1507     }
1508 
1509   switch (TREE_CODE (expr))
1510     {
1511     case COMPONENT_REF:
1512       make_fancy_name_1 (TREE_OPERAND (expr, 0));
1513       obstack_1grow (&name_obstack, '$');
1514       make_fancy_decl_name (TREE_OPERAND (expr, 1));
1515       break;
1516 
1517     case ARRAY_REF:
1518       make_fancy_name_1 (TREE_OPERAND (expr, 0));
1519       obstack_1grow (&name_obstack, '$');
1520       /* Arrays with only one element may not have a constant as their
1521 	 index. */
1522       index = TREE_OPERAND (expr, 1);
1523       if (TREE_CODE (index) != INTEGER_CST)
1524 	break;
1525       sprintf (buffer, HOST_WIDE_INT_PRINT_DEC, TREE_INT_CST_LOW (index));
1526       obstack_grow (&name_obstack, buffer, strlen (buffer));
1527       break;
1528 
1529     case ADDR_EXPR:
1530       make_fancy_name_1 (TREE_OPERAND (expr, 0));
1531       break;
1532 
1533     case MEM_REF:
1534       make_fancy_name_1 (TREE_OPERAND (expr, 0));
1535       if (!integer_zerop (TREE_OPERAND (expr, 1)))
1536 	{
1537 	  obstack_1grow (&name_obstack, '$');
1538 	  sprintf (buffer, HOST_WIDE_INT_PRINT_DEC,
1539 		   TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)));
1540 	  obstack_grow (&name_obstack, buffer, strlen (buffer));
1541 	}
1542       break;
1543 
1544     case BIT_FIELD_REF:
1545     case REALPART_EXPR:
1546     case IMAGPART_EXPR:
1547       gcc_unreachable (); 	/* we treat these as scalars.  */
1548       break;
1549     default:
1550       break;
1551     }
1552 }
1553 
1554 /* Create a human readable name for replacement variable of ACCESS.  */
1555 
1556 static char *
make_fancy_name(tree expr)1557 make_fancy_name (tree expr)
1558 {
1559   make_fancy_name_1 (expr);
1560   obstack_1grow (&name_obstack, '\0');
1561   return XOBFINISH (&name_obstack, char *);
1562 }
1563 
1564 /* Construct a MEM_REF that would reference a part of aggregate BASE of type
1565    EXP_TYPE at the given OFFSET and with storage order REVERSE.  If BASE is
1566    something for which get_addr_base_and_unit_offset returns NULL, gsi must
1567    be non-NULL and is used to insert new statements either before or below
1568    the current one as specified by INSERT_AFTER.  This function is not capable
1569    of handling bitfields.  */
1570 
1571 tree
build_ref_for_offset(location_t loc,tree base,poly_int64 offset,bool reverse,tree exp_type,gimple_stmt_iterator * gsi,bool insert_after)1572 build_ref_for_offset (location_t loc, tree base, poly_int64 offset,
1573 		      bool reverse, tree exp_type, gimple_stmt_iterator *gsi,
1574 		      bool insert_after)
1575 {
1576   tree prev_base = base;
1577   tree off;
1578   tree mem_ref;
1579   poly_int64 base_offset;
1580   unsigned HOST_WIDE_INT misalign;
1581   unsigned int align;
1582 
1583   /* Preserve address-space information.  */
1584   addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (base));
1585   if (as != TYPE_ADDR_SPACE (exp_type))
1586     exp_type = build_qualified_type (exp_type,
1587 				     TYPE_QUALS (exp_type)
1588 				     | ENCODE_QUAL_ADDR_SPACE (as));
1589 
1590   poly_int64 byte_offset = exact_div (offset, BITS_PER_UNIT);
1591   get_object_alignment_1 (base, &align, &misalign);
1592   base = get_addr_base_and_unit_offset (base, &base_offset);
1593 
1594   /* get_addr_base_and_unit_offset returns NULL for references with a variable
1595      offset such as array[var_index].  */
1596   if (!base)
1597     {
1598       gassign *stmt;
1599       tree tmp, addr;
1600 
1601       gcc_checking_assert (gsi);
1602       tmp = make_ssa_name (build_pointer_type (TREE_TYPE (prev_base)));
1603       addr = build_fold_addr_expr (unshare_expr (prev_base));
1604       STRIP_USELESS_TYPE_CONVERSION (addr);
1605       stmt = gimple_build_assign (tmp, addr);
1606       gimple_set_location (stmt, loc);
1607       if (insert_after)
1608 	gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
1609       else
1610 	gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
1611 
1612       off = build_int_cst (reference_alias_ptr_type (prev_base), byte_offset);
1613       base = tmp;
1614     }
1615   else if (TREE_CODE (base) == MEM_REF)
1616     {
1617       off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
1618 			   base_offset + byte_offset);
1619       off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
1620       base = unshare_expr (TREE_OPERAND (base, 0));
1621     }
1622   else
1623     {
1624       off = build_int_cst (reference_alias_ptr_type (prev_base),
1625 			   base_offset + byte_offset);
1626       base = build_fold_addr_expr (unshare_expr (base));
1627     }
1628 
1629   unsigned int align_bound = known_alignment (misalign + offset);
1630   if (align_bound != 0)
1631     align = MIN (align, align_bound);
1632   if (align != TYPE_ALIGN (exp_type))
1633     exp_type = build_aligned_type (exp_type, align);
1634 
1635   mem_ref = fold_build2_loc (loc, MEM_REF, exp_type, base, off);
1636   REF_REVERSE_STORAGE_ORDER (mem_ref) = reverse;
1637   if (TREE_THIS_VOLATILE (prev_base))
1638     TREE_THIS_VOLATILE (mem_ref) = 1;
1639   if (TREE_SIDE_EFFECTS (prev_base))
1640     TREE_SIDE_EFFECTS (mem_ref) = 1;
1641   return mem_ref;
1642 }
1643 
1644 /* Construct and return a memory reference that is equal to a portion of
1645    MODEL->expr but is based on BASE.  If this cannot be done, return NULL.  */
1646 
1647 static tree
build_reconstructed_reference(location_t,tree base,struct access * model)1648 build_reconstructed_reference (location_t, tree base, struct access *model)
1649 {
1650   tree expr = model->expr, prev_expr = NULL;
1651   while (!types_compatible_p (TREE_TYPE (expr), TREE_TYPE (base)))
1652     {
1653       if (!handled_component_p (expr))
1654 	return NULL_TREE;
1655       prev_expr = expr;
1656       expr = TREE_OPERAND (expr, 0);
1657     }
1658 
1659   /* Guard against broken VIEW_CONVERT_EXPRs...  */
1660   if (!prev_expr)
1661     return NULL_TREE;
1662 
1663   TREE_OPERAND (prev_expr, 0) = base;
1664   tree ref = unshare_expr (model->expr);
1665   TREE_OPERAND (prev_expr, 0) = expr;
1666   return ref;
1667 }
1668 
1669 /* Construct a memory reference to a part of an aggregate BASE at the given
1670    OFFSET and of the same type as MODEL.  In case this is a reference to a
1671    bit-field, the function will replicate the last component_ref of model's
1672    expr to access it.  GSI and INSERT_AFTER have the same meaning as in
1673    build_ref_for_offset.  */
1674 
1675 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)1676 build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
1677 		     struct access *model, gimple_stmt_iterator *gsi,
1678 		     bool insert_after)
1679 {
1680   gcc_assert (offset >= 0);
1681   if (TREE_CODE (model->expr) == COMPONENT_REF
1682       && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
1683     {
1684       /* This access represents a bit-field.  */
1685       tree t, exp_type, fld = TREE_OPERAND (model->expr, 1);
1686 
1687       offset -= int_bit_position (fld);
1688       exp_type = TREE_TYPE (TREE_OPERAND (model->expr, 0));
1689       t = build_ref_for_offset (loc, base, offset, model->reverse, exp_type,
1690 				gsi, insert_after);
1691       /* The flag will be set on the record type.  */
1692       REF_REVERSE_STORAGE_ORDER (t) = 0;
1693       return fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (fld), t, fld,
1694 			      NULL_TREE);
1695     }
1696   else
1697     {
1698       tree res;
1699       if (model->grp_same_access_path
1700 	  && !TREE_THIS_VOLATILE (base)
1701 	  && (TYPE_ADDR_SPACE (TREE_TYPE (base))
1702 	      == TYPE_ADDR_SPACE (TREE_TYPE (model->expr)))
1703 	  && offset <= model->offset
1704 	  /* build_reconstructed_reference can still fail if we have already
1705 	     massaged BASE because of another type incompatibility.  */
1706 	  && (res = build_reconstructed_reference (loc, base, model)))
1707 	return res;
1708       else
1709 	return build_ref_for_offset (loc, base, offset, model->reverse,
1710 				     model->type, gsi, insert_after);
1711     }
1712 }
1713 
1714 /* Attempt to build a memory reference that we could but into a gimple
1715    debug_bind statement.  Similar to build_ref_for_model but punts if it has to
1716    create statements and return s NULL instead.  This function also ignores
1717    alignment issues and so its results should never end up in non-debug
1718    statements.  */
1719 
1720 static tree
build_debug_ref_for_model(location_t loc,tree base,HOST_WIDE_INT offset,struct access * model)1721 build_debug_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
1722 			   struct access *model)
1723 {
1724   poly_int64 base_offset;
1725   tree off;
1726 
1727   if (TREE_CODE (model->expr) == COMPONENT_REF
1728       && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
1729     return NULL_TREE;
1730 
1731   base = get_addr_base_and_unit_offset (base, &base_offset);
1732   if (!base)
1733     return NULL_TREE;
1734   if (TREE_CODE (base) == MEM_REF)
1735     {
1736       off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
1737 			   base_offset + offset / BITS_PER_UNIT);
1738       off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
1739       base = unshare_expr (TREE_OPERAND (base, 0));
1740     }
1741   else
1742     {
1743       off = build_int_cst (reference_alias_ptr_type (base),
1744 			   base_offset + offset / BITS_PER_UNIT);
1745       base = build_fold_addr_expr (unshare_expr (base));
1746     }
1747 
1748   return fold_build2_loc (loc, MEM_REF, model->type, base, off);
1749 }
1750 
1751 /* Construct a memory reference consisting of component_refs and array_refs to
1752    a part of an aggregate *RES (which is of type TYPE).  The requested part
1753    should have type EXP_TYPE at be the given OFFSET.  This function might not
1754    succeed, it returns true when it does and only then *RES points to something
1755    meaningful.  This function should be used only to build expressions that we
1756    might need to present to user (e.g. in warnings).  In all other situations,
1757    build_ref_for_model or build_ref_for_offset should be used instead.  */
1758 
1759 static bool
build_user_friendly_ref_for_offset(tree * res,tree type,HOST_WIDE_INT offset,tree exp_type)1760 build_user_friendly_ref_for_offset (tree *res, tree type, HOST_WIDE_INT offset,
1761 				    tree exp_type)
1762 {
1763   while (1)
1764     {
1765       tree fld;
1766       tree tr_size, index, minidx;
1767       HOST_WIDE_INT el_size;
1768 
1769       if (offset == 0 && exp_type
1770 	  && types_compatible_p (exp_type, type))
1771 	return true;
1772 
1773       switch (TREE_CODE (type))
1774 	{
1775 	case UNION_TYPE:
1776 	case QUAL_UNION_TYPE:
1777 	case RECORD_TYPE:
1778 	  for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
1779 	    {
1780 	      HOST_WIDE_INT pos, size;
1781 	      tree tr_pos, expr, *expr_ptr;
1782 
1783 	      if (TREE_CODE (fld) != FIELD_DECL)
1784 		continue;
1785 
1786 	      tr_pos = bit_position (fld);
1787 	      if (!tr_pos || !tree_fits_uhwi_p (tr_pos))
1788 		continue;
1789 	      pos = tree_to_uhwi (tr_pos);
1790 	      gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0);
1791 	      tr_size = DECL_SIZE (fld);
1792 	      if (!tr_size || !tree_fits_uhwi_p (tr_size))
1793 		continue;
1794 	      size = tree_to_uhwi (tr_size);
1795 	      if (size == 0)
1796 		{
1797 		  if (pos != offset)
1798 		    continue;
1799 		}
1800 	      else if (pos > offset || (pos + size) <= offset)
1801 		continue;
1802 
1803 	      expr = build3 (COMPONENT_REF, TREE_TYPE (fld), *res, fld,
1804 			     NULL_TREE);
1805 	      expr_ptr = &expr;
1806 	      if (build_user_friendly_ref_for_offset (expr_ptr, TREE_TYPE (fld),
1807 						      offset - pos, exp_type))
1808 		{
1809 		  *res = expr;
1810 		  return true;
1811 		}
1812 	    }
1813 	  return false;
1814 
1815 	case ARRAY_TYPE:
1816 	  tr_size = TYPE_SIZE (TREE_TYPE (type));
1817 	  if (!tr_size || !tree_fits_uhwi_p (tr_size))
1818 	    return false;
1819 	  el_size = tree_to_uhwi (tr_size);
1820 
1821 	  minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
1822 	  if (TREE_CODE (minidx) != INTEGER_CST || el_size == 0)
1823 	    return false;
1824 	  index = build_int_cst (TYPE_DOMAIN (type), offset / el_size);
1825 	  if (!integer_zerop (minidx))
1826 	    index = int_const_binop (PLUS_EXPR, index, minidx);
1827 	  *res = build4 (ARRAY_REF, TREE_TYPE (type), *res, index,
1828 			 NULL_TREE, NULL_TREE);
1829 	  offset = offset % el_size;
1830 	  type = TREE_TYPE (type);
1831 	  break;
1832 
1833 	default:
1834 	  if (offset != 0)
1835 	    return false;
1836 
1837 	  if (exp_type)
1838 	    return false;
1839 	  else
1840 	    return true;
1841 	}
1842     }
1843 }
1844 
1845 /* Print message to dump file why a variable was rejected. */
1846 
1847 static void
reject(tree var,const char * msg)1848 reject (tree var, const char *msg)
1849 {
1850   if (dump_file && (dump_flags & TDF_DETAILS))
1851     {
1852       fprintf (dump_file, "Rejected (%d): %s: ", DECL_UID (var), msg);
1853       print_generic_expr (dump_file, var);
1854       fprintf (dump_file, "\n");
1855     }
1856 }
1857 
1858 /* Return true if VAR is a candidate for SRA.  */
1859 
1860 static bool
maybe_add_sra_candidate(tree var)1861 maybe_add_sra_candidate (tree var)
1862 {
1863   tree type = TREE_TYPE (var);
1864   const char *msg;
1865   tree_node **slot;
1866 
1867   if (!AGGREGATE_TYPE_P (type))
1868     {
1869       reject (var, "not aggregate");
1870       return false;
1871     }
1872   /* Allow constant-pool entries that "need to live in memory".  */
1873   if (needs_to_live_in_memory (var) && !constant_decl_p (var))
1874     {
1875       reject (var, "needs to live in memory");
1876       return false;
1877     }
1878   if (TREE_THIS_VOLATILE (var))
1879     {
1880       reject (var, "is volatile");
1881       return false;
1882     }
1883   if (!COMPLETE_TYPE_P (type))
1884     {
1885       reject (var, "has incomplete type");
1886       return false;
1887     }
1888   if (!tree_fits_shwi_p (TYPE_SIZE (type)))
1889     {
1890       reject (var, "type size not fixed");
1891       return false;
1892     }
1893   if (tree_to_shwi (TYPE_SIZE (type)) == 0)
1894     {
1895       reject (var, "type size is zero");
1896       return false;
1897     }
1898   if (type_internals_preclude_sra_p (type, &msg))
1899     {
1900       reject (var, msg);
1901       return false;
1902     }
1903   if (/* Fix for PR 41089.  tree-stdarg.c needs to have va_lists intact but
1904 	 we also want to schedule it rather late.  Thus we ignore it in
1905 	 the early pass. */
1906       (sra_mode == SRA_MODE_EARLY_INTRA
1907        && is_va_list_type (type)))
1908     {
1909       reject (var, "is va_list");
1910       return false;
1911     }
1912 
1913   bitmap_set_bit (candidate_bitmap, DECL_UID (var));
1914   slot = candidates->find_slot_with_hash (var, DECL_UID (var), INSERT);
1915   *slot = var;
1916 
1917   if (dump_file && (dump_flags & TDF_DETAILS))
1918     {
1919       fprintf (dump_file, "Candidate (%d): ", DECL_UID (var));
1920       print_generic_expr (dump_file, var);
1921       fprintf (dump_file, "\n");
1922     }
1923 
1924   return true;
1925 }
1926 
1927 /* The very first phase of intraprocedural SRA.  It marks in candidate_bitmap
1928    those with type which is suitable for scalarization.  */
1929 
1930 static bool
find_var_candidates(void)1931 find_var_candidates (void)
1932 {
1933   tree var, parm;
1934   unsigned int i;
1935   bool ret = false;
1936 
1937   for (parm = DECL_ARGUMENTS (current_function_decl);
1938        parm;
1939        parm = DECL_CHAIN (parm))
1940     ret |= maybe_add_sra_candidate (parm);
1941 
1942   FOR_EACH_LOCAL_DECL (cfun, i, var)
1943     {
1944       if (!VAR_P (var))
1945         continue;
1946 
1947       ret |= maybe_add_sra_candidate (var);
1948     }
1949 
1950   return ret;
1951 }
1952 
1953 /* Return true if EXP is a reference chain of COMPONENT_REFs and AREAY_REFs
1954    ending either with a DECL or a MEM_REF with zero offset.  */
1955 
1956 static bool
path_comparable_for_same_access(tree expr)1957 path_comparable_for_same_access (tree expr)
1958 {
1959   while (handled_component_p (expr))
1960     {
1961       if (TREE_CODE (expr) == ARRAY_REF)
1962 	{
1963 	  /* SSA name indices can occur here too when the array is of sie one.
1964 	     But we cannot just re-use array_refs with SSA names elsewhere in
1965 	     the function, so disallow non-constant indices.  TODO: Remove this
1966 	     limitation after teaching build_reconstructed_reference to replace
1967 	     the index with the index type lower bound.  */
1968 	  if (TREE_CODE (TREE_OPERAND (expr, 1)) != INTEGER_CST)
1969 	    return false;
1970 	}
1971       expr = TREE_OPERAND (expr, 0);
1972     }
1973 
1974   if (TREE_CODE (expr) == MEM_REF)
1975     {
1976       if (!zerop (TREE_OPERAND (expr, 1)))
1977 	return false;
1978     }
1979   else
1980     gcc_assert (DECL_P (expr));
1981 
1982   return true;
1983 }
1984 
1985 /* Assuming that EXP1 consists of only COMPONENT_REFs and ARRAY_REFs, return
1986    true if the chain of these handled components are exactly the same as EXP2
1987    and the expression under them is the same DECL or an equivalent MEM_REF.
1988    The reference picked by compare_access_positions must go to EXP1.  */
1989 
1990 static bool
same_access_path_p(tree exp1,tree exp2)1991 same_access_path_p (tree exp1, tree exp2)
1992 {
1993   if (TREE_CODE (exp1) != TREE_CODE (exp2))
1994     {
1995       /* Special case single-field structures loaded sometimes as the field
1996 	 and sometimes as the structure.  If the field is of a scalar type,
1997 	 compare_access_positions will put it into exp1.
1998 
1999 	 TODO: The gimple register type condition can be removed if teach
2000 	 compare_access_positions to put inner types first.  */
2001       if (is_gimple_reg_type (TREE_TYPE (exp1))
2002 	  && TREE_CODE (exp1) == COMPONENT_REF
2003 	  && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (exp1, 0)))
2004 	      == TYPE_MAIN_VARIANT (TREE_TYPE (exp2))))
2005 	exp1 = TREE_OPERAND (exp1, 0);
2006       else
2007 	return false;
2008     }
2009 
2010   if (!operand_equal_p (exp1, exp2, OEP_ADDRESS_OF))
2011     return false;
2012 
2013   return true;
2014 }
2015 
2016 /* Sort all accesses for the given variable, check for partial overlaps and
2017    return NULL if there are any.  If there are none, pick a representative for
2018    each combination of offset and size and create a linked list out of them.
2019    Return the pointer to the first representative and make sure it is the first
2020    one in the vector of accesses.  */
2021 
2022 static struct access *
sort_and_splice_var_accesses(tree var)2023 sort_and_splice_var_accesses (tree var)
2024 {
2025   int i, j, access_count;
2026   struct access *res, **prev_acc_ptr = &res;
2027   vec<access_p> *access_vec;
2028   bool first = true;
2029   HOST_WIDE_INT low = -1, high = 0;
2030 
2031   access_vec = get_base_access_vector (var);
2032   if (!access_vec)
2033     return NULL;
2034   access_count = access_vec->length ();
2035 
2036   /* Sort by <OFFSET, SIZE>.  */
2037   access_vec->qsort (compare_access_positions);
2038 
2039   i = 0;
2040   while (i < access_count)
2041     {
2042       struct access *access = (*access_vec)[i];
2043       bool grp_write = access->write;
2044       bool grp_read = !access->write;
2045       bool grp_scalar_write = access->write
2046 	&& is_gimple_reg_type (access->type);
2047       bool grp_scalar_read = !access->write
2048 	&& is_gimple_reg_type (access->type);
2049       bool grp_assignment_read = access->grp_assignment_read;
2050       bool grp_assignment_write = access->grp_assignment_write;
2051       bool multiple_scalar_reads = false;
2052       bool grp_partial_lhs = access->grp_partial_lhs;
2053       bool first_scalar = is_gimple_reg_type (access->type);
2054       bool unscalarizable_region = access->grp_unscalarizable_region;
2055       bool grp_same_access_path = true;
2056       bool bf_non_full_precision
2057 	= (INTEGRAL_TYPE_P (access->type)
2058 	   && TYPE_PRECISION (access->type) != access->size
2059 	   && TREE_CODE (access->expr) == COMPONENT_REF
2060 	   && DECL_BIT_FIELD (TREE_OPERAND (access->expr, 1)));
2061 
2062       if (first || access->offset >= high)
2063 	{
2064 	  first = false;
2065 	  low = access->offset;
2066 	  high = access->offset + access->size;
2067 	}
2068       else if (access->offset > low && access->offset + access->size > high)
2069 	return NULL;
2070       else
2071 	gcc_assert (access->offset >= low
2072 		    && access->offset + access->size <= high);
2073 
2074       grp_same_access_path = path_comparable_for_same_access (access->expr);
2075 
2076       j = i + 1;
2077       while (j < access_count)
2078 	{
2079 	  struct access *ac2 = (*access_vec)[j];
2080 	  if (ac2->offset != access->offset || ac2->size != access->size)
2081 	    break;
2082 	  if (ac2->write)
2083 	    {
2084 	      grp_write = true;
2085 	      grp_scalar_write = (grp_scalar_write
2086 				  || is_gimple_reg_type (ac2->type));
2087 	    }
2088 	  else
2089 	    {
2090 	      grp_read = true;
2091 	      if (is_gimple_reg_type (ac2->type))
2092 		{
2093 		  if (grp_scalar_read)
2094 		    multiple_scalar_reads = true;
2095 		  else
2096 		    grp_scalar_read = true;
2097 		}
2098 	    }
2099 	  grp_assignment_read |= ac2->grp_assignment_read;
2100 	  grp_assignment_write |= ac2->grp_assignment_write;
2101 	  grp_partial_lhs |= ac2->grp_partial_lhs;
2102 	  unscalarizable_region |= ac2->grp_unscalarizable_region;
2103 	  relink_to_new_repr (access, ac2);
2104 
2105 	  /* If there are both aggregate-type and scalar-type accesses with
2106 	     this combination of size and offset, the comparison function
2107 	     should have put the scalars first.  */
2108 	  gcc_assert (first_scalar || !is_gimple_reg_type (ac2->type));
2109 	  /* It also prefers integral types to non-integral.  However, when the
2110 	     precision of the selected type does not span the entire area and
2111 	     should also be used for a non-integer (i.e. float), we must not
2112 	     let that happen.  Normally analyze_access_subtree expands the type
2113 	     to cover the entire area but for bit-fields it doesn't.  */
2114 	  if (bf_non_full_precision && !INTEGRAL_TYPE_P (ac2->type))
2115 	    {
2116 	      if (dump_file && (dump_flags & TDF_DETAILS))
2117 		{
2118 		  fprintf (dump_file, "Cannot scalarize the following access "
2119 			   "because insufficient precision integer type was "
2120 			   "selected.\n  ");
2121 		  dump_access (dump_file, access, false);
2122 		}
2123 	      unscalarizable_region = true;
2124 	    }
2125 
2126 	  if (grp_same_access_path
2127 	      && !same_access_path_p (access->expr, ac2->expr))
2128 	    grp_same_access_path = false;
2129 
2130 	  ac2->group_representative = access;
2131 	  j++;
2132 	}
2133 
2134       i = j;
2135 
2136       access->group_representative = access;
2137       access->grp_write = grp_write;
2138       access->grp_read = grp_read;
2139       access->grp_scalar_read = grp_scalar_read;
2140       access->grp_scalar_write = grp_scalar_write;
2141       access->grp_assignment_read = grp_assignment_read;
2142       access->grp_assignment_write = grp_assignment_write;
2143       access->grp_hint = multiple_scalar_reads && !constant_decl_p (var);
2144       access->grp_partial_lhs = grp_partial_lhs;
2145       access->grp_unscalarizable_region = unscalarizable_region;
2146       access->grp_same_access_path = grp_same_access_path;
2147 
2148       *prev_acc_ptr = access;
2149       prev_acc_ptr = &access->next_grp;
2150     }
2151 
2152   gcc_assert (res == (*access_vec)[0]);
2153   return res;
2154 }
2155 
2156 /* Create a variable for the given ACCESS which determines the type, name and a
2157    few other properties.  Return the variable declaration and store it also to
2158    ACCESS->replacement.  REG_TREE is used when creating a declaration to base a
2159    default-definition SSA name on in order to facilitate an uninitialized
2160    warning.  It is used instead of the actual ACCESS type if that is not of a
2161    gimple register type.  */
2162 
2163 static tree
2164 create_access_replacement (struct access *access, tree reg_type = NULL_TREE)
2165 {
2166   tree repl;
2167 
2168   tree type = access->type;
2169   if (reg_type && !is_gimple_reg_type (type))
2170     type = reg_type;
2171 
2172   if (access->grp_to_be_debug_replaced)
2173     {
2174       repl = create_tmp_var_raw (access->type);
2175       DECL_CONTEXT (repl) = current_function_decl;
2176     }
2177   else
2178     /* Drop any special alignment on the type if it's not on the main
2179        variant.  This avoids issues with weirdo ABIs like AAPCS.  */
2180     repl = create_tmp_var (build_qualified_type (TYPE_MAIN_VARIANT (type),
2181 						 TYPE_QUALS (type)), "SR");
2182   if (access->grp_partial_lhs
2183       && is_gimple_reg_type (type))
2184     DECL_NOT_GIMPLE_REG_P (repl) = 1;
2185 
2186   DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base);
2187   DECL_ARTIFICIAL (repl) = 1;
2188   DECL_IGNORED_P (repl) = DECL_IGNORED_P (access->base);
2189 
2190   if (DECL_NAME (access->base)
2191       && !DECL_IGNORED_P (access->base)
2192       && !DECL_ARTIFICIAL (access->base))
2193     {
2194       char *pretty_name = make_fancy_name (access->expr);
2195       tree debug_expr = unshare_expr_without_location (access->expr), d;
2196       bool fail = false;
2197 
2198       DECL_NAME (repl) = get_identifier (pretty_name);
2199       DECL_NAMELESS (repl) = 1;
2200       obstack_free (&name_obstack, pretty_name);
2201 
2202       /* Get rid of any SSA_NAMEs embedded in debug_expr,
2203 	 as DECL_DEBUG_EXPR isn't considered when looking for still
2204 	 used SSA_NAMEs and thus they could be freed.  All debug info
2205 	 generation cares is whether something is constant or variable
2206 	 and that get_ref_base_and_extent works properly on the
2207 	 expression.  It cannot handle accesses at a non-constant offset
2208 	 though, so just give up in those cases.  */
2209       for (d = debug_expr;
2210 	   !fail && (handled_component_p (d) || TREE_CODE (d) == MEM_REF);
2211 	   d = TREE_OPERAND (d, 0))
2212 	switch (TREE_CODE (d))
2213 	  {
2214 	  case ARRAY_REF:
2215 	  case ARRAY_RANGE_REF:
2216 	    if (TREE_OPERAND (d, 1)
2217 		&& TREE_CODE (TREE_OPERAND (d, 1)) != INTEGER_CST)
2218 	      fail = true;
2219 	    if (TREE_OPERAND (d, 3)
2220 		&& TREE_CODE (TREE_OPERAND (d, 3)) != INTEGER_CST)
2221 	      fail = true;
2222 	    /* FALLTHRU */
2223 	  case COMPONENT_REF:
2224 	    if (TREE_OPERAND (d, 2)
2225 		&& TREE_CODE (TREE_OPERAND (d, 2)) != INTEGER_CST)
2226 	      fail = true;
2227 	    break;
2228 	  case MEM_REF:
2229 	    if (TREE_CODE (TREE_OPERAND (d, 0)) != ADDR_EXPR)
2230 	      fail = true;
2231 	    else
2232 	      d = TREE_OPERAND (d, 0);
2233 	    break;
2234 	  default:
2235 	    break;
2236 	  }
2237       if (!fail)
2238 	{
2239 	  SET_DECL_DEBUG_EXPR (repl, debug_expr);
2240 	  DECL_HAS_DEBUG_EXPR_P (repl) = 1;
2241 	}
2242       if (access->grp_no_warning)
2243 	TREE_NO_WARNING (repl) = 1;
2244       else
2245 	TREE_NO_WARNING (repl) = TREE_NO_WARNING (access->base);
2246     }
2247   else
2248     TREE_NO_WARNING (repl) = 1;
2249 
2250   if (dump_file)
2251     {
2252       if (access->grp_to_be_debug_replaced)
2253 	{
2254 	  fprintf (dump_file, "Created a debug-only replacement for ");
2255 	  print_generic_expr (dump_file, access->base);
2256 	  fprintf (dump_file, " offset: %u, size: %u\n",
2257 		   (unsigned) access->offset, (unsigned) access->size);
2258 	}
2259       else
2260 	{
2261 	  fprintf (dump_file, "Created a replacement for ");
2262 	  print_generic_expr (dump_file, access->base);
2263 	  fprintf (dump_file, " offset: %u, size: %u: ",
2264 		   (unsigned) access->offset, (unsigned) access->size);
2265 	  print_generic_expr (dump_file, repl, TDF_UID);
2266 	  fprintf (dump_file, "\n");
2267 	}
2268     }
2269   sra_stats.replacements++;
2270 
2271   return repl;
2272 }
2273 
2274 /* Return ACCESS scalar replacement, which must exist.  */
2275 
2276 static inline tree
get_access_replacement(struct access * access)2277 get_access_replacement (struct access *access)
2278 {
2279   gcc_checking_assert (access->replacement_decl);
2280   return access->replacement_decl;
2281 }
2282 
2283 
2284 /* Build a subtree of accesses rooted in *ACCESS, and move the pointer in the
2285    linked list along the way.  Stop when *ACCESS is NULL or the access pointed
2286    to it is not "within" the root.  Return false iff some accesses partially
2287    overlap.  */
2288 
2289 static bool
build_access_subtree(struct access ** access)2290 build_access_subtree (struct access **access)
2291 {
2292   struct access *root = *access, *last_child = NULL;
2293   HOST_WIDE_INT limit = root->offset + root->size;
2294 
2295   *access = (*access)->next_grp;
2296   while  (*access && (*access)->offset + (*access)->size <= limit)
2297     {
2298       if (!last_child)
2299 	root->first_child = *access;
2300       else
2301 	last_child->next_sibling = *access;
2302       last_child = *access;
2303       (*access)->parent = root;
2304       (*access)->grp_write |= root->grp_write;
2305 
2306       if (!build_access_subtree (access))
2307 	return false;
2308     }
2309 
2310   if (*access && (*access)->offset < limit)
2311     return false;
2312 
2313   return true;
2314 }
2315 
2316 /* Build a tree of access representatives, ACCESS is the pointer to the first
2317    one, others are linked in a list by the next_grp field.  Return false iff
2318    some accesses partially overlap.  */
2319 
2320 static bool
build_access_trees(struct access * access)2321 build_access_trees (struct access *access)
2322 {
2323   while (access)
2324     {
2325       struct access *root = access;
2326 
2327       if (!build_access_subtree (&access))
2328 	return false;
2329       root->next_grp = access;
2330     }
2331   return true;
2332 }
2333 
2334 /* Traverse the access forest where ROOT is the first root and verify that
2335    various important invariants hold true.  */
2336 
2337 DEBUG_FUNCTION void
verify_sra_access_forest(struct access * root)2338 verify_sra_access_forest (struct access *root)
2339 {
2340   struct access *access = root;
2341   tree first_base = root->base;
2342   gcc_assert (DECL_P (first_base));
2343   do
2344     {
2345       gcc_assert (access->base == first_base);
2346       if (access->parent)
2347 	gcc_assert (access->offset >= access->parent->offset
2348 		    && access->size <= access->parent->size);
2349       if (access->next_sibling)
2350 	gcc_assert (access->next_sibling->offset
2351 		    >= access->offset + access->size);
2352 
2353       poly_int64 poffset, psize, pmax_size;
2354       bool reverse;
2355       tree base = get_ref_base_and_extent (access->expr, &poffset, &psize,
2356 					   &pmax_size, &reverse);
2357       HOST_WIDE_INT offset, size, max_size;
2358       if (!poffset.is_constant (&offset)
2359 	  || !psize.is_constant (&size)
2360 	  || !pmax_size.is_constant (&max_size))
2361 	gcc_unreachable ();
2362       gcc_assert (base == first_base);
2363       gcc_assert (offset == access->offset);
2364       gcc_assert (access->grp_unscalarizable_region
2365 		  || access->grp_total_scalarization
2366 		  || size == max_size);
2367       gcc_assert (access->grp_unscalarizable_region
2368 		  || !is_gimple_reg_type (access->type)
2369 		  || size == access->size);
2370       gcc_assert (reverse == access->reverse);
2371 
2372       if (access->first_child)
2373 	{
2374 	  gcc_assert (access->first_child->parent == access);
2375 	  access = access->first_child;
2376 	}
2377       else if (access->next_sibling)
2378 	{
2379 	  gcc_assert (access->next_sibling->parent == access->parent);
2380 	  access = access->next_sibling;
2381 	}
2382       else
2383 	{
2384 	  while (access->parent && !access->next_sibling)
2385 	    access = access->parent;
2386 	  if (access->next_sibling)
2387 	    access = access->next_sibling;
2388 	  else
2389 	    {
2390 	      gcc_assert (access == root);
2391 	      root = root->next_grp;
2392 	      access = root;
2393 	    }
2394 	}
2395     }
2396   while (access);
2397 }
2398 
2399 /* Verify access forests of all candidates with accesses by calling
2400    verify_access_forest on each on them.  */
2401 
2402 DEBUG_FUNCTION void
verify_all_sra_access_forests(void)2403 verify_all_sra_access_forests (void)
2404 {
2405   bitmap_iterator bi;
2406   unsigned i;
2407   EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
2408     {
2409       tree var = candidate (i);
2410       struct access *access = get_first_repr_for_decl (var);
2411       if (access)
2412 	{
2413 	  gcc_assert (access->base == var);
2414 	  verify_sra_access_forest (access);
2415 	}
2416     }
2417 }
2418 
2419 /* Return true if expr contains some ARRAY_REFs into a variable bounded
2420    array.  */
2421 
2422 static bool
expr_with_var_bounded_array_refs_p(tree expr)2423 expr_with_var_bounded_array_refs_p (tree expr)
2424 {
2425   while (handled_component_p (expr))
2426     {
2427       if (TREE_CODE (expr) == ARRAY_REF
2428 	  && !tree_fits_shwi_p (array_ref_low_bound (expr)))
2429 	return true;
2430       expr = TREE_OPERAND (expr, 0);
2431     }
2432   return false;
2433 }
2434 
2435 /* Analyze the subtree of accesses rooted in ROOT, scheduling replacements when
2436    both seeming beneficial and when ALLOW_REPLACEMENTS allows it.  If TOTALLY
2437    is set, we are totally scalarizing the aggregate.  Also set all sorts of
2438    access flags appropriately along the way, notably always set grp_read and
2439    grp_assign_read according to MARK_READ and grp_write when MARK_WRITE is
2440    true.
2441 
2442    Creating a replacement for a scalar access is considered beneficial if its
2443    grp_hint ot TOTALLY is set (this means either that there is more than one
2444    direct read access or that we are attempting total scalarization) or
2445    according to the following table:
2446 
2447    Access written to through a scalar type (once or more times)
2448    |
2449    |	Written to in an assignment statement
2450    |	|
2451    |	|	Access read as scalar _once_
2452    |	|	|
2453    |   	|	|	Read in an assignment statement
2454    |	|	|	|
2455    |   	|	|	|	Scalarize	Comment
2456 -----------------------------------------------------------------------------
2457    0	0	0	0			No access for the scalar
2458    0	0	0	1			No access for the scalar
2459    0	0	1	0	No		Single read - won't help
2460    0	0	1	1	No		The same case
2461    0	1	0	0			No access for the scalar
2462    0	1	0	1			No access for the scalar
2463    0	1	1	0	Yes		s = *g; return s.i;
2464    0	1	1	1       Yes		The same case as above
2465    1	0	0	0	No		Won't help
2466    1	0	0	1	Yes		s.i = 1; *g = s;
2467    1	0	1	0	Yes		s.i = 5; g = s.i;
2468    1	0	1	1	Yes		The same case as above
2469    1	1	0	0	No		Won't help.
2470    1	1	0	1	Yes		s.i = 1; *g = s;
2471    1	1	1	0	Yes		s = *g; return s.i;
2472    1	1	1	1	Yes		Any of the above yeses  */
2473 
2474 static bool
analyze_access_subtree(struct access * root,struct access * parent,bool allow_replacements,bool totally)2475 analyze_access_subtree (struct access *root, struct access *parent,
2476 			bool allow_replacements, bool totally)
2477 {
2478   struct access *child;
2479   HOST_WIDE_INT limit = root->offset + root->size;
2480   HOST_WIDE_INT covered_to = root->offset;
2481   bool scalar = is_gimple_reg_type (root->type);
2482   bool hole = false, sth_created = false;
2483 
2484   if (parent)
2485     {
2486       if (parent->grp_read)
2487 	root->grp_read = 1;
2488       if (parent->grp_assignment_read)
2489 	root->grp_assignment_read = 1;
2490       if (parent->grp_write)
2491 	root->grp_write = 1;
2492       if (parent->grp_assignment_write)
2493 	root->grp_assignment_write = 1;
2494       if (!parent->grp_same_access_path)
2495 	root->grp_same_access_path = 0;
2496     }
2497 
2498   if (root->grp_unscalarizable_region)
2499     allow_replacements = false;
2500 
2501   if (allow_replacements && expr_with_var_bounded_array_refs_p (root->expr))
2502     allow_replacements = false;
2503 
2504   for (child = root->first_child; child; child = child->next_sibling)
2505     {
2506       hole |= covered_to < child->offset;
2507       sth_created |= analyze_access_subtree (child, root,
2508 					     allow_replacements && !scalar,
2509 					     totally);
2510 
2511       root->grp_unscalarized_data |= child->grp_unscalarized_data;
2512       if (child->grp_covered)
2513 	covered_to += child->size;
2514       else
2515 	hole = true;
2516     }
2517 
2518   if (allow_replacements && scalar && !root->first_child
2519       && (totally || !root->grp_total_scalarization)
2520       && (totally
2521 	  || root->grp_hint
2522 	  || ((root->grp_scalar_read || root->grp_assignment_read)
2523 	      && (root->grp_scalar_write || root->grp_assignment_write))))
2524     {
2525       /* Always create access replacements that cover the whole access.
2526          For integral types this means the precision has to match.
2527 	 Avoid assumptions based on the integral type kind, too.  */
2528       if (INTEGRAL_TYPE_P (root->type)
2529 	  && (TREE_CODE (root->type) != INTEGER_TYPE
2530 	      || TYPE_PRECISION (root->type) != root->size)
2531 	  /* But leave bitfield accesses alone.  */
2532 	  && (TREE_CODE (root->expr) != COMPONENT_REF
2533 	      || !DECL_BIT_FIELD (TREE_OPERAND (root->expr, 1))))
2534 	{
2535 	  tree rt = root->type;
2536 	  gcc_assert ((root->offset % BITS_PER_UNIT) == 0
2537 		      && (root->size % BITS_PER_UNIT) == 0);
2538 	  root->type = build_nonstandard_integer_type (root->size,
2539 						       TYPE_UNSIGNED (rt));
2540 	  root->expr = build_ref_for_offset (UNKNOWN_LOCATION, root->base,
2541 					     root->offset, root->reverse,
2542 					     root->type, NULL, false);
2543 
2544 	  if (dump_file && (dump_flags & TDF_DETAILS))
2545 	    {
2546 	      fprintf (dump_file, "Changing the type of a replacement for ");
2547 	      print_generic_expr (dump_file, root->base);
2548 	      fprintf (dump_file, " offset: %u, size: %u ",
2549 		       (unsigned) root->offset, (unsigned) root->size);
2550 	      fprintf (dump_file, " to an integer.\n");
2551 	    }
2552 	}
2553 
2554       root->grp_to_be_replaced = 1;
2555       root->replacement_decl = create_access_replacement (root);
2556       sth_created = true;
2557       hole = false;
2558     }
2559   else
2560     {
2561       if (allow_replacements
2562 	  && scalar && !root->first_child
2563 	  && !root->grp_total_scalarization
2564 	  && (root->grp_scalar_write || root->grp_assignment_write)
2565 	  && !bitmap_bit_p (cannot_scalarize_away_bitmap,
2566 			    DECL_UID (root->base)))
2567 	{
2568 	  gcc_checking_assert (!root->grp_scalar_read
2569 			       && !root->grp_assignment_read);
2570 	  sth_created = true;
2571 	  if (MAY_HAVE_DEBUG_BIND_STMTS)
2572 	    {
2573 	      root->grp_to_be_debug_replaced = 1;
2574 	      root->replacement_decl = create_access_replacement (root);
2575 	    }
2576 	}
2577 
2578       if (covered_to < limit)
2579 	hole = true;
2580       if (scalar || !allow_replacements)
2581 	root->grp_total_scalarization = 0;
2582     }
2583 
2584   if (!hole || totally)
2585     root->grp_covered = 1;
2586   else if (root->grp_write || comes_initialized_p (root->base))
2587     root->grp_unscalarized_data = 1; /* not covered and written to */
2588   return sth_created;
2589 }
2590 
2591 /* Analyze all access trees linked by next_grp by the means of
2592    analyze_access_subtree.  */
2593 static bool
analyze_access_trees(struct access * access)2594 analyze_access_trees (struct access *access)
2595 {
2596   bool ret = false;
2597 
2598   while (access)
2599     {
2600       if (analyze_access_subtree (access, NULL, true,
2601 				  access->grp_total_scalarization))
2602 	ret = true;
2603       access = access->next_grp;
2604     }
2605 
2606   return ret;
2607 }
2608 
2609 /* Return true iff a potential new child of ACC at offset OFFSET and with size
2610    SIZE would conflict with an already existing one.  If exactly such a child
2611    already exists in ACC, store a pointer to it in EXACT_MATCH.  */
2612 
2613 static bool
child_would_conflict_in_acc(struct access * acc,HOST_WIDE_INT norm_offset,HOST_WIDE_INT size,struct access ** exact_match)2614 child_would_conflict_in_acc (struct access *acc, HOST_WIDE_INT norm_offset,
2615 			      HOST_WIDE_INT size, struct access **exact_match)
2616 {
2617   struct access *child;
2618 
2619   for (child = acc->first_child; child; child = child->next_sibling)
2620     {
2621       if (child->offset == norm_offset && child->size == size)
2622 	{
2623 	  *exact_match = child;
2624 	  return true;
2625 	}
2626 
2627       if (child->offset < norm_offset + size
2628 	  && child->offset + child->size > norm_offset)
2629 	return true;
2630     }
2631 
2632   return false;
2633 }
2634 
2635 /* Create a new child access of PARENT, with all properties just like MODEL
2636    except for its offset and with its grp_write false and grp_read true.
2637    Return the new access or NULL if it cannot be created.  Note that this
2638    access is created long after all splicing and sorting, it's not located in
2639    any access vector and is automatically a representative of its group.  Set
2640    the gpr_write flag of the new accesss if SET_GRP_WRITE is true.  */
2641 
2642 static struct access *
create_artificial_child_access(struct access * parent,struct access * model,HOST_WIDE_INT new_offset,bool set_grp_read,bool set_grp_write)2643 create_artificial_child_access (struct access *parent, struct access *model,
2644 				HOST_WIDE_INT new_offset,
2645 				bool set_grp_read, bool set_grp_write)
2646 {
2647   struct access **child;
2648   tree expr = parent->base;
2649 
2650   gcc_assert (!model->grp_unscalarizable_region);
2651 
2652   struct access *access = access_pool.allocate ();
2653   memset (access, 0, sizeof (struct access));
2654   if (!build_user_friendly_ref_for_offset (&expr, TREE_TYPE (expr), new_offset,
2655 					   model->type))
2656     {
2657       access->grp_no_warning = true;
2658       expr = build_ref_for_model (EXPR_LOCATION (parent->base), parent->base,
2659 				  new_offset, model, NULL, false);
2660     }
2661 
2662   access->base = parent->base;
2663   access->expr = expr;
2664   access->offset = new_offset;
2665   access->size = model->size;
2666   access->type = model->type;
2667   access->parent = parent;
2668   access->grp_read = set_grp_read;
2669   access->grp_write = set_grp_write;
2670   access->reverse = model->reverse;
2671 
2672   child = &parent->first_child;
2673   while (*child && (*child)->offset < new_offset)
2674     child = &(*child)->next_sibling;
2675 
2676   access->next_sibling = *child;
2677   *child = access;
2678 
2679   return access;
2680 }
2681 
2682 
2683 /* Beginning with ACCESS, traverse its whole access subtree and mark all
2684    sub-trees as written to.  If any of them has not been marked so previously
2685    and has assignment links leading from it, re-enqueue it.  */
2686 
2687 static void
subtree_mark_written_and_rhs_enqueue(struct access * access)2688 subtree_mark_written_and_rhs_enqueue (struct access *access)
2689 {
2690   if (access->grp_write)
2691     return;
2692   access->grp_write = true;
2693   add_access_to_rhs_work_queue (access);
2694 
2695   struct access *child;
2696   for (child = access->first_child; child; child = child->next_sibling)
2697     subtree_mark_written_and_rhs_enqueue (child);
2698 }
2699 
2700 /* If there is still budget to create a propagation access for DECL, return
2701    true and decrement the budget.  Otherwise return false.  */
2702 
2703 static bool
budget_for_propagation_access(tree decl)2704 budget_for_propagation_access (tree decl)
2705 {
2706   unsigned b, *p = propagation_budget->get (decl);
2707   if (p)
2708     b = *p;
2709   else
2710     b = param_sra_max_propagations;
2711 
2712   if (b == 0)
2713     return false;
2714   b--;
2715 
2716   if (b == 0 && dump_file && (dump_flags & TDF_DETAILS))
2717     {
2718       fprintf (dump_file, "The propagation budget of ");
2719       print_generic_expr (dump_file, decl);
2720       fprintf (dump_file, " (UID: %u) has been exhausted.\n", DECL_UID (decl));
2721     }
2722   propagation_budget->put (decl, b);
2723   return true;
2724 }
2725 
2726 /* Return true if ACC or any of its subaccesses has grp_child set.  */
2727 
2728 static bool
access_or_its_child_written(struct access * acc)2729 access_or_its_child_written (struct access *acc)
2730 {
2731   if (acc->grp_write)
2732     return true;
2733   for (struct access *sub = acc->first_child; sub; sub = sub->next_sibling)
2734     if (access_or_its_child_written (sub))
2735       return true;
2736   return false;
2737 }
2738 
2739 /* Propagate subaccesses and grp_write flags of RACC across an assignment link
2740    to LACC.  Enqueue sub-accesses as necessary so that the write flag is
2741    propagated transitively.  Return true if anything changed.  Additionally, if
2742    RACC is a scalar access but LACC is not, change the type of the latter, if
2743    possible.  */
2744 
2745 static bool
propagate_subaccesses_from_rhs(struct access * lacc,struct access * racc)2746 propagate_subaccesses_from_rhs (struct access *lacc, struct access *racc)
2747 {
2748   struct access *rchild;
2749   HOST_WIDE_INT norm_delta = lacc->offset - racc->offset;
2750   bool ret = false;
2751 
2752   /* IF the LHS is still not marked as being written to, we only need to do so
2753      if the RHS at this level actually was.  */
2754   if (!lacc->grp_write)
2755     {
2756       gcc_checking_assert (!comes_initialized_p (racc->base));
2757       if (racc->grp_write)
2758 	{
2759 	  subtree_mark_written_and_rhs_enqueue (lacc);
2760 	  ret = true;
2761 	}
2762     }
2763 
2764   if (is_gimple_reg_type (lacc->type)
2765       || lacc->grp_unscalarizable_region
2766       || racc->grp_unscalarizable_region)
2767     {
2768       if (!lacc->grp_write)
2769 	{
2770 	  ret = true;
2771 	  subtree_mark_written_and_rhs_enqueue (lacc);
2772 	}
2773       return ret;
2774     }
2775 
2776   if (is_gimple_reg_type (racc->type))
2777     {
2778       if (!lacc->grp_write)
2779 	{
2780 	  ret = true;
2781 	  subtree_mark_written_and_rhs_enqueue (lacc);
2782 	}
2783       if (!lacc->first_child && !racc->first_child)
2784 	{
2785 	  /* We are about to change the access type from aggregate to scalar,
2786 	     so we need to put the reverse flag onto the access, if any.  */
2787 	  const bool reverse = TYPE_REVERSE_STORAGE_ORDER (lacc->type);
2788 	  tree t = lacc->base;
2789 
2790 	  lacc->type = racc->type;
2791 	  if (build_user_friendly_ref_for_offset (&t, TREE_TYPE (t),
2792 						  lacc->offset, racc->type))
2793 	    {
2794 	      lacc->expr = t;
2795 	      lacc->grp_same_access_path = true;
2796 	    }
2797 	  else
2798 	    {
2799 	      lacc->expr = build_ref_for_model (EXPR_LOCATION (lacc->base),
2800 						lacc->base, lacc->offset,
2801 						racc, NULL, false);
2802 	      if (TREE_CODE (lacc->expr) == MEM_REF)
2803 		REF_REVERSE_STORAGE_ORDER (lacc->expr) = reverse;
2804 	      lacc->grp_no_warning = true;
2805 	      lacc->grp_same_access_path = false;
2806 	    }
2807 	  lacc->reverse = reverse;
2808 	}
2809       return ret;
2810     }
2811 
2812   for (rchild = racc->first_child; rchild; rchild = rchild->next_sibling)
2813     {
2814       struct access *new_acc = NULL;
2815       HOST_WIDE_INT norm_offset = rchild->offset + norm_delta;
2816 
2817       if (child_would_conflict_in_acc (lacc, norm_offset, rchild->size,
2818 					&new_acc))
2819 	{
2820 	  if (new_acc)
2821 	    {
2822 	      if (!new_acc->grp_write && rchild->grp_write)
2823 		{
2824 		  gcc_assert (!lacc->grp_write);
2825 		  subtree_mark_written_and_rhs_enqueue (new_acc);
2826 		  ret = true;
2827 		}
2828 
2829 	      rchild->grp_hint = 1;
2830 	      new_acc->grp_hint |= new_acc->grp_read;
2831 	      if (rchild->first_child
2832 		  && propagate_subaccesses_from_rhs (new_acc, rchild))
2833 		{
2834 		  ret = 1;
2835 		  add_access_to_rhs_work_queue (new_acc);
2836 		}
2837 	    }
2838 	  else
2839 	    {
2840 	      if (!lacc->grp_write)
2841 		{
2842 		  ret = true;
2843 		  subtree_mark_written_and_rhs_enqueue (lacc);
2844 		}
2845 	    }
2846 	  continue;
2847 	}
2848 
2849       if (rchild->grp_unscalarizable_region
2850 	  || !budget_for_propagation_access (lacc->base))
2851 	{
2852 	  if (!lacc->grp_write && access_or_its_child_written (rchild))
2853 	    {
2854 	      ret = true;
2855 	      subtree_mark_written_and_rhs_enqueue (lacc);
2856 	    }
2857 	  continue;
2858 	}
2859 
2860       rchild->grp_hint = 1;
2861       /* Because get_ref_base_and_extent always includes padding in size for
2862 	 accesses to DECLs but not necessarily for COMPONENT_REFs of the same
2863 	 type, we might be actually attempting to here to create a child of the
2864 	 same type as the parent.  */
2865       if (!types_compatible_p (lacc->type, rchild->type))
2866 	new_acc = create_artificial_child_access (lacc, rchild, norm_offset,
2867 						  false,
2868 						  (lacc->grp_write
2869 						   || rchild->grp_write));
2870       else
2871 	new_acc = lacc;
2872       gcc_checking_assert (new_acc);
2873       if (racc->first_child)
2874 	propagate_subaccesses_from_rhs (new_acc, rchild);
2875 
2876       add_access_to_rhs_work_queue (lacc);
2877       ret = true;
2878     }
2879 
2880   return ret;
2881 }
2882 
2883 /* Propagate subaccesses of LACC across an assignment link to RACC if they
2884    should inhibit total scalarization of the corresponding area.  No flags are
2885    being propagated in the process.  Return true if anything changed.  */
2886 
2887 static bool
propagate_subaccesses_from_lhs(struct access * lacc,struct access * racc)2888 propagate_subaccesses_from_lhs (struct access *lacc, struct access *racc)
2889 {
2890   if (is_gimple_reg_type (racc->type)
2891       || lacc->grp_unscalarizable_region
2892       || racc->grp_unscalarizable_region)
2893     return false;
2894 
2895   /* TODO: Do we want set some new racc flag to stop potential total
2896      scalarization if lacc is a scalar access (and none fo the two have
2897      children)?  */
2898 
2899   bool ret = false;
2900   HOST_WIDE_INT norm_delta = racc->offset - lacc->offset;
2901   for (struct access *lchild = lacc->first_child;
2902        lchild;
2903        lchild = lchild->next_sibling)
2904     {
2905       struct access *matching_acc = NULL;
2906       HOST_WIDE_INT norm_offset = lchild->offset + norm_delta;
2907 
2908       if (lchild->grp_unscalarizable_region
2909 	  || child_would_conflict_in_acc (racc, norm_offset, lchild->size,
2910 					  &matching_acc)
2911 	  || !budget_for_propagation_access (racc->base))
2912 	{
2913 	  if (matching_acc
2914 	      && propagate_subaccesses_from_lhs (lchild, matching_acc))
2915 	    add_access_to_lhs_work_queue (matching_acc);
2916 	  continue;
2917 	}
2918 
2919       /* Because get_ref_base_and_extent always includes padding in size for
2920 	 accesses to DECLs but not necessarily for COMPONENT_REFs of the same
2921 	 type, we might be actually attempting to here to create a child of the
2922 	 same type as the parent.  */
2923       if (!types_compatible_p (racc->type, lchild->type))
2924 	{
2925 	  struct access *new_acc
2926 	    = create_artificial_child_access (racc, lchild, norm_offset,
2927 					      true, false);
2928 	  propagate_subaccesses_from_lhs (lchild, new_acc);
2929 	}
2930       else
2931 	propagate_subaccesses_from_lhs (lchild, racc);
2932       ret = true;
2933     }
2934   return ret;
2935 }
2936 
2937 /* Propagate all subaccesses across assignment links.  */
2938 
2939 static void
propagate_all_subaccesses(void)2940 propagate_all_subaccesses (void)
2941 {
2942   propagation_budget = new hash_map<tree, unsigned>;
2943   while (rhs_work_queue_head)
2944     {
2945       struct access *racc = pop_access_from_rhs_work_queue ();
2946       struct assign_link *link;
2947 
2948       if (racc->group_representative)
2949 	racc= racc->group_representative;
2950       gcc_assert (racc->first_rhs_link);
2951 
2952       for (link = racc->first_rhs_link; link; link = link->next_rhs)
2953 	{
2954 	  struct access *lacc = link->lacc;
2955 
2956 	  if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
2957 	    continue;
2958 	  lacc = lacc->group_representative;
2959 
2960 	  bool reque_parents = false;
2961 	  if (!bitmap_bit_p (candidate_bitmap, DECL_UID (racc->base)))
2962 	    {
2963 	      if (!lacc->grp_write)
2964 		{
2965 		  subtree_mark_written_and_rhs_enqueue (lacc);
2966 		  reque_parents = true;
2967 		}
2968 	    }
2969 	  else if (propagate_subaccesses_from_rhs (lacc, racc))
2970 	    reque_parents = true;
2971 
2972 	  if (reque_parents)
2973 	    do
2974 	      {
2975 		add_access_to_rhs_work_queue (lacc);
2976 		lacc = lacc->parent;
2977 	      }
2978 	    while (lacc);
2979 	}
2980     }
2981 
2982   while (lhs_work_queue_head)
2983     {
2984       struct access *lacc = pop_access_from_lhs_work_queue ();
2985       struct assign_link *link;
2986 
2987       if (lacc->group_representative)
2988 	lacc = lacc->group_representative;
2989       gcc_assert (lacc->first_lhs_link);
2990 
2991       if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
2992 	continue;
2993 
2994       for (link = lacc->first_lhs_link; link; link = link->next_lhs)
2995 	{
2996 	  struct access *racc = link->racc;
2997 
2998 	  if (racc->group_representative)
2999 	    racc = racc->group_representative;
3000 	  if (!bitmap_bit_p (candidate_bitmap, DECL_UID (racc->base)))
3001 	    continue;
3002 	  if (propagate_subaccesses_from_lhs (lacc, racc))
3003 	    add_access_to_lhs_work_queue (racc);
3004 	}
3005     }
3006   delete propagation_budget;
3007 }
3008 
3009 /* Return true if the forest beginning with ROOT does not contain
3010    unscalarizable regions or non-byte aligned accesses.  */
3011 
3012 static bool
can_totally_scalarize_forest_p(struct access * root)3013 can_totally_scalarize_forest_p (struct access *root)
3014 {
3015   struct access *access = root;
3016   do
3017     {
3018       if (access->grp_unscalarizable_region
3019 	  || (access->offset % BITS_PER_UNIT) != 0
3020 	  || (access->size % BITS_PER_UNIT) != 0
3021 	  || (is_gimple_reg_type (access->type)
3022 	      && access->first_child))
3023 	return false;
3024 
3025       if (access->first_child)
3026 	access = access->first_child;
3027       else if (access->next_sibling)
3028 	access = access->next_sibling;
3029       else
3030 	{
3031 	  while (access->parent && !access->next_sibling)
3032 	    access = access->parent;
3033 	  if (access->next_sibling)
3034 	    access = access->next_sibling;
3035 	  else
3036 	    {
3037 	      gcc_assert (access == root);
3038 	      root = root->next_grp;
3039 	      access = root;
3040 	    }
3041 	}
3042     }
3043   while (access);
3044   return true;
3045 }
3046 
3047 /* Create and return an ACCESS in PARENT spanning from POS with SIZE, TYPE and
3048    reference EXPR for total scalarization purposes and mark it as such.  Within
3049    the children of PARENT, link it in between PTR and NEXT_SIBLING.  */
3050 
3051 static struct access *
create_total_scalarization_access(struct access * parent,HOST_WIDE_INT pos,HOST_WIDE_INT size,tree type,tree expr,struct access ** ptr,struct access * next_sibling)3052 create_total_scalarization_access (struct access *parent, HOST_WIDE_INT pos,
3053 				   HOST_WIDE_INT size, tree type, tree expr,
3054 				   struct access **ptr,
3055 				   struct access *next_sibling)
3056 {
3057   struct access *access = access_pool.allocate ();
3058   memset (access, 0, sizeof (struct access));
3059   access->base = parent->base;
3060   access->offset = pos;
3061   access->size = size;
3062   access->expr = expr;
3063   access->type = type;
3064   access->parent = parent;
3065   access->grp_write = parent->grp_write;
3066   access->grp_total_scalarization = 1;
3067   access->grp_hint = 1;
3068   access->grp_same_access_path = path_comparable_for_same_access (expr);
3069   access->reverse = reverse_storage_order_for_component_p (expr);
3070 
3071   access->next_sibling = next_sibling;
3072   *ptr = access;
3073   return access;
3074 }
3075 
3076 /* Create and return an ACCESS in PARENT spanning from POS with SIZE, TYPE and
3077    reference EXPR for total scalarization purposes and mark it as such, link it
3078    at *PTR and reshape the tree so that those elements at *PTR and their
3079    siblings which fall within the part described by POS and SIZE are moved to
3080    be children of the new access.  If a partial overlap is detected, return
3081    NULL.  */
3082 
3083 static struct access *
create_total_access_and_reshape(struct access * parent,HOST_WIDE_INT pos,HOST_WIDE_INT size,tree type,tree expr,struct access ** ptr)3084 create_total_access_and_reshape (struct access *parent, HOST_WIDE_INT pos,
3085 				 HOST_WIDE_INT size, tree type, tree expr,
3086 				 struct access **ptr)
3087 {
3088   struct access **p = ptr;
3089 
3090   while (*p && (*p)->offset < pos + size)
3091     {
3092       if ((*p)->offset + (*p)->size > pos + size)
3093 	return NULL;
3094       p = &(*p)->next_sibling;
3095     }
3096 
3097   struct access *next_child = *ptr;
3098   struct access *new_acc
3099     = create_total_scalarization_access (parent, pos, size, type, expr,
3100 					 ptr, *p);
3101   if (p != ptr)
3102     {
3103       new_acc->first_child = next_child;
3104       *p = NULL;
3105       for (struct access *a = next_child; a; a = a->next_sibling)
3106 	a->parent = new_acc;
3107     }
3108   return new_acc;
3109 }
3110 
3111 static bool totally_scalarize_subtree (struct access *root);
3112 
3113 /* Return true if INNER is either the same type as OUTER or if it is the type
3114    of a record field in OUTER at offset zero, possibly in nested
3115    sub-records.  */
3116 
3117 static bool
access_and_field_type_match_p(tree outer,tree inner)3118 access_and_field_type_match_p (tree outer, tree inner)
3119 {
3120   if (TYPE_MAIN_VARIANT (outer) == TYPE_MAIN_VARIANT (inner))
3121     return true;
3122   if (TREE_CODE (outer) != RECORD_TYPE)
3123     return false;
3124   tree fld = TYPE_FIELDS (outer);
3125   while (fld)
3126     {
3127      if (TREE_CODE (fld) == FIELD_DECL)
3128        {
3129 	if (!zerop (DECL_FIELD_OFFSET (fld)))
3130 	  return false;
3131 	if (TYPE_MAIN_VARIANT (TREE_TYPE (fld)) == inner)
3132 	  return true;
3133 	if (TREE_CODE (TREE_TYPE (fld)) == RECORD_TYPE)
3134 	  fld = TYPE_FIELDS (TREE_TYPE (fld));
3135 	else
3136 	  return false;
3137        }
3138      else
3139        fld = DECL_CHAIN (fld);
3140     }
3141   return false;
3142 }
3143 
3144 /* Return type of total_should_skip_creating_access indicating whether a total
3145    scalarization access for a field/element should be created, whether it
3146    already exists or whether the entire total scalarization has to fail.  */
3147 
3148 enum total_sra_field_state {TOTAL_FLD_CREATE, TOTAL_FLD_DONE, TOTAL_FLD_FAILED};
3149 
3150 /* Do all the necessary steps in total scalarization when the given aggregate
3151    type has a TYPE at POS with the given SIZE should be put into PARENT and
3152    when we have processed all its siblings with smaller offsets up until and
3153    including LAST_SEEN_SIBLING (which can be NULL).
3154 
3155    If some further siblings are to be skipped, set *LAST_SEEN_SIBLING as
3156    appropriate.  Return TOTAL_FLD_CREATE id the caller should carry on with
3157    creating a new access, TOTAL_FLD_DONE if access or accesses capable of
3158    representing the described part of the aggregate for the purposes of total
3159    scalarization already exist or TOTAL_FLD_FAILED if there is a problem which
3160    prevents total scalarization from happening at all.  */
3161 
3162 static enum total_sra_field_state
total_should_skip_creating_access(struct access * parent,struct access ** last_seen_sibling,tree type,HOST_WIDE_INT pos,HOST_WIDE_INT size)3163 total_should_skip_creating_access (struct access *parent,
3164 				   struct access **last_seen_sibling,
3165 				   tree type, HOST_WIDE_INT pos,
3166 				   HOST_WIDE_INT size)
3167 {
3168   struct access *next_child;
3169   if (!*last_seen_sibling)
3170     next_child = parent->first_child;
3171   else
3172     next_child = (*last_seen_sibling)->next_sibling;
3173 
3174   /* First, traverse the chain of siblings until it points to an access with
3175      offset at least equal to POS.  Check all skipped accesses whether they
3176      span the POS boundary and if so, return with a failure.  */
3177   while (next_child && next_child->offset < pos)
3178     {
3179       if (next_child->offset + next_child->size > pos)
3180 	return TOTAL_FLD_FAILED;
3181       *last_seen_sibling = next_child;
3182       next_child = next_child->next_sibling;
3183     }
3184 
3185   /* Now check whether next_child has exactly the right POS and SIZE and if so,
3186      whether it can represent what we need and can be totally scalarized
3187      itself.  */
3188   if (next_child && next_child->offset == pos
3189       && next_child->size == size)
3190     {
3191       if (!is_gimple_reg_type (next_child->type)
3192 	  && (!access_and_field_type_match_p (type, next_child->type)
3193 	      || !totally_scalarize_subtree (next_child)))
3194 	return TOTAL_FLD_FAILED;
3195 
3196       *last_seen_sibling = next_child;
3197       return TOTAL_FLD_DONE;
3198     }
3199 
3200   /* If the child we're looking at would partially overlap, we just cannot
3201      totally scalarize.  */
3202   if (next_child
3203       && next_child->offset < pos + size
3204       && next_child->offset + next_child->size > pos + size)
3205     return TOTAL_FLD_FAILED;
3206 
3207   if (is_gimple_reg_type (type))
3208     {
3209       /* We don't scalarize accesses that are children of other scalar type
3210 	 accesses, so if we go on and create an access for a register type,
3211 	 there should not be any pre-existing children.  There are rare cases
3212 	 where the requested type is a vector but we already have register
3213 	 accesses for all its elements which is equally good.  Detect that
3214 	 situation or whether we need to bail out.  */
3215 
3216       HOST_WIDE_INT covered = pos;
3217       bool skipping = false;
3218       while (next_child
3219 	     && next_child->offset + next_child->size <= pos + size)
3220 	{
3221 	  if (next_child->offset != covered
3222 	      || !is_gimple_reg_type (next_child->type))
3223 	    return TOTAL_FLD_FAILED;
3224 
3225 	  covered += next_child->size;
3226 	  *last_seen_sibling = next_child;
3227 	  next_child = next_child->next_sibling;
3228 	  skipping = true;
3229 	}
3230 
3231       if (skipping)
3232 	{
3233 	  if (covered != pos + size)
3234 	    return TOTAL_FLD_FAILED;
3235 	  else
3236 	    return TOTAL_FLD_DONE;
3237 	}
3238     }
3239 
3240   return TOTAL_FLD_CREATE;
3241 }
3242 
3243 /* Go over sub-tree rooted in ROOT and attempt to create scalar accesses
3244    spanning all uncovered areas covered by ROOT, return false if the attempt
3245    failed.  All created accesses will have grp_unscalarizable_region set (and
3246    should be ignored if the function returns false).  */
3247 
3248 static bool
totally_scalarize_subtree(struct access * root)3249 totally_scalarize_subtree (struct access *root)
3250 {
3251   gcc_checking_assert (!root->grp_unscalarizable_region);
3252   gcc_checking_assert (!is_gimple_reg_type (root->type));
3253 
3254   struct access *last_seen_sibling = NULL;
3255 
3256   switch (TREE_CODE (root->type))
3257     {
3258     case RECORD_TYPE:
3259       for (tree fld = TYPE_FIELDS (root->type); fld; fld = DECL_CHAIN (fld))
3260 	if (TREE_CODE (fld) == FIELD_DECL)
3261 	  {
3262 	    tree ft = TREE_TYPE (fld);
3263 	    HOST_WIDE_INT fsize = tree_to_uhwi (DECL_SIZE (fld));
3264 	    if (!fsize)
3265 	      continue;
3266 
3267 	    HOST_WIDE_INT pos = root->offset + int_bit_position (fld);
3268 	    enum total_sra_field_state
3269 	      state = total_should_skip_creating_access (root,
3270 							 &last_seen_sibling,
3271 							 ft, pos, fsize);
3272 	    switch (state)
3273 	      {
3274 	      case TOTAL_FLD_FAILED:
3275 		return false;
3276 	      case TOTAL_FLD_DONE:
3277 		continue;
3278 	      case TOTAL_FLD_CREATE:
3279 		break;
3280 	      default:
3281 		gcc_unreachable ();
3282 	      }
3283 
3284 	    struct access **p = (last_seen_sibling
3285 				 ? &last_seen_sibling->next_sibling
3286 				 : &root->first_child);
3287 	    tree nref = build3 (COMPONENT_REF, ft, root->expr, fld, NULL_TREE);
3288 	    struct access *new_child
3289 	      = create_total_access_and_reshape (root, pos, fsize, ft, nref, p);
3290 	    if (!new_child)
3291 	      return false;
3292 
3293 	    if (!is_gimple_reg_type (ft)
3294 		&& !totally_scalarize_subtree (new_child))
3295 	      return false;
3296 	    last_seen_sibling = new_child;
3297 	  }
3298       break;
3299     case ARRAY_TYPE:
3300       {
3301 	tree elemtype = TREE_TYPE (root->type);
3302 	tree elem_size = TYPE_SIZE (elemtype);
3303 	gcc_assert (elem_size && tree_fits_shwi_p (elem_size));
3304 	HOST_WIDE_INT el_size = tree_to_shwi (elem_size);
3305 	gcc_assert (el_size > 0);
3306 
3307 	tree minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (root->type));
3308 	gcc_assert (TREE_CODE (minidx) == INTEGER_CST);
3309 	tree maxidx = TYPE_MAX_VALUE (TYPE_DOMAIN (root->type));
3310 	/* Skip (some) zero-length arrays; others have MAXIDX == MINIDX - 1.  */
3311 	if (!maxidx)
3312 	  goto out;
3313 	gcc_assert (TREE_CODE (maxidx) == INTEGER_CST);
3314 	tree domain = TYPE_DOMAIN (root->type);
3315 	/* MINIDX and MAXIDX are inclusive, and must be interpreted in
3316 	   DOMAIN (e.g. signed int, whereas min/max may be size_int).  */
3317 	offset_int idx = wi::to_offset (minidx);
3318 	offset_int max = wi::to_offset (maxidx);
3319 	if (!TYPE_UNSIGNED (domain))
3320 	  {
3321 	    idx = wi::sext (idx, TYPE_PRECISION (domain));
3322 	    max = wi::sext (max, TYPE_PRECISION (domain));
3323 	  }
3324 	for (HOST_WIDE_INT pos = root->offset;
3325 	     idx <= max;
3326 	     pos += el_size, ++idx)
3327 	  {
3328 	    enum total_sra_field_state
3329 	      state = total_should_skip_creating_access (root,
3330 							 &last_seen_sibling,
3331 							 elemtype, pos,
3332 							 el_size);
3333 	    switch (state)
3334 	      {
3335 	      case TOTAL_FLD_FAILED:
3336 		return false;
3337 	      case TOTAL_FLD_DONE:
3338 		continue;
3339 	      case TOTAL_FLD_CREATE:
3340 		break;
3341 	      default:
3342 		gcc_unreachable ();
3343 	      }
3344 
3345 	    struct access **p = (last_seen_sibling
3346 				 ? &last_seen_sibling->next_sibling
3347 				 : &root->first_child);
3348 	    tree nref = build4 (ARRAY_REF, elemtype, root->expr,
3349 				wide_int_to_tree (domain, idx),
3350 				NULL_TREE, NULL_TREE);
3351 	    struct access *new_child
3352 	      = create_total_access_and_reshape (root, pos, el_size, elemtype,
3353 						 nref, p);
3354 	    if (!new_child)
3355 	      return false;
3356 
3357 	    if (!is_gimple_reg_type (elemtype)
3358 		&& !totally_scalarize_subtree (new_child))
3359 	      return false;
3360 	    last_seen_sibling = new_child;
3361 	  }
3362       }
3363       break;
3364     default:
3365       gcc_unreachable ();
3366     }
3367 
3368  out:
3369   return true;
3370 }
3371 
3372 /* Go through all accesses collected throughout the (intraprocedural) analysis
3373    stage, exclude overlapping ones, identify representatives and build trees
3374    out of them, making decisions about scalarization on the way.  Return true
3375    iff there are any to-be-scalarized variables after this stage. */
3376 
3377 static bool
analyze_all_variable_accesses(void)3378 analyze_all_variable_accesses (void)
3379 {
3380   int res = 0;
3381   bitmap tmp = BITMAP_ALLOC (NULL);
3382   bitmap_iterator bi;
3383   unsigned i;
3384 
3385   bitmap_copy (tmp, candidate_bitmap);
3386   EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
3387     {
3388       tree var = candidate (i);
3389       struct access *access;
3390 
3391       access = sort_and_splice_var_accesses (var);
3392       if (!access || !build_access_trees (access))
3393 	disqualify_candidate (var,
3394 			      "No or inhibitingly overlapping accesses.");
3395     }
3396 
3397   propagate_all_subaccesses ();
3398 
3399   bool optimize_speed_p = !optimize_function_for_size_p (cfun);
3400   /* If the user didn't set PARAM_SRA_MAX_SCALARIZATION_SIZE_<...>,
3401      fall back to a target default.  */
3402   unsigned HOST_WIDE_INT max_scalarization_size
3403     = get_move_ratio (optimize_speed_p) * UNITS_PER_WORD;
3404 
3405   if (optimize_speed_p)
3406     {
3407       if (global_options_set.x_param_sra_max_scalarization_size_speed)
3408 	max_scalarization_size = param_sra_max_scalarization_size_speed;
3409     }
3410   else
3411     {
3412       if (global_options_set.x_param_sra_max_scalarization_size_size)
3413 	max_scalarization_size = param_sra_max_scalarization_size_size;
3414     }
3415   max_scalarization_size *= BITS_PER_UNIT;
3416 
3417   EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
3418     if (bitmap_bit_p (should_scalarize_away_bitmap, i)
3419 	&& !bitmap_bit_p (cannot_scalarize_away_bitmap, i))
3420       {
3421 	tree var = candidate (i);
3422 	if (!VAR_P (var))
3423 	  continue;
3424 
3425 	if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (var))) > max_scalarization_size)
3426 	  {
3427 	    if (dump_file && (dump_flags & TDF_DETAILS))
3428 	      {
3429 		fprintf (dump_file, "Too big to totally scalarize: ");
3430 		print_generic_expr (dump_file, var);
3431 		fprintf (dump_file, " (UID: %u)\n", DECL_UID (var));
3432 	      }
3433 	    continue;
3434 	  }
3435 
3436 	bool all_types_ok = true;
3437 	for (struct access *access = get_first_repr_for_decl (var);
3438 	     access;
3439 	     access = access->next_grp)
3440 	  if (!can_totally_scalarize_forest_p (access)
3441 	      || !scalarizable_type_p (access->type, constant_decl_p (var)))
3442 	    {
3443 	      all_types_ok = false;
3444 	      break;
3445 	    }
3446 	if (!all_types_ok)
3447 	  continue;
3448 
3449 	if (dump_file && (dump_flags & TDF_DETAILS))
3450 	  {
3451 	    fprintf (dump_file, "Will attempt to totally scalarize ");
3452 	    print_generic_expr (dump_file, var);
3453 	    fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
3454 	  }
3455 	bool scalarized = true;
3456 	for (struct access *access = get_first_repr_for_decl (var);
3457 	     access;
3458 	     access = access->next_grp)
3459 	  if (!is_gimple_reg_type (access->type)
3460 	      && !totally_scalarize_subtree (access))
3461 	    {
3462 	      scalarized = false;
3463 	      break;
3464 	    }
3465 
3466 	if (scalarized)
3467 	  for (struct access *access = get_first_repr_for_decl (var);
3468 	       access;
3469 	       access = access->next_grp)
3470 	    access->grp_total_scalarization = true;
3471       }
3472 
3473   if (flag_checking)
3474     verify_all_sra_access_forests ();
3475 
3476   bitmap_copy (tmp, candidate_bitmap);
3477   EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
3478     {
3479       tree var = candidate (i);
3480       struct access *access = get_first_repr_for_decl (var);
3481 
3482       if (analyze_access_trees (access))
3483 	{
3484 	  res++;
3485 	  if (dump_file && (dump_flags & TDF_DETAILS))
3486 	    {
3487 	      fprintf (dump_file, "\nAccess trees for ");
3488 	      print_generic_expr (dump_file, var);
3489 	      fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
3490 	      dump_access_tree (dump_file, access);
3491 	      fprintf (dump_file, "\n");
3492 	    }
3493 	}
3494       else
3495 	disqualify_candidate (var, "No scalar replacements to be created.");
3496     }
3497 
3498   BITMAP_FREE (tmp);
3499 
3500   if (res)
3501     {
3502       statistics_counter_event (cfun, "Scalarized aggregates", res);
3503       return true;
3504     }
3505   else
3506     return false;
3507 }
3508 
3509 /* Generate statements copying scalar replacements of accesses within a subtree
3510    into or out of AGG.  ACCESS, all its children, siblings and their children
3511    are to be processed.  AGG is an aggregate type expression (can be a
3512    declaration but does not have to be, it can for example also be a mem_ref or
3513    a series of handled components).  TOP_OFFSET is the offset of the processed
3514    subtree which has to be subtracted from offsets of individual accesses to
3515    get corresponding offsets for AGG.  If CHUNK_SIZE is non-null, copy only
3516    replacements in the interval <start_offset, start_offset + chunk_size>,
3517    otherwise copy all.  GSI is a statement iterator used to place the new
3518    statements.  WRITE should be true when the statements should write from AGG
3519    to the replacement and false if vice versa.  if INSERT_AFTER is true, new
3520    statements will be added after the current statement in GSI, they will be
3521    added before the statement otherwise.  */
3522 
3523 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)3524 generate_subtree_copies (struct access *access, tree agg,
3525 			 HOST_WIDE_INT top_offset,
3526 			 HOST_WIDE_INT start_offset, HOST_WIDE_INT chunk_size,
3527 			 gimple_stmt_iterator *gsi, bool write,
3528 			 bool insert_after, location_t loc)
3529 {
3530   /* Never write anything into constant pool decls.  See PR70602.  */
3531   if (!write && constant_decl_p (agg))
3532     return;
3533   do
3534     {
3535       if (chunk_size && access->offset >= start_offset + chunk_size)
3536 	return;
3537 
3538       if (access->grp_to_be_replaced
3539 	  && (chunk_size == 0
3540 	      || access->offset + access->size > start_offset))
3541 	{
3542 	  tree expr, repl = get_access_replacement (access);
3543 	  gassign *stmt;
3544 
3545 	  expr = build_ref_for_model (loc, agg, access->offset - top_offset,
3546 				      access, gsi, insert_after);
3547 
3548 	  if (write)
3549 	    {
3550 	      if (access->grp_partial_lhs)
3551 		expr = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
3552 						 !insert_after,
3553 						 insert_after ? GSI_NEW_STMT
3554 						 : GSI_SAME_STMT);
3555 	      stmt = gimple_build_assign (repl, expr);
3556 	    }
3557 	  else
3558 	    {
3559 	      TREE_NO_WARNING (repl) = 1;
3560 	      if (access->grp_partial_lhs)
3561 		repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
3562 						 !insert_after,
3563 						 insert_after ? GSI_NEW_STMT
3564 						 : GSI_SAME_STMT);
3565 	      stmt = gimple_build_assign (expr, repl);
3566 	    }
3567 	  gimple_set_location (stmt, loc);
3568 
3569 	  if (insert_after)
3570 	    gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
3571 	  else
3572 	    gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3573 	  update_stmt (stmt);
3574 	  sra_stats.subtree_copies++;
3575 	}
3576       else if (write
3577 	       && access->grp_to_be_debug_replaced
3578 	       && (chunk_size == 0
3579 		   || access->offset + access->size > start_offset))
3580 	{
3581 	  gdebug *ds;
3582 	  tree drhs = build_debug_ref_for_model (loc, agg,
3583 						 access->offset - top_offset,
3584 						 access);
3585 	  ds = gimple_build_debug_bind (get_access_replacement (access),
3586 					drhs, gsi_stmt (*gsi));
3587 	  if (insert_after)
3588 	    gsi_insert_after (gsi, ds, GSI_NEW_STMT);
3589 	  else
3590 	    gsi_insert_before (gsi, ds, GSI_SAME_STMT);
3591 	}
3592 
3593       if (access->first_child)
3594 	generate_subtree_copies (access->first_child, agg, top_offset,
3595 				 start_offset, chunk_size, gsi,
3596 				 write, insert_after, loc);
3597 
3598       access = access->next_sibling;
3599     }
3600   while (access);
3601 }
3602 
3603 /* Assign zero to all scalar replacements in an access subtree.  ACCESS is the
3604    root of the subtree to be processed.  GSI is the statement iterator used
3605    for inserting statements which are added after the current statement if
3606    INSERT_AFTER is true or before it otherwise.  */
3607 
3608 static void
init_subtree_with_zero(struct access * access,gimple_stmt_iterator * gsi,bool insert_after,location_t loc)3609 init_subtree_with_zero (struct access *access, gimple_stmt_iterator *gsi,
3610 			bool insert_after, location_t loc)
3611 
3612 {
3613   struct access *child;
3614 
3615   if (access->grp_to_be_replaced)
3616     {
3617       gassign *stmt;
3618 
3619       stmt = gimple_build_assign (get_access_replacement (access),
3620 				  build_zero_cst (access->type));
3621       if (insert_after)
3622 	gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
3623       else
3624 	gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3625       update_stmt (stmt);
3626       gimple_set_location (stmt, loc);
3627     }
3628   else if (access->grp_to_be_debug_replaced)
3629     {
3630       gdebug *ds
3631 	= gimple_build_debug_bind (get_access_replacement (access),
3632 				   build_zero_cst (access->type),
3633 				   gsi_stmt (*gsi));
3634       if (insert_after)
3635 	gsi_insert_after (gsi, ds, GSI_NEW_STMT);
3636       else
3637 	gsi_insert_before (gsi, ds, GSI_SAME_STMT);
3638     }
3639 
3640   for (child = access->first_child; child; child = child->next_sibling)
3641     init_subtree_with_zero (child, gsi, insert_after, loc);
3642 }
3643 
3644 /* Clobber all scalar replacements in an access subtree.  ACCESS is the
3645    root of the subtree to be processed.  GSI is the statement iterator used
3646    for inserting statements which are added after the current statement if
3647    INSERT_AFTER is true or before it otherwise.  */
3648 
3649 static void
clobber_subtree(struct access * access,gimple_stmt_iterator * gsi,bool insert_after,location_t loc)3650 clobber_subtree (struct access *access, gimple_stmt_iterator *gsi,
3651 		bool insert_after, location_t loc)
3652 
3653 {
3654   struct access *child;
3655 
3656   if (access->grp_to_be_replaced)
3657     {
3658       tree rep = get_access_replacement (access);
3659       tree clobber = build_clobber (access->type);
3660       gimple *stmt = gimple_build_assign (rep, clobber);
3661 
3662       if (insert_after)
3663 	gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
3664       else
3665 	gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3666       update_stmt (stmt);
3667       gimple_set_location (stmt, loc);
3668     }
3669 
3670   for (child = access->first_child; child; child = child->next_sibling)
3671     clobber_subtree (child, gsi, insert_after, loc);
3672 }
3673 
3674 /* Search for an access representative for the given expression EXPR and
3675    return it or NULL if it cannot be found.  */
3676 
3677 static struct access *
get_access_for_expr(tree expr)3678 get_access_for_expr (tree expr)
3679 {
3680   poly_int64 poffset, psize, pmax_size;
3681   HOST_WIDE_INT offset, max_size;
3682   tree base;
3683   bool reverse;
3684 
3685   /* FIXME: This should not be necessary but Ada produces V_C_Es with a type of
3686      a different size than the size of its argument and we need the latter
3687      one.  */
3688   if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
3689     expr = TREE_OPERAND (expr, 0);
3690 
3691   base = get_ref_base_and_extent (expr, &poffset, &psize, &pmax_size,
3692 				  &reverse);
3693   if (!known_size_p (pmax_size)
3694       || !pmax_size.is_constant (&max_size)
3695       || !poffset.is_constant (&offset)
3696       || !DECL_P (base))
3697     return NULL;
3698 
3699   if (tree basesize = DECL_SIZE (base))
3700     {
3701       poly_int64 sz;
3702       if (offset < 0
3703 	  || !poly_int_tree_p (basesize, &sz)
3704 	  || known_le (sz, offset))
3705 	return NULL;
3706     }
3707 
3708   if (max_size == 0
3709       || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
3710     return NULL;
3711 
3712   return get_var_base_offset_size_access (base, offset, max_size);
3713 }
3714 
3715 /* Replace the expression EXPR with a scalar replacement if there is one and
3716    generate other statements to do type conversion or subtree copying if
3717    necessary.  GSI is used to place newly created statements, WRITE is true if
3718    the expression is being written to (it is on a LHS of a statement or output
3719    in an assembly statement).  */
3720 
3721 static bool
sra_modify_expr(tree * expr,gimple_stmt_iterator * gsi,bool write)3722 sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
3723 {
3724   location_t loc;
3725   struct access *access;
3726   tree type, bfr, orig_expr;
3727   bool partial_cplx_access = false;
3728 
3729   if (TREE_CODE (*expr) == BIT_FIELD_REF)
3730     {
3731       bfr = *expr;
3732       expr = &TREE_OPERAND (*expr, 0);
3733     }
3734   else
3735     bfr = NULL_TREE;
3736 
3737   if (TREE_CODE (*expr) == REALPART_EXPR || TREE_CODE (*expr) == IMAGPART_EXPR)
3738     {
3739       expr = &TREE_OPERAND (*expr, 0);
3740       partial_cplx_access = true;
3741     }
3742   access = get_access_for_expr (*expr);
3743   if (!access)
3744     return false;
3745   type = TREE_TYPE (*expr);
3746   orig_expr = *expr;
3747 
3748   loc = gimple_location (gsi_stmt (*gsi));
3749   gimple_stmt_iterator alt_gsi = gsi_none ();
3750   if (write && stmt_ends_bb_p (gsi_stmt (*gsi)))
3751     {
3752       alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi)));
3753       gsi = &alt_gsi;
3754     }
3755 
3756   if (access->grp_to_be_replaced)
3757     {
3758       tree repl = get_access_replacement (access);
3759       /* If we replace a non-register typed access simply use the original
3760          access expression to extract the scalar component afterwards.
3761 	 This happens if scalarizing a function return value or parameter
3762 	 like in gcc.c-torture/execute/20041124-1.c, 20050316-1.c and
3763 	 gcc.c-torture/compile/20011217-1.c.
3764 
3765          We also want to use this when accessing a complex or vector which can
3766          be accessed as a different type too, potentially creating a need for
3767          type conversion (see PR42196) and when scalarized unions are involved
3768          in assembler statements (see PR42398).  */
3769       if (!bfr && !useless_type_conversion_p (type, access->type))
3770 	{
3771 	  tree ref;
3772 
3773 	  ref = build_ref_for_model (loc, orig_expr, 0, access, gsi, false);
3774 
3775 	  if (partial_cplx_access)
3776 	    {
3777 	    /* VIEW_CONVERT_EXPRs in partial complex access are always fine in
3778 	       the case of a write because in such case the replacement cannot
3779 	       be a gimple register.  In the case of a load, we have to
3780 	       differentiate in between a register an non-register
3781 	       replacement.  */
3782 	      tree t = build1 (VIEW_CONVERT_EXPR, type, repl);
3783 	      gcc_checking_assert (!write || access->grp_partial_lhs);
3784 	      if (!access->grp_partial_lhs)
3785 		{
3786 		  tree tmp = make_ssa_name (type);
3787 		  gassign *stmt = gimple_build_assign (tmp, t);
3788 		  /* This is always a read. */
3789 		  gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3790 		  t = tmp;
3791 		}
3792 	      *expr = t;
3793 	    }
3794 	  else if (write)
3795 	    {
3796 	      gassign *stmt;
3797 
3798 	      if (access->grp_partial_lhs)
3799 		ref = force_gimple_operand_gsi (gsi, ref, true, NULL_TREE,
3800 						 false, GSI_NEW_STMT);
3801 	      stmt = gimple_build_assign (repl, ref);
3802 	      gimple_set_location (stmt, loc);
3803 	      gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
3804 	    }
3805 	  else
3806 	    {
3807 	      gassign *stmt;
3808 
3809 	      if (access->grp_partial_lhs)
3810 		repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
3811 						 true, GSI_SAME_STMT);
3812 	      stmt = gimple_build_assign (ref, repl);
3813 	      gimple_set_location (stmt, loc);
3814 	      gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3815 	    }
3816 	}
3817       else
3818 	*expr = repl;
3819       sra_stats.exprs++;
3820     }
3821   else if (write && access->grp_to_be_debug_replaced)
3822     {
3823       gdebug *ds = gimple_build_debug_bind (get_access_replacement (access),
3824 					    NULL_TREE,
3825 					    gsi_stmt (*gsi));
3826       gsi_insert_after (gsi, ds, GSI_NEW_STMT);
3827     }
3828 
3829   if (access->first_child)
3830     {
3831       HOST_WIDE_INT start_offset, chunk_size;
3832       if (bfr
3833 	  && tree_fits_uhwi_p (TREE_OPERAND (bfr, 1))
3834 	  && tree_fits_uhwi_p (TREE_OPERAND (bfr, 2)))
3835 	{
3836 	  chunk_size = tree_to_uhwi (TREE_OPERAND (bfr, 1));
3837 	  start_offset = access->offset
3838 	    + tree_to_uhwi (TREE_OPERAND (bfr, 2));
3839 	}
3840       else
3841 	start_offset = chunk_size = 0;
3842 
3843       generate_subtree_copies (access->first_child, orig_expr, access->offset,
3844 			       start_offset, chunk_size, gsi, write, write,
3845 			       loc);
3846     }
3847   return true;
3848 }
3849 
3850 /* Where scalar replacements of the RHS have been written to when a replacement
3851    of a LHS of an assigments cannot be direclty loaded from a replacement of
3852    the RHS. */
3853 enum unscalarized_data_handling { SRA_UDH_NONE,  /* Nothing done so far. */
3854 				  SRA_UDH_RIGHT, /* Data flushed to the RHS. */
3855 				  SRA_UDH_LEFT }; /* Data flushed to the LHS. */
3856 
3857 struct subreplacement_assignment_data
3858 {
3859   /* Offset of the access representing the lhs of the assignment.  */
3860   HOST_WIDE_INT left_offset;
3861 
3862   /* LHS and RHS of the original assignment.  */
3863   tree assignment_lhs, assignment_rhs;
3864 
3865   /* Access representing the rhs of the whole assignment.  */
3866   struct access *top_racc;
3867 
3868   /* Stmt iterator used for statement insertions after the original assignment.
3869    It points to the main GSI used to traverse a BB during function body
3870    modification.  */
3871   gimple_stmt_iterator *new_gsi;
3872 
3873   /* Stmt iterator used for statement insertions before the original
3874    assignment.  Keeps on pointing to the original statement.  */
3875   gimple_stmt_iterator old_gsi;
3876 
3877   /* Location of the assignment.   */
3878   location_t loc;
3879 
3880   /* Keeps the information whether we have needed to refresh replacements of
3881    the LHS and from which side of the assignments this takes place.  */
3882   enum unscalarized_data_handling refreshed;
3883 };
3884 
3885 /* Store all replacements in the access tree rooted in TOP_RACC either to their
3886    base aggregate if there are unscalarized data or directly to LHS of the
3887    statement that is pointed to by GSI otherwise.  */
3888 
3889 static void
handle_unscalarized_data_in_subtree(struct subreplacement_assignment_data * sad)3890 handle_unscalarized_data_in_subtree (struct subreplacement_assignment_data *sad)
3891 {
3892   tree src;
3893   if (sad->top_racc->grp_unscalarized_data)
3894     {
3895       src = sad->assignment_rhs;
3896       sad->refreshed = SRA_UDH_RIGHT;
3897     }
3898   else
3899     {
3900       src = sad->assignment_lhs;
3901       sad->refreshed = SRA_UDH_LEFT;
3902     }
3903   generate_subtree_copies (sad->top_racc->first_child, src,
3904 			   sad->top_racc->offset, 0, 0,
3905 			   &sad->old_gsi, false, false, sad->loc);
3906 }
3907 
3908 /* Try to generate statements to load all sub-replacements in an access subtree
3909    formed by children of LACC from scalar replacements in the SAD->top_racc
3910    subtree.  If that is not possible, refresh the SAD->top_racc base aggregate
3911    and load the accesses from it.  */
3912 
3913 static void
load_assign_lhs_subreplacements(struct access * lacc,struct subreplacement_assignment_data * sad)3914 load_assign_lhs_subreplacements (struct access *lacc,
3915 				 struct subreplacement_assignment_data *sad)
3916 {
3917   for (lacc = lacc->first_child; lacc; lacc = lacc->next_sibling)
3918     {
3919       HOST_WIDE_INT offset;
3920       offset = lacc->offset - sad->left_offset + sad->top_racc->offset;
3921 
3922       if (lacc->grp_to_be_replaced)
3923 	{
3924 	  struct access *racc;
3925 	  gassign *stmt;
3926 	  tree rhs;
3927 
3928 	  racc = find_access_in_subtree (sad->top_racc, offset, lacc->size);
3929 	  if (racc && racc->grp_to_be_replaced)
3930 	    {
3931 	      rhs = get_access_replacement (racc);
3932 	      if (!useless_type_conversion_p (lacc->type, racc->type))
3933 		rhs = fold_build1_loc (sad->loc, VIEW_CONVERT_EXPR,
3934 				       lacc->type, rhs);
3935 
3936 	      if (racc->grp_partial_lhs && lacc->grp_partial_lhs)
3937 		rhs = force_gimple_operand_gsi (&sad->old_gsi, rhs, true,
3938 						NULL_TREE, true, GSI_SAME_STMT);
3939 	    }
3940 	  else
3941 	    {
3942 	      /* No suitable access on the right hand side, need to load from
3943 		 the aggregate.  See if we have to update it first... */
3944 	      if (sad->refreshed == SRA_UDH_NONE)
3945 		handle_unscalarized_data_in_subtree (sad);
3946 
3947 	      if (sad->refreshed == SRA_UDH_LEFT)
3948 		rhs = build_ref_for_model (sad->loc, sad->assignment_lhs,
3949 					   lacc->offset - sad->left_offset,
3950 					   lacc, sad->new_gsi, true);
3951 	      else
3952 		rhs = build_ref_for_model (sad->loc, sad->assignment_rhs,
3953 					   lacc->offset - sad->left_offset,
3954 					   lacc, sad->new_gsi, true);
3955 	      if (lacc->grp_partial_lhs)
3956 		rhs = force_gimple_operand_gsi (sad->new_gsi,
3957 						rhs, true, NULL_TREE,
3958 						false, GSI_NEW_STMT);
3959 	    }
3960 
3961 	  stmt = gimple_build_assign (get_access_replacement (lacc), rhs);
3962 	  gsi_insert_after (sad->new_gsi, stmt, GSI_NEW_STMT);
3963 	  gimple_set_location (stmt, sad->loc);
3964 	  update_stmt (stmt);
3965 	  sra_stats.subreplacements++;
3966 	}
3967       else
3968 	{
3969 	  if (sad->refreshed == SRA_UDH_NONE
3970 	      && lacc->grp_read && !lacc->grp_covered)
3971 	    handle_unscalarized_data_in_subtree (sad);
3972 
3973 	  if (lacc && lacc->grp_to_be_debug_replaced)
3974 	    {
3975 	      gdebug *ds;
3976 	      tree drhs;
3977 	      struct access *racc = find_access_in_subtree (sad->top_racc,
3978 							    offset,
3979 							    lacc->size);
3980 
3981 	      if (racc && racc->grp_to_be_replaced)
3982 		{
3983 		  if (racc->grp_write || constant_decl_p (racc->base))
3984 		    drhs = get_access_replacement (racc);
3985 		  else
3986 		    drhs = NULL;
3987 		}
3988 	      else if (sad->refreshed == SRA_UDH_LEFT)
3989 		drhs = build_debug_ref_for_model (sad->loc, lacc->base,
3990 						  lacc->offset, lacc);
3991 	      else if (sad->refreshed == SRA_UDH_RIGHT)
3992 		drhs = build_debug_ref_for_model (sad->loc, sad->top_racc->base,
3993 						  offset, lacc);
3994 	      else
3995 		drhs = NULL_TREE;
3996 	      if (drhs
3997 		  && !useless_type_conversion_p (lacc->type, TREE_TYPE (drhs)))
3998 		drhs = fold_build1_loc (sad->loc, VIEW_CONVERT_EXPR,
3999 					lacc->type, drhs);
4000 	      ds = gimple_build_debug_bind (get_access_replacement (lacc),
4001 					    drhs, gsi_stmt (sad->old_gsi));
4002 	      gsi_insert_after (sad->new_gsi, ds, GSI_NEW_STMT);
4003 	    }
4004 	}
4005 
4006       if (lacc->first_child)
4007 	load_assign_lhs_subreplacements (lacc, sad);
4008     }
4009 }
4010 
4011 /* Result code for SRA assignment modification.  */
4012 enum assignment_mod_result { SRA_AM_NONE,       /* nothing done for the stmt */
4013 			     SRA_AM_MODIFIED,  /* stmt changed but not
4014 						  removed */
4015 			     SRA_AM_REMOVED };  /* stmt eliminated */
4016 
4017 /* Modify assignments with a CONSTRUCTOR on their RHS.  STMT contains a pointer
4018    to the assignment and GSI is the statement iterator pointing at it.  Returns
4019    the same values as sra_modify_assign.  */
4020 
4021 static enum assignment_mod_result
sra_modify_constructor_assign(gimple * stmt,gimple_stmt_iterator * gsi)4022 sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
4023 {
4024   tree lhs = gimple_assign_lhs (stmt);
4025   struct access *acc = get_access_for_expr (lhs);
4026   if (!acc)
4027     return SRA_AM_NONE;
4028   location_t loc = gimple_location (stmt);
4029 
4030   if (gimple_clobber_p (stmt))
4031     {
4032       /* Clobber the replacement variable.  */
4033       clobber_subtree (acc, gsi, !acc->grp_covered, loc);
4034       /* Remove clobbers of fully scalarized variables, they are dead.  */
4035       if (acc->grp_covered)
4036 	{
4037 	  unlink_stmt_vdef (stmt);
4038 	  gsi_remove (gsi, true);
4039 	  release_defs (stmt);
4040 	  return SRA_AM_REMOVED;
4041 	}
4042       else
4043 	return SRA_AM_MODIFIED;
4044     }
4045 
4046   if (CONSTRUCTOR_NELTS (gimple_assign_rhs1 (stmt)) > 0)
4047     {
4048       /* I have never seen this code path trigger but if it can happen the
4049 	 following should handle it gracefully.  */
4050       if (access_has_children_p (acc))
4051 	generate_subtree_copies (acc->first_child, lhs, acc->offset, 0, 0, gsi,
4052 				 true, true, loc);
4053       return SRA_AM_MODIFIED;
4054     }
4055 
4056   if (acc->grp_covered)
4057     {
4058       init_subtree_with_zero (acc, gsi, false, loc);
4059       unlink_stmt_vdef (stmt);
4060       gsi_remove (gsi, true);
4061       release_defs (stmt);
4062       return SRA_AM_REMOVED;
4063     }
4064   else
4065     {
4066       init_subtree_with_zero (acc, gsi, true, loc);
4067       return SRA_AM_MODIFIED;
4068     }
4069 }
4070 
4071 /* Create and return a new suitable default definition SSA_NAME for RACC which
4072    is an access describing an uninitialized part of an aggregate that is being
4073    loaded.  REG_TREE is used instead of the actual RACC type if that is not of
4074    a gimple register type.  */
4075 
4076 static tree
get_repl_default_def_ssa_name(struct access * racc,tree reg_type)4077 get_repl_default_def_ssa_name (struct access *racc, tree reg_type)
4078 {
4079   gcc_checking_assert (!racc->grp_to_be_replaced
4080 		       && !racc->grp_to_be_debug_replaced);
4081   if (!racc->replacement_decl)
4082     racc->replacement_decl = create_access_replacement (racc, reg_type);
4083   return get_or_create_ssa_default_def (cfun, racc->replacement_decl);
4084 }
4085 
4086 /* Examine both sides of the assignment statement pointed to by STMT, replace
4087    them with a scalare replacement if there is one and generate copying of
4088    replacements if scalarized aggregates have been used in the assignment.  GSI
4089    is used to hold generated statements for type conversions and subtree
4090    copying.  */
4091 
4092 static enum assignment_mod_result
sra_modify_assign(gimple * stmt,gimple_stmt_iterator * gsi)4093 sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi)
4094 {
4095   struct access *lacc, *racc;
4096   tree lhs, rhs;
4097   bool modify_this_stmt = false;
4098   bool force_gimple_rhs = false;
4099   location_t loc;
4100   gimple_stmt_iterator orig_gsi = *gsi;
4101 
4102   if (!gimple_assign_single_p (stmt))
4103     return SRA_AM_NONE;
4104   lhs = gimple_assign_lhs (stmt);
4105   rhs = gimple_assign_rhs1 (stmt);
4106 
4107   if (TREE_CODE (rhs) == CONSTRUCTOR)
4108     return sra_modify_constructor_assign (stmt, gsi);
4109 
4110   if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (lhs) == REALPART_EXPR
4111       || TREE_CODE (rhs) == IMAGPART_EXPR || TREE_CODE (lhs) == IMAGPART_EXPR
4112       || TREE_CODE (rhs) == BIT_FIELD_REF || TREE_CODE (lhs) == BIT_FIELD_REF)
4113     {
4114       modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (stmt),
4115 					  gsi, false);
4116       modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (stmt),
4117 					   gsi, true);
4118       return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
4119     }
4120 
4121   lacc = get_access_for_expr (lhs);
4122   racc = get_access_for_expr (rhs);
4123   if (!lacc && !racc)
4124     return SRA_AM_NONE;
4125   /* Avoid modifying initializations of constant-pool replacements.  */
4126   if (racc && (racc->replacement_decl == lhs))
4127     return SRA_AM_NONE;
4128 
4129   loc = gimple_location (stmt);
4130   if (lacc && lacc->grp_to_be_replaced)
4131     {
4132       lhs = get_access_replacement (lacc);
4133       gimple_assign_set_lhs (stmt, lhs);
4134       modify_this_stmt = true;
4135       if (lacc->grp_partial_lhs)
4136 	force_gimple_rhs = true;
4137       sra_stats.exprs++;
4138     }
4139 
4140   if (racc && racc->grp_to_be_replaced)
4141     {
4142       rhs = get_access_replacement (racc);
4143       modify_this_stmt = true;
4144       if (racc->grp_partial_lhs)
4145 	force_gimple_rhs = true;
4146       sra_stats.exprs++;
4147     }
4148   else if (racc
4149 	   && !racc->grp_unscalarized_data
4150 	   && !racc->grp_unscalarizable_region
4151 	   && TREE_CODE (lhs) == SSA_NAME
4152 	   && !access_has_replacements_p (racc))
4153     {
4154       rhs = get_repl_default_def_ssa_name (racc, TREE_TYPE (lhs));
4155       modify_this_stmt = true;
4156       sra_stats.exprs++;
4157     }
4158 
4159   if (modify_this_stmt)
4160     {
4161       if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
4162 	{
4163 	  /* If we can avoid creating a VIEW_CONVERT_EXPR do so.
4164 	     ???  This should move to fold_stmt which we simply should
4165 	     call after building a VIEW_CONVERT_EXPR here.  */
4166 	  if (AGGREGATE_TYPE_P (TREE_TYPE (lhs))
4167 	      && !contains_bitfld_component_ref_p (lhs))
4168 	    {
4169 	      lhs = build_ref_for_model (loc, lhs, 0, racc, gsi, false);
4170 	      gimple_assign_set_lhs (stmt, lhs);
4171 	    }
4172 	  else if (lacc
4173 		   && AGGREGATE_TYPE_P (TREE_TYPE (rhs))
4174 		   && !contains_vce_or_bfcref_p (rhs))
4175 	    rhs = build_ref_for_model (loc, rhs, 0, lacc, gsi, false);
4176 
4177 	  if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
4178 	    {
4179 	      rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
4180 				     rhs);
4181 	      if (is_gimple_reg_type (TREE_TYPE (lhs))
4182 		  && TREE_CODE (lhs) != SSA_NAME)
4183 		force_gimple_rhs = true;
4184 	    }
4185 	}
4186     }
4187 
4188   if (lacc && lacc->grp_to_be_debug_replaced)
4189     {
4190       tree dlhs = get_access_replacement (lacc);
4191       tree drhs = unshare_expr (rhs);
4192       if (!useless_type_conversion_p (TREE_TYPE (dlhs), TREE_TYPE (drhs)))
4193 	{
4194 	  if (AGGREGATE_TYPE_P (TREE_TYPE (drhs))
4195 	      && !contains_vce_or_bfcref_p (drhs))
4196 	    drhs = build_debug_ref_for_model (loc, drhs, 0, lacc);
4197 	  if (drhs
4198 	      && !useless_type_conversion_p (TREE_TYPE (dlhs),
4199 					     TREE_TYPE (drhs)))
4200 	    drhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
4201 				    TREE_TYPE (dlhs), drhs);
4202 	}
4203       gdebug *ds = gimple_build_debug_bind (dlhs, drhs, stmt);
4204       gsi_insert_before (gsi, ds, GSI_SAME_STMT);
4205     }
4206 
4207   /* From this point on, the function deals with assignments in between
4208      aggregates when at least one has scalar reductions of some of its
4209      components.  There are three possible scenarios: Both the LHS and RHS have
4210      to-be-scalarized components, 2) only the RHS has or 3) only the LHS has.
4211 
4212      In the first case, we would like to load the LHS components from RHS
4213      components whenever possible.  If that is not possible, we would like to
4214      read it directly from the RHS (after updating it by storing in it its own
4215      components).  If there are some necessary unscalarized data in the LHS,
4216      those will be loaded by the original assignment too.  If neither of these
4217      cases happen, the original statement can be removed.  Most of this is done
4218      by load_assign_lhs_subreplacements.
4219 
4220      In the second case, we would like to store all RHS scalarized components
4221      directly into LHS and if they cover the aggregate completely, remove the
4222      statement too.  In the third case, we want the LHS components to be loaded
4223      directly from the RHS (DSE will remove the original statement if it
4224      becomes redundant).
4225 
4226      This is a bit complex but manageable when types match and when unions do
4227      not cause confusion in a way that we cannot really load a component of LHS
4228      from the RHS or vice versa (the access representing this level can have
4229      subaccesses that are accessible only through a different union field at a
4230      higher level - different from the one used in the examined expression).
4231      Unions are fun.
4232 
4233      Therefore, I specially handle a fourth case, happening when there is a
4234      specific type cast or it is impossible to locate a scalarized subaccess on
4235      the other side of the expression.  If that happens, I simply "refresh" the
4236      RHS by storing in it is scalarized components leave the original statement
4237      there to do the copying and then load the scalar replacements of the LHS.
4238      This is what the first branch does.  */
4239 
4240   if (modify_this_stmt
4241       || gimple_has_volatile_ops (stmt)
4242       || contains_vce_or_bfcref_p (rhs)
4243       || contains_vce_or_bfcref_p (lhs)
4244       || stmt_ends_bb_p (stmt))
4245     {
4246       /* No need to copy into a constant-pool, it comes pre-initialized.  */
4247       if (access_has_children_p (racc) && !constant_decl_p (racc->base))
4248 	generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0,
4249 				 gsi, false, false, loc);
4250       if (access_has_children_p (lacc))
4251 	{
4252 	  gimple_stmt_iterator alt_gsi = gsi_none ();
4253 	  if (stmt_ends_bb_p (stmt))
4254 	    {
4255 	      alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi)));
4256 	      gsi = &alt_gsi;
4257 	    }
4258 	  generate_subtree_copies (lacc->first_child, lhs, lacc->offset, 0, 0,
4259 				   gsi, true, true, loc);
4260 	}
4261       sra_stats.separate_lhs_rhs_handling++;
4262 
4263       /* This gimplification must be done after generate_subtree_copies,
4264 	 lest we insert the subtree copies in the middle of the gimplified
4265 	 sequence.  */
4266       if (force_gimple_rhs)
4267 	rhs = force_gimple_operand_gsi (&orig_gsi, rhs, true, NULL_TREE,
4268 					true, GSI_SAME_STMT);
4269       if (gimple_assign_rhs1 (stmt) != rhs)
4270 	{
4271 	  modify_this_stmt = true;
4272 	  gimple_assign_set_rhs_from_tree (&orig_gsi, rhs);
4273 	  gcc_assert (stmt == gsi_stmt (orig_gsi));
4274 	}
4275 
4276       return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
4277     }
4278   else
4279     {
4280       if (access_has_children_p (lacc)
4281 	  && access_has_children_p (racc)
4282 	  /* When an access represents an unscalarizable region, it usually
4283 	     represents accesses with variable offset and thus must not be used
4284 	     to generate new memory accesses.  */
4285 	  && !lacc->grp_unscalarizable_region
4286 	  && !racc->grp_unscalarizable_region)
4287 	{
4288 	  struct subreplacement_assignment_data sad;
4289 
4290 	  sad.left_offset = lacc->offset;
4291 	  sad.assignment_lhs = lhs;
4292 	  sad.assignment_rhs = rhs;
4293 	  sad.top_racc = racc;
4294 	  sad.old_gsi = *gsi;
4295 	  sad.new_gsi = gsi;
4296 	  sad.loc = gimple_location (stmt);
4297 	  sad.refreshed = SRA_UDH_NONE;
4298 
4299 	  if (lacc->grp_read && !lacc->grp_covered)
4300 	    handle_unscalarized_data_in_subtree (&sad);
4301 
4302 	  load_assign_lhs_subreplacements (lacc, &sad);
4303 	  if (sad.refreshed != SRA_UDH_RIGHT)
4304 	    {
4305 	      gsi_next (gsi);
4306 	      unlink_stmt_vdef (stmt);
4307 	      gsi_remove (&sad.old_gsi, true);
4308 	      release_defs (stmt);
4309 	      sra_stats.deleted++;
4310 	      return SRA_AM_REMOVED;
4311 	    }
4312 	}
4313       else
4314 	{
4315 	  if (access_has_children_p (racc)
4316 	      && !racc->grp_unscalarized_data
4317 	      && TREE_CODE (lhs) != SSA_NAME)
4318 	    {
4319 	      if (dump_file)
4320 		{
4321 		  fprintf (dump_file, "Removing load: ");
4322 		  print_gimple_stmt (dump_file, stmt, 0);
4323 		}
4324 	      generate_subtree_copies (racc->first_child, lhs,
4325 				       racc->offset, 0, 0, gsi,
4326 				       false, false, loc);
4327 	      gcc_assert (stmt == gsi_stmt (*gsi));
4328 	      unlink_stmt_vdef (stmt);
4329 	      gsi_remove (gsi, true);
4330 	      release_defs (stmt);
4331 	      sra_stats.deleted++;
4332 	      return SRA_AM_REMOVED;
4333 	    }
4334 	  /* Restore the aggregate RHS from its components so the
4335 	     prevailing aggregate copy does the right thing.  */
4336 	  if (access_has_children_p (racc))
4337 	    generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0,
4338 				     gsi, false, false, loc);
4339 	  /* Re-load the components of the aggregate copy destination.
4340 	     But use the RHS aggregate to load from to expose more
4341 	     optimization opportunities.  */
4342 	  if (access_has_children_p (lacc))
4343 	    generate_subtree_copies (lacc->first_child, rhs, lacc->offset,
4344 				     0, 0, gsi, true, true, loc);
4345 	}
4346 
4347       return SRA_AM_NONE;
4348     }
4349 }
4350 
4351 /* Set any scalar replacements of values in the constant pool to the initial
4352    value of the constant.  (Constant-pool decls like *.LC0 have effectively
4353    been initialized before the program starts, we must do the same for their
4354    replacements.)  Thus, we output statements like 'SR.1 = *.LC0[0];' into
4355    the function's entry block.  */
4356 
4357 static void
initialize_constant_pool_replacements(void)4358 initialize_constant_pool_replacements (void)
4359 {
4360   gimple_seq seq = NULL;
4361   gimple_stmt_iterator gsi = gsi_start (seq);
4362   bitmap_iterator bi;
4363   unsigned i;
4364 
4365   EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
4366     {
4367       tree var = candidate (i);
4368       if (!constant_decl_p (var))
4369 	continue;
4370 
4371       struct access *access = get_first_repr_for_decl (var);
4372 
4373       while (access)
4374 	{
4375 	  if (access->replacement_decl)
4376 	    {
4377 	      gassign *stmt
4378 		= gimple_build_assign (get_access_replacement (access),
4379 				       unshare_expr (access->expr));
4380 	      if (dump_file && (dump_flags & TDF_DETAILS))
4381 		{
4382 		  fprintf (dump_file, "Generating constant initializer: ");
4383 		  print_gimple_stmt (dump_file, stmt, 0);
4384 		  fprintf (dump_file, "\n");
4385 		}
4386 	      gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
4387 	      update_stmt (stmt);
4388 	    }
4389 
4390 	  if (access->first_child)
4391 	    access = access->first_child;
4392 	  else if (access->next_sibling)
4393 	    access = access->next_sibling;
4394 	  else
4395 	    {
4396 	      while (access->parent && !access->next_sibling)
4397 		access = access->parent;
4398 	      if (access->next_sibling)
4399 		access = access->next_sibling;
4400 	      else
4401 		access = access->next_grp;
4402 	    }
4403 	}
4404     }
4405 
4406   seq = gsi_seq (gsi);
4407   if (seq)
4408     gsi_insert_seq_on_edge_immediate (
4409       single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
4410 }
4411 
4412 /* Traverse the function body and all modifications as decided in
4413    analyze_all_variable_accesses.  Return true iff the CFG has been
4414    changed.  */
4415 
4416 static bool
sra_modify_function_body(void)4417 sra_modify_function_body (void)
4418 {
4419   bool cfg_changed = false;
4420   basic_block bb;
4421 
4422   initialize_constant_pool_replacements ();
4423 
4424   FOR_EACH_BB_FN (bb, cfun)
4425     {
4426       gimple_stmt_iterator gsi = gsi_start_bb (bb);
4427       while (!gsi_end_p (gsi))
4428 	{
4429 	  gimple *stmt = gsi_stmt (gsi);
4430 	  enum assignment_mod_result assign_result;
4431 	  bool modified = false, deleted = false;
4432 	  tree *t;
4433 	  unsigned i;
4434 
4435 	  switch (gimple_code (stmt))
4436 	    {
4437 	    case GIMPLE_RETURN:
4438 	      t = gimple_return_retval_ptr (as_a <greturn *> (stmt));
4439 	      if (*t != NULL_TREE)
4440 		modified |= sra_modify_expr (t, &gsi, false);
4441 	      break;
4442 
4443 	    case GIMPLE_ASSIGN:
4444 	      assign_result = sra_modify_assign (stmt, &gsi);
4445 	      modified |= assign_result == SRA_AM_MODIFIED;
4446 	      deleted = assign_result == SRA_AM_REMOVED;
4447 	      break;
4448 
4449 	    case GIMPLE_CALL:
4450 	      /* Operands must be processed before the lhs.  */
4451 	      for (i = 0; i < gimple_call_num_args (stmt); i++)
4452 		{
4453 		  t = gimple_call_arg_ptr (stmt, i);
4454 		  modified |= sra_modify_expr (t, &gsi, false);
4455 		}
4456 
4457 	      if (gimple_call_lhs (stmt))
4458 		{
4459 		  t = gimple_call_lhs_ptr (stmt);
4460 		  modified |= sra_modify_expr (t, &gsi, true);
4461 		}
4462 	      break;
4463 
4464 	    case GIMPLE_ASM:
4465 	      {
4466 		gasm *asm_stmt = as_a <gasm *> (stmt);
4467 		for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
4468 		  {
4469 		    t = &TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
4470 		    modified |= sra_modify_expr (t, &gsi, false);
4471 		  }
4472 		for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
4473 		  {
4474 		    t = &TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
4475 		    modified |= sra_modify_expr (t, &gsi, true);
4476 		  }
4477 	      }
4478 	      break;
4479 
4480 	    default:
4481 	      break;
4482 	    }
4483 
4484 	  if (modified)
4485 	    {
4486 	      update_stmt (stmt);
4487 	      if (maybe_clean_eh_stmt (stmt)
4488 		  && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
4489 		cfg_changed = true;
4490 	    }
4491 	  if (!deleted)
4492 	    gsi_next (&gsi);
4493 	}
4494     }
4495 
4496   gsi_commit_edge_inserts ();
4497   return cfg_changed;
4498 }
4499 
4500 /* Generate statements initializing scalar replacements of parts of function
4501    parameters.  */
4502 
4503 static void
initialize_parameter_reductions(void)4504 initialize_parameter_reductions (void)
4505 {
4506   gimple_stmt_iterator gsi;
4507   gimple_seq seq = NULL;
4508   tree parm;
4509 
4510   gsi = gsi_start (seq);
4511   for (parm = DECL_ARGUMENTS (current_function_decl);
4512        parm;
4513        parm = DECL_CHAIN (parm))
4514     {
4515       vec<access_p> *access_vec;
4516       struct access *access;
4517 
4518       if (!bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
4519 	continue;
4520       access_vec = get_base_access_vector (parm);
4521       if (!access_vec)
4522 	continue;
4523 
4524       for (access = (*access_vec)[0];
4525 	   access;
4526 	   access = access->next_grp)
4527 	generate_subtree_copies (access, parm, 0, 0, 0, &gsi, true, true,
4528 				 EXPR_LOCATION (parm));
4529     }
4530 
4531   seq = gsi_seq (gsi);
4532   if (seq)
4533     gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
4534 }
4535 
4536 /* The "main" function of intraprocedural SRA passes.  Runs the analysis and if
4537    it reveals there are components of some aggregates to be scalarized, it runs
4538    the required transformations.  */
4539 static unsigned int
perform_intra_sra(void)4540 perform_intra_sra (void)
4541 {
4542   int ret = 0;
4543   sra_initialize ();
4544 
4545   if (!find_var_candidates ())
4546     goto out;
4547 
4548   if (!scan_function ())
4549     goto out;
4550 
4551   if (!analyze_all_variable_accesses ())
4552     goto out;
4553 
4554   if (sra_modify_function_body ())
4555     ret = TODO_update_ssa | TODO_cleanup_cfg;
4556   else
4557     ret = TODO_update_ssa;
4558   initialize_parameter_reductions ();
4559 
4560   statistics_counter_event (cfun, "Scalar replacements created",
4561 			    sra_stats.replacements);
4562   statistics_counter_event (cfun, "Modified expressions", sra_stats.exprs);
4563   statistics_counter_event (cfun, "Subtree copy stmts",
4564 			    sra_stats.subtree_copies);
4565   statistics_counter_event (cfun, "Subreplacement stmts",
4566 			    sra_stats.subreplacements);
4567   statistics_counter_event (cfun, "Deleted stmts", sra_stats.deleted);
4568   statistics_counter_event (cfun, "Separate LHS and RHS handling",
4569 			    sra_stats.separate_lhs_rhs_handling);
4570 
4571  out:
4572   sra_deinitialize ();
4573   return ret;
4574 }
4575 
4576 /* Perform early intraprocedural SRA.  */
4577 static unsigned int
early_intra_sra(void)4578 early_intra_sra (void)
4579 {
4580   sra_mode = SRA_MODE_EARLY_INTRA;
4581   return perform_intra_sra ();
4582 }
4583 
4584 /* Perform "late" intraprocedural SRA.  */
4585 static unsigned int
late_intra_sra(void)4586 late_intra_sra (void)
4587 {
4588   sra_mode = SRA_MODE_INTRA;
4589   return perform_intra_sra ();
4590 }
4591 
4592 
4593 static bool
gate_intra_sra(void)4594 gate_intra_sra (void)
4595 {
4596   return flag_tree_sra != 0 && dbg_cnt (tree_sra);
4597 }
4598 
4599 
4600 namespace {
4601 
4602 const pass_data pass_data_sra_early =
4603 {
4604   GIMPLE_PASS, /* type */
4605   "esra", /* name */
4606   OPTGROUP_NONE, /* optinfo_flags */
4607   TV_TREE_SRA, /* tv_id */
4608   ( PROP_cfg | PROP_ssa ), /* properties_required */
4609   0, /* properties_provided */
4610   0, /* properties_destroyed */
4611   0, /* todo_flags_start */
4612   TODO_update_ssa, /* todo_flags_finish */
4613 };
4614 
4615 class pass_sra_early : public gimple_opt_pass
4616 {
4617 public:
pass_sra_early(gcc::context * ctxt)4618   pass_sra_early (gcc::context *ctxt)
4619     : gimple_opt_pass (pass_data_sra_early, ctxt)
4620   {}
4621 
4622   /* opt_pass methods: */
gate(function *)4623   virtual bool gate (function *) { return gate_intra_sra (); }
execute(function *)4624   virtual unsigned int execute (function *) { return early_intra_sra (); }
4625 
4626 }; // class pass_sra_early
4627 
4628 } // anon namespace
4629 
4630 gimple_opt_pass *
make_pass_sra_early(gcc::context * ctxt)4631 make_pass_sra_early (gcc::context *ctxt)
4632 {
4633   return new pass_sra_early (ctxt);
4634 }
4635 
4636 namespace {
4637 
4638 const pass_data pass_data_sra =
4639 {
4640   GIMPLE_PASS, /* type */
4641   "sra", /* name */
4642   OPTGROUP_NONE, /* optinfo_flags */
4643   TV_TREE_SRA, /* tv_id */
4644   ( PROP_cfg | PROP_ssa ), /* properties_required */
4645   0, /* properties_provided */
4646   0, /* properties_destroyed */
4647   TODO_update_address_taken, /* todo_flags_start */
4648   TODO_update_ssa, /* todo_flags_finish */
4649 };
4650 
4651 class pass_sra : public gimple_opt_pass
4652 {
4653 public:
pass_sra(gcc::context * ctxt)4654   pass_sra (gcc::context *ctxt)
4655     : gimple_opt_pass (pass_data_sra, ctxt)
4656   {}
4657 
4658   /* opt_pass methods: */
gate(function *)4659   virtual bool gate (function *) { return gate_intra_sra (); }
execute(function *)4660   virtual unsigned int execute (function *) { return late_intra_sra (); }
4661 
4662 }; // class pass_sra
4663 
4664 } // anon namespace
4665 
4666 gimple_opt_pass *
make_pass_sra(gcc::context * ctxt)4667 make_pass_sra (gcc::context *ctxt)
4668 {
4669   return new pass_sra (ctxt);
4670 }
4671