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