c++: ICE on anon struct with base [PR96636]
[official-gcc.git] / gcc / tree-sra.c
blobc05d22f3e8f1ea4e5c3c6a4c61781f6a6baec054
1 /* Scalar Replacement of Aggregates (SRA) converts some structure
2 references into scalar references, exposing them to the scalar
3 optimizers.
4 Copyright (C) 2008-2021 Free Software Foundation, Inc.
5 Contributed by Martin Jambor <mjambor@suse.cz>
7 This file is part of GCC.
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.
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.
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/>. */
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.
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.
33 Both passes operate in four stages:
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.
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.
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.
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.
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).
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.
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.
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. */
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"
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 */
109 /* Global variable describing which aggregate reduction we are performing at
110 the moment. */
111 static enum sra_mode sra_mode;
113 struct assign_link;
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.
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.
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. */
131 struct access
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;
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;
147 /* The statement this access belongs to. */
148 gimple *stmt;
150 /* Next group representative for this aggregate. */
151 struct access *next_grp;
153 /* Pointer to the group representative. Pointer to itself if the struct is
154 the representative. */
155 struct access *group_representative;
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;
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;
165 /* In intraprocedural SRA, pointer to the next sibling in the access tree as
166 described above. */
167 struct access *next_sibling;
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;
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;
177 /* Pointer to the next access in the work queues. */
178 struct access *next_rhs_queued, *next_lhs_queued;
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;
185 /* Is this access made in reverse storage order? */
186 unsigned reverse : 1;
188 /* Is this particular access write access? */
189 unsigned write : 1;
191 /* Is this access currently in the rhs work queue? */
192 unsigned grp_rhs_queued : 1;
194 /* Is this access currently in the lhs work queue? */
195 unsigned grp_lhs_queued : 1;
197 /* Does this group contain a write access? This flag is propagated down the
198 access tree. */
199 unsigned grp_write : 1;
201 /* Does this group contain a read access? This flag is propagated down the
202 access tree. */
203 unsigned grp_read : 1;
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;
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;
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;
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;
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;
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;
233 /* Is the subtree rooted in this access fully covered by scalar
234 replacements? */
235 unsigned grp_covered : 1;
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;
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;
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;
250 /* Does this access and/or group contain a write access through a
251 BIT_FIELD_REF? */
252 unsigned grp_partial_lhs : 1;
254 /* Set when a scalar replacement should be created for this variable. */
255 unsigned grp_to_be_replaced : 1;
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;
261 /* Should TREE_NO_WARNING of a replacement be set? */
262 unsigned grp_no_warning : 1;
265 typedef struct access *access_p;
268 /* Alloc pool for allocating access structures. */
269 static object_allocator<struct access> access_pool ("SRA accesses");
271 /* A structure linking lhs and rhs accesses from an aggregate assignment. They
272 are used to propagate subaccesses from rhs to lhs and vice versa as long as
273 they don't conflict with what is already there. In the RHS->LHS direction,
274 we also propagate grp_write flag to lazily mark that the access contains any
275 meaningful data. */
276 struct assign_link
278 struct access *lacc, *racc;
279 struct assign_link *next_rhs, *next_lhs;
282 /* Alloc pool for allocating assign link structures. */
283 static object_allocator<assign_link> assign_link_pool ("SRA links");
285 /* Base (tree) -> Vector (vec<access_p> *) map. */
286 static hash_map<tree, auto_vec<access_p> > *base_access_vec;
288 /* Hash to limit creation of artificial accesses */
289 static hash_map<tree, unsigned> *propagation_budget;
291 /* Candidate hash table helpers. */
293 struct uid_decl_hasher : nofree_ptr_hash <tree_node>
295 static inline hashval_t hash (const tree_node *);
296 static inline bool equal (const tree_node *, const tree_node *);
299 /* Hash a tree in a uid_decl_map. */
301 inline hashval_t
302 uid_decl_hasher::hash (const tree_node *item)
304 return item->decl_minimal.uid;
307 /* Return true if the DECL_UID in both trees are equal. */
309 inline bool
310 uid_decl_hasher::equal (const tree_node *a, const tree_node *b)
312 return (a->decl_minimal.uid == b->decl_minimal.uid);
315 /* Set of candidates. */
316 static bitmap candidate_bitmap;
317 static hash_table<uid_decl_hasher> *candidates;
319 /* For a candidate UID return the candidates decl. */
321 static inline tree
322 candidate (unsigned uid)
324 tree_node t;
325 t.decl_minimal.uid = uid;
326 return candidates->find_with_hash (&t, static_cast <hashval_t> (uid));
329 /* Bitmap of candidates which we should try to entirely scalarize away and
330 those which cannot be (because they are and need be used as a whole). */
331 static bitmap should_scalarize_away_bitmap, cannot_scalarize_away_bitmap;
333 /* Bitmap of candidates in the constant pool, which cannot be scalarized
334 because this would produce non-constant expressions (e.g. Ada). */
335 static bitmap disqualified_constants;
337 /* Obstack for creation of fancy names. */
338 static struct obstack name_obstack;
340 /* Head of a linked list of accesses that need to have its subaccesses
341 propagated to their assignment counterparts. */
342 static struct access *rhs_work_queue_head, *lhs_work_queue_head;
344 /* Dump contents of ACCESS to file F in a human friendly way. If GRP is true,
345 representative fields are dumped, otherwise those which only describe the
346 individual access are. */
348 static struct
350 /* Number of processed aggregates is readily available in
351 analyze_all_variable_accesses and so is not stored here. */
353 /* Number of created scalar replacements. */
354 int replacements;
356 /* Number of times sra_modify_expr or sra_modify_assign themselves changed an
357 expression. */
358 int exprs;
360 /* Number of statements created by generate_subtree_copies. */
361 int subtree_copies;
363 /* Number of statements created by load_assign_lhs_subreplacements. */
364 int subreplacements;
366 /* Number of times sra_modify_assign has deleted a statement. */
367 int deleted;
369 /* Number of times sra_modify_assign has to deal with subaccesses of LHS and
370 RHS reparately due to type conversions or nonexistent matching
371 references. */
372 int separate_lhs_rhs_handling;
374 /* Number of parameters that were removed because they were unused. */
375 int deleted_unused_parameters;
377 /* Number of scalars passed as parameters by reference that have been
378 converted to be passed by value. */
379 int scalar_by_ref_to_by_val;
381 /* Number of aggregate parameters that were replaced by one or more of their
382 components. */
383 int aggregate_params_reduced;
385 /* Numbber of components created when splitting aggregate parameters. */
386 int param_reductions_created;
387 } sra_stats;
389 static void
390 dump_access (FILE *f, struct access *access, bool grp)
392 fprintf (f, "access { ");
393 fprintf (f, "base = (%d)'", DECL_UID (access->base));
394 print_generic_expr (f, access->base);
395 fprintf (f, "', offset = " HOST_WIDE_INT_PRINT_DEC, access->offset);
396 fprintf (f, ", size = " HOST_WIDE_INT_PRINT_DEC, access->size);
397 fprintf (f, ", expr = ");
398 print_generic_expr (f, access->expr);
399 fprintf (f, ", type = ");
400 print_generic_expr (f, access->type);
401 fprintf (f, ", reverse = %d", access->reverse);
402 if (grp)
403 fprintf (f, ", grp_read = %d, grp_write = %d, grp_assignment_read = %d, "
404 "grp_assignment_write = %d, grp_scalar_read = %d, "
405 "grp_scalar_write = %d, grp_total_scalarization = %d, "
406 "grp_hint = %d, grp_covered = %d, "
407 "grp_unscalarizable_region = %d, grp_unscalarized_data = %d, "
408 "grp_same_access_path = %d, grp_partial_lhs = %d, "
409 "grp_to_be_replaced = %d, grp_to_be_debug_replaced = %d}\n",
410 access->grp_read, access->grp_write, access->grp_assignment_read,
411 access->grp_assignment_write, access->grp_scalar_read,
412 access->grp_scalar_write, access->grp_total_scalarization,
413 access->grp_hint, access->grp_covered,
414 access->grp_unscalarizable_region, access->grp_unscalarized_data,
415 access->grp_same_access_path, access->grp_partial_lhs,
416 access->grp_to_be_replaced, access->grp_to_be_debug_replaced);
417 else
418 fprintf (f, ", write = %d, grp_total_scalarization = %d, "
419 "grp_partial_lhs = %d}\n",
420 access->write, access->grp_total_scalarization,
421 access->grp_partial_lhs);
424 /* Dump a subtree rooted in ACCESS to file F, indent by LEVEL. */
426 static void
427 dump_access_tree_1 (FILE *f, struct access *access, int level)
431 int i;
433 for (i = 0; i < level; i++)
434 fputs ("* ", f);
436 dump_access (f, access, true);
438 if (access->first_child)
439 dump_access_tree_1 (f, access->first_child, level + 1);
441 access = access->next_sibling;
443 while (access);
446 /* Dump all access trees for a variable, given the pointer to the first root in
447 ACCESS. */
449 static void
450 dump_access_tree (FILE *f, struct access *access)
452 for (; access; access = access->next_grp)
453 dump_access_tree_1 (f, access, 0);
456 /* Return true iff ACC is non-NULL and has subaccesses. */
458 static inline bool
459 access_has_children_p (struct access *acc)
461 return acc && acc->first_child;
464 /* Return true iff ACC is (partly) covered by at least one replacement. */
466 static bool
467 access_has_replacements_p (struct access *acc)
469 struct access *child;
470 if (acc->grp_to_be_replaced)
471 return true;
472 for (child = acc->first_child; child; child = child->next_sibling)
473 if (access_has_replacements_p (child))
474 return true;
475 return false;
478 /* Return a vector of pointers to accesses for the variable given in BASE or
479 NULL if there is none. */
481 static vec<access_p> *
482 get_base_access_vector (tree base)
484 return base_access_vec->get (base);
487 /* Find an access with required OFFSET and SIZE in a subtree of accesses rooted
488 in ACCESS. Return NULL if it cannot be found. */
490 static struct access *
491 find_access_in_subtree (struct access *access, HOST_WIDE_INT offset,
492 HOST_WIDE_INT size)
494 while (access && (access->offset != offset || access->size != size))
496 struct access *child = access->first_child;
498 while (child && (child->offset + child->size <= offset))
499 child = child->next_sibling;
500 access = child;
503 /* Total scalarization does not replace single field structures with their
504 single field but rather creates an access for them underneath. Look for
505 it. */
506 if (access)
507 while (access->first_child
508 && access->first_child->offset == offset
509 && access->first_child->size == size)
510 access = access->first_child;
512 return access;
515 /* Return the first group representative for DECL or NULL if none exists. */
517 static struct access *
518 get_first_repr_for_decl (tree base)
520 vec<access_p> *access_vec;
522 access_vec = get_base_access_vector (base);
523 if (!access_vec)
524 return NULL;
526 return (*access_vec)[0];
529 /* Find an access representative for the variable BASE and given OFFSET and
530 SIZE. Requires that access trees have already been built. Return NULL if
531 it cannot be found. */
533 static struct access *
534 get_var_base_offset_size_access (tree base, HOST_WIDE_INT offset,
535 HOST_WIDE_INT size)
537 struct access *access;
539 access = get_first_repr_for_decl (base);
540 while (access && (access->offset + access->size <= offset))
541 access = access->next_grp;
542 if (!access)
543 return NULL;
545 return find_access_in_subtree (access, offset, size);
548 /* Add LINK to the linked list of assign links of RACC. */
550 static void
551 add_link_to_rhs (struct access *racc, struct assign_link *link)
553 gcc_assert (link->racc == racc);
555 if (!racc->first_rhs_link)
557 gcc_assert (!racc->last_rhs_link);
558 racc->first_rhs_link = link;
560 else
561 racc->last_rhs_link->next_rhs = link;
563 racc->last_rhs_link = link;
564 link->next_rhs = NULL;
567 /* Add LINK to the linked list of lhs assign links of LACC. */
569 static void
570 add_link_to_lhs (struct access *lacc, struct assign_link *link)
572 gcc_assert (link->lacc == lacc);
574 if (!lacc->first_lhs_link)
576 gcc_assert (!lacc->last_lhs_link);
577 lacc->first_lhs_link = link;
579 else
580 lacc->last_lhs_link->next_lhs = link;
582 lacc->last_lhs_link = link;
583 link->next_lhs = NULL;
586 /* Move all link structures in their linked list in OLD_ACC to the linked list
587 in NEW_ACC. */
588 static void
589 relink_to_new_repr (struct access *new_acc, struct access *old_acc)
591 if (old_acc->first_rhs_link)
594 if (new_acc->first_rhs_link)
596 gcc_assert (!new_acc->last_rhs_link->next_rhs);
597 gcc_assert (!old_acc->last_rhs_link
598 || !old_acc->last_rhs_link->next_rhs);
600 new_acc->last_rhs_link->next_rhs = old_acc->first_rhs_link;
601 new_acc->last_rhs_link = old_acc->last_rhs_link;
603 else
605 gcc_assert (!new_acc->last_rhs_link);
607 new_acc->first_rhs_link = old_acc->first_rhs_link;
608 new_acc->last_rhs_link = old_acc->last_rhs_link;
610 old_acc->first_rhs_link = old_acc->last_rhs_link = NULL;
612 else
613 gcc_assert (!old_acc->last_rhs_link);
615 if (old_acc->first_lhs_link)
618 if (new_acc->first_lhs_link)
620 gcc_assert (!new_acc->last_lhs_link->next_lhs);
621 gcc_assert (!old_acc->last_lhs_link
622 || !old_acc->last_lhs_link->next_lhs);
624 new_acc->last_lhs_link->next_lhs = old_acc->first_lhs_link;
625 new_acc->last_lhs_link = old_acc->last_lhs_link;
627 else
629 gcc_assert (!new_acc->last_lhs_link);
631 new_acc->first_lhs_link = old_acc->first_lhs_link;
632 new_acc->last_lhs_link = old_acc->last_lhs_link;
634 old_acc->first_lhs_link = old_acc->last_lhs_link = NULL;
636 else
637 gcc_assert (!old_acc->last_lhs_link);
641 /* Add ACCESS to the work to queue for propagation of subaccesses from RHS to
642 LHS (which is actually a stack). */
644 static void
645 add_access_to_rhs_work_queue (struct access *access)
647 if (access->first_rhs_link && !access->grp_rhs_queued)
649 gcc_assert (!access->next_rhs_queued);
650 access->next_rhs_queued = rhs_work_queue_head;
651 access->grp_rhs_queued = 1;
652 rhs_work_queue_head = access;
656 /* Add ACCESS to the work to queue for propagation of subaccesses from LHS to
657 RHS (which is actually a stack). */
659 static void
660 add_access_to_lhs_work_queue (struct access *access)
662 if (access->first_lhs_link && !access->grp_lhs_queued)
664 gcc_assert (!access->next_lhs_queued);
665 access->next_lhs_queued = lhs_work_queue_head;
666 access->grp_lhs_queued = 1;
667 lhs_work_queue_head = access;
671 /* Pop an access from the work queue for propagating from RHS to LHS, and
672 return it, assuming there is one. */
674 static struct access *
675 pop_access_from_rhs_work_queue (void)
677 struct access *access = rhs_work_queue_head;
679 rhs_work_queue_head = access->next_rhs_queued;
680 access->next_rhs_queued = NULL;
681 access->grp_rhs_queued = 0;
682 return access;
685 /* Pop an access from the work queue for propagating from LHS to RHS, and
686 return it, assuming there is one. */
688 static struct access *
689 pop_access_from_lhs_work_queue (void)
691 struct access *access = lhs_work_queue_head;
693 lhs_work_queue_head = access->next_lhs_queued;
694 access->next_lhs_queued = NULL;
695 access->grp_lhs_queued = 0;
696 return access;
699 /* Allocate necessary structures. */
701 static void
702 sra_initialize (void)
704 candidate_bitmap = BITMAP_ALLOC (NULL);
705 candidates = new hash_table<uid_decl_hasher>
706 (vec_safe_length (cfun->local_decls) / 2);
707 should_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
708 cannot_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
709 disqualified_constants = BITMAP_ALLOC (NULL);
710 gcc_obstack_init (&name_obstack);
711 base_access_vec = new hash_map<tree, auto_vec<access_p> >;
712 memset (&sra_stats, 0, sizeof (sra_stats));
715 /* Deallocate all general structures. */
717 static void
718 sra_deinitialize (void)
720 BITMAP_FREE (candidate_bitmap);
721 delete candidates;
722 candidates = NULL;
723 BITMAP_FREE (should_scalarize_away_bitmap);
724 BITMAP_FREE (cannot_scalarize_away_bitmap);
725 BITMAP_FREE (disqualified_constants);
726 access_pool.release ();
727 assign_link_pool.release ();
728 obstack_free (&name_obstack, NULL);
730 delete base_access_vec;
733 /* Return true if DECL is a VAR_DECL in the constant pool, false otherwise. */
735 static bool constant_decl_p (tree decl)
737 return VAR_P (decl) && DECL_IN_CONSTANT_POOL (decl);
740 /* Remove DECL from candidates for SRA and write REASON to the dump file if
741 there is one. */
743 static void
744 disqualify_candidate (tree decl, const char *reason)
746 if (bitmap_clear_bit (candidate_bitmap, DECL_UID (decl)))
747 candidates->remove_elt_with_hash (decl, DECL_UID (decl));
748 if (constant_decl_p (decl))
749 bitmap_set_bit (disqualified_constants, DECL_UID (decl));
751 if (dump_file && (dump_flags & TDF_DETAILS))
753 fprintf (dump_file, "! Disqualifying ");
754 print_generic_expr (dump_file, decl);
755 fprintf (dump_file, " - %s\n", reason);
759 /* Return true iff the type contains a field or an element which does not allow
760 scalarization. Use VISITED_TYPES to avoid re-checking already checked
761 (sub-)types. */
763 static bool
764 type_internals_preclude_sra_p_1 (tree type, const char **msg,
765 hash_set<tree> *visited_types)
767 tree fld;
768 tree et;
770 if (visited_types->contains (type))
771 return false;
772 visited_types->add (type);
774 switch (TREE_CODE (type))
776 case RECORD_TYPE:
777 case UNION_TYPE:
778 case QUAL_UNION_TYPE:
779 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
780 if (TREE_CODE (fld) == FIELD_DECL)
782 if (TREE_CODE (fld) == FUNCTION_DECL)
783 continue;
784 tree ft = TREE_TYPE (fld);
786 if (TREE_THIS_VOLATILE (fld))
788 *msg = "volatile structure field";
789 return true;
791 if (!DECL_FIELD_OFFSET (fld))
793 *msg = "no structure field offset";
794 return true;
796 if (!DECL_SIZE (fld))
798 *msg = "zero structure field size";
799 return true;
801 if (!tree_fits_uhwi_p (DECL_FIELD_OFFSET (fld)))
803 *msg = "structure field offset not fixed";
804 return true;
806 if (!tree_fits_uhwi_p (DECL_SIZE (fld)))
808 *msg = "structure field size not fixed";
809 return true;
811 if (!tree_fits_shwi_p (bit_position (fld)))
813 *msg = "structure field size too big";
814 return true;
816 if (AGGREGATE_TYPE_P (ft)
817 && int_bit_position (fld) % BITS_PER_UNIT != 0)
819 *msg = "structure field is bit field";
820 return true;
823 if (AGGREGATE_TYPE_P (ft)
824 && type_internals_preclude_sra_p_1 (ft, msg, visited_types))
825 return true;
828 return false;
830 case ARRAY_TYPE:
831 et = TREE_TYPE (type);
833 if (TYPE_VOLATILE (et))
835 *msg = "element type is volatile";
836 return true;
839 if (AGGREGATE_TYPE_P (et)
840 && type_internals_preclude_sra_p_1 (et, msg, visited_types))
841 return true;
843 return false;
845 default:
846 return false;
850 /* Return true iff the type contains a field or an element which does not allow
851 scalarization. */
853 bool
854 type_internals_preclude_sra_p (tree type, const char **msg)
856 hash_set<tree> visited_types;
857 return type_internals_preclude_sra_p_1 (type, msg, &visited_types);
861 /* Allocate an access structure for BASE, OFFSET and SIZE, clear it, fill in
862 the three fields. Also add it to the vector of accesses corresponding to
863 the base. Finally, return the new access. */
865 static struct access *
866 create_access_1 (tree base, HOST_WIDE_INT offset, HOST_WIDE_INT size)
868 struct access *access = access_pool.allocate ();
870 memset (access, 0, sizeof (struct access));
871 access->base = base;
872 access->offset = offset;
873 access->size = size;
875 base_access_vec->get_or_insert (base).safe_push (access);
877 return access;
880 static bool maybe_add_sra_candidate (tree);
882 /* Create and insert access for EXPR. Return created access, or NULL if it is
883 not possible. Also scan for uses of constant pool as we go along and add
884 to candidates. */
886 static struct access *
887 create_access (tree expr, gimple *stmt, bool write)
889 struct access *access;
890 poly_int64 poffset, psize, pmax_size;
891 tree base = expr;
892 bool reverse, unscalarizable_region = false;
894 base = get_ref_base_and_extent (expr, &poffset, &psize, &pmax_size,
895 &reverse);
897 /* For constant-pool entries, check we can substitute the constant value. */
898 if (constant_decl_p (base))
900 gcc_assert (!bitmap_bit_p (disqualified_constants, DECL_UID (base)));
901 if (expr != base
902 && !is_gimple_reg_type (TREE_TYPE (expr))
903 && dump_file && (dump_flags & TDF_DETAILS))
905 /* This occurs in Ada with accesses to ARRAY_RANGE_REFs,
906 and elements of multidimensional arrays (which are
907 multi-element arrays in their own right). */
908 fprintf (dump_file, "Allowing non-reg-type load of part"
909 " of constant-pool entry: ");
910 print_generic_expr (dump_file, expr);
912 maybe_add_sra_candidate (base);
915 if (!DECL_P (base) || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
916 return NULL;
918 if (write && TREE_READONLY (base))
920 disqualify_candidate (base, "Encountered a store to a read-only decl.");
921 return NULL;
924 HOST_WIDE_INT offset, size, max_size;
925 if (!poffset.is_constant (&offset)
926 || !psize.is_constant (&size)
927 || !pmax_size.is_constant (&max_size))
929 disqualify_candidate (base, "Encountered a polynomial-sized access.");
930 return NULL;
933 if (size != max_size)
935 size = max_size;
936 unscalarizable_region = true;
938 if (size == 0)
939 return NULL;
940 if (offset < 0)
942 disqualify_candidate (base, "Encountered a negative offset access.");
943 return NULL;
945 if (size < 0)
947 disqualify_candidate (base, "Encountered an unconstrained access.");
948 return NULL;
950 if (offset + size > tree_to_shwi (DECL_SIZE (base)))
952 disqualify_candidate (base, "Encountered an access beyond the base.");
953 return NULL;
956 access = create_access_1 (base, offset, size);
957 access->expr = expr;
958 access->type = TREE_TYPE (expr);
959 access->write = write;
960 access->grp_unscalarizable_region = unscalarizable_region;
961 access->stmt = stmt;
962 access->reverse = reverse;
964 return access;
968 /* Return true iff TYPE is scalarizable - i.e. a RECORD_TYPE or fixed-length
969 ARRAY_TYPE with fields that are either of gimple register types (excluding
970 bit-fields) or (recursively) scalarizable types. CONST_DECL must be true if
971 we are considering a decl from constant pool. If it is false, char arrays
972 will be refused. */
974 static bool
975 scalarizable_type_p (tree type, bool const_decl)
977 if (is_gimple_reg_type (type))
978 return true;
979 if (type_contains_placeholder_p (type))
980 return false;
982 bool have_predecessor_field = false;
983 HOST_WIDE_INT prev_pos = 0;
985 switch (TREE_CODE (type))
987 case RECORD_TYPE:
988 for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
989 if (TREE_CODE (fld) == FIELD_DECL)
991 tree ft = TREE_TYPE (fld);
993 if (zerop (DECL_SIZE (fld)))
994 continue;
996 HOST_WIDE_INT pos = int_bit_position (fld);
997 if (have_predecessor_field
998 && pos <= prev_pos)
999 return false;
1001 have_predecessor_field = true;
1002 prev_pos = pos;
1004 if (DECL_BIT_FIELD (fld))
1005 return false;
1007 if (!scalarizable_type_p (ft, const_decl))
1008 return false;
1011 return true;
1013 case ARRAY_TYPE:
1015 HOST_WIDE_INT min_elem_size;
1016 if (const_decl)
1017 min_elem_size = 0;
1018 else
1019 min_elem_size = BITS_PER_UNIT;
1021 if (TYPE_DOMAIN (type) == NULL_TREE
1022 || !tree_fits_shwi_p (TYPE_SIZE (type))
1023 || !tree_fits_shwi_p (TYPE_SIZE (TREE_TYPE (type)))
1024 || (tree_to_shwi (TYPE_SIZE (TREE_TYPE (type))) <= min_elem_size)
1025 || !tree_fits_shwi_p (TYPE_MIN_VALUE (TYPE_DOMAIN (type))))
1026 return false;
1027 if (tree_to_shwi (TYPE_SIZE (type)) == 0
1028 && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE)
1029 /* Zero-element array, should not prevent scalarization. */
1031 else if ((tree_to_shwi (TYPE_SIZE (type)) <= 0)
1032 || !tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
1033 /* Variable-length array, do not allow scalarization. */
1034 return false;
1036 tree elem = TREE_TYPE (type);
1037 if (!scalarizable_type_p (elem, const_decl))
1038 return false;
1039 return true;
1041 default:
1042 return false;
1046 /* Return true if REF has an VIEW_CONVERT_EXPR somewhere in it. */
1048 static inline bool
1049 contains_view_convert_expr_p (const_tree ref)
1051 while (handled_component_p (ref))
1053 if (TREE_CODE (ref) == VIEW_CONVERT_EXPR)
1054 return true;
1055 ref = TREE_OPERAND (ref, 0);
1058 return false;
1061 /* Return true if REF contains a VIEW_CONVERT_EXPR or a COMPONENT_REF with a
1062 bit-field field declaration. If TYPE_CHANGING_P is non-NULL, set the bool
1063 it points to will be set if REF contains any of the above or a MEM_REF
1064 expression that effectively performs type conversion. */
1066 static bool
1067 contains_vce_or_bfcref_p (const_tree ref, bool *type_changing_p = NULL)
1069 while (handled_component_p (ref))
1071 if (TREE_CODE (ref) == VIEW_CONVERT_EXPR
1072 || (TREE_CODE (ref) == COMPONENT_REF
1073 && DECL_BIT_FIELD (TREE_OPERAND (ref, 1))))
1075 if (type_changing_p)
1076 *type_changing_p = true;
1077 return true;
1079 ref = TREE_OPERAND (ref, 0);
1082 if (!type_changing_p
1083 || TREE_CODE (ref) != MEM_REF
1084 || TREE_CODE (TREE_OPERAND (ref, 0)) != ADDR_EXPR)
1085 return false;
1087 tree mem = TREE_OPERAND (TREE_OPERAND (ref, 0), 0);
1088 if (TYPE_MAIN_VARIANT (TREE_TYPE (ref))
1089 != TYPE_MAIN_VARIANT (TREE_TYPE (mem)))
1090 *type_changing_p = true;
1092 return false;
1095 /* Search the given tree for a declaration by skipping handled components and
1096 exclude it from the candidates. */
1098 static void
1099 disqualify_base_of_expr (tree t, const char *reason)
1101 t = get_base_address (t);
1102 if (t && DECL_P (t))
1103 disqualify_candidate (t, reason);
1106 /* Scan expression EXPR and create access structures for all accesses to
1107 candidates for scalarization. Return the created access or NULL if none is
1108 created. */
1110 static struct access *
1111 build_access_from_expr_1 (tree expr, gimple *stmt, bool write)
1113 struct access *ret = NULL;
1114 bool partial_ref;
1116 if (TREE_CODE (expr) == BIT_FIELD_REF
1117 || TREE_CODE (expr) == IMAGPART_EXPR
1118 || TREE_CODE (expr) == REALPART_EXPR)
1120 expr = TREE_OPERAND (expr, 0);
1121 partial_ref = true;
1123 else
1124 partial_ref = false;
1126 if (storage_order_barrier_p (expr))
1128 disqualify_base_of_expr (expr, "storage order barrier.");
1129 return NULL;
1132 /* We need to dive through V_C_Es in order to get the size of its parameter
1133 and not the result type. Ada produces such statements. We are also
1134 capable of handling the topmost V_C_E but not any of those buried in other
1135 handled components. */
1136 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
1137 expr = TREE_OPERAND (expr, 0);
1139 if (contains_view_convert_expr_p (expr))
1141 disqualify_base_of_expr (expr, "V_C_E under a different handled "
1142 "component.");
1143 return NULL;
1145 if (TREE_THIS_VOLATILE (expr))
1147 disqualify_base_of_expr (expr, "part of a volatile reference.");
1148 return NULL;
1151 switch (TREE_CODE (expr))
1153 case MEM_REF:
1154 if (TREE_CODE (TREE_OPERAND (expr, 0)) != ADDR_EXPR)
1155 return NULL;
1156 /* fall through */
1157 case VAR_DECL:
1158 case PARM_DECL:
1159 case RESULT_DECL:
1160 case COMPONENT_REF:
1161 case ARRAY_REF:
1162 case ARRAY_RANGE_REF:
1163 ret = create_access (expr, stmt, write);
1164 break;
1166 default:
1167 break;
1170 if (write && partial_ref && ret)
1171 ret->grp_partial_lhs = 1;
1173 return ret;
1176 /* Scan expression EXPR and create access structures for all accesses to
1177 candidates for scalarization. Return true if any access has been inserted.
1178 STMT must be the statement from which the expression is taken, WRITE must be
1179 true if the expression is a store and false otherwise. */
1181 static bool
1182 build_access_from_expr (tree expr, gimple *stmt, bool write)
1184 struct access *access;
1186 access = build_access_from_expr_1 (expr, stmt, write);
1187 if (access)
1189 /* This means the aggregate is accesses as a whole in a way other than an
1190 assign statement and thus cannot be removed even if we had a scalar
1191 replacement for everything. */
1192 if (cannot_scalarize_away_bitmap)
1193 bitmap_set_bit (cannot_scalarize_away_bitmap, DECL_UID (access->base));
1194 return true;
1196 return false;
1199 /* Return the single non-EH successor edge of BB or NULL if there is none or
1200 more than one. */
1202 static edge
1203 single_non_eh_succ (basic_block bb)
1205 edge e, res = NULL;
1206 edge_iterator ei;
1208 FOR_EACH_EDGE (e, ei, bb->succs)
1209 if (!(e->flags & EDGE_EH))
1211 if (res)
1212 return NULL;
1213 res = e;
1216 return res;
1219 /* Disqualify LHS and RHS for scalarization if STMT has to terminate its BB and
1220 there is no alternative spot where to put statements SRA might need to
1221 generate after it. The spot we are looking for is an edge leading to a
1222 single non-EH successor, if it exists and is indeed single. RHS may be
1223 NULL, in that case ignore it. */
1225 static bool
1226 disqualify_if_bad_bb_terminating_stmt (gimple *stmt, tree lhs, tree rhs)
1228 if (stmt_ends_bb_p (stmt))
1230 if (single_non_eh_succ (gimple_bb (stmt)))
1231 return false;
1233 disqualify_base_of_expr (lhs, "LHS of a throwing stmt.");
1234 if (rhs)
1235 disqualify_base_of_expr (rhs, "RHS of a throwing stmt.");
1236 return true;
1238 return false;
1241 /* Return true if the nature of BASE is such that it contains data even if
1242 there is no write to it in the function. */
1244 static bool
1245 comes_initialized_p (tree base)
1247 return TREE_CODE (base) == PARM_DECL || constant_decl_p (base);
1250 /* Scan expressions occurring in STMT, create access structures for all accesses
1251 to candidates for scalarization and remove those candidates which occur in
1252 statements or expressions that prevent them from being split apart. Return
1253 true if any access has been inserted. */
1255 static bool
1256 build_accesses_from_assign (gimple *stmt)
1258 tree lhs, rhs;
1259 struct access *lacc, *racc;
1261 if (!gimple_assign_single_p (stmt)
1262 /* Scope clobbers don't influence scalarization. */
1263 || gimple_clobber_p (stmt))
1264 return false;
1266 lhs = gimple_assign_lhs (stmt);
1267 rhs = gimple_assign_rhs1 (stmt);
1269 if (disqualify_if_bad_bb_terminating_stmt (stmt, lhs, rhs))
1270 return false;
1272 racc = build_access_from_expr_1 (rhs, stmt, false);
1273 lacc = build_access_from_expr_1 (lhs, stmt, true);
1275 if (lacc)
1277 lacc->grp_assignment_write = 1;
1278 if (storage_order_barrier_p (rhs))
1279 lacc->grp_unscalarizable_region = 1;
1281 if (should_scalarize_away_bitmap && !is_gimple_reg_type (lacc->type))
1283 bool type_changing_p = false;
1284 contains_vce_or_bfcref_p (lhs, &type_changing_p);
1285 if (type_changing_p)
1286 bitmap_set_bit (cannot_scalarize_away_bitmap,
1287 DECL_UID (lacc->base));
1291 if (racc)
1293 racc->grp_assignment_read = 1;
1294 if (should_scalarize_away_bitmap && !is_gimple_reg_type (racc->type))
1296 bool type_changing_p = false;
1297 contains_vce_or_bfcref_p (rhs, &type_changing_p);
1299 if (type_changing_p || gimple_has_volatile_ops (stmt))
1300 bitmap_set_bit (cannot_scalarize_away_bitmap,
1301 DECL_UID (racc->base));
1302 else
1303 bitmap_set_bit (should_scalarize_away_bitmap,
1304 DECL_UID (racc->base));
1306 if (storage_order_barrier_p (lhs))
1307 racc->grp_unscalarizable_region = 1;
1310 if (lacc && racc
1311 && (sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
1312 && !lacc->grp_unscalarizable_region
1313 && !racc->grp_unscalarizable_region
1314 && AGGREGATE_TYPE_P (TREE_TYPE (lhs))
1315 && lacc->size == racc->size
1316 && useless_type_conversion_p (lacc->type, racc->type))
1318 struct assign_link *link;
1320 link = assign_link_pool.allocate ();
1321 memset (link, 0, sizeof (struct assign_link));
1323 link->lacc = lacc;
1324 link->racc = racc;
1325 add_link_to_rhs (racc, link);
1326 add_link_to_lhs (lacc, link);
1327 add_access_to_rhs_work_queue (racc);
1328 add_access_to_lhs_work_queue (lacc);
1330 /* Let's delay marking the areas as written until propagation of accesses
1331 across link, unless the nature of rhs tells us that its data comes
1332 from elsewhere. */
1333 if (!comes_initialized_p (racc->base))
1334 lacc->write = false;
1337 return lacc || racc;
1340 /* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine
1341 GIMPLE_ASM operands with memory constrains which cannot be scalarized. */
1343 static bool
1344 asm_visit_addr (gimple *, tree op, tree, void *)
1346 op = get_base_address (op);
1347 if (op
1348 && DECL_P (op))
1349 disqualify_candidate (op, "Non-scalarizable GIMPLE_ASM operand.");
1351 return false;
1354 /* Scan function and look for interesting expressions and create access
1355 structures for them. Return true iff any access is created. */
1357 static bool
1358 scan_function (void)
1360 basic_block bb;
1361 bool ret = false;
1363 FOR_EACH_BB_FN (bb, cfun)
1365 gimple_stmt_iterator gsi;
1366 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1368 gimple *stmt = gsi_stmt (gsi);
1369 tree t;
1370 unsigned i;
1372 switch (gimple_code (stmt))
1374 case GIMPLE_RETURN:
1375 t = gimple_return_retval (as_a <greturn *> (stmt));
1376 if (t != NULL_TREE)
1377 ret |= build_access_from_expr (t, stmt, false);
1378 break;
1380 case GIMPLE_ASSIGN:
1381 ret |= build_accesses_from_assign (stmt);
1382 break;
1384 case GIMPLE_CALL:
1385 for (i = 0; i < gimple_call_num_args (stmt); i++)
1386 ret |= build_access_from_expr (gimple_call_arg (stmt, i),
1387 stmt, false);
1389 t = gimple_call_lhs (stmt);
1390 if (t && !disqualify_if_bad_bb_terminating_stmt (stmt, t, NULL))
1391 ret |= build_access_from_expr (t, stmt, true);
1392 break;
1394 case GIMPLE_ASM:
1396 gasm *asm_stmt = as_a <gasm *> (stmt);
1397 walk_stmt_load_store_addr_ops (asm_stmt, NULL, NULL, NULL,
1398 asm_visit_addr);
1399 for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
1401 t = TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
1402 ret |= build_access_from_expr (t, asm_stmt, false);
1404 for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
1406 t = TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
1407 ret |= build_access_from_expr (t, asm_stmt, true);
1410 break;
1412 default:
1413 break;
1418 return ret;
1421 /* Helper of QSORT function. There are pointers to accesses in the array. An
1422 access is considered smaller than another if it has smaller offset or if the
1423 offsets are the same but is size is bigger. */
1425 static int
1426 compare_access_positions (const void *a, const void *b)
1428 const access_p *fp1 = (const access_p *) a;
1429 const access_p *fp2 = (const access_p *) b;
1430 const access_p f1 = *fp1;
1431 const access_p f2 = *fp2;
1433 if (f1->offset != f2->offset)
1434 return f1->offset < f2->offset ? -1 : 1;
1436 if (f1->size == f2->size)
1438 if (f1->type == f2->type)
1439 return 0;
1440 /* Put any non-aggregate type before any aggregate type. */
1441 else if (!is_gimple_reg_type (f1->type)
1442 && is_gimple_reg_type (f2->type))
1443 return 1;
1444 else if (is_gimple_reg_type (f1->type)
1445 && !is_gimple_reg_type (f2->type))
1446 return -1;
1447 /* Put any complex or vector type before any other scalar type. */
1448 else if (TREE_CODE (f1->type) != COMPLEX_TYPE
1449 && TREE_CODE (f1->type) != VECTOR_TYPE
1450 && (TREE_CODE (f2->type) == COMPLEX_TYPE
1451 || TREE_CODE (f2->type) == VECTOR_TYPE))
1452 return 1;
1453 else if ((TREE_CODE (f1->type) == COMPLEX_TYPE
1454 || TREE_CODE (f1->type) == VECTOR_TYPE)
1455 && TREE_CODE (f2->type) != COMPLEX_TYPE
1456 && TREE_CODE (f2->type) != VECTOR_TYPE)
1457 return -1;
1458 /* Put any integral type before any non-integral type. When splicing, we
1459 make sure that those with insufficient precision and occupying the
1460 same space are not scalarized. */
1461 else if (INTEGRAL_TYPE_P (f1->type)
1462 && !INTEGRAL_TYPE_P (f2->type))
1463 return -1;
1464 else if (!INTEGRAL_TYPE_P (f1->type)
1465 && INTEGRAL_TYPE_P (f2->type))
1466 return 1;
1467 /* Put the integral type with the bigger precision first. */
1468 else if (INTEGRAL_TYPE_P (f1->type)
1469 && INTEGRAL_TYPE_P (f2->type)
1470 && (TYPE_PRECISION (f2->type) != TYPE_PRECISION (f1->type)))
1471 return TYPE_PRECISION (f2->type) - TYPE_PRECISION (f1->type);
1472 /* Stabilize the sort. */
1473 return TYPE_UID (f1->type) - TYPE_UID (f2->type);
1476 /* We want the bigger accesses first, thus the opposite operator in the next
1477 line: */
1478 return f1->size > f2->size ? -1 : 1;
1482 /* Append a name of the declaration to the name obstack. A helper function for
1483 make_fancy_name. */
1485 static void
1486 make_fancy_decl_name (tree decl)
1488 char buffer[32];
1490 tree name = DECL_NAME (decl);
1491 if (name)
1492 obstack_grow (&name_obstack, IDENTIFIER_POINTER (name),
1493 IDENTIFIER_LENGTH (name));
1494 else
1496 sprintf (buffer, "D%u", DECL_UID (decl));
1497 obstack_grow (&name_obstack, buffer, strlen (buffer));
1501 /* Helper for make_fancy_name. */
1503 static void
1504 make_fancy_name_1 (tree expr)
1506 char buffer[32];
1507 tree index;
1509 if (DECL_P (expr))
1511 make_fancy_decl_name (expr);
1512 return;
1515 switch (TREE_CODE (expr))
1517 case COMPONENT_REF:
1518 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1519 obstack_1grow (&name_obstack, '$');
1520 make_fancy_decl_name (TREE_OPERAND (expr, 1));
1521 break;
1523 case ARRAY_REF:
1524 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1525 obstack_1grow (&name_obstack, '$');
1526 /* Arrays with only one element may not have a constant as their
1527 index. */
1528 index = TREE_OPERAND (expr, 1);
1529 if (TREE_CODE (index) != INTEGER_CST)
1530 break;
1531 sprintf (buffer, HOST_WIDE_INT_PRINT_DEC, TREE_INT_CST_LOW (index));
1532 obstack_grow (&name_obstack, buffer, strlen (buffer));
1533 break;
1535 case ADDR_EXPR:
1536 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1537 break;
1539 case MEM_REF:
1540 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1541 if (!integer_zerop (TREE_OPERAND (expr, 1)))
1543 obstack_1grow (&name_obstack, '$');
1544 sprintf (buffer, HOST_WIDE_INT_PRINT_DEC,
1545 TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)));
1546 obstack_grow (&name_obstack, buffer, strlen (buffer));
1548 break;
1550 case BIT_FIELD_REF:
1551 case REALPART_EXPR:
1552 case IMAGPART_EXPR:
1553 gcc_unreachable (); /* we treat these as scalars. */
1554 break;
1555 default:
1556 break;
1560 /* Create a human readable name for replacement variable of ACCESS. */
1562 static char *
1563 make_fancy_name (tree expr)
1565 make_fancy_name_1 (expr);
1566 obstack_1grow (&name_obstack, '\0');
1567 return XOBFINISH (&name_obstack, char *);
1570 /* Construct a MEM_REF that would reference a part of aggregate BASE of type
1571 EXP_TYPE at the given OFFSET and with storage order REVERSE. If BASE is
1572 something for which get_addr_base_and_unit_offset returns NULL, gsi must
1573 be non-NULL and is used to insert new statements either before or below
1574 the current one as specified by INSERT_AFTER. This function is not capable
1575 of handling bitfields. */
1577 tree
1578 build_ref_for_offset (location_t loc, tree base, poly_int64 offset,
1579 bool reverse, tree exp_type, gimple_stmt_iterator *gsi,
1580 bool insert_after)
1582 tree prev_base = base;
1583 tree off;
1584 tree mem_ref;
1585 poly_int64 base_offset;
1586 unsigned HOST_WIDE_INT misalign;
1587 unsigned int align;
1589 /* Preserve address-space information. */
1590 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (base));
1591 if (as != TYPE_ADDR_SPACE (exp_type))
1592 exp_type = build_qualified_type (exp_type,
1593 TYPE_QUALS (exp_type)
1594 | ENCODE_QUAL_ADDR_SPACE (as));
1596 poly_int64 byte_offset = exact_div (offset, BITS_PER_UNIT);
1597 get_object_alignment_1 (base, &align, &misalign);
1598 base = get_addr_base_and_unit_offset (base, &base_offset);
1600 /* get_addr_base_and_unit_offset returns NULL for references with a variable
1601 offset such as array[var_index]. */
1602 if (!base)
1604 gassign *stmt;
1605 tree tmp, addr;
1607 gcc_checking_assert (gsi);
1608 tmp = make_ssa_name (build_pointer_type (TREE_TYPE (prev_base)));
1609 addr = build_fold_addr_expr (unshare_expr (prev_base));
1610 STRIP_USELESS_TYPE_CONVERSION (addr);
1611 stmt = gimple_build_assign (tmp, addr);
1612 gimple_set_location (stmt, loc);
1613 if (insert_after)
1614 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
1615 else
1616 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
1618 off = build_int_cst (reference_alias_ptr_type (prev_base), byte_offset);
1619 base = tmp;
1621 else if (TREE_CODE (base) == MEM_REF)
1623 off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
1624 base_offset + byte_offset);
1625 off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
1626 base = unshare_expr (TREE_OPERAND (base, 0));
1628 else
1630 off = build_int_cst (reference_alias_ptr_type (prev_base),
1631 base_offset + byte_offset);
1632 base = build_fold_addr_expr (unshare_expr (base));
1635 unsigned int align_bound = known_alignment (misalign + offset);
1636 if (align_bound != 0)
1637 align = MIN (align, align_bound);
1638 if (align != TYPE_ALIGN (exp_type))
1639 exp_type = build_aligned_type (exp_type, align);
1641 mem_ref = fold_build2_loc (loc, MEM_REF, exp_type, base, off);
1642 REF_REVERSE_STORAGE_ORDER (mem_ref) = reverse;
1643 if (TREE_THIS_VOLATILE (prev_base))
1644 TREE_THIS_VOLATILE (mem_ref) = 1;
1645 if (TREE_SIDE_EFFECTS (prev_base))
1646 TREE_SIDE_EFFECTS (mem_ref) = 1;
1647 return mem_ref;
1650 /* Construct and return a memory reference that is equal to a portion of
1651 MODEL->expr but is based on BASE. If this cannot be done, return NULL. */
1653 static tree
1654 build_reconstructed_reference (location_t, tree base, struct access *model)
1656 tree expr = model->expr, prev_expr = NULL;
1657 while (!types_compatible_p (TREE_TYPE (expr), TREE_TYPE (base)))
1659 if (!handled_component_p (expr))
1660 return NULL_TREE;
1661 prev_expr = expr;
1662 expr = TREE_OPERAND (expr, 0);
1665 /* Guard against broken VIEW_CONVERT_EXPRs... */
1666 if (!prev_expr)
1667 return NULL_TREE;
1669 TREE_OPERAND (prev_expr, 0) = base;
1670 tree ref = unshare_expr (model->expr);
1671 TREE_OPERAND (prev_expr, 0) = expr;
1672 return ref;
1675 /* Construct a memory reference to a part of an aggregate BASE at the given
1676 OFFSET and of the same type as MODEL. In case this is a reference to a
1677 bit-field, the function will replicate the last component_ref of model's
1678 expr to access it. GSI and INSERT_AFTER have the same meaning as in
1679 build_ref_for_offset. */
1681 static tree
1682 build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
1683 struct access *model, gimple_stmt_iterator *gsi,
1684 bool insert_after)
1686 gcc_assert (offset >= 0);
1687 if (TREE_CODE (model->expr) == COMPONENT_REF
1688 && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
1690 /* This access represents a bit-field. */
1691 tree t, exp_type, fld = TREE_OPERAND (model->expr, 1);
1693 offset -= int_bit_position (fld);
1694 exp_type = TREE_TYPE (TREE_OPERAND (model->expr, 0));
1695 t = build_ref_for_offset (loc, base, offset, model->reverse, exp_type,
1696 gsi, insert_after);
1697 /* The flag will be set on the record type. */
1698 REF_REVERSE_STORAGE_ORDER (t) = 0;
1699 return fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (fld), t, fld,
1700 NULL_TREE);
1702 else
1704 tree res;
1705 if (model->grp_same_access_path
1706 && !TREE_THIS_VOLATILE (base)
1707 && (TYPE_ADDR_SPACE (TREE_TYPE (base))
1708 == TYPE_ADDR_SPACE (TREE_TYPE (model->expr)))
1709 && offset <= model->offset
1710 /* build_reconstructed_reference can still fail if we have already
1711 massaged BASE because of another type incompatibility. */
1712 && (res = build_reconstructed_reference (loc, base, model)))
1713 return res;
1714 else
1715 return build_ref_for_offset (loc, base, offset, model->reverse,
1716 model->type, gsi, insert_after);
1720 /* Attempt to build a memory reference that we could but into a gimple
1721 debug_bind statement. Similar to build_ref_for_model but punts if it has to
1722 create statements and return s NULL instead. This function also ignores
1723 alignment issues and so its results should never end up in non-debug
1724 statements. */
1726 static tree
1727 build_debug_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
1728 struct access *model)
1730 poly_int64 base_offset;
1731 tree off;
1733 if (TREE_CODE (model->expr) == COMPONENT_REF
1734 && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
1735 return NULL_TREE;
1737 base = get_addr_base_and_unit_offset (base, &base_offset);
1738 if (!base)
1739 return NULL_TREE;
1740 if (TREE_CODE (base) == MEM_REF)
1742 off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
1743 base_offset + offset / BITS_PER_UNIT);
1744 off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
1745 base = unshare_expr (TREE_OPERAND (base, 0));
1747 else
1749 off = build_int_cst (reference_alias_ptr_type (base),
1750 base_offset + offset / BITS_PER_UNIT);
1751 base = build_fold_addr_expr (unshare_expr (base));
1754 return fold_build2_loc (loc, MEM_REF, model->type, base, off);
1757 /* Construct a memory reference consisting of component_refs and array_refs to
1758 a part of an aggregate *RES (which is of type TYPE). The requested part
1759 should have type EXP_TYPE at be the given OFFSET. This function might not
1760 succeed, it returns true when it does and only then *RES points to something
1761 meaningful. This function should be used only to build expressions that we
1762 might need to present to user (e.g. in warnings). In all other situations,
1763 build_ref_for_model or build_ref_for_offset should be used instead. */
1765 static bool
1766 build_user_friendly_ref_for_offset (tree *res, tree type, HOST_WIDE_INT offset,
1767 tree exp_type)
1769 while (1)
1771 tree fld;
1772 tree tr_size, index, minidx;
1773 HOST_WIDE_INT el_size;
1775 if (offset == 0 && exp_type
1776 && types_compatible_p (exp_type, type))
1777 return true;
1779 switch (TREE_CODE (type))
1781 case UNION_TYPE:
1782 case QUAL_UNION_TYPE:
1783 case RECORD_TYPE:
1784 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
1786 HOST_WIDE_INT pos, size;
1787 tree tr_pos, expr, *expr_ptr;
1789 if (TREE_CODE (fld) != FIELD_DECL)
1790 continue;
1792 tr_pos = bit_position (fld);
1793 if (!tr_pos || !tree_fits_uhwi_p (tr_pos))
1794 continue;
1795 pos = tree_to_uhwi (tr_pos);
1796 gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0);
1797 tr_size = DECL_SIZE (fld);
1798 if (!tr_size || !tree_fits_uhwi_p (tr_size))
1799 continue;
1800 size = tree_to_uhwi (tr_size);
1801 if (size == 0)
1803 if (pos != offset)
1804 continue;
1806 else if (pos > offset || (pos + size) <= offset)
1807 continue;
1809 expr = build3 (COMPONENT_REF, TREE_TYPE (fld), *res, fld,
1810 NULL_TREE);
1811 expr_ptr = &expr;
1812 if (build_user_friendly_ref_for_offset (expr_ptr, TREE_TYPE (fld),
1813 offset - pos, exp_type))
1815 *res = expr;
1816 return true;
1819 return false;
1821 case ARRAY_TYPE:
1822 tr_size = TYPE_SIZE (TREE_TYPE (type));
1823 if (!tr_size || !tree_fits_uhwi_p (tr_size))
1824 return false;
1825 el_size = tree_to_uhwi (tr_size);
1827 minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
1828 if (TREE_CODE (minidx) != INTEGER_CST || el_size == 0)
1829 return false;
1830 index = build_int_cst (TYPE_DOMAIN (type), offset / el_size);
1831 if (!integer_zerop (minidx))
1832 index = int_const_binop (PLUS_EXPR, index, minidx);
1833 *res = build4 (ARRAY_REF, TREE_TYPE (type), *res, index,
1834 NULL_TREE, NULL_TREE);
1835 offset = offset % el_size;
1836 type = TREE_TYPE (type);
1837 break;
1839 default:
1840 if (offset != 0)
1841 return false;
1843 if (exp_type)
1844 return false;
1845 else
1846 return true;
1851 /* Print message to dump file why a variable was rejected. */
1853 static void
1854 reject (tree var, const char *msg)
1856 if (dump_file && (dump_flags & TDF_DETAILS))
1858 fprintf (dump_file, "Rejected (%d): %s: ", DECL_UID (var), msg);
1859 print_generic_expr (dump_file, var);
1860 fprintf (dump_file, "\n");
1864 /* Return true if VAR is a candidate for SRA. */
1866 static bool
1867 maybe_add_sra_candidate (tree var)
1869 tree type = TREE_TYPE (var);
1870 const char *msg;
1871 tree_node **slot;
1873 if (!AGGREGATE_TYPE_P (type))
1875 reject (var, "not aggregate");
1876 return false;
1878 /* Allow constant-pool entries that "need to live in memory". */
1879 if (needs_to_live_in_memory (var) && !constant_decl_p (var))
1881 reject (var, "needs to live in memory");
1882 return false;
1884 if (TREE_THIS_VOLATILE (var))
1886 reject (var, "is volatile");
1887 return false;
1889 if (!COMPLETE_TYPE_P (type))
1891 reject (var, "has incomplete type");
1892 return false;
1894 if (!tree_fits_shwi_p (TYPE_SIZE (type)))
1896 reject (var, "type size not fixed");
1897 return false;
1899 if (tree_to_shwi (TYPE_SIZE (type)) == 0)
1901 reject (var, "type size is zero");
1902 return false;
1904 if (type_internals_preclude_sra_p (type, &msg))
1906 reject (var, msg);
1907 return false;
1909 if (/* Fix for PR 41089. tree-stdarg.c needs to have va_lists intact but
1910 we also want to schedule it rather late. Thus we ignore it in
1911 the early pass. */
1912 (sra_mode == SRA_MODE_EARLY_INTRA
1913 && is_va_list_type (type)))
1915 reject (var, "is va_list");
1916 return false;
1919 bitmap_set_bit (candidate_bitmap, DECL_UID (var));
1920 slot = candidates->find_slot_with_hash (var, DECL_UID (var), INSERT);
1921 *slot = var;
1923 if (dump_file && (dump_flags & TDF_DETAILS))
1925 fprintf (dump_file, "Candidate (%d): ", DECL_UID (var));
1926 print_generic_expr (dump_file, var);
1927 fprintf (dump_file, "\n");
1930 return true;
1933 /* The very first phase of intraprocedural SRA. It marks in candidate_bitmap
1934 those with type which is suitable for scalarization. */
1936 static bool
1937 find_var_candidates (void)
1939 tree var, parm;
1940 unsigned int i;
1941 bool ret = false;
1943 for (parm = DECL_ARGUMENTS (current_function_decl);
1944 parm;
1945 parm = DECL_CHAIN (parm))
1946 ret |= maybe_add_sra_candidate (parm);
1948 FOR_EACH_LOCAL_DECL (cfun, i, var)
1950 if (!VAR_P (var))
1951 continue;
1953 ret |= maybe_add_sra_candidate (var);
1956 return ret;
1959 /* Return true if EXP is a reference chain of COMPONENT_REFs and AREAY_REFs
1960 ending either with a DECL or a MEM_REF with zero offset. */
1962 static bool
1963 path_comparable_for_same_access (tree expr)
1965 while (handled_component_p (expr))
1967 if (TREE_CODE (expr) == ARRAY_REF)
1969 /* SSA name indices can occur here too when the array is of sie one.
1970 But we cannot just re-use array_refs with SSA names elsewhere in
1971 the function, so disallow non-constant indices. TODO: Remove this
1972 limitation after teaching build_reconstructed_reference to replace
1973 the index with the index type lower bound. */
1974 if (TREE_CODE (TREE_OPERAND (expr, 1)) != INTEGER_CST)
1975 return false;
1977 expr = TREE_OPERAND (expr, 0);
1980 if (TREE_CODE (expr) == MEM_REF)
1982 if (!zerop (TREE_OPERAND (expr, 1)))
1983 return false;
1985 else
1986 gcc_assert (DECL_P (expr));
1988 return true;
1991 /* Assuming that EXP1 consists of only COMPONENT_REFs and ARRAY_REFs, return
1992 true if the chain of these handled components are exactly the same as EXP2
1993 and the expression under them is the same DECL or an equivalent MEM_REF.
1994 The reference picked by compare_access_positions must go to EXP1. */
1996 static bool
1997 same_access_path_p (tree exp1, tree exp2)
1999 if (TREE_CODE (exp1) != TREE_CODE (exp2))
2001 /* Special case single-field structures loaded sometimes as the field
2002 and sometimes as the structure. If the field is of a scalar type,
2003 compare_access_positions will put it into exp1.
2005 TODO: The gimple register type condition can be removed if teach
2006 compare_access_positions to put inner types first. */
2007 if (is_gimple_reg_type (TREE_TYPE (exp1))
2008 && TREE_CODE (exp1) == COMPONENT_REF
2009 && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (exp1, 0)))
2010 == TYPE_MAIN_VARIANT (TREE_TYPE (exp2))))
2011 exp1 = TREE_OPERAND (exp1, 0);
2012 else
2013 return false;
2016 if (!operand_equal_p (exp1, exp2, OEP_ADDRESS_OF))
2017 return false;
2019 return true;
2022 /* Sort all accesses for the given variable, check for partial overlaps and
2023 return NULL if there are any. If there are none, pick a representative for
2024 each combination of offset and size and create a linked list out of them.
2025 Return the pointer to the first representative and make sure it is the first
2026 one in the vector of accesses. */
2028 static struct access *
2029 sort_and_splice_var_accesses (tree var)
2031 int i, j, access_count;
2032 struct access *res, **prev_acc_ptr = &res;
2033 vec<access_p> *access_vec;
2034 bool first = true;
2035 HOST_WIDE_INT low = -1, high = 0;
2037 access_vec = get_base_access_vector (var);
2038 if (!access_vec)
2039 return NULL;
2040 access_count = access_vec->length ();
2042 /* Sort by <OFFSET, SIZE>. */
2043 access_vec->qsort (compare_access_positions);
2045 i = 0;
2046 while (i < access_count)
2048 struct access *access = (*access_vec)[i];
2049 bool grp_write = access->write;
2050 bool grp_read = !access->write;
2051 bool grp_scalar_write = access->write
2052 && is_gimple_reg_type (access->type);
2053 bool grp_scalar_read = !access->write
2054 && is_gimple_reg_type (access->type);
2055 bool grp_assignment_read = access->grp_assignment_read;
2056 bool grp_assignment_write = access->grp_assignment_write;
2057 bool multiple_scalar_reads = false;
2058 bool grp_partial_lhs = access->grp_partial_lhs;
2059 bool first_scalar = is_gimple_reg_type (access->type);
2060 bool unscalarizable_region = access->grp_unscalarizable_region;
2061 bool grp_same_access_path = true;
2062 bool bf_non_full_precision
2063 = (INTEGRAL_TYPE_P (access->type)
2064 && TYPE_PRECISION (access->type) != access->size
2065 && TREE_CODE (access->expr) == COMPONENT_REF
2066 && DECL_BIT_FIELD (TREE_OPERAND (access->expr, 1)));
2068 if (first || access->offset >= high)
2070 first = false;
2071 low = access->offset;
2072 high = access->offset + access->size;
2074 else if (access->offset > low && access->offset + access->size > high)
2075 return NULL;
2076 else
2077 gcc_assert (access->offset >= low
2078 && access->offset + access->size <= high);
2080 grp_same_access_path = path_comparable_for_same_access (access->expr);
2082 j = i + 1;
2083 while (j < access_count)
2085 struct access *ac2 = (*access_vec)[j];
2086 if (ac2->offset != access->offset || ac2->size != access->size)
2087 break;
2088 if (ac2->write)
2090 grp_write = true;
2091 grp_scalar_write = (grp_scalar_write
2092 || is_gimple_reg_type (ac2->type));
2094 else
2096 grp_read = true;
2097 if (is_gimple_reg_type (ac2->type))
2099 if (grp_scalar_read)
2100 multiple_scalar_reads = true;
2101 else
2102 grp_scalar_read = true;
2105 grp_assignment_read |= ac2->grp_assignment_read;
2106 grp_assignment_write |= ac2->grp_assignment_write;
2107 grp_partial_lhs |= ac2->grp_partial_lhs;
2108 unscalarizable_region |= ac2->grp_unscalarizable_region;
2109 relink_to_new_repr (access, ac2);
2111 /* If there are both aggregate-type and scalar-type accesses with
2112 this combination of size and offset, the comparison function
2113 should have put the scalars first. */
2114 gcc_assert (first_scalar || !is_gimple_reg_type (ac2->type));
2115 /* It also prefers integral types to non-integral. However, when the
2116 precision of the selected type does not span the entire area and
2117 should also be used for a non-integer (i.e. float), we must not
2118 let that happen. Normally analyze_access_subtree expands the type
2119 to cover the entire area but for bit-fields it doesn't. */
2120 if (bf_non_full_precision && !INTEGRAL_TYPE_P (ac2->type))
2122 if (dump_file && (dump_flags & TDF_DETAILS))
2124 fprintf (dump_file, "Cannot scalarize the following access "
2125 "because insufficient precision integer type was "
2126 "selected.\n ");
2127 dump_access (dump_file, access, false);
2129 unscalarizable_region = true;
2132 if (grp_same_access_path
2133 && !same_access_path_p (access->expr, ac2->expr))
2134 grp_same_access_path = false;
2136 ac2->group_representative = access;
2137 j++;
2140 i = j;
2142 access->group_representative = access;
2143 access->grp_write = grp_write;
2144 access->grp_read = grp_read;
2145 access->grp_scalar_read = grp_scalar_read;
2146 access->grp_scalar_write = grp_scalar_write;
2147 access->grp_assignment_read = grp_assignment_read;
2148 access->grp_assignment_write = grp_assignment_write;
2149 access->grp_hint = multiple_scalar_reads && !constant_decl_p (var);
2150 access->grp_partial_lhs = grp_partial_lhs;
2151 access->grp_unscalarizable_region = unscalarizable_region;
2152 access->grp_same_access_path = grp_same_access_path;
2154 *prev_acc_ptr = access;
2155 prev_acc_ptr = &access->next_grp;
2158 gcc_assert (res == (*access_vec)[0]);
2159 return res;
2162 /* Create a variable for the given ACCESS which determines the type, name and a
2163 few other properties. Return the variable declaration and store it also to
2164 ACCESS->replacement. REG_TREE is used when creating a declaration to base a
2165 default-definition SSA name on in order to facilitate an uninitialized
2166 warning. It is used instead of the actual ACCESS type if that is not of a
2167 gimple register type. */
2169 static tree
2170 create_access_replacement (struct access *access, tree reg_type = NULL_TREE)
2172 tree repl;
2174 tree type = access->type;
2175 if (reg_type && !is_gimple_reg_type (type))
2176 type = reg_type;
2178 if (access->grp_to_be_debug_replaced)
2180 repl = create_tmp_var_raw (access->type);
2181 DECL_CONTEXT (repl) = current_function_decl;
2183 else
2184 /* Drop any special alignment on the type if it's not on the main
2185 variant. This avoids issues with weirdo ABIs like AAPCS. */
2186 repl = create_tmp_var (build_qualified_type (TYPE_MAIN_VARIANT (type),
2187 TYPE_QUALS (type)), "SR");
2188 if (access->grp_partial_lhs
2189 && is_gimple_reg_type (type))
2190 DECL_NOT_GIMPLE_REG_P (repl) = 1;
2192 DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base);
2193 DECL_ARTIFICIAL (repl) = 1;
2194 DECL_IGNORED_P (repl) = DECL_IGNORED_P (access->base);
2196 if (DECL_NAME (access->base)
2197 && !DECL_IGNORED_P (access->base)
2198 && !DECL_ARTIFICIAL (access->base))
2200 char *pretty_name = make_fancy_name (access->expr);
2201 tree debug_expr = unshare_expr_without_location (access->expr), d;
2202 bool fail = false;
2204 DECL_NAME (repl) = get_identifier (pretty_name);
2205 DECL_NAMELESS (repl) = 1;
2206 obstack_free (&name_obstack, pretty_name);
2208 /* Get rid of any SSA_NAMEs embedded in debug_expr,
2209 as DECL_DEBUG_EXPR isn't considered when looking for still
2210 used SSA_NAMEs and thus they could be freed. All debug info
2211 generation cares is whether something is constant or variable
2212 and that get_ref_base_and_extent works properly on the
2213 expression. It cannot handle accesses at a non-constant offset
2214 though, so just give up in those cases. */
2215 for (d = debug_expr;
2216 !fail && (handled_component_p (d) || TREE_CODE (d) == MEM_REF);
2217 d = TREE_OPERAND (d, 0))
2218 switch (TREE_CODE (d))
2220 case ARRAY_REF:
2221 case ARRAY_RANGE_REF:
2222 if (TREE_OPERAND (d, 1)
2223 && TREE_CODE (TREE_OPERAND (d, 1)) != INTEGER_CST)
2224 fail = true;
2225 if (TREE_OPERAND (d, 3)
2226 && TREE_CODE (TREE_OPERAND (d, 3)) != INTEGER_CST)
2227 fail = true;
2228 /* FALLTHRU */
2229 case COMPONENT_REF:
2230 if (TREE_OPERAND (d, 2)
2231 && TREE_CODE (TREE_OPERAND (d, 2)) != INTEGER_CST)
2232 fail = true;
2233 break;
2234 case MEM_REF:
2235 if (TREE_CODE (TREE_OPERAND (d, 0)) != ADDR_EXPR)
2236 fail = true;
2237 else
2238 d = TREE_OPERAND (d, 0);
2239 break;
2240 default:
2241 break;
2243 if (!fail)
2245 SET_DECL_DEBUG_EXPR (repl, debug_expr);
2246 DECL_HAS_DEBUG_EXPR_P (repl) = 1;
2248 if (access->grp_no_warning)
2249 suppress_warning (repl /* Be more selective! */);
2250 else
2251 copy_warning (repl, access->base);
2253 else
2254 suppress_warning (repl /* Be more selective! */);
2256 if (dump_file)
2258 if (access->grp_to_be_debug_replaced)
2260 fprintf (dump_file, "Created a debug-only replacement for ");
2261 print_generic_expr (dump_file, access->base);
2262 fprintf (dump_file, " offset: %u, size: %u\n",
2263 (unsigned) access->offset, (unsigned) access->size);
2265 else
2267 fprintf (dump_file, "Created a replacement for ");
2268 print_generic_expr (dump_file, access->base);
2269 fprintf (dump_file, " offset: %u, size: %u: ",
2270 (unsigned) access->offset, (unsigned) access->size);
2271 print_generic_expr (dump_file, repl, TDF_UID);
2272 fprintf (dump_file, "\n");
2275 sra_stats.replacements++;
2277 return repl;
2280 /* Return ACCESS scalar replacement, which must exist. */
2282 static inline tree
2283 get_access_replacement (struct access *access)
2285 gcc_checking_assert (access->replacement_decl);
2286 return access->replacement_decl;
2290 /* Build a subtree of accesses rooted in *ACCESS, and move the pointer in the
2291 linked list along the way. Stop when *ACCESS is NULL or the access pointed
2292 to it is not "within" the root. Return false iff some accesses partially
2293 overlap. */
2295 static bool
2296 build_access_subtree (struct access **access)
2298 struct access *root = *access, *last_child = NULL;
2299 HOST_WIDE_INT limit = root->offset + root->size;
2301 *access = (*access)->next_grp;
2302 while (*access && (*access)->offset + (*access)->size <= limit)
2304 if (!last_child)
2305 root->first_child = *access;
2306 else
2307 last_child->next_sibling = *access;
2308 last_child = *access;
2309 (*access)->parent = root;
2310 (*access)->grp_write |= root->grp_write;
2312 if (!build_access_subtree (access))
2313 return false;
2316 if (*access && (*access)->offset < limit)
2317 return false;
2319 return true;
2322 /* Build a tree of access representatives, ACCESS is the pointer to the first
2323 one, others are linked in a list by the next_grp field. Return false iff
2324 some accesses partially overlap. */
2326 static bool
2327 build_access_trees (struct access *access)
2329 while (access)
2331 struct access *root = access;
2333 if (!build_access_subtree (&access))
2334 return false;
2335 root->next_grp = access;
2337 return true;
2340 /* Traverse the access forest where ROOT is the first root and verify that
2341 various important invariants hold true. */
2343 DEBUG_FUNCTION void
2344 verify_sra_access_forest (struct access *root)
2346 struct access *access = root;
2347 tree first_base = root->base;
2348 gcc_assert (DECL_P (first_base));
2351 gcc_assert (access->base == first_base);
2352 if (access->parent)
2353 gcc_assert (access->offset >= access->parent->offset
2354 && access->size <= access->parent->size);
2355 if (access->next_sibling)
2356 gcc_assert (access->next_sibling->offset
2357 >= access->offset + access->size);
2359 poly_int64 poffset, psize, pmax_size;
2360 bool reverse;
2361 tree base = get_ref_base_and_extent (access->expr, &poffset, &psize,
2362 &pmax_size, &reverse);
2363 HOST_WIDE_INT offset, size, max_size;
2364 if (!poffset.is_constant (&offset)
2365 || !psize.is_constant (&size)
2366 || !pmax_size.is_constant (&max_size))
2367 gcc_unreachable ();
2368 gcc_assert (base == first_base);
2369 gcc_assert (offset == access->offset);
2370 gcc_assert (access->grp_unscalarizable_region
2371 || access->grp_total_scalarization
2372 || size == max_size);
2373 gcc_assert (access->grp_unscalarizable_region
2374 || !is_gimple_reg_type (access->type)
2375 || size == access->size);
2376 gcc_assert (reverse == access->reverse);
2378 if (access->first_child)
2380 gcc_assert (access->first_child->parent == access);
2381 access = access->first_child;
2383 else if (access->next_sibling)
2385 gcc_assert (access->next_sibling->parent == access->parent);
2386 access = access->next_sibling;
2388 else
2390 while (access->parent && !access->next_sibling)
2391 access = access->parent;
2392 if (access->next_sibling)
2393 access = access->next_sibling;
2394 else
2396 gcc_assert (access == root);
2397 root = root->next_grp;
2398 access = root;
2402 while (access);
2405 /* Verify access forests of all candidates with accesses by calling
2406 verify_access_forest on each on them. */
2408 DEBUG_FUNCTION void
2409 verify_all_sra_access_forests (void)
2411 bitmap_iterator bi;
2412 unsigned i;
2413 EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
2415 tree var = candidate (i);
2416 struct access *access = get_first_repr_for_decl (var);
2417 if (access)
2419 gcc_assert (access->base == var);
2420 verify_sra_access_forest (access);
2425 /* Return true if expr contains some ARRAY_REFs into a variable bounded
2426 array. */
2428 static bool
2429 expr_with_var_bounded_array_refs_p (tree expr)
2431 while (handled_component_p (expr))
2433 if (TREE_CODE (expr) == ARRAY_REF
2434 && !tree_fits_shwi_p (array_ref_low_bound (expr)))
2435 return true;
2436 expr = TREE_OPERAND (expr, 0);
2438 return false;
2441 /* Analyze the subtree of accesses rooted in ROOT, scheduling replacements when
2442 both seeming beneficial and when ALLOW_REPLACEMENTS allows it. If TOTALLY
2443 is set, we are totally scalarizing the aggregate. Also set all sorts of
2444 access flags appropriately along the way, notably always set grp_read and
2445 grp_assign_read according to MARK_READ and grp_write when MARK_WRITE is
2446 true.
2448 Creating a replacement for a scalar access is considered beneficial if its
2449 grp_hint ot TOTALLY is set (this means either that there is more than one
2450 direct read access or that we are attempting total scalarization) or
2451 according to the following table:
2453 Access written to through a scalar type (once or more times)
2455 | Written to in an assignment statement
2457 | | Access read as scalar _once_
2458 | | |
2459 | | | Read in an assignment statement
2460 | | | |
2461 | | | | Scalarize Comment
2462 -----------------------------------------------------------------------------
2463 0 0 0 0 No access for the scalar
2464 0 0 0 1 No access for the scalar
2465 0 0 1 0 No Single read - won't help
2466 0 0 1 1 No The same case
2467 0 1 0 0 No access for the scalar
2468 0 1 0 1 No access for the scalar
2469 0 1 1 0 Yes s = *g; return s.i;
2470 0 1 1 1 Yes The same case as above
2471 1 0 0 0 No Won't help
2472 1 0 0 1 Yes s.i = 1; *g = s;
2473 1 0 1 0 Yes s.i = 5; g = s.i;
2474 1 0 1 1 Yes The same case as above
2475 1 1 0 0 No Won't help.
2476 1 1 0 1 Yes s.i = 1; *g = s;
2477 1 1 1 0 Yes s = *g; return s.i;
2478 1 1 1 1 Yes Any of the above yeses */
2480 static bool
2481 analyze_access_subtree (struct access *root, struct access *parent,
2482 bool allow_replacements, bool totally)
2484 struct access *child;
2485 HOST_WIDE_INT limit = root->offset + root->size;
2486 HOST_WIDE_INT covered_to = root->offset;
2487 bool scalar = is_gimple_reg_type (root->type);
2488 bool hole = false, sth_created = false;
2490 if (parent)
2492 if (parent->grp_read)
2493 root->grp_read = 1;
2494 if (parent->grp_assignment_read)
2495 root->grp_assignment_read = 1;
2496 if (parent->grp_write)
2497 root->grp_write = 1;
2498 if (parent->grp_assignment_write)
2499 root->grp_assignment_write = 1;
2500 if (!parent->grp_same_access_path)
2501 root->grp_same_access_path = 0;
2504 if (root->grp_unscalarizable_region)
2505 allow_replacements = false;
2507 if (allow_replacements && expr_with_var_bounded_array_refs_p (root->expr))
2508 allow_replacements = false;
2510 for (child = root->first_child; child; child = child->next_sibling)
2512 hole |= covered_to < child->offset;
2513 sth_created |= analyze_access_subtree (child, root,
2514 allow_replacements && !scalar,
2515 totally);
2517 root->grp_unscalarized_data |= child->grp_unscalarized_data;
2518 if (child->grp_covered)
2519 covered_to += child->size;
2520 else
2521 hole = true;
2524 if (allow_replacements && scalar && !root->first_child
2525 && (totally || !root->grp_total_scalarization)
2526 && (totally
2527 || root->grp_hint
2528 || ((root->grp_scalar_read || root->grp_assignment_read)
2529 && (root->grp_scalar_write || root->grp_assignment_write))))
2531 /* Always create access replacements that cover the whole access.
2532 For integral types this means the precision has to match.
2533 Avoid assumptions based on the integral type kind, too. */
2534 if (INTEGRAL_TYPE_P (root->type)
2535 && (TREE_CODE (root->type) != INTEGER_TYPE
2536 || TYPE_PRECISION (root->type) != root->size)
2537 /* But leave bitfield accesses alone. */
2538 && (TREE_CODE (root->expr) != COMPONENT_REF
2539 || !DECL_BIT_FIELD (TREE_OPERAND (root->expr, 1))))
2541 tree rt = root->type;
2542 gcc_assert ((root->offset % BITS_PER_UNIT) == 0
2543 && (root->size % BITS_PER_UNIT) == 0);
2544 root->type = build_nonstandard_integer_type (root->size,
2545 TYPE_UNSIGNED (rt));
2546 root->expr = build_ref_for_offset (UNKNOWN_LOCATION, root->base,
2547 root->offset, root->reverse,
2548 root->type, NULL, false);
2550 if (dump_file && (dump_flags & TDF_DETAILS))
2552 fprintf (dump_file, "Changing the type of a replacement for ");
2553 print_generic_expr (dump_file, root->base);
2554 fprintf (dump_file, " offset: %u, size: %u ",
2555 (unsigned) root->offset, (unsigned) root->size);
2556 fprintf (dump_file, " to an integer.\n");
2560 root->grp_to_be_replaced = 1;
2561 root->replacement_decl = create_access_replacement (root);
2562 sth_created = true;
2563 hole = false;
2565 else
2567 if (allow_replacements
2568 && scalar && !root->first_child
2569 && !root->grp_total_scalarization
2570 && (root->grp_scalar_write || root->grp_assignment_write)
2571 && !bitmap_bit_p (cannot_scalarize_away_bitmap,
2572 DECL_UID (root->base)))
2574 gcc_checking_assert (!root->grp_scalar_read
2575 && !root->grp_assignment_read);
2576 sth_created = true;
2577 if (MAY_HAVE_DEBUG_BIND_STMTS)
2579 root->grp_to_be_debug_replaced = 1;
2580 root->replacement_decl = create_access_replacement (root);
2584 if (covered_to < limit)
2585 hole = true;
2586 if (scalar || !allow_replacements)
2587 root->grp_total_scalarization = 0;
2590 if (!hole || totally)
2591 root->grp_covered = 1;
2592 else if (root->grp_write || comes_initialized_p (root->base))
2593 root->grp_unscalarized_data = 1; /* not covered and written to */
2594 return sth_created;
2597 /* Analyze all access trees linked by next_grp by the means of
2598 analyze_access_subtree. */
2599 static bool
2600 analyze_access_trees (struct access *access)
2602 bool ret = false;
2604 while (access)
2606 if (analyze_access_subtree (access, NULL, true,
2607 access->grp_total_scalarization))
2608 ret = true;
2609 access = access->next_grp;
2612 return ret;
2615 /* Return true iff a potential new child of ACC at offset OFFSET and with size
2616 SIZE would conflict with an already existing one. If exactly such a child
2617 already exists in ACC, store a pointer to it in EXACT_MATCH. */
2619 static bool
2620 child_would_conflict_in_acc (struct access *acc, HOST_WIDE_INT norm_offset,
2621 HOST_WIDE_INT size, struct access **exact_match)
2623 struct access *child;
2625 for (child = acc->first_child; child; child = child->next_sibling)
2627 if (child->offset == norm_offset && child->size == size)
2629 *exact_match = child;
2630 return true;
2633 if (child->offset < norm_offset + size
2634 && child->offset + child->size > norm_offset)
2635 return true;
2638 return false;
2641 /* Create a new child access of PARENT, with all properties just like MODEL
2642 except for its offset and with its grp_write false and grp_read true.
2643 Return the new access or NULL if it cannot be created. Note that this
2644 access is created long after all splicing and sorting, it's not located in
2645 any access vector and is automatically a representative of its group. Set
2646 the gpr_write flag of the new accesss if SET_GRP_WRITE is true. */
2648 static struct access *
2649 create_artificial_child_access (struct access *parent, struct access *model,
2650 HOST_WIDE_INT new_offset,
2651 bool set_grp_read, bool set_grp_write)
2653 struct access **child;
2654 tree expr = parent->base;
2656 gcc_assert (!model->grp_unscalarizable_region);
2658 struct access *access = access_pool.allocate ();
2659 memset (access, 0, sizeof (struct access));
2660 if (!build_user_friendly_ref_for_offset (&expr, TREE_TYPE (expr), new_offset,
2661 model->type))
2663 access->grp_no_warning = true;
2664 expr = build_ref_for_model (EXPR_LOCATION (parent->base), parent->base,
2665 new_offset, model, NULL, false);
2668 access->base = parent->base;
2669 access->expr = expr;
2670 access->offset = new_offset;
2671 access->size = model->size;
2672 access->type = model->type;
2673 access->parent = parent;
2674 access->grp_read = set_grp_read;
2675 access->grp_write = set_grp_write;
2676 access->reverse = model->reverse;
2678 child = &parent->first_child;
2679 while (*child && (*child)->offset < new_offset)
2680 child = &(*child)->next_sibling;
2682 access->next_sibling = *child;
2683 *child = access;
2685 return access;
2689 /* Beginning with ACCESS, traverse its whole access subtree and mark all
2690 sub-trees as written to. If any of them has not been marked so previously
2691 and has assignment links leading from it, re-enqueue it. */
2693 static void
2694 subtree_mark_written_and_rhs_enqueue (struct access *access)
2696 if (access->grp_write)
2697 return;
2698 access->grp_write = true;
2699 add_access_to_rhs_work_queue (access);
2701 struct access *child;
2702 for (child = access->first_child; child; child = child->next_sibling)
2703 subtree_mark_written_and_rhs_enqueue (child);
2706 /* If there is still budget to create a propagation access for DECL, return
2707 true and decrement the budget. Otherwise return false. */
2709 static bool
2710 budget_for_propagation_access (tree decl)
2712 unsigned b, *p = propagation_budget->get (decl);
2713 if (p)
2714 b = *p;
2715 else
2716 b = param_sra_max_propagations;
2718 if (b == 0)
2719 return false;
2720 b--;
2722 if (b == 0 && dump_file && (dump_flags & TDF_DETAILS))
2724 fprintf (dump_file, "The propagation budget of ");
2725 print_generic_expr (dump_file, decl);
2726 fprintf (dump_file, " (UID: %u) has been exhausted.\n", DECL_UID (decl));
2728 propagation_budget->put (decl, b);
2729 return true;
2732 /* Return true if ACC or any of its subaccesses has grp_child set. */
2734 static bool
2735 access_or_its_child_written (struct access *acc)
2737 if (acc->grp_write)
2738 return true;
2739 for (struct access *sub = acc->first_child; sub; sub = sub->next_sibling)
2740 if (access_or_its_child_written (sub))
2741 return true;
2742 return false;
2745 /* Propagate subaccesses and grp_write flags of RACC across an assignment link
2746 to LACC. Enqueue sub-accesses as necessary so that the write flag is
2747 propagated transitively. Return true if anything changed. Additionally, if
2748 RACC is a scalar access but LACC is not, change the type of the latter, if
2749 possible. */
2751 static bool
2752 propagate_subaccesses_from_rhs (struct access *lacc, struct access *racc)
2754 struct access *rchild;
2755 HOST_WIDE_INT norm_delta = lacc->offset - racc->offset;
2756 bool ret = false;
2758 /* IF the LHS is still not marked as being written to, we only need to do so
2759 if the RHS at this level actually was. */
2760 if (!lacc->grp_write)
2762 gcc_checking_assert (!comes_initialized_p (racc->base));
2763 if (racc->grp_write)
2765 subtree_mark_written_and_rhs_enqueue (lacc);
2766 ret = true;
2770 if (is_gimple_reg_type (lacc->type)
2771 || lacc->grp_unscalarizable_region
2772 || racc->grp_unscalarizable_region)
2774 if (!lacc->grp_write)
2776 ret = true;
2777 subtree_mark_written_and_rhs_enqueue (lacc);
2779 return ret;
2782 if (is_gimple_reg_type (racc->type))
2784 if (!lacc->grp_write)
2786 ret = true;
2787 subtree_mark_written_and_rhs_enqueue (lacc);
2789 if (!lacc->first_child && !racc->first_child)
2791 /* We are about to change the access type from aggregate to scalar,
2792 so we need to put the reverse flag onto the access, if any. */
2793 const bool reverse = TYPE_REVERSE_STORAGE_ORDER (lacc->type);
2794 tree t = lacc->base;
2796 lacc->type = racc->type;
2797 if (build_user_friendly_ref_for_offset (&t, TREE_TYPE (t),
2798 lacc->offset, racc->type))
2800 lacc->expr = t;
2801 lacc->grp_same_access_path = true;
2803 else
2805 lacc->expr = build_ref_for_model (EXPR_LOCATION (lacc->base),
2806 lacc->base, lacc->offset,
2807 racc, NULL, false);
2808 if (TREE_CODE (lacc->expr) == MEM_REF)
2809 REF_REVERSE_STORAGE_ORDER (lacc->expr) = reverse;
2810 lacc->grp_no_warning = true;
2811 lacc->grp_same_access_path = false;
2813 lacc->reverse = reverse;
2815 return ret;
2818 for (rchild = racc->first_child; rchild; rchild = rchild->next_sibling)
2820 struct access *new_acc = NULL;
2821 HOST_WIDE_INT norm_offset = rchild->offset + norm_delta;
2823 if (child_would_conflict_in_acc (lacc, norm_offset, rchild->size,
2824 &new_acc))
2826 if (new_acc)
2828 if (!new_acc->grp_write && rchild->grp_write)
2830 gcc_assert (!lacc->grp_write);
2831 subtree_mark_written_and_rhs_enqueue (new_acc);
2832 ret = true;
2835 rchild->grp_hint = 1;
2836 new_acc->grp_hint |= new_acc->grp_read;
2837 if (rchild->first_child
2838 && propagate_subaccesses_from_rhs (new_acc, rchild))
2840 ret = 1;
2841 add_access_to_rhs_work_queue (new_acc);
2844 else
2846 if (!lacc->grp_write)
2848 ret = true;
2849 subtree_mark_written_and_rhs_enqueue (lacc);
2852 continue;
2855 if (rchild->grp_unscalarizable_region
2856 || !budget_for_propagation_access (lacc->base))
2858 if (!lacc->grp_write && access_or_its_child_written (rchild))
2860 ret = true;
2861 subtree_mark_written_and_rhs_enqueue (lacc);
2863 continue;
2866 rchild->grp_hint = 1;
2867 /* Because get_ref_base_and_extent always includes padding in size for
2868 accesses to DECLs but not necessarily for COMPONENT_REFs of the same
2869 type, we might be actually attempting to here to create a child of the
2870 same type as the parent. */
2871 if (!types_compatible_p (lacc->type, rchild->type))
2872 new_acc = create_artificial_child_access (lacc, rchild, norm_offset,
2873 false,
2874 (lacc->grp_write
2875 || rchild->grp_write));
2876 else
2877 new_acc = lacc;
2878 gcc_checking_assert (new_acc);
2879 if (racc->first_child)
2880 propagate_subaccesses_from_rhs (new_acc, rchild);
2882 add_access_to_rhs_work_queue (lacc);
2883 ret = true;
2886 return ret;
2889 /* Propagate subaccesses of LACC across an assignment link to RACC if they
2890 should inhibit total scalarization of the corresponding area. No flags are
2891 being propagated in the process. Return true if anything changed. */
2893 static bool
2894 propagate_subaccesses_from_lhs (struct access *lacc, struct access *racc)
2896 if (is_gimple_reg_type (racc->type)
2897 || lacc->grp_unscalarizable_region
2898 || racc->grp_unscalarizable_region)
2899 return false;
2901 /* TODO: Do we want set some new racc flag to stop potential total
2902 scalarization if lacc is a scalar access (and none fo the two have
2903 children)? */
2905 bool ret = false;
2906 HOST_WIDE_INT norm_delta = racc->offset - lacc->offset;
2907 for (struct access *lchild = lacc->first_child;
2908 lchild;
2909 lchild = lchild->next_sibling)
2911 struct access *matching_acc = NULL;
2912 HOST_WIDE_INT norm_offset = lchild->offset + norm_delta;
2914 if (lchild->grp_unscalarizable_region
2915 || child_would_conflict_in_acc (racc, norm_offset, lchild->size,
2916 &matching_acc)
2917 || !budget_for_propagation_access (racc->base))
2919 if (matching_acc
2920 && propagate_subaccesses_from_lhs (lchild, matching_acc))
2921 add_access_to_lhs_work_queue (matching_acc);
2922 continue;
2925 /* Because get_ref_base_and_extent always includes padding in size for
2926 accesses to DECLs but not necessarily for COMPONENT_REFs of the same
2927 type, we might be actually attempting to here to create a child of the
2928 same type as the parent. */
2929 if (!types_compatible_p (racc->type, lchild->type))
2931 struct access *new_acc
2932 = create_artificial_child_access (racc, lchild, norm_offset,
2933 true, false);
2934 propagate_subaccesses_from_lhs (lchild, new_acc);
2936 else
2937 propagate_subaccesses_from_lhs (lchild, racc);
2938 ret = true;
2940 return ret;
2943 /* Propagate all subaccesses across assignment links. */
2945 static void
2946 propagate_all_subaccesses (void)
2948 propagation_budget = new hash_map<tree, unsigned>;
2949 while (rhs_work_queue_head)
2951 struct access *racc = pop_access_from_rhs_work_queue ();
2952 struct assign_link *link;
2954 if (racc->group_representative)
2955 racc= racc->group_representative;
2956 gcc_assert (racc->first_rhs_link);
2958 for (link = racc->first_rhs_link; link; link = link->next_rhs)
2960 struct access *lacc = link->lacc;
2962 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
2963 continue;
2964 lacc = lacc->group_representative;
2966 bool reque_parents = false;
2967 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (racc->base)))
2969 if (!lacc->grp_write)
2971 subtree_mark_written_and_rhs_enqueue (lacc);
2972 reque_parents = true;
2975 else if (propagate_subaccesses_from_rhs (lacc, racc))
2976 reque_parents = true;
2978 if (reque_parents)
2981 add_access_to_rhs_work_queue (lacc);
2982 lacc = lacc->parent;
2984 while (lacc);
2988 while (lhs_work_queue_head)
2990 struct access *lacc = pop_access_from_lhs_work_queue ();
2991 struct assign_link *link;
2993 if (lacc->group_representative)
2994 lacc = lacc->group_representative;
2995 gcc_assert (lacc->first_lhs_link);
2997 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
2998 continue;
3000 for (link = lacc->first_lhs_link; link; link = link->next_lhs)
3002 struct access *racc = link->racc;
3004 if (racc->group_representative)
3005 racc = racc->group_representative;
3006 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (racc->base)))
3007 continue;
3008 if (propagate_subaccesses_from_lhs (lacc, racc))
3009 add_access_to_lhs_work_queue (racc);
3012 delete propagation_budget;
3015 /* Return true if the forest beginning with ROOT does not contain
3016 unscalarizable regions or non-byte aligned accesses. */
3018 static bool
3019 can_totally_scalarize_forest_p (struct access *root)
3021 struct access *access = root;
3024 if (access->grp_unscalarizable_region
3025 || (access->offset % BITS_PER_UNIT) != 0
3026 || (access->size % BITS_PER_UNIT) != 0
3027 || (is_gimple_reg_type (access->type)
3028 && access->first_child))
3029 return false;
3031 if (access->first_child)
3032 access = access->first_child;
3033 else if (access->next_sibling)
3034 access = access->next_sibling;
3035 else
3037 while (access->parent && !access->next_sibling)
3038 access = access->parent;
3039 if (access->next_sibling)
3040 access = access->next_sibling;
3041 else
3043 gcc_assert (access == root);
3044 root = root->next_grp;
3045 access = root;
3049 while (access);
3050 return true;
3053 /* Create and return an ACCESS in PARENT spanning from POS with SIZE, TYPE and
3054 reference EXPR for total scalarization purposes and mark it as such. Within
3055 the children of PARENT, link it in between PTR and NEXT_SIBLING. */
3057 static struct access *
3058 create_total_scalarization_access (struct access *parent, HOST_WIDE_INT pos,
3059 HOST_WIDE_INT size, tree type, tree expr,
3060 struct access **ptr,
3061 struct access *next_sibling)
3063 struct access *access = access_pool.allocate ();
3064 memset (access, 0, sizeof (struct access));
3065 access->base = parent->base;
3066 access->offset = pos;
3067 access->size = size;
3068 access->expr = expr;
3069 access->type = type;
3070 access->parent = parent;
3071 access->grp_write = parent->grp_write;
3072 access->grp_total_scalarization = 1;
3073 access->grp_hint = 1;
3074 access->grp_same_access_path = path_comparable_for_same_access (expr);
3075 access->reverse = reverse_storage_order_for_component_p (expr);
3077 access->next_sibling = next_sibling;
3078 *ptr = access;
3079 return access;
3082 /* Create and return an ACCESS in PARENT spanning from POS with SIZE, TYPE and
3083 reference EXPR for total scalarization purposes and mark it as such, link it
3084 at *PTR and reshape the tree so that those elements at *PTR and their
3085 siblings which fall within the part described by POS and SIZE are moved to
3086 be children of the new access. If a partial overlap is detected, return
3087 NULL. */
3089 static struct access *
3090 create_total_access_and_reshape (struct access *parent, HOST_WIDE_INT pos,
3091 HOST_WIDE_INT size, tree type, tree expr,
3092 struct access **ptr)
3094 struct access **p = ptr;
3096 while (*p && (*p)->offset < pos + size)
3098 if ((*p)->offset + (*p)->size > pos + size)
3099 return NULL;
3100 p = &(*p)->next_sibling;
3103 struct access *next_child = *ptr;
3104 struct access *new_acc
3105 = create_total_scalarization_access (parent, pos, size, type, expr,
3106 ptr, *p);
3107 if (p != ptr)
3109 new_acc->first_child = next_child;
3110 *p = NULL;
3111 for (struct access *a = next_child; a; a = a->next_sibling)
3112 a->parent = new_acc;
3114 return new_acc;
3117 static bool totally_scalarize_subtree (struct access *root);
3119 /* Return true if INNER is either the same type as OUTER or if it is the type
3120 of a record field in OUTER at offset zero, possibly in nested
3121 sub-records. */
3123 static bool
3124 access_and_field_type_match_p (tree outer, tree inner)
3126 if (TYPE_MAIN_VARIANT (outer) == TYPE_MAIN_VARIANT (inner))
3127 return true;
3128 if (TREE_CODE (outer) != RECORD_TYPE)
3129 return false;
3130 tree fld = TYPE_FIELDS (outer);
3131 while (fld)
3133 if (TREE_CODE (fld) == FIELD_DECL)
3135 if (!zerop (DECL_FIELD_OFFSET (fld)))
3136 return false;
3137 if (TYPE_MAIN_VARIANT (TREE_TYPE (fld)) == inner)
3138 return true;
3139 if (TREE_CODE (TREE_TYPE (fld)) == RECORD_TYPE)
3140 fld = TYPE_FIELDS (TREE_TYPE (fld));
3141 else
3142 return false;
3144 else
3145 fld = DECL_CHAIN (fld);
3147 return false;
3150 /* Return type of total_should_skip_creating_access indicating whether a total
3151 scalarization access for a field/element should be created, whether it
3152 already exists or whether the entire total scalarization has to fail. */
3154 enum total_sra_field_state {TOTAL_FLD_CREATE, TOTAL_FLD_DONE, TOTAL_FLD_FAILED};
3156 /* Do all the necessary steps in total scalarization when the given aggregate
3157 type has a TYPE at POS with the given SIZE should be put into PARENT and
3158 when we have processed all its siblings with smaller offsets up until and
3159 including LAST_SEEN_SIBLING (which can be NULL).
3161 If some further siblings are to be skipped, set *LAST_SEEN_SIBLING as
3162 appropriate. Return TOTAL_FLD_CREATE id the caller should carry on with
3163 creating a new access, TOTAL_FLD_DONE if access or accesses capable of
3164 representing the described part of the aggregate for the purposes of total
3165 scalarization already exist or TOTAL_FLD_FAILED if there is a problem which
3166 prevents total scalarization from happening at all. */
3168 static enum total_sra_field_state
3169 total_should_skip_creating_access (struct access *parent,
3170 struct access **last_seen_sibling,
3171 tree type, HOST_WIDE_INT pos,
3172 HOST_WIDE_INT size)
3174 struct access *next_child;
3175 if (!*last_seen_sibling)
3176 next_child = parent->first_child;
3177 else
3178 next_child = (*last_seen_sibling)->next_sibling;
3180 /* First, traverse the chain of siblings until it points to an access with
3181 offset at least equal to POS. Check all skipped accesses whether they
3182 span the POS boundary and if so, return with a failure. */
3183 while (next_child && next_child->offset < pos)
3185 if (next_child->offset + next_child->size > pos)
3186 return TOTAL_FLD_FAILED;
3187 *last_seen_sibling = next_child;
3188 next_child = next_child->next_sibling;
3191 /* Now check whether next_child has exactly the right POS and SIZE and if so,
3192 whether it can represent what we need and can be totally scalarized
3193 itself. */
3194 if (next_child && next_child->offset == pos
3195 && next_child->size == size)
3197 if (!is_gimple_reg_type (next_child->type)
3198 && (!access_and_field_type_match_p (type, next_child->type)
3199 || !totally_scalarize_subtree (next_child)))
3200 return TOTAL_FLD_FAILED;
3202 *last_seen_sibling = next_child;
3203 return TOTAL_FLD_DONE;
3206 /* If the child we're looking at would partially overlap, we just cannot
3207 totally scalarize. */
3208 if (next_child
3209 && next_child->offset < pos + size
3210 && next_child->offset + next_child->size > pos + size)
3211 return TOTAL_FLD_FAILED;
3213 if (is_gimple_reg_type (type))
3215 /* We don't scalarize accesses that are children of other scalar type
3216 accesses, so if we go on and create an access for a register type,
3217 there should not be any pre-existing children. There are rare cases
3218 where the requested type is a vector but we already have register
3219 accesses for all its elements which is equally good. Detect that
3220 situation or whether we need to bail out. */
3222 HOST_WIDE_INT covered = pos;
3223 bool skipping = false;
3224 while (next_child
3225 && next_child->offset + next_child->size <= pos + size)
3227 if (next_child->offset != covered
3228 || !is_gimple_reg_type (next_child->type))
3229 return TOTAL_FLD_FAILED;
3231 covered += next_child->size;
3232 *last_seen_sibling = next_child;
3233 next_child = next_child->next_sibling;
3234 skipping = true;
3237 if (skipping)
3239 if (covered != pos + size)
3240 return TOTAL_FLD_FAILED;
3241 else
3242 return TOTAL_FLD_DONE;
3246 return TOTAL_FLD_CREATE;
3249 /* Go over sub-tree rooted in ROOT and attempt to create scalar accesses
3250 spanning all uncovered areas covered by ROOT, return false if the attempt
3251 failed. All created accesses will have grp_unscalarizable_region set (and
3252 should be ignored if the function returns false). */
3254 static bool
3255 totally_scalarize_subtree (struct access *root)
3257 gcc_checking_assert (!root->grp_unscalarizable_region);
3258 gcc_checking_assert (!is_gimple_reg_type (root->type));
3260 struct access *last_seen_sibling = NULL;
3262 switch (TREE_CODE (root->type))
3264 case RECORD_TYPE:
3265 for (tree fld = TYPE_FIELDS (root->type); fld; fld = DECL_CHAIN (fld))
3266 if (TREE_CODE (fld) == FIELD_DECL)
3268 tree ft = TREE_TYPE (fld);
3269 HOST_WIDE_INT fsize = tree_to_uhwi (DECL_SIZE (fld));
3270 if (!fsize)
3271 continue;
3273 HOST_WIDE_INT pos = root->offset + int_bit_position (fld);
3274 enum total_sra_field_state
3275 state = total_should_skip_creating_access (root,
3276 &last_seen_sibling,
3277 ft, pos, fsize);
3278 switch (state)
3280 case TOTAL_FLD_FAILED:
3281 return false;
3282 case TOTAL_FLD_DONE:
3283 continue;
3284 case TOTAL_FLD_CREATE:
3285 break;
3286 default:
3287 gcc_unreachable ();
3290 struct access **p = (last_seen_sibling
3291 ? &last_seen_sibling->next_sibling
3292 : &root->first_child);
3293 tree nref = build3 (COMPONENT_REF, ft, root->expr, fld, NULL_TREE);
3294 struct access *new_child
3295 = create_total_access_and_reshape (root, pos, fsize, ft, nref, p);
3296 if (!new_child)
3297 return false;
3299 if (!is_gimple_reg_type (ft)
3300 && !totally_scalarize_subtree (new_child))
3301 return false;
3302 last_seen_sibling = new_child;
3304 break;
3305 case ARRAY_TYPE:
3307 tree elemtype = TREE_TYPE (root->type);
3308 tree elem_size = TYPE_SIZE (elemtype);
3309 gcc_assert (elem_size && tree_fits_shwi_p (elem_size));
3310 HOST_WIDE_INT el_size = tree_to_shwi (elem_size);
3311 gcc_assert (el_size > 0);
3313 tree minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (root->type));
3314 gcc_assert (TREE_CODE (minidx) == INTEGER_CST);
3315 tree maxidx = TYPE_MAX_VALUE (TYPE_DOMAIN (root->type));
3316 /* Skip (some) zero-length arrays; others have MAXIDX == MINIDX - 1. */
3317 if (!maxidx)
3318 goto out;
3319 gcc_assert (TREE_CODE (maxidx) == INTEGER_CST);
3320 tree domain = TYPE_DOMAIN (root->type);
3321 /* MINIDX and MAXIDX are inclusive, and must be interpreted in
3322 DOMAIN (e.g. signed int, whereas min/max may be size_int). */
3323 offset_int idx = wi::to_offset (minidx);
3324 offset_int max = wi::to_offset (maxidx);
3325 if (!TYPE_UNSIGNED (domain))
3327 idx = wi::sext (idx, TYPE_PRECISION (domain));
3328 max = wi::sext (max, TYPE_PRECISION (domain));
3330 for (HOST_WIDE_INT pos = root->offset;
3331 idx <= max;
3332 pos += el_size, ++idx)
3334 enum total_sra_field_state
3335 state = total_should_skip_creating_access (root,
3336 &last_seen_sibling,
3337 elemtype, pos,
3338 el_size);
3339 switch (state)
3341 case TOTAL_FLD_FAILED:
3342 return false;
3343 case TOTAL_FLD_DONE:
3344 continue;
3345 case TOTAL_FLD_CREATE:
3346 break;
3347 default:
3348 gcc_unreachable ();
3351 struct access **p = (last_seen_sibling
3352 ? &last_seen_sibling->next_sibling
3353 : &root->first_child);
3354 tree nref = build4 (ARRAY_REF, elemtype, root->expr,
3355 wide_int_to_tree (domain, idx),
3356 NULL_TREE, NULL_TREE);
3357 struct access *new_child
3358 = create_total_access_and_reshape (root, pos, el_size, elemtype,
3359 nref, p);
3360 if (!new_child)
3361 return false;
3363 if (!is_gimple_reg_type (elemtype)
3364 && !totally_scalarize_subtree (new_child))
3365 return false;
3366 last_seen_sibling = new_child;
3369 break;
3370 default:
3371 gcc_unreachable ();
3374 out:
3375 return true;
3378 /* Go through all accesses collected throughout the (intraprocedural) analysis
3379 stage, exclude overlapping ones, identify representatives and build trees
3380 out of them, making decisions about scalarization on the way. Return true
3381 iff there are any to-be-scalarized variables after this stage. */
3383 static bool
3384 analyze_all_variable_accesses (void)
3386 int res = 0;
3387 bitmap tmp = BITMAP_ALLOC (NULL);
3388 bitmap_iterator bi;
3389 unsigned i;
3391 bitmap_copy (tmp, candidate_bitmap);
3392 EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
3394 tree var = candidate (i);
3395 struct access *access;
3397 access = sort_and_splice_var_accesses (var);
3398 if (!access || !build_access_trees (access))
3399 disqualify_candidate (var,
3400 "No or inhibitingly overlapping accesses.");
3403 propagate_all_subaccesses ();
3405 bool optimize_speed_p = !optimize_function_for_size_p (cfun);
3406 /* If the user didn't set PARAM_SRA_MAX_SCALARIZATION_SIZE_<...>,
3407 fall back to a target default. */
3408 unsigned HOST_WIDE_INT max_scalarization_size
3409 = get_move_ratio (optimize_speed_p) * UNITS_PER_WORD;
3411 if (optimize_speed_p)
3413 if (global_options_set.x_param_sra_max_scalarization_size_speed)
3414 max_scalarization_size = param_sra_max_scalarization_size_speed;
3416 else
3418 if (global_options_set.x_param_sra_max_scalarization_size_size)
3419 max_scalarization_size = param_sra_max_scalarization_size_size;
3421 max_scalarization_size *= BITS_PER_UNIT;
3423 EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
3424 if (bitmap_bit_p (should_scalarize_away_bitmap, i)
3425 && !bitmap_bit_p (cannot_scalarize_away_bitmap, i))
3427 tree var = candidate (i);
3428 if (!VAR_P (var))
3429 continue;
3431 if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (var))) > max_scalarization_size)
3433 if (dump_file && (dump_flags & TDF_DETAILS))
3435 fprintf (dump_file, "Too big to totally scalarize: ");
3436 print_generic_expr (dump_file, var);
3437 fprintf (dump_file, " (UID: %u)\n", DECL_UID (var));
3439 continue;
3442 bool all_types_ok = true;
3443 for (struct access *access = get_first_repr_for_decl (var);
3444 access;
3445 access = access->next_grp)
3446 if (!can_totally_scalarize_forest_p (access)
3447 || !scalarizable_type_p (access->type, constant_decl_p (var)))
3449 all_types_ok = false;
3450 break;
3452 if (!all_types_ok)
3453 continue;
3455 if (dump_file && (dump_flags & TDF_DETAILS))
3457 fprintf (dump_file, "Will attempt to totally scalarize ");
3458 print_generic_expr (dump_file, var);
3459 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
3461 bool scalarized = true;
3462 for (struct access *access = get_first_repr_for_decl (var);
3463 access;
3464 access = access->next_grp)
3465 if (!is_gimple_reg_type (access->type)
3466 && !totally_scalarize_subtree (access))
3468 scalarized = false;
3469 break;
3472 if (scalarized)
3473 for (struct access *access = get_first_repr_for_decl (var);
3474 access;
3475 access = access->next_grp)
3476 access->grp_total_scalarization = true;
3479 if (flag_checking)
3480 verify_all_sra_access_forests ();
3482 bitmap_copy (tmp, candidate_bitmap);
3483 EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
3485 tree var = candidate (i);
3486 struct access *access = get_first_repr_for_decl (var);
3488 if (analyze_access_trees (access))
3490 res++;
3491 if (dump_file && (dump_flags & TDF_DETAILS))
3493 fprintf (dump_file, "\nAccess trees for ");
3494 print_generic_expr (dump_file, var);
3495 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
3496 dump_access_tree (dump_file, access);
3497 fprintf (dump_file, "\n");
3500 else
3501 disqualify_candidate (var, "No scalar replacements to be created.");
3504 BITMAP_FREE (tmp);
3506 if (res)
3508 statistics_counter_event (cfun, "Scalarized aggregates", res);
3509 return true;
3511 else
3512 return false;
3515 /* Generate statements copying scalar replacements of accesses within a subtree
3516 into or out of AGG. ACCESS, all its children, siblings and their children
3517 are to be processed. AGG is an aggregate type expression (can be a
3518 declaration but does not have to be, it can for example also be a mem_ref or
3519 a series of handled components). TOP_OFFSET is the offset of the processed
3520 subtree which has to be subtracted from offsets of individual accesses to
3521 get corresponding offsets for AGG. If CHUNK_SIZE is non-null, copy only
3522 replacements in the interval <start_offset, start_offset + chunk_size>,
3523 otherwise copy all. GSI is a statement iterator used to place the new
3524 statements. WRITE should be true when the statements should write from AGG
3525 to the replacement and false if vice versa. if INSERT_AFTER is true, new
3526 statements will be added after the current statement in GSI, they will be
3527 added before the statement otherwise. */
3529 static void
3530 generate_subtree_copies (struct access *access, tree agg,
3531 HOST_WIDE_INT top_offset,
3532 HOST_WIDE_INT start_offset, HOST_WIDE_INT chunk_size,
3533 gimple_stmt_iterator *gsi, bool write,
3534 bool insert_after, location_t loc)
3536 /* Never write anything into constant pool decls. See PR70602. */
3537 if (!write && constant_decl_p (agg))
3538 return;
3541 if (chunk_size && access->offset >= start_offset + chunk_size)
3542 return;
3544 if (access->grp_to_be_replaced
3545 && (chunk_size == 0
3546 || access->offset + access->size > start_offset))
3548 tree expr, repl = get_access_replacement (access);
3549 gassign *stmt;
3551 expr = build_ref_for_model (loc, agg, access->offset - top_offset,
3552 access, gsi, insert_after);
3554 if (write)
3556 if (access->grp_partial_lhs)
3557 expr = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
3558 !insert_after,
3559 insert_after ? GSI_NEW_STMT
3560 : GSI_SAME_STMT);
3561 stmt = gimple_build_assign (repl, expr);
3563 else
3565 suppress_warning (repl /* Be more selective! */);
3566 if (access->grp_partial_lhs)
3567 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
3568 !insert_after,
3569 insert_after ? GSI_NEW_STMT
3570 : GSI_SAME_STMT);
3571 stmt = gimple_build_assign (expr, repl);
3573 gimple_set_location (stmt, loc);
3575 if (insert_after)
3576 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
3577 else
3578 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3579 update_stmt (stmt);
3580 sra_stats.subtree_copies++;
3582 else if (write
3583 && access->grp_to_be_debug_replaced
3584 && (chunk_size == 0
3585 || access->offset + access->size > start_offset))
3587 gdebug *ds;
3588 tree drhs = build_debug_ref_for_model (loc, agg,
3589 access->offset - top_offset,
3590 access);
3591 ds = gimple_build_debug_bind (get_access_replacement (access),
3592 drhs, gsi_stmt (*gsi));
3593 if (insert_after)
3594 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
3595 else
3596 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
3599 if (access->first_child)
3600 generate_subtree_copies (access->first_child, agg, top_offset,
3601 start_offset, chunk_size, gsi,
3602 write, insert_after, loc);
3604 access = access->next_sibling;
3606 while (access);
3609 /* Assign zero to all scalar replacements in an access subtree. ACCESS is the
3610 root of the subtree to be processed. GSI is the statement iterator used
3611 for inserting statements which are added after the current statement if
3612 INSERT_AFTER is true or before it otherwise. */
3614 static void
3615 init_subtree_with_zero (struct access *access, gimple_stmt_iterator *gsi,
3616 bool insert_after, location_t loc)
3619 struct access *child;
3621 if (access->grp_to_be_replaced)
3623 gassign *stmt;
3625 stmt = gimple_build_assign (get_access_replacement (access),
3626 build_zero_cst (access->type));
3627 if (insert_after)
3628 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
3629 else
3630 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3631 update_stmt (stmt);
3632 gimple_set_location (stmt, loc);
3634 else if (access->grp_to_be_debug_replaced)
3636 gdebug *ds
3637 = gimple_build_debug_bind (get_access_replacement (access),
3638 build_zero_cst (access->type),
3639 gsi_stmt (*gsi));
3640 if (insert_after)
3641 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
3642 else
3643 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
3646 for (child = access->first_child; child; child = child->next_sibling)
3647 init_subtree_with_zero (child, gsi, insert_after, loc);
3650 /* Clobber all scalar replacements in an access subtree. ACCESS is the
3651 root of the subtree to be processed. GSI is the statement iterator used
3652 for inserting statements which are added after the current statement if
3653 INSERT_AFTER is true or before it otherwise. */
3655 static void
3656 clobber_subtree (struct access *access, gimple_stmt_iterator *gsi,
3657 bool insert_after, location_t loc)
3660 struct access *child;
3662 if (access->grp_to_be_replaced)
3664 tree rep = get_access_replacement (access);
3665 tree clobber = build_clobber (access->type);
3666 gimple *stmt = gimple_build_assign (rep, clobber);
3668 if (insert_after)
3669 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
3670 else
3671 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3672 update_stmt (stmt);
3673 gimple_set_location (stmt, loc);
3676 for (child = access->first_child; child; child = child->next_sibling)
3677 clobber_subtree (child, gsi, insert_after, loc);
3680 /* Search for an access representative for the given expression EXPR and
3681 return it or NULL if it cannot be found. */
3683 static struct access *
3684 get_access_for_expr (tree expr)
3686 poly_int64 poffset, psize, pmax_size;
3687 HOST_WIDE_INT offset, max_size;
3688 tree base;
3689 bool reverse;
3691 /* FIXME: This should not be necessary but Ada produces V_C_Es with a type of
3692 a different size than the size of its argument and we need the latter
3693 one. */
3694 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
3695 expr = TREE_OPERAND (expr, 0);
3697 base = get_ref_base_and_extent (expr, &poffset, &psize, &pmax_size,
3698 &reverse);
3699 if (!known_size_p (pmax_size)
3700 || !pmax_size.is_constant (&max_size)
3701 || !poffset.is_constant (&offset)
3702 || !DECL_P (base))
3703 return NULL;
3705 if (tree basesize = DECL_SIZE (base))
3707 poly_int64 sz;
3708 if (offset < 0
3709 || !poly_int_tree_p (basesize, &sz)
3710 || known_le (sz, offset))
3711 return NULL;
3714 if (max_size == 0
3715 || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
3716 return NULL;
3718 return get_var_base_offset_size_access (base, offset, max_size);
3721 /* Replace the expression EXPR with a scalar replacement if there is one and
3722 generate other statements to do type conversion or subtree copying if
3723 necessary. GSI is used to place newly created statements, WRITE is true if
3724 the expression is being written to (it is on a LHS of a statement or output
3725 in an assembly statement). */
3727 static bool
3728 sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
3730 location_t loc;
3731 struct access *access;
3732 tree type, bfr, orig_expr;
3733 bool partial_cplx_access = false;
3735 if (TREE_CODE (*expr) == BIT_FIELD_REF)
3737 bfr = *expr;
3738 expr = &TREE_OPERAND (*expr, 0);
3740 else
3741 bfr = NULL_TREE;
3743 if (TREE_CODE (*expr) == REALPART_EXPR || TREE_CODE (*expr) == IMAGPART_EXPR)
3745 expr = &TREE_OPERAND (*expr, 0);
3746 partial_cplx_access = true;
3748 access = get_access_for_expr (*expr);
3749 if (!access)
3750 return false;
3751 type = TREE_TYPE (*expr);
3752 orig_expr = *expr;
3754 loc = gimple_location (gsi_stmt (*gsi));
3755 gimple_stmt_iterator alt_gsi = gsi_none ();
3756 if (write && stmt_ends_bb_p (gsi_stmt (*gsi)))
3758 alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi)));
3759 gsi = &alt_gsi;
3762 if (access->grp_to_be_replaced)
3764 tree repl = get_access_replacement (access);
3765 /* If we replace a non-register typed access simply use the original
3766 access expression to extract the scalar component afterwards.
3767 This happens if scalarizing a function return value or parameter
3768 like in gcc.c-torture/execute/20041124-1.c, 20050316-1.c and
3769 gcc.c-torture/compile/20011217-1.c.
3771 We also want to use this when accessing a complex or vector which can
3772 be accessed as a different type too, potentially creating a need for
3773 type conversion (see PR42196) and when scalarized unions are involved
3774 in assembler statements (see PR42398). */
3775 if (!bfr && !useless_type_conversion_p (type, access->type))
3777 tree ref;
3779 ref = build_ref_for_model (loc, orig_expr, 0, access, gsi, false);
3781 if (partial_cplx_access)
3783 /* VIEW_CONVERT_EXPRs in partial complex access are always fine in
3784 the case of a write because in such case the replacement cannot
3785 be a gimple register. In the case of a load, we have to
3786 differentiate in between a register an non-register
3787 replacement. */
3788 tree t = build1 (VIEW_CONVERT_EXPR, type, repl);
3789 gcc_checking_assert (!write || access->grp_partial_lhs);
3790 if (!access->grp_partial_lhs)
3792 tree tmp = make_ssa_name (type);
3793 gassign *stmt = gimple_build_assign (tmp, t);
3794 /* This is always a read. */
3795 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3796 t = tmp;
3798 *expr = t;
3800 else if (write)
3802 gassign *stmt;
3804 if (access->grp_partial_lhs)
3805 ref = force_gimple_operand_gsi (gsi, ref, true, NULL_TREE,
3806 false, GSI_NEW_STMT);
3807 stmt = gimple_build_assign (repl, ref);
3808 gimple_set_location (stmt, loc);
3809 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
3811 else
3813 gassign *stmt;
3815 if (access->grp_partial_lhs)
3816 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
3817 true, GSI_SAME_STMT);
3818 stmt = gimple_build_assign (ref, repl);
3819 gimple_set_location (stmt, loc);
3820 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3823 else
3824 *expr = repl;
3825 sra_stats.exprs++;
3827 else if (write && access->grp_to_be_debug_replaced)
3829 gdebug *ds = gimple_build_debug_bind (get_access_replacement (access),
3830 NULL_TREE,
3831 gsi_stmt (*gsi));
3832 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
3835 if (access->first_child && !TREE_READONLY (access->base))
3837 HOST_WIDE_INT start_offset, chunk_size;
3838 if (bfr
3839 && tree_fits_uhwi_p (TREE_OPERAND (bfr, 1))
3840 && tree_fits_uhwi_p (TREE_OPERAND (bfr, 2)))
3842 chunk_size = tree_to_uhwi (TREE_OPERAND (bfr, 1));
3843 start_offset = access->offset
3844 + tree_to_uhwi (TREE_OPERAND (bfr, 2));
3846 else
3847 start_offset = chunk_size = 0;
3849 generate_subtree_copies (access->first_child, orig_expr, access->offset,
3850 start_offset, chunk_size, gsi, write, write,
3851 loc);
3853 return true;
3856 /* Where scalar replacements of the RHS have been written to when a replacement
3857 of a LHS of an assigments cannot be direclty loaded from a replacement of
3858 the RHS. */
3859 enum unscalarized_data_handling { SRA_UDH_NONE, /* Nothing done so far. */
3860 SRA_UDH_RIGHT, /* Data flushed to the RHS. */
3861 SRA_UDH_LEFT }; /* Data flushed to the LHS. */
3863 struct subreplacement_assignment_data
3865 /* Offset of the access representing the lhs of the assignment. */
3866 HOST_WIDE_INT left_offset;
3868 /* LHS and RHS of the original assignment. */
3869 tree assignment_lhs, assignment_rhs;
3871 /* Access representing the rhs of the whole assignment. */
3872 struct access *top_racc;
3874 /* Stmt iterator used for statement insertions after the original assignment.
3875 It points to the main GSI used to traverse a BB during function body
3876 modification. */
3877 gimple_stmt_iterator *new_gsi;
3879 /* Stmt iterator used for statement insertions before the original
3880 assignment. Keeps on pointing to the original statement. */
3881 gimple_stmt_iterator old_gsi;
3883 /* Location of the assignment. */
3884 location_t loc;
3886 /* Keeps the information whether we have needed to refresh replacements of
3887 the LHS and from which side of the assignments this takes place. */
3888 enum unscalarized_data_handling refreshed;
3891 /* Store all replacements in the access tree rooted in TOP_RACC either to their
3892 base aggregate if there are unscalarized data or directly to LHS of the
3893 statement that is pointed to by GSI otherwise. */
3895 static void
3896 handle_unscalarized_data_in_subtree (struct subreplacement_assignment_data *sad)
3898 tree src;
3899 /* If the RHS is a load from a constant, we do not need to (and must not)
3900 flush replacements to it and can use it directly as if we did. */
3901 if (TREE_READONLY (sad->top_racc->base))
3903 sad->refreshed = SRA_UDH_RIGHT;
3904 return;
3906 if (sad->top_racc->grp_unscalarized_data)
3908 src = sad->assignment_rhs;
3909 sad->refreshed = SRA_UDH_RIGHT;
3911 else
3913 src = sad->assignment_lhs;
3914 sad->refreshed = SRA_UDH_LEFT;
3916 generate_subtree_copies (sad->top_racc->first_child, src,
3917 sad->top_racc->offset, 0, 0,
3918 &sad->old_gsi, false, false, sad->loc);
3921 /* Try to generate statements to load all sub-replacements in an access subtree
3922 formed by children of LACC from scalar replacements in the SAD->top_racc
3923 subtree. If that is not possible, refresh the SAD->top_racc base aggregate
3924 and load the accesses from it. */
3926 static void
3927 load_assign_lhs_subreplacements (struct access *lacc,
3928 struct subreplacement_assignment_data *sad)
3930 for (lacc = lacc->first_child; lacc; lacc = lacc->next_sibling)
3932 HOST_WIDE_INT offset;
3933 offset = lacc->offset - sad->left_offset + sad->top_racc->offset;
3935 if (lacc->grp_to_be_replaced)
3937 struct access *racc;
3938 gassign *stmt;
3939 tree rhs;
3941 racc = find_access_in_subtree (sad->top_racc, offset, lacc->size);
3942 if (racc && racc->grp_to_be_replaced)
3944 rhs = get_access_replacement (racc);
3945 if (!useless_type_conversion_p (lacc->type, racc->type))
3946 rhs = fold_build1_loc (sad->loc, VIEW_CONVERT_EXPR,
3947 lacc->type, rhs);
3949 if (racc->grp_partial_lhs && lacc->grp_partial_lhs)
3950 rhs = force_gimple_operand_gsi (&sad->old_gsi, rhs, true,
3951 NULL_TREE, true, GSI_SAME_STMT);
3953 else
3955 /* No suitable access on the right hand side, need to load from
3956 the aggregate. See if we have to update it first... */
3957 if (sad->refreshed == SRA_UDH_NONE)
3958 handle_unscalarized_data_in_subtree (sad);
3960 if (sad->refreshed == SRA_UDH_LEFT)
3961 rhs = build_ref_for_model (sad->loc, sad->assignment_lhs,
3962 lacc->offset - sad->left_offset,
3963 lacc, sad->new_gsi, true);
3964 else
3965 rhs = build_ref_for_model (sad->loc, sad->assignment_rhs,
3966 lacc->offset - sad->left_offset,
3967 lacc, sad->new_gsi, true);
3968 if (lacc->grp_partial_lhs)
3969 rhs = force_gimple_operand_gsi (sad->new_gsi,
3970 rhs, true, NULL_TREE,
3971 false, GSI_NEW_STMT);
3974 stmt = gimple_build_assign (get_access_replacement (lacc), rhs);
3975 gsi_insert_after (sad->new_gsi, stmt, GSI_NEW_STMT);
3976 gimple_set_location (stmt, sad->loc);
3977 update_stmt (stmt);
3978 sra_stats.subreplacements++;
3980 else
3982 if (sad->refreshed == SRA_UDH_NONE
3983 && lacc->grp_read && !lacc->grp_covered)
3984 handle_unscalarized_data_in_subtree (sad);
3986 if (lacc && lacc->grp_to_be_debug_replaced)
3988 gdebug *ds;
3989 tree drhs;
3990 struct access *racc = find_access_in_subtree (sad->top_racc,
3991 offset,
3992 lacc->size);
3994 if (racc && racc->grp_to_be_replaced)
3996 if (racc->grp_write || constant_decl_p (racc->base))
3997 drhs = get_access_replacement (racc);
3998 else
3999 drhs = NULL;
4001 else if (sad->refreshed == SRA_UDH_LEFT)
4002 drhs = build_debug_ref_for_model (sad->loc, lacc->base,
4003 lacc->offset, lacc);
4004 else if (sad->refreshed == SRA_UDH_RIGHT)
4005 drhs = build_debug_ref_for_model (sad->loc, sad->top_racc->base,
4006 offset, lacc);
4007 else
4008 drhs = NULL_TREE;
4009 if (drhs
4010 && !useless_type_conversion_p (lacc->type, TREE_TYPE (drhs)))
4011 drhs = fold_build1_loc (sad->loc, VIEW_CONVERT_EXPR,
4012 lacc->type, drhs);
4013 ds = gimple_build_debug_bind (get_access_replacement (lacc),
4014 drhs, gsi_stmt (sad->old_gsi));
4015 gsi_insert_after (sad->new_gsi, ds, GSI_NEW_STMT);
4019 if (lacc->first_child)
4020 load_assign_lhs_subreplacements (lacc, sad);
4024 /* Result code for SRA assignment modification. */
4025 enum assignment_mod_result { SRA_AM_NONE, /* nothing done for the stmt */
4026 SRA_AM_MODIFIED, /* stmt changed but not
4027 removed */
4028 SRA_AM_REMOVED }; /* stmt eliminated */
4030 /* Modify assignments with a CONSTRUCTOR on their RHS. STMT contains a pointer
4031 to the assignment and GSI is the statement iterator pointing at it. Returns
4032 the same values as sra_modify_assign. */
4034 static enum assignment_mod_result
4035 sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
4037 tree lhs = gimple_assign_lhs (stmt);
4038 struct access *acc = get_access_for_expr (lhs);
4039 if (!acc)
4040 return SRA_AM_NONE;
4041 location_t loc = gimple_location (stmt);
4043 if (gimple_clobber_p (stmt))
4045 /* Clobber the replacement variable. */
4046 clobber_subtree (acc, gsi, !acc->grp_covered, loc);
4047 /* Remove clobbers of fully scalarized variables, they are dead. */
4048 if (acc->grp_covered)
4050 unlink_stmt_vdef (stmt);
4051 gsi_remove (gsi, true);
4052 release_defs (stmt);
4053 return SRA_AM_REMOVED;
4055 else
4056 return SRA_AM_MODIFIED;
4059 if (CONSTRUCTOR_NELTS (gimple_assign_rhs1 (stmt)) > 0)
4061 /* I have never seen this code path trigger but if it can happen the
4062 following should handle it gracefully. */
4063 if (access_has_children_p (acc))
4064 generate_subtree_copies (acc->first_child, lhs, acc->offset, 0, 0, gsi,
4065 true, true, loc);
4066 return SRA_AM_MODIFIED;
4069 if (acc->grp_covered)
4071 init_subtree_with_zero (acc, gsi, false, loc);
4072 unlink_stmt_vdef (stmt);
4073 gsi_remove (gsi, true);
4074 release_defs (stmt);
4075 return SRA_AM_REMOVED;
4077 else
4079 init_subtree_with_zero (acc, gsi, true, loc);
4080 return SRA_AM_MODIFIED;
4084 /* Create and return a new suitable default definition SSA_NAME for RACC which
4085 is an access describing an uninitialized part of an aggregate that is being
4086 loaded. REG_TREE is used instead of the actual RACC type if that is not of
4087 a gimple register type. */
4089 static tree
4090 get_repl_default_def_ssa_name (struct access *racc, tree reg_type)
4092 gcc_checking_assert (!racc->grp_to_be_replaced
4093 && !racc->grp_to_be_debug_replaced);
4094 if (!racc->replacement_decl)
4095 racc->replacement_decl = create_access_replacement (racc, reg_type);
4096 return get_or_create_ssa_default_def (cfun, racc->replacement_decl);
4099 /* Examine both sides of the assignment statement pointed to by STMT, replace
4100 them with a scalare replacement if there is one and generate copying of
4101 replacements if scalarized aggregates have been used in the assignment. GSI
4102 is used to hold generated statements for type conversions and subtree
4103 copying. */
4105 static enum assignment_mod_result
4106 sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi)
4108 struct access *lacc, *racc;
4109 tree lhs, rhs;
4110 bool modify_this_stmt = false;
4111 bool force_gimple_rhs = false;
4112 location_t loc;
4113 gimple_stmt_iterator orig_gsi = *gsi;
4115 if (!gimple_assign_single_p (stmt))
4116 return SRA_AM_NONE;
4117 lhs = gimple_assign_lhs (stmt);
4118 rhs = gimple_assign_rhs1 (stmt);
4120 if (TREE_CODE (rhs) == CONSTRUCTOR)
4121 return sra_modify_constructor_assign (stmt, gsi);
4123 if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (lhs) == REALPART_EXPR
4124 || TREE_CODE (rhs) == IMAGPART_EXPR || TREE_CODE (lhs) == IMAGPART_EXPR
4125 || TREE_CODE (rhs) == BIT_FIELD_REF || TREE_CODE (lhs) == BIT_FIELD_REF)
4127 modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (stmt),
4128 gsi, false);
4129 modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (stmt),
4130 gsi, true);
4131 return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
4134 lacc = get_access_for_expr (lhs);
4135 racc = get_access_for_expr (rhs);
4136 if (!lacc && !racc)
4137 return SRA_AM_NONE;
4138 /* Avoid modifying initializations of constant-pool replacements. */
4139 if (racc && (racc->replacement_decl == lhs))
4140 return SRA_AM_NONE;
4142 loc = gimple_location (stmt);
4143 if (lacc && lacc->grp_to_be_replaced)
4145 lhs = get_access_replacement (lacc);
4146 gimple_assign_set_lhs (stmt, lhs);
4147 modify_this_stmt = true;
4148 if (lacc->grp_partial_lhs)
4149 force_gimple_rhs = true;
4150 sra_stats.exprs++;
4153 if (racc && racc->grp_to_be_replaced)
4155 rhs = get_access_replacement (racc);
4156 modify_this_stmt = true;
4157 if (racc->grp_partial_lhs)
4158 force_gimple_rhs = true;
4159 sra_stats.exprs++;
4161 else if (racc
4162 && !racc->grp_unscalarized_data
4163 && !racc->grp_unscalarizable_region
4164 && TREE_CODE (lhs) == SSA_NAME
4165 && !access_has_replacements_p (racc))
4167 rhs = get_repl_default_def_ssa_name (racc, TREE_TYPE (lhs));
4168 modify_this_stmt = true;
4169 sra_stats.exprs++;
4172 if (modify_this_stmt)
4174 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
4176 /* If we can avoid creating a VIEW_CONVERT_EXPR do so.
4177 ??? This should move to fold_stmt which we simply should
4178 call after building a VIEW_CONVERT_EXPR here. */
4179 if (AGGREGATE_TYPE_P (TREE_TYPE (lhs))
4180 && !contains_bitfld_component_ref_p (lhs))
4182 lhs = build_ref_for_model (loc, lhs, 0, racc, gsi, false);
4183 gimple_assign_set_lhs (stmt, lhs);
4185 else if (lacc
4186 && AGGREGATE_TYPE_P (TREE_TYPE (rhs))
4187 && !contains_vce_or_bfcref_p (rhs))
4188 rhs = build_ref_for_model (loc, rhs, 0, lacc, gsi, false);
4190 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
4192 rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
4193 rhs);
4194 if (is_gimple_reg_type (TREE_TYPE (lhs))
4195 && TREE_CODE (lhs) != SSA_NAME)
4196 force_gimple_rhs = true;
4201 if (lacc && lacc->grp_to_be_debug_replaced)
4203 tree dlhs = get_access_replacement (lacc);
4204 tree drhs = unshare_expr (rhs);
4205 if (!useless_type_conversion_p (TREE_TYPE (dlhs), TREE_TYPE (drhs)))
4207 if (AGGREGATE_TYPE_P (TREE_TYPE (drhs))
4208 && !contains_vce_or_bfcref_p (drhs))
4209 drhs = build_debug_ref_for_model (loc, drhs, 0, lacc);
4210 if (drhs
4211 && !useless_type_conversion_p (TREE_TYPE (dlhs),
4212 TREE_TYPE (drhs)))
4213 drhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
4214 TREE_TYPE (dlhs), drhs);
4216 gdebug *ds = gimple_build_debug_bind (dlhs, drhs, stmt);
4217 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
4220 /* From this point on, the function deals with assignments in between
4221 aggregates when at least one has scalar reductions of some of its
4222 components. There are three possible scenarios: Both the LHS and RHS have
4223 to-be-scalarized components, 2) only the RHS has or 3) only the LHS has.
4225 In the first case, we would like to load the LHS components from RHS
4226 components whenever possible. If that is not possible, we would like to
4227 read it directly from the RHS (after updating it by storing in it its own
4228 components). If there are some necessary unscalarized data in the LHS,
4229 those will be loaded by the original assignment too. If neither of these
4230 cases happen, the original statement can be removed. Most of this is done
4231 by load_assign_lhs_subreplacements.
4233 In the second case, we would like to store all RHS scalarized components
4234 directly into LHS and if they cover the aggregate completely, remove the
4235 statement too. In the third case, we want the LHS components to be loaded
4236 directly from the RHS (DSE will remove the original statement if it
4237 becomes redundant).
4239 This is a bit complex but manageable when types match and when unions do
4240 not cause confusion in a way that we cannot really load a component of LHS
4241 from the RHS or vice versa (the access representing this level can have
4242 subaccesses that are accessible only through a different union field at a
4243 higher level - different from the one used in the examined expression).
4244 Unions are fun.
4246 Therefore, I specially handle a fourth case, happening when there is a
4247 specific type cast or it is impossible to locate a scalarized subaccess on
4248 the other side of the expression. If that happens, I simply "refresh" the
4249 RHS by storing in it is scalarized components leave the original statement
4250 there to do the copying and then load the scalar replacements of the LHS.
4251 This is what the first branch does. */
4253 if (modify_this_stmt
4254 || gimple_has_volatile_ops (stmt)
4255 || contains_vce_or_bfcref_p (rhs)
4256 || contains_vce_or_bfcref_p (lhs)
4257 || stmt_ends_bb_p (stmt))
4259 /* No need to copy into a constant, it comes pre-initialized. */
4260 if (access_has_children_p (racc) && !TREE_READONLY (racc->base))
4261 generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0,
4262 gsi, false, false, loc);
4263 if (access_has_children_p (lacc))
4265 gimple_stmt_iterator alt_gsi = gsi_none ();
4266 if (stmt_ends_bb_p (stmt))
4268 alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi)));
4269 gsi = &alt_gsi;
4271 generate_subtree_copies (lacc->first_child, lhs, lacc->offset, 0, 0,
4272 gsi, true, true, loc);
4274 sra_stats.separate_lhs_rhs_handling++;
4276 /* This gimplification must be done after generate_subtree_copies,
4277 lest we insert the subtree copies in the middle of the gimplified
4278 sequence. */
4279 if (force_gimple_rhs)
4280 rhs = force_gimple_operand_gsi (&orig_gsi, rhs, true, NULL_TREE,
4281 true, GSI_SAME_STMT);
4282 if (gimple_assign_rhs1 (stmt) != rhs)
4284 modify_this_stmt = true;
4285 gimple_assign_set_rhs_from_tree (&orig_gsi, rhs);
4286 gcc_assert (stmt == gsi_stmt (orig_gsi));
4289 return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
4291 else
4293 if (access_has_children_p (lacc)
4294 && access_has_children_p (racc)
4295 /* When an access represents an unscalarizable region, it usually
4296 represents accesses with variable offset and thus must not be used
4297 to generate new memory accesses. */
4298 && !lacc->grp_unscalarizable_region
4299 && !racc->grp_unscalarizable_region)
4301 struct subreplacement_assignment_data sad;
4303 sad.left_offset = lacc->offset;
4304 sad.assignment_lhs = lhs;
4305 sad.assignment_rhs = rhs;
4306 sad.top_racc = racc;
4307 sad.old_gsi = *gsi;
4308 sad.new_gsi = gsi;
4309 sad.loc = gimple_location (stmt);
4310 sad.refreshed = SRA_UDH_NONE;
4312 if (lacc->grp_read && !lacc->grp_covered)
4313 handle_unscalarized_data_in_subtree (&sad);
4315 load_assign_lhs_subreplacements (lacc, &sad);
4316 if (sad.refreshed != SRA_UDH_RIGHT)
4318 gsi_next (gsi);
4319 unlink_stmt_vdef (stmt);
4320 gsi_remove (&sad.old_gsi, true);
4321 release_defs (stmt);
4322 sra_stats.deleted++;
4323 return SRA_AM_REMOVED;
4326 else
4328 if (access_has_children_p (racc)
4329 && !racc->grp_unscalarized_data
4330 && TREE_CODE (lhs) != SSA_NAME)
4332 if (dump_file)
4334 fprintf (dump_file, "Removing load: ");
4335 print_gimple_stmt (dump_file, stmt, 0);
4337 generate_subtree_copies (racc->first_child, lhs,
4338 racc->offset, 0, 0, gsi,
4339 false, false, loc);
4340 gcc_assert (stmt == gsi_stmt (*gsi));
4341 unlink_stmt_vdef (stmt);
4342 gsi_remove (gsi, true);
4343 release_defs (stmt);
4344 sra_stats.deleted++;
4345 return SRA_AM_REMOVED;
4347 /* Restore the aggregate RHS from its components so the
4348 prevailing aggregate copy does the right thing. */
4349 if (access_has_children_p (racc) && !TREE_READONLY (racc->base))
4350 generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0,
4351 gsi, false, false, loc);
4352 /* Re-load the components of the aggregate copy destination.
4353 But use the RHS aggregate to load from to expose more
4354 optimization opportunities. */
4355 if (access_has_children_p (lacc))
4356 generate_subtree_copies (lacc->first_child, rhs, lacc->offset,
4357 0, 0, gsi, true, true, loc);
4360 return SRA_AM_NONE;
4364 /* Set any scalar replacements of values in the constant pool to the initial
4365 value of the constant. (Constant-pool decls like *.LC0 have effectively
4366 been initialized before the program starts, we must do the same for their
4367 replacements.) Thus, we output statements like 'SR.1 = *.LC0[0];' into
4368 the function's entry block. */
4370 static void
4371 initialize_constant_pool_replacements (void)
4373 gimple_seq seq = NULL;
4374 gimple_stmt_iterator gsi = gsi_start (seq);
4375 bitmap_iterator bi;
4376 unsigned i;
4378 EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
4380 tree var = candidate (i);
4381 if (!constant_decl_p (var))
4382 continue;
4384 struct access *access = get_first_repr_for_decl (var);
4386 while (access)
4388 if (access->replacement_decl)
4390 gassign *stmt
4391 = gimple_build_assign (get_access_replacement (access),
4392 unshare_expr (access->expr));
4393 if (dump_file && (dump_flags & TDF_DETAILS))
4395 fprintf (dump_file, "Generating constant initializer: ");
4396 print_gimple_stmt (dump_file, stmt, 0);
4397 fprintf (dump_file, "\n");
4399 gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
4400 update_stmt (stmt);
4403 if (access->first_child)
4404 access = access->first_child;
4405 else if (access->next_sibling)
4406 access = access->next_sibling;
4407 else
4409 while (access->parent && !access->next_sibling)
4410 access = access->parent;
4411 if (access->next_sibling)
4412 access = access->next_sibling;
4413 else
4414 access = access->next_grp;
4419 seq = gsi_seq (gsi);
4420 if (seq)
4421 gsi_insert_seq_on_edge_immediate (
4422 single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
4425 /* Traverse the function body and all modifications as decided in
4426 analyze_all_variable_accesses. Return true iff the CFG has been
4427 changed. */
4429 static bool
4430 sra_modify_function_body (void)
4432 bool cfg_changed = false;
4433 basic_block bb;
4435 initialize_constant_pool_replacements ();
4437 FOR_EACH_BB_FN (bb, cfun)
4439 gimple_stmt_iterator gsi = gsi_start_bb (bb);
4440 while (!gsi_end_p (gsi))
4442 gimple *stmt = gsi_stmt (gsi);
4443 enum assignment_mod_result assign_result;
4444 bool modified = false, deleted = false;
4445 tree *t;
4446 unsigned i;
4448 switch (gimple_code (stmt))
4450 case GIMPLE_RETURN:
4451 t = gimple_return_retval_ptr (as_a <greturn *> (stmt));
4452 if (*t != NULL_TREE)
4453 modified |= sra_modify_expr (t, &gsi, false);
4454 break;
4456 case GIMPLE_ASSIGN:
4457 assign_result = sra_modify_assign (stmt, &gsi);
4458 modified |= assign_result == SRA_AM_MODIFIED;
4459 deleted = assign_result == SRA_AM_REMOVED;
4460 break;
4462 case GIMPLE_CALL:
4463 /* Operands must be processed before the lhs. */
4464 for (i = 0; i < gimple_call_num_args (stmt); i++)
4466 t = gimple_call_arg_ptr (stmt, i);
4467 modified |= sra_modify_expr (t, &gsi, false);
4470 if (gimple_call_lhs (stmt))
4472 t = gimple_call_lhs_ptr (stmt);
4473 modified |= sra_modify_expr (t, &gsi, true);
4475 break;
4477 case GIMPLE_ASM:
4479 gasm *asm_stmt = as_a <gasm *> (stmt);
4480 for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
4482 t = &TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
4483 modified |= sra_modify_expr (t, &gsi, false);
4485 for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
4487 t = &TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
4488 modified |= sra_modify_expr (t, &gsi, true);
4491 break;
4493 default:
4494 break;
4497 if (modified)
4499 update_stmt (stmt);
4500 if (maybe_clean_eh_stmt (stmt)
4501 && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
4502 cfg_changed = true;
4504 if (!deleted)
4505 gsi_next (&gsi);
4509 gsi_commit_edge_inserts ();
4510 return cfg_changed;
4513 /* Generate statements initializing scalar replacements of parts of function
4514 parameters. */
4516 static void
4517 initialize_parameter_reductions (void)
4519 gimple_stmt_iterator gsi;
4520 gimple_seq seq = NULL;
4521 tree parm;
4523 gsi = gsi_start (seq);
4524 for (parm = DECL_ARGUMENTS (current_function_decl);
4525 parm;
4526 parm = DECL_CHAIN (parm))
4528 vec<access_p> *access_vec;
4529 struct access *access;
4531 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
4532 continue;
4533 access_vec = get_base_access_vector (parm);
4534 if (!access_vec)
4535 continue;
4537 for (access = (*access_vec)[0];
4538 access;
4539 access = access->next_grp)
4540 generate_subtree_copies (access, parm, 0, 0, 0, &gsi, true, true,
4541 EXPR_LOCATION (parm));
4544 seq = gsi_seq (gsi);
4545 if (seq)
4546 gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
4549 /* The "main" function of intraprocedural SRA passes. Runs the analysis and if
4550 it reveals there are components of some aggregates to be scalarized, it runs
4551 the required transformations. */
4552 static unsigned int
4553 perform_intra_sra (void)
4555 int ret = 0;
4556 sra_initialize ();
4558 if (!find_var_candidates ())
4559 goto out;
4561 if (!scan_function ())
4562 goto out;
4564 if (!analyze_all_variable_accesses ())
4565 goto out;
4567 if (sra_modify_function_body ())
4568 ret = TODO_update_ssa | TODO_cleanup_cfg;
4569 else
4570 ret = TODO_update_ssa;
4571 initialize_parameter_reductions ();
4573 statistics_counter_event (cfun, "Scalar replacements created",
4574 sra_stats.replacements);
4575 statistics_counter_event (cfun, "Modified expressions", sra_stats.exprs);
4576 statistics_counter_event (cfun, "Subtree copy stmts",
4577 sra_stats.subtree_copies);
4578 statistics_counter_event (cfun, "Subreplacement stmts",
4579 sra_stats.subreplacements);
4580 statistics_counter_event (cfun, "Deleted stmts", sra_stats.deleted);
4581 statistics_counter_event (cfun, "Separate LHS and RHS handling",
4582 sra_stats.separate_lhs_rhs_handling);
4584 out:
4585 sra_deinitialize ();
4586 return ret;
4589 /* Perform early intraprocedural SRA. */
4590 static unsigned int
4591 early_intra_sra (void)
4593 sra_mode = SRA_MODE_EARLY_INTRA;
4594 return perform_intra_sra ();
4597 /* Perform "late" intraprocedural SRA. */
4598 static unsigned int
4599 late_intra_sra (void)
4601 sra_mode = SRA_MODE_INTRA;
4602 return perform_intra_sra ();
4606 static bool
4607 gate_intra_sra (void)
4609 return flag_tree_sra != 0 && dbg_cnt (tree_sra);
4613 namespace {
4615 const pass_data pass_data_sra_early =
4617 GIMPLE_PASS, /* type */
4618 "esra", /* name */
4619 OPTGROUP_NONE, /* optinfo_flags */
4620 TV_TREE_SRA, /* tv_id */
4621 ( PROP_cfg | PROP_ssa ), /* properties_required */
4622 0, /* properties_provided */
4623 0, /* properties_destroyed */
4624 0, /* todo_flags_start */
4625 TODO_update_ssa, /* todo_flags_finish */
4628 class pass_sra_early : public gimple_opt_pass
4630 public:
4631 pass_sra_early (gcc::context *ctxt)
4632 : gimple_opt_pass (pass_data_sra_early, ctxt)
4635 /* opt_pass methods: */
4636 virtual bool gate (function *) { return gate_intra_sra (); }
4637 virtual unsigned int execute (function *) { return early_intra_sra (); }
4639 }; // class pass_sra_early
4641 } // anon namespace
4643 gimple_opt_pass *
4644 make_pass_sra_early (gcc::context *ctxt)
4646 return new pass_sra_early (ctxt);
4649 namespace {
4651 const pass_data pass_data_sra =
4653 GIMPLE_PASS, /* type */
4654 "sra", /* name */
4655 OPTGROUP_NONE, /* optinfo_flags */
4656 TV_TREE_SRA, /* tv_id */
4657 ( PROP_cfg | PROP_ssa ), /* properties_required */
4658 0, /* properties_provided */
4659 0, /* properties_destroyed */
4660 TODO_update_address_taken, /* todo_flags_start */
4661 TODO_update_ssa, /* todo_flags_finish */
4664 class pass_sra : public gimple_opt_pass
4666 public:
4667 pass_sra (gcc::context *ctxt)
4668 : gimple_opt_pass (pass_data_sra, ctxt)
4671 /* opt_pass methods: */
4672 virtual bool gate (function *) { return gate_intra_sra (); }
4673 virtual unsigned int execute (function *) { return late_intra_sra (); }
4675 }; // class pass_sra
4677 } // anon namespace
4679 gimple_opt_pass *
4680 make_pass_sra (gcc::context *ctxt)
4682 return new pass_sra (ctxt);