Daily bump.
[official-gcc.git] / gcc / tree-sra.cc
blob32fa28911f2d5796411adc3ba63fc09f08d17ad3
1 /* Scalar Replacement of Aggregates (SRA) converts some structure
2 references into scalar references, exposing them to the scalar
3 optimizers.
4 Copyright (C) 2008-2024 Free Software Foundation, Inc.
5 Contributed by Martin Jambor <mjambor@suse.cz>
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"
102 #include "opts.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;
264 /* Result of propagation accross link from LHS to RHS. */
265 unsigned grp_result_of_prop_from_lhs : 1;
268 typedef struct access *access_p;
271 /* Alloc pool for allocating access structures. */
272 static object_allocator<struct access> access_pool ("SRA accesses");
274 /* A structure linking lhs and rhs accesses from an aggregate assignment. They
275 are used to propagate subaccesses from rhs to lhs and vice versa as long as
276 they don't conflict with what is already there. In the RHS->LHS direction,
277 we also propagate grp_write flag to lazily mark that the access contains any
278 meaningful data. */
279 struct assign_link
281 struct access *lacc, *racc;
282 struct assign_link *next_rhs, *next_lhs;
285 /* Alloc pool for allocating assign link structures. */
286 static object_allocator<assign_link> assign_link_pool ("SRA links");
288 /* Base (tree) -> Vector (vec<access_p> *) map. */
289 static hash_map<tree, auto_vec<access_p> > *base_access_vec;
291 /* Hash to limit creation of artificial accesses */
292 static hash_map<tree, unsigned> *propagation_budget;
294 /* Candidate hash table helpers. */
296 struct uid_decl_hasher : nofree_ptr_hash <tree_node>
298 static inline hashval_t hash (const tree_node *);
299 static inline bool equal (const tree_node *, const tree_node *);
302 /* Hash a tree in a uid_decl_map. */
304 inline hashval_t
305 uid_decl_hasher::hash (const tree_node *item)
307 return item->decl_minimal.uid;
310 /* Return true if the DECL_UID in both trees are equal. */
312 inline bool
313 uid_decl_hasher::equal (const tree_node *a, const tree_node *b)
315 return (a->decl_minimal.uid == b->decl_minimal.uid);
318 /* Set of candidates. */
319 static bitmap candidate_bitmap;
320 static hash_table<uid_decl_hasher> *candidates;
322 /* For a candidate UID return the candidates decl. */
324 static inline tree
325 candidate (unsigned uid)
327 tree_node t;
328 t.decl_minimal.uid = uid;
329 return candidates->find_with_hash (&t, static_cast <hashval_t> (uid));
332 /* Bitmap of candidates which we should try to entirely scalarize away and
333 those which cannot be (because they are and need be used as a whole). */
334 static bitmap should_scalarize_away_bitmap, cannot_scalarize_away_bitmap;
336 /* Bitmap of candidates in the constant pool, which cannot be scalarized
337 because this would produce non-constant expressions (e.g. Ada). */
338 static bitmap disqualified_constants;
340 /* Bitmap of candidates which are passed by reference in call arguments. */
341 static bitmap passed_by_ref_in_call;
343 /* Obstack for creation of fancy names. */
344 static struct obstack name_obstack;
346 /* Head of a linked list of accesses that need to have its subaccesses
347 propagated to their assignment counterparts. */
348 static struct access *rhs_work_queue_head, *lhs_work_queue_head;
350 /* Dump contents of ACCESS to file F in a human friendly way. If GRP is true,
351 representative fields are dumped, otherwise those which only describe the
352 individual access are. */
354 static struct
356 /* Number of processed aggregates is readily available in
357 analyze_all_variable_accesses and so is not stored here. */
359 /* Number of created scalar replacements. */
360 int replacements;
362 /* Number of times sra_modify_expr or sra_modify_assign themselves changed an
363 expression. */
364 int exprs;
366 /* Number of statements created by generate_subtree_copies. */
367 int subtree_copies;
369 /* Number of statements created by load_assign_lhs_subreplacements. */
370 int subreplacements;
372 /* Number of times sra_modify_assign has deleted a statement. */
373 int deleted;
375 /* Number of times sra_modify_assign has to deal with subaccesses of LHS and
376 RHS reparately due to type conversions or nonexistent matching
377 references. */
378 int separate_lhs_rhs_handling;
380 /* Number of parameters that were removed because they were unused. */
381 int deleted_unused_parameters;
383 /* Number of scalars passed as parameters by reference that have been
384 converted to be passed by value. */
385 int scalar_by_ref_to_by_val;
387 /* Number of aggregate parameters that were replaced by one or more of their
388 components. */
389 int aggregate_params_reduced;
391 /* Numbber of components created when splitting aggregate parameters. */
392 int param_reductions_created;
394 /* Number of deferred_init calls that are modified. */
395 int deferred_init;
397 /* Number of deferred_init calls that are created by
398 generate_subtree_deferred_init. */
399 int subtree_deferred_init;
400 } sra_stats;
402 static void
403 dump_access (FILE *f, struct access *access, bool grp)
405 fprintf (f, "access { ");
406 fprintf (f, "base = (%d)'", DECL_UID (access->base));
407 print_generic_expr (f, access->base);
408 fprintf (f, "', offset = " HOST_WIDE_INT_PRINT_DEC, access->offset);
409 fprintf (f, ", size = " HOST_WIDE_INT_PRINT_DEC, access->size);
410 fprintf (f, ", expr = ");
411 print_generic_expr (f, access->expr);
412 fprintf (f, ", type = ");
413 print_generic_expr (f, access->type);
414 fprintf (f, ", reverse = %d", access->reverse);
415 if (grp)
416 fprintf (f, ", grp_read = %d, grp_write = %d, grp_assignment_read = %d, "
417 "grp_assignment_write = %d, grp_scalar_read = %d, "
418 "grp_scalar_write = %d, grp_total_scalarization = %d, "
419 "grp_hint = %d, grp_covered = %d, "
420 "grp_unscalarizable_region = %d, grp_unscalarized_data = %d, "
421 "grp_same_access_path = %d, grp_partial_lhs = %d, "
422 "grp_to_be_replaced = %d, grp_to_be_debug_replaced = %d}\n",
423 access->grp_read, access->grp_write, access->grp_assignment_read,
424 access->grp_assignment_write, access->grp_scalar_read,
425 access->grp_scalar_write, access->grp_total_scalarization,
426 access->grp_hint, access->grp_covered,
427 access->grp_unscalarizable_region, access->grp_unscalarized_data,
428 access->grp_same_access_path, access->grp_partial_lhs,
429 access->grp_to_be_replaced, access->grp_to_be_debug_replaced);
430 else
431 fprintf (f, ", write = %d, grp_total_scalarization = %d, "
432 "grp_partial_lhs = %d}\n",
433 access->write, access->grp_total_scalarization,
434 access->grp_partial_lhs);
437 /* Dump a subtree rooted in ACCESS to file F, indent by LEVEL. */
439 static void
440 dump_access_tree_1 (FILE *f, struct access *access, int level)
444 int i;
446 for (i = 0; i < level; i++)
447 fputs ("* ", f);
449 dump_access (f, access, true);
451 if (access->first_child)
452 dump_access_tree_1 (f, access->first_child, level + 1);
454 access = access->next_sibling;
456 while (access);
459 /* Dump all access trees for a variable, given the pointer to the first root in
460 ACCESS. */
462 static void
463 dump_access_tree (FILE *f, struct access *access)
465 for (; access; access = access->next_grp)
466 dump_access_tree_1 (f, access, 0);
469 /* Return true iff ACC is non-NULL and has subaccesses. */
471 static inline bool
472 access_has_children_p (struct access *acc)
474 return acc && acc->first_child;
477 /* Return true iff ACC is (partly) covered by at least one replacement. */
479 static bool
480 access_has_replacements_p (struct access *acc)
482 struct access *child;
483 if (acc->grp_to_be_replaced)
484 return true;
485 for (child = acc->first_child; child; child = child->next_sibling)
486 if (access_has_replacements_p (child))
487 return true;
488 return false;
491 /* Return a vector of pointers to accesses for the variable given in BASE or
492 NULL if there is none. */
494 static vec<access_p> *
495 get_base_access_vector (tree base)
497 return base_access_vec->get (base);
500 /* Find an access with required OFFSET and SIZE in a subtree of accesses rooted
501 in ACCESS. Return NULL if it cannot be found. */
503 static struct access *
504 find_access_in_subtree (struct access *access, HOST_WIDE_INT offset,
505 HOST_WIDE_INT size)
507 while (access && (access->offset != offset || access->size != size))
509 struct access *child = access->first_child;
511 while (child && (child->offset + child->size <= offset))
512 child = child->next_sibling;
513 access = child;
516 /* Total scalarization does not replace single field structures with their
517 single field but rather creates an access for them underneath. Look for
518 it. */
519 if (access)
520 while (access->first_child
521 && access->first_child->offset == offset
522 && access->first_child->size == size)
523 access = access->first_child;
525 return access;
528 /* Return the first group representative for DECL or NULL if none exists. */
530 static struct access *
531 get_first_repr_for_decl (tree base)
533 vec<access_p> *access_vec;
535 access_vec = get_base_access_vector (base);
536 if (!access_vec)
537 return NULL;
539 return (*access_vec)[0];
542 /* Find an access representative for the variable BASE and given OFFSET and
543 SIZE. Requires that access trees have already been built. Return NULL if
544 it cannot be found. */
546 static struct access *
547 get_var_base_offset_size_access (tree base, HOST_WIDE_INT offset,
548 HOST_WIDE_INT size)
550 struct access *access;
552 access = get_first_repr_for_decl (base);
553 while (access && (access->offset + access->size <= offset))
554 access = access->next_grp;
555 if (!access)
556 return NULL;
558 return find_access_in_subtree (access, offset, size);
561 /* Add LINK to the linked list of assign links of RACC. */
563 static void
564 add_link_to_rhs (struct access *racc, struct assign_link *link)
566 gcc_assert (link->racc == racc);
568 if (!racc->first_rhs_link)
570 gcc_assert (!racc->last_rhs_link);
571 racc->first_rhs_link = link;
573 else
574 racc->last_rhs_link->next_rhs = link;
576 racc->last_rhs_link = link;
577 link->next_rhs = NULL;
580 /* Add LINK to the linked list of lhs assign links of LACC. */
582 static void
583 add_link_to_lhs (struct access *lacc, struct assign_link *link)
585 gcc_assert (link->lacc == lacc);
587 if (!lacc->first_lhs_link)
589 gcc_assert (!lacc->last_lhs_link);
590 lacc->first_lhs_link = link;
592 else
593 lacc->last_lhs_link->next_lhs = link;
595 lacc->last_lhs_link = link;
596 link->next_lhs = NULL;
599 /* Move all link structures in their linked list in OLD_ACC to the linked list
600 in NEW_ACC. */
601 static void
602 relink_to_new_repr (struct access *new_acc, struct access *old_acc)
604 if (old_acc->first_rhs_link)
607 if (new_acc->first_rhs_link)
609 gcc_assert (!new_acc->last_rhs_link->next_rhs);
610 gcc_assert (!old_acc->last_rhs_link
611 || !old_acc->last_rhs_link->next_rhs);
613 new_acc->last_rhs_link->next_rhs = old_acc->first_rhs_link;
614 new_acc->last_rhs_link = old_acc->last_rhs_link;
616 else
618 gcc_assert (!new_acc->last_rhs_link);
620 new_acc->first_rhs_link = old_acc->first_rhs_link;
621 new_acc->last_rhs_link = old_acc->last_rhs_link;
623 old_acc->first_rhs_link = old_acc->last_rhs_link = NULL;
625 else
626 gcc_assert (!old_acc->last_rhs_link);
628 if (old_acc->first_lhs_link)
631 if (new_acc->first_lhs_link)
633 gcc_assert (!new_acc->last_lhs_link->next_lhs);
634 gcc_assert (!old_acc->last_lhs_link
635 || !old_acc->last_lhs_link->next_lhs);
637 new_acc->last_lhs_link->next_lhs = old_acc->first_lhs_link;
638 new_acc->last_lhs_link = old_acc->last_lhs_link;
640 else
642 gcc_assert (!new_acc->last_lhs_link);
644 new_acc->first_lhs_link = old_acc->first_lhs_link;
645 new_acc->last_lhs_link = old_acc->last_lhs_link;
647 old_acc->first_lhs_link = old_acc->last_lhs_link = NULL;
649 else
650 gcc_assert (!old_acc->last_lhs_link);
654 /* Add ACCESS to the work to queue for propagation of subaccesses from RHS to
655 LHS (which is actually a stack). */
657 static void
658 add_access_to_rhs_work_queue (struct access *access)
660 if (access->first_rhs_link && !access->grp_rhs_queued)
662 gcc_assert (!access->next_rhs_queued);
663 access->next_rhs_queued = rhs_work_queue_head;
664 access->grp_rhs_queued = 1;
665 rhs_work_queue_head = access;
669 /* Add ACCESS to the work to queue for propagation of subaccesses from LHS to
670 RHS (which is actually a stack). */
672 static void
673 add_access_to_lhs_work_queue (struct access *access)
675 if (access->first_lhs_link && !access->grp_lhs_queued)
677 gcc_assert (!access->next_lhs_queued);
678 access->next_lhs_queued = lhs_work_queue_head;
679 access->grp_lhs_queued = 1;
680 lhs_work_queue_head = access;
684 /* Pop an access from the work queue for propagating from RHS to LHS, and
685 return it, assuming there is one. */
687 static struct access *
688 pop_access_from_rhs_work_queue (void)
690 struct access *access = rhs_work_queue_head;
692 rhs_work_queue_head = access->next_rhs_queued;
693 access->next_rhs_queued = NULL;
694 access->grp_rhs_queued = 0;
695 return access;
698 /* Pop an access from the work queue for propagating from LHS to RHS, and
699 return it, assuming there is one. */
701 static struct access *
702 pop_access_from_lhs_work_queue (void)
704 struct access *access = lhs_work_queue_head;
706 lhs_work_queue_head = access->next_lhs_queued;
707 access->next_lhs_queued = NULL;
708 access->grp_lhs_queued = 0;
709 return access;
712 /* Allocate necessary structures. */
714 static void
715 sra_initialize (void)
717 candidate_bitmap = BITMAP_ALLOC (NULL);
718 candidates = new hash_table<uid_decl_hasher>
719 (vec_safe_length (cfun->local_decls) / 2);
720 should_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
721 cannot_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
722 disqualified_constants = BITMAP_ALLOC (NULL);
723 passed_by_ref_in_call = BITMAP_ALLOC (NULL);
724 gcc_obstack_init (&name_obstack);
725 base_access_vec = new hash_map<tree, auto_vec<access_p> >;
726 memset (&sra_stats, 0, sizeof (sra_stats));
729 /* Deallocate all general structures. */
731 static void
732 sra_deinitialize (void)
734 BITMAP_FREE (candidate_bitmap);
735 delete candidates;
736 candidates = NULL;
737 BITMAP_FREE (should_scalarize_away_bitmap);
738 BITMAP_FREE (cannot_scalarize_away_bitmap);
739 BITMAP_FREE (disqualified_constants);
740 BITMAP_FREE (passed_by_ref_in_call);
741 access_pool.release ();
742 assign_link_pool.release ();
743 obstack_free (&name_obstack, NULL);
745 delete base_access_vec;
748 /* Return true if DECL is a VAR_DECL in the constant pool, false otherwise. */
750 static bool constant_decl_p (tree decl)
752 return VAR_P (decl) && DECL_IN_CONSTANT_POOL (decl);
755 /* Remove DECL from candidates for SRA and write REASON to the dump file if
756 there is one. */
758 static void
759 disqualify_candidate (tree decl, const char *reason)
761 if (bitmap_clear_bit (candidate_bitmap, DECL_UID (decl)))
762 candidates->remove_elt_with_hash (decl, DECL_UID (decl));
763 if (constant_decl_p (decl))
764 bitmap_set_bit (disqualified_constants, DECL_UID (decl));
766 if (dump_file && (dump_flags & TDF_DETAILS))
768 fprintf (dump_file, "! Disqualifying ");
769 print_generic_expr (dump_file, decl);
770 fprintf (dump_file, " - %s\n", reason);
774 /* Return true iff the type contains a field or an element which does not allow
775 scalarization. Use VISITED_TYPES to avoid re-checking already checked
776 (sub-)types. */
778 static bool
779 type_internals_preclude_sra_p_1 (tree type, const char **msg,
780 hash_set<tree> *visited_types)
782 tree fld;
783 tree et;
785 if (visited_types->contains (type))
786 return false;
787 visited_types->add (type);
789 switch (TREE_CODE (type))
791 case RECORD_TYPE:
792 case UNION_TYPE:
793 case QUAL_UNION_TYPE:
794 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
795 if (TREE_CODE (fld) == FIELD_DECL)
797 if (TREE_CODE (fld) == FUNCTION_DECL)
798 continue;
799 tree ft = TREE_TYPE (fld);
801 if (TREE_THIS_VOLATILE (fld))
803 *msg = "volatile structure field";
804 return true;
806 if (!DECL_FIELD_OFFSET (fld))
808 *msg = "no structure field offset";
809 return true;
811 if (!DECL_SIZE (fld))
813 *msg = "zero structure field size";
814 return true;
816 if (!tree_fits_uhwi_p (DECL_FIELD_OFFSET (fld)))
818 *msg = "structure field offset not fixed";
819 return true;
821 if (!tree_fits_uhwi_p (DECL_SIZE (fld)))
823 *msg = "structure field size not fixed";
824 return true;
826 if (!tree_fits_shwi_p (bit_position (fld)))
828 *msg = "structure field size too big";
829 return true;
831 if (AGGREGATE_TYPE_P (ft)
832 && int_bit_position (fld) % BITS_PER_UNIT != 0)
834 *msg = "structure field is bit field";
835 return true;
838 if (AGGREGATE_TYPE_P (ft)
839 && type_internals_preclude_sra_p_1 (ft, msg, visited_types))
840 return true;
843 return false;
845 case ARRAY_TYPE:
846 et = TREE_TYPE (type);
848 if (TYPE_VOLATILE (et))
850 *msg = "element type is volatile";
851 return true;
854 if (AGGREGATE_TYPE_P (et)
855 && type_internals_preclude_sra_p_1 (et, msg, visited_types))
856 return true;
858 return false;
860 default:
861 return false;
865 /* Return true iff the type contains a field or an element which does not allow
866 scalarization. */
868 bool
869 type_internals_preclude_sra_p (tree type, const char **msg)
871 hash_set<tree> visited_types;
872 return type_internals_preclude_sra_p_1 (type, msg, &visited_types);
876 /* Allocate an access structure for BASE, OFFSET and SIZE, clear it, fill in
877 the three fields. Also add it to the vector of accesses corresponding to
878 the base. Finally, return the new access. */
880 static struct access *
881 create_access_1 (tree base, HOST_WIDE_INT offset, HOST_WIDE_INT size)
883 struct access *access = access_pool.allocate ();
885 memset (access, 0, sizeof (struct access));
886 access->base = base;
887 access->offset = offset;
888 access->size = size;
890 base_access_vec->get_or_insert (base).safe_push (access);
892 return access;
895 static bool maybe_add_sra_candidate (tree);
897 /* Create and insert access for EXPR. Return created access, or NULL if it is
898 not possible. Also scan for uses of constant pool as we go along and add
899 to candidates. */
901 static struct access *
902 create_access (tree expr, gimple *stmt, bool write)
904 struct access *access;
905 poly_int64 poffset, psize, pmax_size;
906 tree base = expr;
907 bool reverse, unscalarizable_region = false;
909 base = get_ref_base_and_extent (expr, &poffset, &psize, &pmax_size,
910 &reverse);
912 /* For constant-pool entries, check we can substitute the constant value. */
913 if (constant_decl_p (base)
914 && !bitmap_bit_p (disqualified_constants, DECL_UID (base)))
916 if (expr != base
917 && !is_gimple_reg_type (TREE_TYPE (expr))
918 && dump_file && (dump_flags & TDF_DETAILS))
920 /* This occurs in Ada with accesses to ARRAY_RANGE_REFs,
921 and elements of multidimensional arrays (which are
922 multi-element arrays in their own right). */
923 fprintf (dump_file, "Allowing non-reg-type load of part"
924 " of constant-pool entry: ");
925 print_generic_expr (dump_file, expr);
927 maybe_add_sra_candidate (base);
930 if (!DECL_P (base) || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
931 return NULL;
933 if (write && TREE_READONLY (base))
935 disqualify_candidate (base, "Encountered a store to a read-only decl.");
936 return NULL;
939 HOST_WIDE_INT offset, size, max_size;
940 if (!poffset.is_constant (&offset)
941 || !psize.is_constant (&size)
942 || !pmax_size.is_constant (&max_size))
944 disqualify_candidate (base, "Encountered a polynomial-sized access.");
945 return NULL;
948 if (size != max_size)
950 size = max_size;
951 unscalarizable_region = true;
953 if (size == 0)
954 return NULL;
955 if (offset < 0)
957 disqualify_candidate (base, "Encountered a negative offset access.");
958 return NULL;
960 if (size < 0)
962 disqualify_candidate (base, "Encountered an unconstrained access.");
963 return NULL;
965 if (offset + size > tree_to_shwi (DECL_SIZE (base)))
967 disqualify_candidate (base, "Encountered an access beyond the base.");
968 return NULL;
970 if (TREE_CODE (TREE_TYPE (expr)) == BITINT_TYPE
971 && size > WIDE_INT_MAX_PRECISION - 1)
973 disqualify_candidate (base, "Encountered too large _BitInt access.");
974 return NULL;
977 access = create_access_1 (base, offset, size);
978 access->expr = expr;
979 access->type = TREE_TYPE (expr);
980 access->write = write;
981 access->grp_unscalarizable_region = unscalarizable_region;
982 access->stmt = stmt;
983 access->reverse = reverse;
985 return access;
988 /* Given an array type TYPE, extract element size to *EL_SIZE, minimum index to
989 *IDX and maximum index to *MAX so that the caller can iterate over all
990 elements and return true, except if the array is known to be zero-length,
991 then return false. */
993 static bool
994 prepare_iteration_over_array_elts (tree type, HOST_WIDE_INT *el_size,
995 offset_int *idx, offset_int *max)
997 tree elem_size = TYPE_SIZE (TREE_TYPE (type));
998 gcc_assert (elem_size && tree_fits_shwi_p (elem_size));
999 *el_size = tree_to_shwi (elem_size);
1000 gcc_assert (*el_size > 0);
1002 tree minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
1003 gcc_assert (TREE_CODE (minidx) == INTEGER_CST);
1004 tree maxidx = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
1005 /* Skip (some) zero-length arrays; others have MAXIDX == MINIDX - 1. */
1006 if (!maxidx)
1007 return false;
1008 gcc_assert (TREE_CODE (maxidx) == INTEGER_CST);
1009 tree domain = TYPE_DOMAIN (type);
1010 /* MINIDX and MAXIDX are inclusive, and must be interpreted in
1011 DOMAIN (e.g. signed int, whereas min/max may be size_int). */
1012 *idx = wi::to_offset (minidx);
1013 *max = wi::to_offset (maxidx);
1014 if (!TYPE_UNSIGNED (domain))
1016 *idx = wi::sext (*idx, TYPE_PRECISION (domain));
1017 *max = wi::sext (*max, TYPE_PRECISION (domain));
1019 return true;
1022 /* A structure to track collecting padding and hold collected padding
1023 information. */
1025 class sra_padding_collecting
1027 public:
1028 /* Given that there won't be any data until at least OFFSET, add an
1029 appropriate entry to the list of paddings or extend the last one. */
1030 void record_padding (HOST_WIDE_INT offset);
1031 /* Vector of pairs describing contiguous pieces of padding, each pair
1032 consisting of offset and length. */
1033 auto_vec<std::pair<HOST_WIDE_INT, HOST_WIDE_INT>, 10> m_padding;
1034 /* Offset where data should continue after the last seen actual bit of data
1035 if there was no padding. */
1036 HOST_WIDE_INT m_data_until = 0;
1039 /* Given that there won't be any data until at least OFFSET, add an appropriate
1040 entry to the list of paddings or extend the last one. */
1042 void sra_padding_collecting::record_padding (HOST_WIDE_INT offset)
1044 if (offset > m_data_until)
1046 HOST_WIDE_INT psz = offset - m_data_until;
1047 if (!m_padding.is_empty ()
1048 && ((m_padding[m_padding.length () - 1].first
1049 + m_padding[m_padding.length () - 1].second) == offset))
1050 m_padding[m_padding.length () - 1].second += psz;
1051 else
1052 m_padding.safe_push (std::make_pair (m_data_until, psz));
1056 /* Return true iff TYPE is totally scalarizable - i.e. a RECORD_TYPE or
1057 fixed-length ARRAY_TYPE with fields that are either of gimple register types
1058 (excluding bit-fields) or (recursively) scalarizable types. CONST_DECL must
1059 be true if we are considering a decl from constant pool. If it is false,
1060 char arrays will be refused.
1062 TOTAL_OFFSET is the offset of TYPE within any outer type that is being
1063 examined.
1065 If PC is non-NULL, collect padding information into the vector within the
1066 structure. The information is however only complete if the function returns
1067 true and does not contain any padding at its end. */
1069 static bool
1070 totally_scalarizable_type_p (tree type, bool const_decl,
1071 HOST_WIDE_INT total_offset,
1072 sra_padding_collecting *pc)
1074 if (is_gimple_reg_type (type))
1076 if (pc)
1078 pc->record_padding (total_offset);
1079 pc->m_data_until = total_offset + tree_to_shwi (TYPE_SIZE (type));
1081 return true;
1083 if (type_contains_placeholder_p (type))
1084 return false;
1086 bool have_predecessor_field = false;
1087 HOST_WIDE_INT prev_pos = 0;
1089 switch (TREE_CODE (type))
1091 case RECORD_TYPE:
1092 for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
1093 if (TREE_CODE (fld) == FIELD_DECL)
1095 tree ft = TREE_TYPE (fld);
1097 if (!DECL_SIZE (fld))
1098 return false;
1099 if (zerop (DECL_SIZE (fld)))
1100 continue;
1102 HOST_WIDE_INT pos = int_bit_position (fld);
1103 if (have_predecessor_field
1104 && pos <= prev_pos)
1105 return false;
1107 have_predecessor_field = true;
1108 prev_pos = pos;
1110 if (DECL_BIT_FIELD (fld))
1111 return false;
1113 if (!totally_scalarizable_type_p (ft, const_decl, total_offset + pos,
1114 pc))
1115 return false;
1118 return true;
1120 case ARRAY_TYPE:
1122 HOST_WIDE_INT min_elem_size;
1123 if (const_decl)
1124 min_elem_size = 0;
1125 else
1126 min_elem_size = BITS_PER_UNIT;
1128 if (TYPE_DOMAIN (type) == NULL_TREE
1129 || !tree_fits_shwi_p (TYPE_SIZE (type))
1130 || !tree_fits_shwi_p (TYPE_SIZE (TREE_TYPE (type)))
1131 || (tree_to_shwi (TYPE_SIZE (TREE_TYPE (type))) <= min_elem_size)
1132 || !tree_fits_shwi_p (TYPE_MIN_VALUE (TYPE_DOMAIN (type))))
1133 return false;
1134 if (tree_to_shwi (TYPE_SIZE (type)) == 0
1135 && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE)
1136 /* Zero-element array, should not prevent scalarization. */
1138 else if ((tree_to_shwi (TYPE_SIZE (type)) <= 0)
1139 || !tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
1140 /* Variable-length array, do not allow scalarization. */
1141 return false;
1143 unsigned old_padding_len = 0;
1144 if (pc)
1145 old_padding_len = pc->m_padding.length ();
1146 tree elem = TREE_TYPE (type);
1147 if (!totally_scalarizable_type_p (elem, const_decl, total_offset, pc))
1148 return false;
1149 if (pc)
1151 unsigned new_padding_len = pc->m_padding.length ();
1152 HOST_WIDE_INT el_size;
1153 offset_int idx, max;
1154 if (!prepare_iteration_over_array_elts (type, &el_size, &idx, &max))
1155 return true;
1156 pc->record_padding (total_offset + el_size);
1157 ++idx;
1158 for (HOST_WIDE_INT pos = total_offset + el_size;
1159 idx <= max;
1160 pos += el_size, ++idx)
1162 for (unsigned i = old_padding_len; i < new_padding_len; i++)
1164 HOST_WIDE_INT pp
1165 = pos + pc->m_padding[i].first - total_offset;
1166 HOST_WIDE_INT psz = pc->m_padding[i].second;
1167 pc->m_padding.safe_push (std::make_pair (pp, psz));
1170 pc->m_data_until = total_offset + tree_to_shwi (TYPE_SIZE (type));
1172 return true;
1174 default:
1175 return false;
1179 /* Return true if REF has an VIEW_CONVERT_EXPR somewhere in it. */
1181 static inline bool
1182 contains_view_convert_expr_p (const_tree ref)
1184 while (handled_component_p (ref))
1186 if (TREE_CODE (ref) == VIEW_CONVERT_EXPR)
1187 return true;
1188 ref = TREE_OPERAND (ref, 0);
1191 return false;
1194 /* Return true if REF contains a VIEW_CONVERT_EXPR or a COMPONENT_REF with a
1195 bit-field field declaration. If TYPE_CHANGING_P is non-NULL, set the bool
1196 it points to will be set if REF contains any of the above or a MEM_REF
1197 expression that effectively performs type conversion. */
1199 static bool
1200 contains_vce_or_bfcref_p (const_tree ref, bool *type_changing_p = NULL)
1202 while (handled_component_p (ref))
1204 if (TREE_CODE (ref) == VIEW_CONVERT_EXPR
1205 || (TREE_CODE (ref) == COMPONENT_REF
1206 && DECL_BIT_FIELD (TREE_OPERAND (ref, 1))))
1208 if (type_changing_p)
1209 *type_changing_p = true;
1210 return true;
1212 ref = TREE_OPERAND (ref, 0);
1215 if (!type_changing_p
1216 || TREE_CODE (ref) != MEM_REF
1217 || TREE_CODE (TREE_OPERAND (ref, 0)) != ADDR_EXPR)
1218 return false;
1220 tree mem = TREE_OPERAND (TREE_OPERAND (ref, 0), 0);
1221 if (TYPE_MAIN_VARIANT (TREE_TYPE (ref))
1222 != TYPE_MAIN_VARIANT (TREE_TYPE (mem)))
1223 *type_changing_p = true;
1225 return false;
1228 /* Search the given tree for a declaration by skipping handled components and
1229 exclude it from the candidates. */
1231 static void
1232 disqualify_base_of_expr (tree t, const char *reason)
1234 t = get_base_address (t);
1235 if (t && DECL_P (t))
1236 disqualify_candidate (t, reason);
1239 /* Return true if the BIT_FIELD_REF read EXPR is handled by SRA. */
1241 static bool
1242 sra_handled_bf_read_p (tree expr)
1244 uint64_t size, offset;
1245 if (bit_field_size (expr).is_constant (&size)
1246 && bit_field_offset (expr).is_constant (&offset)
1247 && size % BITS_PER_UNIT == 0
1248 && offset % BITS_PER_UNIT == 0
1249 && pow2p_hwi (size))
1250 return true;
1251 return false;
1254 /* Scan expression EXPR and create access structures for all accesses to
1255 candidates for scalarization. Return the created access or NULL if none is
1256 created. */
1258 static struct access *
1259 build_access_from_expr_1 (tree expr, gimple *stmt, bool write)
1261 /* We only allow ADDR_EXPRs in arguments of function calls and those must
1262 have been dealt with in build_access_from_call_arg. Any other address
1263 taking should have been caught by scan_visit_addr. */
1264 if (TREE_CODE (expr) == ADDR_EXPR)
1266 tree base = get_base_address (TREE_OPERAND (expr, 0));
1267 gcc_assert (!DECL_P (base)
1268 || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)));
1269 return NULL;
1272 struct access *ret = NULL;
1273 bool partial_ref;
1275 if ((TREE_CODE (expr) == BIT_FIELD_REF
1276 && (write || !sra_handled_bf_read_p (expr)))
1277 || TREE_CODE (expr) == IMAGPART_EXPR
1278 || TREE_CODE (expr) == REALPART_EXPR)
1280 expr = TREE_OPERAND (expr, 0);
1281 partial_ref = true;
1283 else
1284 partial_ref = false;
1286 if (storage_order_barrier_p (expr))
1288 disqualify_base_of_expr (expr, "storage order barrier.");
1289 return NULL;
1292 /* We need to dive through V_C_Es in order to get the size of its parameter
1293 and not the result type. Ada produces such statements. We are also
1294 capable of handling the topmost V_C_E but not any of those buried in other
1295 handled components. */
1296 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
1297 expr = TREE_OPERAND (expr, 0);
1299 if (contains_view_convert_expr_p (expr))
1301 disqualify_base_of_expr (expr, "V_C_E under a different handled "
1302 "component.");
1303 return NULL;
1305 if (TREE_THIS_VOLATILE (expr))
1307 disqualify_base_of_expr (expr, "part of a volatile reference.");
1308 return NULL;
1311 switch (TREE_CODE (expr))
1313 case MEM_REF:
1314 if (TREE_CODE (TREE_OPERAND (expr, 0)) != ADDR_EXPR)
1315 return NULL;
1316 /* fall through */
1317 case VAR_DECL:
1318 case PARM_DECL:
1319 case RESULT_DECL:
1320 case COMPONENT_REF:
1321 case ARRAY_REF:
1322 case ARRAY_RANGE_REF:
1323 case BIT_FIELD_REF:
1324 ret = create_access (expr, stmt, write);
1325 break;
1327 default:
1328 break;
1331 if (write && partial_ref && ret)
1332 ret->grp_partial_lhs = 1;
1334 return ret;
1337 /* Scan expression EXPR and create access structures for all accesses to
1338 candidates for scalarization. Return true if any access has been inserted.
1339 STMT must be the statement from which the expression is taken, WRITE must be
1340 true if the expression is a store and false otherwise. */
1342 static bool
1343 build_access_from_expr (tree expr, gimple *stmt, bool write)
1345 struct access *access;
1347 access = build_access_from_expr_1 (expr, stmt, write);
1348 if (access)
1350 /* This means the aggregate is accesses as a whole in a way other than an
1351 assign statement and thus cannot be removed even if we had a scalar
1352 replacement for everything. */
1353 if (cannot_scalarize_away_bitmap)
1354 bitmap_set_bit (cannot_scalarize_away_bitmap, DECL_UID (access->base));
1355 return true;
1357 return false;
1360 enum out_edge_check { SRA_OUTGOING_EDGES_UNCHECKED, SRA_OUTGOING_EDGES_OK,
1361 SRA_OUTGOING_EDGES_FAIL };
1363 /* Return true if STMT terminates BB and there is an abnormal edge going out of
1364 the BB and remember the decision in OE_CHECK. */
1366 static bool
1367 abnormal_edge_after_stmt_p (gimple *stmt, enum out_edge_check *oe_check)
1369 if (*oe_check == SRA_OUTGOING_EDGES_OK)
1370 return false;
1371 if (*oe_check == SRA_OUTGOING_EDGES_FAIL)
1372 return true;
1373 if (stmt_ends_bb_p (stmt))
1375 edge e;
1376 edge_iterator ei;
1377 FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->succs)
1378 if (e->flags & EDGE_ABNORMAL)
1380 *oe_check = SRA_OUTGOING_EDGES_FAIL;
1381 return true;
1384 *oe_check = SRA_OUTGOING_EDGES_OK;
1385 return false;
1388 /* Scan expression EXPR which is an argument of a call and create access
1389 structures for all accesses to candidates for scalarization. Return true
1390 if any access has been inserted. STMT must be the statement from which the
1391 expression is taken. CAN_BE_RETURNED must be true if call argument flags
1392 do not rule out that the argument is directly returned. OE_CHECK is used
1393 to remember result of a test for abnormal outgoing edges after this
1394 statement. */
1396 static bool
1397 build_access_from_call_arg (tree expr, gimple *stmt, bool can_be_returned,
1398 enum out_edge_check *oe_check)
1400 if (TREE_CODE (expr) == ADDR_EXPR)
1402 tree base = get_base_address (TREE_OPERAND (expr, 0));
1404 if (can_be_returned)
1406 disqualify_base_of_expr (base, "Address possibly returned, "
1407 "leading to an alis SRA may not know.");
1408 return false;
1410 if (abnormal_edge_after_stmt_p (stmt, oe_check))
1412 disqualify_base_of_expr (base, "May lead to need to add statements "
1413 "to abnormal edge.");
1414 return false;
1417 bool read = build_access_from_expr (base, stmt, false);
1418 bool write = build_access_from_expr (base, stmt, true);
1419 if (read || write)
1421 if (dump_file && (dump_flags & TDF_DETAILS))
1423 fprintf (dump_file, "Allowed ADDR_EXPR of ");
1424 print_generic_expr (dump_file, base);
1425 fprintf (dump_file, " because of ");
1426 print_gimple_stmt (dump_file, stmt, 0);
1427 fprintf (dump_file, "\n");
1429 bitmap_set_bit (passed_by_ref_in_call, DECL_UID (base));
1430 return true;
1432 else
1433 return false;
1436 return build_access_from_expr (expr, stmt, false);
1440 /* Return the single non-EH successor edge of BB or NULL if there is none or
1441 more than one. */
1443 static edge
1444 single_non_eh_succ (basic_block bb)
1446 edge e, res = NULL;
1447 edge_iterator ei;
1449 FOR_EACH_EDGE (e, ei, bb->succs)
1450 if (!(e->flags & EDGE_EH))
1452 if (res)
1453 return NULL;
1454 res = e;
1457 return res;
1460 /* Disqualify LHS and RHS for scalarization if STMT has to terminate its BB and
1461 there is no alternative spot where to put statements SRA might need to
1462 generate after it. The spot we are looking for is an edge leading to a
1463 single non-EH successor, if it exists and is indeed single. RHS may be
1464 NULL, in that case ignore it. */
1466 static bool
1467 disqualify_if_bad_bb_terminating_stmt (gimple *stmt, tree lhs, tree rhs)
1469 if (stmt_ends_bb_p (stmt))
1471 if (single_non_eh_succ (gimple_bb (stmt)))
1472 return false;
1474 disqualify_base_of_expr (lhs, "LHS of a throwing stmt.");
1475 if (rhs)
1476 disqualify_base_of_expr (rhs, "RHS of a throwing stmt.");
1477 return true;
1479 return false;
1482 /* Return true if the nature of BASE is such that it contains data even if
1483 there is no write to it in the function. */
1485 static bool
1486 comes_initialized_p (tree base)
1488 return TREE_CODE (base) == PARM_DECL || constant_decl_p (base);
1491 /* Scan expressions occurring in STMT, create access structures for all accesses
1492 to candidates for scalarization and remove those candidates which occur in
1493 statements or expressions that prevent them from being split apart. Return
1494 true if any access has been inserted. */
1496 static bool
1497 build_accesses_from_assign (gimple *stmt)
1499 tree lhs, rhs;
1500 struct access *lacc, *racc;
1502 if (!gimple_assign_single_p (stmt)
1503 /* Scope clobbers don't influence scalarization. */
1504 || gimple_clobber_p (stmt))
1505 return false;
1507 lhs = gimple_assign_lhs (stmt);
1508 rhs = gimple_assign_rhs1 (stmt);
1510 if (disqualify_if_bad_bb_terminating_stmt (stmt, lhs, rhs))
1511 return false;
1513 racc = build_access_from_expr_1 (rhs, stmt, false);
1514 lacc = build_access_from_expr_1 (lhs, stmt, true);
1516 if (lacc)
1518 lacc->grp_assignment_write = 1;
1519 if (storage_order_barrier_p (rhs))
1520 lacc->grp_unscalarizable_region = 1;
1522 if (should_scalarize_away_bitmap && !is_gimple_reg_type (lacc->type))
1524 bool type_changing_p = false;
1525 contains_vce_or_bfcref_p (lhs, &type_changing_p);
1526 if (type_changing_p)
1527 bitmap_set_bit (cannot_scalarize_away_bitmap,
1528 DECL_UID (lacc->base));
1532 if (racc)
1534 racc->grp_assignment_read = 1;
1535 if (should_scalarize_away_bitmap && !is_gimple_reg_type (racc->type))
1537 bool type_changing_p = false;
1538 contains_vce_or_bfcref_p (rhs, &type_changing_p);
1540 if (type_changing_p || gimple_has_volatile_ops (stmt))
1541 bitmap_set_bit (cannot_scalarize_away_bitmap,
1542 DECL_UID (racc->base));
1543 else
1544 bitmap_set_bit (should_scalarize_away_bitmap,
1545 DECL_UID (racc->base));
1547 if (storage_order_barrier_p (lhs))
1548 racc->grp_unscalarizable_region = 1;
1551 if (lacc && racc
1552 && (sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
1553 && !lacc->grp_unscalarizable_region
1554 && !racc->grp_unscalarizable_region
1555 && AGGREGATE_TYPE_P (TREE_TYPE (lhs))
1556 && lacc->size == racc->size
1557 && useless_type_conversion_p (lacc->type, racc->type))
1559 struct assign_link *link;
1561 link = assign_link_pool.allocate ();
1562 memset (link, 0, sizeof (struct assign_link));
1564 link->lacc = lacc;
1565 link->racc = racc;
1566 add_link_to_rhs (racc, link);
1567 add_link_to_lhs (lacc, link);
1568 add_access_to_rhs_work_queue (racc);
1569 add_access_to_lhs_work_queue (lacc);
1571 /* Let's delay marking the areas as written until propagation of accesses
1572 across link, unless the nature of rhs tells us that its data comes
1573 from elsewhere. */
1574 if (!comes_initialized_p (racc->base))
1575 lacc->write = false;
1578 return lacc || racc;
1581 /* Callback of walk_stmt_load_store_addr_ops visit_addr used to detect taking
1582 addresses of candidates a places which are not call arguments. Such
1583 candidates are disqalified from SRA. This also applies to GIMPLE_ASM
1584 operands with memory constrains which cannot be scalarized. */
1586 static bool
1587 scan_visit_addr (gimple *, tree op, tree, void *)
1589 op = get_base_address (op);
1590 if (op
1591 && DECL_P (op))
1592 disqualify_candidate (op, "Address taken in a non-call-argument context.");
1594 return false;
1597 /* Scan function and look for interesting expressions and create access
1598 structures for them. Return true iff any access is created. */
1600 static bool
1601 scan_function (void)
1603 basic_block bb;
1604 bool ret = false;
1606 FOR_EACH_BB_FN (bb, cfun)
1608 gimple_stmt_iterator gsi;
1609 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1610 walk_stmt_load_store_addr_ops (gsi_stmt (gsi), NULL, NULL, NULL,
1611 scan_visit_addr);
1613 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1615 gimple *stmt = gsi_stmt (gsi);
1616 tree t;
1617 unsigned i;
1619 if (gimple_code (stmt) != GIMPLE_CALL)
1620 walk_stmt_load_store_addr_ops (stmt, NULL, NULL, NULL,
1621 scan_visit_addr);
1623 switch (gimple_code (stmt))
1625 case GIMPLE_RETURN:
1626 t = gimple_return_retval (as_a <greturn *> (stmt));
1627 if (t != NULL_TREE)
1628 ret |= build_access_from_expr (t, stmt, false);
1629 break;
1631 case GIMPLE_ASSIGN:
1632 ret |= build_accesses_from_assign (stmt);
1633 break;
1635 case GIMPLE_CALL:
1637 enum out_edge_check oe_check = SRA_OUTGOING_EDGES_UNCHECKED;
1638 gcall *call = as_a <gcall *> (stmt);
1639 for (i = 0; i < gimple_call_num_args (call); i++)
1641 bool can_be_returned;
1642 if (gimple_call_lhs (call))
1644 int af = gimple_call_arg_flags (call, i);
1645 can_be_returned = !(af & EAF_NOT_RETURNED_DIRECTLY);
1647 else
1648 can_be_returned = false;
1649 ret |= build_access_from_call_arg (gimple_call_arg (call,
1651 stmt, can_be_returned,
1652 &oe_check);
1654 if (gimple_call_chain(stmt))
1655 ret |= build_access_from_call_arg (gimple_call_chain(call),
1656 stmt, false, &oe_check);
1659 t = gimple_call_lhs (stmt);
1660 if (t && !disqualify_if_bad_bb_terminating_stmt (stmt, t, NULL))
1662 /* If the STMT is a call to DEFERRED_INIT, avoid setting
1663 cannot_scalarize_away_bitmap. */
1664 if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
1665 ret |= !!build_access_from_expr_1 (t, stmt, true);
1666 else
1667 ret |= build_access_from_expr (t, stmt, true);
1669 break;
1671 case GIMPLE_ASM:
1673 gasm *asm_stmt = as_a <gasm *> (stmt);
1674 if (stmt_ends_bb_p (asm_stmt)
1675 && !single_succ_p (gimple_bb (asm_stmt)))
1677 for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
1679 t = TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
1680 disqualify_base_of_expr (t, "OP of asm goto.");
1682 for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
1684 t = TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
1685 disqualify_base_of_expr (t, "OP of asm goto.");
1688 else
1690 for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
1692 t = TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
1693 ret |= build_access_from_expr (t, asm_stmt, false);
1695 for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
1697 t = TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
1698 ret |= build_access_from_expr (t, asm_stmt, true);
1702 break;
1704 default:
1705 break;
1710 return ret;
1713 /* Helper of QSORT function. There are pointers to accesses in the array. An
1714 access is considered smaller than another if it has smaller offset or if the
1715 offsets are the same but is size is bigger. */
1717 static int
1718 compare_access_positions (const void *a, const void *b)
1720 const access_p *fp1 = (const access_p *) a;
1721 const access_p *fp2 = (const access_p *) b;
1722 const access_p f1 = *fp1;
1723 const access_p f2 = *fp2;
1725 if (f1->offset != f2->offset)
1726 return f1->offset < f2->offset ? -1 : 1;
1728 if (f1->size == f2->size)
1730 if (f1->type == f2->type)
1731 return 0;
1732 /* Put any non-aggregate type before any aggregate type. */
1733 else if (!is_gimple_reg_type (f1->type)
1734 && is_gimple_reg_type (f2->type))
1735 return 1;
1736 else if (is_gimple_reg_type (f1->type)
1737 && !is_gimple_reg_type (f2->type))
1738 return -1;
1739 /* Put any complex or vector type before any other scalar type. */
1740 else if (TREE_CODE (f1->type) != COMPLEX_TYPE
1741 && TREE_CODE (f1->type) != VECTOR_TYPE
1742 && (TREE_CODE (f2->type) == COMPLEX_TYPE
1743 || VECTOR_TYPE_P (f2->type)))
1744 return 1;
1745 else if ((TREE_CODE (f1->type) == COMPLEX_TYPE
1746 || VECTOR_TYPE_P (f1->type))
1747 && TREE_CODE (f2->type) != COMPLEX_TYPE
1748 && TREE_CODE (f2->type) != VECTOR_TYPE)
1749 return -1;
1750 /* Put any integral type before any non-integral type. When splicing, we
1751 make sure that those with insufficient precision and occupying the
1752 same space are not scalarized. */
1753 else if (INTEGRAL_TYPE_P (f1->type)
1754 && !INTEGRAL_TYPE_P (f2->type))
1755 return -1;
1756 else if (!INTEGRAL_TYPE_P (f1->type)
1757 && INTEGRAL_TYPE_P (f2->type))
1758 return 1;
1759 /* Put the integral type with the bigger precision first. */
1760 else if (INTEGRAL_TYPE_P (f1->type)
1761 && INTEGRAL_TYPE_P (f2->type)
1762 && (TYPE_PRECISION (f2->type) != TYPE_PRECISION (f1->type)))
1763 return TYPE_PRECISION (f2->type) - TYPE_PRECISION (f1->type);
1764 /* Stabilize the sort. */
1765 return TYPE_UID (f1->type) - TYPE_UID (f2->type);
1768 /* We want the bigger accesses first, thus the opposite operator in the next
1769 line: */
1770 return f1->size > f2->size ? -1 : 1;
1774 /* Append a name of the declaration to the name obstack. A helper function for
1775 make_fancy_name. */
1777 static void
1778 make_fancy_decl_name (tree decl)
1780 char buffer[32];
1782 tree name = DECL_NAME (decl);
1783 if (name)
1784 obstack_grow (&name_obstack, IDENTIFIER_POINTER (name),
1785 IDENTIFIER_LENGTH (name));
1786 else
1788 sprintf (buffer, "D%u", DECL_UID (decl));
1789 obstack_grow (&name_obstack, buffer, strlen (buffer));
1793 /* Helper for make_fancy_name. */
1795 static void
1796 make_fancy_name_1 (tree expr)
1798 char buffer[32];
1799 tree index;
1801 if (DECL_P (expr))
1803 make_fancy_decl_name (expr);
1804 return;
1807 switch (TREE_CODE (expr))
1809 case COMPONENT_REF:
1810 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1811 obstack_1grow (&name_obstack, '$');
1812 make_fancy_decl_name (TREE_OPERAND (expr, 1));
1813 break;
1815 case ARRAY_REF:
1816 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1817 obstack_1grow (&name_obstack, '$');
1818 /* Arrays with only one element may not have a constant as their
1819 index. */
1820 index = TREE_OPERAND (expr, 1);
1821 if (TREE_CODE (index) != INTEGER_CST)
1822 break;
1823 sprintf (buffer, HOST_WIDE_INT_PRINT_DEC, TREE_INT_CST_LOW (index));
1824 obstack_grow (&name_obstack, buffer, strlen (buffer));
1825 break;
1827 case BIT_FIELD_REF:
1828 case ADDR_EXPR:
1829 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1830 break;
1832 case MEM_REF:
1833 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1834 if (!integer_zerop (TREE_OPERAND (expr, 1)))
1836 obstack_1grow (&name_obstack, '$');
1837 sprintf (buffer, HOST_WIDE_INT_PRINT_DEC,
1838 TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)));
1839 obstack_grow (&name_obstack, buffer, strlen (buffer));
1841 break;
1843 case REALPART_EXPR:
1844 case IMAGPART_EXPR:
1845 gcc_unreachable (); /* we treat these as scalars. */
1846 break;
1847 default:
1848 break;
1852 /* Create a human readable name for replacement variable of ACCESS. */
1854 static char *
1855 make_fancy_name (tree expr)
1857 make_fancy_name_1 (expr);
1858 obstack_1grow (&name_obstack, '\0');
1859 return XOBFINISH (&name_obstack, char *);
1862 /* Construct a MEM_REF that would reference a part of aggregate BASE of type
1863 EXP_TYPE at the given OFFSET and with storage order REVERSE. If BASE is
1864 something for which get_addr_base_and_unit_offset returns NULL, gsi must
1865 be non-NULL and is used to insert new statements either before or below
1866 the current one as specified by INSERT_AFTER. This function is not capable
1867 of handling bitfields. */
1869 tree
1870 build_ref_for_offset (location_t loc, tree base, poly_int64 offset,
1871 bool reverse, tree exp_type, gimple_stmt_iterator *gsi,
1872 bool insert_after)
1874 tree prev_base = base;
1875 tree off;
1876 tree mem_ref;
1877 poly_int64 base_offset;
1878 unsigned HOST_WIDE_INT misalign;
1879 unsigned int align;
1881 /* Preserve address-space information. */
1882 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (base));
1883 if (as != TYPE_ADDR_SPACE (exp_type))
1884 exp_type = build_qualified_type (exp_type,
1885 TYPE_QUALS (exp_type)
1886 | ENCODE_QUAL_ADDR_SPACE (as));
1888 poly_int64 byte_offset = exact_div (offset, BITS_PER_UNIT);
1889 get_object_alignment_1 (base, &align, &misalign);
1890 base = get_addr_base_and_unit_offset (base, &base_offset);
1892 /* get_addr_base_and_unit_offset returns NULL for references with a variable
1893 offset such as array[var_index]. */
1894 if (!base)
1896 gassign *stmt;
1897 tree tmp, addr;
1899 gcc_checking_assert (gsi);
1900 tmp = make_ssa_name (build_pointer_type (TREE_TYPE (prev_base)));
1901 addr = build_fold_addr_expr (unshare_expr (prev_base));
1902 STRIP_USELESS_TYPE_CONVERSION (addr);
1903 stmt = gimple_build_assign (tmp, addr);
1904 gimple_set_location (stmt, loc);
1905 if (insert_after)
1906 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
1907 else
1908 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
1910 off = build_int_cst (reference_alias_ptr_type (prev_base), byte_offset);
1911 base = tmp;
1913 else if (TREE_CODE (base) == MEM_REF)
1915 off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
1916 base_offset + byte_offset);
1917 off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
1918 base = unshare_expr (TREE_OPERAND (base, 0));
1920 else
1922 off = build_int_cst (reference_alias_ptr_type (prev_base),
1923 base_offset + byte_offset);
1924 base = build_fold_addr_expr (unshare_expr (base));
1927 unsigned int align_bound = known_alignment (misalign + offset);
1928 if (align_bound != 0)
1929 align = MIN (align, align_bound);
1930 if (align != TYPE_ALIGN (exp_type))
1931 exp_type = build_aligned_type (exp_type, align);
1933 mem_ref = fold_build2_loc (loc, MEM_REF, exp_type, base, off);
1934 REF_REVERSE_STORAGE_ORDER (mem_ref) = reverse;
1935 if (TREE_THIS_VOLATILE (prev_base))
1936 TREE_THIS_VOLATILE (mem_ref) = 1;
1937 if (TREE_SIDE_EFFECTS (prev_base))
1938 TREE_SIDE_EFFECTS (mem_ref) = 1;
1939 return mem_ref;
1942 /* Construct and return a memory reference that is equal to a portion of
1943 MODEL->expr but is based on BASE. If this cannot be done, return NULL. */
1945 static tree
1946 build_reconstructed_reference (location_t, tree base, struct access *model)
1948 tree expr = model->expr;
1949 /* We have to make sure to start just below the outermost union. */
1950 tree start_expr = expr;
1951 while (handled_component_p (expr))
1953 if (TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == UNION_TYPE)
1954 start_expr = expr;
1955 expr = TREE_OPERAND (expr, 0);
1958 expr = start_expr;
1959 tree prev_expr = NULL_TREE;
1960 while (!types_compatible_p (TREE_TYPE (expr), TREE_TYPE (base)))
1962 if (!handled_component_p (expr))
1963 return NULL_TREE;
1964 prev_expr = expr;
1965 expr = TREE_OPERAND (expr, 0);
1968 /* Guard against broken VIEW_CONVERT_EXPRs... */
1969 if (!prev_expr)
1970 return NULL_TREE;
1972 TREE_OPERAND (prev_expr, 0) = base;
1973 tree ref = unshare_expr (model->expr);
1974 TREE_OPERAND (prev_expr, 0) = expr;
1975 return ref;
1978 /* Construct a memory reference to a part of an aggregate BASE at the given
1979 OFFSET and of the same type as MODEL. In case this is a reference to a
1980 bit-field, the function will replicate the last component_ref of model's
1981 expr to access it. INSERT_AFTER and GSI have the same meaning as in
1982 build_ref_for_offset, furthermore, when GSI is NULL, the function expects
1983 that it re-builds the entire reference from a DECL to the final access and
1984 so will create a MEM_REF when OFFSET does not exactly match offset of
1985 MODEL. */
1987 static tree
1988 build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
1989 struct access *model, gimple_stmt_iterator *gsi,
1990 bool insert_after)
1992 gcc_assert (offset >= 0);
1993 if (TREE_CODE (model->expr) == COMPONENT_REF
1994 && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
1996 /* This access represents a bit-field. */
1997 tree t, exp_type, fld = TREE_OPERAND (model->expr, 1);
1999 offset -= int_bit_position (fld);
2000 exp_type = TREE_TYPE (TREE_OPERAND (model->expr, 0));
2001 t = build_ref_for_offset (loc, base, offset, model->reverse, exp_type,
2002 gsi, insert_after);
2003 /* The flag will be set on the record type. */
2004 REF_REVERSE_STORAGE_ORDER (t) = 0;
2005 return fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (fld), t, fld,
2006 NULL_TREE);
2008 else
2010 tree res;
2011 if (model->grp_same_access_path
2012 && !TREE_THIS_VOLATILE (base)
2013 && (TYPE_ADDR_SPACE (TREE_TYPE (base))
2014 == TYPE_ADDR_SPACE (TREE_TYPE (model->expr)))
2015 && (offset == model->offset
2016 || (gsi && offset <= model->offset))
2017 /* build_reconstructed_reference can still fail if we have already
2018 massaged BASE because of another type incompatibility. */
2019 && (res = build_reconstructed_reference (loc, base, model)))
2020 return res;
2021 else
2022 return build_ref_for_offset (loc, base, offset, model->reverse,
2023 model->type, gsi, insert_after);
2027 /* Attempt to build a memory reference that we could but into a gimple
2028 debug_bind statement. Similar to build_ref_for_model but punts if it has to
2029 create statements and return s NULL instead. This function also ignores
2030 alignment issues and so its results should never end up in non-debug
2031 statements. */
2033 static tree
2034 build_debug_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
2035 struct access *model)
2037 poly_int64 base_offset;
2038 tree off;
2040 if (TREE_CODE (model->expr) == COMPONENT_REF
2041 && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
2042 return NULL_TREE;
2044 base = get_addr_base_and_unit_offset (base, &base_offset);
2045 if (!base)
2046 return NULL_TREE;
2047 if (TREE_CODE (base) == MEM_REF)
2049 off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
2050 base_offset + offset / BITS_PER_UNIT);
2051 off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
2052 base = unshare_expr (TREE_OPERAND (base, 0));
2054 else
2056 off = build_int_cst (reference_alias_ptr_type (base),
2057 base_offset + offset / BITS_PER_UNIT);
2058 base = build_fold_addr_expr (unshare_expr (base));
2061 return fold_build2_loc (loc, MEM_REF, model->type, base, off);
2064 /* Construct a memory reference consisting of component_refs and array_refs to
2065 a part of an aggregate *RES (which is of type TYPE). The requested part
2066 should have type EXP_TYPE at be the given OFFSET. This function might not
2067 succeed, it returns true when it does and only then *RES points to something
2068 meaningful. This function should be used only to build expressions that we
2069 might need to present to user (e.g. in warnings). In all other situations,
2070 build_ref_for_model or build_ref_for_offset should be used instead. */
2072 static bool
2073 build_user_friendly_ref_for_offset (tree *res, tree type, HOST_WIDE_INT offset,
2074 tree exp_type)
2076 while (1)
2078 tree fld;
2079 tree tr_size, index, minidx;
2080 HOST_WIDE_INT el_size;
2082 if (offset == 0 && exp_type
2083 && types_compatible_p (exp_type, type))
2084 return true;
2086 switch (TREE_CODE (type))
2088 case UNION_TYPE:
2089 case QUAL_UNION_TYPE:
2090 case RECORD_TYPE:
2091 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
2093 HOST_WIDE_INT pos, size;
2094 tree tr_pos, expr, *expr_ptr;
2096 if (TREE_CODE (fld) != FIELD_DECL)
2097 continue;
2099 tr_pos = bit_position (fld);
2100 if (!tr_pos || !tree_fits_uhwi_p (tr_pos))
2101 continue;
2102 pos = tree_to_uhwi (tr_pos);
2103 gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0);
2104 tr_size = DECL_SIZE (fld);
2105 if (!tr_size || !tree_fits_uhwi_p (tr_size))
2106 continue;
2107 size = tree_to_uhwi (tr_size);
2108 if (size == 0)
2110 if (pos != offset)
2111 continue;
2113 else if (pos > offset || (pos + size) <= offset)
2114 continue;
2116 expr = build3 (COMPONENT_REF, TREE_TYPE (fld), *res, fld,
2117 NULL_TREE);
2118 expr_ptr = &expr;
2119 if (build_user_friendly_ref_for_offset (expr_ptr, TREE_TYPE (fld),
2120 offset - pos, exp_type))
2122 *res = expr;
2123 return true;
2126 return false;
2128 case ARRAY_TYPE:
2129 tr_size = TYPE_SIZE (TREE_TYPE (type));
2130 if (!tr_size || !tree_fits_uhwi_p (tr_size))
2131 return false;
2132 el_size = tree_to_uhwi (tr_size);
2134 minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
2135 if (TREE_CODE (minidx) != INTEGER_CST || el_size == 0)
2136 return false;
2137 index = build_int_cst (TYPE_DOMAIN (type), offset / el_size);
2138 if (!integer_zerop (minidx))
2139 index = int_const_binop (PLUS_EXPR, index, minidx);
2140 *res = build4 (ARRAY_REF, TREE_TYPE (type), *res, index,
2141 NULL_TREE, NULL_TREE);
2142 offset = offset % el_size;
2143 type = TREE_TYPE (type);
2144 break;
2146 default:
2147 if (offset != 0)
2148 return false;
2150 if (exp_type)
2151 return false;
2152 else
2153 return true;
2158 /* Print message to dump file why a variable was rejected. */
2160 static void
2161 reject (tree var, const char *msg)
2163 if (dump_file && (dump_flags & TDF_DETAILS))
2165 fprintf (dump_file, "Rejected (%d): %s: ", DECL_UID (var), msg);
2166 print_generic_expr (dump_file, var);
2167 fprintf (dump_file, "\n");
2171 /* Return true if VAR is a candidate for SRA. */
2173 static bool
2174 maybe_add_sra_candidate (tree var)
2176 tree type = TREE_TYPE (var);
2177 const char *msg;
2178 tree_node **slot;
2180 if (!AGGREGATE_TYPE_P (type))
2182 reject (var, "not aggregate");
2183 return false;
2186 if ((is_global_var (var)
2187 /* There are cases where non-addressable variables fail the
2188 pt_solutions_check test, e.g in gcc.dg/uninit-40.c. */
2189 || (TREE_ADDRESSABLE (var)
2190 && pt_solution_includes (&cfun->gimple_df->escaped_return, var))
2191 || (TREE_CODE (var) == RESULT_DECL
2192 && !DECL_BY_REFERENCE (var)
2193 && aggregate_value_p (var, current_function_decl)))
2194 /* Allow constant-pool entries that "need to live in memory". */
2195 && !constant_decl_p (var))
2197 reject (var, "needs to live in memory and escapes or global");
2198 return false;
2200 if (TREE_THIS_VOLATILE (var))
2202 reject (var, "is volatile");
2203 return false;
2205 if (!COMPLETE_TYPE_P (type))
2207 reject (var, "has incomplete type");
2208 return false;
2210 if (!tree_fits_shwi_p (TYPE_SIZE (type)))
2212 reject (var, "type size not fixed");
2213 return false;
2215 if (tree_to_shwi (TYPE_SIZE (type)) == 0)
2217 reject (var, "type size is zero");
2218 return false;
2220 if (type_internals_preclude_sra_p (type, &msg))
2222 reject (var, msg);
2223 return false;
2225 if (/* Fix for PR 41089. tree-stdarg.cc needs to have va_lists intact but
2226 we also want to schedule it rather late. Thus we ignore it in
2227 the early pass. */
2228 (sra_mode == SRA_MODE_EARLY_INTRA
2229 && is_va_list_type (type)))
2231 reject (var, "is va_list");
2232 return false;
2235 bitmap_set_bit (candidate_bitmap, DECL_UID (var));
2236 slot = candidates->find_slot_with_hash (var, DECL_UID (var), INSERT);
2237 *slot = var;
2239 if (dump_file && (dump_flags & TDF_DETAILS))
2241 fprintf (dump_file, "Candidate (%d): ", DECL_UID (var));
2242 print_generic_expr (dump_file, var);
2243 fprintf (dump_file, "\n");
2246 return true;
2249 /* The very first phase of intraprocedural SRA. It marks in candidate_bitmap
2250 those with type which is suitable for scalarization. */
2252 static bool
2253 find_var_candidates (void)
2255 tree var, parm;
2256 unsigned int i;
2257 bool ret = false;
2259 for (parm = DECL_ARGUMENTS (current_function_decl);
2260 parm;
2261 parm = DECL_CHAIN (parm))
2262 ret |= maybe_add_sra_candidate (parm);
2264 FOR_EACH_LOCAL_DECL (cfun, i, var)
2266 if (!VAR_P (var))
2267 continue;
2269 ret |= maybe_add_sra_candidate (var);
2272 return ret;
2275 /* Return true if EXP is a reference chain of COMPONENT_REFs and AREAY_REFs
2276 ending either with a DECL or a MEM_REF with zero offset. */
2278 static bool
2279 path_comparable_for_same_access (tree expr)
2281 while (handled_component_p (expr))
2283 if (TREE_CODE (expr) == ARRAY_REF)
2285 /* SSA name indices can occur here too when the array is of sie one.
2286 But we cannot just re-use array_refs with SSA names elsewhere in
2287 the function, so disallow non-constant indices. TODO: Remove this
2288 limitation after teaching build_reconstructed_reference to replace
2289 the index with the index type lower bound. */
2290 if (TREE_CODE (TREE_OPERAND (expr, 1)) != INTEGER_CST)
2291 return false;
2293 expr = TREE_OPERAND (expr, 0);
2296 if (TREE_CODE (expr) == MEM_REF)
2298 if (!zerop (TREE_OPERAND (expr, 1)))
2299 return false;
2301 else
2302 gcc_assert (DECL_P (expr));
2304 return true;
2307 /* Assuming that EXP1 consists of only COMPONENT_REFs and ARRAY_REFs, return
2308 true if the chain of these handled components are exactly the same as EXP2
2309 and the expression under them is the same DECL or an equivalent MEM_REF.
2310 The reference picked by compare_access_positions must go to EXP1. */
2312 static bool
2313 same_access_path_p (tree exp1, tree exp2)
2315 if (TREE_CODE (exp1) != TREE_CODE (exp2))
2317 /* Special case single-field structures loaded sometimes as the field
2318 and sometimes as the structure. If the field is of a scalar type,
2319 compare_access_positions will put it into exp1.
2321 TODO: The gimple register type condition can be removed if teach
2322 compare_access_positions to put inner types first. */
2323 if (is_gimple_reg_type (TREE_TYPE (exp1))
2324 && TREE_CODE (exp1) == COMPONENT_REF
2325 && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (exp1, 0)))
2326 == TYPE_MAIN_VARIANT (TREE_TYPE (exp2))))
2327 exp1 = TREE_OPERAND (exp1, 0);
2328 else
2329 return false;
2332 if (!operand_equal_p (exp1, exp2, OEP_ADDRESS_OF))
2333 return false;
2335 return true;
2338 /* Sort all accesses for the given variable, check for partial overlaps and
2339 return NULL if there are any. If there are none, pick a representative for
2340 each combination of offset and size and create a linked list out of them.
2341 Return the pointer to the first representative and make sure it is the first
2342 one in the vector of accesses. */
2344 static struct access *
2345 sort_and_splice_var_accesses (tree var)
2347 int i, j, access_count;
2348 struct access *res, **prev_acc_ptr = &res;
2349 vec<access_p> *access_vec;
2350 bool first = true;
2351 HOST_WIDE_INT low = -1, high = 0;
2353 access_vec = get_base_access_vector (var);
2354 if (!access_vec)
2355 return NULL;
2356 access_count = access_vec->length ();
2358 /* Sort by <OFFSET, SIZE>. */
2359 access_vec->qsort (compare_access_positions);
2361 i = 0;
2362 while (i < access_count)
2364 struct access *access = (*access_vec)[i];
2365 bool grp_write = access->write;
2366 bool grp_read = !access->write;
2367 bool grp_scalar_write = access->write
2368 && is_gimple_reg_type (access->type);
2369 bool grp_scalar_read = !access->write
2370 && is_gimple_reg_type (access->type);
2371 bool grp_assignment_read = access->grp_assignment_read;
2372 bool grp_assignment_write = access->grp_assignment_write;
2373 bool multiple_scalar_reads = false;
2374 bool grp_partial_lhs = access->grp_partial_lhs;
2375 bool first_scalar = is_gimple_reg_type (access->type);
2376 bool unscalarizable_region = access->grp_unscalarizable_region;
2377 bool grp_same_access_path = true;
2378 bool bf_non_full_precision
2379 = (INTEGRAL_TYPE_P (access->type)
2380 && TYPE_PRECISION (access->type) != access->size
2381 && TREE_CODE (access->expr) == COMPONENT_REF
2382 && DECL_BIT_FIELD (TREE_OPERAND (access->expr, 1)));
2384 if (first || access->offset >= high)
2386 first = false;
2387 low = access->offset;
2388 high = access->offset + access->size;
2390 else if (access->offset > low && access->offset + access->size > high)
2391 return NULL;
2392 else
2393 gcc_assert (access->offset >= low
2394 && access->offset + access->size <= high);
2396 if (INTEGRAL_TYPE_P (access->type)
2397 && TYPE_PRECISION (access->type) != access->size
2398 && bitmap_bit_p (passed_by_ref_in_call, DECL_UID (access->base)))
2400 /* This can lead to performance regressions because we can generate
2401 excessive zero extensions. */
2402 if (dump_file && (dump_flags & TDF_DETAILS))
2404 fprintf (dump_file, "Won't scalarize ");
2405 print_generic_expr (dump_file, access->base);
2406 fprintf (dump_file, "(%d), it is passed by reference to a call "
2407 "and there are accesses with precision not covering "
2408 "their type size.", DECL_UID (access->base));
2410 return NULL;
2413 grp_same_access_path = path_comparable_for_same_access (access->expr);
2415 j = i + 1;
2416 while (j < access_count)
2418 struct access *ac2 = (*access_vec)[j];
2419 if (ac2->offset != access->offset || ac2->size != access->size)
2420 break;
2421 if (ac2->write)
2423 grp_write = true;
2424 grp_scalar_write = (grp_scalar_write
2425 || is_gimple_reg_type (ac2->type));
2427 else
2429 grp_read = true;
2430 if (is_gimple_reg_type (ac2->type))
2432 if (grp_scalar_read)
2433 multiple_scalar_reads = true;
2434 else
2435 grp_scalar_read = true;
2438 grp_assignment_read |= ac2->grp_assignment_read;
2439 grp_assignment_write |= ac2->grp_assignment_write;
2440 grp_partial_lhs |= ac2->grp_partial_lhs;
2441 unscalarizable_region |= ac2->grp_unscalarizable_region;
2442 relink_to_new_repr (access, ac2);
2444 /* If there are both aggregate-type and scalar-type accesses with
2445 this combination of size and offset, the comparison function
2446 should have put the scalars first. */
2447 gcc_assert (first_scalar || !is_gimple_reg_type (ac2->type));
2448 /* It also prefers integral types to non-integral. However, when the
2449 precision of the selected type does not span the entire area and
2450 should also be used for a non-integer (i.e. float), we must not
2451 let that happen. Normally analyze_access_subtree expands the type
2452 to cover the entire area but for bit-fields it doesn't. */
2453 if (bf_non_full_precision && !INTEGRAL_TYPE_P (ac2->type))
2455 if (dump_file && (dump_flags & TDF_DETAILS))
2457 fprintf (dump_file, "Cannot scalarize the following access "
2458 "because insufficient precision integer type was "
2459 "selected.\n ");
2460 dump_access (dump_file, access, false);
2462 unscalarizable_region = true;
2465 if (grp_same_access_path
2466 && !same_access_path_p (access->expr, ac2->expr))
2467 grp_same_access_path = false;
2469 ac2->group_representative = access;
2470 j++;
2473 i = j;
2475 access->group_representative = access;
2476 access->grp_write = grp_write;
2477 access->grp_read = grp_read;
2478 access->grp_scalar_read = grp_scalar_read;
2479 access->grp_scalar_write = grp_scalar_write;
2480 access->grp_assignment_read = grp_assignment_read;
2481 access->grp_assignment_write = grp_assignment_write;
2482 access->grp_hint = multiple_scalar_reads && !constant_decl_p (var);
2483 access->grp_partial_lhs = grp_partial_lhs;
2484 access->grp_unscalarizable_region = unscalarizable_region;
2485 access->grp_same_access_path = grp_same_access_path;
2487 *prev_acc_ptr = access;
2488 prev_acc_ptr = &access->next_grp;
2491 gcc_assert (res == (*access_vec)[0]);
2492 return res;
2495 /* Create a variable for the given ACCESS which determines the type, name and a
2496 few other properties. Return the variable declaration and store it also to
2497 ACCESS->replacement. REG_TREE is used when creating a declaration to base a
2498 default-definition SSA name on in order to facilitate an uninitialized
2499 warning. It is used instead of the actual ACCESS type if that is not of a
2500 gimple register type. */
2502 static tree
2503 create_access_replacement (struct access *access, tree reg_type = NULL_TREE)
2505 tree repl;
2507 tree type = access->type;
2508 if (reg_type && !is_gimple_reg_type (type))
2509 type = reg_type;
2511 if (access->grp_to_be_debug_replaced)
2513 repl = create_tmp_var_raw (access->type);
2514 DECL_CONTEXT (repl) = current_function_decl;
2516 else
2517 /* Drop any special alignment on the type if it's not on the main
2518 variant. This avoids issues with weirdo ABIs like AAPCS. */
2519 repl = create_tmp_var (build_qualified_type (TYPE_MAIN_VARIANT (type),
2520 TYPE_QUALS (type)), "SR");
2521 if (access->grp_partial_lhs
2522 && is_gimple_reg_type (type))
2523 DECL_NOT_GIMPLE_REG_P (repl) = 1;
2525 DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base);
2526 DECL_ARTIFICIAL (repl) = 1;
2527 DECL_IGNORED_P (repl) = DECL_IGNORED_P (access->base);
2529 if (DECL_NAME (access->base)
2530 && !DECL_IGNORED_P (access->base)
2531 && !DECL_ARTIFICIAL (access->base))
2533 char *pretty_name = make_fancy_name (access->expr);
2534 tree debug_expr = unshare_expr_without_location (access->expr), d;
2535 bool fail = false;
2537 DECL_NAME (repl) = get_identifier (pretty_name);
2538 DECL_NAMELESS (repl) = 1;
2539 obstack_free (&name_obstack, pretty_name);
2541 /* Get rid of any SSA_NAMEs embedded in debug_expr,
2542 as DECL_DEBUG_EXPR isn't considered when looking for still
2543 used SSA_NAMEs and thus they could be freed. All debug info
2544 generation cares is whether something is constant or variable
2545 and that get_ref_base_and_extent works properly on the
2546 expression. It cannot handle accesses at a non-constant offset
2547 though, so just give up in those cases. */
2548 for (d = debug_expr;
2549 !fail && (handled_component_p (d) || TREE_CODE (d) == MEM_REF);
2550 d = TREE_OPERAND (d, 0))
2551 switch (TREE_CODE (d))
2553 case ARRAY_REF:
2554 case ARRAY_RANGE_REF:
2555 if (TREE_OPERAND (d, 1)
2556 && TREE_CODE (TREE_OPERAND (d, 1)) != INTEGER_CST)
2557 fail = true;
2558 if (TREE_OPERAND (d, 3)
2559 && TREE_CODE (TREE_OPERAND (d, 3)) != INTEGER_CST)
2560 fail = true;
2561 /* FALLTHRU */
2562 case COMPONENT_REF:
2563 if (TREE_OPERAND (d, 2)
2564 && TREE_CODE (TREE_OPERAND (d, 2)) != INTEGER_CST)
2565 fail = true;
2566 break;
2567 case MEM_REF:
2568 if (TREE_CODE (TREE_OPERAND (d, 0)) != ADDR_EXPR)
2569 fail = true;
2570 else
2571 d = TREE_OPERAND (d, 0);
2572 break;
2573 default:
2574 break;
2576 if (!fail)
2578 SET_DECL_DEBUG_EXPR (repl, debug_expr);
2579 DECL_HAS_DEBUG_EXPR_P (repl) = 1;
2581 if (access->grp_no_warning)
2582 suppress_warning (repl /* Be more selective! */);
2583 else
2584 copy_warning (repl, access->base);
2586 else
2587 suppress_warning (repl /* Be more selective! */);
2589 if (dump_file)
2591 if (access->grp_to_be_debug_replaced)
2593 fprintf (dump_file, "Created a debug-only replacement for ");
2594 print_generic_expr (dump_file, access->base);
2595 fprintf (dump_file, " offset: %u, size: %u\n",
2596 (unsigned) access->offset, (unsigned) access->size);
2598 else
2600 fprintf (dump_file, "Created a replacement for ");
2601 print_generic_expr (dump_file, access->base);
2602 fprintf (dump_file, " offset: %u, size: %u: ",
2603 (unsigned) access->offset, (unsigned) access->size);
2604 print_generic_expr (dump_file, repl, TDF_UID);
2605 fprintf (dump_file, "\n");
2608 sra_stats.replacements++;
2610 return repl;
2613 /* Return ACCESS scalar replacement, which must exist. */
2615 static inline tree
2616 get_access_replacement (struct access *access)
2618 gcc_checking_assert (access->replacement_decl);
2619 return access->replacement_decl;
2623 /* Build a subtree of accesses rooted in *ACCESS, and move the pointer in the
2624 linked list along the way. Stop when *ACCESS is NULL or the access pointed
2625 to it is not "within" the root. Return false iff some accesses partially
2626 overlap. */
2628 static bool
2629 build_access_subtree (struct access **access)
2631 struct access *root = *access, *last_child = NULL;
2632 HOST_WIDE_INT limit = root->offset + root->size;
2634 *access = (*access)->next_grp;
2635 while (*access && (*access)->offset + (*access)->size <= limit)
2637 if (!last_child)
2638 root->first_child = *access;
2639 else
2640 last_child->next_sibling = *access;
2641 last_child = *access;
2642 (*access)->parent = root;
2643 (*access)->grp_write |= root->grp_write;
2645 if (!build_access_subtree (access))
2646 return false;
2649 if (*access && (*access)->offset < limit)
2650 return false;
2652 return true;
2655 /* Build a tree of access representatives, ACCESS is the pointer to the first
2656 one, others are linked in a list by the next_grp field. Return false iff
2657 some accesses partially overlap. */
2659 static bool
2660 build_access_trees (struct access *access)
2662 while (access)
2664 struct access *root = access;
2666 if (!build_access_subtree (&access))
2667 return false;
2668 root->next_grp = access;
2670 return true;
2673 /* Traverse the access forest where ROOT is the first root and verify that
2674 various important invariants hold true. */
2676 DEBUG_FUNCTION void
2677 verify_sra_access_forest (struct access *root)
2679 struct access *access = root;
2680 tree first_base = root->base;
2681 gcc_assert (DECL_P (first_base));
2684 gcc_assert (access->base == first_base);
2685 if (access->parent)
2686 gcc_assert (access->offset >= access->parent->offset
2687 && access->size <= access->parent->size);
2688 if (access->next_sibling)
2689 gcc_assert (access->next_sibling->offset
2690 >= access->offset + access->size);
2692 poly_int64 poffset, psize, pmax_size;
2693 bool reverse;
2694 tree base = get_ref_base_and_extent (access->expr, &poffset, &psize,
2695 &pmax_size, &reverse);
2696 HOST_WIDE_INT offset, size, max_size;
2697 if (!poffset.is_constant (&offset)
2698 || !psize.is_constant (&size)
2699 || !pmax_size.is_constant (&max_size))
2700 gcc_unreachable ();
2701 gcc_assert (base == first_base);
2702 gcc_assert (offset == access->offset);
2703 gcc_assert (access->grp_unscalarizable_region
2704 || access->grp_total_scalarization
2705 || size == max_size);
2706 gcc_assert (access->grp_unscalarizable_region
2707 || !is_gimple_reg_type (access->type)
2708 || size == access->size);
2709 gcc_assert (reverse == access->reverse);
2711 if (access->first_child)
2713 gcc_assert (access->first_child->parent == access);
2714 access = access->first_child;
2716 else if (access->next_sibling)
2718 gcc_assert (access->next_sibling->parent == access->parent);
2719 access = access->next_sibling;
2721 else
2723 while (access->parent && !access->next_sibling)
2724 access = access->parent;
2725 if (access->next_sibling)
2726 access = access->next_sibling;
2727 else
2729 gcc_assert (access == root);
2730 root = root->next_grp;
2731 access = root;
2735 while (access);
2738 /* Verify access forests of all candidates with accesses by calling
2739 verify_access_forest on each on them. */
2741 DEBUG_FUNCTION void
2742 verify_all_sra_access_forests (void)
2744 bitmap_iterator bi;
2745 unsigned i;
2746 EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
2748 tree var = candidate (i);
2749 struct access *access = get_first_repr_for_decl (var);
2750 if (access)
2752 gcc_assert (access->base == var);
2753 verify_sra_access_forest (access);
2758 /* Return true if expr contains some ARRAY_REFs into a variable bounded
2759 array. */
2761 static bool
2762 expr_with_var_bounded_array_refs_p (tree expr)
2764 while (handled_component_p (expr))
2766 if (TREE_CODE (expr) == ARRAY_REF
2767 && !tree_fits_shwi_p (array_ref_low_bound (expr)))
2768 return true;
2769 expr = TREE_OPERAND (expr, 0);
2771 return false;
2774 /* Analyze the subtree of accesses rooted in ROOT, scheduling replacements when
2775 both seeming beneficial and when ALLOW_REPLACEMENTS allows it. If TOTALLY
2776 is set, we are totally scalarizing the aggregate. Also set all sorts of
2777 access flags appropriately along the way, notably always set grp_read and
2778 grp_assign_read according to MARK_READ and grp_write when MARK_WRITE is
2779 true.
2781 Creating a replacement for a scalar access is considered beneficial if its
2782 grp_hint ot TOTALLY is set (this means either that there is more than one
2783 direct read access or that we are attempting total scalarization) or
2784 according to the following table:
2786 Access written to through a scalar type (once or more times)
2788 | Written to in an assignment statement
2790 | | Access read as scalar _once_
2791 | | |
2792 | | | Read in an assignment statement
2793 | | | |
2794 | | | | Scalarize Comment
2795 -----------------------------------------------------------------------------
2796 0 0 0 0 No access for the scalar
2797 0 0 0 1 No access for the scalar
2798 0 0 1 0 No Single read - won't help
2799 0 0 1 1 No The same case
2800 0 1 0 0 No access for the scalar
2801 0 1 0 1 No access for the scalar
2802 0 1 1 0 Yes s = *g; return s.i;
2803 0 1 1 1 Yes The same case as above
2804 1 0 0 0 No Won't help
2805 1 0 0 1 Yes s.i = 1; *g = s;
2806 1 0 1 0 Yes s.i = 5; g = s.i;
2807 1 0 1 1 Yes The same case as above
2808 1 1 0 0 No Won't help.
2809 1 1 0 1 Yes s.i = 1; *g = s;
2810 1 1 1 0 Yes s = *g; return s.i;
2811 1 1 1 1 Yes Any of the above yeses */
2813 static bool
2814 analyze_access_subtree (struct access *root, struct access *parent,
2815 bool allow_replacements, bool totally)
2817 struct access *child;
2818 HOST_WIDE_INT limit = root->offset + root->size;
2819 HOST_WIDE_INT covered_to = root->offset;
2820 bool scalar = is_gimple_reg_type (root->type);
2821 bool hole = false, sth_created = false;
2823 if (parent)
2825 if (parent->grp_read)
2826 root->grp_read = 1;
2827 if (parent->grp_assignment_read)
2828 root->grp_assignment_read = 1;
2829 if (parent->grp_write)
2830 root->grp_write = 1;
2831 if (parent->grp_assignment_write)
2832 root->grp_assignment_write = 1;
2833 if (!parent->grp_same_access_path)
2834 root->grp_same_access_path = 0;
2837 if (root->grp_unscalarizable_region)
2838 allow_replacements = false;
2840 if (allow_replacements && expr_with_var_bounded_array_refs_p (root->expr))
2841 allow_replacements = false;
2843 if (!totally && root->grp_result_of_prop_from_lhs)
2844 allow_replacements = false;
2846 for (child = root->first_child; child; child = child->next_sibling)
2848 hole |= covered_to < child->offset;
2849 sth_created |= analyze_access_subtree (child, root,
2850 allow_replacements && !scalar
2851 && !root->grp_partial_lhs,
2852 totally);
2854 root->grp_unscalarized_data |= child->grp_unscalarized_data;
2855 if (child->grp_covered)
2856 covered_to += child->size;
2857 else
2858 hole = true;
2861 if (allow_replacements && scalar && !root->first_child
2862 && (totally || !root->grp_total_scalarization)
2863 && (totally
2864 || root->grp_hint
2865 || ((root->grp_scalar_read || root->grp_assignment_read)
2866 && (root->grp_scalar_write || root->grp_assignment_write))))
2868 /* Always create access replacements that cover the whole access.
2869 For integral types this means the precision has to match.
2870 Avoid assumptions based on the integral type kind, too. */
2871 if (INTEGRAL_TYPE_P (root->type)
2872 && ((TREE_CODE (root->type) != INTEGER_TYPE
2873 && TREE_CODE (root->type) != BITINT_TYPE)
2874 || TYPE_PRECISION (root->type) != root->size)
2875 /* But leave bitfield accesses alone. */
2876 && (TREE_CODE (root->expr) != COMPONENT_REF
2877 || !DECL_BIT_FIELD (TREE_OPERAND (root->expr, 1))))
2879 tree rt = root->type;
2880 gcc_assert ((root->offset % BITS_PER_UNIT) == 0
2881 && (root->size % BITS_PER_UNIT) == 0);
2882 if (TREE_CODE (root->type) == BITINT_TYPE)
2883 root->type = build_bitint_type (root->size, TYPE_UNSIGNED (rt));
2884 else
2885 root->type = build_nonstandard_integer_type (root->size,
2886 TYPE_UNSIGNED (rt));
2887 root->expr = build_ref_for_offset (UNKNOWN_LOCATION, root->base,
2888 root->offset, root->reverse,
2889 root->type, NULL, false);
2891 if (dump_file && (dump_flags & TDF_DETAILS))
2893 fprintf (dump_file, "Changing the type of a replacement for ");
2894 print_generic_expr (dump_file, root->base);
2895 fprintf (dump_file, " offset: %u, size: %u ",
2896 (unsigned) root->offset, (unsigned) root->size);
2897 fprintf (dump_file, " to an integer.\n");
2901 root->grp_to_be_replaced = 1;
2902 root->replacement_decl = create_access_replacement (root);
2903 sth_created = true;
2904 hole = false;
2906 else
2908 if (allow_replacements
2909 && scalar && !root->first_child
2910 && !root->grp_total_scalarization
2911 && (root->grp_scalar_write || root->grp_assignment_write)
2912 && !bitmap_bit_p (cannot_scalarize_away_bitmap,
2913 DECL_UID (root->base)))
2915 gcc_checking_assert (!root->grp_scalar_read
2916 && !root->grp_assignment_read);
2917 sth_created = true;
2918 if (MAY_HAVE_DEBUG_BIND_STMTS)
2920 root->grp_to_be_debug_replaced = 1;
2921 root->replacement_decl = create_access_replacement (root);
2925 if (covered_to < limit)
2926 hole = true;
2927 if (scalar || !allow_replacements)
2928 root->grp_total_scalarization = 0;
2931 if (!hole || totally)
2932 root->grp_covered = 1;
2933 else if (root->grp_write || comes_initialized_p (root->base))
2934 root->grp_unscalarized_data = 1; /* not covered and written to */
2935 return sth_created;
2938 /* Analyze all access trees linked by next_grp by the means of
2939 analyze_access_subtree. */
2940 static bool
2941 analyze_access_trees (struct access *access)
2943 bool ret = false;
2945 while (access)
2947 if (analyze_access_subtree (access, NULL, true,
2948 access->grp_total_scalarization))
2949 ret = true;
2950 access = access->next_grp;
2953 return ret;
2956 /* Return true iff a potential new child of ACC at offset OFFSET and with size
2957 SIZE would conflict with an already existing one. If exactly such a child
2958 already exists in ACC, store a pointer to it in EXACT_MATCH. */
2960 static bool
2961 child_would_conflict_in_acc (struct access *acc, HOST_WIDE_INT norm_offset,
2962 HOST_WIDE_INT size, struct access **exact_match)
2964 struct access *child;
2966 for (child = acc->first_child; child; child = child->next_sibling)
2968 if (child->offset == norm_offset && child->size == size)
2970 *exact_match = child;
2971 return true;
2974 if (child->offset < norm_offset + size
2975 && child->offset + child->size > norm_offset)
2976 return true;
2979 return false;
2982 /* Create a new child access of PARENT, with all properties just like MODEL
2983 except for its offset and with its grp_write false and grp_read true.
2984 Return the new access or NULL if it cannot be created. Note that this
2985 access is created long after all splicing and sorting, it's not located in
2986 any access vector and is automatically a representative of its group. Set
2987 the gpr_write flag of the new accesss if SET_GRP_WRITE is true. */
2989 static struct access *
2990 create_artificial_child_access (struct access *parent, struct access *model,
2991 HOST_WIDE_INT new_offset,
2992 bool set_grp_read, bool set_grp_write)
2994 struct access **child;
2995 tree expr = parent->base;
2997 gcc_assert (!model->grp_unscalarizable_region);
2999 struct access *access = access_pool.allocate ();
3000 memset (access, 0, sizeof (struct access));
3001 if (!build_user_friendly_ref_for_offset (&expr, TREE_TYPE (expr), new_offset,
3002 model->type))
3004 access->grp_no_warning = true;
3005 expr = build_ref_for_model (EXPR_LOCATION (parent->base), parent->base,
3006 new_offset, model, NULL, false);
3009 access->base = parent->base;
3010 access->expr = expr;
3011 access->offset = new_offset;
3012 access->size = model->size;
3013 access->type = model->type;
3014 access->parent = parent;
3015 access->grp_read = set_grp_read;
3016 access->grp_write = set_grp_write;
3017 access->reverse = model->reverse;
3019 child = &parent->first_child;
3020 while (*child && (*child)->offset < new_offset)
3021 child = &(*child)->next_sibling;
3023 access->next_sibling = *child;
3024 *child = access;
3026 return access;
3030 /* Beginning with ACCESS, traverse its whole access subtree and mark all
3031 sub-trees as written to. If any of them has not been marked so previously
3032 and has assignment links leading from it, re-enqueue it. */
3034 static void
3035 subtree_mark_written_and_rhs_enqueue (struct access *access)
3037 if (access->grp_write)
3038 return;
3039 access->grp_write = true;
3040 add_access_to_rhs_work_queue (access);
3042 struct access *child;
3043 for (child = access->first_child; child; child = child->next_sibling)
3044 subtree_mark_written_and_rhs_enqueue (child);
3047 /* If there is still budget to create a propagation access for DECL, return
3048 true and decrement the budget. Otherwise return false. */
3050 static bool
3051 budget_for_propagation_access (tree decl)
3053 unsigned b, *p = propagation_budget->get (decl);
3054 if (p)
3055 b = *p;
3056 else
3057 b = param_sra_max_propagations;
3059 if (b == 0)
3060 return false;
3061 b--;
3063 if (b == 0 && dump_file && (dump_flags & TDF_DETAILS))
3065 fprintf (dump_file, "The propagation budget of ");
3066 print_generic_expr (dump_file, decl);
3067 fprintf (dump_file, " (UID: %u) has been exhausted.\n", DECL_UID (decl));
3069 propagation_budget->put (decl, b);
3070 return true;
3073 /* Return true if ACC or any of its subaccesses has grp_child set. */
3075 static bool
3076 access_or_its_child_written (struct access *acc)
3078 if (acc->grp_write)
3079 return true;
3080 for (struct access *sub = acc->first_child; sub; sub = sub->next_sibling)
3081 if (access_or_its_child_written (sub))
3082 return true;
3083 return false;
3086 /* Propagate subaccesses and grp_write flags of RACC across an assignment link
3087 to LACC. Enqueue sub-accesses as necessary so that the write flag is
3088 propagated transitively. Return true if anything changed. Additionally, if
3089 RACC is a scalar access but LACC is not, change the type of the latter, if
3090 possible. */
3092 static bool
3093 propagate_subaccesses_from_rhs (struct access *lacc, struct access *racc)
3095 struct access *rchild;
3096 HOST_WIDE_INT norm_delta = lacc->offset - racc->offset;
3097 bool ret = false;
3099 /* IF the LHS is still not marked as being written to, we only need to do so
3100 if the RHS at this level actually was. */
3101 if (!lacc->grp_write)
3103 gcc_checking_assert (!comes_initialized_p (racc->base));
3104 if (racc->grp_write)
3106 subtree_mark_written_and_rhs_enqueue (lacc);
3107 ret = true;
3111 if (is_gimple_reg_type (lacc->type)
3112 || lacc->grp_unscalarizable_region
3113 || racc->grp_unscalarizable_region)
3115 if (!lacc->grp_write)
3117 ret = true;
3118 subtree_mark_written_and_rhs_enqueue (lacc);
3120 return ret;
3123 if (is_gimple_reg_type (racc->type))
3125 if (!lacc->grp_write)
3127 ret = true;
3128 subtree_mark_written_and_rhs_enqueue (lacc);
3130 if (!lacc->first_child && !racc->first_child)
3132 /* We are about to change the access type from aggregate to scalar,
3133 so we need to put the reverse flag onto the access, if any. */
3134 const bool reverse
3135 = TYPE_REVERSE_STORAGE_ORDER (lacc->type)
3136 && !POINTER_TYPE_P (racc->type)
3137 && !VECTOR_TYPE_P (racc->type);
3138 tree t = lacc->base;
3140 lacc->type = racc->type;
3141 if (build_user_friendly_ref_for_offset (&t, TREE_TYPE (t),
3142 lacc->offset, racc->type))
3144 lacc->expr = t;
3145 lacc->grp_same_access_path = true;
3147 else
3149 lacc->expr = build_ref_for_model (EXPR_LOCATION (lacc->base),
3150 lacc->base, lacc->offset,
3151 racc, NULL, false);
3152 if (TREE_CODE (lacc->expr) == MEM_REF)
3153 REF_REVERSE_STORAGE_ORDER (lacc->expr) = reverse;
3154 lacc->grp_no_warning = true;
3155 lacc->grp_same_access_path = false;
3157 lacc->reverse = reverse;
3159 return ret;
3162 for (rchild = racc->first_child; rchild; rchild = rchild->next_sibling)
3164 struct access *new_acc = NULL;
3165 HOST_WIDE_INT norm_offset = rchild->offset + norm_delta;
3167 if (child_would_conflict_in_acc (lacc, norm_offset, rchild->size,
3168 &new_acc))
3170 if (new_acc)
3172 if (!new_acc->grp_write && rchild->grp_write)
3174 gcc_assert (!lacc->grp_write);
3175 subtree_mark_written_and_rhs_enqueue (new_acc);
3176 ret = true;
3179 rchild->grp_hint = 1;
3180 new_acc->grp_hint |= new_acc->grp_read;
3181 if (rchild->first_child
3182 && propagate_subaccesses_from_rhs (new_acc, rchild))
3184 ret = 1;
3185 add_access_to_rhs_work_queue (new_acc);
3188 else
3190 if (!lacc->grp_write)
3192 ret = true;
3193 subtree_mark_written_and_rhs_enqueue (lacc);
3196 continue;
3199 if (rchild->grp_unscalarizable_region
3200 || !budget_for_propagation_access (lacc->base))
3202 if (!lacc->grp_write && access_or_its_child_written (rchild))
3204 ret = true;
3205 subtree_mark_written_and_rhs_enqueue (lacc);
3207 continue;
3210 rchild->grp_hint = 1;
3211 /* Because get_ref_base_and_extent always includes padding in size for
3212 accesses to DECLs but not necessarily for COMPONENT_REFs of the same
3213 type, we might be actually attempting to here to create a child of the
3214 same type as the parent. */
3215 if (!types_compatible_p (lacc->type, rchild->type))
3216 new_acc = create_artificial_child_access (lacc, rchild, norm_offset,
3217 false,
3218 (lacc->grp_write
3219 || rchild->grp_write));
3220 else
3221 new_acc = lacc;
3222 gcc_checking_assert (new_acc);
3223 if (racc->first_child)
3224 propagate_subaccesses_from_rhs (new_acc, rchild);
3226 add_access_to_rhs_work_queue (lacc);
3227 ret = true;
3230 return ret;
3233 /* Propagate subaccesses of LACC across an assignment link to RACC if they
3234 should inhibit total scalarization of the corresponding area. No flags are
3235 being propagated in the process. Return true if anything changed. */
3237 static bool
3238 propagate_subaccesses_from_lhs (struct access *lacc, struct access *racc)
3240 if (is_gimple_reg_type (racc->type)
3241 || lacc->grp_unscalarizable_region
3242 || racc->grp_unscalarizable_region)
3243 return false;
3245 /* TODO: Do we want set some new racc flag to stop potential total
3246 scalarization if lacc is a scalar access (and none fo the two have
3247 children)? */
3249 bool ret = false;
3250 HOST_WIDE_INT norm_delta = racc->offset - lacc->offset;
3251 for (struct access *lchild = lacc->first_child;
3252 lchild;
3253 lchild = lchild->next_sibling)
3255 struct access *matching_acc = NULL;
3256 HOST_WIDE_INT norm_offset = lchild->offset + norm_delta;
3258 if (lchild->grp_unscalarizable_region
3259 || child_would_conflict_in_acc (racc, norm_offset, lchild->size,
3260 &matching_acc)
3261 || !budget_for_propagation_access (racc->base))
3263 if (matching_acc
3264 && propagate_subaccesses_from_lhs (lchild, matching_acc))
3265 add_access_to_lhs_work_queue (matching_acc);
3266 continue;
3269 /* Because get_ref_base_and_extent always includes padding in size for
3270 accesses to DECLs but not necessarily for COMPONENT_REFs of the same
3271 type, we might be actually attempting to here to create a child of the
3272 same type as the parent. */
3273 if (!types_compatible_p (racc->type, lchild->type))
3275 struct access *new_acc
3276 = create_artificial_child_access (racc, lchild, norm_offset,
3277 true, false);
3278 new_acc->grp_result_of_prop_from_lhs = 1;
3279 propagate_subaccesses_from_lhs (lchild, new_acc);
3281 else
3282 propagate_subaccesses_from_lhs (lchild, racc);
3283 ret = true;
3285 return ret;
3288 /* Propagate all subaccesses across assignment links. */
3290 static void
3291 propagate_all_subaccesses (void)
3293 propagation_budget = new hash_map<tree, unsigned>;
3294 while (rhs_work_queue_head)
3296 struct access *racc = pop_access_from_rhs_work_queue ();
3297 struct assign_link *link;
3299 if (racc->group_representative)
3300 racc= racc->group_representative;
3301 gcc_assert (racc->first_rhs_link);
3303 for (link = racc->first_rhs_link; link; link = link->next_rhs)
3305 struct access *lacc = link->lacc;
3307 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
3308 continue;
3309 lacc = lacc->group_representative;
3311 bool reque_parents = false;
3312 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (racc->base)))
3314 if (!lacc->grp_write)
3316 subtree_mark_written_and_rhs_enqueue (lacc);
3317 reque_parents = true;
3320 else if (propagate_subaccesses_from_rhs (lacc, racc))
3321 reque_parents = true;
3323 if (reque_parents)
3326 add_access_to_rhs_work_queue (lacc);
3327 lacc = lacc->parent;
3329 while (lacc);
3333 while (lhs_work_queue_head)
3335 struct access *lacc = pop_access_from_lhs_work_queue ();
3336 struct assign_link *link;
3338 if (lacc->group_representative)
3339 lacc = lacc->group_representative;
3340 gcc_assert (lacc->first_lhs_link);
3342 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
3343 continue;
3345 for (link = lacc->first_lhs_link; link; link = link->next_lhs)
3347 struct access *racc = link->racc;
3349 if (racc->group_representative)
3350 racc = racc->group_representative;
3351 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (racc->base)))
3352 continue;
3353 if (propagate_subaccesses_from_lhs (lacc, racc))
3354 add_access_to_lhs_work_queue (racc);
3357 delete propagation_budget;
3360 /* Return true if the forest beginning with ROOT does not contain
3361 unscalarizable regions or non-byte aligned accesses. */
3363 static bool
3364 can_totally_scalarize_forest_p (struct access *root)
3366 struct access *access = root;
3369 if (access->grp_unscalarizable_region
3370 || (access->offset % BITS_PER_UNIT) != 0
3371 || (access->size % BITS_PER_UNIT) != 0
3372 || (is_gimple_reg_type (access->type)
3373 && access->first_child))
3374 return false;
3376 if (access->first_child)
3377 access = access->first_child;
3378 else if (access->next_sibling)
3379 access = access->next_sibling;
3380 else
3382 while (access->parent && !access->next_sibling)
3383 access = access->parent;
3384 if (access->next_sibling)
3385 access = access->next_sibling;
3386 else
3388 gcc_assert (access == root);
3389 root = root->next_grp;
3390 access = root;
3394 while (access);
3395 return true;
3398 /* Create and return an ACCESS in PARENT spanning from POS with SIZE, TYPE and
3399 reference EXPR for total scalarization purposes and mark it as such. Within
3400 the children of PARENT, link it in between PTR and NEXT_SIBLING. */
3402 static struct access *
3403 create_total_scalarization_access (struct access *parent, HOST_WIDE_INT pos,
3404 HOST_WIDE_INT size, tree type, tree expr,
3405 struct access **ptr,
3406 struct access *next_sibling)
3408 struct access *access = access_pool.allocate ();
3409 memset (access, 0, sizeof (struct access));
3410 access->base = parent->base;
3411 access->offset = pos;
3412 access->size = size;
3413 access->expr = expr;
3414 access->type = type;
3415 access->parent = parent;
3416 access->grp_write = parent->grp_write;
3417 access->grp_total_scalarization = 1;
3418 access->grp_hint = 1;
3419 access->grp_same_access_path = path_comparable_for_same_access (expr);
3420 access->reverse = reverse_storage_order_for_component_p (expr);
3422 access->next_sibling = next_sibling;
3423 *ptr = access;
3424 return access;
3427 /* Create and return an ACCESS in PARENT spanning from POS with SIZE, TYPE and
3428 reference EXPR for total scalarization purposes and mark it as such, link it
3429 at *PTR and reshape the tree so that those elements at *PTR and their
3430 siblings which fall within the part described by POS and SIZE are moved to
3431 be children of the new access. If a partial overlap is detected, return
3432 NULL. */
3434 static struct access *
3435 create_total_access_and_reshape (struct access *parent, HOST_WIDE_INT pos,
3436 HOST_WIDE_INT size, tree type, tree expr,
3437 struct access **ptr)
3439 struct access **p = ptr;
3441 while (*p && (*p)->offset < pos + size)
3443 if ((*p)->offset + (*p)->size > pos + size)
3444 return NULL;
3445 p = &(*p)->next_sibling;
3448 struct access *next_child = *ptr;
3449 struct access *new_acc
3450 = create_total_scalarization_access (parent, pos, size, type, expr,
3451 ptr, *p);
3452 if (p != ptr)
3454 new_acc->first_child = next_child;
3455 *p = NULL;
3456 for (struct access *a = next_child; a; a = a->next_sibling)
3457 a->parent = new_acc;
3459 return new_acc;
3462 static bool totally_scalarize_subtree (struct access *root);
3464 /* Return true if INNER is either the same type as OUTER or if it is the type
3465 of a record field in OUTER at offset zero, possibly in nested
3466 sub-records. */
3468 static bool
3469 access_and_field_type_match_p (tree outer, tree inner)
3471 if (TYPE_MAIN_VARIANT (outer) == TYPE_MAIN_VARIANT (inner))
3472 return true;
3473 if (TREE_CODE (outer) != RECORD_TYPE)
3474 return false;
3475 tree fld = TYPE_FIELDS (outer);
3476 while (fld)
3478 if (TREE_CODE (fld) == FIELD_DECL)
3480 if (!zerop (DECL_FIELD_OFFSET (fld)))
3481 return false;
3482 if (TYPE_MAIN_VARIANT (TREE_TYPE (fld)) == inner)
3483 return true;
3484 if (TREE_CODE (TREE_TYPE (fld)) == RECORD_TYPE)
3485 fld = TYPE_FIELDS (TREE_TYPE (fld));
3486 else
3487 return false;
3489 else
3490 fld = DECL_CHAIN (fld);
3492 return false;
3495 /* Return type of total_should_skip_creating_access indicating whether a total
3496 scalarization access for a field/element should be created, whether it
3497 already exists or whether the entire total scalarization has to fail. */
3499 enum total_sra_field_state {TOTAL_FLD_CREATE, TOTAL_FLD_DONE, TOTAL_FLD_FAILED};
3501 /* Do all the necessary steps in total scalarization when the given aggregate
3502 type has a TYPE at POS with the given SIZE should be put into PARENT and
3503 when we have processed all its siblings with smaller offsets up until and
3504 including LAST_SEEN_SIBLING (which can be NULL).
3506 If some further siblings are to be skipped, set *LAST_SEEN_SIBLING as
3507 appropriate. Return TOTAL_FLD_CREATE id the caller should carry on with
3508 creating a new access, TOTAL_FLD_DONE if access or accesses capable of
3509 representing the described part of the aggregate for the purposes of total
3510 scalarization already exist or TOTAL_FLD_FAILED if there is a problem which
3511 prevents total scalarization from happening at all. */
3513 static enum total_sra_field_state
3514 total_should_skip_creating_access (struct access *parent,
3515 struct access **last_seen_sibling,
3516 tree type, HOST_WIDE_INT pos,
3517 HOST_WIDE_INT size)
3519 struct access *next_child;
3520 if (!*last_seen_sibling)
3521 next_child = parent->first_child;
3522 else
3523 next_child = (*last_seen_sibling)->next_sibling;
3525 /* First, traverse the chain of siblings until it points to an access with
3526 offset at least equal to POS. Check all skipped accesses whether they
3527 span the POS boundary and if so, return with a failure. */
3528 while (next_child && next_child->offset < pos)
3530 if (next_child->offset + next_child->size > pos)
3531 return TOTAL_FLD_FAILED;
3532 *last_seen_sibling = next_child;
3533 next_child = next_child->next_sibling;
3536 /* Now check whether next_child has exactly the right POS and SIZE and if so,
3537 whether it can represent what we need and can be totally scalarized
3538 itself. */
3539 if (next_child && next_child->offset == pos
3540 && next_child->size == size)
3542 if (!is_gimple_reg_type (next_child->type)
3543 && (!access_and_field_type_match_p (type, next_child->type)
3544 || !totally_scalarize_subtree (next_child)))
3545 return TOTAL_FLD_FAILED;
3547 *last_seen_sibling = next_child;
3548 return TOTAL_FLD_DONE;
3551 /* If the child we're looking at would partially overlap, we just cannot
3552 totally scalarize. */
3553 if (next_child
3554 && next_child->offset < pos + size
3555 && next_child->offset + next_child->size > pos + size)
3556 return TOTAL_FLD_FAILED;
3558 if (is_gimple_reg_type (type))
3560 /* We don't scalarize accesses that are children of other scalar type
3561 accesses, so if we go on and create an access for a register type,
3562 there should not be any pre-existing children. There are rare cases
3563 where the requested type is a vector but we already have register
3564 accesses for all its elements which is equally good. Detect that
3565 situation or whether we need to bail out. */
3567 HOST_WIDE_INT covered = pos;
3568 bool skipping = false;
3569 while (next_child
3570 && next_child->offset + next_child->size <= pos + size)
3572 if (next_child->offset != covered
3573 || !is_gimple_reg_type (next_child->type))
3574 return TOTAL_FLD_FAILED;
3576 covered += next_child->size;
3577 *last_seen_sibling = next_child;
3578 next_child = next_child->next_sibling;
3579 skipping = true;
3582 if (skipping)
3584 if (covered != pos + size)
3585 return TOTAL_FLD_FAILED;
3586 else
3587 return TOTAL_FLD_DONE;
3591 return TOTAL_FLD_CREATE;
3594 /* Go over sub-tree rooted in ROOT and attempt to create scalar accesses
3595 spanning all uncovered areas covered by ROOT, return false if the attempt
3596 failed. All created accesses will have grp_unscalarizable_region set (and
3597 should be ignored if the function returns false). */
3599 static bool
3600 totally_scalarize_subtree (struct access *root)
3602 gcc_checking_assert (!root->grp_unscalarizable_region);
3603 gcc_checking_assert (!is_gimple_reg_type (root->type));
3605 struct access *last_seen_sibling = NULL;
3607 switch (TREE_CODE (root->type))
3609 case RECORD_TYPE:
3610 for (tree fld = TYPE_FIELDS (root->type); fld; fld = DECL_CHAIN (fld))
3611 if (TREE_CODE (fld) == FIELD_DECL)
3613 tree ft = TREE_TYPE (fld);
3614 HOST_WIDE_INT fsize = tree_to_uhwi (DECL_SIZE (fld));
3615 if (!fsize)
3616 continue;
3618 HOST_WIDE_INT pos = root->offset + int_bit_position (fld);
3619 if (pos + fsize > root->offset + root->size)
3620 return false;
3621 enum total_sra_field_state
3622 state = total_should_skip_creating_access (root,
3623 &last_seen_sibling,
3624 ft, pos, fsize);
3625 switch (state)
3627 case TOTAL_FLD_FAILED:
3628 return false;
3629 case TOTAL_FLD_DONE:
3630 continue;
3631 case TOTAL_FLD_CREATE:
3632 break;
3633 default:
3634 gcc_unreachable ();
3637 struct access **p = (last_seen_sibling
3638 ? &last_seen_sibling->next_sibling
3639 : &root->first_child);
3640 tree nref = build3 (COMPONENT_REF, ft, root->expr, fld, NULL_TREE);
3641 struct access *new_child
3642 = create_total_access_and_reshape (root, pos, fsize, ft, nref, p);
3643 if (!new_child)
3644 return false;
3646 if (!is_gimple_reg_type (ft)
3647 && !totally_scalarize_subtree (new_child))
3648 return false;
3649 last_seen_sibling = new_child;
3651 break;
3652 case ARRAY_TYPE:
3654 tree elemtype = TREE_TYPE (root->type);
3655 HOST_WIDE_INT el_size;
3656 offset_int idx, max;
3657 if (!prepare_iteration_over_array_elts (root->type, &el_size,
3658 &idx, &max))
3659 break;
3661 for (HOST_WIDE_INT pos = root->offset;
3662 idx <= max;
3663 pos += el_size, ++idx)
3665 enum total_sra_field_state
3666 state = total_should_skip_creating_access (root,
3667 &last_seen_sibling,
3668 elemtype, pos,
3669 el_size);
3670 switch (state)
3672 case TOTAL_FLD_FAILED:
3673 return false;
3674 case TOTAL_FLD_DONE:
3675 continue;
3676 case TOTAL_FLD_CREATE:
3677 break;
3678 default:
3679 gcc_unreachable ();
3682 struct access **p = (last_seen_sibling
3683 ? &last_seen_sibling->next_sibling
3684 : &root->first_child);
3685 tree nref = build4 (ARRAY_REF, elemtype, root->expr,
3686 wide_int_to_tree (TYPE_DOMAIN (root->type),
3687 idx),
3688 NULL_TREE, NULL_TREE);
3689 struct access *new_child
3690 = create_total_access_and_reshape (root, pos, el_size, elemtype,
3691 nref, p);
3692 if (!new_child)
3693 return false;
3695 if (!is_gimple_reg_type (elemtype)
3696 && !totally_scalarize_subtree (new_child))
3697 return false;
3698 last_seen_sibling = new_child;
3701 break;
3702 default:
3703 gcc_unreachable ();
3705 return true;
3708 /* Get the total total scalarization size limit in the current function. */
3710 unsigned HOST_WIDE_INT
3711 sra_get_max_scalarization_size (void)
3713 bool optimize_speed_p = !optimize_function_for_size_p (cfun);
3714 /* If the user didn't set PARAM_SRA_MAX_SCALARIZATION_SIZE_<...>,
3715 fall back to a target default. */
3716 unsigned HOST_WIDE_INT max_scalarization_size
3717 = get_move_ratio (optimize_speed_p) * UNITS_PER_WORD;
3719 if (optimize_speed_p)
3721 if (OPTION_SET_P (param_sra_max_scalarization_size_speed))
3722 max_scalarization_size = param_sra_max_scalarization_size_speed;
3724 else
3726 if (OPTION_SET_P (param_sra_max_scalarization_size_size))
3727 max_scalarization_size = param_sra_max_scalarization_size_size;
3729 max_scalarization_size *= BITS_PER_UNIT;
3730 return max_scalarization_size;
3733 /* Go through all accesses collected throughout the (intraprocedural) analysis
3734 stage, exclude overlapping ones, identify representatives and build trees
3735 out of them, making decisions about scalarization on the way. Return true
3736 iff there are any to-be-scalarized variables after this stage. */
3738 static bool
3739 analyze_all_variable_accesses (void)
3741 int res = 0;
3742 bitmap tmp = BITMAP_ALLOC (NULL);
3743 bitmap_iterator bi;
3744 unsigned i;
3746 bitmap_copy (tmp, candidate_bitmap);
3747 EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
3749 tree var = candidate (i);
3750 struct access *access;
3752 access = sort_and_splice_var_accesses (var);
3753 if (!access || !build_access_trees (access))
3754 disqualify_candidate (var,
3755 "No or inhibitingly overlapping accesses.");
3758 propagate_all_subaccesses ();
3760 unsigned HOST_WIDE_INT max_scalarization_size
3761 = sra_get_max_scalarization_size ();
3762 EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
3763 if (bitmap_bit_p (should_scalarize_away_bitmap, i)
3764 && !bitmap_bit_p (cannot_scalarize_away_bitmap, i))
3766 tree var = candidate (i);
3767 if (!VAR_P (var))
3768 continue;
3770 if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (var))) > max_scalarization_size)
3772 if (dump_file && (dump_flags & TDF_DETAILS))
3774 fprintf (dump_file, "Too big to totally scalarize: ");
3775 print_generic_expr (dump_file, var);
3776 fprintf (dump_file, " (UID: %u)\n", DECL_UID (var));
3778 continue;
3781 bool all_types_ok = true;
3782 for (struct access *access = get_first_repr_for_decl (var);
3783 access;
3784 access = access->next_grp)
3785 if (!can_totally_scalarize_forest_p (access)
3786 || !totally_scalarizable_type_p (access->type,
3787 constant_decl_p (var),
3788 0, nullptr))
3790 all_types_ok = false;
3791 break;
3793 if (!all_types_ok)
3794 continue;
3796 if (dump_file && (dump_flags & TDF_DETAILS))
3798 fprintf (dump_file, "Will attempt to totally scalarize ");
3799 print_generic_expr (dump_file, var);
3800 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
3802 bool scalarized = true;
3803 for (struct access *access = get_first_repr_for_decl (var);
3804 access;
3805 access = access->next_grp)
3806 if (!is_gimple_reg_type (access->type)
3807 && !totally_scalarize_subtree (access))
3809 scalarized = false;
3810 break;
3813 if (scalarized)
3814 for (struct access *access = get_first_repr_for_decl (var);
3815 access;
3816 access = access->next_grp)
3817 access->grp_total_scalarization = true;
3820 if (flag_checking)
3821 verify_all_sra_access_forests ();
3823 bitmap_copy (tmp, candidate_bitmap);
3824 EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
3826 tree var = candidate (i);
3827 struct access *access = get_first_repr_for_decl (var);
3829 if (analyze_access_trees (access))
3831 res++;
3832 if (dump_file && (dump_flags & TDF_DETAILS))
3834 fprintf (dump_file, "\nAccess trees for ");
3835 print_generic_expr (dump_file, var);
3836 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
3837 dump_access_tree (dump_file, access);
3838 fprintf (dump_file, "\n");
3841 else
3842 disqualify_candidate (var, "No scalar replacements to be created.");
3845 BITMAP_FREE (tmp);
3847 if (res)
3849 statistics_counter_event (cfun, "Scalarized aggregates", res);
3850 return true;
3852 else
3853 return false;
3856 /* Generate statements copying scalar replacements of accesses within a subtree
3857 into or out of AGG. ACCESS, all its children, siblings and their children
3858 are to be processed. AGG is an aggregate type expression (can be a
3859 declaration but does not have to be, it can for example also be a mem_ref or
3860 a series of handled components). TOP_OFFSET is the offset of the processed
3861 subtree which has to be subtracted from offsets of individual accesses to
3862 get corresponding offsets for AGG. If CHUNK_SIZE is non-null, copy only
3863 replacements in the interval <start_offset, start_offset + chunk_size>,
3864 otherwise copy all. GSI is a statement iterator used to place the new
3865 statements. WRITE should be true when the statements should write from AGG
3866 to the replacement and false if vice versa. if INSERT_AFTER is true, new
3867 statements will be added after the current statement in GSI, they will be
3868 added before the statement otherwise. */
3870 static void
3871 generate_subtree_copies (struct access *access, tree agg,
3872 HOST_WIDE_INT top_offset,
3873 HOST_WIDE_INT start_offset, HOST_WIDE_INT chunk_size,
3874 gimple_stmt_iterator *gsi, bool write,
3875 bool insert_after, location_t loc)
3877 /* Never write anything into constant pool decls. See PR70602. */
3878 if (!write && constant_decl_p (agg))
3879 return;
3882 if (chunk_size && access->offset >= start_offset + chunk_size)
3883 return;
3885 if (access->grp_to_be_replaced
3886 && (chunk_size == 0
3887 || access->offset + access->size > start_offset))
3889 tree expr, repl = get_access_replacement (access);
3890 gassign *stmt;
3892 expr = build_ref_for_model (loc, agg, access->offset - top_offset,
3893 access, gsi, insert_after);
3895 if (write)
3897 if (access->grp_partial_lhs)
3898 expr = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
3899 !insert_after,
3900 insert_after ? GSI_NEW_STMT
3901 : GSI_SAME_STMT);
3902 stmt = gimple_build_assign (repl, expr);
3904 else
3906 suppress_warning (repl /* Be more selective! */);
3907 if (access->grp_partial_lhs)
3908 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
3909 !insert_after,
3910 insert_after ? GSI_NEW_STMT
3911 : GSI_SAME_STMT);
3912 stmt = gimple_build_assign (expr, repl);
3914 gimple_set_location (stmt, loc);
3916 if (insert_after)
3917 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
3918 else
3919 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3920 update_stmt (stmt);
3921 sra_stats.subtree_copies++;
3923 else if (write
3924 && access->grp_to_be_debug_replaced
3925 && (chunk_size == 0
3926 || access->offset + access->size > start_offset))
3928 gdebug *ds;
3929 tree drhs = build_debug_ref_for_model (loc, agg,
3930 access->offset - top_offset,
3931 access);
3932 ds = gimple_build_debug_bind (get_access_replacement (access),
3933 drhs, gsi_stmt (*gsi));
3934 if (insert_after)
3935 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
3936 else
3937 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
3940 if (access->first_child)
3941 generate_subtree_copies (access->first_child, agg, top_offset,
3942 start_offset, chunk_size, gsi,
3943 write, insert_after, loc);
3945 access = access->next_sibling;
3947 while (access);
3950 /* Assign zero to all scalar replacements in an access subtree. ACCESS is the
3951 root of the subtree to be processed. GSI is the statement iterator used
3952 for inserting statements which are added after the current statement if
3953 INSERT_AFTER is true or before it otherwise. */
3955 static void
3956 init_subtree_with_zero (struct access *access, gimple_stmt_iterator *gsi,
3957 bool insert_after, location_t loc)
3960 struct access *child;
3962 if (access->grp_to_be_replaced)
3964 gassign *stmt;
3966 stmt = gimple_build_assign (get_access_replacement (access),
3967 build_zero_cst (access->type));
3968 if (insert_after)
3969 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
3970 else
3971 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3972 update_stmt (stmt);
3973 gimple_set_location (stmt, loc);
3975 else if (access->grp_to_be_debug_replaced)
3977 gdebug *ds
3978 = gimple_build_debug_bind (get_access_replacement (access),
3979 build_zero_cst (access->type),
3980 gsi_stmt (*gsi));
3981 if (insert_after)
3982 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
3983 else
3984 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
3987 for (child = access->first_child; child; child = child->next_sibling)
3988 init_subtree_with_zero (child, gsi, insert_after, loc);
3991 /* Clobber all scalar replacements in an access subtree. ACCESS is the
3992 root of the subtree to be processed. GSI is the statement iterator used
3993 for inserting statements which are added after the current statement if
3994 INSERT_AFTER is true or before it otherwise. */
3996 static void
3997 clobber_subtree (struct access *access, gimple_stmt_iterator *gsi,
3998 bool insert_after, location_t loc)
4001 struct access *child;
4003 if (access->grp_to_be_replaced)
4005 tree rep = get_access_replacement (access);
4006 tree clobber = build_clobber (access->type);
4007 gimple *stmt = gimple_build_assign (rep, clobber);
4009 if (insert_after)
4010 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
4011 else
4012 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
4013 update_stmt (stmt);
4014 gimple_set_location (stmt, loc);
4017 for (child = access->first_child; child; child = child->next_sibling)
4018 clobber_subtree (child, gsi, insert_after, loc);
4021 /* Search for an access representative for the given expression EXPR and
4022 return it or NULL if it cannot be found. */
4024 static struct access *
4025 get_access_for_expr (tree expr)
4027 poly_int64 poffset, psize, pmax_size;
4028 HOST_WIDE_INT offset, max_size;
4029 tree base;
4030 bool reverse;
4032 /* FIXME: This should not be necessary but Ada produces V_C_Es with a type of
4033 a different size than the size of its argument and we need the latter
4034 one. */
4035 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
4036 expr = TREE_OPERAND (expr, 0);
4038 base = get_ref_base_and_extent (expr, &poffset, &psize, &pmax_size,
4039 &reverse);
4040 if (!known_size_p (pmax_size)
4041 || !pmax_size.is_constant (&max_size)
4042 || !poffset.is_constant (&offset)
4043 || !DECL_P (base))
4044 return NULL;
4046 if (tree basesize = DECL_SIZE (base))
4048 poly_int64 sz;
4049 if (offset < 0
4050 || !poly_int_tree_p (basesize, &sz)
4051 || known_le (sz, offset))
4052 return NULL;
4055 if (max_size == 0
4056 || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
4057 return NULL;
4059 return get_var_base_offset_size_access (base, offset, max_size);
4062 /* Replace the expression EXPR with a scalar replacement if there is one and
4063 generate other statements to do type conversion or subtree copying if
4064 necessary. WRITE is true if the expression is being written to (it is on a
4065 LHS of a statement or output in an assembly statement). STMT_GSI is used to
4066 place newly created statements before the processed statement, REFRESH_GSI
4067 is used to place them afterwards - unless the processed statement must end a
4068 BB in which case it is placed on the outgoing non-EH edge. REFRESH_GSI and
4069 is then used to continue iteration over the BB. If sra_modify_expr is
4070 called only once with WRITE equal to true on a given statement, both
4071 iterator parameters can point to the same one. */
4073 static bool
4074 sra_modify_expr (tree *expr, bool write, gimple_stmt_iterator *stmt_gsi,
4075 gimple_stmt_iterator *refresh_gsi)
4077 location_t loc;
4078 struct access *access;
4079 tree type, bfr, orig_expr;
4080 bool partial_cplx_access = false;
4082 if (TREE_CODE (*expr) == BIT_FIELD_REF
4083 && (write || !sra_handled_bf_read_p (*expr)))
4085 bfr = *expr;
4086 expr = &TREE_OPERAND (*expr, 0);
4088 else
4089 bfr = NULL_TREE;
4091 if (TREE_CODE (*expr) == REALPART_EXPR || TREE_CODE (*expr) == IMAGPART_EXPR)
4093 expr = &TREE_OPERAND (*expr, 0);
4094 partial_cplx_access = true;
4096 access = get_access_for_expr (*expr);
4097 if (!access)
4098 return false;
4099 type = TREE_TYPE (*expr);
4100 orig_expr = *expr;
4102 loc = gimple_location (gsi_stmt (*stmt_gsi));
4103 gimple_stmt_iterator alt_gsi = gsi_none ();
4104 if (write && stmt_ends_bb_p (gsi_stmt (*stmt_gsi)))
4106 alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*stmt_gsi)));
4107 refresh_gsi = &alt_gsi;
4110 if (access->grp_to_be_replaced)
4112 tree repl = get_access_replacement (access);
4113 /* If we replace a non-register typed access simply use the original
4114 access expression to extract the scalar component afterwards.
4115 This happens if scalarizing a function return value or parameter
4116 like in gcc.c-torture/execute/20041124-1.c, 20050316-1.c and
4117 gcc.c-torture/compile/20011217-1.c.
4119 We also want to use this when accessing a complex or vector which can
4120 be accessed as a different type too, potentially creating a need for
4121 type conversion (see PR42196) and when scalarized unions are involved
4122 in assembler statements (see PR42398). */
4123 if (!bfr && !useless_type_conversion_p (type, access->type))
4125 tree ref;
4127 ref = build_ref_for_model (loc, orig_expr, 0, access, stmt_gsi,
4128 false);
4130 if (partial_cplx_access)
4132 /* VIEW_CONVERT_EXPRs in partial complex access are always fine in
4133 the case of a write because in such case the replacement cannot
4134 be a gimple register. In the case of a load, we have to
4135 differentiate in between a register an non-register
4136 replacement. */
4137 tree t = build1 (VIEW_CONVERT_EXPR, type, repl);
4138 gcc_checking_assert (!write || access->grp_partial_lhs);
4139 if (!access->grp_partial_lhs)
4141 tree tmp = make_ssa_name (type);
4142 gassign *stmt = gimple_build_assign (tmp, t);
4143 /* This is always a read. */
4144 gsi_insert_before (stmt_gsi, stmt, GSI_SAME_STMT);
4145 t = tmp;
4147 *expr = t;
4149 else if (write)
4151 gassign *stmt;
4153 if (access->grp_partial_lhs)
4154 ref = force_gimple_operand_gsi (refresh_gsi, ref, true,
4155 NULL_TREE, false, GSI_NEW_STMT);
4156 stmt = gimple_build_assign (repl, ref);
4157 gimple_set_location (stmt, loc);
4158 gsi_insert_after (refresh_gsi, stmt, GSI_NEW_STMT);
4160 else
4162 gassign *stmt;
4164 if (access->grp_partial_lhs)
4165 repl = force_gimple_operand_gsi (stmt_gsi, repl, true,
4166 NULL_TREE, true,
4167 GSI_SAME_STMT);
4168 stmt = gimple_build_assign (ref, repl);
4169 gimple_set_location (stmt, loc);
4170 gsi_insert_before (stmt_gsi, stmt, GSI_SAME_STMT);
4173 else
4175 /* If we are going to replace a scalar field in a structure with
4176 reverse storage order by a stand-alone scalar, we are going to
4177 effectively byte-swap the scalar and we also need to byte-swap
4178 the portion of it represented by the bit-field. */
4179 if (bfr && REF_REVERSE_STORAGE_ORDER (bfr))
4181 REF_REVERSE_STORAGE_ORDER (bfr) = 0;
4182 TREE_OPERAND (bfr, 2)
4183 = size_binop (MINUS_EXPR, TYPE_SIZE (TREE_TYPE (repl)),
4184 size_binop (PLUS_EXPR, TREE_OPERAND (bfr, 1),
4185 TREE_OPERAND (bfr, 2)));
4188 *expr = repl;
4191 sra_stats.exprs++;
4193 else if (write && access->grp_to_be_debug_replaced)
4195 gdebug *ds = gimple_build_debug_bind (get_access_replacement (access),
4196 NULL_TREE,
4197 gsi_stmt (*stmt_gsi));
4198 gsi_insert_after (stmt_gsi, ds, GSI_NEW_STMT);
4201 if (access->first_child && !TREE_READONLY (access->base))
4203 HOST_WIDE_INT start_offset, chunk_size;
4204 if (bfr
4205 && tree_fits_uhwi_p (TREE_OPERAND (bfr, 1))
4206 && tree_fits_uhwi_p (TREE_OPERAND (bfr, 2)))
4208 chunk_size = tree_to_uhwi (TREE_OPERAND (bfr, 1));
4209 start_offset = access->offset
4210 + tree_to_uhwi (TREE_OPERAND (bfr, 2));
4212 else
4213 start_offset = chunk_size = 0;
4215 generate_subtree_copies (access->first_child, orig_expr, access->offset,
4216 start_offset, chunk_size,
4217 write ? refresh_gsi : stmt_gsi,
4218 write, write, loc);
4220 return true;
4223 /* If EXPR, which must be a call argument, is an ADDR_EXPR, generate writes and
4224 reads from its base before and after the call statement given in CALL_GSI
4225 and return true if any copying took place. Otherwise call sra_modify_expr
4226 on EXPR and return its value. FLAGS is what the gimple_call_arg_flags
4227 return for the given parameter. */
4229 static bool
4230 sra_modify_call_arg (tree *expr, gimple_stmt_iterator *call_gsi,
4231 gimple_stmt_iterator *refresh_gsi, int flags)
4233 if (TREE_CODE (*expr) != ADDR_EXPR)
4234 return sra_modify_expr (expr, false, call_gsi, refresh_gsi);
4236 if (flags & EAF_UNUSED)
4237 return false;
4239 tree base = get_base_address (TREE_OPERAND (*expr, 0));
4240 if (!DECL_P (base))
4241 return false;
4242 struct access *access = get_access_for_expr (base);
4243 if (!access)
4244 return false;
4246 gimple *stmt = gsi_stmt (*call_gsi);
4247 location_t loc = gimple_location (stmt);
4248 generate_subtree_copies (access, base, 0, 0, 0, call_gsi, false, false,
4249 loc);
4251 if (flags & EAF_NO_DIRECT_CLOBBER)
4252 return true;
4254 if (!stmt_ends_bb_p (stmt))
4255 generate_subtree_copies (access, base, 0, 0, 0, refresh_gsi, true,
4256 true, loc);
4257 else
4259 edge e;
4260 edge_iterator ei;
4261 FOR_EACH_EDGE (e, ei, gsi_bb (*call_gsi)->succs)
4263 gimple_stmt_iterator alt_gsi = gsi_start_edge (e);
4264 generate_subtree_copies (access, base, 0, 0, 0, &alt_gsi, true,
4265 true, loc);
4268 return true;
4271 /* Where scalar replacements of the RHS have been written to when a replacement
4272 of a LHS of an assigments cannot be direclty loaded from a replacement of
4273 the RHS. */
4274 enum unscalarized_data_handling { SRA_UDH_NONE, /* Nothing done so far. */
4275 SRA_UDH_RIGHT, /* Data flushed to the RHS. */
4276 SRA_UDH_LEFT }; /* Data flushed to the LHS. */
4278 struct subreplacement_assignment_data
4280 /* Offset of the access representing the lhs of the assignment. */
4281 HOST_WIDE_INT left_offset;
4283 /* LHS and RHS of the original assignment. */
4284 tree assignment_lhs, assignment_rhs;
4286 /* Access representing the rhs of the whole assignment. */
4287 struct access *top_racc;
4289 /* Stmt iterator used for statement insertions after the original assignment.
4290 It points to the main GSI used to traverse a BB during function body
4291 modification. */
4292 gimple_stmt_iterator *new_gsi;
4294 /* Stmt iterator used for statement insertions before the original
4295 assignment. Keeps on pointing to the original statement. */
4296 gimple_stmt_iterator old_gsi;
4298 /* Location of the assignment. */
4299 location_t loc;
4301 /* Keeps the information whether we have needed to refresh replacements of
4302 the LHS and from which side of the assignments this takes place. */
4303 enum unscalarized_data_handling refreshed;
4306 /* Store all replacements in the access tree rooted in TOP_RACC either to their
4307 base aggregate if there are unscalarized data or directly to LHS of the
4308 statement that is pointed to by GSI otherwise. */
4310 static void
4311 handle_unscalarized_data_in_subtree (struct subreplacement_assignment_data *sad)
4313 tree src;
4314 /* If the RHS is a load from a constant, we do not need to (and must not)
4315 flush replacements to it and can use it directly as if we did. */
4316 if (TREE_READONLY (sad->top_racc->base))
4318 sad->refreshed = SRA_UDH_RIGHT;
4319 return;
4321 if (sad->top_racc->grp_unscalarized_data)
4323 src = sad->assignment_rhs;
4324 sad->refreshed = SRA_UDH_RIGHT;
4326 else
4328 src = sad->assignment_lhs;
4329 sad->refreshed = SRA_UDH_LEFT;
4331 generate_subtree_copies (sad->top_racc->first_child, src,
4332 sad->top_racc->offset, 0, 0,
4333 &sad->old_gsi, false, false, sad->loc);
4336 /* Try to generate statements to load all sub-replacements in an access subtree
4337 formed by children of LACC from scalar replacements in the SAD->top_racc
4338 subtree. If that is not possible, refresh the SAD->top_racc base aggregate
4339 and load the accesses from it. */
4341 static void
4342 load_assign_lhs_subreplacements (struct access *lacc,
4343 struct subreplacement_assignment_data *sad)
4345 for (lacc = lacc->first_child; lacc; lacc = lacc->next_sibling)
4347 HOST_WIDE_INT offset;
4348 offset = lacc->offset - sad->left_offset + sad->top_racc->offset;
4350 if (lacc->grp_to_be_replaced)
4352 struct access *racc;
4353 gassign *stmt;
4354 tree rhs;
4356 racc = find_access_in_subtree (sad->top_racc, offset, lacc->size);
4357 if (racc && racc->grp_to_be_replaced)
4359 rhs = get_access_replacement (racc);
4360 bool vce = false;
4361 if (!useless_type_conversion_p (lacc->type, racc->type))
4363 rhs = fold_build1_loc (sad->loc, VIEW_CONVERT_EXPR,
4364 lacc->type, rhs);
4365 vce = true;
4368 if (lacc->grp_partial_lhs && (vce || racc->grp_partial_lhs))
4369 rhs = force_gimple_operand_gsi (&sad->old_gsi, rhs, true,
4370 NULL_TREE, true, GSI_SAME_STMT);
4372 else
4374 /* No suitable access on the right hand side, need to load from
4375 the aggregate. See if we have to update it first... */
4376 if (sad->refreshed == SRA_UDH_NONE)
4377 handle_unscalarized_data_in_subtree (sad);
4379 if (sad->refreshed == SRA_UDH_LEFT)
4380 rhs = build_ref_for_model (sad->loc, sad->assignment_lhs,
4381 lacc->offset - sad->left_offset,
4382 lacc, sad->new_gsi, true);
4383 else
4384 rhs = build_ref_for_model (sad->loc, sad->assignment_rhs,
4385 lacc->offset - sad->left_offset,
4386 lacc, sad->new_gsi, true);
4387 if (lacc->grp_partial_lhs)
4388 rhs = force_gimple_operand_gsi (sad->new_gsi,
4389 rhs, true, NULL_TREE,
4390 false, GSI_NEW_STMT);
4393 stmt = gimple_build_assign (get_access_replacement (lacc), rhs);
4394 gsi_insert_after (sad->new_gsi, stmt, GSI_NEW_STMT);
4395 gimple_set_location (stmt, sad->loc);
4396 update_stmt (stmt);
4397 sra_stats.subreplacements++;
4399 else
4401 if (sad->refreshed == SRA_UDH_NONE
4402 && lacc->grp_read && !lacc->grp_covered)
4403 handle_unscalarized_data_in_subtree (sad);
4405 if (lacc && lacc->grp_to_be_debug_replaced)
4407 gdebug *ds;
4408 tree drhs;
4409 struct access *racc = find_access_in_subtree (sad->top_racc,
4410 offset,
4411 lacc->size);
4413 if (racc && racc->grp_to_be_replaced)
4415 if (racc->grp_write || constant_decl_p (racc->base))
4416 drhs = get_access_replacement (racc);
4417 else
4418 drhs = NULL;
4420 else if (sad->refreshed == SRA_UDH_LEFT)
4421 drhs = build_debug_ref_for_model (sad->loc, lacc->base,
4422 lacc->offset, lacc);
4423 else if (sad->refreshed == SRA_UDH_RIGHT)
4424 drhs = build_debug_ref_for_model (sad->loc, sad->top_racc->base,
4425 offset, lacc);
4426 else
4427 drhs = NULL_TREE;
4428 if (drhs
4429 && !useless_type_conversion_p (lacc->type, TREE_TYPE (drhs)))
4430 drhs = fold_build1_loc (sad->loc, VIEW_CONVERT_EXPR,
4431 lacc->type, drhs);
4432 ds = gimple_build_debug_bind (get_access_replacement (lacc),
4433 drhs, gsi_stmt (sad->old_gsi));
4434 gsi_insert_after (sad->new_gsi, ds, GSI_NEW_STMT);
4438 if (lacc->first_child)
4439 load_assign_lhs_subreplacements (lacc, sad);
4443 /* Result code for SRA assignment modification. */
4444 enum assignment_mod_result { SRA_AM_NONE, /* nothing done for the stmt */
4445 SRA_AM_MODIFIED, /* stmt changed but not
4446 removed */
4447 SRA_AM_REMOVED }; /* stmt eliminated */
4449 /* Modify assignments with a CONSTRUCTOR on their RHS. STMT contains a pointer
4450 to the assignment and GSI is the statement iterator pointing at it. Returns
4451 the same values as sra_modify_assign. */
4453 static enum assignment_mod_result
4454 sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
4456 tree lhs = gimple_assign_lhs (stmt);
4457 struct access *acc = get_access_for_expr (lhs);
4458 if (!acc)
4459 return SRA_AM_NONE;
4460 location_t loc = gimple_location (stmt);
4462 if (gimple_clobber_p (stmt))
4464 /* Clobber the replacement variable. */
4465 clobber_subtree (acc, gsi, !acc->grp_covered, loc);
4466 /* Remove clobbers of fully scalarized variables, they are dead. */
4467 if (acc->grp_covered)
4469 unlink_stmt_vdef (stmt);
4470 gsi_remove (gsi, true);
4471 release_defs (stmt);
4472 return SRA_AM_REMOVED;
4474 else
4475 return SRA_AM_MODIFIED;
4478 if (CONSTRUCTOR_NELTS (gimple_assign_rhs1 (stmt)) > 0)
4480 /* I have never seen this code path trigger but if it can happen the
4481 following should handle it gracefully. */
4482 if (access_has_children_p (acc))
4483 generate_subtree_copies (acc->first_child, lhs, acc->offset, 0, 0, gsi,
4484 true, true, loc);
4485 return SRA_AM_MODIFIED;
4488 if (acc->grp_covered)
4490 init_subtree_with_zero (acc, gsi, false, loc);
4491 unlink_stmt_vdef (stmt);
4492 gsi_remove (gsi, true);
4493 release_defs (stmt);
4494 return SRA_AM_REMOVED;
4496 else
4498 init_subtree_with_zero (acc, gsi, true, loc);
4499 return SRA_AM_MODIFIED;
4503 /* Create and return a new suitable default definition SSA_NAME for RACC which
4504 is an access describing an uninitialized part of an aggregate that is being
4505 loaded. REG_TREE is used instead of the actual RACC type if that is not of
4506 a gimple register type. */
4508 static tree
4509 get_repl_default_def_ssa_name (struct access *racc, tree reg_type)
4511 gcc_checking_assert (!racc->grp_to_be_replaced
4512 && !racc->grp_to_be_debug_replaced);
4513 if (!racc->replacement_decl)
4514 racc->replacement_decl = create_access_replacement (racc, reg_type);
4515 return get_or_create_ssa_default_def (cfun, racc->replacement_decl);
4519 /* Generate statements to call .DEFERRED_INIT to initialize scalar replacements
4520 of accesses within a subtree ACCESS; all its children, siblings and their
4521 children are to be processed.
4522 GSI is a statement iterator used to place the new statements. */
4523 static void
4524 generate_subtree_deferred_init (struct access *access,
4525 tree init_type,
4526 tree decl_name,
4527 gimple_stmt_iterator *gsi,
4528 location_t loc)
4532 if (access->grp_to_be_replaced)
4534 tree repl = get_access_replacement (access);
4535 gimple *call
4536 = gimple_build_call_internal (IFN_DEFERRED_INIT, 3,
4537 TYPE_SIZE_UNIT (TREE_TYPE (repl)),
4538 init_type, decl_name);
4539 gimple_call_set_lhs (call, repl);
4540 gsi_insert_before (gsi, call, GSI_SAME_STMT);
4541 update_stmt (call);
4542 gimple_set_location (call, loc);
4543 sra_stats.subtree_deferred_init++;
4545 if (access->first_child)
4546 generate_subtree_deferred_init (access->first_child, init_type,
4547 decl_name, gsi, loc);
4549 access = access ->next_sibling;
4551 while (access);
4554 /* For a call to .DEFERRED_INIT:
4555 var = .DEFERRED_INIT (size_of_var, init_type, name_of_var);
4556 examine the LHS variable VAR and replace it with a scalar replacement if
4557 there is one, also replace the RHS call to a call to .DEFERRED_INIT of
4558 the corresponding scalar relacement variable. Examine the subtree and
4559 do the scalar replacements in the subtree too. STMT is the call, GSI is
4560 the statment iterator to place newly created statement. */
4562 static enum assignment_mod_result
4563 sra_modify_deferred_init (gimple *stmt, gimple_stmt_iterator *gsi)
4565 tree lhs = gimple_call_lhs (stmt);
4566 tree init_type = gimple_call_arg (stmt, 1);
4567 tree decl_name = gimple_call_arg (stmt, 2);
4569 struct access *lhs_access = get_access_for_expr (lhs);
4570 if (!lhs_access)
4571 return SRA_AM_NONE;
4573 location_t loc = gimple_location (stmt);
4575 if (lhs_access->grp_to_be_replaced)
4577 tree lhs_repl = get_access_replacement (lhs_access);
4578 gimple_call_set_lhs (stmt, lhs_repl);
4579 tree arg0_repl = TYPE_SIZE_UNIT (TREE_TYPE (lhs_repl));
4580 gimple_call_set_arg (stmt, 0, arg0_repl);
4581 sra_stats.deferred_init++;
4582 gcc_assert (!lhs_access->first_child);
4583 return SRA_AM_MODIFIED;
4586 if (lhs_access->first_child)
4587 generate_subtree_deferred_init (lhs_access->first_child,
4588 init_type, decl_name, gsi, loc);
4589 if (lhs_access->grp_covered)
4591 unlink_stmt_vdef (stmt);
4592 gsi_remove (gsi, true);
4593 release_defs (stmt);
4594 return SRA_AM_REMOVED;
4597 return SRA_AM_MODIFIED;
4600 /* Examine both sides of the assignment statement pointed to by STMT, replace
4601 them with a scalare replacement if there is one and generate copying of
4602 replacements if scalarized aggregates have been used in the assignment. GSI
4603 is used to hold generated statements for type conversions and subtree
4604 copying. */
4606 static enum assignment_mod_result
4607 sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi)
4609 struct access *lacc, *racc;
4610 tree lhs, rhs;
4611 bool modify_this_stmt = false;
4612 bool force_gimple_rhs = false;
4613 location_t loc;
4614 gimple_stmt_iterator orig_gsi = *gsi;
4616 if (!gimple_assign_single_p (stmt))
4617 return SRA_AM_NONE;
4618 lhs = gimple_assign_lhs (stmt);
4619 rhs = gimple_assign_rhs1 (stmt);
4621 if (TREE_CODE (rhs) == CONSTRUCTOR)
4622 return sra_modify_constructor_assign (stmt, gsi);
4624 if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (lhs) == REALPART_EXPR
4625 || TREE_CODE (rhs) == IMAGPART_EXPR || TREE_CODE (lhs) == IMAGPART_EXPR
4626 || (TREE_CODE (rhs) == BIT_FIELD_REF && !sra_handled_bf_read_p (rhs))
4627 || TREE_CODE (lhs) == BIT_FIELD_REF)
4629 modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (stmt),
4630 false, gsi, gsi);
4631 modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (stmt),
4632 true, gsi, gsi);
4633 return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
4636 lacc = get_access_for_expr (lhs);
4637 racc = get_access_for_expr (rhs);
4638 if (!lacc && !racc)
4639 return SRA_AM_NONE;
4640 /* Avoid modifying initializations of constant-pool replacements. */
4641 if (racc && (racc->replacement_decl == lhs))
4642 return SRA_AM_NONE;
4644 loc = gimple_location (stmt);
4645 if (lacc && lacc->grp_to_be_replaced)
4647 lhs = get_access_replacement (lacc);
4648 gimple_assign_set_lhs (stmt, lhs);
4649 modify_this_stmt = true;
4650 if (lacc->grp_partial_lhs)
4651 force_gimple_rhs = true;
4652 sra_stats.exprs++;
4655 if (racc && racc->grp_to_be_replaced)
4657 rhs = get_access_replacement (racc);
4658 modify_this_stmt = true;
4659 if (racc->grp_partial_lhs)
4660 force_gimple_rhs = true;
4661 sra_stats.exprs++;
4663 else if (racc
4664 && !racc->grp_unscalarized_data
4665 && !racc->grp_unscalarizable_region
4666 && TREE_CODE (lhs) == SSA_NAME
4667 && !access_has_replacements_p (racc))
4669 rhs = get_repl_default_def_ssa_name (racc, TREE_TYPE (lhs));
4670 modify_this_stmt = true;
4671 sra_stats.exprs++;
4674 if (modify_this_stmt
4675 && !useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
4677 /* If we can avoid creating a VIEW_CONVERT_EXPR, then do so.
4678 ??? This should move to fold_stmt which we simply should
4679 call after building a VIEW_CONVERT_EXPR here. */
4680 if (AGGREGATE_TYPE_P (TREE_TYPE (lhs))
4681 && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (lhs)) == racc->reverse
4682 && !contains_bitfld_component_ref_p (lhs))
4684 lhs = build_ref_for_model (loc, lhs, 0, racc, gsi, false);
4685 gimple_assign_set_lhs (stmt, lhs);
4687 else if (lacc
4688 && AGGREGATE_TYPE_P (TREE_TYPE (rhs))
4689 && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (rhs)) == lacc->reverse
4690 && !contains_vce_or_bfcref_p (rhs))
4691 rhs = build_ref_for_model (loc, rhs, 0, lacc, gsi, false);
4693 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
4695 rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), rhs);
4696 if (is_gimple_reg_type (TREE_TYPE (lhs))
4697 && TREE_CODE (lhs) != SSA_NAME)
4698 force_gimple_rhs = true;
4702 if (lacc && lacc->grp_to_be_debug_replaced)
4704 tree dlhs = get_access_replacement (lacc);
4705 tree drhs = unshare_expr (rhs);
4706 if (!useless_type_conversion_p (TREE_TYPE (dlhs), TREE_TYPE (drhs)))
4708 if (AGGREGATE_TYPE_P (TREE_TYPE (drhs))
4709 && !contains_vce_or_bfcref_p (drhs))
4710 drhs = build_debug_ref_for_model (loc, drhs, 0, lacc);
4711 if (drhs
4712 && !useless_type_conversion_p (TREE_TYPE (dlhs),
4713 TREE_TYPE (drhs)))
4714 drhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
4715 TREE_TYPE (dlhs), drhs);
4717 gdebug *ds = gimple_build_debug_bind (dlhs, drhs, stmt);
4718 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
4721 /* From this point on, the function deals with assignments in between
4722 aggregates when at least one has scalar reductions of some of its
4723 components. There are three possible scenarios: Both the LHS and RHS have
4724 to-be-scalarized components, 2) only the RHS has or 3) only the LHS has.
4726 In the first case, we would like to load the LHS components from RHS
4727 components whenever possible. If that is not possible, we would like to
4728 read it directly from the RHS (after updating it by storing in it its own
4729 components). If there are some necessary unscalarized data in the LHS,
4730 those will be loaded by the original assignment too. If neither of these
4731 cases happen, the original statement can be removed. Most of this is done
4732 by load_assign_lhs_subreplacements.
4734 In the second case, we would like to store all RHS scalarized components
4735 directly into LHS and if they cover the aggregate completely, remove the
4736 statement too. In the third case, we want the LHS components to be loaded
4737 directly from the RHS (DSE will remove the original statement if it
4738 becomes redundant).
4740 This is a bit complex but manageable when types match and when unions do
4741 not cause confusion in a way that we cannot really load a component of LHS
4742 from the RHS or vice versa (the access representing this level can have
4743 subaccesses that are accessible only through a different union field at a
4744 higher level - different from the one used in the examined expression).
4745 Unions are fun.
4747 Therefore, I specially handle a fourth case, happening when there is a
4748 specific type cast or it is impossible to locate a scalarized subaccess on
4749 the other side of the expression. If that happens, I simply "refresh" the
4750 RHS by storing in it is scalarized components leave the original statement
4751 there to do the copying and then load the scalar replacements of the LHS.
4752 This is what the first branch does. */
4754 if (modify_this_stmt
4755 || gimple_has_volatile_ops (stmt)
4756 || contains_vce_or_bfcref_p (rhs)
4757 || contains_vce_or_bfcref_p (lhs)
4758 || stmt_ends_bb_p (stmt))
4760 /* No need to copy into a constant, it comes pre-initialized. */
4761 if (access_has_children_p (racc) && !TREE_READONLY (racc->base))
4762 generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0,
4763 gsi, false, false, loc);
4764 if (access_has_children_p (lacc))
4766 gimple_stmt_iterator alt_gsi = gsi_none ();
4767 if (stmt_ends_bb_p (stmt))
4769 alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi)));
4770 gsi = &alt_gsi;
4772 generate_subtree_copies (lacc->first_child, lhs, lacc->offset, 0, 0,
4773 gsi, true, true, loc);
4775 sra_stats.separate_lhs_rhs_handling++;
4777 /* This gimplification must be done after generate_subtree_copies,
4778 lest we insert the subtree copies in the middle of the gimplified
4779 sequence. */
4780 if (force_gimple_rhs)
4781 rhs = force_gimple_operand_gsi (&orig_gsi, rhs, true, NULL_TREE,
4782 true, GSI_SAME_STMT);
4783 if (gimple_assign_rhs1 (stmt) != rhs)
4785 modify_this_stmt = true;
4786 gimple_assign_set_rhs_from_tree (&orig_gsi, rhs);
4787 gcc_assert (stmt == gsi_stmt (orig_gsi));
4790 return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
4792 else
4794 if (access_has_children_p (lacc)
4795 && access_has_children_p (racc)
4796 /* When an access represents an unscalarizable region, it usually
4797 represents accesses with variable offset and thus must not be used
4798 to generate new memory accesses. */
4799 && !lacc->grp_unscalarizable_region
4800 && !racc->grp_unscalarizable_region)
4802 struct subreplacement_assignment_data sad;
4804 sad.left_offset = lacc->offset;
4805 sad.assignment_lhs = lhs;
4806 sad.assignment_rhs = rhs;
4807 sad.top_racc = racc;
4808 sad.old_gsi = *gsi;
4809 sad.new_gsi = gsi;
4810 sad.loc = gimple_location (stmt);
4811 sad.refreshed = SRA_UDH_NONE;
4813 if (lacc->grp_read && !lacc->grp_covered)
4814 handle_unscalarized_data_in_subtree (&sad);
4816 load_assign_lhs_subreplacements (lacc, &sad);
4817 if (sad.refreshed != SRA_UDH_RIGHT)
4819 gsi_next (gsi);
4820 unlink_stmt_vdef (stmt);
4821 gsi_remove (&sad.old_gsi, true);
4822 release_defs (stmt);
4823 sra_stats.deleted++;
4824 return SRA_AM_REMOVED;
4827 else
4829 if (access_has_children_p (racc)
4830 && !racc->grp_unscalarized_data
4831 && TREE_CODE (lhs) != SSA_NAME)
4833 if (dump_file)
4835 fprintf (dump_file, "Removing load: ");
4836 print_gimple_stmt (dump_file, stmt, 0);
4838 generate_subtree_copies (racc->first_child, lhs,
4839 racc->offset, 0, 0, gsi,
4840 false, false, loc);
4841 gcc_assert (stmt == gsi_stmt (*gsi));
4842 unlink_stmt_vdef (stmt);
4843 gsi_remove (gsi, true);
4844 release_defs (stmt);
4845 sra_stats.deleted++;
4846 return SRA_AM_REMOVED;
4848 /* Restore the aggregate RHS from its components so the
4849 prevailing aggregate copy does the right thing. */
4850 if (access_has_children_p (racc) && !TREE_READONLY (racc->base))
4851 generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0,
4852 gsi, false, false, loc);
4853 /* Re-load the components of the aggregate copy destination.
4854 But use the RHS aggregate to load from to expose more
4855 optimization opportunities. */
4856 if (access_has_children_p (lacc))
4857 generate_subtree_copies (lacc->first_child, rhs, lacc->offset,
4858 0, 0, gsi, true, true, loc);
4861 return SRA_AM_NONE;
4865 /* Set any scalar replacements of values in the constant pool to the initial
4866 value of the constant. (Constant-pool decls like *.LC0 have effectively
4867 been initialized before the program starts, we must do the same for their
4868 replacements.) Thus, we output statements like 'SR.1 = *.LC0[0];' into
4869 the function's entry block. */
4871 static void
4872 initialize_constant_pool_replacements (void)
4874 gimple_seq seq = NULL;
4875 gimple_stmt_iterator gsi = gsi_start (seq);
4876 bitmap_iterator bi;
4877 unsigned i;
4879 EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
4881 tree var = candidate (i);
4882 if (!constant_decl_p (var))
4883 continue;
4885 struct access *access = get_first_repr_for_decl (var);
4887 while (access)
4889 if (access->replacement_decl)
4891 gassign *stmt
4892 = gimple_build_assign (get_access_replacement (access),
4893 unshare_expr (access->expr));
4894 if (dump_file && (dump_flags & TDF_DETAILS))
4896 fprintf (dump_file, "Generating constant initializer: ");
4897 print_gimple_stmt (dump_file, stmt, 0);
4898 fprintf (dump_file, "\n");
4900 gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
4901 update_stmt (stmt);
4904 if (access->first_child)
4905 access = access->first_child;
4906 else if (access->next_sibling)
4907 access = access->next_sibling;
4908 else
4910 while (access->parent && !access->next_sibling)
4911 access = access->parent;
4912 if (access->next_sibling)
4913 access = access->next_sibling;
4914 else
4915 access = access->next_grp;
4920 seq = gsi_seq (gsi);
4921 if (seq)
4922 gsi_insert_seq_on_edge_immediate (
4923 single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
4926 /* Traverse the function body and all modifications as decided in
4927 analyze_all_variable_accesses. Return true iff the CFG has been
4928 changed. */
4930 static bool
4931 sra_modify_function_body (void)
4933 bool cfg_changed = false;
4934 basic_block bb;
4936 initialize_constant_pool_replacements ();
4938 FOR_EACH_BB_FN (bb, cfun)
4940 gimple_stmt_iterator gsi = gsi_start_bb (bb);
4941 while (!gsi_end_p (gsi))
4943 gimple *stmt = gsi_stmt (gsi);
4944 enum assignment_mod_result assign_result;
4945 bool modified = false, deleted = false;
4946 tree *t;
4947 unsigned i;
4949 switch (gimple_code (stmt))
4951 case GIMPLE_RETURN:
4952 t = gimple_return_retval_ptr (as_a <greturn *> (stmt));
4953 if (*t != NULL_TREE)
4954 modified |= sra_modify_expr (t, false, &gsi, &gsi);
4955 break;
4957 case GIMPLE_ASSIGN:
4958 assign_result = sra_modify_assign (stmt, &gsi);
4959 modified |= assign_result == SRA_AM_MODIFIED;
4960 deleted = assign_result == SRA_AM_REMOVED;
4961 break;
4963 case GIMPLE_CALL:
4964 /* Handle calls to .DEFERRED_INIT specially. */
4965 if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
4967 assign_result = sra_modify_deferred_init (stmt, &gsi);
4968 modified |= assign_result == SRA_AM_MODIFIED;
4969 deleted = assign_result == SRA_AM_REMOVED;
4971 else
4973 gcall *call = as_a <gcall *> (stmt);
4974 gimple_stmt_iterator call_gsi = gsi;
4976 /* Operands must be processed before the lhs. */
4977 for (i = 0; i < gimple_call_num_args (call); i++)
4979 int flags = gimple_call_arg_flags (call, i);
4980 t = gimple_call_arg_ptr (call, i);
4981 modified |= sra_modify_call_arg (t, &call_gsi, &gsi, flags);
4983 if (gimple_call_chain (call))
4985 t = gimple_call_chain_ptr (call);
4986 int flags = gimple_call_static_chain_flags (call);
4987 modified |= sra_modify_call_arg (t, &call_gsi, &gsi,
4988 flags);
4990 if (gimple_call_lhs (call))
4992 t = gimple_call_lhs_ptr (call);
4993 modified |= sra_modify_expr (t, true, &call_gsi, &gsi);
4996 break;
4998 case GIMPLE_ASM:
5000 gimple_stmt_iterator stmt_gsi = gsi;
5001 gasm *asm_stmt = as_a <gasm *> (stmt);
5002 for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
5004 t = &TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
5005 modified |= sra_modify_expr (t, false, &stmt_gsi, &gsi);
5007 for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
5009 t = &TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
5010 modified |= sra_modify_expr (t, true, &stmt_gsi, &gsi);
5013 break;
5015 default:
5016 break;
5019 if (modified)
5021 update_stmt (stmt);
5022 if (maybe_clean_eh_stmt (stmt)
5023 && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
5024 cfg_changed = true;
5026 if (!deleted)
5027 gsi_next (&gsi);
5031 gsi_commit_edge_inserts ();
5032 return cfg_changed;
5035 /* Generate statements initializing scalar replacements of parts of function
5036 parameters. */
5038 static void
5039 initialize_parameter_reductions (void)
5041 gimple_stmt_iterator gsi;
5042 gimple_seq seq = NULL;
5043 tree parm;
5045 gsi = gsi_start (seq);
5046 for (parm = DECL_ARGUMENTS (current_function_decl);
5047 parm;
5048 parm = DECL_CHAIN (parm))
5050 vec<access_p> *access_vec;
5051 struct access *access;
5053 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
5054 continue;
5055 access_vec = get_base_access_vector (parm);
5056 if (!access_vec)
5057 continue;
5059 for (access = (*access_vec)[0];
5060 access;
5061 access = access->next_grp)
5062 generate_subtree_copies (access, parm, 0, 0, 0, &gsi, true, true,
5063 EXPR_LOCATION (parm));
5066 seq = gsi_seq (gsi);
5067 if (seq)
5068 gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
5071 /* The "main" function of intraprocedural SRA passes. Runs the analysis and if
5072 it reveals there are components of some aggregates to be scalarized, it runs
5073 the required transformations. */
5074 static unsigned int
5075 perform_intra_sra (void)
5077 int ret = 0;
5078 sra_initialize ();
5080 if (!find_var_candidates ())
5081 goto out;
5083 if (!scan_function ())
5084 goto out;
5086 if (!analyze_all_variable_accesses ())
5087 goto out;
5089 if (sra_modify_function_body ())
5090 ret = TODO_update_ssa | TODO_cleanup_cfg;
5091 else
5092 ret = TODO_update_ssa;
5093 initialize_parameter_reductions ();
5095 statistics_counter_event (cfun, "Scalar replacements created",
5096 sra_stats.replacements);
5097 statistics_counter_event (cfun, "Modified expressions", sra_stats.exprs);
5098 statistics_counter_event (cfun, "Subtree copy stmts",
5099 sra_stats.subtree_copies);
5100 statistics_counter_event (cfun, "Subreplacement stmts",
5101 sra_stats.subreplacements);
5102 statistics_counter_event (cfun, "Deleted stmts", sra_stats.deleted);
5103 statistics_counter_event (cfun, "Separate LHS and RHS handling",
5104 sra_stats.separate_lhs_rhs_handling);
5106 out:
5107 sra_deinitialize ();
5108 return ret;
5111 /* Perform early intraprocedural SRA. */
5112 static unsigned int
5113 early_intra_sra (void)
5115 sra_mode = SRA_MODE_EARLY_INTRA;
5116 return perform_intra_sra ();
5119 /* Perform "late" intraprocedural SRA. */
5120 static unsigned int
5121 late_intra_sra (void)
5123 sra_mode = SRA_MODE_INTRA;
5124 return perform_intra_sra ();
5128 static bool
5129 gate_intra_sra (void)
5131 return flag_tree_sra != 0 && dbg_cnt (tree_sra);
5135 namespace {
5137 const pass_data pass_data_sra_early =
5139 GIMPLE_PASS, /* type */
5140 "esra", /* name */
5141 OPTGROUP_NONE, /* optinfo_flags */
5142 TV_TREE_SRA, /* tv_id */
5143 ( PROP_cfg | PROP_ssa ), /* properties_required */
5144 0, /* properties_provided */
5145 0, /* properties_destroyed */
5146 0, /* todo_flags_start */
5147 TODO_update_ssa, /* todo_flags_finish */
5150 class pass_sra_early : public gimple_opt_pass
5152 public:
5153 pass_sra_early (gcc::context *ctxt)
5154 : gimple_opt_pass (pass_data_sra_early, ctxt)
5157 /* opt_pass methods: */
5158 bool gate (function *) final override { return gate_intra_sra (); }
5159 unsigned int execute (function *) final override
5161 return early_intra_sra ();
5164 }; // class pass_sra_early
5166 } // anon namespace
5168 gimple_opt_pass *
5169 make_pass_sra_early (gcc::context *ctxt)
5171 return new pass_sra_early (ctxt);
5174 namespace {
5176 const pass_data pass_data_sra =
5178 GIMPLE_PASS, /* type */
5179 "sra", /* name */
5180 OPTGROUP_NONE, /* optinfo_flags */
5181 TV_TREE_SRA, /* tv_id */
5182 ( PROP_cfg | PROP_ssa ), /* properties_required */
5183 0, /* properties_provided */
5184 0, /* properties_destroyed */
5185 TODO_update_address_taken, /* todo_flags_start */
5186 TODO_update_ssa, /* todo_flags_finish */
5189 class pass_sra : public gimple_opt_pass
5191 public:
5192 pass_sra (gcc::context *ctxt)
5193 : gimple_opt_pass (pass_data_sra, ctxt)
5196 /* opt_pass methods: */
5197 bool gate (function *) final override { return gate_intra_sra (); }
5198 unsigned int execute (function *) final override { return late_intra_sra (); }
5200 }; // class pass_sra
5202 } // anon namespace
5204 gimple_opt_pass *
5205 make_pass_sra (gcc::context *ctxt)
5207 return new pass_sra (ctxt);
5211 /* If type T cannot be totally scalarized, return false. Otherwise return true
5212 and push to the vector within PC offsets and lengths of all padding in the
5213 type as total scalarization would encounter it. */
5215 static bool
5216 check_ts_and_push_padding_to_vec (tree type, sra_padding_collecting *pc)
5218 if (!totally_scalarizable_type_p (type, true /* optimistic value */,
5219 0, pc))
5220 return false;
5222 pc->record_padding (tree_to_shwi (TYPE_SIZE (type)));
5223 return true;
5226 /* Given two types in an assignment, return true either if any one cannot be
5227 totally scalarized or if they have padding (i.e. not copied bits) */
5229 bool
5230 sra_total_scalarization_would_copy_same_data_p (tree t1, tree t2)
5232 sra_padding_collecting p1;
5233 if (!check_ts_and_push_padding_to_vec (t1, &p1))
5234 return true;
5236 sra_padding_collecting p2;
5237 if (!check_ts_and_push_padding_to_vec (t2, &p2))
5238 return true;
5240 unsigned l = p1.m_padding.length ();
5241 if (l != p2.m_padding.length ())
5242 return false;
5243 for (unsigned i = 0; i < l; i++)
5244 if (p1.m_padding[i].first != p2.m_padding[i].first
5245 || p1.m_padding[i].second != p2.m_padding[i].second)
5246 return false;
5248 return true;