xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/tree-sra.c (revision 23f5f46327e37e7811da3520f4bb933f9489322f)
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-2020 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;
1651   /* We have to make sure to start just below the outermost union.  */
1652   tree start_expr = expr;
1653   while (handled_component_p (expr))
1654     {
1655       if (TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == UNION_TYPE)
1656 	start_expr = expr;
1657       expr = TREE_OPERAND (expr, 0);
1658     }
1659 
1660   expr = start_expr;
1661   tree prev_expr = NULL_TREE;
1662   while (!types_compatible_p (TREE_TYPE (expr), TREE_TYPE (base)))
1663     {
1664       if (!handled_component_p (expr))
1665 	return NULL_TREE;
1666       prev_expr = expr;
1667       expr = TREE_OPERAND (expr, 0);
1668     }
1669 
1670   /* Guard against broken VIEW_CONVERT_EXPRs...  */
1671   if (!prev_expr)
1672     return NULL_TREE;
1673 
1674   TREE_OPERAND (prev_expr, 0) = base;
1675   tree ref = unshare_expr (model->expr);
1676   TREE_OPERAND (prev_expr, 0) = expr;
1677   return ref;
1678 }
1679 
1680 /* Construct a memory reference to a part of an aggregate BASE at the given
1681    OFFSET and of the same type as MODEL.  In case this is a reference to a
1682    bit-field, the function will replicate the last component_ref of model's
1683    expr to access it.  GSI and INSERT_AFTER have the same meaning as in
1684    build_ref_for_offset.  */
1685 
1686 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)1687 build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
1688 		     struct access *model, gimple_stmt_iterator *gsi,
1689 		     bool insert_after)
1690 {
1691   gcc_assert (offset >= 0);
1692   if (TREE_CODE (model->expr) == COMPONENT_REF
1693       && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
1694     {
1695       /* This access represents a bit-field.  */
1696       tree t, exp_type, fld = TREE_OPERAND (model->expr, 1);
1697 
1698       offset -= int_bit_position (fld);
1699       exp_type = TREE_TYPE (TREE_OPERAND (model->expr, 0));
1700       t = build_ref_for_offset (loc, base, offset, model->reverse, exp_type,
1701 				gsi, insert_after);
1702       /* The flag will be set on the record type.  */
1703       REF_REVERSE_STORAGE_ORDER (t) = 0;
1704       return fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (fld), t, fld,
1705 			      NULL_TREE);
1706     }
1707   else
1708     {
1709       tree res;
1710       if (model->grp_same_access_path
1711 	  && !TREE_THIS_VOLATILE (base)
1712 	  && (TYPE_ADDR_SPACE (TREE_TYPE (base))
1713 	      == TYPE_ADDR_SPACE (TREE_TYPE (model->expr)))
1714 	  && offset <= model->offset
1715 	  /* build_reconstructed_reference can still fail if we have already
1716 	     massaged BASE because of another type incompatibility.  */
1717 	  && (res = build_reconstructed_reference (loc, base, model)))
1718 	return res;
1719       else
1720 	return build_ref_for_offset (loc, base, offset, model->reverse,
1721 				     model->type, gsi, insert_after);
1722     }
1723 }
1724 
1725 /* Attempt to build a memory reference that we could but into a gimple
1726    debug_bind statement.  Similar to build_ref_for_model but punts if it has to
1727    create statements and return s NULL instead.  This function also ignores
1728    alignment issues and so its results should never end up in non-debug
1729    statements.  */
1730 
1731 static tree
build_debug_ref_for_model(location_t loc,tree base,HOST_WIDE_INT offset,struct access * model)1732 build_debug_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
1733 			   struct access *model)
1734 {
1735   poly_int64 base_offset;
1736   tree off;
1737 
1738   if (TREE_CODE (model->expr) == COMPONENT_REF
1739       && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
1740     return NULL_TREE;
1741 
1742   base = get_addr_base_and_unit_offset (base, &base_offset);
1743   if (!base)
1744     return NULL_TREE;
1745   if (TREE_CODE (base) == MEM_REF)
1746     {
1747       off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
1748 			   base_offset + offset / BITS_PER_UNIT);
1749       off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
1750       base = unshare_expr (TREE_OPERAND (base, 0));
1751     }
1752   else
1753     {
1754       off = build_int_cst (reference_alias_ptr_type (base),
1755 			   base_offset + offset / BITS_PER_UNIT);
1756       base = build_fold_addr_expr (unshare_expr (base));
1757     }
1758 
1759   return fold_build2_loc (loc, MEM_REF, model->type, base, off);
1760 }
1761 
1762 /* Construct a memory reference consisting of component_refs and array_refs to
1763    a part of an aggregate *RES (which is of type TYPE).  The requested part
1764    should have type EXP_TYPE at be the given OFFSET.  This function might not
1765    succeed, it returns true when it does and only then *RES points to something
1766    meaningful.  This function should be used only to build expressions that we
1767    might need to present to user (e.g. in warnings).  In all other situations,
1768    build_ref_for_model or build_ref_for_offset should be used instead.  */
1769 
1770 static bool
build_user_friendly_ref_for_offset(tree * res,tree type,HOST_WIDE_INT offset,tree exp_type)1771 build_user_friendly_ref_for_offset (tree *res, tree type, HOST_WIDE_INT offset,
1772 				    tree exp_type)
1773 {
1774   while (1)
1775     {
1776       tree fld;
1777       tree tr_size, index, minidx;
1778       HOST_WIDE_INT el_size;
1779 
1780       if (offset == 0 && exp_type
1781 	  && types_compatible_p (exp_type, type))
1782 	return true;
1783 
1784       switch (TREE_CODE (type))
1785 	{
1786 	case UNION_TYPE:
1787 	case QUAL_UNION_TYPE:
1788 	case RECORD_TYPE:
1789 	  for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
1790 	    {
1791 	      HOST_WIDE_INT pos, size;
1792 	      tree tr_pos, expr, *expr_ptr;
1793 
1794 	      if (TREE_CODE (fld) != FIELD_DECL)
1795 		continue;
1796 
1797 	      tr_pos = bit_position (fld);
1798 	      if (!tr_pos || !tree_fits_uhwi_p (tr_pos))
1799 		continue;
1800 	      pos = tree_to_uhwi (tr_pos);
1801 	      gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0);
1802 	      tr_size = DECL_SIZE (fld);
1803 	      if (!tr_size || !tree_fits_uhwi_p (tr_size))
1804 		continue;
1805 	      size = tree_to_uhwi (tr_size);
1806 	      if (size == 0)
1807 		{
1808 		  if (pos != offset)
1809 		    continue;
1810 		}
1811 	      else if (pos > offset || (pos + size) <= offset)
1812 		continue;
1813 
1814 	      expr = build3 (COMPONENT_REF, TREE_TYPE (fld), *res, fld,
1815 			     NULL_TREE);
1816 	      expr_ptr = &expr;
1817 	      if (build_user_friendly_ref_for_offset (expr_ptr, TREE_TYPE (fld),
1818 						      offset - pos, exp_type))
1819 		{
1820 		  *res = expr;
1821 		  return true;
1822 		}
1823 	    }
1824 	  return false;
1825 
1826 	case ARRAY_TYPE:
1827 	  tr_size = TYPE_SIZE (TREE_TYPE (type));
1828 	  if (!tr_size || !tree_fits_uhwi_p (tr_size))
1829 	    return false;
1830 	  el_size = tree_to_uhwi (tr_size);
1831 
1832 	  minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
1833 	  if (TREE_CODE (minidx) != INTEGER_CST || el_size == 0)
1834 	    return false;
1835 	  index = build_int_cst (TYPE_DOMAIN (type), offset / el_size);
1836 	  if (!integer_zerop (minidx))
1837 	    index = int_const_binop (PLUS_EXPR, index, minidx);
1838 	  *res = build4 (ARRAY_REF, TREE_TYPE (type), *res, index,
1839 			 NULL_TREE, NULL_TREE);
1840 	  offset = offset % el_size;
1841 	  type = TREE_TYPE (type);
1842 	  break;
1843 
1844 	default:
1845 	  if (offset != 0)
1846 	    return false;
1847 
1848 	  if (exp_type)
1849 	    return false;
1850 	  else
1851 	    return true;
1852 	}
1853     }
1854 }
1855 
1856 /* Print message to dump file why a variable was rejected. */
1857 
1858 static void
reject(tree var,const char * msg)1859 reject (tree var, const char *msg)
1860 {
1861   if (dump_file && (dump_flags & TDF_DETAILS))
1862     {
1863       fprintf (dump_file, "Rejected (%d): %s: ", DECL_UID (var), msg);
1864       print_generic_expr (dump_file, var);
1865       fprintf (dump_file, "\n");
1866     }
1867 }
1868 
1869 /* Return true if VAR is a candidate for SRA.  */
1870 
1871 static bool
maybe_add_sra_candidate(tree var)1872 maybe_add_sra_candidate (tree var)
1873 {
1874   tree type = TREE_TYPE (var);
1875   const char *msg;
1876   tree_node **slot;
1877 
1878   if (!AGGREGATE_TYPE_P (type))
1879     {
1880       reject (var, "not aggregate");
1881       return false;
1882     }
1883   /* Allow constant-pool entries that "need to live in memory".  */
1884   if (needs_to_live_in_memory (var) && !constant_decl_p (var))
1885     {
1886       reject (var, "needs to live in memory");
1887       return false;
1888     }
1889   if (TREE_THIS_VOLATILE (var))
1890     {
1891       reject (var, "is volatile");
1892       return false;
1893     }
1894   if (!COMPLETE_TYPE_P (type))
1895     {
1896       reject (var, "has incomplete type");
1897       return false;
1898     }
1899   if (!tree_fits_shwi_p (TYPE_SIZE (type)))
1900     {
1901       reject (var, "type size not fixed");
1902       return false;
1903     }
1904   if (tree_to_shwi (TYPE_SIZE (type)) == 0)
1905     {
1906       reject (var, "type size is zero");
1907       return false;
1908     }
1909   if (type_internals_preclude_sra_p (type, &msg))
1910     {
1911       reject (var, msg);
1912       return false;
1913     }
1914   if (/* Fix for PR 41089.  tree-stdarg.c needs to have va_lists intact but
1915 	 we also want to schedule it rather late.  Thus we ignore it in
1916 	 the early pass. */
1917       (sra_mode == SRA_MODE_EARLY_INTRA
1918        && is_va_list_type (type)))
1919     {
1920       reject (var, "is va_list");
1921       return false;
1922     }
1923 
1924   bitmap_set_bit (candidate_bitmap, DECL_UID (var));
1925   slot = candidates->find_slot_with_hash (var, DECL_UID (var), INSERT);
1926   *slot = var;
1927 
1928   if (dump_file && (dump_flags & TDF_DETAILS))
1929     {
1930       fprintf (dump_file, "Candidate (%d): ", DECL_UID (var));
1931       print_generic_expr (dump_file, var);
1932       fprintf (dump_file, "\n");
1933     }
1934 
1935   return true;
1936 }
1937 
1938 /* The very first phase of intraprocedural SRA.  It marks in candidate_bitmap
1939    those with type which is suitable for scalarization.  */
1940 
1941 static bool
find_var_candidates(void)1942 find_var_candidates (void)
1943 {
1944   tree var, parm;
1945   unsigned int i;
1946   bool ret = false;
1947 
1948   for (parm = DECL_ARGUMENTS (current_function_decl);
1949        parm;
1950        parm = DECL_CHAIN (parm))
1951     ret |= maybe_add_sra_candidate (parm);
1952 
1953   FOR_EACH_LOCAL_DECL (cfun, i, var)
1954     {
1955       if (!VAR_P (var))
1956         continue;
1957 
1958       ret |= maybe_add_sra_candidate (var);
1959     }
1960 
1961   return ret;
1962 }
1963 
1964 /* Return true if EXP is a reference chain of COMPONENT_REFs and AREAY_REFs
1965    ending either with a DECL or a MEM_REF with zero offset.  */
1966 
1967 static bool
path_comparable_for_same_access(tree expr)1968 path_comparable_for_same_access (tree expr)
1969 {
1970   while (handled_component_p (expr))
1971     {
1972       if (TREE_CODE (expr) == ARRAY_REF)
1973 	{
1974 	  /* SSA name indices can occur here too when the array is of sie one.
1975 	     But we cannot just re-use array_refs with SSA names elsewhere in
1976 	     the function, so disallow non-constant indices.  TODO: Remove this
1977 	     limitation after teaching build_reconstructed_reference to replace
1978 	     the index with the index type lower bound.  */
1979 	  if (TREE_CODE (TREE_OPERAND (expr, 1)) != INTEGER_CST)
1980 	    return false;
1981 	}
1982       expr = TREE_OPERAND (expr, 0);
1983     }
1984 
1985   if (TREE_CODE (expr) == MEM_REF)
1986     {
1987       if (!zerop (TREE_OPERAND (expr, 1)))
1988 	return false;
1989     }
1990   else
1991     gcc_assert (DECL_P (expr));
1992 
1993   return true;
1994 }
1995 
1996 /* Assuming that EXP1 consists of only COMPONENT_REFs and ARRAY_REFs, return
1997    true if the chain of these handled components are exactly the same as EXP2
1998    and the expression under them is the same DECL or an equivalent MEM_REF.
1999    The reference picked by compare_access_positions must go to EXP1.  */
2000 
2001 static bool
same_access_path_p(tree exp1,tree exp2)2002 same_access_path_p (tree exp1, tree exp2)
2003 {
2004   if (TREE_CODE (exp1) != TREE_CODE (exp2))
2005     {
2006       /* Special case single-field structures loaded sometimes as the field
2007 	 and sometimes as the structure.  If the field is of a scalar type,
2008 	 compare_access_positions will put it into exp1.
2009 
2010 	 TODO: The gimple register type condition can be removed if teach
2011 	 compare_access_positions to put inner types first.  */
2012       if (is_gimple_reg_type (TREE_TYPE (exp1))
2013 	  && TREE_CODE (exp1) == COMPONENT_REF
2014 	  && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (exp1, 0)))
2015 	      == TYPE_MAIN_VARIANT (TREE_TYPE (exp2))))
2016 	exp1 = TREE_OPERAND (exp1, 0);
2017       else
2018 	return false;
2019     }
2020 
2021   if (!operand_equal_p (exp1, exp2, OEP_ADDRESS_OF))
2022     return false;
2023 
2024   return true;
2025 }
2026 
2027 /* Sort all accesses for the given variable, check for partial overlaps and
2028    return NULL if there are any.  If there are none, pick a representative for
2029    each combination of offset and size and create a linked list out of them.
2030    Return the pointer to the first representative and make sure it is the first
2031    one in the vector of accesses.  */
2032 
2033 static struct access *
sort_and_splice_var_accesses(tree var)2034 sort_and_splice_var_accesses (tree var)
2035 {
2036   int i, j, access_count;
2037   struct access *res, **prev_acc_ptr = &res;
2038   vec<access_p> *access_vec;
2039   bool first = true;
2040   HOST_WIDE_INT low = -1, high = 0;
2041 
2042   access_vec = get_base_access_vector (var);
2043   if (!access_vec)
2044     return NULL;
2045   access_count = access_vec->length ();
2046 
2047   /* Sort by <OFFSET, SIZE>.  */
2048   access_vec->qsort (compare_access_positions);
2049 
2050   i = 0;
2051   while (i < access_count)
2052     {
2053       struct access *access = (*access_vec)[i];
2054       bool grp_write = access->write;
2055       bool grp_read = !access->write;
2056       bool grp_scalar_write = access->write
2057 	&& is_gimple_reg_type (access->type);
2058       bool grp_scalar_read = !access->write
2059 	&& is_gimple_reg_type (access->type);
2060       bool grp_assignment_read = access->grp_assignment_read;
2061       bool grp_assignment_write = access->grp_assignment_write;
2062       bool multiple_scalar_reads = false;
2063       bool grp_partial_lhs = access->grp_partial_lhs;
2064       bool first_scalar = is_gimple_reg_type (access->type);
2065       bool unscalarizable_region = access->grp_unscalarizable_region;
2066       bool grp_same_access_path = true;
2067       bool bf_non_full_precision
2068 	= (INTEGRAL_TYPE_P (access->type)
2069 	   && TYPE_PRECISION (access->type) != access->size
2070 	   && TREE_CODE (access->expr) == COMPONENT_REF
2071 	   && DECL_BIT_FIELD (TREE_OPERAND (access->expr, 1)));
2072 
2073       if (first || access->offset >= high)
2074 	{
2075 	  first = false;
2076 	  low = access->offset;
2077 	  high = access->offset + access->size;
2078 	}
2079       else if (access->offset > low && access->offset + access->size > high)
2080 	return NULL;
2081       else
2082 	gcc_assert (access->offset >= low
2083 		    && access->offset + access->size <= high);
2084 
2085       grp_same_access_path = path_comparable_for_same_access (access->expr);
2086 
2087       j = i + 1;
2088       while (j < access_count)
2089 	{
2090 	  struct access *ac2 = (*access_vec)[j];
2091 	  if (ac2->offset != access->offset || ac2->size != access->size)
2092 	    break;
2093 	  if (ac2->write)
2094 	    {
2095 	      grp_write = true;
2096 	      grp_scalar_write = (grp_scalar_write
2097 				  || is_gimple_reg_type (ac2->type));
2098 	    }
2099 	  else
2100 	    {
2101 	      grp_read = true;
2102 	      if (is_gimple_reg_type (ac2->type))
2103 		{
2104 		  if (grp_scalar_read)
2105 		    multiple_scalar_reads = true;
2106 		  else
2107 		    grp_scalar_read = true;
2108 		}
2109 	    }
2110 	  grp_assignment_read |= ac2->grp_assignment_read;
2111 	  grp_assignment_write |= ac2->grp_assignment_write;
2112 	  grp_partial_lhs |= ac2->grp_partial_lhs;
2113 	  unscalarizable_region |= ac2->grp_unscalarizable_region;
2114 	  relink_to_new_repr (access, ac2);
2115 
2116 	  /* If there are both aggregate-type and scalar-type accesses with
2117 	     this combination of size and offset, the comparison function
2118 	     should have put the scalars first.  */
2119 	  gcc_assert (first_scalar || !is_gimple_reg_type (ac2->type));
2120 	  /* It also prefers integral types to non-integral.  However, when the
2121 	     precision of the selected type does not span the entire area and
2122 	     should also be used for a non-integer (i.e. float), we must not
2123 	     let that happen.  Normally analyze_access_subtree expands the type
2124 	     to cover the entire area but for bit-fields it doesn't.  */
2125 	  if (bf_non_full_precision && !INTEGRAL_TYPE_P (ac2->type))
2126 	    {
2127 	      if (dump_file && (dump_flags & TDF_DETAILS))
2128 		{
2129 		  fprintf (dump_file, "Cannot scalarize the following access "
2130 			   "because insufficient precision integer type was "
2131 			   "selected.\n  ");
2132 		  dump_access (dump_file, access, false);
2133 		}
2134 	      unscalarizable_region = true;
2135 	    }
2136 
2137 	  if (grp_same_access_path
2138 	      && !same_access_path_p (access->expr, ac2->expr))
2139 	    grp_same_access_path = false;
2140 
2141 	  ac2->group_representative = access;
2142 	  j++;
2143 	}
2144 
2145       i = j;
2146 
2147       access->group_representative = access;
2148       access->grp_write = grp_write;
2149       access->grp_read = grp_read;
2150       access->grp_scalar_read = grp_scalar_read;
2151       access->grp_scalar_write = grp_scalar_write;
2152       access->grp_assignment_read = grp_assignment_read;
2153       access->grp_assignment_write = grp_assignment_write;
2154       access->grp_hint = multiple_scalar_reads && !constant_decl_p (var);
2155       access->grp_partial_lhs = grp_partial_lhs;
2156       access->grp_unscalarizable_region = unscalarizable_region;
2157       access->grp_same_access_path = grp_same_access_path;
2158 
2159       *prev_acc_ptr = access;
2160       prev_acc_ptr = &access->next_grp;
2161     }
2162 
2163   gcc_assert (res == (*access_vec)[0]);
2164   return res;
2165 }
2166 
2167 /* Create a variable for the given ACCESS which determines the type, name and a
2168    few other properties.  Return the variable declaration and store it also to
2169    ACCESS->replacement.  REG_TREE is used when creating a declaration to base a
2170    default-definition SSA name on in order to facilitate an uninitialized
2171    warning.  It is used instead of the actual ACCESS type if that is not of a
2172    gimple register type.  */
2173 
2174 static tree
2175 create_access_replacement (struct access *access, tree reg_type = NULL_TREE)
2176 {
2177   tree repl;
2178 
2179   tree type = access->type;
2180   if (reg_type && !is_gimple_reg_type (type))
2181     type = reg_type;
2182 
2183   if (access->grp_to_be_debug_replaced)
2184     {
2185       repl = create_tmp_var_raw (access->type);
2186       DECL_CONTEXT (repl) = current_function_decl;
2187     }
2188   else
2189     /* Drop any special alignment on the type if it's not on the main
2190        variant.  This avoids issues with weirdo ABIs like AAPCS.  */
2191     repl = create_tmp_var (build_qualified_type (TYPE_MAIN_VARIANT (type),
2192 						 TYPE_QUALS (type)), "SR");
2193   if (TREE_CODE (type) == COMPLEX_TYPE
2194       || TREE_CODE (type) == VECTOR_TYPE)
2195     {
2196       if (!access->grp_partial_lhs)
2197 	DECL_GIMPLE_REG_P (repl) = 1;
2198     }
2199   else if (access->grp_partial_lhs
2200 	   && is_gimple_reg_type (type))
2201     TREE_ADDRESSABLE (repl) = 1;
2202 
2203   DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base);
2204   DECL_ARTIFICIAL (repl) = 1;
2205   DECL_IGNORED_P (repl) = DECL_IGNORED_P (access->base);
2206 
2207   if (DECL_NAME (access->base)
2208       && !DECL_IGNORED_P (access->base)
2209       && !DECL_ARTIFICIAL (access->base))
2210     {
2211       char *pretty_name = make_fancy_name (access->expr);
2212       tree debug_expr = unshare_expr_without_location (access->expr), d;
2213       bool fail = false;
2214 
2215       DECL_NAME (repl) = get_identifier (pretty_name);
2216       DECL_NAMELESS (repl) = 1;
2217       obstack_free (&name_obstack, pretty_name);
2218 
2219       /* Get rid of any SSA_NAMEs embedded in debug_expr,
2220 	 as DECL_DEBUG_EXPR isn't considered when looking for still
2221 	 used SSA_NAMEs and thus they could be freed.  All debug info
2222 	 generation cares is whether something is constant or variable
2223 	 and that get_ref_base_and_extent works properly on the
2224 	 expression.  It cannot handle accesses at a non-constant offset
2225 	 though, so just give up in those cases.  */
2226       for (d = debug_expr;
2227 	   !fail && (handled_component_p (d) || TREE_CODE (d) == MEM_REF);
2228 	   d = TREE_OPERAND (d, 0))
2229 	switch (TREE_CODE (d))
2230 	  {
2231 	  case ARRAY_REF:
2232 	  case ARRAY_RANGE_REF:
2233 	    if (TREE_OPERAND (d, 1)
2234 		&& TREE_CODE (TREE_OPERAND (d, 1)) != INTEGER_CST)
2235 	      fail = true;
2236 	    if (TREE_OPERAND (d, 3)
2237 		&& TREE_CODE (TREE_OPERAND (d, 3)) != INTEGER_CST)
2238 	      fail = true;
2239 	    /* FALLTHRU */
2240 	  case COMPONENT_REF:
2241 	    if (TREE_OPERAND (d, 2)
2242 		&& TREE_CODE (TREE_OPERAND (d, 2)) != INTEGER_CST)
2243 	      fail = true;
2244 	    break;
2245 	  case MEM_REF:
2246 	    if (TREE_CODE (TREE_OPERAND (d, 0)) != ADDR_EXPR)
2247 	      fail = true;
2248 	    else
2249 	      d = TREE_OPERAND (d, 0);
2250 	    break;
2251 	  default:
2252 	    break;
2253 	  }
2254       if (!fail)
2255 	{
2256 	  SET_DECL_DEBUG_EXPR (repl, debug_expr);
2257 	  DECL_HAS_DEBUG_EXPR_P (repl) = 1;
2258 	}
2259       if (access->grp_no_warning)
2260 	TREE_NO_WARNING (repl) = 1;
2261       else
2262 	TREE_NO_WARNING (repl) = TREE_NO_WARNING (access->base);
2263     }
2264   else
2265     TREE_NO_WARNING (repl) = 1;
2266 
2267   if (dump_file)
2268     {
2269       if (access->grp_to_be_debug_replaced)
2270 	{
2271 	  fprintf (dump_file, "Created a debug-only replacement for ");
2272 	  print_generic_expr (dump_file, access->base);
2273 	  fprintf (dump_file, " offset: %u, size: %u\n",
2274 		   (unsigned) access->offset, (unsigned) access->size);
2275 	}
2276       else
2277 	{
2278 	  fprintf (dump_file, "Created a replacement for ");
2279 	  print_generic_expr (dump_file, access->base);
2280 	  fprintf (dump_file, " offset: %u, size: %u: ",
2281 		   (unsigned) access->offset, (unsigned) access->size);
2282 	  print_generic_expr (dump_file, repl, TDF_UID);
2283 	  fprintf (dump_file, "\n");
2284 	}
2285     }
2286   sra_stats.replacements++;
2287 
2288   return repl;
2289 }
2290 
2291 /* Return ACCESS scalar replacement, which must exist.  */
2292 
2293 static inline tree
get_access_replacement(struct access * access)2294 get_access_replacement (struct access *access)
2295 {
2296   gcc_checking_assert (access->replacement_decl);
2297   return access->replacement_decl;
2298 }
2299 
2300 
2301 /* Build a subtree of accesses rooted in *ACCESS, and move the pointer in the
2302    linked list along the way.  Stop when *ACCESS is NULL or the access pointed
2303    to it is not "within" the root.  Return false iff some accesses partially
2304    overlap.  */
2305 
2306 static bool
build_access_subtree(struct access ** access)2307 build_access_subtree (struct access **access)
2308 {
2309   struct access *root = *access, *last_child = NULL;
2310   HOST_WIDE_INT limit = root->offset + root->size;
2311 
2312   *access = (*access)->next_grp;
2313   while  (*access && (*access)->offset + (*access)->size <= limit)
2314     {
2315       if (!last_child)
2316 	root->first_child = *access;
2317       else
2318 	last_child->next_sibling = *access;
2319       last_child = *access;
2320       (*access)->parent = root;
2321       (*access)->grp_write |= root->grp_write;
2322 
2323       if (!build_access_subtree (access))
2324 	return false;
2325     }
2326 
2327   if (*access && (*access)->offset < limit)
2328     return false;
2329 
2330   return true;
2331 }
2332 
2333 /* Build a tree of access representatives, ACCESS is the pointer to the first
2334    one, others are linked in a list by the next_grp field.  Return false iff
2335    some accesses partially overlap.  */
2336 
2337 static bool
build_access_trees(struct access * access)2338 build_access_trees (struct access *access)
2339 {
2340   while (access)
2341     {
2342       struct access *root = access;
2343 
2344       if (!build_access_subtree (&access))
2345 	return false;
2346       root->next_grp = access;
2347     }
2348   return true;
2349 }
2350 
2351 /* Traverse the access forest where ROOT is the first root and verify that
2352    various important invariants hold true.  */
2353 
2354 DEBUG_FUNCTION void
verify_sra_access_forest(struct access * root)2355 verify_sra_access_forest (struct access *root)
2356 {
2357   struct access *access = root;
2358   tree first_base = root->base;
2359   gcc_assert (DECL_P (first_base));
2360   do
2361     {
2362       gcc_assert (access->base == first_base);
2363       if (access->parent)
2364 	gcc_assert (access->offset >= access->parent->offset
2365 		    && access->size <= access->parent->size);
2366       if (access->next_sibling)
2367 	gcc_assert (access->next_sibling->offset
2368 		    >= access->offset + access->size);
2369 
2370       poly_int64 poffset, psize, pmax_size;
2371       bool reverse;
2372       tree base = get_ref_base_and_extent (access->expr, &poffset, &psize,
2373 					   &pmax_size, &reverse);
2374       HOST_WIDE_INT offset, size, max_size;
2375       if (!poffset.is_constant (&offset)
2376 	  || !psize.is_constant (&size)
2377 	  || !pmax_size.is_constant (&max_size))
2378 	gcc_unreachable ();
2379       gcc_assert (base == first_base);
2380       gcc_assert (offset == access->offset);
2381       gcc_assert (access->grp_unscalarizable_region
2382 		  || access->grp_total_scalarization
2383 		  || size == max_size);
2384       gcc_assert (access->grp_unscalarizable_region
2385 		  || !is_gimple_reg_type (access->type)
2386 		  || size == access->size);
2387       gcc_assert (reverse == access->reverse);
2388 
2389       if (access->first_child)
2390 	{
2391 	  gcc_assert (access->first_child->parent == access);
2392 	  access = access->first_child;
2393 	}
2394       else if (access->next_sibling)
2395 	{
2396 	  gcc_assert (access->next_sibling->parent == access->parent);
2397 	  access = access->next_sibling;
2398 	}
2399       else
2400 	{
2401 	  while (access->parent && !access->next_sibling)
2402 	    access = access->parent;
2403 	  if (access->next_sibling)
2404 	    access = access->next_sibling;
2405 	  else
2406 	    {
2407 	      gcc_assert (access == root);
2408 	      root = root->next_grp;
2409 	      access = root;
2410 	    }
2411 	}
2412     }
2413   while (access);
2414 }
2415 
2416 /* Verify access forests of all candidates with accesses by calling
2417    verify_access_forest on each on them.  */
2418 
2419 DEBUG_FUNCTION void
verify_all_sra_access_forests(void)2420 verify_all_sra_access_forests (void)
2421 {
2422   bitmap_iterator bi;
2423   unsigned i;
2424   EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
2425     {
2426       tree var = candidate (i);
2427       struct access *access = get_first_repr_for_decl (var);
2428       if (access)
2429 	{
2430 	  gcc_assert (access->base == var);
2431 	  verify_sra_access_forest (access);
2432 	}
2433     }
2434 }
2435 
2436 /* Return true if expr contains some ARRAY_REFs into a variable bounded
2437    array.  */
2438 
2439 static bool
expr_with_var_bounded_array_refs_p(tree expr)2440 expr_with_var_bounded_array_refs_p (tree expr)
2441 {
2442   while (handled_component_p (expr))
2443     {
2444       if (TREE_CODE (expr) == ARRAY_REF
2445 	  && !tree_fits_shwi_p (array_ref_low_bound (expr)))
2446 	return true;
2447       expr = TREE_OPERAND (expr, 0);
2448     }
2449   return false;
2450 }
2451 
2452 /* Analyze the subtree of accesses rooted in ROOT, scheduling replacements when
2453    both seeming beneficial and when ALLOW_REPLACEMENTS allows it.  If TOTALLY
2454    is set, we are totally scalarizing the aggregate.  Also set all sorts of
2455    access flags appropriately along the way, notably always set grp_read and
2456    grp_assign_read according to MARK_READ and grp_write when MARK_WRITE is
2457    true.
2458 
2459    Creating a replacement for a scalar access is considered beneficial if its
2460    grp_hint ot TOTALLY is set (this means either that there is more than one
2461    direct read access or that we are attempting total scalarization) or
2462    according to the following table:
2463 
2464    Access written to through a scalar type (once or more times)
2465    |
2466    |	Written to in an assignment statement
2467    |	|
2468    |	|	Access read as scalar _once_
2469    |	|	|
2470    |   	|	|	Read in an assignment statement
2471    |	|	|	|
2472    |   	|	|	|	Scalarize	Comment
2473 -----------------------------------------------------------------------------
2474    0	0	0	0			No access for the scalar
2475    0	0	0	1			No access for the scalar
2476    0	0	1	0	No		Single read - won't help
2477    0	0	1	1	No		The same case
2478    0	1	0	0			No access for the scalar
2479    0	1	0	1			No access for the scalar
2480    0	1	1	0	Yes		s = *g; return s.i;
2481    0	1	1	1       Yes		The same case as above
2482    1	0	0	0	No		Won't help
2483    1	0	0	1	Yes		s.i = 1; *g = s;
2484    1	0	1	0	Yes		s.i = 5; g = s.i;
2485    1	0	1	1	Yes		The same case as above
2486    1	1	0	0	No		Won't help.
2487    1	1	0	1	Yes		s.i = 1; *g = s;
2488    1	1	1	0	Yes		s = *g; return s.i;
2489    1	1	1	1	Yes		Any of the above yeses  */
2490 
2491 static bool
analyze_access_subtree(struct access * root,struct access * parent,bool allow_replacements,bool totally)2492 analyze_access_subtree (struct access *root, struct access *parent,
2493 			bool allow_replacements, bool totally)
2494 {
2495   struct access *child;
2496   HOST_WIDE_INT limit = root->offset + root->size;
2497   HOST_WIDE_INT covered_to = root->offset;
2498   bool scalar = is_gimple_reg_type (root->type);
2499   bool hole = false, sth_created = false;
2500 
2501   if (parent)
2502     {
2503       if (parent->grp_read)
2504 	root->grp_read = 1;
2505       if (parent->grp_assignment_read)
2506 	root->grp_assignment_read = 1;
2507       if (parent->grp_write)
2508 	root->grp_write = 1;
2509       if (parent->grp_assignment_write)
2510 	root->grp_assignment_write = 1;
2511       if (!parent->grp_same_access_path)
2512 	root->grp_same_access_path = 0;
2513     }
2514 
2515   if (root->grp_unscalarizable_region)
2516     allow_replacements = false;
2517 
2518   if (allow_replacements && expr_with_var_bounded_array_refs_p (root->expr))
2519     allow_replacements = false;
2520 
2521   for (child = root->first_child; child; child = child->next_sibling)
2522     {
2523       hole |= covered_to < child->offset;
2524       sth_created |= analyze_access_subtree (child, root,
2525 					     allow_replacements && !scalar,
2526 					     totally);
2527 
2528       root->grp_unscalarized_data |= child->grp_unscalarized_data;
2529       if (child->grp_covered)
2530 	covered_to += child->size;
2531       else
2532 	hole = true;
2533     }
2534 
2535   if (allow_replacements && scalar && !root->first_child
2536       && (totally || !root->grp_total_scalarization)
2537       && (totally
2538 	  || root->grp_hint
2539 	  || ((root->grp_scalar_read || root->grp_assignment_read)
2540 	      && (root->grp_scalar_write || root->grp_assignment_write))))
2541     {
2542       /* Always create access replacements that cover the whole access.
2543          For integral types this means the precision has to match.
2544 	 Avoid assumptions based on the integral type kind, too.  */
2545       if (INTEGRAL_TYPE_P (root->type)
2546 	  && (TREE_CODE (root->type) != INTEGER_TYPE
2547 	      || TYPE_PRECISION (root->type) != root->size)
2548 	  /* But leave bitfield accesses alone.  */
2549 	  && (TREE_CODE (root->expr) != COMPONENT_REF
2550 	      || !DECL_BIT_FIELD (TREE_OPERAND (root->expr, 1))))
2551 	{
2552 	  tree rt = root->type;
2553 	  gcc_assert ((root->offset % BITS_PER_UNIT) == 0
2554 		      && (root->size % BITS_PER_UNIT) == 0);
2555 	  root->type = build_nonstandard_integer_type (root->size,
2556 						       TYPE_UNSIGNED (rt));
2557 	  root->expr = build_ref_for_offset (UNKNOWN_LOCATION, root->base,
2558 					     root->offset, root->reverse,
2559 					     root->type, NULL, false);
2560 
2561 	  if (dump_file && (dump_flags & TDF_DETAILS))
2562 	    {
2563 	      fprintf (dump_file, "Changing the type of a replacement for ");
2564 	      print_generic_expr (dump_file, root->base);
2565 	      fprintf (dump_file, " offset: %u, size: %u ",
2566 		       (unsigned) root->offset, (unsigned) root->size);
2567 	      fprintf (dump_file, " to an integer.\n");
2568 	    }
2569 	}
2570 
2571       root->grp_to_be_replaced = 1;
2572       root->replacement_decl = create_access_replacement (root);
2573       sth_created = true;
2574       hole = false;
2575     }
2576   else
2577     {
2578       if (allow_replacements
2579 	  && scalar && !root->first_child
2580 	  && !root->grp_total_scalarization
2581 	  && (root->grp_scalar_write || root->grp_assignment_write)
2582 	  && !bitmap_bit_p (cannot_scalarize_away_bitmap,
2583 			    DECL_UID (root->base)))
2584 	{
2585 	  gcc_checking_assert (!root->grp_scalar_read
2586 			       && !root->grp_assignment_read);
2587 	  sth_created = true;
2588 	  if (MAY_HAVE_DEBUG_BIND_STMTS)
2589 	    {
2590 	      root->grp_to_be_debug_replaced = 1;
2591 	      root->replacement_decl = create_access_replacement (root);
2592 	    }
2593 	}
2594 
2595       if (covered_to < limit)
2596 	hole = true;
2597       if (scalar || !allow_replacements)
2598 	root->grp_total_scalarization = 0;
2599     }
2600 
2601   if (!hole || totally)
2602     root->grp_covered = 1;
2603   else if (root->grp_write || comes_initialized_p (root->base))
2604     root->grp_unscalarized_data = 1; /* not covered and written to */
2605   return sth_created;
2606 }
2607 
2608 /* Analyze all access trees linked by next_grp by the means of
2609    analyze_access_subtree.  */
2610 static bool
analyze_access_trees(struct access * access)2611 analyze_access_trees (struct access *access)
2612 {
2613   bool ret = false;
2614 
2615   while (access)
2616     {
2617       if (analyze_access_subtree (access, NULL, true,
2618 				  access->grp_total_scalarization))
2619 	ret = true;
2620       access = access->next_grp;
2621     }
2622 
2623   return ret;
2624 }
2625 
2626 /* Return true iff a potential new child of ACC at offset OFFSET and with size
2627    SIZE would conflict with an already existing one.  If exactly such a child
2628    already exists in ACC, store a pointer to it in EXACT_MATCH.  */
2629 
2630 static bool
child_would_conflict_in_acc(struct access * acc,HOST_WIDE_INT norm_offset,HOST_WIDE_INT size,struct access ** exact_match)2631 child_would_conflict_in_acc (struct access *acc, HOST_WIDE_INT norm_offset,
2632 			      HOST_WIDE_INT size, struct access **exact_match)
2633 {
2634   struct access *child;
2635 
2636   for (child = acc->first_child; child; child = child->next_sibling)
2637     {
2638       if (child->offset == norm_offset && child->size == size)
2639 	{
2640 	  *exact_match = child;
2641 	  return true;
2642 	}
2643 
2644       if (child->offset < norm_offset + size
2645 	  && child->offset + child->size > norm_offset)
2646 	return true;
2647     }
2648 
2649   return false;
2650 }
2651 
2652 /* Create a new child access of PARENT, with all properties just like MODEL
2653    except for its offset and with its grp_write false and grp_read true.
2654    Return the new access or NULL if it cannot be created.  Note that this
2655    access is created long after all splicing and sorting, it's not located in
2656    any access vector and is automatically a representative of its group.  Set
2657    the gpr_write flag of the new accesss if SET_GRP_WRITE is true.  */
2658 
2659 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)2660 create_artificial_child_access (struct access *parent, struct access *model,
2661 				HOST_WIDE_INT new_offset,
2662 				bool set_grp_read, bool set_grp_write)
2663 {
2664   struct access **child;
2665   tree expr = parent->base;
2666 
2667   gcc_assert (!model->grp_unscalarizable_region);
2668 
2669   struct access *access = access_pool.allocate ();
2670   memset (access, 0, sizeof (struct access));
2671   if (!build_user_friendly_ref_for_offset (&expr, TREE_TYPE (expr), new_offset,
2672 					   model->type))
2673     {
2674       access->grp_no_warning = true;
2675       expr = build_ref_for_model (EXPR_LOCATION (parent->base), parent->base,
2676 				  new_offset, model, NULL, false);
2677     }
2678 
2679   access->base = parent->base;
2680   access->expr = expr;
2681   access->offset = new_offset;
2682   access->size = model->size;
2683   access->type = model->type;
2684   access->parent = parent;
2685   access->grp_read = set_grp_read;
2686   access->grp_write = set_grp_write;
2687   access->reverse = model->reverse;
2688 
2689   child = &parent->first_child;
2690   while (*child && (*child)->offset < new_offset)
2691     child = &(*child)->next_sibling;
2692 
2693   access->next_sibling = *child;
2694   *child = access;
2695 
2696   return access;
2697 }
2698 
2699 
2700 /* Beginning with ACCESS, traverse its whole access subtree and mark all
2701    sub-trees as written to.  If any of them has not been marked so previously
2702    and has assignment links leading from it, re-enqueue it.  */
2703 
2704 static void
subtree_mark_written_and_rhs_enqueue(struct access * access)2705 subtree_mark_written_and_rhs_enqueue (struct access *access)
2706 {
2707   if (access->grp_write)
2708     return;
2709   access->grp_write = true;
2710   add_access_to_rhs_work_queue (access);
2711 
2712   struct access *child;
2713   for (child = access->first_child; child; child = child->next_sibling)
2714     subtree_mark_written_and_rhs_enqueue (child);
2715 }
2716 
2717 /* If there is still budget to create a propagation access for DECL, return
2718    true and decrement the budget.  Otherwise return false.  */
2719 
2720 static bool
budget_for_propagation_access(tree decl)2721 budget_for_propagation_access (tree decl)
2722 {
2723   unsigned b, *p = propagation_budget->get (decl);
2724   if (p)
2725     b = *p;
2726   else
2727     b = param_sra_max_propagations;
2728 
2729   if (b == 0)
2730     return false;
2731   b--;
2732 
2733   if (b == 0 && dump_file && (dump_flags & TDF_DETAILS))
2734     {
2735       fprintf (dump_file, "The propagation budget of ");
2736       print_generic_expr (dump_file, decl);
2737       fprintf (dump_file, " (UID: %u) has been exhausted.\n", DECL_UID (decl));
2738     }
2739   propagation_budget->put (decl, b);
2740   return true;
2741 }
2742 
2743 /* Return true if ACC or any of its subaccesses has grp_child set.  */
2744 
2745 static bool
access_or_its_child_written(struct access * acc)2746 access_or_its_child_written (struct access *acc)
2747 {
2748   if (acc->grp_write)
2749     return true;
2750   for (struct access *sub = acc->first_child; sub; sub = sub->next_sibling)
2751     if (access_or_its_child_written (sub))
2752       return true;
2753   return false;
2754 }
2755 
2756 /* Propagate subaccesses and grp_write flags of RACC across an assignment link
2757    to LACC.  Enqueue sub-accesses as necessary so that the write flag is
2758    propagated transitively.  Return true if anything changed.  Additionally, if
2759    RACC is a scalar access but LACC is not, change the type of the latter, if
2760    possible.  */
2761 
2762 static bool
propagate_subaccesses_from_rhs(struct access * lacc,struct access * racc)2763 propagate_subaccesses_from_rhs (struct access *lacc, struct access *racc)
2764 {
2765   struct access *rchild;
2766   HOST_WIDE_INT norm_delta = lacc->offset - racc->offset;
2767   bool ret = false;
2768 
2769   /* IF the LHS is still not marked as being written to, we only need to do so
2770      if the RHS at this level actually was.  */
2771   if (!lacc->grp_write)
2772     {
2773       gcc_checking_assert (!comes_initialized_p (racc->base));
2774       if (racc->grp_write)
2775 	{
2776 	  subtree_mark_written_and_rhs_enqueue (lacc);
2777 	  ret = true;
2778 	}
2779     }
2780 
2781   if (is_gimple_reg_type (lacc->type)
2782       || lacc->grp_unscalarizable_region
2783       || racc->grp_unscalarizable_region)
2784     {
2785       if (!lacc->grp_write)
2786 	{
2787 	  ret = true;
2788 	  subtree_mark_written_and_rhs_enqueue (lacc);
2789 	}
2790       return ret;
2791     }
2792 
2793   if (is_gimple_reg_type (racc->type))
2794     {
2795       if (!lacc->grp_write)
2796 	{
2797 	  ret = true;
2798 	  subtree_mark_written_and_rhs_enqueue (lacc);
2799 	}
2800       if (!lacc->first_child && !racc->first_child)
2801 	{
2802 	  tree t = lacc->base;
2803 
2804 	  lacc->type = racc->type;
2805 	  if (build_user_friendly_ref_for_offset (&t, TREE_TYPE (t),
2806 						  lacc->offset, racc->type))
2807 	    {
2808 	      lacc->expr = t;
2809 	      lacc->grp_same_access_path = true;
2810 	    }
2811 	  else
2812 	    {
2813 	      lacc->expr = build_ref_for_model (EXPR_LOCATION (lacc->base),
2814 						lacc->base, lacc->offset,
2815 						racc, NULL, false);
2816 	      lacc->grp_no_warning = true;
2817 	      lacc->grp_same_access_path = false;
2818 	    }
2819 	}
2820       return ret;
2821     }
2822 
2823   for (rchild = racc->first_child; rchild; rchild = rchild->next_sibling)
2824     {
2825       struct access *new_acc = NULL;
2826       HOST_WIDE_INT norm_offset = rchild->offset + norm_delta;
2827 
2828       if (child_would_conflict_in_acc (lacc, norm_offset, rchild->size,
2829 					&new_acc))
2830 	{
2831 	  if (new_acc)
2832 	    {
2833 	      if (!new_acc->grp_write && rchild->grp_write)
2834 		{
2835 		  gcc_assert (!lacc->grp_write);
2836 		  subtree_mark_written_and_rhs_enqueue (new_acc);
2837 		  ret = true;
2838 		}
2839 
2840 	      rchild->grp_hint = 1;
2841 	      new_acc->grp_hint |= new_acc->grp_read;
2842 	      if (rchild->first_child
2843 		  && propagate_subaccesses_from_rhs (new_acc, rchild))
2844 		{
2845 		  ret = 1;
2846 		  add_access_to_rhs_work_queue (new_acc);
2847 		}
2848 	    }
2849 	  else
2850 	    {
2851 	      if (!lacc->grp_write)
2852 		{
2853 		  ret = true;
2854 		  subtree_mark_written_and_rhs_enqueue (lacc);
2855 		}
2856 	    }
2857 	  continue;
2858 	}
2859 
2860       if (rchild->grp_unscalarizable_region
2861 	  || !budget_for_propagation_access (lacc->base))
2862 	{
2863 	  if (!lacc->grp_write && access_or_its_child_written (rchild))
2864 	    {
2865 	      ret = true;
2866 	      subtree_mark_written_and_rhs_enqueue (lacc);
2867 	    }
2868 	  continue;
2869 	}
2870 
2871       rchild->grp_hint = 1;
2872       /* Because get_ref_base_and_extent always includes padding in size for
2873 	 accesses to DECLs but not necessarily for COMPONENT_REFs of the same
2874 	 type, we might be actually attempting to here to create a child of the
2875 	 same type as the parent.  */
2876       if (!types_compatible_p (lacc->type, rchild->type))
2877 	new_acc = create_artificial_child_access (lacc, rchild, norm_offset,
2878 						  false,
2879 						  (lacc->grp_write
2880 						   || rchild->grp_write));
2881       else
2882 	new_acc = lacc;
2883       gcc_checking_assert (new_acc);
2884       if (racc->first_child)
2885 	propagate_subaccesses_from_rhs (new_acc, rchild);
2886 
2887       add_access_to_rhs_work_queue (lacc);
2888       ret = true;
2889     }
2890 
2891   return ret;
2892 }
2893 
2894 /* Propagate subaccesses of LACC across an assignment link to RACC if they
2895    should inhibit total scalarization of the corresponding area.  No flags are
2896    being propagated in the process.  Return true if anything changed.  */
2897 
2898 static bool
propagate_subaccesses_from_lhs(struct access * lacc,struct access * racc)2899 propagate_subaccesses_from_lhs (struct access *lacc, struct access *racc)
2900 {
2901   if (is_gimple_reg_type (racc->type)
2902       || lacc->grp_unscalarizable_region
2903       || racc->grp_unscalarizable_region)
2904     return false;
2905 
2906   /* TODO: Do we want set some new racc flag to stop potential total
2907      scalarization if lacc is a scalar access (and none fo the two have
2908      children)?  */
2909 
2910   bool ret = false;
2911   HOST_WIDE_INT norm_delta = racc->offset - lacc->offset;
2912   for (struct access *lchild = lacc->first_child;
2913        lchild;
2914        lchild = lchild->next_sibling)
2915     {
2916       struct access *matching_acc = NULL;
2917       HOST_WIDE_INT norm_offset = lchild->offset + norm_delta;
2918 
2919       if (lchild->grp_unscalarizable_region
2920 	  || child_would_conflict_in_acc (racc, norm_offset, lchild->size,
2921 					  &matching_acc)
2922 	  || !budget_for_propagation_access (racc->base))
2923 	{
2924 	  if (matching_acc
2925 	      && propagate_subaccesses_from_lhs (lchild, matching_acc))
2926 	    add_access_to_lhs_work_queue (matching_acc);
2927 	  continue;
2928 	}
2929 
2930       /* Because get_ref_base_and_extent always includes padding in size for
2931 	 accesses to DECLs but not necessarily for COMPONENT_REFs of the same
2932 	 type, we might be actually attempting to here to create a child of the
2933 	 same type as the parent.  */
2934       if (!types_compatible_p (racc->type, lchild->type))
2935 	{
2936 	  struct access *new_acc
2937 	    = create_artificial_child_access (racc, lchild, norm_offset,
2938 					      true, false);
2939 	  propagate_subaccesses_from_lhs (lchild, new_acc);
2940 	}
2941       else
2942 	propagate_subaccesses_from_lhs (lchild, racc);
2943       ret = true;
2944     }
2945   return ret;
2946 }
2947 
2948 /* Propagate all subaccesses across assignment links.  */
2949 
2950 static void
propagate_all_subaccesses(void)2951 propagate_all_subaccesses (void)
2952 {
2953   propagation_budget = new hash_map<tree, unsigned>;
2954   while (rhs_work_queue_head)
2955     {
2956       struct access *racc = pop_access_from_rhs_work_queue ();
2957       struct assign_link *link;
2958 
2959       if (racc->group_representative)
2960 	racc= racc->group_representative;
2961       gcc_assert (racc->first_rhs_link);
2962 
2963       for (link = racc->first_rhs_link; link; link = link->next_rhs)
2964 	{
2965 	  struct access *lacc = link->lacc;
2966 
2967 	  if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
2968 	    continue;
2969 	  lacc = lacc->group_representative;
2970 
2971 	  bool reque_parents = false;
2972 	  if (!bitmap_bit_p (candidate_bitmap, DECL_UID (racc->base)))
2973 	    {
2974 	      if (!lacc->grp_write)
2975 		{
2976 		  subtree_mark_written_and_rhs_enqueue (lacc);
2977 		  reque_parents = true;
2978 		}
2979 	    }
2980 	  else if (propagate_subaccesses_from_rhs (lacc, racc))
2981 	    reque_parents = true;
2982 
2983 	  if (reque_parents)
2984 	    do
2985 	      {
2986 		add_access_to_rhs_work_queue (lacc);
2987 		lacc = lacc->parent;
2988 	      }
2989 	    while (lacc);
2990 	}
2991     }
2992 
2993   while (lhs_work_queue_head)
2994     {
2995       struct access *lacc = pop_access_from_lhs_work_queue ();
2996       struct assign_link *link;
2997 
2998       if (lacc->group_representative)
2999 	lacc = lacc->group_representative;
3000       gcc_assert (lacc->first_lhs_link);
3001 
3002       if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
3003 	continue;
3004 
3005       for (link = lacc->first_lhs_link; link; link = link->next_lhs)
3006 	{
3007 	  struct access *racc = link->racc;
3008 
3009 	  if (racc->group_representative)
3010 	    racc = racc->group_representative;
3011 	  if (!bitmap_bit_p (candidate_bitmap, DECL_UID (racc->base)))
3012 	    continue;
3013 	  if (propagate_subaccesses_from_lhs (lacc, racc))
3014 	    add_access_to_lhs_work_queue (racc);
3015 	}
3016     }
3017   delete propagation_budget;
3018 }
3019 
3020 /* Return true if the forest beginning with ROOT does not contain
3021    unscalarizable regions or non-byte aligned accesses.  */
3022 
3023 static bool
can_totally_scalarize_forest_p(struct access * root)3024 can_totally_scalarize_forest_p (struct access *root)
3025 {
3026   struct access *access = root;
3027   do
3028     {
3029       if (access->grp_unscalarizable_region
3030 	  || (access->offset % BITS_PER_UNIT) != 0
3031 	  || (access->size % BITS_PER_UNIT) != 0
3032 	  || (is_gimple_reg_type (access->type)
3033 	      && access->first_child))
3034 	return false;
3035 
3036       if (access->first_child)
3037 	access = access->first_child;
3038       else if (access->next_sibling)
3039 	access = access->next_sibling;
3040       else
3041 	{
3042 	  while (access->parent && !access->next_sibling)
3043 	    access = access->parent;
3044 	  if (access->next_sibling)
3045 	    access = access->next_sibling;
3046 	  else
3047 	    {
3048 	      gcc_assert (access == root);
3049 	      root = root->next_grp;
3050 	      access = root;
3051 	    }
3052 	}
3053     }
3054   while (access);
3055   return true;
3056 }
3057 
3058 /* Create and return an ACCESS in PARENT spanning from POS with SIZE, TYPE and
3059    reference EXPR for total scalarization purposes and mark it as such.  Within
3060    the children of PARENT, link it in between PTR and NEXT_SIBLING.  */
3061 
3062 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)3063 create_total_scalarization_access (struct access *parent, HOST_WIDE_INT pos,
3064 				   HOST_WIDE_INT size, tree type, tree expr,
3065 				   struct access **ptr,
3066 				   struct access *next_sibling)
3067 {
3068   struct access *access = access_pool.allocate ();
3069   memset (access, 0, sizeof (struct access));
3070   access->base = parent->base;
3071   access->offset = pos;
3072   access->size = size;
3073   access->expr = expr;
3074   access->type = type;
3075   access->parent = parent;
3076   access->grp_write = parent->grp_write;
3077   access->grp_total_scalarization = 1;
3078   access->grp_hint = 1;
3079   access->grp_same_access_path = path_comparable_for_same_access (expr);
3080   access->reverse = reverse_storage_order_for_component_p (expr);
3081 
3082   access->next_sibling = next_sibling;
3083   *ptr = access;
3084   return access;
3085 }
3086 
3087 /* Create and return an ACCESS in PARENT spanning from POS with SIZE, TYPE and
3088    reference EXPR for total scalarization purposes and mark it as such, link it
3089    at *PTR and reshape the tree so that those elements at *PTR and their
3090    siblings which fall within the part described by POS and SIZE are moved to
3091    be children of the new access.  If a partial overlap is detected, return
3092    NULL.  */
3093 
3094 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)3095 create_total_access_and_reshape (struct access *parent, HOST_WIDE_INT pos,
3096 				 HOST_WIDE_INT size, tree type, tree expr,
3097 				 struct access **ptr)
3098 {
3099   struct access **p = ptr;
3100 
3101   while (*p && (*p)->offset < pos + size)
3102     {
3103       if ((*p)->offset + (*p)->size > pos + size)
3104 	return NULL;
3105       p = &(*p)->next_sibling;
3106     }
3107 
3108   struct access *next_child = *ptr;
3109   struct access *new_acc
3110     = create_total_scalarization_access (parent, pos, size, type, expr,
3111 					 ptr, *p);
3112   if (p != ptr)
3113     {
3114       new_acc->first_child = next_child;
3115       *p = NULL;
3116       for (struct access *a = next_child; a; a = a->next_sibling)
3117 	a->parent = new_acc;
3118     }
3119   return new_acc;
3120 }
3121 
3122 static bool totally_scalarize_subtree (struct access *root);
3123 
3124 /* Return true if INNER is either the same type as OUTER or if it is the type
3125    of a record field in OUTER at offset zero, possibly in nested
3126    sub-records.  */
3127 
3128 static bool
access_and_field_type_match_p(tree outer,tree inner)3129 access_and_field_type_match_p (tree outer, tree inner)
3130 {
3131   if (TYPE_MAIN_VARIANT (outer) == TYPE_MAIN_VARIANT (inner))
3132     return true;
3133   if (TREE_CODE (outer) != RECORD_TYPE)
3134     return false;
3135   tree fld = TYPE_FIELDS (outer);
3136   while (fld)
3137     {
3138      if (TREE_CODE (fld) == FIELD_DECL)
3139        {
3140 	if (!zerop (DECL_FIELD_OFFSET (fld)))
3141 	  return false;
3142 	if (TYPE_MAIN_VARIANT (TREE_TYPE (fld)) == inner)
3143 	  return true;
3144 	if (TREE_CODE (TREE_TYPE (fld)) == RECORD_TYPE)
3145 	  fld = TYPE_FIELDS (TREE_TYPE (fld));
3146 	else
3147 	  return false;
3148        }
3149      else
3150        fld = DECL_CHAIN (fld);
3151     }
3152   return false;
3153 }
3154 
3155 /* Return type of total_should_skip_creating_access indicating whether a total
3156    scalarization access for a field/element should be created, whether it
3157    already exists or whether the entire total scalarization has to fail.  */
3158 
3159 enum total_sra_field_state {TOTAL_FLD_CREATE, TOTAL_FLD_DONE, TOTAL_FLD_FAILED};
3160 
3161 /* Do all the necessary steps in total scalarization when the given aggregate
3162    type has a TYPE at POS with the given SIZE should be put into PARENT and
3163    when we have processed all its siblings with smaller offsets up until and
3164    including LAST_SEEN_SIBLING (which can be NULL).
3165 
3166    If some further siblings are to be skipped, set *LAST_SEEN_SIBLING as
3167    appropriate.  Return TOTAL_FLD_CREATE id the caller should carry on with
3168    creating a new access, TOTAL_FLD_DONE if access or accesses capable of
3169    representing the described part of the aggregate for the purposes of total
3170    scalarization already exist or TOTAL_FLD_FAILED if there is a problem which
3171    prevents total scalarization from happening at all.  */
3172 
3173 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)3174 total_should_skip_creating_access (struct access *parent,
3175 				   struct access **last_seen_sibling,
3176 				   tree type, HOST_WIDE_INT pos,
3177 				   HOST_WIDE_INT size)
3178 {
3179   struct access *next_child;
3180   if (!*last_seen_sibling)
3181     next_child = parent->first_child;
3182   else
3183     next_child = (*last_seen_sibling)->next_sibling;
3184 
3185   /* First, traverse the chain of siblings until it points to an access with
3186      offset at least equal to POS.  Check all skipped accesses whether they
3187      span the POS boundary and if so, return with a failure.  */
3188   while (next_child && next_child->offset < pos)
3189     {
3190       if (next_child->offset + next_child->size > pos)
3191 	return TOTAL_FLD_FAILED;
3192       *last_seen_sibling = next_child;
3193       next_child = next_child->next_sibling;
3194     }
3195 
3196   /* Now check whether next_child has exactly the right POS and SIZE and if so,
3197      whether it can represent what we need and can be totally scalarized
3198      itself.  */
3199   if (next_child && next_child->offset == pos
3200       && next_child->size == size)
3201     {
3202       if (!is_gimple_reg_type (next_child->type)
3203 	  && (!access_and_field_type_match_p (type, next_child->type)
3204 	      || !totally_scalarize_subtree (next_child)))
3205 	return TOTAL_FLD_FAILED;
3206 
3207       *last_seen_sibling = next_child;
3208       return TOTAL_FLD_DONE;
3209     }
3210 
3211   /* If the child we're looking at would partially overlap, we just cannot
3212      totally scalarize.  */
3213   if (next_child
3214       && next_child->offset < pos + size
3215       && next_child->offset + next_child->size > pos + size)
3216     return TOTAL_FLD_FAILED;
3217 
3218   if (is_gimple_reg_type (type))
3219     {
3220       /* We don't scalarize accesses that are children of other scalar type
3221 	 accesses, so if we go on and create an access for a register type,
3222 	 there should not be any pre-existing children.  There are rare cases
3223 	 where the requested type is a vector but we already have register
3224 	 accesses for all its elements which is equally good.  Detect that
3225 	 situation or whether we need to bail out.  */
3226 
3227       HOST_WIDE_INT covered = pos;
3228       bool skipping = false;
3229       while (next_child
3230 	     && next_child->offset + next_child->size <= pos + size)
3231 	{
3232 	  if (next_child->offset != covered
3233 	      || !is_gimple_reg_type (next_child->type))
3234 	    return TOTAL_FLD_FAILED;
3235 
3236 	  covered += next_child->size;
3237 	  *last_seen_sibling = next_child;
3238 	  next_child = next_child->next_sibling;
3239 	  skipping = true;
3240 	}
3241 
3242       if (skipping)
3243 	{
3244 	  if (covered != pos + size)
3245 	    return TOTAL_FLD_FAILED;
3246 	  else
3247 	    return TOTAL_FLD_DONE;
3248 	}
3249     }
3250 
3251   return TOTAL_FLD_CREATE;
3252 }
3253 
3254 /* Go over sub-tree rooted in ROOT and attempt to create scalar accesses
3255    spanning all uncovered areas covered by ROOT, return false if the attempt
3256    failed.  All created accesses will have grp_unscalarizable_region set (and
3257    should be ignored if the function returns false).  */
3258 
3259 static bool
totally_scalarize_subtree(struct access * root)3260 totally_scalarize_subtree (struct access *root)
3261 {
3262   gcc_checking_assert (!root->grp_unscalarizable_region);
3263   gcc_checking_assert (!is_gimple_reg_type (root->type));
3264 
3265   struct access *last_seen_sibling = NULL;
3266 
3267   switch (TREE_CODE (root->type))
3268     {
3269     case RECORD_TYPE:
3270       for (tree fld = TYPE_FIELDS (root->type); fld; fld = DECL_CHAIN (fld))
3271 	if (TREE_CODE (fld) == FIELD_DECL)
3272 	  {
3273 	    tree ft = TREE_TYPE (fld);
3274 	    HOST_WIDE_INT fsize = tree_to_uhwi (DECL_SIZE (fld));
3275 	    if (!fsize)
3276 	      continue;
3277 
3278 	    HOST_WIDE_INT pos = root->offset + int_bit_position (fld);
3279 	    if (pos + fsize > root->offset + root->size)
3280 	      return false;
3281 	    enum total_sra_field_state
3282 	      state = total_should_skip_creating_access (root,
3283 							 &last_seen_sibling,
3284 							 ft, pos, fsize);
3285 	    switch (state)
3286 	      {
3287 	      case TOTAL_FLD_FAILED:
3288 		return false;
3289 	      case TOTAL_FLD_DONE:
3290 		continue;
3291 	      case TOTAL_FLD_CREATE:
3292 		break;
3293 	      default:
3294 		gcc_unreachable ();
3295 	      }
3296 
3297 	    struct access **p = (last_seen_sibling
3298 				 ? &last_seen_sibling->next_sibling
3299 				 : &root->first_child);
3300 	    tree nref = build3 (COMPONENT_REF, ft, root->expr, fld, NULL_TREE);
3301 	    struct access *new_child
3302 	      = create_total_access_and_reshape (root, pos, fsize, ft, nref, p);
3303 	    if (!new_child)
3304 	      return false;
3305 
3306 	    if (!is_gimple_reg_type (ft)
3307 		&& !totally_scalarize_subtree (new_child))
3308 	      return false;
3309 	    last_seen_sibling = new_child;
3310 	  }
3311       break;
3312     case ARRAY_TYPE:
3313       {
3314 	tree elemtype = TREE_TYPE (root->type);
3315 	tree elem_size = TYPE_SIZE (elemtype);
3316 	gcc_assert (elem_size && tree_fits_shwi_p (elem_size));
3317 	HOST_WIDE_INT el_size = tree_to_shwi (elem_size);
3318 	gcc_assert (el_size > 0);
3319 
3320 	tree minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (root->type));
3321 	gcc_assert (TREE_CODE (minidx) == INTEGER_CST);
3322 	tree maxidx = TYPE_MAX_VALUE (TYPE_DOMAIN (root->type));
3323 	/* Skip (some) zero-length arrays; others have MAXIDX == MINIDX - 1.  */
3324 	if (!maxidx)
3325 	  goto out;
3326 	gcc_assert (TREE_CODE (maxidx) == INTEGER_CST);
3327 	tree domain = TYPE_DOMAIN (root->type);
3328 	/* MINIDX and MAXIDX are inclusive, and must be interpreted in
3329 	   DOMAIN (e.g. signed int, whereas min/max may be size_int).  */
3330 	offset_int idx = wi::to_offset (minidx);
3331 	offset_int max = wi::to_offset (maxidx);
3332 	if (!TYPE_UNSIGNED (domain))
3333 	  {
3334 	    idx = wi::sext (idx, TYPE_PRECISION (domain));
3335 	    max = wi::sext (max, TYPE_PRECISION (domain));
3336 	  }
3337 	for (HOST_WIDE_INT pos = root->offset;
3338 	     idx <= max;
3339 	     pos += el_size, ++idx)
3340 	  {
3341 	    enum total_sra_field_state
3342 	      state = total_should_skip_creating_access (root,
3343 							 &last_seen_sibling,
3344 							 elemtype, pos,
3345 							 el_size);
3346 	    switch (state)
3347 	      {
3348 	      case TOTAL_FLD_FAILED:
3349 		return false;
3350 	      case TOTAL_FLD_DONE:
3351 		continue;
3352 	      case TOTAL_FLD_CREATE:
3353 		break;
3354 	      default:
3355 		gcc_unreachable ();
3356 	      }
3357 
3358 	    struct access **p = (last_seen_sibling
3359 				 ? &last_seen_sibling->next_sibling
3360 				 : &root->first_child);
3361 	    tree nref = build4 (ARRAY_REF, elemtype, root->expr,
3362 				wide_int_to_tree (domain, idx),
3363 				NULL_TREE, NULL_TREE);
3364 	    struct access *new_child
3365 	      = create_total_access_and_reshape (root, pos, el_size, elemtype,
3366 						 nref, p);
3367 	    if (!new_child)
3368 	      return false;
3369 
3370 	    if (!is_gimple_reg_type (elemtype)
3371 		&& !totally_scalarize_subtree (new_child))
3372 	      return false;
3373 	    last_seen_sibling = new_child;
3374 	  }
3375       }
3376       break;
3377     default:
3378       gcc_unreachable ();
3379     }
3380 
3381  out:
3382   return true;
3383 }
3384 
3385 /* Go through all accesses collected throughout the (intraprocedural) analysis
3386    stage, exclude overlapping ones, identify representatives and build trees
3387    out of them, making decisions about scalarization on the way.  Return true
3388    iff there are any to-be-scalarized variables after this stage. */
3389 
3390 static bool
analyze_all_variable_accesses(void)3391 analyze_all_variable_accesses (void)
3392 {
3393   int res = 0;
3394   bitmap tmp = BITMAP_ALLOC (NULL);
3395   bitmap_iterator bi;
3396   unsigned i;
3397 
3398   bitmap_copy (tmp, candidate_bitmap);
3399   EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
3400     {
3401       tree var = candidate (i);
3402       struct access *access;
3403 
3404       access = sort_and_splice_var_accesses (var);
3405       if (!access || !build_access_trees (access))
3406 	disqualify_candidate (var,
3407 			      "No or inhibitingly overlapping accesses.");
3408     }
3409 
3410   propagate_all_subaccesses ();
3411 
3412   bool optimize_speed_p = !optimize_function_for_size_p (cfun);
3413   /* If the user didn't set PARAM_SRA_MAX_SCALARIZATION_SIZE_<...>,
3414      fall back to a target default.  */
3415   unsigned HOST_WIDE_INT max_scalarization_size
3416     = get_move_ratio (optimize_speed_p) * UNITS_PER_WORD;
3417 
3418   if (optimize_speed_p)
3419     {
3420       if (global_options_set.x_param_sra_max_scalarization_size_speed)
3421 	max_scalarization_size = param_sra_max_scalarization_size_speed;
3422     }
3423   else
3424     {
3425       if (global_options_set.x_param_sra_max_scalarization_size_size)
3426 	max_scalarization_size = param_sra_max_scalarization_size_size;
3427     }
3428   max_scalarization_size *= BITS_PER_UNIT;
3429 
3430   EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
3431     if (bitmap_bit_p (should_scalarize_away_bitmap, i)
3432 	&& !bitmap_bit_p (cannot_scalarize_away_bitmap, i))
3433       {
3434 	tree var = candidate (i);
3435 	if (!VAR_P (var))
3436 	  continue;
3437 
3438 	if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (var))) > max_scalarization_size)
3439 	  {
3440 	    if (dump_file && (dump_flags & TDF_DETAILS))
3441 	      {
3442 		fprintf (dump_file, "Too big to totally scalarize: ");
3443 		print_generic_expr (dump_file, var);
3444 		fprintf (dump_file, " (UID: %u)\n", DECL_UID (var));
3445 	      }
3446 	    continue;
3447 	  }
3448 
3449 	bool all_types_ok = true;
3450 	for (struct access *access = get_first_repr_for_decl (var);
3451 	     access;
3452 	     access = access->next_grp)
3453 	  if (!can_totally_scalarize_forest_p (access)
3454 	      || !scalarizable_type_p (access->type, constant_decl_p (var)))
3455 	    {
3456 	      all_types_ok = false;
3457 	      break;
3458 	    }
3459 	if (!all_types_ok)
3460 	  continue;
3461 
3462 	if (dump_file && (dump_flags & TDF_DETAILS))
3463 	  {
3464 	    fprintf (dump_file, "Will attempt to totally scalarize ");
3465 	    print_generic_expr (dump_file, var);
3466 	    fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
3467 	  }
3468 	bool scalarized = true;
3469 	for (struct access *access = get_first_repr_for_decl (var);
3470 	     access;
3471 	     access = access->next_grp)
3472 	  if (!is_gimple_reg_type (access->type)
3473 	      && !totally_scalarize_subtree (access))
3474 	    {
3475 	      scalarized = false;
3476 	      break;
3477 	    }
3478 
3479 	if (scalarized)
3480 	  for (struct access *access = get_first_repr_for_decl (var);
3481 	       access;
3482 	       access = access->next_grp)
3483 	    access->grp_total_scalarization = true;
3484       }
3485 
3486   if (flag_checking)
3487     verify_all_sra_access_forests ();
3488 
3489   bitmap_copy (tmp, candidate_bitmap);
3490   EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
3491     {
3492       tree var = candidate (i);
3493       struct access *access = get_first_repr_for_decl (var);
3494 
3495       if (analyze_access_trees (access))
3496 	{
3497 	  res++;
3498 	  if (dump_file && (dump_flags & TDF_DETAILS))
3499 	    {
3500 	      fprintf (dump_file, "\nAccess trees for ");
3501 	      print_generic_expr (dump_file, var);
3502 	      fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
3503 	      dump_access_tree (dump_file, access);
3504 	      fprintf (dump_file, "\n");
3505 	    }
3506 	}
3507       else
3508 	disqualify_candidate (var, "No scalar replacements to be created.");
3509     }
3510 
3511   BITMAP_FREE (tmp);
3512 
3513   if (res)
3514     {
3515       statistics_counter_event (cfun, "Scalarized aggregates", res);
3516       return true;
3517     }
3518   else
3519     return false;
3520 }
3521 
3522 /* Generate statements copying scalar replacements of accesses within a subtree
3523    into or out of AGG.  ACCESS, all its children, siblings and their children
3524    are to be processed.  AGG is an aggregate type expression (can be a
3525    declaration but does not have to be, it can for example also be a mem_ref or
3526    a series of handled components).  TOP_OFFSET is the offset of the processed
3527    subtree which has to be subtracted from offsets of individual accesses to
3528    get corresponding offsets for AGG.  If CHUNK_SIZE is non-null, copy only
3529    replacements in the interval <start_offset, start_offset + chunk_size>,
3530    otherwise copy all.  GSI is a statement iterator used to place the new
3531    statements.  WRITE should be true when the statements should write from AGG
3532    to the replacement and false if vice versa.  if INSERT_AFTER is true, new
3533    statements will be added after the current statement in GSI, they will be
3534    added before the statement otherwise.  */
3535 
3536 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)3537 generate_subtree_copies (struct access *access, tree agg,
3538 			 HOST_WIDE_INT top_offset,
3539 			 HOST_WIDE_INT start_offset, HOST_WIDE_INT chunk_size,
3540 			 gimple_stmt_iterator *gsi, bool write,
3541 			 bool insert_after, location_t loc)
3542 {
3543   /* Never write anything into constant pool decls.  See PR70602.  */
3544   if (!write && constant_decl_p (agg))
3545     return;
3546   do
3547     {
3548       if (chunk_size && access->offset >= start_offset + chunk_size)
3549 	return;
3550 
3551       if (access->grp_to_be_replaced
3552 	  && (chunk_size == 0
3553 	      || access->offset + access->size > start_offset))
3554 	{
3555 	  tree expr, repl = get_access_replacement (access);
3556 	  gassign *stmt;
3557 
3558 	  expr = build_ref_for_model (loc, agg, access->offset - top_offset,
3559 				      access, gsi, insert_after);
3560 
3561 	  if (write)
3562 	    {
3563 	      if (access->grp_partial_lhs)
3564 		expr = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
3565 						 !insert_after,
3566 						 insert_after ? GSI_NEW_STMT
3567 						 : GSI_SAME_STMT);
3568 	      stmt = gimple_build_assign (repl, expr);
3569 	    }
3570 	  else
3571 	    {
3572 	      TREE_NO_WARNING (repl) = 1;
3573 	      if (access->grp_partial_lhs)
3574 		repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
3575 						 !insert_after,
3576 						 insert_after ? GSI_NEW_STMT
3577 						 : GSI_SAME_STMT);
3578 	      stmt = gimple_build_assign (expr, repl);
3579 	    }
3580 	  gimple_set_location (stmt, loc);
3581 
3582 	  if (insert_after)
3583 	    gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
3584 	  else
3585 	    gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3586 	  update_stmt (stmt);
3587 	  sra_stats.subtree_copies++;
3588 	}
3589       else if (write
3590 	       && access->grp_to_be_debug_replaced
3591 	       && (chunk_size == 0
3592 		   || access->offset + access->size > start_offset))
3593 	{
3594 	  gdebug *ds;
3595 	  tree drhs = build_debug_ref_for_model (loc, agg,
3596 						 access->offset - top_offset,
3597 						 access);
3598 	  ds = gimple_build_debug_bind (get_access_replacement (access),
3599 					drhs, gsi_stmt (*gsi));
3600 	  if (insert_after)
3601 	    gsi_insert_after (gsi, ds, GSI_NEW_STMT);
3602 	  else
3603 	    gsi_insert_before (gsi, ds, GSI_SAME_STMT);
3604 	}
3605 
3606       if (access->first_child)
3607 	generate_subtree_copies (access->first_child, agg, top_offset,
3608 				 start_offset, chunk_size, gsi,
3609 				 write, insert_after, loc);
3610 
3611       access = access->next_sibling;
3612     }
3613   while (access);
3614 }
3615 
3616 /* Assign zero to all scalar replacements in an access subtree.  ACCESS is the
3617    root of the subtree to be processed.  GSI is the statement iterator used
3618    for inserting statements which are added after the current statement if
3619    INSERT_AFTER is true or before it otherwise.  */
3620 
3621 static void
init_subtree_with_zero(struct access * access,gimple_stmt_iterator * gsi,bool insert_after,location_t loc)3622 init_subtree_with_zero (struct access *access, gimple_stmt_iterator *gsi,
3623 			bool insert_after, location_t loc)
3624 
3625 {
3626   struct access *child;
3627 
3628   if (access->grp_to_be_replaced)
3629     {
3630       gassign *stmt;
3631 
3632       stmt = gimple_build_assign (get_access_replacement (access),
3633 				  build_zero_cst (access->type));
3634       if (insert_after)
3635 	gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
3636       else
3637 	gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3638       update_stmt (stmt);
3639       gimple_set_location (stmt, loc);
3640     }
3641   else if (access->grp_to_be_debug_replaced)
3642     {
3643       gdebug *ds
3644 	= gimple_build_debug_bind (get_access_replacement (access),
3645 				   build_zero_cst (access->type),
3646 				   gsi_stmt (*gsi));
3647       if (insert_after)
3648 	gsi_insert_after (gsi, ds, GSI_NEW_STMT);
3649       else
3650 	gsi_insert_before (gsi, ds, GSI_SAME_STMT);
3651     }
3652 
3653   for (child = access->first_child; child; child = child->next_sibling)
3654     init_subtree_with_zero (child, gsi, insert_after, loc);
3655 }
3656 
3657 /* Clobber all scalar replacements in an access subtree.  ACCESS is the
3658    root of the subtree to be processed.  GSI is the statement iterator used
3659    for inserting statements which are added after the current statement if
3660    INSERT_AFTER is true or before it otherwise.  */
3661 
3662 static void
clobber_subtree(struct access * access,gimple_stmt_iterator * gsi,bool insert_after,location_t loc)3663 clobber_subtree (struct access *access, gimple_stmt_iterator *gsi,
3664 		bool insert_after, location_t loc)
3665 
3666 {
3667   struct access *child;
3668 
3669   if (access->grp_to_be_replaced)
3670     {
3671       tree rep = get_access_replacement (access);
3672       tree clobber = build_clobber (access->type);
3673       gimple *stmt = gimple_build_assign (rep, clobber);
3674 
3675       if (insert_after)
3676 	gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
3677       else
3678 	gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3679       update_stmt (stmt);
3680       gimple_set_location (stmt, loc);
3681     }
3682 
3683   for (child = access->first_child; child; child = child->next_sibling)
3684     clobber_subtree (child, gsi, insert_after, loc);
3685 }
3686 
3687 /* Search for an access representative for the given expression EXPR and
3688    return it or NULL if it cannot be found.  */
3689 
3690 static struct access *
get_access_for_expr(tree expr)3691 get_access_for_expr (tree expr)
3692 {
3693   poly_int64 poffset, psize, pmax_size;
3694   HOST_WIDE_INT offset, max_size;
3695   tree base;
3696   bool reverse;
3697 
3698   /* FIXME: This should not be necessary but Ada produces V_C_Es with a type of
3699      a different size than the size of its argument and we need the latter
3700      one.  */
3701   if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
3702     expr = TREE_OPERAND (expr, 0);
3703 
3704   base = get_ref_base_and_extent (expr, &poffset, &psize, &pmax_size,
3705 				  &reverse);
3706   if (!known_size_p (pmax_size)
3707       || !pmax_size.is_constant (&max_size)
3708       || !poffset.is_constant (&offset)
3709       || !DECL_P (base))
3710     return NULL;
3711 
3712   if (tree basesize = DECL_SIZE (base))
3713     {
3714       poly_int64 sz;
3715       if (offset < 0
3716 	  || !poly_int_tree_p (basesize, &sz)
3717 	  || known_le (sz, offset))
3718 	return NULL;
3719     }
3720 
3721   if (max_size == 0
3722       || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
3723     return NULL;
3724 
3725   return get_var_base_offset_size_access (base, offset, max_size);
3726 }
3727 
3728 /* Replace the expression EXPR with a scalar replacement if there is one and
3729    generate other statements to do type conversion or subtree copying if
3730    necessary.  GSI is used to place newly created statements, WRITE is true if
3731    the expression is being written to (it is on a LHS of a statement or output
3732    in an assembly statement).  */
3733 
3734 static bool
sra_modify_expr(tree * expr,gimple_stmt_iterator * gsi,bool write)3735 sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
3736 {
3737   location_t loc;
3738   struct access *access;
3739   tree type, bfr, orig_expr;
3740   bool partial_cplx_access = false;
3741 
3742   if (TREE_CODE (*expr) == BIT_FIELD_REF)
3743     {
3744       bfr = *expr;
3745       expr = &TREE_OPERAND (*expr, 0);
3746     }
3747   else
3748     bfr = NULL_TREE;
3749 
3750   if (TREE_CODE (*expr) == REALPART_EXPR || TREE_CODE (*expr) == IMAGPART_EXPR)
3751     {
3752       expr = &TREE_OPERAND (*expr, 0);
3753       partial_cplx_access = true;
3754     }
3755   access = get_access_for_expr (*expr);
3756   if (!access)
3757     return false;
3758   type = TREE_TYPE (*expr);
3759   orig_expr = *expr;
3760 
3761   loc = gimple_location (gsi_stmt (*gsi));
3762   gimple_stmt_iterator alt_gsi = gsi_none ();
3763   if (write && stmt_ends_bb_p (gsi_stmt (*gsi)))
3764     {
3765       alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi)));
3766       gsi = &alt_gsi;
3767     }
3768 
3769   if (access->grp_to_be_replaced)
3770     {
3771       tree repl = get_access_replacement (access);
3772       /* If we replace a non-register typed access simply use the original
3773          access expression to extract the scalar component afterwards.
3774 	 This happens if scalarizing a function return value or parameter
3775 	 like in gcc.c-torture/execute/20041124-1.c, 20050316-1.c and
3776 	 gcc.c-torture/compile/20011217-1.c.
3777 
3778          We also want to use this when accessing a complex or vector which can
3779          be accessed as a different type too, potentially creating a need for
3780          type conversion (see PR42196) and when scalarized unions are involved
3781          in assembler statements (see PR42398).  */
3782       if (!bfr && !useless_type_conversion_p (type, access->type))
3783 	{
3784 	  tree ref;
3785 
3786 	  ref = build_ref_for_model (loc, orig_expr, 0, access, gsi, false);
3787 
3788 	  if (partial_cplx_access)
3789 	    {
3790 	    /* VIEW_CONVERT_EXPRs in partial complex access are always fine in
3791 	       the case of a write because in such case the replacement cannot
3792 	       be a gimple register.  In the case of a load, we have to
3793 	       differentiate in between a register an non-register
3794 	       replacement.  */
3795 	      tree t = build1 (VIEW_CONVERT_EXPR, type, repl);
3796 	      gcc_checking_assert (!write || access->grp_partial_lhs);
3797 	      if (!access->grp_partial_lhs)
3798 		{
3799 		  tree tmp = make_ssa_name (type);
3800 		  gassign *stmt = gimple_build_assign (tmp, t);
3801 		  /* This is always a read. */
3802 		  gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3803 		  t = tmp;
3804 		}
3805 	      *expr = t;
3806 	    }
3807 	  else if (write)
3808 	    {
3809 	      gassign *stmt;
3810 
3811 	      if (access->grp_partial_lhs)
3812 		ref = force_gimple_operand_gsi (gsi, ref, true, NULL_TREE,
3813 						 false, GSI_NEW_STMT);
3814 	      stmt = gimple_build_assign (repl, ref);
3815 	      gimple_set_location (stmt, loc);
3816 	      gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
3817 	    }
3818 	  else
3819 	    {
3820 	      gassign *stmt;
3821 
3822 	      if (access->grp_partial_lhs)
3823 		repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
3824 						 true, GSI_SAME_STMT);
3825 	      stmt = gimple_build_assign (ref, repl);
3826 	      gimple_set_location (stmt, loc);
3827 	      gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3828 	    }
3829 	}
3830       else
3831 	*expr = repl;
3832       sra_stats.exprs++;
3833     }
3834   else if (write && access->grp_to_be_debug_replaced)
3835     {
3836       gdebug *ds = gimple_build_debug_bind (get_access_replacement (access),
3837 					    NULL_TREE,
3838 					    gsi_stmt (*gsi));
3839       gsi_insert_after (gsi, ds, GSI_NEW_STMT);
3840     }
3841 
3842   if (access->first_child)
3843     {
3844       HOST_WIDE_INT start_offset, chunk_size;
3845       if (bfr
3846 	  && tree_fits_uhwi_p (TREE_OPERAND (bfr, 1))
3847 	  && tree_fits_uhwi_p (TREE_OPERAND (bfr, 2)))
3848 	{
3849 	  chunk_size = tree_to_uhwi (TREE_OPERAND (bfr, 1));
3850 	  start_offset = access->offset
3851 	    + tree_to_uhwi (TREE_OPERAND (bfr, 2));
3852 	}
3853       else
3854 	start_offset = chunk_size = 0;
3855 
3856       generate_subtree_copies (access->first_child, orig_expr, access->offset,
3857 			       start_offset, chunk_size, gsi, write, write,
3858 			       loc);
3859     }
3860   return true;
3861 }
3862 
3863 /* Where scalar replacements of the RHS have been written to when a replacement
3864    of a LHS of an assigments cannot be direclty loaded from a replacement of
3865    the RHS. */
3866 enum unscalarized_data_handling { SRA_UDH_NONE,  /* Nothing done so far. */
3867 				  SRA_UDH_RIGHT, /* Data flushed to the RHS. */
3868 				  SRA_UDH_LEFT }; /* Data flushed to the LHS. */
3869 
3870 struct subreplacement_assignment_data
3871 {
3872   /* Offset of the access representing the lhs of the assignment.  */
3873   HOST_WIDE_INT left_offset;
3874 
3875   /* LHS and RHS of the original assignment.  */
3876   tree assignment_lhs, assignment_rhs;
3877 
3878   /* Access representing the rhs of the whole assignment.  */
3879   struct access *top_racc;
3880 
3881   /* Stmt iterator used for statement insertions after the original assignment.
3882    It points to the main GSI used to traverse a BB during function body
3883    modification.  */
3884   gimple_stmt_iterator *new_gsi;
3885 
3886   /* Stmt iterator used for statement insertions before the original
3887    assignment.  Keeps on pointing to the original statement.  */
3888   gimple_stmt_iterator old_gsi;
3889 
3890   /* Location of the assignment.   */
3891   location_t loc;
3892 
3893   /* Keeps the information whether we have needed to refresh replacements of
3894    the LHS and from which side of the assignments this takes place.  */
3895   enum unscalarized_data_handling refreshed;
3896 };
3897 
3898 /* Store all replacements in the access tree rooted in TOP_RACC either to their
3899    base aggregate if there are unscalarized data or directly to LHS of the
3900    statement that is pointed to by GSI otherwise.  */
3901 
3902 static void
handle_unscalarized_data_in_subtree(struct subreplacement_assignment_data * sad)3903 handle_unscalarized_data_in_subtree (struct subreplacement_assignment_data *sad)
3904 {
3905   tree src;
3906   if (sad->top_racc->grp_unscalarized_data)
3907     {
3908       src = sad->assignment_rhs;
3909       sad->refreshed = SRA_UDH_RIGHT;
3910     }
3911   else
3912     {
3913       src = sad->assignment_lhs;
3914       sad->refreshed = SRA_UDH_LEFT;
3915     }
3916   generate_subtree_copies (sad->top_racc->first_child, src,
3917 			   sad->top_racc->offset, 0, 0,
3918 			   &sad->old_gsi, false, false, sad->loc);
3919 }
3920 
3921 /* Try to generate statements to load all sub-replacements in an access subtree
3922    formed by children of LACC from scalar replacements in the SAD->top_racc
3923    subtree.  If that is not possible, refresh the SAD->top_racc base aggregate
3924    and load the accesses from it.  */
3925 
3926 static void
load_assign_lhs_subreplacements(struct access * lacc,struct subreplacement_assignment_data * sad)3927 load_assign_lhs_subreplacements (struct access *lacc,
3928 				 struct subreplacement_assignment_data *sad)
3929 {
3930   for (lacc = lacc->first_child; lacc; lacc = lacc->next_sibling)
3931     {
3932       HOST_WIDE_INT offset;
3933       offset = lacc->offset - sad->left_offset + sad->top_racc->offset;
3934 
3935       if (lacc->grp_to_be_replaced)
3936 	{
3937 	  struct access *racc;
3938 	  gassign *stmt;
3939 	  tree rhs;
3940 
3941 	  racc = find_access_in_subtree (sad->top_racc, offset, lacc->size);
3942 	  if (racc && racc->grp_to_be_replaced)
3943 	    {
3944 	      rhs = get_access_replacement (racc);
3945 	      if (!useless_type_conversion_p (lacc->type, racc->type))
3946 		rhs = fold_build1_loc (sad->loc, VIEW_CONVERT_EXPR,
3947 				       lacc->type, rhs);
3948 
3949 	      if (racc->grp_partial_lhs && lacc->grp_partial_lhs)
3950 		rhs = force_gimple_operand_gsi (&sad->old_gsi, rhs, true,
3951 						NULL_TREE, true, GSI_SAME_STMT);
3952 	    }
3953 	  else
3954 	    {
3955 	      /* No suitable access on the right hand side, need to load from
3956 		 the aggregate.  See if we have to update it first... */
3957 	      if (sad->refreshed == SRA_UDH_NONE)
3958 		handle_unscalarized_data_in_subtree (sad);
3959 
3960 	      if (sad->refreshed == SRA_UDH_LEFT)
3961 		rhs = build_ref_for_model (sad->loc, sad->assignment_lhs,
3962 					   lacc->offset - sad->left_offset,
3963 					   lacc, sad->new_gsi, true);
3964 	      else
3965 		rhs = build_ref_for_model (sad->loc, sad->assignment_rhs,
3966 					   lacc->offset - sad->left_offset,
3967 					   lacc, sad->new_gsi, true);
3968 	      if (lacc->grp_partial_lhs)
3969 		rhs = force_gimple_operand_gsi (sad->new_gsi,
3970 						rhs, true, NULL_TREE,
3971 						false, GSI_NEW_STMT);
3972 	    }
3973 
3974 	  stmt = gimple_build_assign (get_access_replacement (lacc), rhs);
3975 	  gsi_insert_after (sad->new_gsi, stmt, GSI_NEW_STMT);
3976 	  gimple_set_location (stmt, sad->loc);
3977 	  update_stmt (stmt);
3978 	  sra_stats.subreplacements++;
3979 	}
3980       else
3981 	{
3982 	  if (sad->refreshed == SRA_UDH_NONE
3983 	      && lacc->grp_read && !lacc->grp_covered)
3984 	    handle_unscalarized_data_in_subtree (sad);
3985 
3986 	  if (lacc && lacc->grp_to_be_debug_replaced)
3987 	    {
3988 	      gdebug *ds;
3989 	      tree drhs;
3990 	      struct access *racc = find_access_in_subtree (sad->top_racc,
3991 							    offset,
3992 							    lacc->size);
3993 
3994 	      if (racc && racc->grp_to_be_replaced)
3995 		{
3996 		  if (racc->grp_write || constant_decl_p (racc->base))
3997 		    drhs = get_access_replacement (racc);
3998 		  else
3999 		    drhs = NULL;
4000 		}
4001 	      else if (sad->refreshed == SRA_UDH_LEFT)
4002 		drhs = build_debug_ref_for_model (sad->loc, lacc->base,
4003 						  lacc->offset, lacc);
4004 	      else if (sad->refreshed == SRA_UDH_RIGHT)
4005 		drhs = build_debug_ref_for_model (sad->loc, sad->top_racc->base,
4006 						  offset, lacc);
4007 	      else
4008 		drhs = NULL_TREE;
4009 	      if (drhs
4010 		  && !useless_type_conversion_p (lacc->type, TREE_TYPE (drhs)))
4011 		drhs = fold_build1_loc (sad->loc, VIEW_CONVERT_EXPR,
4012 					lacc->type, drhs);
4013 	      ds = gimple_build_debug_bind (get_access_replacement (lacc),
4014 					    drhs, gsi_stmt (sad->old_gsi));
4015 	      gsi_insert_after (sad->new_gsi, ds, GSI_NEW_STMT);
4016 	    }
4017 	}
4018 
4019       if (lacc->first_child)
4020 	load_assign_lhs_subreplacements (lacc, sad);
4021     }
4022 }
4023 
4024 /* Result code for SRA assignment modification.  */
4025 enum assignment_mod_result { SRA_AM_NONE,       /* nothing done for the stmt */
4026 			     SRA_AM_MODIFIED,  /* stmt changed but not
4027 						  removed */
4028 			     SRA_AM_REMOVED };  /* stmt eliminated */
4029 
4030 /* Modify assignments with a CONSTRUCTOR on their RHS.  STMT contains a pointer
4031    to the assignment and GSI is the statement iterator pointing at it.  Returns
4032    the same values as sra_modify_assign.  */
4033 
4034 static enum assignment_mod_result
sra_modify_constructor_assign(gimple * stmt,gimple_stmt_iterator * gsi)4035 sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
4036 {
4037   tree lhs = gimple_assign_lhs (stmt);
4038   struct access *acc = get_access_for_expr (lhs);
4039   if (!acc)
4040     return SRA_AM_NONE;
4041   location_t loc = gimple_location (stmt);
4042 
4043   if (gimple_clobber_p (stmt))
4044     {
4045       /* Clobber the replacement variable.  */
4046       clobber_subtree (acc, gsi, !acc->grp_covered, loc);
4047       /* Remove clobbers of fully scalarized variables, they are dead.  */
4048       if (acc->grp_covered)
4049 	{
4050 	  unlink_stmt_vdef (stmt);
4051 	  gsi_remove (gsi, true);
4052 	  release_defs (stmt);
4053 	  return SRA_AM_REMOVED;
4054 	}
4055       else
4056 	return SRA_AM_MODIFIED;
4057     }
4058 
4059   if (CONSTRUCTOR_NELTS (gimple_assign_rhs1 (stmt)) > 0)
4060     {
4061       /* I have never seen this code path trigger but if it can happen the
4062 	 following should handle it gracefully.  */
4063       if (access_has_children_p (acc))
4064 	generate_subtree_copies (acc->first_child, lhs, acc->offset, 0, 0, gsi,
4065 				 true, true, loc);
4066       return SRA_AM_MODIFIED;
4067     }
4068 
4069   if (acc->grp_covered)
4070     {
4071       init_subtree_with_zero (acc, gsi, false, loc);
4072       unlink_stmt_vdef (stmt);
4073       gsi_remove (gsi, true);
4074       release_defs (stmt);
4075       return SRA_AM_REMOVED;
4076     }
4077   else
4078     {
4079       init_subtree_with_zero (acc, gsi, true, loc);
4080       return SRA_AM_MODIFIED;
4081     }
4082 }
4083 
4084 /* Create and return a new suitable default definition SSA_NAME for RACC which
4085    is an access describing an uninitialized part of an aggregate that is being
4086    loaded.  REG_TREE is used instead of the actual RACC type if that is not of
4087    a gimple register type.  */
4088 
4089 static tree
get_repl_default_def_ssa_name(struct access * racc,tree reg_type)4090 get_repl_default_def_ssa_name (struct access *racc, tree reg_type)
4091 {
4092   gcc_checking_assert (!racc->grp_to_be_replaced
4093 		       && !racc->grp_to_be_debug_replaced);
4094   if (!racc->replacement_decl)
4095     racc->replacement_decl = create_access_replacement (racc, reg_type);
4096   return get_or_create_ssa_default_def (cfun, racc->replacement_decl);
4097 }
4098 
4099 /* Examine both sides of the assignment statement pointed to by STMT, replace
4100    them with a scalare replacement if there is one and generate copying of
4101    replacements if scalarized aggregates have been used in the assignment.  GSI
4102    is used to hold generated statements for type conversions and subtree
4103    copying.  */
4104 
4105 static enum assignment_mod_result
sra_modify_assign(gimple * stmt,gimple_stmt_iterator * gsi)4106 sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi)
4107 {
4108   struct access *lacc, *racc;
4109   tree lhs, rhs;
4110   bool modify_this_stmt = false;
4111   bool force_gimple_rhs = false;
4112   location_t loc;
4113   gimple_stmt_iterator orig_gsi = *gsi;
4114 
4115   if (!gimple_assign_single_p (stmt))
4116     return SRA_AM_NONE;
4117   lhs = gimple_assign_lhs (stmt);
4118   rhs = gimple_assign_rhs1 (stmt);
4119 
4120   if (TREE_CODE (rhs) == CONSTRUCTOR)
4121     return sra_modify_constructor_assign (stmt, gsi);
4122 
4123   if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (lhs) == REALPART_EXPR
4124       || TREE_CODE (rhs) == IMAGPART_EXPR || TREE_CODE (lhs) == IMAGPART_EXPR
4125       || TREE_CODE (rhs) == BIT_FIELD_REF || TREE_CODE (lhs) == BIT_FIELD_REF)
4126     {
4127       modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (stmt),
4128 					  gsi, false);
4129       modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (stmt),
4130 					   gsi, true);
4131       return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
4132     }
4133 
4134   lacc = get_access_for_expr (lhs);
4135   racc = get_access_for_expr (rhs);
4136   if (!lacc && !racc)
4137     return SRA_AM_NONE;
4138   /* Avoid modifying initializations of constant-pool replacements.  */
4139   if (racc && (racc->replacement_decl == lhs))
4140     return SRA_AM_NONE;
4141 
4142   loc = gimple_location (stmt);
4143   if (lacc && lacc->grp_to_be_replaced)
4144     {
4145       lhs = get_access_replacement (lacc);
4146       gimple_assign_set_lhs (stmt, lhs);
4147       modify_this_stmt = true;
4148       if (lacc->grp_partial_lhs)
4149 	force_gimple_rhs = true;
4150       sra_stats.exprs++;
4151     }
4152 
4153   if (racc && racc->grp_to_be_replaced)
4154     {
4155       rhs = get_access_replacement (racc);
4156       modify_this_stmt = true;
4157       if (racc->grp_partial_lhs)
4158 	force_gimple_rhs = true;
4159       sra_stats.exprs++;
4160     }
4161   else if (racc
4162 	   && !racc->grp_unscalarized_data
4163 	   && !racc->grp_unscalarizable_region
4164 	   && TREE_CODE (lhs) == SSA_NAME
4165 	   && !access_has_replacements_p (racc))
4166     {
4167       rhs = get_repl_default_def_ssa_name (racc, TREE_TYPE (lhs));
4168       modify_this_stmt = true;
4169       sra_stats.exprs++;
4170     }
4171 
4172   if (modify_this_stmt)
4173     {
4174       if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
4175 	{
4176 	  /* If we can avoid creating a VIEW_CONVERT_EXPR do so.
4177 	     ???  This should move to fold_stmt which we simply should
4178 	     call after building a VIEW_CONVERT_EXPR here.  */
4179 	  if (AGGREGATE_TYPE_P (TREE_TYPE (lhs))
4180 	      && !contains_bitfld_component_ref_p (lhs))
4181 	    {
4182 	      lhs = build_ref_for_model (loc, lhs, 0, racc, gsi, false);
4183 	      gimple_assign_set_lhs (stmt, lhs);
4184 	    }
4185 	  else if (lacc
4186 		   && AGGREGATE_TYPE_P (TREE_TYPE (rhs))
4187 		   && !contains_vce_or_bfcref_p (rhs))
4188 	    rhs = build_ref_for_model (loc, rhs, 0, lacc, gsi, false);
4189 
4190 	  if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
4191 	    {
4192 	      rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
4193 				     rhs);
4194 	      if (is_gimple_reg_type (TREE_TYPE (lhs))
4195 		  && TREE_CODE (lhs) != SSA_NAME)
4196 		force_gimple_rhs = true;
4197 	    }
4198 	}
4199     }
4200 
4201   if (lacc && lacc->grp_to_be_debug_replaced)
4202     {
4203       tree dlhs = get_access_replacement (lacc);
4204       tree drhs = unshare_expr (rhs);
4205       if (!useless_type_conversion_p (TREE_TYPE (dlhs), TREE_TYPE (drhs)))
4206 	{
4207 	  if (AGGREGATE_TYPE_P (TREE_TYPE (drhs))
4208 	      && !contains_vce_or_bfcref_p (drhs))
4209 	    drhs = build_debug_ref_for_model (loc, drhs, 0, lacc);
4210 	  if (drhs
4211 	      && !useless_type_conversion_p (TREE_TYPE (dlhs),
4212 					     TREE_TYPE (drhs)))
4213 	    drhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
4214 				    TREE_TYPE (dlhs), drhs);
4215 	}
4216       gdebug *ds = gimple_build_debug_bind (dlhs, drhs, stmt);
4217       gsi_insert_before (gsi, ds, GSI_SAME_STMT);
4218     }
4219 
4220   /* From this point on, the function deals with assignments in between
4221      aggregates when at least one has scalar reductions of some of its
4222      components.  There are three possible scenarios: Both the LHS and RHS have
4223      to-be-scalarized components, 2) only the RHS has or 3) only the LHS has.
4224 
4225      In the first case, we would like to load the LHS components from RHS
4226      components whenever possible.  If that is not possible, we would like to
4227      read it directly from the RHS (after updating it by storing in it its own
4228      components).  If there are some necessary unscalarized data in the LHS,
4229      those will be loaded by the original assignment too.  If neither of these
4230      cases happen, the original statement can be removed.  Most of this is done
4231      by load_assign_lhs_subreplacements.
4232 
4233      In the second case, we would like to store all RHS scalarized components
4234      directly into LHS and if they cover the aggregate completely, remove the
4235      statement too.  In the third case, we want the LHS components to be loaded
4236      directly from the RHS (DSE will remove the original statement if it
4237      becomes redundant).
4238 
4239      This is a bit complex but manageable when types match and when unions do
4240      not cause confusion in a way that we cannot really load a component of LHS
4241      from the RHS or vice versa (the access representing this level can have
4242      subaccesses that are accessible only through a different union field at a
4243      higher level - different from the one used in the examined expression).
4244      Unions are fun.
4245 
4246      Therefore, I specially handle a fourth case, happening when there is a
4247      specific type cast or it is impossible to locate a scalarized subaccess on
4248      the other side of the expression.  If that happens, I simply "refresh" the
4249      RHS by storing in it is scalarized components leave the original statement
4250      there to do the copying and then load the scalar replacements of the LHS.
4251      This is what the first branch does.  */
4252 
4253   if (modify_this_stmt
4254       || gimple_has_volatile_ops (stmt)
4255       || contains_vce_or_bfcref_p (rhs)
4256       || contains_vce_or_bfcref_p (lhs)
4257       || stmt_ends_bb_p (stmt))
4258     {
4259       /* No need to copy into a constant-pool, it comes pre-initialized.  */
4260       if (access_has_children_p (racc) && !constant_decl_p (racc->base))
4261 	generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0,
4262 				 gsi, false, false, loc);
4263       if (access_has_children_p (lacc))
4264 	{
4265 	  gimple_stmt_iterator alt_gsi = gsi_none ();
4266 	  if (stmt_ends_bb_p (stmt))
4267 	    {
4268 	      alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi)));
4269 	      gsi = &alt_gsi;
4270 	    }
4271 	  generate_subtree_copies (lacc->first_child, lhs, lacc->offset, 0, 0,
4272 				   gsi, true, true, loc);
4273 	}
4274       sra_stats.separate_lhs_rhs_handling++;
4275 
4276       /* This gimplification must be done after generate_subtree_copies,
4277 	 lest we insert the subtree copies in the middle of the gimplified
4278 	 sequence.  */
4279       if (force_gimple_rhs)
4280 	rhs = force_gimple_operand_gsi (&orig_gsi, rhs, true, NULL_TREE,
4281 					true, GSI_SAME_STMT);
4282       if (gimple_assign_rhs1 (stmt) != rhs)
4283 	{
4284 	  modify_this_stmt = true;
4285 	  gimple_assign_set_rhs_from_tree (&orig_gsi, rhs);
4286 	  gcc_assert (stmt == gsi_stmt (orig_gsi));
4287 	}
4288 
4289       return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
4290     }
4291   else
4292     {
4293       if (access_has_children_p (lacc)
4294 	  && access_has_children_p (racc)
4295 	  /* When an access represents an unscalarizable region, it usually
4296 	     represents accesses with variable offset and thus must not be used
4297 	     to generate new memory accesses.  */
4298 	  && !lacc->grp_unscalarizable_region
4299 	  && !racc->grp_unscalarizable_region)
4300 	{
4301 	  struct subreplacement_assignment_data sad;
4302 
4303 	  sad.left_offset = lacc->offset;
4304 	  sad.assignment_lhs = lhs;
4305 	  sad.assignment_rhs = rhs;
4306 	  sad.top_racc = racc;
4307 	  sad.old_gsi = *gsi;
4308 	  sad.new_gsi = gsi;
4309 	  sad.loc = gimple_location (stmt);
4310 	  sad.refreshed = SRA_UDH_NONE;
4311 
4312 	  if (lacc->grp_read && !lacc->grp_covered)
4313 	    handle_unscalarized_data_in_subtree (&sad);
4314 
4315 	  load_assign_lhs_subreplacements (lacc, &sad);
4316 	  if (sad.refreshed != SRA_UDH_RIGHT)
4317 	    {
4318 	      gsi_next (gsi);
4319 	      unlink_stmt_vdef (stmt);
4320 	      gsi_remove (&sad.old_gsi, true);
4321 	      release_defs (stmt);
4322 	      sra_stats.deleted++;
4323 	      return SRA_AM_REMOVED;
4324 	    }
4325 	}
4326       else
4327 	{
4328 	  if (access_has_children_p (racc)
4329 	      && !racc->grp_unscalarized_data
4330 	      && TREE_CODE (lhs) != SSA_NAME)
4331 	    {
4332 	      if (dump_file)
4333 		{
4334 		  fprintf (dump_file, "Removing load: ");
4335 		  print_gimple_stmt (dump_file, stmt, 0);
4336 		}
4337 	      generate_subtree_copies (racc->first_child, lhs,
4338 				       racc->offset, 0, 0, gsi,
4339 				       false, false, loc);
4340 	      gcc_assert (stmt == gsi_stmt (*gsi));
4341 	      unlink_stmt_vdef (stmt);
4342 	      gsi_remove (gsi, true);
4343 	      release_defs (stmt);
4344 	      sra_stats.deleted++;
4345 	      return SRA_AM_REMOVED;
4346 	    }
4347 	  /* Restore the aggregate RHS from its components so the
4348 	     prevailing aggregate copy does the right thing.  */
4349 	  if (access_has_children_p (racc))
4350 	    generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0,
4351 				     gsi, false, false, loc);
4352 	  /* Re-load the components of the aggregate copy destination.
4353 	     But use the RHS aggregate to load from to expose more
4354 	     optimization opportunities.  */
4355 	  if (access_has_children_p (lacc))
4356 	    generate_subtree_copies (lacc->first_child, rhs, lacc->offset,
4357 				     0, 0, gsi, true, true, loc);
4358 	}
4359 
4360       return SRA_AM_NONE;
4361     }
4362 }
4363 
4364 /* Set any scalar replacements of values in the constant pool to the initial
4365    value of the constant.  (Constant-pool decls like *.LC0 have effectively
4366    been initialized before the program starts, we must do the same for their
4367    replacements.)  Thus, we output statements like 'SR.1 = *.LC0[0];' into
4368    the function's entry block.  */
4369 
4370 static void
initialize_constant_pool_replacements(void)4371 initialize_constant_pool_replacements (void)
4372 {
4373   gimple_seq seq = NULL;
4374   gimple_stmt_iterator gsi = gsi_start (seq);
4375   bitmap_iterator bi;
4376   unsigned i;
4377 
4378   EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
4379     {
4380       tree var = candidate (i);
4381       if (!constant_decl_p (var))
4382 	continue;
4383 
4384       struct access *access = get_first_repr_for_decl (var);
4385 
4386       while (access)
4387 	{
4388 	  if (access->replacement_decl)
4389 	    {
4390 	      gassign *stmt
4391 		= gimple_build_assign (get_access_replacement (access),
4392 				       unshare_expr (access->expr));
4393 	      if (dump_file && (dump_flags & TDF_DETAILS))
4394 		{
4395 		  fprintf (dump_file, "Generating constant initializer: ");
4396 		  print_gimple_stmt (dump_file, stmt, 0);
4397 		  fprintf (dump_file, "\n");
4398 		}
4399 	      gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
4400 	      update_stmt (stmt);
4401 	    }
4402 
4403 	  if (access->first_child)
4404 	    access = access->first_child;
4405 	  else if (access->next_sibling)
4406 	    access = access->next_sibling;
4407 	  else
4408 	    {
4409 	      while (access->parent && !access->next_sibling)
4410 		access = access->parent;
4411 	      if (access->next_sibling)
4412 		access = access->next_sibling;
4413 	      else
4414 		access = access->next_grp;
4415 	    }
4416 	}
4417     }
4418 
4419   seq = gsi_seq (gsi);
4420   if (seq)
4421     gsi_insert_seq_on_edge_immediate (
4422       single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
4423 }
4424 
4425 /* Traverse the function body and all modifications as decided in
4426    analyze_all_variable_accesses.  Return true iff the CFG has been
4427    changed.  */
4428 
4429 static bool
sra_modify_function_body(void)4430 sra_modify_function_body (void)
4431 {
4432   bool cfg_changed = false;
4433   basic_block bb;
4434 
4435   initialize_constant_pool_replacements ();
4436 
4437   FOR_EACH_BB_FN (bb, cfun)
4438     {
4439       gimple_stmt_iterator gsi = gsi_start_bb (bb);
4440       while (!gsi_end_p (gsi))
4441 	{
4442 	  gimple *stmt = gsi_stmt (gsi);
4443 	  enum assignment_mod_result assign_result;
4444 	  bool modified = false, deleted = false;
4445 	  tree *t;
4446 	  unsigned i;
4447 
4448 	  switch (gimple_code (stmt))
4449 	    {
4450 	    case GIMPLE_RETURN:
4451 	      t = gimple_return_retval_ptr (as_a <greturn *> (stmt));
4452 	      if (*t != NULL_TREE)
4453 		modified |= sra_modify_expr (t, &gsi, false);
4454 	      break;
4455 
4456 	    case GIMPLE_ASSIGN:
4457 	      assign_result = sra_modify_assign (stmt, &gsi);
4458 	      modified |= assign_result == SRA_AM_MODIFIED;
4459 	      deleted = assign_result == SRA_AM_REMOVED;
4460 	      break;
4461 
4462 	    case GIMPLE_CALL:
4463 	      /* Operands must be processed before the lhs.  */
4464 	      for (i = 0; i < gimple_call_num_args (stmt); i++)
4465 		{
4466 		  t = gimple_call_arg_ptr (stmt, i);
4467 		  modified |= sra_modify_expr (t, &gsi, false);
4468 		}
4469 
4470 	      if (gimple_call_lhs (stmt))
4471 		{
4472 		  t = gimple_call_lhs_ptr (stmt);
4473 		  modified |= sra_modify_expr (t, &gsi, true);
4474 		}
4475 	      break;
4476 
4477 	    case GIMPLE_ASM:
4478 	      {
4479 		gasm *asm_stmt = as_a <gasm *> (stmt);
4480 		for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
4481 		  {
4482 		    t = &TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
4483 		    modified |= sra_modify_expr (t, &gsi, false);
4484 		  }
4485 		for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
4486 		  {
4487 		    t = &TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
4488 		    modified |= sra_modify_expr (t, &gsi, true);
4489 		  }
4490 	      }
4491 	      break;
4492 
4493 	    default:
4494 	      break;
4495 	    }
4496 
4497 	  if (modified)
4498 	    {
4499 	      update_stmt (stmt);
4500 	      if (maybe_clean_eh_stmt (stmt)
4501 		  && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
4502 		cfg_changed = true;
4503 	    }
4504 	  if (!deleted)
4505 	    gsi_next (&gsi);
4506 	}
4507     }
4508 
4509   gsi_commit_edge_inserts ();
4510   return cfg_changed;
4511 }
4512 
4513 /* Generate statements initializing scalar replacements of parts of function
4514    parameters.  */
4515 
4516 static void
initialize_parameter_reductions(void)4517 initialize_parameter_reductions (void)
4518 {
4519   gimple_stmt_iterator gsi;
4520   gimple_seq seq = NULL;
4521   tree parm;
4522 
4523   gsi = gsi_start (seq);
4524   for (parm = DECL_ARGUMENTS (current_function_decl);
4525        parm;
4526        parm = DECL_CHAIN (parm))
4527     {
4528       vec<access_p> *access_vec;
4529       struct access *access;
4530 
4531       if (!bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
4532 	continue;
4533       access_vec = get_base_access_vector (parm);
4534       if (!access_vec)
4535 	continue;
4536 
4537       for (access = (*access_vec)[0];
4538 	   access;
4539 	   access = access->next_grp)
4540 	generate_subtree_copies (access, parm, 0, 0, 0, &gsi, true, true,
4541 				 EXPR_LOCATION (parm));
4542     }
4543 
4544   seq = gsi_seq (gsi);
4545   if (seq)
4546     gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
4547 }
4548 
4549 /* The "main" function of intraprocedural SRA passes.  Runs the analysis and if
4550    it reveals there are components of some aggregates to be scalarized, it runs
4551    the required transformations.  */
4552 static unsigned int
perform_intra_sra(void)4553 perform_intra_sra (void)
4554 {
4555   int ret = 0;
4556   sra_initialize ();
4557 
4558   if (!find_var_candidates ())
4559     goto out;
4560 
4561   if (!scan_function ())
4562     goto out;
4563 
4564   if (!analyze_all_variable_accesses ())
4565     goto out;
4566 
4567   if (sra_modify_function_body ())
4568     ret = TODO_update_ssa | TODO_cleanup_cfg;
4569   else
4570     ret = TODO_update_ssa;
4571   initialize_parameter_reductions ();
4572 
4573   statistics_counter_event (cfun, "Scalar replacements created",
4574 			    sra_stats.replacements);
4575   statistics_counter_event (cfun, "Modified expressions", sra_stats.exprs);
4576   statistics_counter_event (cfun, "Subtree copy stmts",
4577 			    sra_stats.subtree_copies);
4578   statistics_counter_event (cfun, "Subreplacement stmts",
4579 			    sra_stats.subreplacements);
4580   statistics_counter_event (cfun, "Deleted stmts", sra_stats.deleted);
4581   statistics_counter_event (cfun, "Separate LHS and RHS handling",
4582 			    sra_stats.separate_lhs_rhs_handling);
4583 
4584  out:
4585   sra_deinitialize ();
4586   return ret;
4587 }
4588 
4589 /* Perform early intraprocedural SRA.  */
4590 static unsigned int
early_intra_sra(void)4591 early_intra_sra (void)
4592 {
4593   sra_mode = SRA_MODE_EARLY_INTRA;
4594   return perform_intra_sra ();
4595 }
4596 
4597 /* Perform "late" intraprocedural SRA.  */
4598 static unsigned int
late_intra_sra(void)4599 late_intra_sra (void)
4600 {
4601   sra_mode = SRA_MODE_INTRA;
4602   return perform_intra_sra ();
4603 }
4604 
4605 
4606 static bool
gate_intra_sra(void)4607 gate_intra_sra (void)
4608 {
4609   return flag_tree_sra != 0 && dbg_cnt (tree_sra);
4610 }
4611 
4612 
4613 namespace {
4614 
4615 const pass_data pass_data_sra_early =
4616 {
4617   GIMPLE_PASS, /* type */
4618   "esra", /* name */
4619   OPTGROUP_NONE, /* optinfo_flags */
4620   TV_TREE_SRA, /* tv_id */
4621   ( PROP_cfg | PROP_ssa ), /* properties_required */
4622   0, /* properties_provided */
4623   0, /* properties_destroyed */
4624   0, /* todo_flags_start */
4625   TODO_update_ssa, /* todo_flags_finish */
4626 };
4627 
4628 class pass_sra_early : public gimple_opt_pass
4629 {
4630 public:
pass_sra_early(gcc::context * ctxt)4631   pass_sra_early (gcc::context *ctxt)
4632     : gimple_opt_pass (pass_data_sra_early, ctxt)
4633   {}
4634 
4635   /* opt_pass methods: */
gate(function *)4636   virtual bool gate (function *) { return gate_intra_sra (); }
execute(function *)4637   virtual unsigned int execute (function *) { return early_intra_sra (); }
4638 
4639 }; // class pass_sra_early
4640 
4641 } // anon namespace
4642 
4643 gimple_opt_pass *
make_pass_sra_early(gcc::context * ctxt)4644 make_pass_sra_early (gcc::context *ctxt)
4645 {
4646   return new pass_sra_early (ctxt);
4647 }
4648 
4649 namespace {
4650 
4651 const pass_data pass_data_sra =
4652 {
4653   GIMPLE_PASS, /* type */
4654   "sra", /* name */
4655   OPTGROUP_NONE, /* optinfo_flags */
4656   TV_TREE_SRA, /* tv_id */
4657   ( PROP_cfg | PROP_ssa ), /* properties_required */
4658   0, /* properties_provided */
4659   0, /* properties_destroyed */
4660   TODO_update_address_taken, /* todo_flags_start */
4661   TODO_update_ssa, /* todo_flags_finish */
4662 };
4663 
4664 class pass_sra : public gimple_opt_pass
4665 {
4666 public:
pass_sra(gcc::context * ctxt)4667   pass_sra (gcc::context *ctxt)
4668     : gimple_opt_pass (pass_data_sra, ctxt)
4669   {}
4670 
4671   /* opt_pass methods: */
gate(function *)4672   virtual bool gate (function *) { return gate_intra_sra (); }
execute(function *)4673   virtual unsigned int execute (function *) { return late_intra_sra (); }
4674 
4675 }; // class pass_sra
4676 
4677 } // anon namespace
4678 
4679 gimple_opt_pass *
make_pass_sra(gcc::context * ctxt)4680 make_pass_sra (gcc::context *ctxt)
4681 {
4682   return new pass_sra (ctxt);
4683 }
4684