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