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