libcpp, c, middle-end: Optimize initializers using #embed in C
[official-gcc.git] / gcc / tree-sra.cc
blob64e2f007d6805cbac3b50858d80f17f66f27f37f
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 /* Return true when either T1 is a type that, when loaded into a register and
2339 stored back to memory will yield the same bits or when both T1 and T2 are
2340 compatible. */
2342 static bool
2343 types_risk_mangled_binary_repr_p (tree t1, tree t2)
2345 if (mode_can_transfer_bits (TYPE_MODE (t1)))
2346 return false;
2348 return !types_compatible_p (t1, t2);
2351 /* Sort all accesses for the given variable, check for partial overlaps and
2352 return NULL if there are any. If there are none, pick a representative for
2353 each combination of offset and size and create a linked list out of them.
2354 Return the pointer to the first representative and make sure it is the first
2355 one in the vector of accesses. */
2357 static struct access *
2358 sort_and_splice_var_accesses (tree var)
2360 int i, j, access_count;
2361 struct access *res, **prev_acc_ptr = &res;
2362 vec<access_p> *access_vec;
2363 bool first = true;
2364 HOST_WIDE_INT low = -1, high = 0;
2366 access_vec = get_base_access_vector (var);
2367 if (!access_vec)
2368 return NULL;
2369 access_count = access_vec->length ();
2371 /* Sort by <OFFSET, SIZE>. */
2372 access_vec->qsort (compare_access_positions);
2374 i = 0;
2375 while (i < access_count)
2377 struct access *access = (*access_vec)[i];
2378 bool grp_write = access->write;
2379 bool grp_read = !access->write;
2380 bool grp_scalar_write = access->write
2381 && is_gimple_reg_type (access->type);
2382 bool grp_scalar_read = !access->write
2383 && is_gimple_reg_type (access->type);
2384 bool grp_assignment_read = access->grp_assignment_read;
2385 bool grp_assignment_write = access->grp_assignment_write;
2386 bool multiple_scalar_reads = false;
2387 bool grp_partial_lhs = access->grp_partial_lhs;
2388 bool first_scalar = is_gimple_reg_type (access->type);
2389 bool unscalarizable_region = access->grp_unscalarizable_region;
2390 bool grp_same_access_path = true;
2391 bool bf_non_full_precision
2392 = (INTEGRAL_TYPE_P (access->type)
2393 && TYPE_PRECISION (access->type) != access->size
2394 && TREE_CODE (access->expr) == COMPONENT_REF
2395 && DECL_BIT_FIELD (TREE_OPERAND (access->expr, 1)));
2397 if (first || access->offset >= high)
2399 first = false;
2400 low = access->offset;
2401 high = access->offset + access->size;
2403 else if (access->offset > low && access->offset + access->size > high)
2404 return NULL;
2405 else
2406 gcc_assert (access->offset >= low
2407 && access->offset + access->size <= high);
2409 if (INTEGRAL_TYPE_P (access->type)
2410 && TYPE_PRECISION (access->type) != access->size
2411 && bitmap_bit_p (passed_by_ref_in_call, DECL_UID (access->base)))
2413 /* This can lead to performance regressions because we can generate
2414 excessive zero extensions. */
2415 if (dump_file && (dump_flags & TDF_DETAILS))
2417 fprintf (dump_file, "Won't scalarize ");
2418 print_generic_expr (dump_file, access->base);
2419 fprintf (dump_file, "(%d), it is passed by reference to a call "
2420 "and there are accesses with precision not covering "
2421 "their type size.", DECL_UID (access->base));
2423 return NULL;
2426 grp_same_access_path = path_comparable_for_same_access (access->expr);
2428 j = i + 1;
2429 while (j < access_count)
2431 struct access *ac2 = (*access_vec)[j];
2432 if (ac2->offset != access->offset || ac2->size != access->size)
2433 break;
2434 if (ac2->write)
2436 grp_write = true;
2437 grp_scalar_write = (grp_scalar_write
2438 || is_gimple_reg_type (ac2->type));
2440 else
2442 grp_read = true;
2443 if (is_gimple_reg_type (ac2->type))
2445 if (grp_scalar_read)
2446 multiple_scalar_reads = true;
2447 else
2448 grp_scalar_read = true;
2451 grp_assignment_read |= ac2->grp_assignment_read;
2452 grp_assignment_write |= ac2->grp_assignment_write;
2453 grp_partial_lhs |= ac2->grp_partial_lhs;
2454 unscalarizable_region |= ac2->grp_unscalarizable_region;
2455 relink_to_new_repr (access, ac2);
2457 /* If there are both aggregate-type and scalar-type accesses with
2458 this combination of size and offset, the comparison function
2459 should have put the scalars first. */
2460 gcc_assert (first_scalar || !is_gimple_reg_type (ac2->type));
2461 /* It also prefers integral types to non-integral. However, when the
2462 precision of the selected type does not span the entire area and
2463 should also be used for a non-integer (i.e. float), we must not
2464 let that happen. Normally analyze_access_subtree expands the type
2465 to cover the entire area but for bit-fields it doesn't. */
2466 if (bf_non_full_precision && !INTEGRAL_TYPE_P (ac2->type))
2468 if (dump_file && (dump_flags & TDF_DETAILS))
2470 fprintf (dump_file, "Cannot scalarize the following access "
2471 "because insufficient precision integer type was "
2472 "selected.\n ");
2473 dump_access (dump_file, access, false);
2475 unscalarizable_region = true;
2477 else if (types_risk_mangled_binary_repr_p (access->type, ac2->type))
2479 if (dump_file && (dump_flags & TDF_DETAILS))
2481 fprintf (dump_file, "Cannot scalarize the following access "
2482 "because data would be held in a mode which is not "
2483 "guaranteed to preserve all bits.\n ");
2484 dump_access (dump_file, access, false);
2486 unscalarizable_region = true;
2489 if (grp_same_access_path
2490 && !same_access_path_p (access->expr, ac2->expr))
2491 grp_same_access_path = false;
2493 ac2->group_representative = access;
2494 j++;
2497 i = j;
2499 access->group_representative = access;
2500 access->grp_write = grp_write;
2501 access->grp_read = grp_read;
2502 access->grp_scalar_read = grp_scalar_read;
2503 access->grp_scalar_write = grp_scalar_write;
2504 access->grp_assignment_read = grp_assignment_read;
2505 access->grp_assignment_write = grp_assignment_write;
2506 access->grp_hint = multiple_scalar_reads && !constant_decl_p (var);
2507 access->grp_partial_lhs = grp_partial_lhs;
2508 access->grp_unscalarizable_region = unscalarizable_region;
2509 access->grp_same_access_path = grp_same_access_path;
2511 *prev_acc_ptr = access;
2512 prev_acc_ptr = &access->next_grp;
2515 gcc_assert (res == (*access_vec)[0]);
2516 return res;
2519 /* Create a variable for the given ACCESS which determines the type, name and a
2520 few other properties. Return the variable declaration and store it also to
2521 ACCESS->replacement. REG_TREE is used when creating a declaration to base a
2522 default-definition SSA name on in order to facilitate an uninitialized
2523 warning. It is used instead of the actual ACCESS type if that is not of a
2524 gimple register type. */
2526 static tree
2527 create_access_replacement (struct access *access, tree reg_type = NULL_TREE)
2529 tree repl;
2531 tree type = access->type;
2532 if (reg_type && !is_gimple_reg_type (type))
2533 type = reg_type;
2535 if (access->grp_to_be_debug_replaced)
2537 repl = create_tmp_var_raw (access->type);
2538 DECL_CONTEXT (repl) = current_function_decl;
2540 else
2541 /* Drop any special alignment on the type if it's not on the main
2542 variant. This avoids issues with weirdo ABIs like AAPCS. */
2543 repl = create_tmp_var (build_qualified_type (TYPE_MAIN_VARIANT (type),
2544 TYPE_QUALS (type)), "SR");
2545 if (access->grp_partial_lhs
2546 && is_gimple_reg_type (type))
2547 DECL_NOT_GIMPLE_REG_P (repl) = 1;
2549 DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base);
2550 DECL_ARTIFICIAL (repl) = 1;
2551 DECL_IGNORED_P (repl) = DECL_IGNORED_P (access->base);
2553 if (DECL_NAME (access->base)
2554 && !DECL_IGNORED_P (access->base)
2555 && !DECL_ARTIFICIAL (access->base))
2557 char *pretty_name = make_fancy_name (access->expr);
2558 tree debug_expr = unshare_expr_without_location (access->expr), d;
2559 bool fail = false;
2561 DECL_NAME (repl) = get_identifier (pretty_name);
2562 DECL_NAMELESS (repl) = 1;
2563 obstack_free (&name_obstack, pretty_name);
2565 /* Get rid of any SSA_NAMEs embedded in debug_expr,
2566 as DECL_DEBUG_EXPR isn't considered when looking for still
2567 used SSA_NAMEs and thus they could be freed. All debug info
2568 generation cares is whether something is constant or variable
2569 and that get_ref_base_and_extent works properly on the
2570 expression. It cannot handle accesses at a non-constant offset
2571 though, so just give up in those cases. */
2572 for (d = debug_expr;
2573 !fail && (handled_component_p (d) || TREE_CODE (d) == MEM_REF);
2574 d = TREE_OPERAND (d, 0))
2575 switch (TREE_CODE (d))
2577 case ARRAY_REF:
2578 case ARRAY_RANGE_REF:
2579 if (TREE_OPERAND (d, 1)
2580 && TREE_CODE (TREE_OPERAND (d, 1)) != INTEGER_CST)
2581 fail = true;
2582 if (TREE_OPERAND (d, 3)
2583 && TREE_CODE (TREE_OPERAND (d, 3)) != INTEGER_CST)
2584 fail = true;
2585 /* FALLTHRU */
2586 case COMPONENT_REF:
2587 if (TREE_OPERAND (d, 2)
2588 && TREE_CODE (TREE_OPERAND (d, 2)) != INTEGER_CST)
2589 fail = true;
2590 break;
2591 case MEM_REF:
2592 if (TREE_CODE (TREE_OPERAND (d, 0)) != ADDR_EXPR)
2593 fail = true;
2594 else
2595 d = TREE_OPERAND (d, 0);
2596 break;
2597 default:
2598 break;
2600 if (!fail)
2602 SET_DECL_DEBUG_EXPR (repl, debug_expr);
2603 DECL_HAS_DEBUG_EXPR_P (repl) = 1;
2605 if (access->grp_no_warning)
2606 suppress_warning (repl /* Be more selective! */);
2607 else
2608 copy_warning (repl, access->base);
2610 else
2611 suppress_warning (repl /* Be more selective! */);
2613 if (dump_file)
2615 if (access->grp_to_be_debug_replaced)
2617 fprintf (dump_file, "Created a debug-only replacement for ");
2618 print_generic_expr (dump_file, access->base);
2619 fprintf (dump_file, " offset: %u, size: %u\n",
2620 (unsigned) access->offset, (unsigned) access->size);
2622 else
2624 fprintf (dump_file, "Created a replacement for ");
2625 print_generic_expr (dump_file, access->base);
2626 fprintf (dump_file, " offset: %u, size: %u: ",
2627 (unsigned) access->offset, (unsigned) access->size);
2628 print_generic_expr (dump_file, repl, TDF_UID);
2629 fprintf (dump_file, "\n");
2632 sra_stats.replacements++;
2634 return repl;
2637 /* Return ACCESS scalar replacement, which must exist. */
2639 static inline tree
2640 get_access_replacement (struct access *access)
2642 gcc_checking_assert (access->replacement_decl);
2643 return access->replacement_decl;
2647 /* Build a subtree of accesses rooted in *ACCESS, and move the pointer in the
2648 linked list along the way. Stop when *ACCESS is NULL or the access pointed
2649 to it is not "within" the root. Return false iff some accesses partially
2650 overlap. */
2652 static bool
2653 build_access_subtree (struct access **access)
2655 struct access *root = *access, *last_child = NULL;
2656 HOST_WIDE_INT limit = root->offset + root->size;
2658 *access = (*access)->next_grp;
2659 while (*access && (*access)->offset + (*access)->size <= limit)
2661 if (!last_child)
2662 root->first_child = *access;
2663 else
2664 last_child->next_sibling = *access;
2665 last_child = *access;
2666 (*access)->parent = root;
2667 (*access)->grp_write |= root->grp_write;
2669 if (!build_access_subtree (access))
2670 return false;
2673 if (*access && (*access)->offset < limit)
2674 return false;
2676 return true;
2679 /* Build a tree of access representatives, ACCESS is the pointer to the first
2680 one, others are linked in a list by the next_grp field. Return false iff
2681 some accesses partially overlap. */
2683 static bool
2684 build_access_trees (struct access *access)
2686 while (access)
2688 struct access *root = access;
2690 if (!build_access_subtree (&access))
2691 return false;
2692 root->next_grp = access;
2694 return true;
2697 /* Traverse the access forest where ROOT is the first root and verify that
2698 various important invariants hold true. */
2700 DEBUG_FUNCTION void
2701 verify_sra_access_forest (struct access *root)
2703 struct access *access = root;
2704 tree first_base = root->base;
2705 gcc_assert (DECL_P (first_base));
2708 gcc_assert (access->base == first_base);
2709 if (access->parent)
2710 gcc_assert (access->offset >= access->parent->offset
2711 && access->size <= access->parent->size);
2712 if (access->next_sibling)
2713 gcc_assert (access->next_sibling->offset
2714 >= access->offset + access->size);
2716 poly_int64 poffset, psize, pmax_size;
2717 bool reverse;
2718 tree base = get_ref_base_and_extent (access->expr, &poffset, &psize,
2719 &pmax_size, &reverse);
2720 HOST_WIDE_INT offset, size, max_size;
2721 if (!poffset.is_constant (&offset)
2722 || !psize.is_constant (&size)
2723 || !pmax_size.is_constant (&max_size))
2724 gcc_unreachable ();
2725 gcc_assert (base == first_base);
2726 gcc_assert (offset == access->offset);
2727 gcc_assert (access->grp_unscalarizable_region
2728 || access->grp_total_scalarization
2729 || size == max_size);
2730 gcc_assert (access->grp_unscalarizable_region
2731 || !is_gimple_reg_type (access->type)
2732 || size == access->size);
2733 gcc_assert (reverse == access->reverse);
2735 if (access->first_child)
2737 gcc_assert (access->first_child->parent == access);
2738 access = access->first_child;
2740 else if (access->next_sibling)
2742 gcc_assert (access->next_sibling->parent == access->parent);
2743 access = access->next_sibling;
2745 else
2747 while (access->parent && !access->next_sibling)
2748 access = access->parent;
2749 if (access->next_sibling)
2750 access = access->next_sibling;
2751 else
2753 gcc_assert (access == root);
2754 root = root->next_grp;
2755 access = root;
2759 while (access);
2762 /* Verify access forests of all candidates with accesses by calling
2763 verify_access_forest on each on them. */
2765 DEBUG_FUNCTION void
2766 verify_all_sra_access_forests (void)
2768 bitmap_iterator bi;
2769 unsigned i;
2770 EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
2772 tree var = candidate (i);
2773 struct access *access = get_first_repr_for_decl (var);
2774 if (access)
2776 gcc_assert (access->base == var);
2777 verify_sra_access_forest (access);
2782 /* Return true if expr contains some ARRAY_REFs into a variable bounded
2783 array. */
2785 static bool
2786 expr_with_var_bounded_array_refs_p (tree expr)
2788 while (handled_component_p (expr))
2790 if (TREE_CODE (expr) == ARRAY_REF
2791 && !tree_fits_shwi_p (array_ref_low_bound (expr)))
2792 return true;
2793 expr = TREE_OPERAND (expr, 0);
2795 return false;
2798 /* Analyze the subtree of accesses rooted in ROOT, scheduling replacements when
2799 both seeming beneficial and when ALLOW_REPLACEMENTS allows it. If TOTALLY
2800 is set, we are totally scalarizing the aggregate. Also set all sorts of
2801 access flags appropriately along the way, notably always set grp_read and
2802 grp_assign_read according to MARK_READ and grp_write when MARK_WRITE is
2803 true.
2805 Creating a replacement for a scalar access is considered beneficial if its
2806 grp_hint ot TOTALLY is set (this means either that there is more than one
2807 direct read access or that we are attempting total scalarization) or
2808 according to the following table:
2810 Access written to through a scalar type (once or more times)
2812 | Written to in an assignment statement
2814 | | Access read as scalar _once_
2815 | | |
2816 | | | Read in an assignment statement
2817 | | | |
2818 | | | | Scalarize Comment
2819 -----------------------------------------------------------------------------
2820 0 0 0 0 No access for the scalar
2821 0 0 0 1 No access for the scalar
2822 0 0 1 0 No Single read - won't help
2823 0 0 1 1 No The same case
2824 0 1 0 0 No access for the scalar
2825 0 1 0 1 No access for the scalar
2826 0 1 1 0 Yes s = *g; return s.i;
2827 0 1 1 1 Yes The same case as above
2828 1 0 0 0 No Won't help
2829 1 0 0 1 Yes s.i = 1; *g = s;
2830 1 0 1 0 Yes s.i = 5; g = s.i;
2831 1 0 1 1 Yes The same case as above
2832 1 1 0 0 No Won't help.
2833 1 1 0 1 Yes s.i = 1; *g = s;
2834 1 1 1 0 Yes s = *g; return s.i;
2835 1 1 1 1 Yes Any of the above yeses */
2837 static bool
2838 analyze_access_subtree (struct access *root, struct access *parent,
2839 bool allow_replacements, bool totally)
2841 struct access *child;
2842 HOST_WIDE_INT limit = root->offset + root->size;
2843 HOST_WIDE_INT covered_to = root->offset;
2844 bool scalar = is_gimple_reg_type (root->type);
2845 bool hole = false, sth_created = false;
2847 if (parent)
2849 if (parent->grp_read)
2850 root->grp_read = 1;
2851 if (parent->grp_assignment_read)
2852 root->grp_assignment_read = 1;
2853 if (parent->grp_write)
2854 root->grp_write = 1;
2855 if (parent->grp_assignment_write)
2856 root->grp_assignment_write = 1;
2857 if (!parent->grp_same_access_path)
2858 root->grp_same_access_path = 0;
2861 if (root->grp_unscalarizable_region)
2862 allow_replacements = false;
2864 if (allow_replacements && expr_with_var_bounded_array_refs_p (root->expr))
2865 allow_replacements = false;
2867 if (!totally && root->grp_result_of_prop_from_lhs)
2868 allow_replacements = false;
2870 for (child = root->first_child; child; child = child->next_sibling)
2872 hole |= covered_to < child->offset;
2873 sth_created |= analyze_access_subtree (child, root,
2874 allow_replacements && !scalar
2875 && !root->grp_partial_lhs,
2876 totally);
2878 root->grp_unscalarized_data |= child->grp_unscalarized_data;
2879 if (child->grp_covered)
2880 covered_to += child->size;
2881 else
2882 hole = true;
2885 if (allow_replacements && scalar && !root->first_child
2886 && (totally || !root->grp_total_scalarization)
2887 && (totally
2888 || root->grp_hint
2889 || ((root->grp_scalar_read || root->grp_assignment_read)
2890 && (root->grp_scalar_write || root->grp_assignment_write))))
2892 /* Always create access replacements that cover the whole access.
2893 For integral types this means the precision has to match.
2894 Avoid assumptions based on the integral type kind, too. */
2895 if (INTEGRAL_TYPE_P (root->type)
2896 && ((TREE_CODE (root->type) != INTEGER_TYPE
2897 && TREE_CODE (root->type) != BITINT_TYPE)
2898 || TYPE_PRECISION (root->type) != root->size)
2899 /* But leave bitfield accesses alone. */
2900 && (TREE_CODE (root->expr) != COMPONENT_REF
2901 || !DECL_BIT_FIELD (TREE_OPERAND (root->expr, 1))))
2903 tree rt = root->type;
2904 gcc_assert ((root->offset % BITS_PER_UNIT) == 0
2905 && (root->size % BITS_PER_UNIT) == 0);
2906 if (TREE_CODE (root->type) == BITINT_TYPE)
2907 root->type = build_bitint_type (root->size, TYPE_UNSIGNED (rt));
2908 else
2909 root->type = build_nonstandard_integer_type (root->size,
2910 TYPE_UNSIGNED (rt));
2911 root->expr = build_ref_for_offset (UNKNOWN_LOCATION, root->base,
2912 root->offset, root->reverse,
2913 root->type, NULL, false);
2915 if (dump_file && (dump_flags & TDF_DETAILS))
2917 fprintf (dump_file, "Changing the type of a replacement for ");
2918 print_generic_expr (dump_file, root->base);
2919 fprintf (dump_file, " offset: %u, size: %u ",
2920 (unsigned) root->offset, (unsigned) root->size);
2921 fprintf (dump_file, " to an integer.\n");
2925 root->grp_to_be_replaced = 1;
2926 root->replacement_decl = create_access_replacement (root);
2927 sth_created = true;
2928 hole = false;
2930 else
2932 if (allow_replacements
2933 && scalar && !root->first_child
2934 && !root->grp_total_scalarization
2935 && (root->grp_scalar_write || root->grp_assignment_write)
2936 && !bitmap_bit_p (cannot_scalarize_away_bitmap,
2937 DECL_UID (root->base)))
2939 gcc_checking_assert (!root->grp_scalar_read
2940 && !root->grp_assignment_read);
2941 sth_created = true;
2942 if (MAY_HAVE_DEBUG_BIND_STMTS)
2944 root->grp_to_be_debug_replaced = 1;
2945 root->replacement_decl = create_access_replacement (root);
2949 if (covered_to < limit)
2950 hole = true;
2951 if (scalar || !allow_replacements)
2952 root->grp_total_scalarization = 0;
2955 if (!hole || totally)
2956 root->grp_covered = 1;
2957 else if (root->grp_write || comes_initialized_p (root->base))
2958 root->grp_unscalarized_data = 1; /* not covered and written to */
2959 return sth_created;
2962 /* Analyze all access trees linked by next_grp by the means of
2963 analyze_access_subtree. */
2964 static bool
2965 analyze_access_trees (struct access *access)
2967 bool ret = false;
2969 while (access)
2971 if (analyze_access_subtree (access, NULL, true,
2972 access->grp_total_scalarization))
2973 ret = true;
2974 access = access->next_grp;
2977 return ret;
2980 /* Return true iff a potential new child of ACC at offset OFFSET and with size
2981 SIZE would conflict with an already existing one. If exactly such a child
2982 already exists in ACC, store a pointer to it in EXACT_MATCH. */
2984 static bool
2985 child_would_conflict_in_acc (struct access *acc, HOST_WIDE_INT norm_offset,
2986 HOST_WIDE_INT size, struct access **exact_match)
2988 struct access *child;
2990 for (child = acc->first_child; child; child = child->next_sibling)
2992 if (child->offset == norm_offset && child->size == size)
2994 *exact_match = child;
2995 return true;
2998 if (child->offset < norm_offset + size
2999 && child->offset + child->size > norm_offset)
3000 return true;
3003 return false;
3006 /* Create a new child access of PARENT, with all properties just like MODEL
3007 except for its offset and with its grp_write false and grp_read true.
3008 Return the new access or NULL if it cannot be created. Note that this
3009 access is created long after all splicing and sorting, it's not located in
3010 any access vector and is automatically a representative of its group. Set
3011 the gpr_write flag of the new accesss if SET_GRP_WRITE is true. */
3013 static struct access *
3014 create_artificial_child_access (struct access *parent, struct access *model,
3015 HOST_WIDE_INT new_offset,
3016 bool set_grp_read, bool set_grp_write)
3018 struct access **child;
3019 tree expr = parent->base;
3021 gcc_assert (!model->grp_unscalarizable_region);
3023 struct access *access = access_pool.allocate ();
3024 memset (access, 0, sizeof (struct access));
3025 if (!build_user_friendly_ref_for_offset (&expr, TREE_TYPE (expr), new_offset,
3026 model->type))
3028 access->grp_no_warning = true;
3029 expr = build_ref_for_model (EXPR_LOCATION (parent->base), parent->base,
3030 new_offset, model, NULL, false);
3033 access->base = parent->base;
3034 access->expr = expr;
3035 access->offset = new_offset;
3036 access->size = model->size;
3037 access->type = model->type;
3038 access->parent = parent;
3039 access->grp_read = set_grp_read;
3040 access->grp_write = set_grp_write;
3041 access->reverse = model->reverse;
3043 child = &parent->first_child;
3044 while (*child && (*child)->offset < new_offset)
3045 child = &(*child)->next_sibling;
3047 access->next_sibling = *child;
3048 *child = access;
3050 return access;
3054 /* Beginning with ACCESS, traverse its whole access subtree and mark all
3055 sub-trees as written to. If any of them has not been marked so previously
3056 and has assignment links leading from it, re-enqueue it. */
3058 static void
3059 subtree_mark_written_and_rhs_enqueue (struct access *access)
3061 if (access->grp_write)
3062 return;
3063 access->grp_write = true;
3064 add_access_to_rhs_work_queue (access);
3066 struct access *child;
3067 for (child = access->first_child; child; child = child->next_sibling)
3068 subtree_mark_written_and_rhs_enqueue (child);
3071 /* If there is still budget to create a propagation access for DECL, return
3072 true and decrement the budget. Otherwise return false. */
3074 static bool
3075 budget_for_propagation_access (tree decl)
3077 unsigned b, *p = propagation_budget->get (decl);
3078 if (p)
3079 b = *p;
3080 else
3081 b = param_sra_max_propagations;
3083 if (b == 0)
3084 return false;
3085 b--;
3087 if (b == 0 && dump_file && (dump_flags & TDF_DETAILS))
3089 fprintf (dump_file, "The propagation budget of ");
3090 print_generic_expr (dump_file, decl);
3091 fprintf (dump_file, " (UID: %u) has been exhausted.\n", DECL_UID (decl));
3093 propagation_budget->put (decl, b);
3094 return true;
3097 /* Return true if ACC or any of its subaccesses has grp_child set. */
3099 static bool
3100 access_or_its_child_written (struct access *acc)
3102 if (acc->grp_write)
3103 return true;
3104 for (struct access *sub = acc->first_child; sub; sub = sub->next_sibling)
3105 if (access_or_its_child_written (sub))
3106 return true;
3107 return false;
3110 /* Propagate subaccesses and grp_write flags of RACC across an assignment link
3111 to LACC. Enqueue sub-accesses as necessary so that the write flag is
3112 propagated transitively. Return true if anything changed. Additionally, if
3113 RACC is a scalar access but LACC is not, change the type of the latter, if
3114 possible. */
3116 static bool
3117 propagate_subaccesses_from_rhs (struct access *lacc, struct access *racc)
3119 struct access *rchild;
3120 HOST_WIDE_INT norm_delta = lacc->offset - racc->offset;
3121 bool ret = false;
3123 /* IF the LHS is still not marked as being written to, we only need to do so
3124 if the RHS at this level actually was. */
3125 if (!lacc->grp_write)
3127 gcc_checking_assert (!comes_initialized_p (racc->base));
3128 if (racc->grp_write)
3130 subtree_mark_written_and_rhs_enqueue (lacc);
3131 ret = true;
3135 if (is_gimple_reg_type (lacc->type)
3136 || lacc->grp_unscalarizable_region
3137 || racc->grp_unscalarizable_region)
3139 if (!lacc->grp_write)
3141 ret = true;
3142 subtree_mark_written_and_rhs_enqueue (lacc);
3144 return ret;
3147 if (is_gimple_reg_type (racc->type))
3149 if (!lacc->grp_write)
3151 ret = true;
3152 subtree_mark_written_and_rhs_enqueue (lacc);
3154 if (!lacc->first_child
3155 && !racc->first_child
3156 && !types_risk_mangled_binary_repr_p (racc->type, lacc->type))
3158 /* We are about to change the access type from aggregate to scalar,
3159 so we need to put the reverse flag onto the access, if any. */
3160 const bool reverse
3161 = TYPE_REVERSE_STORAGE_ORDER (lacc->type)
3162 && !POINTER_TYPE_P (racc->type)
3163 && !VECTOR_TYPE_P (racc->type);
3164 tree t = lacc->base;
3166 lacc->type = racc->type;
3167 if (build_user_friendly_ref_for_offset (&t, TREE_TYPE (t),
3168 lacc->offset, racc->type))
3170 lacc->expr = t;
3171 lacc->grp_same_access_path = true;
3173 else
3175 lacc->expr = build_ref_for_model (EXPR_LOCATION (lacc->base),
3176 lacc->base, lacc->offset,
3177 racc, NULL, false);
3178 if (TREE_CODE (lacc->expr) == MEM_REF)
3179 REF_REVERSE_STORAGE_ORDER (lacc->expr) = reverse;
3180 lacc->grp_no_warning = true;
3181 lacc->grp_same_access_path = false;
3183 lacc->reverse = reverse;
3185 return ret;
3188 for (rchild = racc->first_child; rchild; rchild = rchild->next_sibling)
3190 struct access *new_acc = NULL;
3191 HOST_WIDE_INT norm_offset = rchild->offset + norm_delta;
3193 if (child_would_conflict_in_acc (lacc, norm_offset, rchild->size,
3194 &new_acc))
3196 if (new_acc)
3198 if (!new_acc->grp_write && rchild->grp_write)
3200 gcc_assert (!lacc->grp_write);
3201 subtree_mark_written_and_rhs_enqueue (new_acc);
3202 ret = true;
3205 rchild->grp_hint = 1;
3206 new_acc->grp_hint |= new_acc->grp_read;
3207 if (rchild->first_child
3208 && propagate_subaccesses_from_rhs (new_acc, rchild))
3210 ret = 1;
3211 add_access_to_rhs_work_queue (new_acc);
3214 else
3216 if (!lacc->grp_write)
3218 ret = true;
3219 subtree_mark_written_and_rhs_enqueue (lacc);
3222 continue;
3225 if (rchild->grp_unscalarizable_region
3226 || !budget_for_propagation_access (lacc->base))
3228 if (!lacc->grp_write && access_or_its_child_written (rchild))
3230 ret = true;
3231 subtree_mark_written_and_rhs_enqueue (lacc);
3233 continue;
3236 rchild->grp_hint = 1;
3237 /* Because get_ref_base_and_extent always includes padding in size for
3238 accesses to DECLs but not necessarily for COMPONENT_REFs of the same
3239 type, we might be actually attempting to here to create a child of the
3240 same type as the parent. */
3241 if (!types_compatible_p (lacc->type, rchild->type))
3242 new_acc = create_artificial_child_access (lacc, rchild, norm_offset,
3243 false,
3244 (lacc->grp_write
3245 || rchild->grp_write));
3246 else
3247 new_acc = lacc;
3248 gcc_checking_assert (new_acc);
3249 if (racc->first_child)
3250 propagate_subaccesses_from_rhs (new_acc, rchild);
3252 add_access_to_rhs_work_queue (lacc);
3253 ret = true;
3256 return ret;
3259 /* Propagate subaccesses of LACC across an assignment link to RACC if they
3260 should inhibit total scalarization of the corresponding area. No flags are
3261 being propagated in the process. Return true if anything changed. */
3263 static bool
3264 propagate_subaccesses_from_lhs (struct access *lacc, struct access *racc)
3266 if (is_gimple_reg_type (racc->type)
3267 || lacc->grp_unscalarizable_region
3268 || racc->grp_unscalarizable_region)
3269 return false;
3271 /* TODO: Do we want set some new racc flag to stop potential total
3272 scalarization if lacc is a scalar access (and none fo the two have
3273 children)? */
3275 bool ret = false;
3276 HOST_WIDE_INT norm_delta = racc->offset - lacc->offset;
3277 for (struct access *lchild = lacc->first_child;
3278 lchild;
3279 lchild = lchild->next_sibling)
3281 struct access *matching_acc = NULL;
3282 HOST_WIDE_INT norm_offset = lchild->offset + norm_delta;
3284 if (lchild->grp_unscalarizable_region
3285 || child_would_conflict_in_acc (racc, norm_offset, lchild->size,
3286 &matching_acc)
3287 || !budget_for_propagation_access (racc->base))
3289 if (matching_acc
3290 && propagate_subaccesses_from_lhs (lchild, matching_acc))
3291 add_access_to_lhs_work_queue (matching_acc);
3292 continue;
3295 /* Because get_ref_base_and_extent always includes padding in size for
3296 accesses to DECLs but not necessarily for COMPONENT_REFs of the same
3297 type, we might be actually attempting to here to create a child of the
3298 same type as the parent. */
3299 if (!types_compatible_p (racc->type, lchild->type))
3301 struct access *new_acc
3302 = create_artificial_child_access (racc, lchild, norm_offset,
3303 true, false);
3304 new_acc->grp_result_of_prop_from_lhs = 1;
3305 propagate_subaccesses_from_lhs (lchild, new_acc);
3307 else
3308 propagate_subaccesses_from_lhs (lchild, racc);
3309 ret = true;
3311 return ret;
3314 /* Propagate all subaccesses across assignment links. */
3316 static void
3317 propagate_all_subaccesses (void)
3319 propagation_budget = new hash_map<tree, unsigned>;
3320 while (rhs_work_queue_head)
3322 struct access *racc = pop_access_from_rhs_work_queue ();
3323 struct assign_link *link;
3325 if (racc->group_representative)
3326 racc= racc->group_representative;
3327 gcc_assert (racc->first_rhs_link);
3329 for (link = racc->first_rhs_link; link; link = link->next_rhs)
3331 struct access *lacc = link->lacc;
3333 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
3334 continue;
3335 lacc = lacc->group_representative;
3337 bool reque_parents = false;
3338 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (racc->base)))
3340 if (!lacc->grp_write)
3342 subtree_mark_written_and_rhs_enqueue (lacc);
3343 reque_parents = true;
3346 else if (propagate_subaccesses_from_rhs (lacc, racc))
3347 reque_parents = true;
3349 if (reque_parents)
3352 add_access_to_rhs_work_queue (lacc);
3353 lacc = lacc->parent;
3355 while (lacc);
3359 while (lhs_work_queue_head)
3361 struct access *lacc = pop_access_from_lhs_work_queue ();
3362 struct assign_link *link;
3364 if (lacc->group_representative)
3365 lacc = lacc->group_representative;
3366 gcc_assert (lacc->first_lhs_link);
3368 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
3369 continue;
3371 for (link = lacc->first_lhs_link; link; link = link->next_lhs)
3373 struct access *racc = link->racc;
3375 if (racc->group_representative)
3376 racc = racc->group_representative;
3377 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (racc->base)))
3378 continue;
3379 if (propagate_subaccesses_from_lhs (lacc, racc))
3380 add_access_to_lhs_work_queue (racc);
3383 delete propagation_budget;
3386 /* Return true if the forest beginning with ROOT does not contain
3387 unscalarizable regions or non-byte aligned accesses. */
3389 static bool
3390 can_totally_scalarize_forest_p (struct access *root)
3392 struct access *access = root;
3395 if (access->grp_unscalarizable_region
3396 || (access->offset % BITS_PER_UNIT) != 0
3397 || (access->size % BITS_PER_UNIT) != 0
3398 || (is_gimple_reg_type (access->type)
3399 && access->first_child))
3400 return false;
3402 if (access->first_child)
3403 access = access->first_child;
3404 else if (access->next_sibling)
3405 access = access->next_sibling;
3406 else
3408 while (access->parent && !access->next_sibling)
3409 access = access->parent;
3410 if (access->next_sibling)
3411 access = access->next_sibling;
3412 else
3414 gcc_assert (access == root);
3415 root = root->next_grp;
3416 access = root;
3420 while (access);
3421 return true;
3424 /* Create and return an ACCESS in PARENT spanning from POS with SIZE, TYPE and
3425 reference EXPR for total scalarization purposes and mark it as such. Within
3426 the children of PARENT, link it in between PTR and NEXT_SIBLING. */
3428 static struct access *
3429 create_total_scalarization_access (struct access *parent, HOST_WIDE_INT pos,
3430 HOST_WIDE_INT size, tree type, tree expr,
3431 struct access **ptr,
3432 struct access *next_sibling)
3434 struct access *access = access_pool.allocate ();
3435 memset (access, 0, sizeof (struct access));
3436 access->base = parent->base;
3437 access->offset = pos;
3438 access->size = size;
3439 access->expr = expr;
3440 access->type = type;
3441 access->parent = parent;
3442 access->grp_write = parent->grp_write;
3443 access->grp_total_scalarization = 1;
3444 access->grp_hint = 1;
3445 access->grp_same_access_path = path_comparable_for_same_access (expr);
3446 access->reverse = reverse_storage_order_for_component_p (expr);
3448 access->next_sibling = next_sibling;
3449 *ptr = access;
3450 return access;
3453 /* Create and return an ACCESS in PARENT spanning from POS with SIZE, TYPE and
3454 reference EXPR for total scalarization purposes and mark it as such, link it
3455 at *PTR and reshape the tree so that those elements at *PTR and their
3456 siblings which fall within the part described by POS and SIZE are moved to
3457 be children of the new access. If a partial overlap is detected, return
3458 NULL. */
3460 static struct access *
3461 create_total_access_and_reshape (struct access *parent, HOST_WIDE_INT pos,
3462 HOST_WIDE_INT size, tree type, tree expr,
3463 struct access **ptr)
3465 struct access **p = ptr;
3467 while (*p && (*p)->offset < pos + size)
3469 if ((*p)->offset + (*p)->size > pos + size)
3470 return NULL;
3471 p = &(*p)->next_sibling;
3474 struct access *next_child = *ptr;
3475 struct access *new_acc
3476 = create_total_scalarization_access (parent, pos, size, type, expr,
3477 ptr, *p);
3478 if (p != ptr)
3480 new_acc->first_child = next_child;
3481 *p = NULL;
3482 for (struct access *a = next_child; a; a = a->next_sibling)
3483 a->parent = new_acc;
3485 return new_acc;
3488 static bool totally_scalarize_subtree (struct access *root);
3490 /* Return true if INNER is either the same type as OUTER or if it is the type
3491 of a record field in OUTER at offset zero, possibly in nested
3492 sub-records. */
3494 static bool
3495 access_and_field_type_match_p (tree outer, tree inner)
3497 if (TYPE_MAIN_VARIANT (outer) == TYPE_MAIN_VARIANT (inner))
3498 return true;
3499 if (TREE_CODE (outer) != RECORD_TYPE)
3500 return false;
3501 tree fld = TYPE_FIELDS (outer);
3502 while (fld)
3504 if (TREE_CODE (fld) == FIELD_DECL)
3506 if (!zerop (DECL_FIELD_OFFSET (fld)))
3507 return false;
3508 if (TYPE_MAIN_VARIANT (TREE_TYPE (fld)) == inner)
3509 return true;
3510 if (TREE_CODE (TREE_TYPE (fld)) == RECORD_TYPE)
3511 fld = TYPE_FIELDS (TREE_TYPE (fld));
3512 else
3513 return false;
3515 else
3516 fld = DECL_CHAIN (fld);
3518 return false;
3521 /* Return type of total_should_skip_creating_access indicating whether a total
3522 scalarization access for a field/element should be created, whether it
3523 already exists or whether the entire total scalarization has to fail. */
3525 enum total_sra_field_state {TOTAL_FLD_CREATE, TOTAL_FLD_DONE, TOTAL_FLD_FAILED};
3527 /* Do all the necessary steps in total scalarization when the given aggregate
3528 type has a TYPE at POS with the given SIZE should be put into PARENT and
3529 when we have processed all its siblings with smaller offsets up until and
3530 including LAST_SEEN_SIBLING (which can be NULL).
3532 If some further siblings are to be skipped, set *LAST_SEEN_SIBLING as
3533 appropriate. Return TOTAL_FLD_CREATE id the caller should carry on with
3534 creating a new access, TOTAL_FLD_DONE if access or accesses capable of
3535 representing the described part of the aggregate for the purposes of total
3536 scalarization already exist or TOTAL_FLD_FAILED if there is a problem which
3537 prevents total scalarization from happening at all. */
3539 static enum total_sra_field_state
3540 total_should_skip_creating_access (struct access *parent,
3541 struct access **last_seen_sibling,
3542 tree type, HOST_WIDE_INT pos,
3543 HOST_WIDE_INT size)
3545 struct access *next_child;
3546 if (!*last_seen_sibling)
3547 next_child = parent->first_child;
3548 else
3549 next_child = (*last_seen_sibling)->next_sibling;
3551 /* First, traverse the chain of siblings until it points to an access with
3552 offset at least equal to POS. Check all skipped accesses whether they
3553 span the POS boundary and if so, return with a failure. */
3554 while (next_child && next_child->offset < pos)
3556 if (next_child->offset + next_child->size > pos)
3557 return TOTAL_FLD_FAILED;
3558 *last_seen_sibling = next_child;
3559 next_child = next_child->next_sibling;
3562 /* Now check whether next_child has exactly the right POS and SIZE and if so,
3563 whether it can represent what we need and can be totally scalarized
3564 itself. */
3565 if (next_child && next_child->offset == pos
3566 && next_child->size == size)
3568 if (!is_gimple_reg_type (next_child->type)
3569 && (!access_and_field_type_match_p (type, next_child->type)
3570 || !totally_scalarize_subtree (next_child)))
3571 return TOTAL_FLD_FAILED;
3573 *last_seen_sibling = next_child;
3574 return TOTAL_FLD_DONE;
3577 /* If the child we're looking at would partially overlap, we just cannot
3578 totally scalarize. */
3579 if (next_child
3580 && next_child->offset < pos + size
3581 && next_child->offset + next_child->size > pos + size)
3582 return TOTAL_FLD_FAILED;
3584 if (is_gimple_reg_type (type))
3586 /* We don't scalarize accesses that are children of other scalar type
3587 accesses, so if we go on and create an access for a register type,
3588 there should not be any pre-existing children. There are rare cases
3589 where the requested type is a vector but we already have register
3590 accesses for all its elements which is equally good. Detect that
3591 situation or whether we need to bail out. */
3593 HOST_WIDE_INT covered = pos;
3594 bool skipping = false;
3595 while (next_child
3596 && next_child->offset + next_child->size <= pos + size)
3598 if (next_child->offset != covered
3599 || !is_gimple_reg_type (next_child->type))
3600 return TOTAL_FLD_FAILED;
3602 covered += next_child->size;
3603 *last_seen_sibling = next_child;
3604 next_child = next_child->next_sibling;
3605 skipping = true;
3608 if (skipping)
3610 if (covered != pos + size)
3611 return TOTAL_FLD_FAILED;
3612 else
3613 return TOTAL_FLD_DONE;
3617 return TOTAL_FLD_CREATE;
3620 /* Go over sub-tree rooted in ROOT and attempt to create scalar accesses
3621 spanning all uncovered areas covered by ROOT, return false if the attempt
3622 failed. All created accesses will have grp_unscalarizable_region set (and
3623 should be ignored if the function returns false). */
3625 static bool
3626 totally_scalarize_subtree (struct access *root)
3628 gcc_checking_assert (!root->grp_unscalarizable_region);
3629 gcc_checking_assert (!is_gimple_reg_type (root->type));
3631 struct access *last_seen_sibling = NULL;
3633 switch (TREE_CODE (root->type))
3635 case RECORD_TYPE:
3636 for (tree fld = TYPE_FIELDS (root->type); fld; fld = DECL_CHAIN (fld))
3637 if (TREE_CODE (fld) == FIELD_DECL)
3639 tree ft = TREE_TYPE (fld);
3640 HOST_WIDE_INT fsize = tree_to_uhwi (DECL_SIZE (fld));
3641 if (!fsize)
3642 continue;
3644 HOST_WIDE_INT pos = root->offset + int_bit_position (fld);
3645 if (pos + fsize > root->offset + root->size)
3646 return false;
3647 enum total_sra_field_state
3648 state = total_should_skip_creating_access (root,
3649 &last_seen_sibling,
3650 ft, pos, fsize);
3651 switch (state)
3653 case TOTAL_FLD_FAILED:
3654 return false;
3655 case TOTAL_FLD_DONE:
3656 continue;
3657 case TOTAL_FLD_CREATE:
3658 break;
3659 default:
3660 gcc_unreachable ();
3663 struct access **p = (last_seen_sibling
3664 ? &last_seen_sibling->next_sibling
3665 : &root->first_child);
3666 tree nref = build3 (COMPONENT_REF, ft, root->expr, fld, NULL_TREE);
3667 struct access *new_child
3668 = create_total_access_and_reshape (root, pos, fsize, ft, nref, p);
3669 if (!new_child)
3670 return false;
3672 if (!is_gimple_reg_type (ft)
3673 && !totally_scalarize_subtree (new_child))
3674 return false;
3675 last_seen_sibling = new_child;
3677 break;
3678 case ARRAY_TYPE:
3680 tree elemtype = TREE_TYPE (root->type);
3681 HOST_WIDE_INT el_size;
3682 offset_int idx, max;
3683 if (!prepare_iteration_over_array_elts (root->type, &el_size,
3684 &idx, &max))
3685 break;
3687 for (HOST_WIDE_INT pos = root->offset;
3688 idx <= max;
3689 pos += el_size, ++idx)
3691 enum total_sra_field_state
3692 state = total_should_skip_creating_access (root,
3693 &last_seen_sibling,
3694 elemtype, pos,
3695 el_size);
3696 switch (state)
3698 case TOTAL_FLD_FAILED:
3699 return false;
3700 case TOTAL_FLD_DONE:
3701 continue;
3702 case TOTAL_FLD_CREATE:
3703 break;
3704 default:
3705 gcc_unreachable ();
3708 struct access **p = (last_seen_sibling
3709 ? &last_seen_sibling->next_sibling
3710 : &root->first_child);
3711 tree nref = build4 (ARRAY_REF, elemtype, root->expr,
3712 wide_int_to_tree (TYPE_DOMAIN (root->type),
3713 idx),
3714 NULL_TREE, NULL_TREE);
3715 struct access *new_child
3716 = create_total_access_and_reshape (root, pos, el_size, elemtype,
3717 nref, p);
3718 if (!new_child)
3719 return false;
3721 if (!is_gimple_reg_type (elemtype)
3722 && !totally_scalarize_subtree (new_child))
3723 return false;
3724 last_seen_sibling = new_child;
3727 break;
3728 default:
3729 gcc_unreachable ();
3731 return true;
3734 /* Get the total total scalarization size limit in the current function. */
3736 unsigned HOST_WIDE_INT
3737 sra_get_max_scalarization_size (void)
3739 bool optimize_speed_p = !optimize_function_for_size_p (cfun);
3740 /* If the user didn't set PARAM_SRA_MAX_SCALARIZATION_SIZE_<...>,
3741 fall back to a target default. */
3742 unsigned HOST_WIDE_INT max_scalarization_size
3743 = get_move_ratio (optimize_speed_p) * UNITS_PER_WORD;
3745 if (optimize_speed_p)
3747 if (OPTION_SET_P (param_sra_max_scalarization_size_speed))
3748 max_scalarization_size = param_sra_max_scalarization_size_speed;
3750 else
3752 if (OPTION_SET_P (param_sra_max_scalarization_size_size))
3753 max_scalarization_size = param_sra_max_scalarization_size_size;
3755 max_scalarization_size *= BITS_PER_UNIT;
3756 return max_scalarization_size;
3759 /* Go through all accesses collected throughout the (intraprocedural) analysis
3760 stage, exclude overlapping ones, identify representatives and build trees
3761 out of them, making decisions about scalarization on the way. Return true
3762 iff there are any to-be-scalarized variables after this stage. */
3764 static bool
3765 analyze_all_variable_accesses (void)
3767 int res = 0;
3768 bitmap tmp = BITMAP_ALLOC (NULL);
3769 bitmap_iterator bi;
3770 unsigned i;
3772 bitmap_copy (tmp, candidate_bitmap);
3773 EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
3775 tree var = candidate (i);
3776 struct access *access;
3778 access = sort_and_splice_var_accesses (var);
3779 if (!access || !build_access_trees (access))
3780 disqualify_candidate (var,
3781 "No or inhibitingly overlapping accesses.");
3784 propagate_all_subaccesses ();
3786 unsigned HOST_WIDE_INT max_scalarization_size
3787 = sra_get_max_scalarization_size ();
3788 EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
3789 if (bitmap_bit_p (should_scalarize_away_bitmap, i)
3790 && !bitmap_bit_p (cannot_scalarize_away_bitmap, i))
3792 tree var = candidate (i);
3793 if (!VAR_P (var))
3794 continue;
3796 if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (var))) > max_scalarization_size)
3798 if (dump_file && (dump_flags & TDF_DETAILS))
3800 fprintf (dump_file, "Too big to totally scalarize: ");
3801 print_generic_expr (dump_file, var);
3802 fprintf (dump_file, " (UID: %u)\n", DECL_UID (var));
3804 continue;
3807 bool all_types_ok = true;
3808 for (struct access *access = get_first_repr_for_decl (var);
3809 access;
3810 access = access->next_grp)
3811 if (!can_totally_scalarize_forest_p (access)
3812 || !totally_scalarizable_type_p (access->type,
3813 constant_decl_p (var),
3814 0, nullptr))
3816 all_types_ok = false;
3817 break;
3819 if (!all_types_ok)
3820 continue;
3822 if (dump_file && (dump_flags & TDF_DETAILS))
3824 fprintf (dump_file, "Will attempt to totally scalarize ");
3825 print_generic_expr (dump_file, var);
3826 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
3828 bool scalarized = true;
3829 for (struct access *access = get_first_repr_for_decl (var);
3830 access;
3831 access = access->next_grp)
3832 if (!is_gimple_reg_type (access->type)
3833 && !totally_scalarize_subtree (access))
3835 scalarized = false;
3836 break;
3839 if (scalarized)
3840 for (struct access *access = get_first_repr_for_decl (var);
3841 access;
3842 access = access->next_grp)
3843 access->grp_total_scalarization = true;
3846 if (flag_checking)
3847 verify_all_sra_access_forests ();
3849 bitmap_copy (tmp, candidate_bitmap);
3850 EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
3852 tree var = candidate (i);
3853 struct access *access = get_first_repr_for_decl (var);
3855 if (analyze_access_trees (access))
3857 res++;
3858 if (dump_file && (dump_flags & TDF_DETAILS))
3860 fprintf (dump_file, "\nAccess trees for ");
3861 print_generic_expr (dump_file, var);
3862 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
3863 dump_access_tree (dump_file, access);
3864 fprintf (dump_file, "\n");
3867 else
3868 disqualify_candidate (var, "No scalar replacements to be created.");
3871 BITMAP_FREE (tmp);
3873 if (res)
3875 statistics_counter_event (cfun, "Scalarized aggregates", res);
3876 return true;
3878 else
3879 return false;
3882 /* Generate statements copying scalar replacements of accesses within a subtree
3883 into or out of AGG. ACCESS, all its children, siblings and their children
3884 are to be processed. AGG is an aggregate type expression (can be a
3885 declaration but does not have to be, it can for example also be a mem_ref or
3886 a series of handled components). TOP_OFFSET is the offset of the processed
3887 subtree which has to be subtracted from offsets of individual accesses to
3888 get corresponding offsets for AGG. If CHUNK_SIZE is non-null, copy only
3889 replacements in the interval <start_offset, start_offset + chunk_size>,
3890 otherwise copy all. GSI is a statement iterator used to place the new
3891 statements. WRITE should be true when the statements should write from AGG
3892 to the replacement and false if vice versa. if INSERT_AFTER is true, new
3893 statements will be added after the current statement in GSI, they will be
3894 added before the statement otherwise. */
3896 static void
3897 generate_subtree_copies (struct access *access, tree agg,
3898 HOST_WIDE_INT top_offset,
3899 HOST_WIDE_INT start_offset, HOST_WIDE_INT chunk_size,
3900 gimple_stmt_iterator *gsi, bool write,
3901 bool insert_after, location_t loc)
3903 /* Never write anything into constant pool decls. See PR70602. */
3904 if (!write && constant_decl_p (agg))
3905 return;
3908 if (chunk_size && access->offset >= start_offset + chunk_size)
3909 return;
3911 if (access->grp_to_be_replaced
3912 && (chunk_size == 0
3913 || access->offset + access->size > start_offset))
3915 tree expr, repl = get_access_replacement (access);
3916 gassign *stmt;
3918 expr = build_ref_for_model (loc, agg, access->offset - top_offset,
3919 access, gsi, insert_after);
3921 if (write)
3923 if (access->grp_partial_lhs)
3924 expr = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
3925 !insert_after,
3926 insert_after ? GSI_NEW_STMT
3927 : GSI_SAME_STMT);
3928 stmt = gimple_build_assign (repl, expr);
3930 else
3932 suppress_warning (repl /* Be more selective! */);
3933 if (access->grp_partial_lhs)
3934 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
3935 !insert_after,
3936 insert_after ? GSI_NEW_STMT
3937 : GSI_SAME_STMT);
3938 stmt = gimple_build_assign (expr, repl);
3940 gimple_set_location (stmt, loc);
3942 if (insert_after)
3943 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
3944 else
3945 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3946 update_stmt (stmt);
3947 sra_stats.subtree_copies++;
3949 else if (write
3950 && access->grp_to_be_debug_replaced
3951 && (chunk_size == 0
3952 || access->offset + access->size > start_offset))
3954 gdebug *ds;
3955 tree drhs = build_debug_ref_for_model (loc, agg,
3956 access->offset - top_offset,
3957 access);
3958 ds = gimple_build_debug_bind (get_access_replacement (access),
3959 drhs, gsi_stmt (*gsi));
3960 if (insert_after)
3961 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
3962 else
3963 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
3966 if (access->first_child)
3967 generate_subtree_copies (access->first_child, agg, top_offset,
3968 start_offset, chunk_size, gsi,
3969 write, insert_after, loc);
3971 access = access->next_sibling;
3973 while (access);
3976 /* Assign zero to all scalar replacements in an access subtree. ACCESS is the
3977 root of the subtree to be processed. GSI is the statement iterator used
3978 for inserting statements which are added after the current statement if
3979 INSERT_AFTER is true or before it otherwise. */
3981 static void
3982 init_subtree_with_zero (struct access *access, gimple_stmt_iterator *gsi,
3983 bool insert_after, location_t loc)
3986 struct access *child;
3988 if (access->grp_to_be_replaced)
3990 gassign *stmt;
3992 stmt = gimple_build_assign (get_access_replacement (access),
3993 build_zero_cst (access->type));
3994 if (insert_after)
3995 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
3996 else
3997 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3998 update_stmt (stmt);
3999 gimple_set_location (stmt, loc);
4001 else if (access->grp_to_be_debug_replaced)
4003 gdebug *ds
4004 = gimple_build_debug_bind (get_access_replacement (access),
4005 build_zero_cst (access->type),
4006 gsi_stmt (*gsi));
4007 if (insert_after)
4008 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
4009 else
4010 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
4013 for (child = access->first_child; child; child = child->next_sibling)
4014 init_subtree_with_zero (child, gsi, insert_after, loc);
4017 /* Clobber all scalar replacements in an access subtree. ACCESS is the
4018 root of the subtree to be processed. GSI is the statement iterator used
4019 for inserting statements which are added after the current statement if
4020 INSERT_AFTER is true or before it otherwise. */
4022 static void
4023 clobber_subtree (struct access *access, gimple_stmt_iterator *gsi,
4024 bool insert_after, location_t loc)
4027 struct access *child;
4029 if (access->grp_to_be_replaced)
4031 tree rep = get_access_replacement (access);
4032 tree clobber = build_clobber (access->type);
4033 gimple *stmt = gimple_build_assign (rep, clobber);
4035 if (insert_after)
4036 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
4037 else
4038 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
4039 update_stmt (stmt);
4040 gimple_set_location (stmt, loc);
4043 for (child = access->first_child; child; child = child->next_sibling)
4044 clobber_subtree (child, gsi, insert_after, loc);
4047 /* Search for an access representative for the given expression EXPR and
4048 return it or NULL if it cannot be found. */
4050 static struct access *
4051 get_access_for_expr (tree expr)
4053 poly_int64 poffset, psize, pmax_size;
4054 HOST_WIDE_INT offset, max_size;
4055 tree base;
4056 bool reverse;
4058 /* FIXME: This should not be necessary but Ada produces V_C_Es with a type of
4059 a different size than the size of its argument and we need the latter
4060 one. */
4061 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
4062 expr = TREE_OPERAND (expr, 0);
4064 base = get_ref_base_and_extent (expr, &poffset, &psize, &pmax_size,
4065 &reverse);
4066 if (!known_size_p (pmax_size)
4067 || !pmax_size.is_constant (&max_size)
4068 || !poffset.is_constant (&offset)
4069 || !DECL_P (base))
4070 return NULL;
4072 if (tree basesize = DECL_SIZE (base))
4074 poly_int64 sz;
4075 if (offset < 0
4076 || !poly_int_tree_p (basesize, &sz)
4077 || known_le (sz, offset))
4078 return NULL;
4081 if (max_size == 0
4082 || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
4083 return NULL;
4085 return get_var_base_offset_size_access (base, offset, max_size);
4088 /* Replace the expression EXPR with a scalar replacement if there is one and
4089 generate other statements to do type conversion or subtree copying if
4090 necessary. WRITE is true if the expression is being written to (it is on a
4091 LHS of a statement or output in an assembly statement). STMT_GSI is used to
4092 place newly created statements before the processed statement, REFRESH_GSI
4093 is used to place them afterwards - unless the processed statement must end a
4094 BB in which case it is placed on the outgoing non-EH edge. REFRESH_GSI and
4095 is then used to continue iteration over the BB. If sra_modify_expr is
4096 called only once with WRITE equal to true on a given statement, both
4097 iterator parameters can point to the same one. */
4099 static bool
4100 sra_modify_expr (tree *expr, bool write, gimple_stmt_iterator *stmt_gsi,
4101 gimple_stmt_iterator *refresh_gsi)
4103 location_t loc;
4104 struct access *access;
4105 tree type, bfr, orig_expr;
4106 bool partial_cplx_access = false;
4108 if (TREE_CODE (*expr) == BIT_FIELD_REF
4109 && (write || !sra_handled_bf_read_p (*expr)))
4111 bfr = *expr;
4112 expr = &TREE_OPERAND (*expr, 0);
4114 else
4115 bfr = NULL_TREE;
4117 if (TREE_CODE (*expr) == REALPART_EXPR || TREE_CODE (*expr) == IMAGPART_EXPR)
4119 expr = &TREE_OPERAND (*expr, 0);
4120 partial_cplx_access = true;
4122 access = get_access_for_expr (*expr);
4123 if (!access)
4124 return false;
4125 type = TREE_TYPE (*expr);
4126 orig_expr = *expr;
4128 loc = gimple_location (gsi_stmt (*stmt_gsi));
4129 gimple_stmt_iterator alt_gsi = gsi_none ();
4130 if (write && stmt_ends_bb_p (gsi_stmt (*stmt_gsi)))
4132 alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*stmt_gsi)));
4133 refresh_gsi = &alt_gsi;
4136 if (access->grp_to_be_replaced)
4138 tree repl = get_access_replacement (access);
4139 /* If we replace a non-register typed access simply use the original
4140 access expression to extract the scalar component afterwards.
4141 This happens if scalarizing a function return value or parameter
4142 like in gcc.c-torture/execute/20041124-1.c, 20050316-1.c and
4143 gcc.c-torture/compile/20011217-1.c.
4145 We also want to use this when accessing a complex or vector which can
4146 be accessed as a different type too, potentially creating a need for
4147 type conversion (see PR42196) and when scalarized unions are involved
4148 in assembler statements (see PR42398). */
4149 if (!bfr && !useless_type_conversion_p (type, access->type))
4151 tree ref;
4153 ref = build_ref_for_model (loc, orig_expr, 0, access, stmt_gsi,
4154 false);
4156 if (partial_cplx_access)
4158 /* VIEW_CONVERT_EXPRs in partial complex access are always fine in
4159 the case of a write because in such case the replacement cannot
4160 be a gimple register. In the case of a load, we have to
4161 differentiate in between a register an non-register
4162 replacement. */
4163 tree t = build1 (VIEW_CONVERT_EXPR, type, repl);
4164 gcc_checking_assert (!write || access->grp_partial_lhs);
4165 if (!access->grp_partial_lhs)
4167 tree tmp = make_ssa_name (type);
4168 gassign *stmt = gimple_build_assign (tmp, t);
4169 /* This is always a read. */
4170 gsi_insert_before (stmt_gsi, stmt, GSI_SAME_STMT);
4171 t = tmp;
4173 *expr = t;
4175 else if (write)
4177 gassign *stmt;
4179 if (access->grp_partial_lhs)
4180 ref = force_gimple_operand_gsi (refresh_gsi, ref, true,
4181 NULL_TREE, false, GSI_NEW_STMT);
4182 stmt = gimple_build_assign (repl, ref);
4183 gimple_set_location (stmt, loc);
4184 gsi_insert_after (refresh_gsi, stmt, GSI_NEW_STMT);
4186 else
4188 gassign *stmt;
4190 if (access->grp_partial_lhs)
4191 repl = force_gimple_operand_gsi (stmt_gsi, repl, true,
4192 NULL_TREE, true,
4193 GSI_SAME_STMT);
4194 stmt = gimple_build_assign (ref, repl);
4195 gimple_set_location (stmt, loc);
4196 gsi_insert_before (stmt_gsi, stmt, GSI_SAME_STMT);
4199 else
4201 /* If we are going to replace a scalar field in a structure with
4202 reverse storage order by a stand-alone scalar, we are going to
4203 effectively byte-swap the scalar and we also need to byte-swap
4204 the portion of it represented by the bit-field. */
4205 if (bfr && REF_REVERSE_STORAGE_ORDER (bfr))
4207 REF_REVERSE_STORAGE_ORDER (bfr) = 0;
4208 TREE_OPERAND (bfr, 2)
4209 = size_binop (MINUS_EXPR, TYPE_SIZE (TREE_TYPE (repl)),
4210 size_binop (PLUS_EXPR, TREE_OPERAND (bfr, 1),
4211 TREE_OPERAND (bfr, 2)));
4214 *expr = repl;
4217 sra_stats.exprs++;
4219 else if (write && access->grp_to_be_debug_replaced)
4221 gdebug *ds = gimple_build_debug_bind (get_access_replacement (access),
4222 NULL_TREE,
4223 gsi_stmt (*stmt_gsi));
4224 gsi_insert_after (stmt_gsi, ds, GSI_NEW_STMT);
4227 if (access->first_child && !TREE_READONLY (access->base))
4229 HOST_WIDE_INT start_offset, chunk_size;
4230 if (bfr
4231 && tree_fits_uhwi_p (TREE_OPERAND (bfr, 1))
4232 && tree_fits_uhwi_p (TREE_OPERAND (bfr, 2)))
4234 chunk_size = tree_to_uhwi (TREE_OPERAND (bfr, 1));
4235 start_offset = access->offset
4236 + tree_to_uhwi (TREE_OPERAND (bfr, 2));
4238 else
4239 start_offset = chunk_size = 0;
4241 generate_subtree_copies (access->first_child, orig_expr, access->offset,
4242 start_offset, chunk_size,
4243 write ? refresh_gsi : stmt_gsi,
4244 write, write, loc);
4246 return true;
4249 /* If EXPR, which must be a call argument, is an ADDR_EXPR, generate writes and
4250 reads from its base before and after the call statement given in CALL_GSI
4251 and return true if any copying took place. Otherwise call sra_modify_expr
4252 on EXPR and return its value. FLAGS is what the gimple_call_arg_flags
4253 return for the given parameter. */
4255 static bool
4256 sra_modify_call_arg (tree *expr, gimple_stmt_iterator *call_gsi,
4257 gimple_stmt_iterator *refresh_gsi, int flags)
4259 if (TREE_CODE (*expr) != ADDR_EXPR)
4260 return sra_modify_expr (expr, false, call_gsi, refresh_gsi);
4262 if (flags & EAF_UNUSED)
4263 return false;
4265 tree base = get_base_address (TREE_OPERAND (*expr, 0));
4266 if (!DECL_P (base))
4267 return false;
4268 struct access *access = get_access_for_expr (base);
4269 if (!access)
4270 return false;
4272 gimple *stmt = gsi_stmt (*call_gsi);
4273 location_t loc = gimple_location (stmt);
4274 generate_subtree_copies (access, base, 0, 0, 0, call_gsi, false, false,
4275 loc);
4277 if (flags & EAF_NO_DIRECT_CLOBBER)
4278 return true;
4280 if (!stmt_ends_bb_p (stmt))
4281 generate_subtree_copies (access, base, 0, 0, 0, refresh_gsi, true,
4282 true, loc);
4283 else
4285 edge e;
4286 edge_iterator ei;
4287 FOR_EACH_EDGE (e, ei, gsi_bb (*call_gsi)->succs)
4289 gimple_stmt_iterator alt_gsi = gsi_start_edge (e);
4290 generate_subtree_copies (access, base, 0, 0, 0, &alt_gsi, true,
4291 true, loc);
4294 return true;
4297 /* Where scalar replacements of the RHS have been written to when a replacement
4298 of a LHS of an assigments cannot be direclty loaded from a replacement of
4299 the RHS. */
4300 enum unscalarized_data_handling { SRA_UDH_NONE, /* Nothing done so far. */
4301 SRA_UDH_RIGHT, /* Data flushed to the RHS. */
4302 SRA_UDH_LEFT }; /* Data flushed to the LHS. */
4304 struct subreplacement_assignment_data
4306 /* Offset of the access representing the lhs of the assignment. */
4307 HOST_WIDE_INT left_offset;
4309 /* LHS and RHS of the original assignment. */
4310 tree assignment_lhs, assignment_rhs;
4312 /* Access representing the rhs of the whole assignment. */
4313 struct access *top_racc;
4315 /* Stmt iterator used for statement insertions after the original assignment.
4316 It points to the main GSI used to traverse a BB during function body
4317 modification. */
4318 gimple_stmt_iterator *new_gsi;
4320 /* Stmt iterator used for statement insertions before the original
4321 assignment. Keeps on pointing to the original statement. */
4322 gimple_stmt_iterator old_gsi;
4324 /* Location of the assignment. */
4325 location_t loc;
4327 /* Keeps the information whether we have needed to refresh replacements of
4328 the LHS and from which side of the assignments this takes place. */
4329 enum unscalarized_data_handling refreshed;
4332 /* Store all replacements in the access tree rooted in TOP_RACC either to their
4333 base aggregate if there are unscalarized data or directly to LHS of the
4334 statement that is pointed to by GSI otherwise. */
4336 static void
4337 handle_unscalarized_data_in_subtree (struct subreplacement_assignment_data *sad)
4339 tree src;
4340 /* If the RHS is a load from a constant, we do not need to (and must not)
4341 flush replacements to it and can use it directly as if we did. */
4342 if (TREE_READONLY (sad->top_racc->base))
4344 sad->refreshed = SRA_UDH_RIGHT;
4345 return;
4347 if (sad->top_racc->grp_unscalarized_data)
4349 src = sad->assignment_rhs;
4350 sad->refreshed = SRA_UDH_RIGHT;
4352 else
4354 src = sad->assignment_lhs;
4355 sad->refreshed = SRA_UDH_LEFT;
4357 generate_subtree_copies (sad->top_racc->first_child, src,
4358 sad->top_racc->offset, 0, 0,
4359 &sad->old_gsi, false, false, sad->loc);
4362 /* Try to generate statements to load all sub-replacements in an access subtree
4363 formed by children of LACC from scalar replacements in the SAD->top_racc
4364 subtree. If that is not possible, refresh the SAD->top_racc base aggregate
4365 and load the accesses from it. */
4367 static void
4368 load_assign_lhs_subreplacements (struct access *lacc,
4369 struct subreplacement_assignment_data *sad)
4371 for (lacc = lacc->first_child; lacc; lacc = lacc->next_sibling)
4373 HOST_WIDE_INT offset;
4374 offset = lacc->offset - sad->left_offset + sad->top_racc->offset;
4376 if (lacc->grp_to_be_replaced)
4378 struct access *racc;
4379 gassign *stmt;
4380 tree rhs;
4382 racc = find_access_in_subtree (sad->top_racc, offset, lacc->size);
4383 if (racc && racc->grp_to_be_replaced)
4385 rhs = get_access_replacement (racc);
4386 bool vce = false;
4387 if (!useless_type_conversion_p (lacc->type, racc->type))
4389 rhs = fold_build1_loc (sad->loc, VIEW_CONVERT_EXPR,
4390 lacc->type, rhs);
4391 vce = true;
4394 if (lacc->grp_partial_lhs && (vce || racc->grp_partial_lhs))
4395 rhs = force_gimple_operand_gsi (&sad->old_gsi, rhs, true,
4396 NULL_TREE, true, GSI_SAME_STMT);
4398 else
4400 /* No suitable access on the right hand side, need to load from
4401 the aggregate. See if we have to update it first... */
4402 if (sad->refreshed == SRA_UDH_NONE)
4403 handle_unscalarized_data_in_subtree (sad);
4405 if (sad->refreshed == SRA_UDH_LEFT)
4406 rhs = build_ref_for_model (sad->loc, sad->assignment_lhs,
4407 lacc->offset - sad->left_offset,
4408 lacc, sad->new_gsi, true);
4409 else
4410 rhs = build_ref_for_model (sad->loc, sad->assignment_rhs,
4411 lacc->offset - sad->left_offset,
4412 lacc, sad->new_gsi, true);
4413 if (lacc->grp_partial_lhs)
4414 rhs = force_gimple_operand_gsi (sad->new_gsi,
4415 rhs, true, NULL_TREE,
4416 false, GSI_NEW_STMT);
4419 stmt = gimple_build_assign (get_access_replacement (lacc), rhs);
4420 gsi_insert_after (sad->new_gsi, stmt, GSI_NEW_STMT);
4421 gimple_set_location (stmt, sad->loc);
4422 update_stmt (stmt);
4423 sra_stats.subreplacements++;
4425 else
4427 if (sad->refreshed == SRA_UDH_NONE
4428 && lacc->grp_read && !lacc->grp_covered)
4429 handle_unscalarized_data_in_subtree (sad);
4431 if (lacc && lacc->grp_to_be_debug_replaced)
4433 gdebug *ds;
4434 tree drhs;
4435 struct access *racc = find_access_in_subtree (sad->top_racc,
4436 offset,
4437 lacc->size);
4439 if (racc && racc->grp_to_be_replaced)
4441 if (racc->grp_write || constant_decl_p (racc->base))
4442 drhs = get_access_replacement (racc);
4443 else
4444 drhs = NULL;
4446 else if (sad->refreshed == SRA_UDH_LEFT)
4447 drhs = build_debug_ref_for_model (sad->loc, lacc->base,
4448 lacc->offset, lacc);
4449 else if (sad->refreshed == SRA_UDH_RIGHT)
4450 drhs = build_debug_ref_for_model (sad->loc, sad->top_racc->base,
4451 offset, lacc);
4452 else
4453 drhs = NULL_TREE;
4454 if (drhs
4455 && !useless_type_conversion_p (lacc->type, TREE_TYPE (drhs)))
4456 drhs = fold_build1_loc (sad->loc, VIEW_CONVERT_EXPR,
4457 lacc->type, drhs);
4458 ds = gimple_build_debug_bind (get_access_replacement (lacc),
4459 drhs, gsi_stmt (sad->old_gsi));
4460 gsi_insert_after (sad->new_gsi, ds, GSI_NEW_STMT);
4464 if (lacc->first_child)
4465 load_assign_lhs_subreplacements (lacc, sad);
4469 /* Result code for SRA assignment modification. */
4470 enum assignment_mod_result { SRA_AM_NONE, /* nothing done for the stmt */
4471 SRA_AM_MODIFIED, /* stmt changed but not
4472 removed */
4473 SRA_AM_REMOVED }; /* stmt eliminated */
4475 /* Modify assignments with a CONSTRUCTOR on their RHS. STMT contains a pointer
4476 to the assignment and GSI is the statement iterator pointing at it. Returns
4477 the same values as sra_modify_assign. */
4479 static enum assignment_mod_result
4480 sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
4482 tree lhs = gimple_assign_lhs (stmt);
4483 struct access *acc = get_access_for_expr (lhs);
4484 if (!acc)
4485 return SRA_AM_NONE;
4486 location_t loc = gimple_location (stmt);
4488 if (gimple_clobber_p (stmt))
4490 /* Clobber the replacement variable. */
4491 clobber_subtree (acc, gsi, !acc->grp_covered, loc);
4492 /* Remove clobbers of fully scalarized variables, they are dead. */
4493 if (acc->grp_covered)
4495 unlink_stmt_vdef (stmt);
4496 gsi_remove (gsi, true);
4497 release_defs (stmt);
4498 return SRA_AM_REMOVED;
4500 else
4501 return SRA_AM_MODIFIED;
4504 if (CONSTRUCTOR_NELTS (gimple_assign_rhs1 (stmt)) > 0)
4506 /* I have never seen this code path trigger but if it can happen the
4507 following should handle it gracefully. */
4508 if (access_has_children_p (acc))
4509 generate_subtree_copies (acc->first_child, lhs, acc->offset, 0, 0, gsi,
4510 true, true, loc);
4511 return SRA_AM_MODIFIED;
4514 if (acc->grp_covered)
4516 init_subtree_with_zero (acc, gsi, false, loc);
4517 unlink_stmt_vdef (stmt);
4518 gsi_remove (gsi, true);
4519 release_defs (stmt);
4520 return SRA_AM_REMOVED;
4522 else
4524 init_subtree_with_zero (acc, gsi, true, loc);
4525 return SRA_AM_MODIFIED;
4529 /* Create and return a new suitable default definition SSA_NAME for RACC which
4530 is an access describing an uninitialized part of an aggregate that is being
4531 loaded. REG_TREE is used instead of the actual RACC type if that is not of
4532 a gimple register type. */
4534 static tree
4535 get_repl_default_def_ssa_name (struct access *racc, tree reg_type)
4537 gcc_checking_assert (!racc->grp_to_be_replaced
4538 && !racc->grp_to_be_debug_replaced);
4539 if (!racc->replacement_decl)
4540 racc->replacement_decl = create_access_replacement (racc, reg_type);
4541 return get_or_create_ssa_default_def (cfun, racc->replacement_decl);
4545 /* Generate statements to call .DEFERRED_INIT to initialize scalar replacements
4546 of accesses within a subtree ACCESS; all its children, siblings and their
4547 children are to be processed.
4548 GSI is a statement iterator used to place the new statements. */
4549 static void
4550 generate_subtree_deferred_init (struct access *access,
4551 tree init_type,
4552 tree decl_name,
4553 gimple_stmt_iterator *gsi,
4554 location_t loc)
4558 if (access->grp_to_be_replaced)
4560 tree repl = get_access_replacement (access);
4561 gimple *call
4562 = gimple_build_call_internal (IFN_DEFERRED_INIT, 3,
4563 TYPE_SIZE_UNIT (TREE_TYPE (repl)),
4564 init_type, decl_name);
4565 gimple_call_set_lhs (call, repl);
4566 gsi_insert_before (gsi, call, GSI_SAME_STMT);
4567 update_stmt (call);
4568 gimple_set_location (call, loc);
4569 sra_stats.subtree_deferred_init++;
4571 if (access->first_child)
4572 generate_subtree_deferred_init (access->first_child, init_type,
4573 decl_name, gsi, loc);
4575 access = access ->next_sibling;
4577 while (access);
4580 /* For a call to .DEFERRED_INIT:
4581 var = .DEFERRED_INIT (size_of_var, init_type, name_of_var);
4582 examine the LHS variable VAR and replace it with a scalar replacement if
4583 there is one, also replace the RHS call to a call to .DEFERRED_INIT of
4584 the corresponding scalar relacement variable. Examine the subtree and
4585 do the scalar replacements in the subtree too. STMT is the call, GSI is
4586 the statment iterator to place newly created statement. */
4588 static enum assignment_mod_result
4589 sra_modify_deferred_init (gimple *stmt, gimple_stmt_iterator *gsi)
4591 tree lhs = gimple_call_lhs (stmt);
4592 tree init_type = gimple_call_arg (stmt, 1);
4593 tree decl_name = gimple_call_arg (stmt, 2);
4595 struct access *lhs_access = get_access_for_expr (lhs);
4596 if (!lhs_access)
4597 return SRA_AM_NONE;
4599 location_t loc = gimple_location (stmt);
4601 if (lhs_access->grp_to_be_replaced)
4603 tree lhs_repl = get_access_replacement (lhs_access);
4604 gimple_call_set_lhs (stmt, lhs_repl);
4605 tree arg0_repl = TYPE_SIZE_UNIT (TREE_TYPE (lhs_repl));
4606 gimple_call_set_arg (stmt, 0, arg0_repl);
4607 sra_stats.deferred_init++;
4608 gcc_assert (!lhs_access->first_child);
4609 return SRA_AM_MODIFIED;
4612 if (lhs_access->first_child)
4613 generate_subtree_deferred_init (lhs_access->first_child,
4614 init_type, decl_name, gsi, loc);
4615 if (lhs_access->grp_covered)
4617 unlink_stmt_vdef (stmt);
4618 gsi_remove (gsi, true);
4619 release_defs (stmt);
4620 return SRA_AM_REMOVED;
4623 return SRA_AM_MODIFIED;
4626 /* Examine both sides of the assignment statement pointed to by STMT, replace
4627 them with a scalare replacement if there is one and generate copying of
4628 replacements if scalarized aggregates have been used in the assignment. GSI
4629 is used to hold generated statements for type conversions and subtree
4630 copying. */
4632 static enum assignment_mod_result
4633 sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi)
4635 struct access *lacc, *racc;
4636 tree lhs, rhs;
4637 bool modify_this_stmt = false;
4638 bool force_gimple_rhs = false;
4639 location_t loc;
4640 gimple_stmt_iterator orig_gsi = *gsi;
4642 if (!gimple_assign_single_p (stmt))
4643 return SRA_AM_NONE;
4644 lhs = gimple_assign_lhs (stmt);
4645 rhs = gimple_assign_rhs1 (stmt);
4647 if (TREE_CODE (rhs) == CONSTRUCTOR)
4648 return sra_modify_constructor_assign (stmt, gsi);
4650 if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (lhs) == REALPART_EXPR
4651 || TREE_CODE (rhs) == IMAGPART_EXPR || TREE_CODE (lhs) == IMAGPART_EXPR
4652 || (TREE_CODE (rhs) == BIT_FIELD_REF && !sra_handled_bf_read_p (rhs))
4653 || TREE_CODE (lhs) == BIT_FIELD_REF)
4655 modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (stmt),
4656 false, gsi, gsi);
4657 modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (stmt),
4658 true, gsi, gsi);
4659 return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
4662 lacc = get_access_for_expr (lhs);
4663 racc = get_access_for_expr (rhs);
4664 if (!lacc && !racc)
4665 return SRA_AM_NONE;
4666 /* Avoid modifying initializations of constant-pool replacements. */
4667 if (racc && (racc->replacement_decl == lhs))
4668 return SRA_AM_NONE;
4670 loc = gimple_location (stmt);
4671 if (lacc && lacc->grp_to_be_replaced)
4673 lhs = get_access_replacement (lacc);
4674 gimple_assign_set_lhs (stmt, lhs);
4675 modify_this_stmt = true;
4676 if (lacc->grp_partial_lhs)
4677 force_gimple_rhs = true;
4678 sra_stats.exprs++;
4681 if (racc && racc->grp_to_be_replaced)
4683 rhs = get_access_replacement (racc);
4684 modify_this_stmt = true;
4685 if (racc->grp_partial_lhs)
4686 force_gimple_rhs = true;
4687 sra_stats.exprs++;
4689 else if (racc
4690 && !racc->grp_unscalarized_data
4691 && !racc->grp_unscalarizable_region
4692 && TREE_CODE (lhs) == SSA_NAME
4693 && !access_has_replacements_p (racc))
4695 rhs = get_repl_default_def_ssa_name (racc, TREE_TYPE (lhs));
4696 modify_this_stmt = true;
4697 sra_stats.exprs++;
4700 if (modify_this_stmt
4701 && !useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
4703 /* If we can avoid creating a VIEW_CONVERT_EXPR, then do so.
4704 ??? This should move to fold_stmt which we simply should
4705 call after building a VIEW_CONVERT_EXPR here. */
4706 if (AGGREGATE_TYPE_P (TREE_TYPE (lhs))
4707 && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (lhs)) == racc->reverse
4708 && !contains_bitfld_component_ref_p (lhs))
4710 lhs = build_ref_for_model (loc, lhs, 0, racc, gsi, false);
4711 gimple_assign_set_lhs (stmt, lhs);
4713 else if (lacc
4714 && AGGREGATE_TYPE_P (TREE_TYPE (rhs))
4715 && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (rhs)) == lacc->reverse
4716 && !contains_vce_or_bfcref_p (rhs))
4717 rhs = build_ref_for_model (loc, rhs, 0, lacc, gsi, false);
4719 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
4721 rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), rhs);
4722 if (is_gimple_reg_type (TREE_TYPE (lhs))
4723 && TREE_CODE (lhs) != SSA_NAME)
4724 force_gimple_rhs = true;
4728 if (lacc && lacc->grp_to_be_debug_replaced)
4730 tree dlhs = get_access_replacement (lacc);
4731 tree drhs = unshare_expr (rhs);
4732 if (!useless_type_conversion_p (TREE_TYPE (dlhs), TREE_TYPE (drhs)))
4734 if (AGGREGATE_TYPE_P (TREE_TYPE (drhs))
4735 && !contains_vce_or_bfcref_p (drhs))
4736 drhs = build_debug_ref_for_model (loc, drhs, 0, lacc);
4737 if (drhs
4738 && !useless_type_conversion_p (TREE_TYPE (dlhs),
4739 TREE_TYPE (drhs)))
4740 drhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
4741 TREE_TYPE (dlhs), drhs);
4743 gdebug *ds = gimple_build_debug_bind (dlhs, drhs, stmt);
4744 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
4747 /* From this point on, the function deals with assignments in between
4748 aggregates when at least one has scalar reductions of some of its
4749 components. There are three possible scenarios: Both the LHS and RHS have
4750 to-be-scalarized components, 2) only the RHS has or 3) only the LHS has.
4752 In the first case, we would like to load the LHS components from RHS
4753 components whenever possible. If that is not possible, we would like to
4754 read it directly from the RHS (after updating it by storing in it its own
4755 components). If there are some necessary unscalarized data in the LHS,
4756 those will be loaded by the original assignment too. If neither of these
4757 cases happen, the original statement can be removed. Most of this is done
4758 by load_assign_lhs_subreplacements.
4760 In the second case, we would like to store all RHS scalarized components
4761 directly into LHS and if they cover the aggregate completely, remove the
4762 statement too. In the third case, we want the LHS components to be loaded
4763 directly from the RHS (DSE will remove the original statement if it
4764 becomes redundant).
4766 This is a bit complex but manageable when types match and when unions do
4767 not cause confusion in a way that we cannot really load a component of LHS
4768 from the RHS or vice versa (the access representing this level can have
4769 subaccesses that are accessible only through a different union field at a
4770 higher level - different from the one used in the examined expression).
4771 Unions are fun.
4773 Therefore, I specially handle a fourth case, happening when there is a
4774 specific type cast or it is impossible to locate a scalarized subaccess on
4775 the other side of the expression. If that happens, I simply "refresh" the
4776 RHS by storing in it is scalarized components leave the original statement
4777 there to do the copying and then load the scalar replacements of the LHS.
4778 This is what the first branch does. */
4780 if (modify_this_stmt
4781 || gimple_has_volatile_ops (stmt)
4782 || contains_vce_or_bfcref_p (rhs)
4783 || contains_vce_or_bfcref_p (lhs)
4784 || stmt_ends_bb_p (stmt))
4786 /* No need to copy into a constant, it comes pre-initialized. */
4787 if (access_has_children_p (racc) && !TREE_READONLY (racc->base))
4788 generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0,
4789 gsi, false, false, loc);
4790 if (access_has_children_p (lacc))
4792 gimple_stmt_iterator alt_gsi = gsi_none ();
4793 if (stmt_ends_bb_p (stmt))
4795 alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi)));
4796 gsi = &alt_gsi;
4798 generate_subtree_copies (lacc->first_child, lhs, lacc->offset, 0, 0,
4799 gsi, true, true, loc);
4801 sra_stats.separate_lhs_rhs_handling++;
4803 /* This gimplification must be done after generate_subtree_copies,
4804 lest we insert the subtree copies in the middle of the gimplified
4805 sequence. */
4806 if (force_gimple_rhs)
4807 rhs = force_gimple_operand_gsi (&orig_gsi, rhs, true, NULL_TREE,
4808 true, GSI_SAME_STMT);
4809 if (gimple_assign_rhs1 (stmt) != rhs)
4811 modify_this_stmt = true;
4812 gimple_assign_set_rhs_from_tree (&orig_gsi, rhs);
4813 gcc_assert (stmt == gsi_stmt (orig_gsi));
4816 return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
4818 else
4820 if (access_has_children_p (lacc)
4821 && access_has_children_p (racc)
4822 /* When an access represents an unscalarizable region, it usually
4823 represents accesses with variable offset and thus must not be used
4824 to generate new memory accesses. */
4825 && !lacc->grp_unscalarizable_region
4826 && !racc->grp_unscalarizable_region)
4828 struct subreplacement_assignment_data sad;
4830 sad.left_offset = lacc->offset;
4831 sad.assignment_lhs = lhs;
4832 sad.assignment_rhs = rhs;
4833 sad.top_racc = racc;
4834 sad.old_gsi = *gsi;
4835 sad.new_gsi = gsi;
4836 sad.loc = gimple_location (stmt);
4837 sad.refreshed = SRA_UDH_NONE;
4839 if (lacc->grp_read && !lacc->grp_covered)
4840 handle_unscalarized_data_in_subtree (&sad);
4842 load_assign_lhs_subreplacements (lacc, &sad);
4843 if (sad.refreshed != SRA_UDH_RIGHT)
4845 gsi_next (gsi);
4846 unlink_stmt_vdef (stmt);
4847 gsi_remove (&sad.old_gsi, true);
4848 release_defs (stmt);
4849 sra_stats.deleted++;
4850 return SRA_AM_REMOVED;
4853 else
4855 if (access_has_children_p (racc)
4856 && !racc->grp_unscalarized_data
4857 && TREE_CODE (lhs) != SSA_NAME)
4859 if (dump_file)
4861 fprintf (dump_file, "Removing load: ");
4862 print_gimple_stmt (dump_file, stmt, 0);
4864 generate_subtree_copies (racc->first_child, lhs,
4865 racc->offset, 0, 0, gsi,
4866 false, false, loc);
4867 gcc_assert (stmt == gsi_stmt (*gsi));
4868 unlink_stmt_vdef (stmt);
4869 gsi_remove (gsi, true);
4870 release_defs (stmt);
4871 sra_stats.deleted++;
4872 return SRA_AM_REMOVED;
4874 /* Restore the aggregate RHS from its components so the
4875 prevailing aggregate copy does the right thing. */
4876 if (access_has_children_p (racc) && !TREE_READONLY (racc->base))
4877 generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0,
4878 gsi, false, false, loc);
4879 /* Re-load the components of the aggregate copy destination.
4880 But use the RHS aggregate to load from to expose more
4881 optimization opportunities. */
4882 if (access_has_children_p (lacc))
4884 generate_subtree_copies (lacc->first_child, rhs, lacc->offset,
4885 0, 0, gsi, true, true, loc);
4886 if (lacc->grp_covered)
4888 unlink_stmt_vdef (stmt);
4889 gsi_remove (& orig_gsi, true);
4890 release_defs (stmt);
4891 sra_stats.deleted++;
4892 return SRA_AM_REMOVED;
4897 return SRA_AM_NONE;
4901 /* Set any scalar replacements of values in the constant pool to the initial
4902 value of the constant. (Constant-pool decls like *.LC0 have effectively
4903 been initialized before the program starts, we must do the same for their
4904 replacements.) Thus, we output statements like 'SR.1 = *.LC0[0];' into
4905 the function's entry block. */
4907 static void
4908 initialize_constant_pool_replacements (void)
4910 gimple_seq seq = NULL;
4911 gimple_stmt_iterator gsi = gsi_start (seq);
4912 bitmap_iterator bi;
4913 unsigned i;
4915 EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
4917 tree var = candidate (i);
4918 if (!constant_decl_p (var))
4919 continue;
4921 struct access *access = get_first_repr_for_decl (var);
4923 while (access)
4925 if (access->replacement_decl)
4927 gassign *stmt
4928 = gimple_build_assign (get_access_replacement (access),
4929 unshare_expr (access->expr));
4930 if (dump_file && (dump_flags & TDF_DETAILS))
4932 fprintf (dump_file, "Generating constant initializer: ");
4933 print_gimple_stmt (dump_file, stmt, 0);
4934 fprintf (dump_file, "\n");
4936 gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
4937 update_stmt (stmt);
4940 if (access->first_child)
4941 access = access->first_child;
4942 else if (access->next_sibling)
4943 access = access->next_sibling;
4944 else
4946 while (access->parent && !access->next_sibling)
4947 access = access->parent;
4948 if (access->next_sibling)
4949 access = access->next_sibling;
4950 else
4951 access = access->next_grp;
4956 seq = gsi_seq (gsi);
4957 if (seq)
4958 gsi_insert_seq_on_edge_immediate (
4959 single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
4962 /* Traverse the function body and all modifications as decided in
4963 analyze_all_variable_accesses. Return true iff the CFG has been
4964 changed. */
4966 static bool
4967 sra_modify_function_body (void)
4969 bool cfg_changed = false;
4970 basic_block bb;
4972 initialize_constant_pool_replacements ();
4974 FOR_EACH_BB_FN (bb, cfun)
4976 gimple_stmt_iterator gsi = gsi_start_bb (bb);
4977 while (!gsi_end_p (gsi))
4979 gimple *stmt = gsi_stmt (gsi);
4980 enum assignment_mod_result assign_result;
4981 bool modified = false, deleted = false;
4982 tree *t;
4983 unsigned i;
4985 switch (gimple_code (stmt))
4987 case GIMPLE_RETURN:
4988 t = gimple_return_retval_ptr (as_a <greturn *> (stmt));
4989 if (*t != NULL_TREE)
4990 modified |= sra_modify_expr (t, false, &gsi, &gsi);
4991 break;
4993 case GIMPLE_ASSIGN:
4994 assign_result = sra_modify_assign (stmt, &gsi);
4995 modified |= assign_result == SRA_AM_MODIFIED;
4996 deleted = assign_result == SRA_AM_REMOVED;
4997 break;
4999 case GIMPLE_CALL:
5000 /* Handle calls to .DEFERRED_INIT specially. */
5001 if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
5003 assign_result = sra_modify_deferred_init (stmt, &gsi);
5004 modified |= assign_result == SRA_AM_MODIFIED;
5005 deleted = assign_result == SRA_AM_REMOVED;
5007 else
5009 gcall *call = as_a <gcall *> (stmt);
5010 gimple_stmt_iterator call_gsi = gsi;
5012 /* Operands must be processed before the lhs. */
5013 for (i = 0; i < gimple_call_num_args (call); i++)
5015 int flags = gimple_call_arg_flags (call, i);
5016 t = gimple_call_arg_ptr (call, i);
5017 modified |= sra_modify_call_arg (t, &call_gsi, &gsi, flags);
5019 if (gimple_call_chain (call))
5021 t = gimple_call_chain_ptr (call);
5022 int flags = gimple_call_static_chain_flags (call);
5023 modified |= sra_modify_call_arg (t, &call_gsi, &gsi,
5024 flags);
5026 if (gimple_call_lhs (call))
5028 t = gimple_call_lhs_ptr (call);
5029 modified |= sra_modify_expr (t, true, &call_gsi, &gsi);
5032 break;
5034 case GIMPLE_ASM:
5036 gimple_stmt_iterator stmt_gsi = gsi;
5037 gasm *asm_stmt = as_a <gasm *> (stmt);
5038 for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
5040 t = &TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
5041 modified |= sra_modify_expr (t, false, &stmt_gsi, &gsi);
5043 for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
5045 t = &TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
5046 modified |= sra_modify_expr (t, true, &stmt_gsi, &gsi);
5049 break;
5051 default:
5052 break;
5055 if (modified)
5057 update_stmt (stmt);
5058 if (maybe_clean_eh_stmt (stmt)
5059 && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
5060 cfg_changed = true;
5062 if (!deleted)
5063 gsi_next (&gsi);
5067 gsi_commit_edge_inserts ();
5068 return cfg_changed;
5071 /* Generate statements initializing scalar replacements of parts of function
5072 parameters. */
5074 static void
5075 initialize_parameter_reductions (void)
5077 gimple_stmt_iterator gsi;
5078 gimple_seq seq = NULL;
5079 tree parm;
5081 gsi = gsi_start (seq);
5082 for (parm = DECL_ARGUMENTS (current_function_decl);
5083 parm;
5084 parm = DECL_CHAIN (parm))
5086 vec<access_p> *access_vec;
5087 struct access *access;
5089 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
5090 continue;
5091 access_vec = get_base_access_vector (parm);
5092 if (!access_vec)
5093 continue;
5095 for (access = (*access_vec)[0];
5096 access;
5097 access = access->next_grp)
5098 generate_subtree_copies (access, parm, 0, 0, 0, &gsi, true, true,
5099 EXPR_LOCATION (parm));
5102 seq = gsi_seq (gsi);
5103 if (seq)
5104 gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
5107 /* The "main" function of intraprocedural SRA passes. Runs the analysis and if
5108 it reveals there are components of some aggregates to be scalarized, it runs
5109 the required transformations. */
5110 static unsigned int
5111 perform_intra_sra (void)
5113 int ret = 0;
5114 sra_initialize ();
5116 if (!find_var_candidates ())
5117 goto out;
5119 if (!scan_function ())
5120 goto out;
5122 if (!analyze_all_variable_accesses ())
5123 goto out;
5125 if (sra_modify_function_body ())
5126 ret = TODO_update_ssa | TODO_cleanup_cfg;
5127 else
5128 ret = TODO_update_ssa;
5129 initialize_parameter_reductions ();
5131 statistics_counter_event (cfun, "Scalar replacements created",
5132 sra_stats.replacements);
5133 statistics_counter_event (cfun, "Modified expressions", sra_stats.exprs);
5134 statistics_counter_event (cfun, "Subtree copy stmts",
5135 sra_stats.subtree_copies);
5136 statistics_counter_event (cfun, "Subreplacement stmts",
5137 sra_stats.subreplacements);
5138 statistics_counter_event (cfun, "Deleted stmts", sra_stats.deleted);
5139 statistics_counter_event (cfun, "Separate LHS and RHS handling",
5140 sra_stats.separate_lhs_rhs_handling);
5142 out:
5143 sra_deinitialize ();
5144 return ret;
5147 /* Perform early intraprocedural SRA. */
5148 static unsigned int
5149 early_intra_sra (void)
5151 sra_mode = SRA_MODE_EARLY_INTRA;
5152 return perform_intra_sra ();
5155 /* Perform "late" intraprocedural SRA. */
5156 static unsigned int
5157 late_intra_sra (void)
5159 sra_mode = SRA_MODE_INTRA;
5160 return perform_intra_sra ();
5164 static bool
5165 gate_intra_sra (void)
5167 return flag_tree_sra != 0 && dbg_cnt (tree_sra);
5171 namespace {
5173 const pass_data pass_data_sra_early =
5175 GIMPLE_PASS, /* type */
5176 "esra", /* name */
5177 OPTGROUP_NONE, /* optinfo_flags */
5178 TV_TREE_SRA, /* tv_id */
5179 ( PROP_cfg | PROP_ssa ), /* properties_required */
5180 0, /* properties_provided */
5181 0, /* properties_destroyed */
5182 0, /* todo_flags_start */
5183 TODO_update_ssa, /* todo_flags_finish */
5186 class pass_sra_early : public gimple_opt_pass
5188 public:
5189 pass_sra_early (gcc::context *ctxt)
5190 : gimple_opt_pass (pass_data_sra_early, ctxt)
5193 /* opt_pass methods: */
5194 bool gate (function *) final override { return gate_intra_sra (); }
5195 unsigned int execute (function *) final override
5197 return early_intra_sra ();
5200 }; // class pass_sra_early
5202 } // anon namespace
5204 gimple_opt_pass *
5205 make_pass_sra_early (gcc::context *ctxt)
5207 return new pass_sra_early (ctxt);
5210 namespace {
5212 const pass_data pass_data_sra =
5214 GIMPLE_PASS, /* type */
5215 "sra", /* name */
5216 OPTGROUP_NONE, /* optinfo_flags */
5217 TV_TREE_SRA, /* tv_id */
5218 ( PROP_cfg | PROP_ssa ), /* properties_required */
5219 0, /* properties_provided */
5220 0, /* properties_destroyed */
5221 TODO_update_address_taken, /* todo_flags_start */
5222 TODO_update_ssa, /* todo_flags_finish */
5225 class pass_sra : public gimple_opt_pass
5227 public:
5228 pass_sra (gcc::context *ctxt)
5229 : gimple_opt_pass (pass_data_sra, ctxt)
5232 /* opt_pass methods: */
5233 bool gate (function *) final override { return gate_intra_sra (); }
5234 unsigned int execute (function *) final override { return late_intra_sra (); }
5236 }; // class pass_sra
5238 } // anon namespace
5240 gimple_opt_pass *
5241 make_pass_sra (gcc::context *ctxt)
5243 return new pass_sra (ctxt);
5247 /* If type T cannot be totally scalarized, return false. Otherwise return true
5248 and push to the vector within PC offsets and lengths of all padding in the
5249 type as total scalarization would encounter it. */
5251 static bool
5252 check_ts_and_push_padding_to_vec (tree type, sra_padding_collecting *pc)
5254 if (!totally_scalarizable_type_p (type, true /* optimistic value */,
5255 0, pc))
5256 return false;
5258 pc->record_padding (tree_to_shwi (TYPE_SIZE (type)));
5259 return true;
5262 /* Given two types in an assignment, return true either if any one cannot be
5263 totally scalarized or if they have padding (i.e. not copied bits) */
5265 bool
5266 sra_total_scalarization_would_copy_same_data_p (tree t1, tree t2)
5268 sra_padding_collecting p1;
5269 if (!check_ts_and_push_padding_to_vec (t1, &p1))
5270 return true;
5272 sra_padding_collecting p2;
5273 if (!check_ts_and_push_padding_to_vec (t2, &p2))
5274 return true;
5276 unsigned l = p1.m_padding.length ();
5277 if (l != p2.m_padding.length ())
5278 return false;
5279 for (unsigned i = 0; i < l; i++)
5280 if (p1.m_padding[i].first != p2.m_padding[i].first
5281 || p1.m_padding[i].second != p2.m_padding[i].second)
5282 return false;
5284 return true;