PR c/64423
[official-gcc.git] / gcc / tree-sra.c
blobf80a8c43a7d0f6df2e54d7e7fcc556e906b9b839
1 /* Scalar Replacement of Aggregates (SRA) converts some structure
2 references into scalar references, exposing them to the scalar
3 optimizers.
4 Copyright (C) 2008-2014 Free Software Foundation, Inc.
5 Contributed by Martin Jambor <mjambor@suse.cz>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* This file implements Scalar Reduction of Aggregates (SRA). SRA is run
24 twice, once in the early stages of compilation (early SRA) and once in the
25 late stages (late SRA). The aim of both is to turn references to scalar
26 parts of aggregates into uses of independent scalar variables.
28 The two passes are nearly identical, the only difference is that early SRA
29 does not scalarize unions which are used as the result in a GIMPLE_RETURN
30 statement because together with inlining this can lead to weird type
31 conversions.
33 Both passes operate in four stages:
35 1. The declarations that have properties which make them candidates for
36 scalarization are identified in function find_var_candidates(). The
37 candidates are stored in candidate_bitmap.
39 2. The function body is scanned. In the process, declarations which are
40 used in a manner that prevent their scalarization are removed from the
41 candidate bitmap. More importantly, for every access into an aggregate,
42 an access structure (struct access) is created by create_access() and
43 stored in a vector associated with the aggregate. Among other
44 information, the aggregate declaration, the offset and size of the access
45 and its type are stored in the structure.
47 On a related note, assign_link structures are created for every assign
48 statement between candidate aggregates and attached to the related
49 accesses.
51 3. The vectors of accesses are analyzed. They are first sorted according to
52 their offset and size and then scanned for partially overlapping accesses
53 (i.e. those which overlap but one is not entirely within another). Such
54 an access disqualifies the whole aggregate from being scalarized.
56 If there is no such inhibiting overlap, a representative access structure
57 is chosen for every unique combination of offset and size. Afterwards,
58 the pass builds a set of trees from these structures, in which children
59 of an access are within their parent (in terms of offset and size).
61 Then accesses are propagated whenever possible (i.e. in cases when it
62 does not create a partially overlapping access) across assign_links from
63 the right hand side to the left hand side.
65 Then the set of trees for each declaration is traversed again and those
66 accesses which should be replaced by a scalar are identified.
68 4. The function is traversed again, and for every reference into an
69 aggregate that has some component which is about to be scalarized,
70 statements are amended and new statements are created as necessary.
71 Finally, if a parameter got scalarized, the scalar replacements are
72 initialized with values from respective parameter aggregates. */
74 #include "config.h"
75 #include "system.h"
76 #include "coretypes.h"
77 #include "hash-map.h"
78 #include "hash-table.h"
79 #include "alloc-pool.h"
80 #include "tm.h"
81 #include "tree.h"
82 #include "predict.h"
83 #include "vec.h"
84 #include "hashtab.h"
85 #include "hash-set.h"
86 #include "machmode.h"
87 #include "hard-reg-set.h"
88 #include "input.h"
89 #include "function.h"
90 #include "dominance.h"
91 #include "cfg.h"
92 #include "basic-block.h"
93 #include "tree-ssa-alias.h"
94 #include "internal-fn.h"
95 #include "tree-eh.h"
96 #include "gimple-expr.h"
97 #include "is-a.h"
98 #include "gimple.h"
99 #include "stor-layout.h"
100 #include "gimplify.h"
101 #include "gimple-iterator.h"
102 #include "gimplify-me.h"
103 #include "gimple-walk.h"
104 #include "bitmap.h"
105 #include "gimple-ssa.h"
106 #include "tree-cfg.h"
107 #include "tree-phinodes.h"
108 #include "ssa-iterators.h"
109 #include "stringpool.h"
110 #include "tree-ssanames.h"
111 #include "expr.h"
112 #include "tree-dfa.h"
113 #include "tree-ssa.h"
114 #include "tree-pass.h"
115 #include "plugin-api.h"
116 #include "ipa-ref.h"
117 #include "cgraph.h"
118 #include "symbol-summary.h"
119 #include "ipa-prop.h"
120 #include "statistics.h"
121 #include "params.h"
122 #include "target.h"
123 #include "flags.h"
124 #include "dbgcnt.h"
125 #include "tree-inline.h"
126 #include "gimple-pretty-print.h"
127 #include "ipa-inline.h"
128 #include "ipa-utils.h"
129 #include "builtins.h"
131 /* Enumeration of all aggregate reductions we can do. */
132 enum sra_mode { SRA_MODE_EARLY_IPA, /* early call regularization */
133 SRA_MODE_EARLY_INTRA, /* early intraprocedural SRA */
134 SRA_MODE_INTRA }; /* late intraprocedural SRA */
136 /* Global variable describing which aggregate reduction we are performing at
137 the moment. */
138 static enum sra_mode sra_mode;
140 struct assign_link;
142 /* ACCESS represents each access to an aggregate variable (as a whole or a
143 part). It can also represent a group of accesses that refer to exactly the
144 same fragment of an aggregate (i.e. those that have exactly the same offset
145 and size). Such representatives for a single aggregate, once determined,
146 are linked in a linked list and have the group fields set.
148 Moreover, when doing intraprocedural SRA, a tree is built from those
149 representatives (by the means of first_child and next_sibling pointers), in
150 which all items in a subtree are "within" the root, i.e. their offset is
151 greater or equal to offset of the root and offset+size is smaller or equal
152 to offset+size of the root. Children of an access are sorted by offset.
154 Note that accesses to parts of vector and complex number types always
155 represented by an access to the whole complex number or a vector. It is a
156 duty of the modifying functions to replace them appropriately. */
158 struct access
160 /* Values returned by `get_ref_base_and_extent' for each component reference
161 If EXPR isn't a component reference just set `BASE = EXPR', `OFFSET = 0',
162 `SIZE = TREE_SIZE (TREE_TYPE (expr))'. */
163 HOST_WIDE_INT offset;
164 HOST_WIDE_INT size;
165 tree base;
167 /* Expression. It is context dependent so do not use it to create new
168 expressions to access the original aggregate. See PR 42154 for a
169 testcase. */
170 tree expr;
171 /* Type. */
172 tree type;
174 /* The statement this access belongs to. */
175 gimple stmt;
177 /* Next group representative for this aggregate. */
178 struct access *next_grp;
180 /* Pointer to the group representative. Pointer to itself if the struct is
181 the representative. */
182 struct access *group_representative;
184 /* If this access has any children (in terms of the definition above), this
185 points to the first one. */
186 struct access *first_child;
188 /* In intraprocedural SRA, pointer to the next sibling in the access tree as
189 described above. In IPA-SRA this is a pointer to the next access
190 belonging to the same group (having the same representative). */
191 struct access *next_sibling;
193 /* Pointers to the first and last element in the linked list of assign
194 links. */
195 struct assign_link *first_link, *last_link;
197 /* Pointer to the next access in the work queue. */
198 struct access *next_queued;
200 /* Replacement variable for this access "region." Never to be accessed
201 directly, always only by the means of get_access_replacement() and only
202 when grp_to_be_replaced flag is set. */
203 tree replacement_decl;
205 /* Is this particular access write access? */
206 unsigned write : 1;
208 /* Is this access an access to a non-addressable field? */
209 unsigned non_addressable : 1;
211 /* Is this access currently in the work queue? */
212 unsigned grp_queued : 1;
214 /* Does this group contain a write access? This flag is propagated down the
215 access tree. */
216 unsigned grp_write : 1;
218 /* Does this group contain a read access? This flag is propagated down the
219 access tree. */
220 unsigned grp_read : 1;
222 /* Does this group contain a read access that comes from an assignment
223 statement? This flag is propagated down the access tree. */
224 unsigned grp_assignment_read : 1;
226 /* Does this group contain a write access that comes from an assignment
227 statement? This flag is propagated down the access tree. */
228 unsigned grp_assignment_write : 1;
230 /* Does this group contain a read access through a scalar type? This flag is
231 not propagated in the access tree in any direction. */
232 unsigned grp_scalar_read : 1;
234 /* Does this group contain a write access through a scalar type? This flag
235 is not propagated in the access tree in any direction. */
236 unsigned grp_scalar_write : 1;
238 /* Is this access an artificial one created to scalarize some record
239 entirely? */
240 unsigned grp_total_scalarization : 1;
242 /* Other passes of the analysis use this bit to make function
243 analyze_access_subtree create scalar replacements for this group if
244 possible. */
245 unsigned grp_hint : 1;
247 /* Is the subtree rooted in this access fully covered by scalar
248 replacements? */
249 unsigned grp_covered : 1;
251 /* If set to true, this access and all below it in an access tree must not be
252 scalarized. */
253 unsigned grp_unscalarizable_region : 1;
255 /* Whether data have been written to parts of the aggregate covered by this
256 access which is not to be scalarized. This flag is propagated up in the
257 access tree. */
258 unsigned grp_unscalarized_data : 1;
260 /* Does this access and/or group contain a write access through a
261 BIT_FIELD_REF? */
262 unsigned grp_partial_lhs : 1;
264 /* Set when a scalar replacement should be created for this variable. */
265 unsigned grp_to_be_replaced : 1;
267 /* Set when we want a replacement for the sole purpose of having it in
268 generated debug statements. */
269 unsigned grp_to_be_debug_replaced : 1;
271 /* Should TREE_NO_WARNING of a replacement be set? */
272 unsigned grp_no_warning : 1;
274 /* Is it possible that the group refers to data which might be (directly or
275 otherwise) modified? */
276 unsigned grp_maybe_modified : 1;
278 /* Set when this is a representative of a pointer to scalar (i.e. by
279 reference) parameter which we consider for turning into a plain scalar
280 (i.e. a by value parameter). */
281 unsigned grp_scalar_ptr : 1;
283 /* Set when we discover that this pointer is not safe to dereference in the
284 caller. */
285 unsigned grp_not_necessarilly_dereferenced : 1;
288 typedef struct access *access_p;
291 /* Alloc pool for allocating access structures. */
292 static alloc_pool access_pool;
294 /* A structure linking lhs and rhs accesses from an aggregate assignment. They
295 are used to propagate subaccesses from rhs to lhs as long as they don't
296 conflict with what is already there. */
297 struct assign_link
299 struct access *lacc, *racc;
300 struct assign_link *next;
303 /* Alloc pool for allocating assign link structures. */
304 static alloc_pool link_pool;
306 /* Base (tree) -> Vector (vec<access_p> *) map. */
307 static hash_map<tree, auto_vec<access_p> > *base_access_vec;
309 /* Candidate hash table helpers. */
311 struct uid_decl_hasher : typed_noop_remove <tree_node>
313 typedef tree_node value_type;
314 typedef tree_node compare_type;
315 static inline hashval_t hash (const value_type *);
316 static inline bool equal (const value_type *, const compare_type *);
319 /* Hash a tree in a uid_decl_map. */
321 inline hashval_t
322 uid_decl_hasher::hash (const value_type *item)
324 return item->decl_minimal.uid;
327 /* Return true if the DECL_UID in both trees are equal. */
329 inline bool
330 uid_decl_hasher::equal (const value_type *a, const compare_type *b)
332 return (a->decl_minimal.uid == b->decl_minimal.uid);
335 /* Set of candidates. */
336 static bitmap candidate_bitmap;
337 static hash_table<uid_decl_hasher> *candidates;
339 /* For a candidate UID return the candidates decl. */
341 static inline tree
342 candidate (unsigned uid)
344 tree_node t;
345 t.decl_minimal.uid = uid;
346 return candidates->find_with_hash (&t, static_cast <hashval_t> (uid));
349 /* Bitmap of candidates which we should try to entirely scalarize away and
350 those which cannot be (because they are and need be used as a whole). */
351 static bitmap should_scalarize_away_bitmap, cannot_scalarize_away_bitmap;
353 /* Obstack for creation of fancy names. */
354 static struct obstack name_obstack;
356 /* Head of a linked list of accesses that need to have its subaccesses
357 propagated to their assignment counterparts. */
358 static struct access *work_queue_head;
360 /* Number of parameters of the analyzed function when doing early ipa SRA. */
361 static int func_param_count;
363 /* scan_function sets the following to true if it encounters a call to
364 __builtin_apply_args. */
365 static bool encountered_apply_args;
367 /* Set by scan_function when it finds a recursive call. */
368 static bool encountered_recursive_call;
370 /* Set by scan_function when it finds a recursive call with less actual
371 arguments than formal parameters.. */
372 static bool encountered_unchangable_recursive_call;
374 /* This is a table in which for each basic block and parameter there is a
375 distance (offset + size) in that parameter which is dereferenced and
376 accessed in that BB. */
377 static HOST_WIDE_INT *bb_dereferences;
378 /* Bitmap of BBs that can cause the function to "stop" progressing by
379 returning, throwing externally, looping infinitely or calling a function
380 which might abort etc.. */
381 static bitmap final_bbs;
383 /* Representative of no accesses at all. */
384 static struct access no_accesses_representant;
386 /* Predicate to test the special value. */
388 static inline bool
389 no_accesses_p (struct access *access)
391 return access == &no_accesses_representant;
394 /* Dump contents of ACCESS to file F in a human friendly way. If GRP is true,
395 representative fields are dumped, otherwise those which only describe the
396 individual access are. */
398 static struct
400 /* Number of processed aggregates is readily available in
401 analyze_all_variable_accesses and so is not stored here. */
403 /* Number of created scalar replacements. */
404 int replacements;
406 /* Number of times sra_modify_expr or sra_modify_assign themselves changed an
407 expression. */
408 int exprs;
410 /* Number of statements created by generate_subtree_copies. */
411 int subtree_copies;
413 /* Number of statements created by load_assign_lhs_subreplacements. */
414 int subreplacements;
416 /* Number of times sra_modify_assign has deleted a statement. */
417 int deleted;
419 /* Number of times sra_modify_assign has to deal with subaccesses of LHS and
420 RHS reparately due to type conversions or nonexistent matching
421 references. */
422 int separate_lhs_rhs_handling;
424 /* Number of parameters that were removed because they were unused. */
425 int deleted_unused_parameters;
427 /* Number of scalars passed as parameters by reference that have been
428 converted to be passed by value. */
429 int scalar_by_ref_to_by_val;
431 /* Number of aggregate parameters that were replaced by one or more of their
432 components. */
433 int aggregate_params_reduced;
435 /* Numbber of components created when splitting aggregate parameters. */
436 int param_reductions_created;
437 } sra_stats;
439 static void
440 dump_access (FILE *f, struct access *access, bool grp)
442 fprintf (f, "access { ");
443 fprintf (f, "base = (%d)'", DECL_UID (access->base));
444 print_generic_expr (f, access->base, 0);
445 fprintf (f, "', offset = " HOST_WIDE_INT_PRINT_DEC, access->offset);
446 fprintf (f, ", size = " HOST_WIDE_INT_PRINT_DEC, access->size);
447 fprintf (f, ", expr = ");
448 print_generic_expr (f, access->expr, 0);
449 fprintf (f, ", type = ");
450 print_generic_expr (f, access->type, 0);
451 if (grp)
452 fprintf (f, ", grp_read = %d, grp_write = %d, grp_assignment_read = %d, "
453 "grp_assignment_write = %d, grp_scalar_read = %d, "
454 "grp_scalar_write = %d, grp_total_scalarization = %d, "
455 "grp_hint = %d, grp_covered = %d, "
456 "grp_unscalarizable_region = %d, grp_unscalarized_data = %d, "
457 "grp_partial_lhs = %d, grp_to_be_replaced = %d, "
458 "grp_to_be_debug_replaced = %d, grp_maybe_modified = %d, "
459 "grp_not_necessarilly_dereferenced = %d\n",
460 access->grp_read, access->grp_write, access->grp_assignment_read,
461 access->grp_assignment_write, access->grp_scalar_read,
462 access->grp_scalar_write, access->grp_total_scalarization,
463 access->grp_hint, access->grp_covered,
464 access->grp_unscalarizable_region, access->grp_unscalarized_data,
465 access->grp_partial_lhs, access->grp_to_be_replaced,
466 access->grp_to_be_debug_replaced, access->grp_maybe_modified,
467 access->grp_not_necessarilly_dereferenced);
468 else
469 fprintf (f, ", write = %d, grp_total_scalarization = %d, "
470 "grp_partial_lhs = %d\n",
471 access->write, access->grp_total_scalarization,
472 access->grp_partial_lhs);
475 /* Dump a subtree rooted in ACCESS to file F, indent by LEVEL. */
477 static void
478 dump_access_tree_1 (FILE *f, struct access *access, int level)
482 int i;
484 for (i = 0; i < level; i++)
485 fputs ("* ", dump_file);
487 dump_access (f, access, true);
489 if (access->first_child)
490 dump_access_tree_1 (f, access->first_child, level + 1);
492 access = access->next_sibling;
494 while (access);
497 /* Dump all access trees for a variable, given the pointer to the first root in
498 ACCESS. */
500 static void
501 dump_access_tree (FILE *f, struct access *access)
503 for (; access; access = access->next_grp)
504 dump_access_tree_1 (f, access, 0);
507 /* Return true iff ACC is non-NULL and has subaccesses. */
509 static inline bool
510 access_has_children_p (struct access *acc)
512 return acc && acc->first_child;
515 /* Return true iff ACC is (partly) covered by at least one replacement. */
517 static bool
518 access_has_replacements_p (struct access *acc)
520 struct access *child;
521 if (acc->grp_to_be_replaced)
522 return true;
523 for (child = acc->first_child; child; child = child->next_sibling)
524 if (access_has_replacements_p (child))
525 return true;
526 return false;
529 /* Return a vector of pointers to accesses for the variable given in BASE or
530 NULL if there is none. */
532 static vec<access_p> *
533 get_base_access_vector (tree base)
535 return base_access_vec->get (base);
538 /* Find an access with required OFFSET and SIZE in a subtree of accesses rooted
539 in ACCESS. Return NULL if it cannot be found. */
541 static struct access *
542 find_access_in_subtree (struct access *access, HOST_WIDE_INT offset,
543 HOST_WIDE_INT size)
545 while (access && (access->offset != offset || access->size != size))
547 struct access *child = access->first_child;
549 while (child && (child->offset + child->size <= offset))
550 child = child->next_sibling;
551 access = child;
554 return access;
557 /* Return the first group representative for DECL or NULL if none exists. */
559 static struct access *
560 get_first_repr_for_decl (tree base)
562 vec<access_p> *access_vec;
564 access_vec = get_base_access_vector (base);
565 if (!access_vec)
566 return NULL;
568 return (*access_vec)[0];
571 /* Find an access representative for the variable BASE and given OFFSET and
572 SIZE. Requires that access trees have already been built. Return NULL if
573 it cannot be found. */
575 static struct access *
576 get_var_base_offset_size_access (tree base, HOST_WIDE_INT offset,
577 HOST_WIDE_INT size)
579 struct access *access;
581 access = get_first_repr_for_decl (base);
582 while (access && (access->offset + access->size <= offset))
583 access = access->next_grp;
584 if (!access)
585 return NULL;
587 return find_access_in_subtree (access, offset, size);
590 /* Add LINK to the linked list of assign links of RACC. */
591 static void
592 add_link_to_rhs (struct access *racc, struct assign_link *link)
594 gcc_assert (link->racc == racc);
596 if (!racc->first_link)
598 gcc_assert (!racc->last_link);
599 racc->first_link = link;
601 else
602 racc->last_link->next = link;
604 racc->last_link = link;
605 link->next = NULL;
608 /* Move all link structures in their linked list in OLD_RACC to the linked list
609 in NEW_RACC. */
610 static void
611 relink_to_new_repr (struct access *new_racc, struct access *old_racc)
613 if (!old_racc->first_link)
615 gcc_assert (!old_racc->last_link);
616 return;
619 if (new_racc->first_link)
621 gcc_assert (!new_racc->last_link->next);
622 gcc_assert (!old_racc->last_link || !old_racc->last_link->next);
624 new_racc->last_link->next = old_racc->first_link;
625 new_racc->last_link = old_racc->last_link;
627 else
629 gcc_assert (!new_racc->last_link);
631 new_racc->first_link = old_racc->first_link;
632 new_racc->last_link = old_racc->last_link;
634 old_racc->first_link = old_racc->last_link = NULL;
637 /* Add ACCESS to the work queue (which is actually a stack). */
639 static void
640 add_access_to_work_queue (struct access *access)
642 if (!access->grp_queued)
644 gcc_assert (!access->next_queued);
645 access->next_queued = work_queue_head;
646 access->grp_queued = 1;
647 work_queue_head = access;
651 /* Pop an access from the work queue, and return it, assuming there is one. */
653 static struct access *
654 pop_access_from_work_queue (void)
656 struct access *access = work_queue_head;
658 work_queue_head = access->next_queued;
659 access->next_queued = NULL;
660 access->grp_queued = 0;
661 return access;
665 /* Allocate necessary structures. */
667 static void
668 sra_initialize (void)
670 candidate_bitmap = BITMAP_ALLOC (NULL);
671 candidates = new hash_table<uid_decl_hasher>
672 (vec_safe_length (cfun->local_decls) / 2);
673 should_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
674 cannot_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
675 gcc_obstack_init (&name_obstack);
676 access_pool = create_alloc_pool ("SRA accesses", sizeof (struct access), 16);
677 link_pool = create_alloc_pool ("SRA links", sizeof (struct assign_link), 16);
678 base_access_vec = new hash_map<tree, auto_vec<access_p> >;
679 memset (&sra_stats, 0, sizeof (sra_stats));
680 encountered_apply_args = false;
681 encountered_recursive_call = false;
682 encountered_unchangable_recursive_call = false;
685 /* Deallocate all general structures. */
687 static void
688 sra_deinitialize (void)
690 BITMAP_FREE (candidate_bitmap);
691 delete candidates;
692 candidates = NULL;
693 BITMAP_FREE (should_scalarize_away_bitmap);
694 BITMAP_FREE (cannot_scalarize_away_bitmap);
695 free_alloc_pool (access_pool);
696 free_alloc_pool (link_pool);
697 obstack_free (&name_obstack, NULL);
699 delete base_access_vec;
702 /* Remove DECL from candidates for SRA and write REASON to the dump file if
703 there is one. */
704 static void
705 disqualify_candidate (tree decl, const char *reason)
707 if (bitmap_clear_bit (candidate_bitmap, DECL_UID (decl)))
708 candidates->remove_elt_with_hash (decl, DECL_UID (decl));
710 if (dump_file && (dump_flags & TDF_DETAILS))
712 fprintf (dump_file, "! Disqualifying ");
713 print_generic_expr (dump_file, decl, 0);
714 fprintf (dump_file, " - %s\n", reason);
718 /* Return true iff the type contains a field or an element which does not allow
719 scalarization. */
721 static bool
722 type_internals_preclude_sra_p (tree type, const char **msg)
724 tree fld;
725 tree et;
727 switch (TREE_CODE (type))
729 case RECORD_TYPE:
730 case UNION_TYPE:
731 case QUAL_UNION_TYPE:
732 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
733 if (TREE_CODE (fld) == FIELD_DECL)
735 tree ft = TREE_TYPE (fld);
737 if (TREE_THIS_VOLATILE (fld))
739 *msg = "volatile structure field";
740 return true;
742 if (!DECL_FIELD_OFFSET (fld))
744 *msg = "no structure field offset";
745 return true;
747 if (!DECL_SIZE (fld))
749 *msg = "zero structure field size";
750 return true;
752 if (!tree_fits_uhwi_p (DECL_FIELD_OFFSET (fld)))
754 *msg = "structure field offset not fixed";
755 return true;
757 if (!tree_fits_uhwi_p (DECL_SIZE (fld)))
759 *msg = "structure field size not fixed";
760 return true;
762 if (!tree_fits_shwi_p (bit_position (fld)))
764 *msg = "structure field size too big";
765 return true;
767 if (AGGREGATE_TYPE_P (ft)
768 && int_bit_position (fld) % BITS_PER_UNIT != 0)
770 *msg = "structure field is bit field";
771 return true;
774 if (AGGREGATE_TYPE_P (ft) && type_internals_preclude_sra_p (ft, msg))
775 return true;
778 return false;
780 case ARRAY_TYPE:
781 et = TREE_TYPE (type);
783 if (TYPE_VOLATILE (et))
785 *msg = "element type is volatile";
786 return true;
789 if (AGGREGATE_TYPE_P (et) && type_internals_preclude_sra_p (et, msg))
790 return true;
792 return false;
794 default:
795 return false;
799 /* If T is an SSA_NAME, return NULL if it is not a default def or return its
800 base variable if it is. Return T if it is not an SSA_NAME. */
802 static tree
803 get_ssa_base_param (tree t)
805 if (TREE_CODE (t) == SSA_NAME)
807 if (SSA_NAME_IS_DEFAULT_DEF (t))
808 return SSA_NAME_VAR (t);
809 else
810 return NULL_TREE;
812 return t;
815 /* Mark a dereference of BASE of distance DIST in a basic block tht STMT
816 belongs to, unless the BB has already been marked as a potentially
817 final. */
819 static void
820 mark_parm_dereference (tree base, HOST_WIDE_INT dist, gimple stmt)
822 basic_block bb = gimple_bb (stmt);
823 int idx, parm_index = 0;
824 tree parm;
826 if (bitmap_bit_p (final_bbs, bb->index))
827 return;
829 for (parm = DECL_ARGUMENTS (current_function_decl);
830 parm && parm != base;
831 parm = DECL_CHAIN (parm))
832 parm_index++;
834 gcc_assert (parm_index < func_param_count);
836 idx = bb->index * func_param_count + parm_index;
837 if (bb_dereferences[idx] < dist)
838 bb_dereferences[idx] = dist;
841 /* Allocate an access structure for BASE, OFFSET and SIZE, clear it, fill in
842 the three fields. Also add it to the vector of accesses corresponding to
843 the base. Finally, return the new access. */
845 static struct access *
846 create_access_1 (tree base, HOST_WIDE_INT offset, HOST_WIDE_INT size)
848 struct access *access;
850 access = (struct access *) pool_alloc (access_pool);
851 memset (access, 0, sizeof (struct access));
852 access->base = base;
853 access->offset = offset;
854 access->size = size;
856 base_access_vec->get_or_insert (base).safe_push (access);
858 return access;
861 /* Create and insert access for EXPR. Return created access, or NULL if it is
862 not possible. */
864 static struct access *
865 create_access (tree expr, gimple stmt, bool write)
867 struct access *access;
868 HOST_WIDE_INT offset, size, max_size;
869 tree base = expr;
870 bool ptr, unscalarizable_region = false;
872 base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
874 if (sra_mode == SRA_MODE_EARLY_IPA
875 && TREE_CODE (base) == MEM_REF)
877 base = get_ssa_base_param (TREE_OPERAND (base, 0));
878 if (!base)
879 return NULL;
880 ptr = true;
882 else
883 ptr = false;
885 if (!DECL_P (base) || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
886 return NULL;
888 if (sra_mode == SRA_MODE_EARLY_IPA)
890 if (size < 0 || size != max_size)
892 disqualify_candidate (base, "Encountered a variable sized access.");
893 return NULL;
895 if (TREE_CODE (expr) == COMPONENT_REF
896 && DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
898 disqualify_candidate (base, "Encountered a bit-field access.");
899 return NULL;
901 gcc_checking_assert ((offset % BITS_PER_UNIT) == 0);
903 if (ptr)
904 mark_parm_dereference (base, offset + size, stmt);
906 else
908 if (size != max_size)
910 size = max_size;
911 unscalarizable_region = true;
913 if (size < 0)
915 disqualify_candidate (base, "Encountered an unconstrained access.");
916 return NULL;
920 access = create_access_1 (base, offset, size);
921 access->expr = expr;
922 access->type = TREE_TYPE (expr);
923 access->write = write;
924 access->grp_unscalarizable_region = unscalarizable_region;
925 access->stmt = stmt;
927 if (TREE_CODE (expr) == COMPONENT_REF
928 && DECL_NONADDRESSABLE_P (TREE_OPERAND (expr, 1)))
929 access->non_addressable = 1;
931 return access;
935 /* Return true iff TYPE is a RECORD_TYPE with fields that are either of gimple
936 register types or (recursively) records with only these two kinds of fields.
937 It also returns false if any of these records contains a bit-field. */
939 static bool
940 type_consists_of_records_p (tree type)
942 tree fld;
944 if (TREE_CODE (type) != RECORD_TYPE)
945 return false;
947 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
948 if (TREE_CODE (fld) == FIELD_DECL)
950 tree ft = TREE_TYPE (fld);
952 if (DECL_BIT_FIELD (fld))
953 return false;
955 if (!is_gimple_reg_type (ft)
956 && !type_consists_of_records_p (ft))
957 return false;
960 return true;
963 /* Create total_scalarization accesses for all scalar type fields in DECL that
964 must be of a RECORD_TYPE conforming to type_consists_of_records_p. BASE
965 must be the top-most VAR_DECL representing the variable, OFFSET must be the
966 offset of DECL within BASE. REF must be the memory reference expression for
967 the given decl. */
969 static void
970 completely_scalarize_record (tree base, tree decl, HOST_WIDE_INT offset,
971 tree ref)
973 tree fld, decl_type = TREE_TYPE (decl);
975 for (fld = TYPE_FIELDS (decl_type); fld; fld = DECL_CHAIN (fld))
976 if (TREE_CODE (fld) == FIELD_DECL)
978 HOST_WIDE_INT pos = offset + int_bit_position (fld);
979 tree ft = TREE_TYPE (fld);
980 tree nref = build3 (COMPONENT_REF, TREE_TYPE (fld), ref, fld,
981 NULL_TREE);
983 if (is_gimple_reg_type (ft))
985 struct access *access;
986 HOST_WIDE_INT size;
988 size = tree_to_uhwi (DECL_SIZE (fld));
989 access = create_access_1 (base, pos, size);
990 access->expr = nref;
991 access->type = ft;
992 access->grp_total_scalarization = 1;
993 /* Accesses for intraprocedural SRA can have their stmt NULL. */
995 else
996 completely_scalarize_record (base, fld, pos, nref);
1000 /* Create total_scalarization accesses for all scalar type fields in VAR and
1001 for VAR a a whole. VAR must be of a RECORD_TYPE conforming to
1002 type_consists_of_records_p. */
1004 static void
1005 completely_scalarize_var (tree var)
1007 HOST_WIDE_INT size = tree_to_uhwi (DECL_SIZE (var));
1008 struct access *access;
1010 access = create_access_1 (var, 0, size);
1011 access->expr = var;
1012 access->type = TREE_TYPE (var);
1013 access->grp_total_scalarization = 1;
1015 completely_scalarize_record (var, var, 0, var);
1018 /* Return true if REF has an VIEW_CONVERT_EXPR somewhere in it. */
1020 static inline bool
1021 contains_view_convert_expr_p (const_tree ref)
1023 while (handled_component_p (ref))
1025 if (TREE_CODE (ref) == VIEW_CONVERT_EXPR)
1026 return true;
1027 ref = TREE_OPERAND (ref, 0);
1030 return false;
1033 /* Search the given tree for a declaration by skipping handled components and
1034 exclude it from the candidates. */
1036 static void
1037 disqualify_base_of_expr (tree t, const char *reason)
1039 t = get_base_address (t);
1040 if (sra_mode == SRA_MODE_EARLY_IPA
1041 && TREE_CODE (t) == MEM_REF)
1042 t = get_ssa_base_param (TREE_OPERAND (t, 0));
1044 if (t && DECL_P (t))
1045 disqualify_candidate (t, reason);
1048 /* Scan expression EXPR and create access structures for all accesses to
1049 candidates for scalarization. Return the created access or NULL if none is
1050 created. */
1052 static struct access *
1053 build_access_from_expr_1 (tree expr, gimple stmt, bool write)
1055 struct access *ret = NULL;
1056 bool partial_ref;
1058 if (TREE_CODE (expr) == BIT_FIELD_REF
1059 || TREE_CODE (expr) == IMAGPART_EXPR
1060 || TREE_CODE (expr) == REALPART_EXPR)
1062 expr = TREE_OPERAND (expr, 0);
1063 partial_ref = true;
1065 else
1066 partial_ref = false;
1068 /* We need to dive through V_C_Es in order to get the size of its parameter
1069 and not the result type. Ada produces such statements. We are also
1070 capable of handling the topmost V_C_E but not any of those buried in other
1071 handled components. */
1072 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
1073 expr = TREE_OPERAND (expr, 0);
1075 if (contains_view_convert_expr_p (expr))
1077 disqualify_base_of_expr (expr, "V_C_E under a different handled "
1078 "component.");
1079 return NULL;
1081 if (TREE_THIS_VOLATILE (expr))
1083 disqualify_base_of_expr (expr, "part of a volatile reference.");
1084 return NULL;
1087 switch (TREE_CODE (expr))
1089 case MEM_REF:
1090 if (TREE_CODE (TREE_OPERAND (expr, 0)) != ADDR_EXPR
1091 && sra_mode != SRA_MODE_EARLY_IPA)
1092 return NULL;
1093 /* fall through */
1094 case VAR_DECL:
1095 case PARM_DECL:
1096 case RESULT_DECL:
1097 case COMPONENT_REF:
1098 case ARRAY_REF:
1099 case ARRAY_RANGE_REF:
1100 ret = create_access (expr, stmt, write);
1101 break;
1103 default:
1104 break;
1107 if (write && partial_ref && ret)
1108 ret->grp_partial_lhs = 1;
1110 return ret;
1113 /* Scan expression EXPR and create access structures for all accesses to
1114 candidates for scalarization. Return true if any access has been inserted.
1115 STMT must be the statement from which the expression is taken, WRITE must be
1116 true if the expression is a store and false otherwise. */
1118 static bool
1119 build_access_from_expr (tree expr, gimple stmt, bool write)
1121 struct access *access;
1123 access = build_access_from_expr_1 (expr, stmt, write);
1124 if (access)
1126 /* This means the aggregate is accesses as a whole in a way other than an
1127 assign statement and thus cannot be removed even if we had a scalar
1128 replacement for everything. */
1129 if (cannot_scalarize_away_bitmap)
1130 bitmap_set_bit (cannot_scalarize_away_bitmap, DECL_UID (access->base));
1131 return true;
1133 return false;
1136 /* Return the single non-EH successor edge of BB or NULL if there is none or
1137 more than one. */
1139 static edge
1140 single_non_eh_succ (basic_block bb)
1142 edge e, res = NULL;
1143 edge_iterator ei;
1145 FOR_EACH_EDGE (e, ei, bb->succs)
1146 if (!(e->flags & EDGE_EH))
1148 if (res)
1149 return NULL;
1150 res = e;
1153 return res;
1156 /* Disqualify LHS and RHS for scalarization if STMT has to terminate its BB and
1157 there is no alternative spot where to put statements SRA might need to
1158 generate after it. The spot we are looking for is an edge leading to a
1159 single non-EH successor, if it exists and is indeed single. RHS may be
1160 NULL, in that case ignore it. */
1162 static bool
1163 disqualify_if_bad_bb_terminating_stmt (gimple stmt, tree lhs, tree rhs)
1165 if ((sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
1166 && stmt_ends_bb_p (stmt))
1168 if (single_non_eh_succ (gimple_bb (stmt)))
1169 return false;
1171 disqualify_base_of_expr (lhs, "LHS of a throwing stmt.");
1172 if (rhs)
1173 disqualify_base_of_expr (rhs, "RHS of a throwing stmt.");
1174 return true;
1176 return false;
1179 /* Scan expressions occurring in STMT, create access structures for all accesses
1180 to candidates for scalarization and remove those candidates which occur in
1181 statements or expressions that prevent them from being split apart. Return
1182 true if any access has been inserted. */
1184 static bool
1185 build_accesses_from_assign (gimple stmt)
1187 tree lhs, rhs;
1188 struct access *lacc, *racc;
1190 if (!gimple_assign_single_p (stmt)
1191 /* Scope clobbers don't influence scalarization. */
1192 || gimple_clobber_p (stmt))
1193 return false;
1195 lhs = gimple_assign_lhs (stmt);
1196 rhs = gimple_assign_rhs1 (stmt);
1198 if (disqualify_if_bad_bb_terminating_stmt (stmt, lhs, rhs))
1199 return false;
1201 racc = build_access_from_expr_1 (rhs, stmt, false);
1202 lacc = build_access_from_expr_1 (lhs, stmt, true);
1204 if (lacc)
1205 lacc->grp_assignment_write = 1;
1207 if (racc)
1209 racc->grp_assignment_read = 1;
1210 if (should_scalarize_away_bitmap && !gimple_has_volatile_ops (stmt)
1211 && !is_gimple_reg_type (racc->type))
1212 bitmap_set_bit (should_scalarize_away_bitmap, DECL_UID (racc->base));
1215 if (lacc && racc
1216 && (sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
1217 && !lacc->grp_unscalarizable_region
1218 && !racc->grp_unscalarizable_region
1219 && AGGREGATE_TYPE_P (TREE_TYPE (lhs))
1220 && lacc->size == racc->size
1221 && useless_type_conversion_p (lacc->type, racc->type))
1223 struct assign_link *link;
1225 link = (struct assign_link *) pool_alloc (link_pool);
1226 memset (link, 0, sizeof (struct assign_link));
1228 link->lacc = lacc;
1229 link->racc = racc;
1231 add_link_to_rhs (racc, link);
1234 return lacc || racc;
1237 /* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine
1238 GIMPLE_ASM operands with memory constrains which cannot be scalarized. */
1240 static bool
1241 asm_visit_addr (gimple, tree op, tree, void *)
1243 op = get_base_address (op);
1244 if (op
1245 && DECL_P (op))
1246 disqualify_candidate (op, "Non-scalarizable GIMPLE_ASM operand.");
1248 return false;
1251 /* Return true iff callsite CALL has at least as many actual arguments as there
1252 are formal parameters of the function currently processed by IPA-SRA and
1253 that their types match. */
1255 static inline bool
1256 callsite_arguments_match_p (gimple call)
1258 if (gimple_call_num_args (call) < (unsigned) func_param_count)
1259 return false;
1261 tree parm;
1262 int i;
1263 for (parm = DECL_ARGUMENTS (current_function_decl), i = 0;
1264 parm;
1265 parm = DECL_CHAIN (parm), i++)
1267 tree arg = gimple_call_arg (call, i);
1268 if (!useless_type_conversion_p (TREE_TYPE (parm), TREE_TYPE (arg)))
1269 return false;
1271 return true;
1274 /* Scan function and look for interesting expressions and create access
1275 structures for them. Return true iff any access is created. */
1277 static bool
1278 scan_function (void)
1280 basic_block bb;
1281 bool ret = false;
1283 FOR_EACH_BB_FN (bb, cfun)
1285 gimple_stmt_iterator gsi;
1286 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1288 gimple stmt = gsi_stmt (gsi);
1289 tree t;
1290 unsigned i;
1292 if (final_bbs && stmt_can_throw_external (stmt))
1293 bitmap_set_bit (final_bbs, bb->index);
1294 switch (gimple_code (stmt))
1296 case GIMPLE_RETURN:
1297 t = gimple_return_retval (as_a <greturn *> (stmt));
1298 if (t != NULL_TREE)
1299 ret |= build_access_from_expr (t, stmt, false);
1300 if (final_bbs)
1301 bitmap_set_bit (final_bbs, bb->index);
1302 break;
1304 case GIMPLE_ASSIGN:
1305 ret |= build_accesses_from_assign (stmt);
1306 break;
1308 case GIMPLE_CALL:
1309 for (i = 0; i < gimple_call_num_args (stmt); i++)
1310 ret |= build_access_from_expr (gimple_call_arg (stmt, i),
1311 stmt, false);
1313 if (sra_mode == SRA_MODE_EARLY_IPA)
1315 tree dest = gimple_call_fndecl (stmt);
1316 int flags = gimple_call_flags (stmt);
1318 if (dest)
1320 if (DECL_BUILT_IN_CLASS (dest) == BUILT_IN_NORMAL
1321 && DECL_FUNCTION_CODE (dest) == BUILT_IN_APPLY_ARGS)
1322 encountered_apply_args = true;
1323 if (recursive_call_p (current_function_decl, dest))
1325 encountered_recursive_call = true;
1326 if (!callsite_arguments_match_p (stmt))
1327 encountered_unchangable_recursive_call = true;
1331 if (final_bbs
1332 && (flags & (ECF_CONST | ECF_PURE)) == 0)
1333 bitmap_set_bit (final_bbs, bb->index);
1336 t = gimple_call_lhs (stmt);
1337 if (t && !disqualify_if_bad_bb_terminating_stmt (stmt, t, NULL))
1338 ret |= build_access_from_expr (t, stmt, true);
1339 break;
1341 case GIMPLE_ASM:
1343 gasm *asm_stmt = as_a <gasm *> (stmt);
1344 walk_stmt_load_store_addr_ops (asm_stmt, NULL, NULL, NULL,
1345 asm_visit_addr);
1346 if (final_bbs)
1347 bitmap_set_bit (final_bbs, bb->index);
1349 for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
1351 t = TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
1352 ret |= build_access_from_expr (t, asm_stmt, false);
1354 for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
1356 t = TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
1357 ret |= build_access_from_expr (t, asm_stmt, true);
1360 break;
1362 default:
1363 break;
1368 return ret;
1371 /* Helper of QSORT function. There are pointers to accesses in the array. An
1372 access is considered smaller than another if it has smaller offset or if the
1373 offsets are the same but is size is bigger. */
1375 static int
1376 compare_access_positions (const void *a, const void *b)
1378 const access_p *fp1 = (const access_p *) a;
1379 const access_p *fp2 = (const access_p *) b;
1380 const access_p f1 = *fp1;
1381 const access_p f2 = *fp2;
1383 if (f1->offset != f2->offset)
1384 return f1->offset < f2->offset ? -1 : 1;
1386 if (f1->size == f2->size)
1388 if (f1->type == f2->type)
1389 return 0;
1390 /* Put any non-aggregate type before any aggregate type. */
1391 else if (!is_gimple_reg_type (f1->type)
1392 && is_gimple_reg_type (f2->type))
1393 return 1;
1394 else if (is_gimple_reg_type (f1->type)
1395 && !is_gimple_reg_type (f2->type))
1396 return -1;
1397 /* Put any complex or vector type before any other scalar type. */
1398 else if (TREE_CODE (f1->type) != COMPLEX_TYPE
1399 && TREE_CODE (f1->type) != VECTOR_TYPE
1400 && (TREE_CODE (f2->type) == COMPLEX_TYPE
1401 || TREE_CODE (f2->type) == VECTOR_TYPE))
1402 return 1;
1403 else if ((TREE_CODE (f1->type) == COMPLEX_TYPE
1404 || TREE_CODE (f1->type) == VECTOR_TYPE)
1405 && TREE_CODE (f2->type) != COMPLEX_TYPE
1406 && TREE_CODE (f2->type) != VECTOR_TYPE)
1407 return -1;
1408 /* Put the integral type with the bigger precision first. */
1409 else if (INTEGRAL_TYPE_P (f1->type)
1410 && INTEGRAL_TYPE_P (f2->type))
1411 return TYPE_PRECISION (f2->type) - TYPE_PRECISION (f1->type);
1412 /* Put any integral type with non-full precision last. */
1413 else if (INTEGRAL_TYPE_P (f1->type)
1414 && (TREE_INT_CST_LOW (TYPE_SIZE (f1->type))
1415 != TYPE_PRECISION (f1->type)))
1416 return 1;
1417 else if (INTEGRAL_TYPE_P (f2->type)
1418 && (TREE_INT_CST_LOW (TYPE_SIZE (f2->type))
1419 != TYPE_PRECISION (f2->type)))
1420 return -1;
1421 /* Stabilize the sort. */
1422 return TYPE_UID (f1->type) - TYPE_UID (f2->type);
1425 /* We want the bigger accesses first, thus the opposite operator in the next
1426 line: */
1427 return f1->size > f2->size ? -1 : 1;
1431 /* Append a name of the declaration to the name obstack. A helper function for
1432 make_fancy_name. */
1434 static void
1435 make_fancy_decl_name (tree decl)
1437 char buffer[32];
1439 tree name = DECL_NAME (decl);
1440 if (name)
1441 obstack_grow (&name_obstack, IDENTIFIER_POINTER (name),
1442 IDENTIFIER_LENGTH (name));
1443 else
1445 sprintf (buffer, "D%u", DECL_UID (decl));
1446 obstack_grow (&name_obstack, buffer, strlen (buffer));
1450 /* Helper for make_fancy_name. */
1452 static void
1453 make_fancy_name_1 (tree expr)
1455 char buffer[32];
1456 tree index;
1458 if (DECL_P (expr))
1460 make_fancy_decl_name (expr);
1461 return;
1464 switch (TREE_CODE (expr))
1466 case COMPONENT_REF:
1467 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1468 obstack_1grow (&name_obstack, '$');
1469 make_fancy_decl_name (TREE_OPERAND (expr, 1));
1470 break;
1472 case ARRAY_REF:
1473 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1474 obstack_1grow (&name_obstack, '$');
1475 /* Arrays with only one element may not have a constant as their
1476 index. */
1477 index = TREE_OPERAND (expr, 1);
1478 if (TREE_CODE (index) != INTEGER_CST)
1479 break;
1480 sprintf (buffer, HOST_WIDE_INT_PRINT_DEC, TREE_INT_CST_LOW (index));
1481 obstack_grow (&name_obstack, buffer, strlen (buffer));
1482 break;
1484 case ADDR_EXPR:
1485 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1486 break;
1488 case MEM_REF:
1489 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1490 if (!integer_zerop (TREE_OPERAND (expr, 1)))
1492 obstack_1grow (&name_obstack, '$');
1493 sprintf (buffer, HOST_WIDE_INT_PRINT_DEC,
1494 TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)));
1495 obstack_grow (&name_obstack, buffer, strlen (buffer));
1497 break;
1499 case BIT_FIELD_REF:
1500 case REALPART_EXPR:
1501 case IMAGPART_EXPR:
1502 gcc_unreachable (); /* we treat these as scalars. */
1503 break;
1504 default:
1505 break;
1509 /* Create a human readable name for replacement variable of ACCESS. */
1511 static char *
1512 make_fancy_name (tree expr)
1514 make_fancy_name_1 (expr);
1515 obstack_1grow (&name_obstack, '\0');
1516 return XOBFINISH (&name_obstack, char *);
1519 /* Construct a MEM_REF that would reference a part of aggregate BASE of type
1520 EXP_TYPE at the given OFFSET. If BASE is something for which
1521 get_addr_base_and_unit_offset returns NULL, gsi must be non-NULL and is used
1522 to insert new statements either before or below the current one as specified
1523 by INSERT_AFTER. This function is not capable of handling bitfields.
1525 BASE must be either a declaration or a memory reference that has correct
1526 alignment ifformation embeded in it (e.g. a pre-existing one in SRA). */
1528 tree
1529 build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset,
1530 tree exp_type, gimple_stmt_iterator *gsi,
1531 bool insert_after)
1533 tree prev_base = base;
1534 tree off;
1535 tree mem_ref;
1536 HOST_WIDE_INT base_offset;
1537 unsigned HOST_WIDE_INT misalign;
1538 unsigned int align;
1540 gcc_checking_assert (offset % BITS_PER_UNIT == 0);
1541 get_object_alignment_1 (base, &align, &misalign);
1542 base = get_addr_base_and_unit_offset (base, &base_offset);
1544 /* get_addr_base_and_unit_offset returns NULL for references with a variable
1545 offset such as array[var_index]. */
1546 if (!base)
1548 gassign *stmt;
1549 tree tmp, addr;
1551 gcc_checking_assert (gsi);
1552 tmp = make_ssa_name (build_pointer_type (TREE_TYPE (prev_base)));
1553 addr = build_fold_addr_expr (unshare_expr (prev_base));
1554 STRIP_USELESS_TYPE_CONVERSION (addr);
1555 stmt = gimple_build_assign (tmp, addr);
1556 gimple_set_location (stmt, loc);
1557 if (insert_after)
1558 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
1559 else
1560 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
1562 off = build_int_cst (reference_alias_ptr_type (prev_base),
1563 offset / BITS_PER_UNIT);
1564 base = tmp;
1566 else if (TREE_CODE (base) == MEM_REF)
1568 off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
1569 base_offset + offset / BITS_PER_UNIT);
1570 off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
1571 base = unshare_expr (TREE_OPERAND (base, 0));
1573 else
1575 off = build_int_cst (reference_alias_ptr_type (base),
1576 base_offset + offset / BITS_PER_UNIT);
1577 base = build_fold_addr_expr (unshare_expr (base));
1580 misalign = (misalign + offset) & (align - 1);
1581 if (misalign != 0)
1582 align = (misalign & -misalign);
1583 if (align < TYPE_ALIGN (exp_type))
1584 exp_type = build_aligned_type (exp_type, align);
1586 mem_ref = fold_build2_loc (loc, MEM_REF, exp_type, base, off);
1587 if (TREE_THIS_VOLATILE (prev_base))
1588 TREE_THIS_VOLATILE (mem_ref) = 1;
1589 if (TREE_SIDE_EFFECTS (prev_base))
1590 TREE_SIDE_EFFECTS (mem_ref) = 1;
1591 return mem_ref;
1594 /* Construct a memory reference to a part of an aggregate BASE at the given
1595 OFFSET and of the same type as MODEL. In case this is a reference to a
1596 bit-field, the function will replicate the last component_ref of model's
1597 expr to access it. GSI and INSERT_AFTER have the same meaning as in
1598 build_ref_for_offset. */
1600 static tree
1601 build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
1602 struct access *model, gimple_stmt_iterator *gsi,
1603 bool insert_after)
1605 if (TREE_CODE (model->expr) == COMPONENT_REF
1606 && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
1608 /* This access represents a bit-field. */
1609 tree t, exp_type, fld = TREE_OPERAND (model->expr, 1);
1611 offset -= int_bit_position (fld);
1612 exp_type = TREE_TYPE (TREE_OPERAND (model->expr, 0));
1613 t = build_ref_for_offset (loc, base, offset, exp_type, gsi, insert_after);
1614 return fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (fld), t, fld,
1615 NULL_TREE);
1617 else
1618 return build_ref_for_offset (loc, base, offset, model->type,
1619 gsi, insert_after);
1622 /* Attempt to build a memory reference that we could but into a gimple
1623 debug_bind statement. Similar to build_ref_for_model but punts if it has to
1624 create statements and return s NULL instead. This function also ignores
1625 alignment issues and so its results should never end up in non-debug
1626 statements. */
1628 static tree
1629 build_debug_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
1630 struct access *model)
1632 HOST_WIDE_INT base_offset;
1633 tree off;
1635 if (TREE_CODE (model->expr) == COMPONENT_REF
1636 && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
1637 return NULL_TREE;
1639 base = get_addr_base_and_unit_offset (base, &base_offset);
1640 if (!base)
1641 return NULL_TREE;
1642 if (TREE_CODE (base) == MEM_REF)
1644 off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
1645 base_offset + offset / BITS_PER_UNIT);
1646 off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
1647 base = unshare_expr (TREE_OPERAND (base, 0));
1649 else
1651 off = build_int_cst (reference_alias_ptr_type (base),
1652 base_offset + offset / BITS_PER_UNIT);
1653 base = build_fold_addr_expr (unshare_expr (base));
1656 return fold_build2_loc (loc, MEM_REF, model->type, base, off);
1659 /* Construct a memory reference consisting of component_refs and array_refs to
1660 a part of an aggregate *RES (which is of type TYPE). The requested part
1661 should have type EXP_TYPE at be the given OFFSET. This function might not
1662 succeed, it returns true when it does and only then *RES points to something
1663 meaningful. This function should be used only to build expressions that we
1664 might need to present to user (e.g. in warnings). In all other situations,
1665 build_ref_for_model or build_ref_for_offset should be used instead. */
1667 static bool
1668 build_user_friendly_ref_for_offset (tree *res, tree type, HOST_WIDE_INT offset,
1669 tree exp_type)
1671 while (1)
1673 tree fld;
1674 tree tr_size, index, minidx;
1675 HOST_WIDE_INT el_size;
1677 if (offset == 0 && exp_type
1678 && types_compatible_p (exp_type, type))
1679 return true;
1681 switch (TREE_CODE (type))
1683 case UNION_TYPE:
1684 case QUAL_UNION_TYPE:
1685 case RECORD_TYPE:
1686 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
1688 HOST_WIDE_INT pos, size;
1689 tree tr_pos, expr, *expr_ptr;
1691 if (TREE_CODE (fld) != FIELD_DECL)
1692 continue;
1694 tr_pos = bit_position (fld);
1695 if (!tr_pos || !tree_fits_uhwi_p (tr_pos))
1696 continue;
1697 pos = tree_to_uhwi (tr_pos);
1698 gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0);
1699 tr_size = DECL_SIZE (fld);
1700 if (!tr_size || !tree_fits_uhwi_p (tr_size))
1701 continue;
1702 size = tree_to_uhwi (tr_size);
1703 if (size == 0)
1705 if (pos != offset)
1706 continue;
1708 else if (pos > offset || (pos + size) <= offset)
1709 continue;
1711 expr = build3 (COMPONENT_REF, TREE_TYPE (fld), *res, fld,
1712 NULL_TREE);
1713 expr_ptr = &expr;
1714 if (build_user_friendly_ref_for_offset (expr_ptr, TREE_TYPE (fld),
1715 offset - pos, exp_type))
1717 *res = expr;
1718 return true;
1721 return false;
1723 case ARRAY_TYPE:
1724 tr_size = TYPE_SIZE (TREE_TYPE (type));
1725 if (!tr_size || !tree_fits_uhwi_p (tr_size))
1726 return false;
1727 el_size = tree_to_uhwi (tr_size);
1729 minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
1730 if (TREE_CODE (minidx) != INTEGER_CST || el_size == 0)
1731 return false;
1732 index = build_int_cst (TYPE_DOMAIN (type), offset / el_size);
1733 if (!integer_zerop (minidx))
1734 index = int_const_binop (PLUS_EXPR, index, minidx);
1735 *res = build4 (ARRAY_REF, TREE_TYPE (type), *res, index,
1736 NULL_TREE, NULL_TREE);
1737 offset = offset % el_size;
1738 type = TREE_TYPE (type);
1739 break;
1741 default:
1742 if (offset != 0)
1743 return false;
1745 if (exp_type)
1746 return false;
1747 else
1748 return true;
1753 /* Return true iff TYPE is stdarg va_list type. */
1755 static inline bool
1756 is_va_list_type (tree type)
1758 return TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (va_list_type_node);
1761 /* Print message to dump file why a variable was rejected. */
1763 static void
1764 reject (tree var, const char *msg)
1766 if (dump_file && (dump_flags & TDF_DETAILS))
1768 fprintf (dump_file, "Rejected (%d): %s: ", DECL_UID (var), msg);
1769 print_generic_expr (dump_file, var, 0);
1770 fprintf (dump_file, "\n");
1774 /* Return true if VAR is a candidate for SRA. */
1776 static bool
1777 maybe_add_sra_candidate (tree var)
1779 tree type = TREE_TYPE (var);
1780 const char *msg;
1781 tree_node **slot;
1783 if (!AGGREGATE_TYPE_P (type))
1785 reject (var, "not aggregate");
1786 return false;
1788 if (needs_to_live_in_memory (var))
1790 reject (var, "needs to live in memory");
1791 return false;
1793 if (TREE_THIS_VOLATILE (var))
1795 reject (var, "is volatile");
1796 return false;
1798 if (!COMPLETE_TYPE_P (type))
1800 reject (var, "has incomplete type");
1801 return false;
1803 if (!tree_fits_uhwi_p (TYPE_SIZE (type)))
1805 reject (var, "type size not fixed");
1806 return false;
1808 if (tree_to_uhwi (TYPE_SIZE (type)) == 0)
1810 reject (var, "type size is zero");
1811 return false;
1813 if (type_internals_preclude_sra_p (type, &msg))
1815 reject (var, msg);
1816 return false;
1818 if (/* Fix for PR 41089. tree-stdarg.c needs to have va_lists intact but
1819 we also want to schedule it rather late. Thus we ignore it in
1820 the early pass. */
1821 (sra_mode == SRA_MODE_EARLY_INTRA
1822 && is_va_list_type (type)))
1824 reject (var, "is va_list");
1825 return false;
1828 bitmap_set_bit (candidate_bitmap, DECL_UID (var));
1829 slot = candidates->find_slot_with_hash (var, DECL_UID (var), INSERT);
1830 *slot = var;
1832 if (dump_file && (dump_flags & TDF_DETAILS))
1834 fprintf (dump_file, "Candidate (%d): ", DECL_UID (var));
1835 print_generic_expr (dump_file, var, 0);
1836 fprintf (dump_file, "\n");
1839 return true;
1842 /* The very first phase of intraprocedural SRA. It marks in candidate_bitmap
1843 those with type which is suitable for scalarization. */
1845 static bool
1846 find_var_candidates (void)
1848 tree var, parm;
1849 unsigned int i;
1850 bool ret = false;
1852 for (parm = DECL_ARGUMENTS (current_function_decl);
1853 parm;
1854 parm = DECL_CHAIN (parm))
1855 ret |= maybe_add_sra_candidate (parm);
1857 FOR_EACH_LOCAL_DECL (cfun, i, var)
1859 if (TREE_CODE (var) != VAR_DECL)
1860 continue;
1862 ret |= maybe_add_sra_candidate (var);
1865 return ret;
1868 /* Sort all accesses for the given variable, check for partial overlaps and
1869 return NULL if there are any. If there are none, pick a representative for
1870 each combination of offset and size and create a linked list out of them.
1871 Return the pointer to the first representative and make sure it is the first
1872 one in the vector of accesses. */
1874 static struct access *
1875 sort_and_splice_var_accesses (tree var)
1877 int i, j, access_count;
1878 struct access *res, **prev_acc_ptr = &res;
1879 vec<access_p> *access_vec;
1880 bool first = true;
1881 HOST_WIDE_INT low = -1, high = 0;
1883 access_vec = get_base_access_vector (var);
1884 if (!access_vec)
1885 return NULL;
1886 access_count = access_vec->length ();
1888 /* Sort by <OFFSET, SIZE>. */
1889 access_vec->qsort (compare_access_positions);
1891 i = 0;
1892 while (i < access_count)
1894 struct access *access = (*access_vec)[i];
1895 bool grp_write = access->write;
1896 bool grp_read = !access->write;
1897 bool grp_scalar_write = access->write
1898 && is_gimple_reg_type (access->type);
1899 bool grp_scalar_read = !access->write
1900 && is_gimple_reg_type (access->type);
1901 bool grp_assignment_read = access->grp_assignment_read;
1902 bool grp_assignment_write = access->grp_assignment_write;
1903 bool multiple_scalar_reads = false;
1904 bool total_scalarization = access->grp_total_scalarization;
1905 bool grp_partial_lhs = access->grp_partial_lhs;
1906 bool first_scalar = is_gimple_reg_type (access->type);
1907 bool unscalarizable_region = access->grp_unscalarizable_region;
1909 if (first || access->offset >= high)
1911 first = false;
1912 low = access->offset;
1913 high = access->offset + access->size;
1915 else if (access->offset > low && access->offset + access->size > high)
1916 return NULL;
1917 else
1918 gcc_assert (access->offset >= low
1919 && access->offset + access->size <= high);
1921 j = i + 1;
1922 while (j < access_count)
1924 struct access *ac2 = (*access_vec)[j];
1925 if (ac2->offset != access->offset || ac2->size != access->size)
1926 break;
1927 if (ac2->write)
1929 grp_write = true;
1930 grp_scalar_write = (grp_scalar_write
1931 || is_gimple_reg_type (ac2->type));
1933 else
1935 grp_read = true;
1936 if (is_gimple_reg_type (ac2->type))
1938 if (grp_scalar_read)
1939 multiple_scalar_reads = true;
1940 else
1941 grp_scalar_read = true;
1944 grp_assignment_read |= ac2->grp_assignment_read;
1945 grp_assignment_write |= ac2->grp_assignment_write;
1946 grp_partial_lhs |= ac2->grp_partial_lhs;
1947 unscalarizable_region |= ac2->grp_unscalarizable_region;
1948 total_scalarization |= ac2->grp_total_scalarization;
1949 relink_to_new_repr (access, ac2);
1951 /* If there are both aggregate-type and scalar-type accesses with
1952 this combination of size and offset, the comparison function
1953 should have put the scalars first. */
1954 gcc_assert (first_scalar || !is_gimple_reg_type (ac2->type));
1955 ac2->group_representative = access;
1956 j++;
1959 i = j;
1961 access->group_representative = access;
1962 access->grp_write = grp_write;
1963 access->grp_read = grp_read;
1964 access->grp_scalar_read = grp_scalar_read;
1965 access->grp_scalar_write = grp_scalar_write;
1966 access->grp_assignment_read = grp_assignment_read;
1967 access->grp_assignment_write = grp_assignment_write;
1968 access->grp_hint = multiple_scalar_reads || total_scalarization;
1969 access->grp_total_scalarization = total_scalarization;
1970 access->grp_partial_lhs = grp_partial_lhs;
1971 access->grp_unscalarizable_region = unscalarizable_region;
1972 if (access->first_link)
1973 add_access_to_work_queue (access);
1975 *prev_acc_ptr = access;
1976 prev_acc_ptr = &access->next_grp;
1979 gcc_assert (res == (*access_vec)[0]);
1980 return res;
1983 /* Create a variable for the given ACCESS which determines the type, name and a
1984 few other properties. Return the variable declaration and store it also to
1985 ACCESS->replacement. */
1987 static tree
1988 create_access_replacement (struct access *access)
1990 tree repl;
1992 if (access->grp_to_be_debug_replaced)
1994 repl = create_tmp_var_raw (access->type);
1995 DECL_CONTEXT (repl) = current_function_decl;
1997 else
1998 repl = create_tmp_var (access->type, "SR");
1999 if (TREE_CODE (access->type) == COMPLEX_TYPE
2000 || TREE_CODE (access->type) == VECTOR_TYPE)
2002 if (!access->grp_partial_lhs)
2003 DECL_GIMPLE_REG_P (repl) = 1;
2005 else if (access->grp_partial_lhs
2006 && is_gimple_reg_type (access->type))
2007 TREE_ADDRESSABLE (repl) = 1;
2009 DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base);
2010 DECL_ARTIFICIAL (repl) = 1;
2011 DECL_IGNORED_P (repl) = DECL_IGNORED_P (access->base);
2013 if (DECL_NAME (access->base)
2014 && !DECL_IGNORED_P (access->base)
2015 && !DECL_ARTIFICIAL (access->base))
2017 char *pretty_name = make_fancy_name (access->expr);
2018 tree debug_expr = unshare_expr_without_location (access->expr), d;
2019 bool fail = false;
2021 DECL_NAME (repl) = get_identifier (pretty_name);
2022 obstack_free (&name_obstack, pretty_name);
2024 /* Get rid of any SSA_NAMEs embedded in debug_expr,
2025 as DECL_DEBUG_EXPR isn't considered when looking for still
2026 used SSA_NAMEs and thus they could be freed. All debug info
2027 generation cares is whether something is constant or variable
2028 and that get_ref_base_and_extent works properly on the
2029 expression. It cannot handle accesses at a non-constant offset
2030 though, so just give up in those cases. */
2031 for (d = debug_expr;
2032 !fail && (handled_component_p (d) || TREE_CODE (d) == MEM_REF);
2033 d = TREE_OPERAND (d, 0))
2034 switch (TREE_CODE (d))
2036 case ARRAY_REF:
2037 case ARRAY_RANGE_REF:
2038 if (TREE_OPERAND (d, 1)
2039 && TREE_CODE (TREE_OPERAND (d, 1)) != INTEGER_CST)
2040 fail = true;
2041 if (TREE_OPERAND (d, 3)
2042 && TREE_CODE (TREE_OPERAND (d, 3)) != INTEGER_CST)
2043 fail = true;
2044 /* FALLTHRU */
2045 case COMPONENT_REF:
2046 if (TREE_OPERAND (d, 2)
2047 && TREE_CODE (TREE_OPERAND (d, 2)) != INTEGER_CST)
2048 fail = true;
2049 break;
2050 case MEM_REF:
2051 if (TREE_CODE (TREE_OPERAND (d, 0)) != ADDR_EXPR)
2052 fail = true;
2053 else
2054 d = TREE_OPERAND (d, 0);
2055 break;
2056 default:
2057 break;
2059 if (!fail)
2061 SET_DECL_DEBUG_EXPR (repl, debug_expr);
2062 DECL_HAS_DEBUG_EXPR_P (repl) = 1;
2064 if (access->grp_no_warning)
2065 TREE_NO_WARNING (repl) = 1;
2066 else
2067 TREE_NO_WARNING (repl) = TREE_NO_WARNING (access->base);
2069 else
2070 TREE_NO_WARNING (repl) = 1;
2072 if (dump_file)
2074 if (access->grp_to_be_debug_replaced)
2076 fprintf (dump_file, "Created a debug-only replacement for ");
2077 print_generic_expr (dump_file, access->base, 0);
2078 fprintf (dump_file, " offset: %u, size: %u\n",
2079 (unsigned) access->offset, (unsigned) access->size);
2081 else
2083 fprintf (dump_file, "Created a replacement for ");
2084 print_generic_expr (dump_file, access->base, 0);
2085 fprintf (dump_file, " offset: %u, size: %u: ",
2086 (unsigned) access->offset, (unsigned) access->size);
2087 print_generic_expr (dump_file, repl, 0);
2088 fprintf (dump_file, "\n");
2091 sra_stats.replacements++;
2093 return repl;
2096 /* Return ACCESS scalar replacement, create it if it does not exist yet. */
2098 static inline tree
2099 get_access_replacement (struct access *access)
2101 gcc_checking_assert (access->replacement_decl);
2102 return access->replacement_decl;
2106 /* Build a subtree of accesses rooted in *ACCESS, and move the pointer in the
2107 linked list along the way. Stop when *ACCESS is NULL or the access pointed
2108 to it is not "within" the root. Return false iff some accesses partially
2109 overlap. */
2111 static bool
2112 build_access_subtree (struct access **access)
2114 struct access *root = *access, *last_child = NULL;
2115 HOST_WIDE_INT limit = root->offset + root->size;
2117 *access = (*access)->next_grp;
2118 while (*access && (*access)->offset + (*access)->size <= limit)
2120 if (!last_child)
2121 root->first_child = *access;
2122 else
2123 last_child->next_sibling = *access;
2124 last_child = *access;
2126 if (!build_access_subtree (access))
2127 return false;
2130 if (*access && (*access)->offset < limit)
2131 return false;
2133 return true;
2136 /* Build a tree of access representatives, ACCESS is the pointer to the first
2137 one, others are linked in a list by the next_grp field. Return false iff
2138 some accesses partially overlap. */
2140 static bool
2141 build_access_trees (struct access *access)
2143 while (access)
2145 struct access *root = access;
2147 if (!build_access_subtree (&access))
2148 return false;
2149 root->next_grp = access;
2151 return true;
2154 /* Return true if expr contains some ARRAY_REFs into a variable bounded
2155 array. */
2157 static bool
2158 expr_with_var_bounded_array_refs_p (tree expr)
2160 while (handled_component_p (expr))
2162 if (TREE_CODE (expr) == ARRAY_REF
2163 && !tree_fits_shwi_p (array_ref_low_bound (expr)))
2164 return true;
2165 expr = TREE_OPERAND (expr, 0);
2167 return false;
2170 /* Analyze the subtree of accesses rooted in ROOT, scheduling replacements when
2171 both seeming beneficial and when ALLOW_REPLACEMENTS allows it. Also set all
2172 sorts of access flags appropriately along the way, notably always set
2173 grp_read and grp_assign_read according to MARK_READ and grp_write when
2174 MARK_WRITE is true.
2176 Creating a replacement for a scalar access is considered beneficial if its
2177 grp_hint is set (this means we are either attempting total scalarization or
2178 there is more than one direct read access) or according to the following
2179 table:
2181 Access written to through a scalar type (once or more times)
2183 | Written to in an assignment statement
2185 | | Access read as scalar _once_
2186 | | |
2187 | | | Read in an assignment statement
2188 | | | |
2189 | | | | Scalarize Comment
2190 -----------------------------------------------------------------------------
2191 0 0 0 0 No access for the scalar
2192 0 0 0 1 No access for the scalar
2193 0 0 1 0 No Single read - won't help
2194 0 0 1 1 No The same case
2195 0 1 0 0 No access for the scalar
2196 0 1 0 1 No access for the scalar
2197 0 1 1 0 Yes s = *g; return s.i;
2198 0 1 1 1 Yes The same case as above
2199 1 0 0 0 No Won't help
2200 1 0 0 1 Yes s.i = 1; *g = s;
2201 1 0 1 0 Yes s.i = 5; g = s.i;
2202 1 0 1 1 Yes The same case as above
2203 1 1 0 0 No Won't help.
2204 1 1 0 1 Yes s.i = 1; *g = s;
2205 1 1 1 0 Yes s = *g; return s.i;
2206 1 1 1 1 Yes Any of the above yeses */
2208 static bool
2209 analyze_access_subtree (struct access *root, struct access *parent,
2210 bool allow_replacements)
2212 struct access *child;
2213 HOST_WIDE_INT limit = root->offset + root->size;
2214 HOST_WIDE_INT covered_to = root->offset;
2215 bool scalar = is_gimple_reg_type (root->type);
2216 bool hole = false, sth_created = false;
2218 if (parent)
2220 if (parent->grp_read)
2221 root->grp_read = 1;
2222 if (parent->grp_assignment_read)
2223 root->grp_assignment_read = 1;
2224 if (parent->grp_write)
2225 root->grp_write = 1;
2226 if (parent->grp_assignment_write)
2227 root->grp_assignment_write = 1;
2228 if (parent->grp_total_scalarization)
2229 root->grp_total_scalarization = 1;
2232 if (root->grp_unscalarizable_region)
2233 allow_replacements = false;
2235 if (allow_replacements && expr_with_var_bounded_array_refs_p (root->expr))
2236 allow_replacements = false;
2238 for (child = root->first_child; child; child = child->next_sibling)
2240 hole |= covered_to < child->offset;
2241 sth_created |= analyze_access_subtree (child, root,
2242 allow_replacements && !scalar);
2244 root->grp_unscalarized_data |= child->grp_unscalarized_data;
2245 root->grp_total_scalarization &= child->grp_total_scalarization;
2246 if (child->grp_covered)
2247 covered_to += child->size;
2248 else
2249 hole = true;
2252 if (allow_replacements && scalar && !root->first_child
2253 && (root->grp_hint
2254 || ((root->grp_scalar_read || root->grp_assignment_read)
2255 && (root->grp_scalar_write || root->grp_assignment_write))))
2257 /* Always create access replacements that cover the whole access.
2258 For integral types this means the precision has to match.
2259 Avoid assumptions based on the integral type kind, too. */
2260 if (INTEGRAL_TYPE_P (root->type)
2261 && (TREE_CODE (root->type) != INTEGER_TYPE
2262 || TYPE_PRECISION (root->type) != root->size)
2263 /* But leave bitfield accesses alone. */
2264 && (TREE_CODE (root->expr) != COMPONENT_REF
2265 || !DECL_BIT_FIELD (TREE_OPERAND (root->expr, 1))))
2267 tree rt = root->type;
2268 gcc_assert ((root->offset % BITS_PER_UNIT) == 0
2269 && (root->size % BITS_PER_UNIT) == 0);
2270 root->type = build_nonstandard_integer_type (root->size,
2271 TYPE_UNSIGNED (rt));
2272 root->expr = build_ref_for_offset (UNKNOWN_LOCATION,
2273 root->base, root->offset,
2274 root->type, NULL, false);
2276 if (dump_file && (dump_flags & TDF_DETAILS))
2278 fprintf (dump_file, "Changing the type of a replacement for ");
2279 print_generic_expr (dump_file, root->base, 0);
2280 fprintf (dump_file, " offset: %u, size: %u ",
2281 (unsigned) root->offset, (unsigned) root->size);
2282 fprintf (dump_file, " to an integer.\n");
2286 root->grp_to_be_replaced = 1;
2287 root->replacement_decl = create_access_replacement (root);
2288 sth_created = true;
2289 hole = false;
2291 else
2293 if (allow_replacements
2294 && scalar && !root->first_child
2295 && (root->grp_scalar_write || root->grp_assignment_write)
2296 && !bitmap_bit_p (cannot_scalarize_away_bitmap,
2297 DECL_UID (root->base)))
2299 gcc_checking_assert (!root->grp_scalar_read
2300 && !root->grp_assignment_read);
2301 sth_created = true;
2302 if (MAY_HAVE_DEBUG_STMTS)
2304 root->grp_to_be_debug_replaced = 1;
2305 root->replacement_decl = create_access_replacement (root);
2309 if (covered_to < limit)
2310 hole = true;
2311 if (scalar)
2312 root->grp_total_scalarization = 0;
2315 if (!hole || root->grp_total_scalarization)
2316 root->grp_covered = 1;
2317 else if (root->grp_write || TREE_CODE (root->base) == PARM_DECL)
2318 root->grp_unscalarized_data = 1; /* not covered and written to */
2319 return sth_created;
2322 /* Analyze all access trees linked by next_grp by the means of
2323 analyze_access_subtree. */
2324 static bool
2325 analyze_access_trees (struct access *access)
2327 bool ret = false;
2329 while (access)
2331 if (analyze_access_subtree (access, NULL, true))
2332 ret = true;
2333 access = access->next_grp;
2336 return ret;
2339 /* Return true iff a potential new child of LACC at offset OFFSET and with size
2340 SIZE would conflict with an already existing one. If exactly such a child
2341 already exists in LACC, store a pointer to it in EXACT_MATCH. */
2343 static bool
2344 child_would_conflict_in_lacc (struct access *lacc, HOST_WIDE_INT norm_offset,
2345 HOST_WIDE_INT size, struct access **exact_match)
2347 struct access *child;
2349 for (child = lacc->first_child; child; child = child->next_sibling)
2351 if (child->offset == norm_offset && child->size == size)
2353 *exact_match = child;
2354 return true;
2357 if (child->offset < norm_offset + size
2358 && child->offset + child->size > norm_offset)
2359 return true;
2362 return false;
2365 /* Create a new child access of PARENT, with all properties just like MODEL
2366 except for its offset and with its grp_write false and grp_read true.
2367 Return the new access or NULL if it cannot be created. Note that this access
2368 is created long after all splicing and sorting, it's not located in any
2369 access vector and is automatically a representative of its group. */
2371 static struct access *
2372 create_artificial_child_access (struct access *parent, struct access *model,
2373 HOST_WIDE_INT new_offset)
2375 struct access *access;
2376 struct access **child;
2377 tree expr = parent->base;
2379 gcc_assert (!model->grp_unscalarizable_region);
2381 access = (struct access *) pool_alloc (access_pool);
2382 memset (access, 0, sizeof (struct access));
2383 if (!build_user_friendly_ref_for_offset (&expr, TREE_TYPE (expr), new_offset,
2384 model->type))
2386 access->grp_no_warning = true;
2387 expr = build_ref_for_model (EXPR_LOCATION (parent->base), parent->base,
2388 new_offset, model, NULL, false);
2391 access->base = parent->base;
2392 access->expr = expr;
2393 access->offset = new_offset;
2394 access->size = model->size;
2395 access->type = model->type;
2396 access->grp_write = true;
2397 access->grp_read = false;
2399 child = &parent->first_child;
2400 while (*child && (*child)->offset < new_offset)
2401 child = &(*child)->next_sibling;
2403 access->next_sibling = *child;
2404 *child = access;
2406 return access;
2410 /* Propagate all subaccesses of RACC across an assignment link to LACC. Return
2411 true if any new subaccess was created. Additionally, if RACC is a scalar
2412 access but LACC is not, change the type of the latter, if possible. */
2414 static bool
2415 propagate_subaccesses_across_link (struct access *lacc, struct access *racc)
2417 struct access *rchild;
2418 HOST_WIDE_INT norm_delta = lacc->offset - racc->offset;
2419 bool ret = false;
2421 if (is_gimple_reg_type (lacc->type)
2422 || lacc->grp_unscalarizable_region
2423 || racc->grp_unscalarizable_region)
2424 return false;
2426 if (is_gimple_reg_type (racc->type))
2428 if (!lacc->first_child && !racc->first_child)
2430 tree t = lacc->base;
2432 lacc->type = racc->type;
2433 if (build_user_friendly_ref_for_offset (&t, TREE_TYPE (t),
2434 lacc->offset, racc->type))
2435 lacc->expr = t;
2436 else
2438 lacc->expr = build_ref_for_model (EXPR_LOCATION (lacc->base),
2439 lacc->base, lacc->offset,
2440 racc, NULL, false);
2441 lacc->grp_no_warning = true;
2444 return false;
2447 for (rchild = racc->first_child; rchild; rchild = rchild->next_sibling)
2449 struct access *new_acc = NULL;
2450 HOST_WIDE_INT norm_offset = rchild->offset + norm_delta;
2452 if (rchild->grp_unscalarizable_region)
2453 continue;
2455 if (child_would_conflict_in_lacc (lacc, norm_offset, rchild->size,
2456 &new_acc))
2458 if (new_acc)
2460 rchild->grp_hint = 1;
2461 new_acc->grp_hint |= new_acc->grp_read;
2462 if (rchild->first_child)
2463 ret |= propagate_subaccesses_across_link (new_acc, rchild);
2465 continue;
2468 rchild->grp_hint = 1;
2469 new_acc = create_artificial_child_access (lacc, rchild, norm_offset);
2470 if (new_acc)
2472 ret = true;
2473 if (racc->first_child)
2474 propagate_subaccesses_across_link (new_acc, rchild);
2478 return ret;
2481 /* Propagate all subaccesses across assignment links. */
2483 static void
2484 propagate_all_subaccesses (void)
2486 while (work_queue_head)
2488 struct access *racc = pop_access_from_work_queue ();
2489 struct assign_link *link;
2491 gcc_assert (racc->first_link);
2493 for (link = racc->first_link; link; link = link->next)
2495 struct access *lacc = link->lacc;
2497 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
2498 continue;
2499 lacc = lacc->group_representative;
2500 if (propagate_subaccesses_across_link (lacc, racc)
2501 && lacc->first_link)
2502 add_access_to_work_queue (lacc);
2507 /* Go through all accesses collected throughout the (intraprocedural) analysis
2508 stage, exclude overlapping ones, identify representatives and build trees
2509 out of them, making decisions about scalarization on the way. Return true
2510 iff there are any to-be-scalarized variables after this stage. */
2512 static bool
2513 analyze_all_variable_accesses (void)
2515 int res = 0;
2516 bitmap tmp = BITMAP_ALLOC (NULL);
2517 bitmap_iterator bi;
2518 unsigned i;
2519 unsigned max_scalarization_size
2520 = (optimize_function_for_size_p (cfun)
2521 ? PARAM_VALUE (PARAM_SRA_MAX_SCALARIZATION_SIZE_SIZE)
2522 : PARAM_VALUE (PARAM_SRA_MAX_SCALARIZATION_SIZE_SPEED))
2523 * BITS_PER_UNIT;
2525 EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
2526 if (bitmap_bit_p (should_scalarize_away_bitmap, i)
2527 && !bitmap_bit_p (cannot_scalarize_away_bitmap, i))
2529 tree var = candidate (i);
2531 if (TREE_CODE (var) == VAR_DECL
2532 && type_consists_of_records_p (TREE_TYPE (var)))
2534 if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (var)))
2535 <= max_scalarization_size)
2537 completely_scalarize_var (var);
2538 if (dump_file && (dump_flags & TDF_DETAILS))
2540 fprintf (dump_file, "Will attempt to totally scalarize ");
2541 print_generic_expr (dump_file, var, 0);
2542 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
2545 else if (dump_file && (dump_flags & TDF_DETAILS))
2547 fprintf (dump_file, "Too big to totally scalarize: ");
2548 print_generic_expr (dump_file, var, 0);
2549 fprintf (dump_file, " (UID: %u)\n", DECL_UID (var));
2554 bitmap_copy (tmp, candidate_bitmap);
2555 EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
2557 tree var = candidate (i);
2558 struct access *access;
2560 access = sort_and_splice_var_accesses (var);
2561 if (!access || !build_access_trees (access))
2562 disqualify_candidate (var,
2563 "No or inhibitingly overlapping accesses.");
2566 propagate_all_subaccesses ();
2568 bitmap_copy (tmp, candidate_bitmap);
2569 EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
2571 tree var = candidate (i);
2572 struct access *access = get_first_repr_for_decl (var);
2574 if (analyze_access_trees (access))
2576 res++;
2577 if (dump_file && (dump_flags & TDF_DETAILS))
2579 fprintf (dump_file, "\nAccess trees for ");
2580 print_generic_expr (dump_file, var, 0);
2581 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
2582 dump_access_tree (dump_file, access);
2583 fprintf (dump_file, "\n");
2586 else
2587 disqualify_candidate (var, "No scalar replacements to be created.");
2590 BITMAP_FREE (tmp);
2592 if (res)
2594 statistics_counter_event (cfun, "Scalarized aggregates", res);
2595 return true;
2597 else
2598 return false;
2601 /* Generate statements copying scalar replacements of accesses within a subtree
2602 into or out of AGG. ACCESS, all its children, siblings and their children
2603 are to be processed. AGG is an aggregate type expression (can be a
2604 declaration but does not have to be, it can for example also be a mem_ref or
2605 a series of handled components). TOP_OFFSET is the offset of the processed
2606 subtree which has to be subtracted from offsets of individual accesses to
2607 get corresponding offsets for AGG. If CHUNK_SIZE is non-null, copy only
2608 replacements in the interval <start_offset, start_offset + chunk_size>,
2609 otherwise copy all. GSI is a statement iterator used to place the new
2610 statements. WRITE should be true when the statements should write from AGG
2611 to the replacement and false if vice versa. if INSERT_AFTER is true, new
2612 statements will be added after the current statement in GSI, they will be
2613 added before the statement otherwise. */
2615 static void
2616 generate_subtree_copies (struct access *access, tree agg,
2617 HOST_WIDE_INT top_offset,
2618 HOST_WIDE_INT start_offset, HOST_WIDE_INT chunk_size,
2619 gimple_stmt_iterator *gsi, bool write,
2620 bool insert_after, location_t loc)
2624 if (chunk_size && access->offset >= start_offset + chunk_size)
2625 return;
2627 if (access->grp_to_be_replaced
2628 && (chunk_size == 0
2629 || access->offset + access->size > start_offset))
2631 tree expr, repl = get_access_replacement (access);
2632 gassign *stmt;
2634 expr = build_ref_for_model (loc, agg, access->offset - top_offset,
2635 access, gsi, insert_after);
2637 if (write)
2639 if (access->grp_partial_lhs)
2640 expr = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
2641 !insert_after,
2642 insert_after ? GSI_NEW_STMT
2643 : GSI_SAME_STMT);
2644 stmt = gimple_build_assign (repl, expr);
2646 else
2648 TREE_NO_WARNING (repl) = 1;
2649 if (access->grp_partial_lhs)
2650 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
2651 !insert_after,
2652 insert_after ? GSI_NEW_STMT
2653 : GSI_SAME_STMT);
2654 stmt = gimple_build_assign (expr, repl);
2656 gimple_set_location (stmt, loc);
2658 if (insert_after)
2659 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2660 else
2661 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2662 update_stmt (stmt);
2663 sra_stats.subtree_copies++;
2665 else if (write
2666 && access->grp_to_be_debug_replaced
2667 && (chunk_size == 0
2668 || access->offset + access->size > start_offset))
2670 gdebug *ds;
2671 tree drhs = build_debug_ref_for_model (loc, agg,
2672 access->offset - top_offset,
2673 access);
2674 ds = gimple_build_debug_bind (get_access_replacement (access),
2675 drhs, gsi_stmt (*gsi));
2676 if (insert_after)
2677 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
2678 else
2679 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
2682 if (access->first_child)
2683 generate_subtree_copies (access->first_child, agg, top_offset,
2684 start_offset, chunk_size, gsi,
2685 write, insert_after, loc);
2687 access = access->next_sibling;
2689 while (access);
2692 /* Assign zero to all scalar replacements in an access subtree. ACCESS is the
2693 the root of the subtree to be processed. GSI is the statement iterator used
2694 for inserting statements which are added after the current statement if
2695 INSERT_AFTER is true or before it otherwise. */
2697 static void
2698 init_subtree_with_zero (struct access *access, gimple_stmt_iterator *gsi,
2699 bool insert_after, location_t loc)
2702 struct access *child;
2704 if (access->grp_to_be_replaced)
2706 gassign *stmt;
2708 stmt = gimple_build_assign (get_access_replacement (access),
2709 build_zero_cst (access->type));
2710 if (insert_after)
2711 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2712 else
2713 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2714 update_stmt (stmt);
2715 gimple_set_location (stmt, loc);
2717 else if (access->grp_to_be_debug_replaced)
2719 gdebug *ds
2720 = gimple_build_debug_bind (get_access_replacement (access),
2721 build_zero_cst (access->type),
2722 gsi_stmt (*gsi));
2723 if (insert_after)
2724 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
2725 else
2726 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
2729 for (child = access->first_child; child; child = child->next_sibling)
2730 init_subtree_with_zero (child, gsi, insert_after, loc);
2733 /* Clobber all scalar replacements in an access subtree. ACCESS is the the
2734 root of the subtree to be processed. GSI is the statement iterator used
2735 for inserting statements which are added after the current statement if
2736 INSERT_AFTER is true or before it otherwise. */
2738 static void
2739 clobber_subtree (struct access *access, gimple_stmt_iterator *gsi,
2740 bool insert_after, location_t loc)
2743 struct access *child;
2745 if (access->grp_to_be_replaced)
2747 tree rep = get_access_replacement (access);
2748 tree clobber = build_constructor (access->type, NULL);
2749 TREE_THIS_VOLATILE (clobber) = 1;
2750 gimple stmt = gimple_build_assign (rep, clobber);
2752 if (insert_after)
2753 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2754 else
2755 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2756 update_stmt (stmt);
2757 gimple_set_location (stmt, loc);
2760 for (child = access->first_child; child; child = child->next_sibling)
2761 clobber_subtree (child, gsi, insert_after, loc);
2764 /* Search for an access representative for the given expression EXPR and
2765 return it or NULL if it cannot be found. */
2767 static struct access *
2768 get_access_for_expr (tree expr)
2770 HOST_WIDE_INT offset, size, max_size;
2771 tree base;
2773 /* FIXME: This should not be necessary but Ada produces V_C_Es with a type of
2774 a different size than the size of its argument and we need the latter
2775 one. */
2776 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
2777 expr = TREE_OPERAND (expr, 0);
2779 base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
2780 if (max_size == -1 || !DECL_P (base))
2781 return NULL;
2783 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
2784 return NULL;
2786 return get_var_base_offset_size_access (base, offset, max_size);
2789 /* Replace the expression EXPR with a scalar replacement if there is one and
2790 generate other statements to do type conversion or subtree copying if
2791 necessary. GSI is used to place newly created statements, WRITE is true if
2792 the expression is being written to (it is on a LHS of a statement or output
2793 in an assembly statement). */
2795 static bool
2796 sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
2798 location_t loc;
2799 struct access *access;
2800 tree type, bfr, orig_expr;
2802 if (TREE_CODE (*expr) == BIT_FIELD_REF)
2804 bfr = *expr;
2805 expr = &TREE_OPERAND (*expr, 0);
2807 else
2808 bfr = NULL_TREE;
2810 if (TREE_CODE (*expr) == REALPART_EXPR || TREE_CODE (*expr) == IMAGPART_EXPR)
2811 expr = &TREE_OPERAND (*expr, 0);
2812 access = get_access_for_expr (*expr);
2813 if (!access)
2814 return false;
2815 type = TREE_TYPE (*expr);
2816 orig_expr = *expr;
2818 loc = gimple_location (gsi_stmt (*gsi));
2819 gimple_stmt_iterator alt_gsi = gsi_none ();
2820 if (write && stmt_ends_bb_p (gsi_stmt (*gsi)))
2822 alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi)));
2823 gsi = &alt_gsi;
2826 if (access->grp_to_be_replaced)
2828 tree repl = get_access_replacement (access);
2829 /* If we replace a non-register typed access simply use the original
2830 access expression to extract the scalar component afterwards.
2831 This happens if scalarizing a function return value or parameter
2832 like in gcc.c-torture/execute/20041124-1.c, 20050316-1.c and
2833 gcc.c-torture/compile/20011217-1.c.
2835 We also want to use this when accessing a complex or vector which can
2836 be accessed as a different type too, potentially creating a need for
2837 type conversion (see PR42196) and when scalarized unions are involved
2838 in assembler statements (see PR42398). */
2839 if (!useless_type_conversion_p (type, access->type))
2841 tree ref;
2843 ref = build_ref_for_model (loc, orig_expr, 0, access, gsi, false);
2845 if (write)
2847 gassign *stmt;
2849 if (access->grp_partial_lhs)
2850 ref = force_gimple_operand_gsi (gsi, ref, true, NULL_TREE,
2851 false, GSI_NEW_STMT);
2852 stmt = gimple_build_assign (repl, ref);
2853 gimple_set_location (stmt, loc);
2854 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2856 else
2858 gassign *stmt;
2860 if (access->grp_partial_lhs)
2861 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
2862 true, GSI_SAME_STMT);
2863 stmt = gimple_build_assign (ref, repl);
2864 gimple_set_location (stmt, loc);
2865 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2868 else
2869 *expr = repl;
2870 sra_stats.exprs++;
2872 else if (write && access->grp_to_be_debug_replaced)
2874 gdebug *ds = gimple_build_debug_bind (get_access_replacement (access),
2875 NULL_TREE,
2876 gsi_stmt (*gsi));
2877 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
2880 if (access->first_child)
2882 HOST_WIDE_INT start_offset, chunk_size;
2883 if (bfr
2884 && tree_fits_uhwi_p (TREE_OPERAND (bfr, 1))
2885 && tree_fits_uhwi_p (TREE_OPERAND (bfr, 2)))
2887 chunk_size = tree_to_uhwi (TREE_OPERAND (bfr, 1));
2888 start_offset = access->offset
2889 + tree_to_uhwi (TREE_OPERAND (bfr, 2));
2891 else
2892 start_offset = chunk_size = 0;
2894 generate_subtree_copies (access->first_child, orig_expr, access->offset,
2895 start_offset, chunk_size, gsi, write, write,
2896 loc);
2898 return true;
2901 /* Where scalar replacements of the RHS have been written to when a replacement
2902 of a LHS of an assigments cannot be direclty loaded from a replacement of
2903 the RHS. */
2904 enum unscalarized_data_handling { SRA_UDH_NONE, /* Nothing done so far. */
2905 SRA_UDH_RIGHT, /* Data flushed to the RHS. */
2906 SRA_UDH_LEFT }; /* Data flushed to the LHS. */
2908 struct subreplacement_assignment_data
2910 /* Offset of the access representing the lhs of the assignment. */
2911 HOST_WIDE_INT left_offset;
2913 /* LHS and RHS of the original assignment. */
2914 tree assignment_lhs, assignment_rhs;
2916 /* Access representing the rhs of the whole assignment. */
2917 struct access *top_racc;
2919 /* Stmt iterator used for statement insertions after the original assignment.
2920 It points to the main GSI used to traverse a BB during function body
2921 modification. */
2922 gimple_stmt_iterator *new_gsi;
2924 /* Stmt iterator used for statement insertions before the original
2925 assignment. Keeps on pointing to the original statement. */
2926 gimple_stmt_iterator old_gsi;
2928 /* Location of the assignment. */
2929 location_t loc;
2931 /* Keeps the information whether we have needed to refresh replacements of
2932 the LHS and from which side of the assignments this takes place. */
2933 enum unscalarized_data_handling refreshed;
2936 /* Store all replacements in the access tree rooted in TOP_RACC either to their
2937 base aggregate if there are unscalarized data or directly to LHS of the
2938 statement that is pointed to by GSI otherwise. */
2940 static void
2941 handle_unscalarized_data_in_subtree (struct subreplacement_assignment_data *sad)
2943 tree src;
2944 if (sad->top_racc->grp_unscalarized_data)
2946 src = sad->assignment_rhs;
2947 sad->refreshed = SRA_UDH_RIGHT;
2949 else
2951 src = sad->assignment_lhs;
2952 sad->refreshed = SRA_UDH_LEFT;
2954 generate_subtree_copies (sad->top_racc->first_child, src,
2955 sad->top_racc->offset, 0, 0,
2956 &sad->old_gsi, false, false, sad->loc);
2959 /* Try to generate statements to load all sub-replacements in an access subtree
2960 formed by children of LACC from scalar replacements in the SAD->top_racc
2961 subtree. If that is not possible, refresh the SAD->top_racc base aggregate
2962 and load the accesses from it. */
2964 static void
2965 load_assign_lhs_subreplacements (struct access *lacc,
2966 struct subreplacement_assignment_data *sad)
2968 for (lacc = lacc->first_child; lacc; lacc = lacc->next_sibling)
2970 HOST_WIDE_INT offset;
2971 offset = lacc->offset - sad->left_offset + sad->top_racc->offset;
2973 if (lacc->grp_to_be_replaced)
2975 struct access *racc;
2976 gassign *stmt;
2977 tree rhs;
2979 racc = find_access_in_subtree (sad->top_racc, offset, lacc->size);
2980 if (racc && racc->grp_to_be_replaced)
2982 rhs = get_access_replacement (racc);
2983 if (!useless_type_conversion_p (lacc->type, racc->type))
2984 rhs = fold_build1_loc (sad->loc, VIEW_CONVERT_EXPR,
2985 lacc->type, rhs);
2987 if (racc->grp_partial_lhs && lacc->grp_partial_lhs)
2988 rhs = force_gimple_operand_gsi (&sad->old_gsi, rhs, true,
2989 NULL_TREE, true, GSI_SAME_STMT);
2991 else
2993 /* No suitable access on the right hand side, need to load from
2994 the aggregate. See if we have to update it first... */
2995 if (sad->refreshed == SRA_UDH_NONE)
2996 handle_unscalarized_data_in_subtree (sad);
2998 if (sad->refreshed == SRA_UDH_LEFT)
2999 rhs = build_ref_for_model (sad->loc, sad->assignment_lhs,
3000 lacc->offset - sad->left_offset,
3001 lacc, sad->new_gsi, true);
3002 else
3003 rhs = build_ref_for_model (sad->loc, sad->assignment_rhs,
3004 lacc->offset - sad->left_offset,
3005 lacc, sad->new_gsi, true);
3006 if (lacc->grp_partial_lhs)
3007 rhs = force_gimple_operand_gsi (sad->new_gsi,
3008 rhs, true, NULL_TREE,
3009 false, GSI_NEW_STMT);
3012 stmt = gimple_build_assign (get_access_replacement (lacc), rhs);
3013 gsi_insert_after (sad->new_gsi, stmt, GSI_NEW_STMT);
3014 gimple_set_location (stmt, sad->loc);
3015 update_stmt (stmt);
3016 sra_stats.subreplacements++;
3018 else
3020 if (sad->refreshed == SRA_UDH_NONE
3021 && lacc->grp_read && !lacc->grp_covered)
3022 handle_unscalarized_data_in_subtree (sad);
3024 if (lacc && lacc->grp_to_be_debug_replaced)
3026 gdebug *ds;
3027 tree drhs;
3028 struct access *racc = find_access_in_subtree (sad->top_racc,
3029 offset,
3030 lacc->size);
3032 if (racc && racc->grp_to_be_replaced)
3034 if (racc->grp_write)
3035 drhs = get_access_replacement (racc);
3036 else
3037 drhs = NULL;
3039 else if (sad->refreshed == SRA_UDH_LEFT)
3040 drhs = build_debug_ref_for_model (sad->loc, lacc->base,
3041 lacc->offset, lacc);
3042 else if (sad->refreshed == SRA_UDH_RIGHT)
3043 drhs = build_debug_ref_for_model (sad->loc, sad->top_racc->base,
3044 offset, lacc);
3045 else
3046 drhs = NULL_TREE;
3047 if (drhs
3048 && !useless_type_conversion_p (lacc->type, TREE_TYPE (drhs)))
3049 drhs = fold_build1_loc (sad->loc, VIEW_CONVERT_EXPR,
3050 lacc->type, drhs);
3051 ds = gimple_build_debug_bind (get_access_replacement (lacc),
3052 drhs, gsi_stmt (sad->old_gsi));
3053 gsi_insert_after (sad->new_gsi, ds, GSI_NEW_STMT);
3057 if (lacc->first_child)
3058 load_assign_lhs_subreplacements (lacc, sad);
3062 /* Result code for SRA assignment modification. */
3063 enum assignment_mod_result { SRA_AM_NONE, /* nothing done for the stmt */
3064 SRA_AM_MODIFIED, /* stmt changed but not
3065 removed */
3066 SRA_AM_REMOVED }; /* stmt eliminated */
3068 /* Modify assignments with a CONSTRUCTOR on their RHS. STMT contains a pointer
3069 to the assignment and GSI is the statement iterator pointing at it. Returns
3070 the same values as sra_modify_assign. */
3072 static enum assignment_mod_result
3073 sra_modify_constructor_assign (gimple stmt, gimple_stmt_iterator *gsi)
3075 tree lhs = gimple_assign_lhs (stmt);
3076 struct access *acc = get_access_for_expr (lhs);
3077 if (!acc)
3078 return SRA_AM_NONE;
3079 location_t loc = gimple_location (stmt);
3081 if (gimple_clobber_p (stmt))
3083 /* Clobber the replacement variable. */
3084 clobber_subtree (acc, gsi, !acc->grp_covered, loc);
3085 /* Remove clobbers of fully scalarized variables, they are dead. */
3086 if (acc->grp_covered)
3088 unlink_stmt_vdef (stmt);
3089 gsi_remove (gsi, true);
3090 release_defs (stmt);
3091 return SRA_AM_REMOVED;
3093 else
3094 return SRA_AM_MODIFIED;
3097 if (vec_safe_length (CONSTRUCTOR_ELTS (gimple_assign_rhs1 (stmt))) > 0)
3099 /* I have never seen this code path trigger but if it can happen the
3100 following should handle it gracefully. */
3101 if (access_has_children_p (acc))
3102 generate_subtree_copies (acc->first_child, lhs, acc->offset, 0, 0, gsi,
3103 true, true, loc);
3104 return SRA_AM_MODIFIED;
3107 if (acc->grp_covered)
3109 init_subtree_with_zero (acc, gsi, false, loc);
3110 unlink_stmt_vdef (stmt);
3111 gsi_remove (gsi, true);
3112 release_defs (stmt);
3113 return SRA_AM_REMOVED;
3115 else
3117 init_subtree_with_zero (acc, gsi, true, loc);
3118 return SRA_AM_MODIFIED;
3122 /* Create and return a new suitable default definition SSA_NAME for RACC which
3123 is an access describing an uninitialized part of an aggregate that is being
3124 loaded. */
3126 static tree
3127 get_repl_default_def_ssa_name (struct access *racc)
3129 gcc_checking_assert (!racc->grp_to_be_replaced
3130 && !racc->grp_to_be_debug_replaced);
3131 if (!racc->replacement_decl)
3132 racc->replacement_decl = create_access_replacement (racc);
3133 return get_or_create_ssa_default_def (cfun, racc->replacement_decl);
3136 /* Return true if REF has an VIEW_CONVERT_EXPR or a COMPONENT_REF with a
3137 bit-field field declaration somewhere in it. */
3139 static inline bool
3140 contains_vce_or_bfcref_p (const_tree ref)
3142 while (handled_component_p (ref))
3144 if (TREE_CODE (ref) == VIEW_CONVERT_EXPR
3145 || (TREE_CODE (ref) == COMPONENT_REF
3146 && DECL_BIT_FIELD (TREE_OPERAND (ref, 1))))
3147 return true;
3148 ref = TREE_OPERAND (ref, 0);
3151 return false;
3154 /* Examine both sides of the assignment statement pointed to by STMT, replace
3155 them with a scalare replacement if there is one and generate copying of
3156 replacements if scalarized aggregates have been used in the assignment. GSI
3157 is used to hold generated statements for type conversions and subtree
3158 copying. */
3160 static enum assignment_mod_result
3161 sra_modify_assign (gimple stmt, gimple_stmt_iterator *gsi)
3163 struct access *lacc, *racc;
3164 tree lhs, rhs;
3165 bool modify_this_stmt = false;
3166 bool force_gimple_rhs = false;
3167 location_t loc;
3168 gimple_stmt_iterator orig_gsi = *gsi;
3170 if (!gimple_assign_single_p (stmt))
3171 return SRA_AM_NONE;
3172 lhs = gimple_assign_lhs (stmt);
3173 rhs = gimple_assign_rhs1 (stmt);
3175 if (TREE_CODE (rhs) == CONSTRUCTOR)
3176 return sra_modify_constructor_assign (stmt, gsi);
3178 if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (lhs) == REALPART_EXPR
3179 || TREE_CODE (rhs) == IMAGPART_EXPR || TREE_CODE (lhs) == IMAGPART_EXPR
3180 || TREE_CODE (rhs) == BIT_FIELD_REF || TREE_CODE (lhs) == BIT_FIELD_REF)
3182 modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (stmt),
3183 gsi, false);
3184 modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (stmt),
3185 gsi, true);
3186 return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
3189 lacc = get_access_for_expr (lhs);
3190 racc = get_access_for_expr (rhs);
3191 if (!lacc && !racc)
3192 return SRA_AM_NONE;
3194 loc = gimple_location (stmt);
3195 if (lacc && lacc->grp_to_be_replaced)
3197 lhs = get_access_replacement (lacc);
3198 gimple_assign_set_lhs (stmt, lhs);
3199 modify_this_stmt = true;
3200 if (lacc->grp_partial_lhs)
3201 force_gimple_rhs = true;
3202 sra_stats.exprs++;
3205 if (racc && racc->grp_to_be_replaced)
3207 rhs = get_access_replacement (racc);
3208 modify_this_stmt = true;
3209 if (racc->grp_partial_lhs)
3210 force_gimple_rhs = true;
3211 sra_stats.exprs++;
3213 else if (racc
3214 && !racc->grp_unscalarized_data
3215 && TREE_CODE (lhs) == SSA_NAME
3216 && !access_has_replacements_p (racc))
3218 rhs = get_repl_default_def_ssa_name (racc);
3219 modify_this_stmt = true;
3220 sra_stats.exprs++;
3223 if (modify_this_stmt)
3225 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
3227 /* If we can avoid creating a VIEW_CONVERT_EXPR do so.
3228 ??? This should move to fold_stmt which we simply should
3229 call after building a VIEW_CONVERT_EXPR here. */
3230 if (AGGREGATE_TYPE_P (TREE_TYPE (lhs))
3231 && !contains_bitfld_component_ref_p (lhs))
3233 lhs = build_ref_for_model (loc, lhs, 0, racc, gsi, false);
3234 gimple_assign_set_lhs (stmt, lhs);
3236 else if (AGGREGATE_TYPE_P (TREE_TYPE (rhs))
3237 && !contains_vce_or_bfcref_p (rhs))
3238 rhs = build_ref_for_model (loc, rhs, 0, lacc, gsi, false);
3240 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
3242 rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
3243 rhs);
3244 if (is_gimple_reg_type (TREE_TYPE (lhs))
3245 && TREE_CODE (lhs) != SSA_NAME)
3246 force_gimple_rhs = true;
3251 if (lacc && lacc->grp_to_be_debug_replaced)
3253 tree dlhs = get_access_replacement (lacc);
3254 tree drhs = unshare_expr (rhs);
3255 if (!useless_type_conversion_p (TREE_TYPE (dlhs), TREE_TYPE (drhs)))
3257 if (AGGREGATE_TYPE_P (TREE_TYPE (drhs))
3258 && !contains_vce_or_bfcref_p (drhs))
3259 drhs = build_debug_ref_for_model (loc, drhs, 0, lacc);
3260 if (drhs
3261 && !useless_type_conversion_p (TREE_TYPE (dlhs),
3262 TREE_TYPE (drhs)))
3263 drhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
3264 TREE_TYPE (dlhs), drhs);
3266 gdebug *ds = gimple_build_debug_bind (dlhs, drhs, stmt);
3267 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
3270 /* From this point on, the function deals with assignments in between
3271 aggregates when at least one has scalar reductions of some of its
3272 components. There are three possible scenarios: Both the LHS and RHS have
3273 to-be-scalarized components, 2) only the RHS has or 3) only the LHS has.
3275 In the first case, we would like to load the LHS components from RHS
3276 components whenever possible. If that is not possible, we would like to
3277 read it directly from the RHS (after updating it by storing in it its own
3278 components). If there are some necessary unscalarized data in the LHS,
3279 those will be loaded by the original assignment too. If neither of these
3280 cases happen, the original statement can be removed. Most of this is done
3281 by load_assign_lhs_subreplacements.
3283 In the second case, we would like to store all RHS scalarized components
3284 directly into LHS and if they cover the aggregate completely, remove the
3285 statement too. In the third case, we want the LHS components to be loaded
3286 directly from the RHS (DSE will remove the original statement if it
3287 becomes redundant).
3289 This is a bit complex but manageable when types match and when unions do
3290 not cause confusion in a way that we cannot really load a component of LHS
3291 from the RHS or vice versa (the access representing this level can have
3292 subaccesses that are accessible only through a different union field at a
3293 higher level - different from the one used in the examined expression).
3294 Unions are fun.
3296 Therefore, I specially handle a fourth case, happening when there is a
3297 specific type cast or it is impossible to locate a scalarized subaccess on
3298 the other side of the expression. If that happens, I simply "refresh" the
3299 RHS by storing in it is scalarized components leave the original statement
3300 there to do the copying and then load the scalar replacements of the LHS.
3301 This is what the first branch does. */
3303 if (modify_this_stmt
3304 || gimple_has_volatile_ops (stmt)
3305 || contains_vce_or_bfcref_p (rhs)
3306 || contains_vce_or_bfcref_p (lhs)
3307 || stmt_ends_bb_p (stmt))
3309 if (access_has_children_p (racc))
3310 generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0,
3311 gsi, false, false, loc);
3312 if (access_has_children_p (lacc))
3314 gimple_stmt_iterator alt_gsi = gsi_none ();
3315 if (stmt_ends_bb_p (stmt))
3317 alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi)));
3318 gsi = &alt_gsi;
3320 generate_subtree_copies (lacc->first_child, lhs, lacc->offset, 0, 0,
3321 gsi, true, true, loc);
3323 sra_stats.separate_lhs_rhs_handling++;
3325 /* This gimplification must be done after generate_subtree_copies,
3326 lest we insert the subtree copies in the middle of the gimplified
3327 sequence. */
3328 if (force_gimple_rhs)
3329 rhs = force_gimple_operand_gsi (&orig_gsi, rhs, true, NULL_TREE,
3330 true, GSI_SAME_STMT);
3331 if (gimple_assign_rhs1 (stmt) != rhs)
3333 modify_this_stmt = true;
3334 gimple_assign_set_rhs_from_tree (&orig_gsi, rhs);
3335 gcc_assert (stmt == gsi_stmt (orig_gsi));
3338 return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
3340 else
3342 if (access_has_children_p (lacc)
3343 && access_has_children_p (racc)
3344 /* When an access represents an unscalarizable region, it usually
3345 represents accesses with variable offset and thus must not be used
3346 to generate new memory accesses. */
3347 && !lacc->grp_unscalarizable_region
3348 && !racc->grp_unscalarizable_region)
3350 struct subreplacement_assignment_data sad;
3352 sad.left_offset = lacc->offset;
3353 sad.assignment_lhs = lhs;
3354 sad.assignment_rhs = rhs;
3355 sad.top_racc = racc;
3356 sad.old_gsi = *gsi;
3357 sad.new_gsi = gsi;
3358 sad.loc = gimple_location (stmt);
3359 sad.refreshed = SRA_UDH_NONE;
3361 if (lacc->grp_read && !lacc->grp_covered)
3362 handle_unscalarized_data_in_subtree (&sad);
3364 load_assign_lhs_subreplacements (lacc, &sad);
3365 if (sad.refreshed != SRA_UDH_RIGHT)
3367 gsi_next (gsi);
3368 unlink_stmt_vdef (stmt);
3369 gsi_remove (&sad.old_gsi, true);
3370 release_defs (stmt);
3371 sra_stats.deleted++;
3372 return SRA_AM_REMOVED;
3375 else
3377 if (access_has_children_p (racc)
3378 && !racc->grp_unscalarized_data)
3380 if (dump_file)
3382 fprintf (dump_file, "Removing load: ");
3383 print_gimple_stmt (dump_file, stmt, 0, 0);
3385 generate_subtree_copies (racc->first_child, lhs,
3386 racc->offset, 0, 0, gsi,
3387 false, false, loc);
3388 gcc_assert (stmt == gsi_stmt (*gsi));
3389 unlink_stmt_vdef (stmt);
3390 gsi_remove (gsi, true);
3391 release_defs (stmt);
3392 sra_stats.deleted++;
3393 return SRA_AM_REMOVED;
3395 /* Restore the aggregate RHS from its components so the
3396 prevailing aggregate copy does the right thing. */
3397 if (access_has_children_p (racc))
3398 generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0,
3399 gsi, false, false, loc);
3400 /* Re-load the components of the aggregate copy destination.
3401 But use the RHS aggregate to load from to expose more
3402 optimization opportunities. */
3403 if (access_has_children_p (lacc))
3404 generate_subtree_copies (lacc->first_child, rhs, lacc->offset,
3405 0, 0, gsi, true, true, loc);
3408 return SRA_AM_NONE;
3412 /* Traverse the function body and all modifications as decided in
3413 analyze_all_variable_accesses. Return true iff the CFG has been
3414 changed. */
3416 static bool
3417 sra_modify_function_body (void)
3419 bool cfg_changed = false;
3420 basic_block bb;
3422 FOR_EACH_BB_FN (bb, cfun)
3424 gimple_stmt_iterator gsi = gsi_start_bb (bb);
3425 while (!gsi_end_p (gsi))
3427 gimple stmt = gsi_stmt (gsi);
3428 enum assignment_mod_result assign_result;
3429 bool modified = false, deleted = false;
3430 tree *t;
3431 unsigned i;
3433 switch (gimple_code (stmt))
3435 case GIMPLE_RETURN:
3436 t = gimple_return_retval_ptr (as_a <greturn *> (stmt));
3437 if (*t != NULL_TREE)
3438 modified |= sra_modify_expr (t, &gsi, false);
3439 break;
3441 case GIMPLE_ASSIGN:
3442 assign_result = sra_modify_assign (stmt, &gsi);
3443 modified |= assign_result == SRA_AM_MODIFIED;
3444 deleted = assign_result == SRA_AM_REMOVED;
3445 break;
3447 case GIMPLE_CALL:
3448 /* Operands must be processed before the lhs. */
3449 for (i = 0; i < gimple_call_num_args (stmt); i++)
3451 t = gimple_call_arg_ptr (stmt, i);
3452 modified |= sra_modify_expr (t, &gsi, false);
3455 if (gimple_call_lhs (stmt))
3457 t = gimple_call_lhs_ptr (stmt);
3458 modified |= sra_modify_expr (t, &gsi, true);
3460 break;
3462 case GIMPLE_ASM:
3464 gasm *asm_stmt = as_a <gasm *> (stmt);
3465 for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
3467 t = &TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
3468 modified |= sra_modify_expr (t, &gsi, false);
3470 for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
3472 t = &TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
3473 modified |= sra_modify_expr (t, &gsi, true);
3476 break;
3478 default:
3479 break;
3482 if (modified)
3484 update_stmt (stmt);
3485 if (maybe_clean_eh_stmt (stmt)
3486 && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
3487 cfg_changed = true;
3489 if (!deleted)
3490 gsi_next (&gsi);
3494 gsi_commit_edge_inserts ();
3495 return cfg_changed;
3498 /* Generate statements initializing scalar replacements of parts of function
3499 parameters. */
3501 static void
3502 initialize_parameter_reductions (void)
3504 gimple_stmt_iterator gsi;
3505 gimple_seq seq = NULL;
3506 tree parm;
3508 gsi = gsi_start (seq);
3509 for (parm = DECL_ARGUMENTS (current_function_decl);
3510 parm;
3511 parm = DECL_CHAIN (parm))
3513 vec<access_p> *access_vec;
3514 struct access *access;
3516 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
3517 continue;
3518 access_vec = get_base_access_vector (parm);
3519 if (!access_vec)
3520 continue;
3522 for (access = (*access_vec)[0];
3523 access;
3524 access = access->next_grp)
3525 generate_subtree_copies (access, parm, 0, 0, 0, &gsi, true, true,
3526 EXPR_LOCATION (parm));
3529 seq = gsi_seq (gsi);
3530 if (seq)
3531 gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
3534 /* The "main" function of intraprocedural SRA passes. Runs the analysis and if
3535 it reveals there are components of some aggregates to be scalarized, it runs
3536 the required transformations. */
3537 static unsigned int
3538 perform_intra_sra (void)
3540 int ret = 0;
3541 sra_initialize ();
3543 if (!find_var_candidates ())
3544 goto out;
3546 if (!scan_function ())
3547 goto out;
3549 if (!analyze_all_variable_accesses ())
3550 goto out;
3552 if (sra_modify_function_body ())
3553 ret = TODO_update_ssa | TODO_cleanup_cfg;
3554 else
3555 ret = TODO_update_ssa;
3556 initialize_parameter_reductions ();
3558 statistics_counter_event (cfun, "Scalar replacements created",
3559 sra_stats.replacements);
3560 statistics_counter_event (cfun, "Modified expressions", sra_stats.exprs);
3561 statistics_counter_event (cfun, "Subtree copy stmts",
3562 sra_stats.subtree_copies);
3563 statistics_counter_event (cfun, "Subreplacement stmts",
3564 sra_stats.subreplacements);
3565 statistics_counter_event (cfun, "Deleted stmts", sra_stats.deleted);
3566 statistics_counter_event (cfun, "Separate LHS and RHS handling",
3567 sra_stats.separate_lhs_rhs_handling);
3569 out:
3570 sra_deinitialize ();
3571 return ret;
3574 /* Perform early intraprocedural SRA. */
3575 static unsigned int
3576 early_intra_sra (void)
3578 sra_mode = SRA_MODE_EARLY_INTRA;
3579 return perform_intra_sra ();
3582 /* Perform "late" intraprocedural SRA. */
3583 static unsigned int
3584 late_intra_sra (void)
3586 sra_mode = SRA_MODE_INTRA;
3587 return perform_intra_sra ();
3591 static bool
3592 gate_intra_sra (void)
3594 return flag_tree_sra != 0 && dbg_cnt (tree_sra);
3598 namespace {
3600 const pass_data pass_data_sra_early =
3602 GIMPLE_PASS, /* type */
3603 "esra", /* name */
3604 OPTGROUP_NONE, /* optinfo_flags */
3605 TV_TREE_SRA, /* tv_id */
3606 ( PROP_cfg | PROP_ssa ), /* properties_required */
3607 0, /* properties_provided */
3608 0, /* properties_destroyed */
3609 0, /* todo_flags_start */
3610 TODO_update_ssa, /* todo_flags_finish */
3613 class pass_sra_early : public gimple_opt_pass
3615 public:
3616 pass_sra_early (gcc::context *ctxt)
3617 : gimple_opt_pass (pass_data_sra_early, ctxt)
3620 /* opt_pass methods: */
3621 virtual bool gate (function *) { return gate_intra_sra (); }
3622 virtual unsigned int execute (function *) { return early_intra_sra (); }
3624 }; // class pass_sra_early
3626 } // anon namespace
3628 gimple_opt_pass *
3629 make_pass_sra_early (gcc::context *ctxt)
3631 return new pass_sra_early (ctxt);
3634 namespace {
3636 const pass_data pass_data_sra =
3638 GIMPLE_PASS, /* type */
3639 "sra", /* name */
3640 OPTGROUP_NONE, /* optinfo_flags */
3641 TV_TREE_SRA, /* tv_id */
3642 ( PROP_cfg | PROP_ssa ), /* properties_required */
3643 0, /* properties_provided */
3644 0, /* properties_destroyed */
3645 TODO_update_address_taken, /* todo_flags_start */
3646 TODO_update_ssa, /* todo_flags_finish */
3649 class pass_sra : public gimple_opt_pass
3651 public:
3652 pass_sra (gcc::context *ctxt)
3653 : gimple_opt_pass (pass_data_sra, ctxt)
3656 /* opt_pass methods: */
3657 virtual bool gate (function *) { return gate_intra_sra (); }
3658 virtual unsigned int execute (function *) { return late_intra_sra (); }
3660 }; // class pass_sra
3662 } // anon namespace
3664 gimple_opt_pass *
3665 make_pass_sra (gcc::context *ctxt)
3667 return new pass_sra (ctxt);
3671 /* Return true iff PARM (which must be a parm_decl) is an unused scalar
3672 parameter. */
3674 static bool
3675 is_unused_scalar_param (tree parm)
3677 tree name;
3678 return (is_gimple_reg (parm)
3679 && (!(name = ssa_default_def (cfun, parm))
3680 || has_zero_uses (name)));
3683 /* Scan immediate uses of a default definition SSA name of a parameter PARM and
3684 examine whether there are any direct or otherwise infeasible ones. If so,
3685 return true, otherwise return false. PARM must be a gimple register with a
3686 non-NULL default definition. */
3688 static bool
3689 ptr_parm_has_direct_uses (tree parm)
3691 imm_use_iterator ui;
3692 gimple stmt;
3693 tree name = ssa_default_def (cfun, parm);
3694 bool ret = false;
3696 FOR_EACH_IMM_USE_STMT (stmt, ui, name)
3698 int uses_ok = 0;
3699 use_operand_p use_p;
3701 if (is_gimple_debug (stmt))
3702 continue;
3704 /* Valid uses include dereferences on the lhs and the rhs. */
3705 if (gimple_has_lhs (stmt))
3707 tree lhs = gimple_get_lhs (stmt);
3708 while (handled_component_p (lhs))
3709 lhs = TREE_OPERAND (lhs, 0);
3710 if (TREE_CODE (lhs) == MEM_REF
3711 && TREE_OPERAND (lhs, 0) == name
3712 && integer_zerop (TREE_OPERAND (lhs, 1))
3713 && types_compatible_p (TREE_TYPE (lhs),
3714 TREE_TYPE (TREE_TYPE (name)))
3715 && !TREE_THIS_VOLATILE (lhs))
3716 uses_ok++;
3718 if (gimple_assign_single_p (stmt))
3720 tree rhs = gimple_assign_rhs1 (stmt);
3721 while (handled_component_p (rhs))
3722 rhs = TREE_OPERAND (rhs, 0);
3723 if (TREE_CODE (rhs) == MEM_REF
3724 && TREE_OPERAND (rhs, 0) == name
3725 && integer_zerop (TREE_OPERAND (rhs, 1))
3726 && types_compatible_p (TREE_TYPE (rhs),
3727 TREE_TYPE (TREE_TYPE (name)))
3728 && !TREE_THIS_VOLATILE (rhs))
3729 uses_ok++;
3731 else if (is_gimple_call (stmt))
3733 unsigned i;
3734 for (i = 0; i < gimple_call_num_args (stmt); ++i)
3736 tree arg = gimple_call_arg (stmt, i);
3737 while (handled_component_p (arg))
3738 arg = TREE_OPERAND (arg, 0);
3739 if (TREE_CODE (arg) == MEM_REF
3740 && TREE_OPERAND (arg, 0) == name
3741 && integer_zerop (TREE_OPERAND (arg, 1))
3742 && types_compatible_p (TREE_TYPE (arg),
3743 TREE_TYPE (TREE_TYPE (name)))
3744 && !TREE_THIS_VOLATILE (arg))
3745 uses_ok++;
3749 /* If the number of valid uses does not match the number of
3750 uses in this stmt there is an unhandled use. */
3751 FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
3752 --uses_ok;
3754 if (uses_ok != 0)
3755 ret = true;
3757 if (ret)
3758 BREAK_FROM_IMM_USE_STMT (ui);
3761 return ret;
3764 /* Identify candidates for reduction for IPA-SRA based on their type and mark
3765 them in candidate_bitmap. Note that these do not necessarily include
3766 parameter which are unused and thus can be removed. Return true iff any
3767 such candidate has been found. */
3769 static bool
3770 find_param_candidates (void)
3772 tree parm;
3773 int count = 0;
3774 bool ret = false;
3775 const char *msg;
3777 for (parm = DECL_ARGUMENTS (current_function_decl);
3778 parm;
3779 parm = DECL_CHAIN (parm))
3781 tree type = TREE_TYPE (parm);
3782 tree_node **slot;
3784 count++;
3786 if (TREE_THIS_VOLATILE (parm)
3787 || TREE_ADDRESSABLE (parm)
3788 || (!is_gimple_reg_type (type) && is_va_list_type (type)))
3789 continue;
3791 if (is_unused_scalar_param (parm))
3793 ret = true;
3794 continue;
3797 if (POINTER_TYPE_P (type))
3799 type = TREE_TYPE (type);
3801 if (TREE_CODE (type) == FUNCTION_TYPE
3802 || TYPE_VOLATILE (type)
3803 || (TREE_CODE (type) == ARRAY_TYPE
3804 && TYPE_NONALIASED_COMPONENT (type))
3805 || !is_gimple_reg (parm)
3806 || is_va_list_type (type)
3807 || ptr_parm_has_direct_uses (parm))
3808 continue;
3810 else if (!AGGREGATE_TYPE_P (type))
3811 continue;
3813 if (!COMPLETE_TYPE_P (type)
3814 || !tree_fits_uhwi_p (TYPE_SIZE (type))
3815 || tree_to_uhwi (TYPE_SIZE (type)) == 0
3816 || (AGGREGATE_TYPE_P (type)
3817 && type_internals_preclude_sra_p (type, &msg)))
3818 continue;
3820 bitmap_set_bit (candidate_bitmap, DECL_UID (parm));
3821 slot = candidates->find_slot_with_hash (parm, DECL_UID (parm), INSERT);
3822 *slot = parm;
3824 ret = true;
3825 if (dump_file && (dump_flags & TDF_DETAILS))
3827 fprintf (dump_file, "Candidate (%d): ", DECL_UID (parm));
3828 print_generic_expr (dump_file, parm, 0);
3829 fprintf (dump_file, "\n");
3833 func_param_count = count;
3834 return ret;
3837 /* Callback of walk_aliased_vdefs, marks the access passed as DATA as
3838 maybe_modified. */
3840 static bool
3841 mark_maybe_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
3842 void *data)
3844 struct access *repr = (struct access *) data;
3846 repr->grp_maybe_modified = 1;
3847 return true;
3850 /* Analyze what representatives (in linked lists accessible from
3851 REPRESENTATIVES) can be modified by side effects of statements in the
3852 current function. */
3854 static void
3855 analyze_modified_params (vec<access_p> representatives)
3857 int i;
3859 for (i = 0; i < func_param_count; i++)
3861 struct access *repr;
3863 for (repr = representatives[i];
3864 repr;
3865 repr = repr->next_grp)
3867 struct access *access;
3868 bitmap visited;
3869 ao_ref ar;
3871 if (no_accesses_p (repr))
3872 continue;
3873 if (!POINTER_TYPE_P (TREE_TYPE (repr->base))
3874 || repr->grp_maybe_modified)
3875 continue;
3877 ao_ref_init (&ar, repr->expr);
3878 visited = BITMAP_ALLOC (NULL);
3879 for (access = repr; access; access = access->next_sibling)
3881 /* All accesses are read ones, otherwise grp_maybe_modified would
3882 be trivially set. */
3883 walk_aliased_vdefs (&ar, gimple_vuse (access->stmt),
3884 mark_maybe_modified, repr, &visited);
3885 if (repr->grp_maybe_modified)
3886 break;
3888 BITMAP_FREE (visited);
3893 /* Propagate distances in bb_dereferences in the opposite direction than the
3894 control flow edges, in each step storing the maximum of the current value
3895 and the minimum of all successors. These steps are repeated until the table
3896 stabilizes. Note that BBs which might terminate the functions (according to
3897 final_bbs bitmap) never updated in this way. */
3899 static void
3900 propagate_dereference_distances (void)
3902 basic_block bb;
3904 auto_vec<basic_block> queue (last_basic_block_for_fn (cfun));
3905 queue.quick_push (ENTRY_BLOCK_PTR_FOR_FN (cfun));
3906 FOR_EACH_BB_FN (bb, cfun)
3908 queue.quick_push (bb);
3909 bb->aux = bb;
3912 while (!queue.is_empty ())
3914 edge_iterator ei;
3915 edge e;
3916 bool change = false;
3917 int i;
3919 bb = queue.pop ();
3920 bb->aux = NULL;
3922 if (bitmap_bit_p (final_bbs, bb->index))
3923 continue;
3925 for (i = 0; i < func_param_count; i++)
3927 int idx = bb->index * func_param_count + i;
3928 bool first = true;
3929 HOST_WIDE_INT inh = 0;
3931 FOR_EACH_EDGE (e, ei, bb->succs)
3933 int succ_idx = e->dest->index * func_param_count + i;
3935 if (e->src == EXIT_BLOCK_PTR_FOR_FN (cfun))
3936 continue;
3938 if (first)
3940 first = false;
3941 inh = bb_dereferences [succ_idx];
3943 else if (bb_dereferences [succ_idx] < inh)
3944 inh = bb_dereferences [succ_idx];
3947 if (!first && bb_dereferences[idx] < inh)
3949 bb_dereferences[idx] = inh;
3950 change = true;
3954 if (change && !bitmap_bit_p (final_bbs, bb->index))
3955 FOR_EACH_EDGE (e, ei, bb->preds)
3957 if (e->src->aux)
3958 continue;
3960 e->src->aux = e->src;
3961 queue.quick_push (e->src);
3966 /* Dump a dereferences TABLE with heading STR to file F. */
3968 static void
3969 dump_dereferences_table (FILE *f, const char *str, HOST_WIDE_INT *table)
3971 basic_block bb;
3973 fprintf (dump_file, str);
3974 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun),
3975 EXIT_BLOCK_PTR_FOR_FN (cfun), next_bb)
3977 fprintf (f, "%4i %i ", bb->index, bitmap_bit_p (final_bbs, bb->index));
3978 if (bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
3980 int i;
3981 for (i = 0; i < func_param_count; i++)
3983 int idx = bb->index * func_param_count + i;
3984 fprintf (f, " %4" HOST_WIDE_INT_PRINT "d", table[idx]);
3987 fprintf (f, "\n");
3989 fprintf (dump_file, "\n");
3992 /* Determine what (parts of) parameters passed by reference that are not
3993 assigned to are not certainly dereferenced in this function and thus the
3994 dereferencing cannot be safely moved to the caller without potentially
3995 introducing a segfault. Mark such REPRESENTATIVES as
3996 grp_not_necessarilly_dereferenced.
3998 The dereferenced maximum "distance," i.e. the offset + size of the accessed
3999 part is calculated rather than simple booleans are calculated for each
4000 pointer parameter to handle cases when only a fraction of the whole
4001 aggregate is allocated (see testsuite/gcc.c-torture/execute/ipa-sra-2.c for
4002 an example).
4004 The maximum dereference distances for each pointer parameter and BB are
4005 already stored in bb_dereference. This routine simply propagates these
4006 values upwards by propagate_dereference_distances and then compares the
4007 distances of individual parameters in the ENTRY BB to the equivalent
4008 distances of each representative of a (fraction of a) parameter. */
4010 static void
4011 analyze_caller_dereference_legality (vec<access_p> representatives)
4013 int i;
4015 if (dump_file && (dump_flags & TDF_DETAILS))
4016 dump_dereferences_table (dump_file,
4017 "Dereference table before propagation:\n",
4018 bb_dereferences);
4020 propagate_dereference_distances ();
4022 if (dump_file && (dump_flags & TDF_DETAILS))
4023 dump_dereferences_table (dump_file,
4024 "Dereference table after propagation:\n",
4025 bb_dereferences);
4027 for (i = 0; i < func_param_count; i++)
4029 struct access *repr = representatives[i];
4030 int idx = ENTRY_BLOCK_PTR_FOR_FN (cfun)->index * func_param_count + i;
4032 if (!repr || no_accesses_p (repr))
4033 continue;
4037 if ((repr->offset + repr->size) > bb_dereferences[idx])
4038 repr->grp_not_necessarilly_dereferenced = 1;
4039 repr = repr->next_grp;
4041 while (repr);
4045 /* Return the representative access for the parameter declaration PARM if it is
4046 a scalar passed by reference which is not written to and the pointer value
4047 is not used directly. Thus, if it is legal to dereference it in the caller
4048 and we can rule out modifications through aliases, such parameter should be
4049 turned into one passed by value. Return NULL otherwise. */
4051 static struct access *
4052 unmodified_by_ref_scalar_representative (tree parm)
4054 int i, access_count;
4055 struct access *repr;
4056 vec<access_p> *access_vec;
4058 access_vec = get_base_access_vector (parm);
4059 gcc_assert (access_vec);
4060 repr = (*access_vec)[0];
4061 if (repr->write)
4062 return NULL;
4063 repr->group_representative = repr;
4065 access_count = access_vec->length ();
4066 for (i = 1; i < access_count; i++)
4068 struct access *access = (*access_vec)[i];
4069 if (access->write)
4070 return NULL;
4071 access->group_representative = repr;
4072 access->next_sibling = repr->next_sibling;
4073 repr->next_sibling = access;
4076 repr->grp_read = 1;
4077 repr->grp_scalar_ptr = 1;
4078 return repr;
4081 /* Return true iff this ACCESS precludes IPA-SRA of the parameter it is
4082 associated with. REQ_ALIGN is the minimum required alignment. */
4084 static bool
4085 access_precludes_ipa_sra_p (struct access *access, unsigned int req_align)
4087 unsigned int exp_align;
4088 /* Avoid issues such as the second simple testcase in PR 42025. The problem
4089 is incompatible assign in a call statement (and possibly even in asm
4090 statements). This can be relaxed by using a new temporary but only for
4091 non-TREE_ADDRESSABLE types and is probably not worth the complexity. (In
4092 intraprocedural SRA we deal with this by keeping the old aggregate around,
4093 something we cannot do in IPA-SRA.) */
4094 if (access->write
4095 && (is_gimple_call (access->stmt)
4096 || gimple_code (access->stmt) == GIMPLE_ASM))
4097 return true;
4099 exp_align = get_object_alignment (access->expr);
4100 if (exp_align < req_align)
4101 return true;
4103 return false;
4107 /* Sort collected accesses for parameter PARM, identify representatives for
4108 each accessed region and link them together. Return NULL if there are
4109 different but overlapping accesses, return the special ptr value meaning
4110 there are no accesses for this parameter if that is the case and return the
4111 first representative otherwise. Set *RO_GRP if there is a group of accesses
4112 with only read (i.e. no write) accesses. */
4114 static struct access *
4115 splice_param_accesses (tree parm, bool *ro_grp)
4117 int i, j, access_count, group_count;
4118 int agg_size, total_size = 0;
4119 struct access *access, *res, **prev_acc_ptr = &res;
4120 vec<access_p> *access_vec;
4122 access_vec = get_base_access_vector (parm);
4123 if (!access_vec)
4124 return &no_accesses_representant;
4125 access_count = access_vec->length ();
4127 access_vec->qsort (compare_access_positions);
4129 i = 0;
4130 total_size = 0;
4131 group_count = 0;
4132 while (i < access_count)
4134 bool modification;
4135 tree a1_alias_type;
4136 access = (*access_vec)[i];
4137 modification = access->write;
4138 if (access_precludes_ipa_sra_p (access, TYPE_ALIGN (access->type)))
4139 return NULL;
4140 a1_alias_type = reference_alias_ptr_type (access->expr);
4142 /* Access is about to become group representative unless we find some
4143 nasty overlap which would preclude us from breaking this parameter
4144 apart. */
4146 j = i + 1;
4147 while (j < access_count)
4149 struct access *ac2 = (*access_vec)[j];
4150 if (ac2->offset != access->offset)
4152 /* All or nothing law for parameters. */
4153 if (access->offset + access->size > ac2->offset)
4154 return NULL;
4155 else
4156 break;
4158 else if (ac2->size != access->size)
4159 return NULL;
4161 if (access_precludes_ipa_sra_p (ac2, TYPE_ALIGN (access->type))
4162 || (ac2->type != access->type
4163 && (TREE_ADDRESSABLE (ac2->type)
4164 || TREE_ADDRESSABLE (access->type)))
4165 || (reference_alias_ptr_type (ac2->expr) != a1_alias_type))
4166 return NULL;
4168 modification |= ac2->write;
4169 ac2->group_representative = access;
4170 ac2->next_sibling = access->next_sibling;
4171 access->next_sibling = ac2;
4172 j++;
4175 group_count++;
4176 access->grp_maybe_modified = modification;
4177 if (!modification)
4178 *ro_grp = true;
4179 *prev_acc_ptr = access;
4180 prev_acc_ptr = &access->next_grp;
4181 total_size += access->size;
4182 i = j;
4185 if (POINTER_TYPE_P (TREE_TYPE (parm)))
4186 agg_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))));
4187 else
4188 agg_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (parm)));
4189 if (total_size >= agg_size)
4190 return NULL;
4192 gcc_assert (group_count > 0);
4193 return res;
4196 /* Decide whether parameters with representative accesses given by REPR should
4197 be reduced into components. */
4199 static int
4200 decide_one_param_reduction (struct access *repr)
4202 int total_size, cur_parm_size, agg_size, new_param_count, parm_size_limit;
4203 bool by_ref;
4204 tree parm;
4206 parm = repr->base;
4207 cur_parm_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (parm)));
4208 gcc_assert (cur_parm_size > 0);
4210 if (POINTER_TYPE_P (TREE_TYPE (parm)))
4212 by_ref = true;
4213 agg_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))));
4215 else
4217 by_ref = false;
4218 agg_size = cur_parm_size;
4221 if (dump_file)
4223 struct access *acc;
4224 fprintf (dump_file, "Evaluating PARAM group sizes for ");
4225 print_generic_expr (dump_file, parm, 0);
4226 fprintf (dump_file, " (UID: %u): \n", DECL_UID (parm));
4227 for (acc = repr; acc; acc = acc->next_grp)
4228 dump_access (dump_file, acc, true);
4231 total_size = 0;
4232 new_param_count = 0;
4234 for (; repr; repr = repr->next_grp)
4236 gcc_assert (parm == repr->base);
4238 /* Taking the address of a non-addressable field is verboten. */
4239 if (by_ref && repr->non_addressable)
4240 return 0;
4242 /* Do not decompose a non-BLKmode param in a way that would
4243 create BLKmode params. Especially for by-reference passing
4244 (thus, pointer-type param) this is hardly worthwhile. */
4245 if (DECL_MODE (parm) != BLKmode
4246 && TYPE_MODE (repr->type) == BLKmode)
4247 return 0;
4249 if (!by_ref || (!repr->grp_maybe_modified
4250 && !repr->grp_not_necessarilly_dereferenced))
4251 total_size += repr->size;
4252 else
4253 total_size += cur_parm_size;
4255 new_param_count++;
4258 gcc_assert (new_param_count > 0);
4260 if (optimize_function_for_size_p (cfun))
4261 parm_size_limit = cur_parm_size;
4262 else
4263 parm_size_limit = (PARAM_VALUE (PARAM_IPA_SRA_PTR_GROWTH_FACTOR)
4264 * cur_parm_size);
4266 if (total_size < agg_size
4267 && total_size <= parm_size_limit)
4269 if (dump_file)
4270 fprintf (dump_file, " ....will be split into %i components\n",
4271 new_param_count);
4272 return new_param_count;
4274 else
4275 return 0;
4278 /* The order of the following enums is important, we need to do extra work for
4279 UNUSED_PARAMS, BY_VAL_ACCESSES and UNMODIF_BY_REF_ACCESSES. */
4280 enum ipa_splicing_result { NO_GOOD_ACCESS, UNUSED_PARAMS, BY_VAL_ACCESSES,
4281 MODIF_BY_REF_ACCESSES, UNMODIF_BY_REF_ACCESSES };
4283 /* Identify representatives of all accesses to all candidate parameters for
4284 IPA-SRA. Return result based on what representatives have been found. */
4286 static enum ipa_splicing_result
4287 splice_all_param_accesses (vec<access_p> &representatives)
4289 enum ipa_splicing_result result = NO_GOOD_ACCESS;
4290 tree parm;
4291 struct access *repr;
4293 representatives.create (func_param_count);
4295 for (parm = DECL_ARGUMENTS (current_function_decl);
4296 parm;
4297 parm = DECL_CHAIN (parm))
4299 if (is_unused_scalar_param (parm))
4301 representatives.quick_push (&no_accesses_representant);
4302 if (result == NO_GOOD_ACCESS)
4303 result = UNUSED_PARAMS;
4305 else if (POINTER_TYPE_P (TREE_TYPE (parm))
4306 && is_gimple_reg_type (TREE_TYPE (TREE_TYPE (parm)))
4307 && bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
4309 repr = unmodified_by_ref_scalar_representative (parm);
4310 representatives.quick_push (repr);
4311 if (repr)
4312 result = UNMODIF_BY_REF_ACCESSES;
4314 else if (bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
4316 bool ro_grp = false;
4317 repr = splice_param_accesses (parm, &ro_grp);
4318 representatives.quick_push (repr);
4320 if (repr && !no_accesses_p (repr))
4322 if (POINTER_TYPE_P (TREE_TYPE (parm)))
4324 if (ro_grp)
4325 result = UNMODIF_BY_REF_ACCESSES;
4326 else if (result < MODIF_BY_REF_ACCESSES)
4327 result = MODIF_BY_REF_ACCESSES;
4329 else if (result < BY_VAL_ACCESSES)
4330 result = BY_VAL_ACCESSES;
4332 else if (no_accesses_p (repr) && (result == NO_GOOD_ACCESS))
4333 result = UNUSED_PARAMS;
4335 else
4336 representatives.quick_push (NULL);
4339 if (result == NO_GOOD_ACCESS)
4341 representatives.release ();
4342 return NO_GOOD_ACCESS;
4345 return result;
4348 /* Return the index of BASE in PARMS. Abort if it is not found. */
4350 static inline int
4351 get_param_index (tree base, vec<tree> parms)
4353 int i, len;
4355 len = parms.length ();
4356 for (i = 0; i < len; i++)
4357 if (parms[i] == base)
4358 return i;
4359 gcc_unreachable ();
4362 /* Convert the decisions made at the representative level into compact
4363 parameter adjustments. REPRESENTATIVES are pointers to first
4364 representatives of each param accesses, ADJUSTMENTS_COUNT is the expected
4365 final number of adjustments. */
4367 static ipa_parm_adjustment_vec
4368 turn_representatives_into_adjustments (vec<access_p> representatives,
4369 int adjustments_count)
4371 vec<tree> parms;
4372 ipa_parm_adjustment_vec adjustments;
4373 tree parm;
4374 int i;
4376 gcc_assert (adjustments_count > 0);
4377 parms = ipa_get_vector_of_formal_parms (current_function_decl);
4378 adjustments.create (adjustments_count);
4379 parm = DECL_ARGUMENTS (current_function_decl);
4380 for (i = 0; i < func_param_count; i++, parm = DECL_CHAIN (parm))
4382 struct access *repr = representatives[i];
4384 if (!repr || no_accesses_p (repr))
4386 struct ipa_parm_adjustment adj;
4388 memset (&adj, 0, sizeof (adj));
4389 adj.base_index = get_param_index (parm, parms);
4390 adj.base = parm;
4391 if (!repr)
4392 adj.op = IPA_PARM_OP_COPY;
4393 else
4394 adj.op = IPA_PARM_OP_REMOVE;
4395 adj.arg_prefix = "ISRA";
4396 adjustments.quick_push (adj);
4398 else
4400 struct ipa_parm_adjustment adj;
4401 int index = get_param_index (parm, parms);
4403 for (; repr; repr = repr->next_grp)
4405 memset (&adj, 0, sizeof (adj));
4406 gcc_assert (repr->base == parm);
4407 adj.base_index = index;
4408 adj.base = repr->base;
4409 adj.type = repr->type;
4410 adj.alias_ptr_type = reference_alias_ptr_type (repr->expr);
4411 adj.offset = repr->offset;
4412 adj.by_ref = (POINTER_TYPE_P (TREE_TYPE (repr->base))
4413 && (repr->grp_maybe_modified
4414 || repr->grp_not_necessarilly_dereferenced));
4415 adj.arg_prefix = "ISRA";
4416 adjustments.quick_push (adj);
4420 parms.release ();
4421 return adjustments;
4424 /* Analyze the collected accesses and produce a plan what to do with the
4425 parameters in the form of adjustments, NULL meaning nothing. */
4427 static ipa_parm_adjustment_vec
4428 analyze_all_param_acesses (void)
4430 enum ipa_splicing_result repr_state;
4431 bool proceed = false;
4432 int i, adjustments_count = 0;
4433 vec<access_p> representatives;
4434 ipa_parm_adjustment_vec adjustments;
4436 repr_state = splice_all_param_accesses (representatives);
4437 if (repr_state == NO_GOOD_ACCESS)
4438 return ipa_parm_adjustment_vec ();
4440 /* If there are any parameters passed by reference which are not modified
4441 directly, we need to check whether they can be modified indirectly. */
4442 if (repr_state == UNMODIF_BY_REF_ACCESSES)
4444 analyze_caller_dereference_legality (representatives);
4445 analyze_modified_params (representatives);
4448 for (i = 0; i < func_param_count; i++)
4450 struct access *repr = representatives[i];
4452 if (repr && !no_accesses_p (repr))
4454 if (repr->grp_scalar_ptr)
4456 adjustments_count++;
4457 if (repr->grp_not_necessarilly_dereferenced
4458 || repr->grp_maybe_modified)
4459 representatives[i] = NULL;
4460 else
4462 proceed = true;
4463 sra_stats.scalar_by_ref_to_by_val++;
4466 else
4468 int new_components = decide_one_param_reduction (repr);
4470 if (new_components == 0)
4472 representatives[i] = NULL;
4473 adjustments_count++;
4475 else
4477 adjustments_count += new_components;
4478 sra_stats.aggregate_params_reduced++;
4479 sra_stats.param_reductions_created += new_components;
4480 proceed = true;
4484 else
4486 if (no_accesses_p (repr))
4488 proceed = true;
4489 sra_stats.deleted_unused_parameters++;
4491 adjustments_count++;
4495 if (!proceed && dump_file)
4496 fprintf (dump_file, "NOT proceeding to change params.\n");
4498 if (proceed)
4499 adjustments = turn_representatives_into_adjustments (representatives,
4500 adjustments_count);
4501 else
4502 adjustments = ipa_parm_adjustment_vec ();
4504 representatives.release ();
4505 return adjustments;
4508 /* If a parameter replacement identified by ADJ does not yet exist in the form
4509 of declaration, create it and record it, otherwise return the previously
4510 created one. */
4512 static tree
4513 get_replaced_param_substitute (struct ipa_parm_adjustment *adj)
4515 tree repl;
4516 if (!adj->new_ssa_base)
4518 char *pretty_name = make_fancy_name (adj->base);
4520 repl = create_tmp_reg (TREE_TYPE (adj->base), "ISR");
4521 DECL_NAME (repl) = get_identifier (pretty_name);
4522 obstack_free (&name_obstack, pretty_name);
4524 adj->new_ssa_base = repl;
4526 else
4527 repl = adj->new_ssa_base;
4528 return repl;
4531 /* Find the first adjustment for a particular parameter BASE in a vector of
4532 ADJUSTMENTS which is not a copy_param. Return NULL if there is no such
4533 adjustment. */
4535 static struct ipa_parm_adjustment *
4536 get_adjustment_for_base (ipa_parm_adjustment_vec adjustments, tree base)
4538 int i, len;
4540 len = adjustments.length ();
4541 for (i = 0; i < len; i++)
4543 struct ipa_parm_adjustment *adj;
4545 adj = &adjustments[i];
4546 if (adj->op != IPA_PARM_OP_COPY && adj->base == base)
4547 return adj;
4550 return NULL;
4553 /* If the statement STMT defines an SSA_NAME of a parameter which is to be
4554 removed because its value is not used, replace the SSA_NAME with a one
4555 relating to a created VAR_DECL together all of its uses and return true.
4556 ADJUSTMENTS is a pointer to an adjustments vector. */
4558 static bool
4559 replace_removed_params_ssa_names (gimple stmt,
4560 ipa_parm_adjustment_vec adjustments)
4562 struct ipa_parm_adjustment *adj;
4563 tree lhs, decl, repl, name;
4565 if (gimple_code (stmt) == GIMPLE_PHI)
4566 lhs = gimple_phi_result (stmt);
4567 else if (is_gimple_assign (stmt))
4568 lhs = gimple_assign_lhs (stmt);
4569 else if (is_gimple_call (stmt))
4570 lhs = gimple_call_lhs (stmt);
4571 else
4572 gcc_unreachable ();
4574 if (TREE_CODE (lhs) != SSA_NAME)
4575 return false;
4577 decl = SSA_NAME_VAR (lhs);
4578 if (decl == NULL_TREE
4579 || TREE_CODE (decl) != PARM_DECL)
4580 return false;
4582 adj = get_adjustment_for_base (adjustments, decl);
4583 if (!adj)
4584 return false;
4586 repl = get_replaced_param_substitute (adj);
4587 name = make_ssa_name (repl, stmt);
4589 if (dump_file)
4591 fprintf (dump_file, "replacing an SSA name of a removed param ");
4592 print_generic_expr (dump_file, lhs, 0);
4593 fprintf (dump_file, " with ");
4594 print_generic_expr (dump_file, name, 0);
4595 fprintf (dump_file, "\n");
4598 if (is_gimple_assign (stmt))
4599 gimple_assign_set_lhs (stmt, name);
4600 else if (is_gimple_call (stmt))
4601 gimple_call_set_lhs (stmt, name);
4602 else
4603 gimple_phi_set_result (as_a <gphi *> (stmt), name);
4605 replace_uses_by (lhs, name);
4606 release_ssa_name (lhs);
4607 return true;
4610 /* If the statement STMT contains any expressions that need to replaced with a
4611 different one as noted by ADJUSTMENTS, do so. Handle any potential type
4612 incompatibilities (GSI is used to accommodate conversion statements and must
4613 point to the statement). Return true iff the statement was modified. */
4615 static bool
4616 sra_ipa_modify_assign (gimple stmt, gimple_stmt_iterator *gsi,
4617 ipa_parm_adjustment_vec adjustments)
4619 tree *lhs_p, *rhs_p;
4620 bool any;
4622 if (!gimple_assign_single_p (stmt))
4623 return false;
4625 rhs_p = gimple_assign_rhs1_ptr (stmt);
4626 lhs_p = gimple_assign_lhs_ptr (stmt);
4628 any = ipa_modify_expr (rhs_p, false, adjustments);
4629 any |= ipa_modify_expr (lhs_p, false, adjustments);
4630 if (any)
4632 tree new_rhs = NULL_TREE;
4634 if (!useless_type_conversion_p (TREE_TYPE (*lhs_p), TREE_TYPE (*rhs_p)))
4636 if (TREE_CODE (*rhs_p) == CONSTRUCTOR)
4638 /* V_C_Es of constructors can cause trouble (PR 42714). */
4639 if (is_gimple_reg_type (TREE_TYPE (*lhs_p)))
4640 *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
4641 else
4642 *rhs_p = build_constructor (TREE_TYPE (*lhs_p),
4643 NULL);
4645 else
4646 new_rhs = fold_build1_loc (gimple_location (stmt),
4647 VIEW_CONVERT_EXPR, TREE_TYPE (*lhs_p),
4648 *rhs_p);
4650 else if (REFERENCE_CLASS_P (*rhs_p)
4651 && is_gimple_reg_type (TREE_TYPE (*lhs_p))
4652 && !is_gimple_reg (*lhs_p))
4653 /* This can happen when an assignment in between two single field
4654 structures is turned into an assignment in between two pointers to
4655 scalars (PR 42237). */
4656 new_rhs = *rhs_p;
4658 if (new_rhs)
4660 tree tmp = force_gimple_operand_gsi (gsi, new_rhs, true, NULL_TREE,
4661 true, GSI_SAME_STMT);
4663 gimple_assign_set_rhs_from_tree (gsi, tmp);
4666 return true;
4669 return false;
4672 /* Traverse the function body and all modifications as described in
4673 ADJUSTMENTS. Return true iff the CFG has been changed. */
4675 bool
4676 ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments)
4678 bool cfg_changed = false;
4679 basic_block bb;
4681 FOR_EACH_BB_FN (bb, cfun)
4683 gimple_stmt_iterator gsi;
4685 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4686 replace_removed_params_ssa_names (gsi_stmt (gsi), adjustments);
4688 gsi = gsi_start_bb (bb);
4689 while (!gsi_end_p (gsi))
4691 gimple stmt = gsi_stmt (gsi);
4692 bool modified = false;
4693 tree *t;
4694 unsigned i;
4696 switch (gimple_code (stmt))
4698 case GIMPLE_RETURN:
4699 t = gimple_return_retval_ptr (as_a <greturn *> (stmt));
4700 if (*t != NULL_TREE)
4701 modified |= ipa_modify_expr (t, true, adjustments);
4702 break;
4704 case GIMPLE_ASSIGN:
4705 modified |= sra_ipa_modify_assign (stmt, &gsi, adjustments);
4706 modified |= replace_removed_params_ssa_names (stmt, adjustments);
4707 break;
4709 case GIMPLE_CALL:
4710 /* Operands must be processed before the lhs. */
4711 for (i = 0; i < gimple_call_num_args (stmt); i++)
4713 t = gimple_call_arg_ptr (stmt, i);
4714 modified |= ipa_modify_expr (t, true, adjustments);
4717 if (gimple_call_lhs (stmt))
4719 t = gimple_call_lhs_ptr (stmt);
4720 modified |= ipa_modify_expr (t, false, adjustments);
4721 modified |= replace_removed_params_ssa_names (stmt,
4722 adjustments);
4724 break;
4726 case GIMPLE_ASM:
4728 gasm *asm_stmt = as_a <gasm *> (stmt);
4729 for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
4731 t = &TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
4732 modified |= ipa_modify_expr (t, true, adjustments);
4734 for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
4736 t = &TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
4737 modified |= ipa_modify_expr (t, false, adjustments);
4740 break;
4742 default:
4743 break;
4746 if (modified)
4748 update_stmt (stmt);
4749 if (maybe_clean_eh_stmt (stmt)
4750 && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
4751 cfg_changed = true;
4753 gsi_next (&gsi);
4757 return cfg_changed;
4760 /* Call gimple_debug_bind_reset_value on all debug statements describing
4761 gimple register parameters that are being removed or replaced. */
4763 static void
4764 sra_ipa_reset_debug_stmts (ipa_parm_adjustment_vec adjustments)
4766 int i, len;
4767 gimple_stmt_iterator *gsip = NULL, gsi;
4769 if (MAY_HAVE_DEBUG_STMTS && single_succ_p (ENTRY_BLOCK_PTR_FOR_FN (cfun)))
4771 gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
4772 gsip = &gsi;
4774 len = adjustments.length ();
4775 for (i = 0; i < len; i++)
4777 struct ipa_parm_adjustment *adj;
4778 imm_use_iterator ui;
4779 gimple stmt;
4780 gdebug *def_temp;
4781 tree name, vexpr, copy = NULL_TREE;
4782 use_operand_p use_p;
4784 adj = &adjustments[i];
4785 if (adj->op == IPA_PARM_OP_COPY || !is_gimple_reg (adj->base))
4786 continue;
4787 name = ssa_default_def (cfun, adj->base);
4788 vexpr = NULL;
4789 if (name)
4790 FOR_EACH_IMM_USE_STMT (stmt, ui, name)
4792 if (gimple_clobber_p (stmt))
4794 gimple_stmt_iterator cgsi = gsi_for_stmt (stmt);
4795 unlink_stmt_vdef (stmt);
4796 gsi_remove (&cgsi, true);
4797 release_defs (stmt);
4798 continue;
4800 /* All other users must have been removed by
4801 ipa_sra_modify_function_body. */
4802 gcc_assert (is_gimple_debug (stmt));
4803 if (vexpr == NULL && gsip != NULL)
4805 gcc_assert (TREE_CODE (adj->base) == PARM_DECL);
4806 vexpr = make_node (DEBUG_EXPR_DECL);
4807 def_temp = gimple_build_debug_source_bind (vexpr, adj->base,
4808 NULL);
4809 DECL_ARTIFICIAL (vexpr) = 1;
4810 TREE_TYPE (vexpr) = TREE_TYPE (name);
4811 DECL_MODE (vexpr) = DECL_MODE (adj->base);
4812 gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
4814 if (vexpr)
4816 FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
4817 SET_USE (use_p, vexpr);
4819 else
4820 gimple_debug_bind_reset_value (stmt);
4821 update_stmt (stmt);
4823 /* Create a VAR_DECL for debug info purposes. */
4824 if (!DECL_IGNORED_P (adj->base))
4826 copy = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
4827 VAR_DECL, DECL_NAME (adj->base),
4828 TREE_TYPE (adj->base));
4829 if (DECL_PT_UID_SET_P (adj->base))
4830 SET_DECL_PT_UID (copy, DECL_PT_UID (adj->base));
4831 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (adj->base);
4832 TREE_READONLY (copy) = TREE_READONLY (adj->base);
4833 TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (adj->base);
4834 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (adj->base);
4835 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (adj->base);
4836 DECL_IGNORED_P (copy) = DECL_IGNORED_P (adj->base);
4837 DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (adj->base);
4838 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
4839 SET_DECL_RTL (copy, 0);
4840 TREE_USED (copy) = 1;
4841 DECL_CONTEXT (copy) = current_function_decl;
4842 add_local_decl (cfun, copy);
4843 DECL_CHAIN (copy) =
4844 BLOCK_VARS (DECL_INITIAL (current_function_decl));
4845 BLOCK_VARS (DECL_INITIAL (current_function_decl)) = copy;
4847 if (gsip != NULL && copy && target_for_debug_bind (adj->base))
4849 gcc_assert (TREE_CODE (adj->base) == PARM_DECL);
4850 if (vexpr)
4851 def_temp = gimple_build_debug_bind (copy, vexpr, NULL);
4852 else
4853 def_temp = gimple_build_debug_source_bind (copy, adj->base,
4854 NULL);
4855 gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
4860 /* Return false if all callers have at least as many actual arguments as there
4861 are formal parameters in the current function and that their types
4862 match. */
4864 static bool
4865 some_callers_have_mismatched_arguments_p (struct cgraph_node *node,
4866 void *data ATTRIBUTE_UNUSED)
4868 struct cgraph_edge *cs;
4869 for (cs = node->callers; cs; cs = cs->next_caller)
4870 if (!callsite_arguments_match_p (cs->call_stmt))
4871 return true;
4873 return false;
4876 /* Convert all callers of NODE. */
4878 static bool
4879 convert_callers_for_node (struct cgraph_node *node,
4880 void *data)
4882 ipa_parm_adjustment_vec *adjustments = (ipa_parm_adjustment_vec *) data;
4883 bitmap recomputed_callers = BITMAP_ALLOC (NULL);
4884 struct cgraph_edge *cs;
4886 for (cs = node->callers; cs; cs = cs->next_caller)
4888 push_cfun (DECL_STRUCT_FUNCTION (cs->caller->decl));
4890 if (dump_file)
4891 fprintf (dump_file, "Adjusting call %s/%i -> %s/%i\n",
4892 xstrdup (cs->caller->name ()),
4893 cs->caller->order,
4894 xstrdup (cs->callee->name ()),
4895 cs->callee->order);
4897 ipa_modify_call_arguments (cs, cs->call_stmt, *adjustments);
4899 pop_cfun ();
4902 for (cs = node->callers; cs; cs = cs->next_caller)
4903 if (bitmap_set_bit (recomputed_callers, cs->caller->uid)
4904 && gimple_in_ssa_p (DECL_STRUCT_FUNCTION (cs->caller->decl)))
4905 compute_inline_parameters (cs->caller, true);
4906 BITMAP_FREE (recomputed_callers);
4908 return true;
4911 /* Convert all callers of NODE to pass parameters as given in ADJUSTMENTS. */
4913 static void
4914 convert_callers (struct cgraph_node *node, tree old_decl,
4915 ipa_parm_adjustment_vec adjustments)
4917 basic_block this_block;
4919 node->call_for_symbol_thunks_and_aliases (convert_callers_for_node,
4920 &adjustments, false);
4922 if (!encountered_recursive_call)
4923 return;
4925 FOR_EACH_BB_FN (this_block, cfun)
4927 gimple_stmt_iterator gsi;
4929 for (gsi = gsi_start_bb (this_block); !gsi_end_p (gsi); gsi_next (&gsi))
4931 gcall *stmt;
4932 tree call_fndecl;
4933 stmt = dyn_cast <gcall *> (gsi_stmt (gsi));
4934 if (!stmt)
4935 continue;
4936 call_fndecl = gimple_call_fndecl (stmt);
4937 if (call_fndecl == old_decl)
4939 if (dump_file)
4940 fprintf (dump_file, "Adjusting recursive call");
4941 gimple_call_set_fndecl (stmt, node->decl);
4942 ipa_modify_call_arguments (NULL, stmt, adjustments);
4947 return;
4950 /* Perform all the modification required in IPA-SRA for NODE to have parameters
4951 as given in ADJUSTMENTS. Return true iff the CFG has been changed. */
4953 static bool
4954 modify_function (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments)
4956 struct cgraph_node *new_node;
4957 bool cfg_changed;
4959 cgraph_edge::rebuild_edges ();
4960 free_dominance_info (CDI_DOMINATORS);
4961 pop_cfun ();
4963 /* This must be done after rebuilding cgraph edges for node above.
4964 Otherwise any recursive calls to node that are recorded in
4965 redirect_callers will be corrupted. */
4966 vec<cgraph_edge *> redirect_callers = node->collect_callers ();
4967 new_node = node->create_version_clone_with_body (redirect_callers, NULL,
4968 NULL, false, NULL, NULL,
4969 "isra");
4970 redirect_callers.release ();
4972 push_cfun (DECL_STRUCT_FUNCTION (new_node->decl));
4973 ipa_modify_formal_parameters (current_function_decl, adjustments);
4974 cfg_changed = ipa_sra_modify_function_body (adjustments);
4975 sra_ipa_reset_debug_stmts (adjustments);
4976 convert_callers (new_node, node->decl, adjustments);
4977 new_node->make_local ();
4978 return cfg_changed;
4981 /* If NODE has a caller, return true. */
4983 static bool
4984 has_caller_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
4986 if (node->callers)
4987 return true;
4988 return false;
4991 /* Return false the function is apparently unsuitable for IPA-SRA based on it's
4992 attributes, return true otherwise. NODE is the cgraph node of the current
4993 function. */
4995 static bool
4996 ipa_sra_preliminary_function_checks (struct cgraph_node *node)
4998 if (!node->can_be_local_p ())
5000 if (dump_file)
5001 fprintf (dump_file, "Function not local to this compilation unit.\n");
5002 return false;
5005 if (!node->local.can_change_signature)
5007 if (dump_file)
5008 fprintf (dump_file, "Function can not change signature.\n");
5009 return false;
5012 if (!tree_versionable_function_p (node->decl))
5014 if (dump_file)
5015 fprintf (dump_file, "Function is not versionable.\n");
5016 return false;
5019 if (!opt_for_fn (node->decl, optimize)
5020 || !opt_for_fn (node->decl, flag_ipa_sra))
5022 if (dump_file)
5023 fprintf (dump_file, "Function not optimized.\n");
5024 return false;
5027 if (DECL_VIRTUAL_P (current_function_decl))
5029 if (dump_file)
5030 fprintf (dump_file, "Function is a virtual method.\n");
5031 return false;
5034 if ((DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl))
5035 && inline_summaries->get (node)->size >= MAX_INLINE_INSNS_AUTO)
5037 if (dump_file)
5038 fprintf (dump_file, "Function too big to be made truly local.\n");
5039 return false;
5042 if (!node->call_for_symbol_thunks_and_aliases (has_caller_p, NULL, true))
5044 if (dump_file)
5045 fprintf (dump_file,
5046 "Function has no callers in this compilation unit.\n");
5047 return false;
5050 if (cfun->stdarg)
5052 if (dump_file)
5053 fprintf (dump_file, "Function uses stdarg. \n");
5054 return false;
5057 if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl)))
5058 return false;
5060 if (DECL_DISREGARD_INLINE_LIMITS (node->decl))
5062 if (dump_file)
5063 fprintf (dump_file, "Always inline function will be inlined "
5064 "anyway. \n");
5065 return false;
5068 return true;
5071 /* Perform early interprocedural SRA. */
5073 static unsigned int
5074 ipa_early_sra (void)
5076 struct cgraph_node *node = cgraph_node::get (current_function_decl);
5077 ipa_parm_adjustment_vec adjustments;
5078 int ret = 0;
5080 if (!ipa_sra_preliminary_function_checks (node))
5081 return 0;
5083 sra_initialize ();
5084 sra_mode = SRA_MODE_EARLY_IPA;
5086 if (!find_param_candidates ())
5088 if (dump_file)
5089 fprintf (dump_file, "Function has no IPA-SRA candidates.\n");
5090 goto simple_out;
5093 if (node->call_for_symbol_thunks_and_aliases
5094 (some_callers_have_mismatched_arguments_p, NULL, true))
5096 if (dump_file)
5097 fprintf (dump_file, "There are callers with insufficient number of "
5098 "arguments or arguments with type mismatches.\n");
5099 goto simple_out;
5102 bb_dereferences = XCNEWVEC (HOST_WIDE_INT,
5103 func_param_count
5104 * last_basic_block_for_fn (cfun));
5105 final_bbs = BITMAP_ALLOC (NULL);
5107 scan_function ();
5108 if (encountered_apply_args)
5110 if (dump_file)
5111 fprintf (dump_file, "Function calls __builtin_apply_args().\n");
5112 goto out;
5115 if (encountered_unchangable_recursive_call)
5117 if (dump_file)
5118 fprintf (dump_file, "Function calls itself with insufficient "
5119 "number of arguments.\n");
5120 goto out;
5123 adjustments = analyze_all_param_acesses ();
5124 if (!adjustments.exists ())
5125 goto out;
5126 if (dump_file)
5127 ipa_dump_param_adjustments (dump_file, adjustments, current_function_decl);
5129 if (modify_function (node, adjustments))
5130 ret = TODO_update_ssa | TODO_cleanup_cfg;
5131 else
5132 ret = TODO_update_ssa;
5133 adjustments.release ();
5135 statistics_counter_event (cfun, "Unused parameters deleted",
5136 sra_stats.deleted_unused_parameters);
5137 statistics_counter_event (cfun, "Scalar parameters converted to by-value",
5138 sra_stats.scalar_by_ref_to_by_val);
5139 statistics_counter_event (cfun, "Aggregate parameters broken up",
5140 sra_stats.aggregate_params_reduced);
5141 statistics_counter_event (cfun, "Aggregate parameter components created",
5142 sra_stats.param_reductions_created);
5144 out:
5145 BITMAP_FREE (final_bbs);
5146 free (bb_dereferences);
5147 simple_out:
5148 sra_deinitialize ();
5149 return ret;
5152 namespace {
5154 const pass_data pass_data_early_ipa_sra =
5156 GIMPLE_PASS, /* type */
5157 "eipa_sra", /* name */
5158 OPTGROUP_NONE, /* optinfo_flags */
5159 TV_IPA_SRA, /* tv_id */
5160 0, /* properties_required */
5161 0, /* properties_provided */
5162 0, /* properties_destroyed */
5163 0, /* todo_flags_start */
5164 TODO_dump_symtab, /* todo_flags_finish */
5167 class pass_early_ipa_sra : public gimple_opt_pass
5169 public:
5170 pass_early_ipa_sra (gcc::context *ctxt)
5171 : gimple_opt_pass (pass_data_early_ipa_sra, ctxt)
5174 /* opt_pass methods: */
5175 virtual bool gate (function *) { return flag_ipa_sra && dbg_cnt (eipa_sra); }
5176 virtual unsigned int execute (function *) { return ipa_early_sra (); }
5178 }; // class pass_early_ipa_sra
5180 } // anon namespace
5182 gimple_opt_pass *
5183 make_pass_early_ipa_sra (gcc::context *ctxt)
5185 return new pass_early_ipa_sra (ctxt);