PR ipa/64481
[official-gcc.git] / gcc / tree-sra.c
blobf560fe0c5993f969abaadd05a782c2ecab550223
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-2015 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 "hash-set.h"
82 #include "machmode.h"
83 #include "vec.h"
84 #include "double-int.h"
85 #include "input.h"
86 #include "alias.h"
87 #include "symtab.h"
88 #include "wide-int.h"
89 #include "inchash.h"
90 #include "tree.h"
91 #include "fold-const.h"
92 #include "predict.h"
93 #include "hard-reg-set.h"
94 #include "input.h"
95 #include "function.h"
96 #include "dominance.h"
97 #include "cfg.h"
98 #include "basic-block.h"
99 #include "tree-ssa-alias.h"
100 #include "internal-fn.h"
101 #include "tree-eh.h"
102 #include "gimple-expr.h"
103 #include "is-a.h"
104 #include "gimple.h"
105 #include "stor-layout.h"
106 #include "gimplify.h"
107 #include "gimple-iterator.h"
108 #include "gimplify-me.h"
109 #include "gimple-walk.h"
110 #include "bitmap.h"
111 #include "gimple-ssa.h"
112 #include "tree-cfg.h"
113 #include "tree-phinodes.h"
114 #include "ssa-iterators.h"
115 #include "stringpool.h"
116 #include "tree-ssanames.h"
117 #include "expr.h"
118 #include "tree-dfa.h"
119 #include "tree-ssa.h"
120 #include "tree-pass.h"
121 #include "plugin-api.h"
122 #include "ipa-ref.h"
123 #include "cgraph.h"
124 #include "symbol-summary.h"
125 #include "ipa-prop.h"
126 #include "statistics.h"
127 #include "params.h"
128 #include "target.h"
129 #include "flags.h"
130 #include "dbgcnt.h"
131 #include "tree-inline.h"
132 #include "gimple-pretty-print.h"
133 #include "ipa-inline.h"
134 #include "ipa-utils.h"
135 #include "builtins.h"
137 /* Enumeration of all aggregate reductions we can do. */
138 enum sra_mode { SRA_MODE_EARLY_IPA, /* early call regularization */
139 SRA_MODE_EARLY_INTRA, /* early intraprocedural SRA */
140 SRA_MODE_INTRA }; /* late intraprocedural SRA */
142 /* Global variable describing which aggregate reduction we are performing at
143 the moment. */
144 static enum sra_mode sra_mode;
146 struct assign_link;
148 /* ACCESS represents each access to an aggregate variable (as a whole or a
149 part). It can also represent a group of accesses that refer to exactly the
150 same fragment of an aggregate (i.e. those that have exactly the same offset
151 and size). Such representatives for a single aggregate, once determined,
152 are linked in a linked list and have the group fields set.
154 Moreover, when doing intraprocedural SRA, a tree is built from those
155 representatives (by the means of first_child and next_sibling pointers), in
156 which all items in a subtree are "within" the root, i.e. their offset is
157 greater or equal to offset of the root and offset+size is smaller or equal
158 to offset+size of the root. Children of an access are sorted by offset.
160 Note that accesses to parts of vector and complex number types always
161 represented by an access to the whole complex number or a vector. It is a
162 duty of the modifying functions to replace them appropriately. */
164 struct access
166 /* Values returned by `get_ref_base_and_extent' for each component reference
167 If EXPR isn't a component reference just set `BASE = EXPR', `OFFSET = 0',
168 `SIZE = TREE_SIZE (TREE_TYPE (expr))'. */
169 HOST_WIDE_INT offset;
170 HOST_WIDE_INT size;
171 tree base;
173 /* Expression. It is context dependent so do not use it to create new
174 expressions to access the original aggregate. See PR 42154 for a
175 testcase. */
176 tree expr;
177 /* Type. */
178 tree type;
180 /* The statement this access belongs to. */
181 gimple stmt;
183 /* Next group representative for this aggregate. */
184 struct access *next_grp;
186 /* Pointer to the group representative. Pointer to itself if the struct is
187 the representative. */
188 struct access *group_representative;
190 /* If this access has any children (in terms of the definition above), this
191 points to the first one. */
192 struct access *first_child;
194 /* In intraprocedural SRA, pointer to the next sibling in the access tree as
195 described above. In IPA-SRA this is a pointer to the next access
196 belonging to the same group (having the same representative). */
197 struct access *next_sibling;
199 /* Pointers to the first and last element in the linked list of assign
200 links. */
201 struct assign_link *first_link, *last_link;
203 /* Pointer to the next access in the work queue. */
204 struct access *next_queued;
206 /* Replacement variable for this access "region." Never to be accessed
207 directly, always only by the means of get_access_replacement() and only
208 when grp_to_be_replaced flag is set. */
209 tree replacement_decl;
211 /* Is this particular access write access? */
212 unsigned write : 1;
214 /* Is this access an access to a non-addressable field? */
215 unsigned non_addressable : 1;
217 /* Is this access currently in the work queue? */
218 unsigned grp_queued : 1;
220 /* Does this group contain a write access? This flag is propagated down the
221 access tree. */
222 unsigned grp_write : 1;
224 /* Does this group contain a read access? This flag is propagated down the
225 access tree. */
226 unsigned grp_read : 1;
228 /* Does this group contain a read access that comes from an assignment
229 statement? This flag is propagated down the access tree. */
230 unsigned grp_assignment_read : 1;
232 /* Does this group contain a write access that comes from an assignment
233 statement? This flag is propagated down the access tree. */
234 unsigned grp_assignment_write : 1;
236 /* Does this group contain a read access through a scalar type? This flag is
237 not propagated in the access tree in any direction. */
238 unsigned grp_scalar_read : 1;
240 /* Does this group contain a write access through a scalar type? This flag
241 is not propagated in the access tree in any direction. */
242 unsigned grp_scalar_write : 1;
244 /* Is this access an artificial one created to scalarize some record
245 entirely? */
246 unsigned grp_total_scalarization : 1;
248 /* Other passes of the analysis use this bit to make function
249 analyze_access_subtree create scalar replacements for this group if
250 possible. */
251 unsigned grp_hint : 1;
253 /* Is the subtree rooted in this access fully covered by scalar
254 replacements? */
255 unsigned grp_covered : 1;
257 /* If set to true, this access and all below it in an access tree must not be
258 scalarized. */
259 unsigned grp_unscalarizable_region : 1;
261 /* Whether data have been written to parts of the aggregate covered by this
262 access which is not to be scalarized. This flag is propagated up in the
263 access tree. */
264 unsigned grp_unscalarized_data : 1;
266 /* Does this access and/or group contain a write access through a
267 BIT_FIELD_REF? */
268 unsigned grp_partial_lhs : 1;
270 /* Set when a scalar replacement should be created for this variable. */
271 unsigned grp_to_be_replaced : 1;
273 /* Set when we want a replacement for the sole purpose of having it in
274 generated debug statements. */
275 unsigned grp_to_be_debug_replaced : 1;
277 /* Should TREE_NO_WARNING of a replacement be set? */
278 unsigned grp_no_warning : 1;
280 /* Is it possible that the group refers to data which might be (directly or
281 otherwise) modified? */
282 unsigned grp_maybe_modified : 1;
284 /* Set when this is a representative of a pointer to scalar (i.e. by
285 reference) parameter which we consider for turning into a plain scalar
286 (i.e. a by value parameter). */
287 unsigned grp_scalar_ptr : 1;
289 /* Set when we discover that this pointer is not safe to dereference in the
290 caller. */
291 unsigned grp_not_necessarilly_dereferenced : 1;
294 typedef struct access *access_p;
297 /* Alloc pool for allocating access structures. */
298 static alloc_pool access_pool;
300 /* A structure linking lhs and rhs accesses from an aggregate assignment. They
301 are used to propagate subaccesses from rhs to lhs as long as they don't
302 conflict with what is already there. */
303 struct assign_link
305 struct access *lacc, *racc;
306 struct assign_link *next;
309 /* Alloc pool for allocating assign link structures. */
310 static alloc_pool link_pool;
312 /* Base (tree) -> Vector (vec<access_p> *) map. */
313 static hash_map<tree, auto_vec<access_p> > *base_access_vec;
315 /* Candidate hash table helpers. */
317 struct uid_decl_hasher : typed_noop_remove <tree_node>
319 typedef tree_node value_type;
320 typedef tree_node compare_type;
321 static inline hashval_t hash (const value_type *);
322 static inline bool equal (const value_type *, const compare_type *);
325 /* Hash a tree in a uid_decl_map. */
327 inline hashval_t
328 uid_decl_hasher::hash (const value_type *item)
330 return item->decl_minimal.uid;
333 /* Return true if the DECL_UID in both trees are equal. */
335 inline bool
336 uid_decl_hasher::equal (const value_type *a, const compare_type *b)
338 return (a->decl_minimal.uid == b->decl_minimal.uid);
341 /* Set of candidates. */
342 static bitmap candidate_bitmap;
343 static hash_table<uid_decl_hasher> *candidates;
345 /* For a candidate UID return the candidates decl. */
347 static inline tree
348 candidate (unsigned uid)
350 tree_node t;
351 t.decl_minimal.uid = uid;
352 return candidates->find_with_hash (&t, static_cast <hashval_t> (uid));
355 /* Bitmap of candidates which we should try to entirely scalarize away and
356 those which cannot be (because they are and need be used as a whole). */
357 static bitmap should_scalarize_away_bitmap, cannot_scalarize_away_bitmap;
359 /* Obstack for creation of fancy names. */
360 static struct obstack name_obstack;
362 /* Head of a linked list of accesses that need to have its subaccesses
363 propagated to their assignment counterparts. */
364 static struct access *work_queue_head;
366 /* Number of parameters of the analyzed function when doing early ipa SRA. */
367 static int func_param_count;
369 /* scan_function sets the following to true if it encounters a call to
370 __builtin_apply_args. */
371 static bool encountered_apply_args;
373 /* Set by scan_function when it finds a recursive call. */
374 static bool encountered_recursive_call;
376 /* Set by scan_function when it finds a recursive call with less actual
377 arguments than formal parameters.. */
378 static bool encountered_unchangable_recursive_call;
380 /* This is a table in which for each basic block and parameter there is a
381 distance (offset + size) in that parameter which is dereferenced and
382 accessed in that BB. */
383 static HOST_WIDE_INT *bb_dereferences;
384 /* Bitmap of BBs that can cause the function to "stop" progressing by
385 returning, throwing externally, looping infinitely or calling a function
386 which might abort etc.. */
387 static bitmap final_bbs;
389 /* Representative of no accesses at all. */
390 static struct access no_accesses_representant;
392 /* Predicate to test the special value. */
394 static inline bool
395 no_accesses_p (struct access *access)
397 return access == &no_accesses_representant;
400 /* Dump contents of ACCESS to file F in a human friendly way. If GRP is true,
401 representative fields are dumped, otherwise those which only describe the
402 individual access are. */
404 static struct
406 /* Number of processed aggregates is readily available in
407 analyze_all_variable_accesses and so is not stored here. */
409 /* Number of created scalar replacements. */
410 int replacements;
412 /* Number of times sra_modify_expr or sra_modify_assign themselves changed an
413 expression. */
414 int exprs;
416 /* Number of statements created by generate_subtree_copies. */
417 int subtree_copies;
419 /* Number of statements created by load_assign_lhs_subreplacements. */
420 int subreplacements;
422 /* Number of times sra_modify_assign has deleted a statement. */
423 int deleted;
425 /* Number of times sra_modify_assign has to deal with subaccesses of LHS and
426 RHS reparately due to type conversions or nonexistent matching
427 references. */
428 int separate_lhs_rhs_handling;
430 /* Number of parameters that were removed because they were unused. */
431 int deleted_unused_parameters;
433 /* Number of scalars passed as parameters by reference that have been
434 converted to be passed by value. */
435 int scalar_by_ref_to_by_val;
437 /* Number of aggregate parameters that were replaced by one or more of their
438 components. */
439 int aggregate_params_reduced;
441 /* Numbber of components created when splitting aggregate parameters. */
442 int param_reductions_created;
443 } sra_stats;
445 static void
446 dump_access (FILE *f, struct access *access, bool grp)
448 fprintf (f, "access { ");
449 fprintf (f, "base = (%d)'", DECL_UID (access->base));
450 print_generic_expr (f, access->base, 0);
451 fprintf (f, "', offset = " HOST_WIDE_INT_PRINT_DEC, access->offset);
452 fprintf (f, ", size = " HOST_WIDE_INT_PRINT_DEC, access->size);
453 fprintf (f, ", expr = ");
454 print_generic_expr (f, access->expr, 0);
455 fprintf (f, ", type = ");
456 print_generic_expr (f, access->type, 0);
457 if (grp)
458 fprintf (f, ", grp_read = %d, grp_write = %d, grp_assignment_read = %d, "
459 "grp_assignment_write = %d, grp_scalar_read = %d, "
460 "grp_scalar_write = %d, grp_total_scalarization = %d, "
461 "grp_hint = %d, grp_covered = %d, "
462 "grp_unscalarizable_region = %d, grp_unscalarized_data = %d, "
463 "grp_partial_lhs = %d, grp_to_be_replaced = %d, "
464 "grp_to_be_debug_replaced = %d, grp_maybe_modified = %d, "
465 "grp_not_necessarilly_dereferenced = %d\n",
466 access->grp_read, access->grp_write, access->grp_assignment_read,
467 access->grp_assignment_write, access->grp_scalar_read,
468 access->grp_scalar_write, access->grp_total_scalarization,
469 access->grp_hint, access->grp_covered,
470 access->grp_unscalarizable_region, access->grp_unscalarized_data,
471 access->grp_partial_lhs, access->grp_to_be_replaced,
472 access->grp_to_be_debug_replaced, access->grp_maybe_modified,
473 access->grp_not_necessarilly_dereferenced);
474 else
475 fprintf (f, ", write = %d, grp_total_scalarization = %d, "
476 "grp_partial_lhs = %d\n",
477 access->write, access->grp_total_scalarization,
478 access->grp_partial_lhs);
481 /* Dump a subtree rooted in ACCESS to file F, indent by LEVEL. */
483 static void
484 dump_access_tree_1 (FILE *f, struct access *access, int level)
488 int i;
490 for (i = 0; i < level; i++)
491 fputs ("* ", dump_file);
493 dump_access (f, access, true);
495 if (access->first_child)
496 dump_access_tree_1 (f, access->first_child, level + 1);
498 access = access->next_sibling;
500 while (access);
503 /* Dump all access trees for a variable, given the pointer to the first root in
504 ACCESS. */
506 static void
507 dump_access_tree (FILE *f, struct access *access)
509 for (; access; access = access->next_grp)
510 dump_access_tree_1 (f, access, 0);
513 /* Return true iff ACC is non-NULL and has subaccesses. */
515 static inline bool
516 access_has_children_p (struct access *acc)
518 return acc && acc->first_child;
521 /* Return true iff ACC is (partly) covered by at least one replacement. */
523 static bool
524 access_has_replacements_p (struct access *acc)
526 struct access *child;
527 if (acc->grp_to_be_replaced)
528 return true;
529 for (child = acc->first_child; child; child = child->next_sibling)
530 if (access_has_replacements_p (child))
531 return true;
532 return false;
535 /* Return a vector of pointers to accesses for the variable given in BASE or
536 NULL if there is none. */
538 static vec<access_p> *
539 get_base_access_vector (tree base)
541 return base_access_vec->get (base);
544 /* Find an access with required OFFSET and SIZE in a subtree of accesses rooted
545 in ACCESS. Return NULL if it cannot be found. */
547 static struct access *
548 find_access_in_subtree (struct access *access, HOST_WIDE_INT offset,
549 HOST_WIDE_INT size)
551 while (access && (access->offset != offset || access->size != size))
553 struct access *child = access->first_child;
555 while (child && (child->offset + child->size <= offset))
556 child = child->next_sibling;
557 access = child;
560 return access;
563 /* Return the first group representative for DECL or NULL if none exists. */
565 static struct access *
566 get_first_repr_for_decl (tree base)
568 vec<access_p> *access_vec;
570 access_vec = get_base_access_vector (base);
571 if (!access_vec)
572 return NULL;
574 return (*access_vec)[0];
577 /* Find an access representative for the variable BASE and given OFFSET and
578 SIZE. Requires that access trees have already been built. Return NULL if
579 it cannot be found. */
581 static struct access *
582 get_var_base_offset_size_access (tree base, HOST_WIDE_INT offset,
583 HOST_WIDE_INT size)
585 struct access *access;
587 access = get_first_repr_for_decl (base);
588 while (access && (access->offset + access->size <= offset))
589 access = access->next_grp;
590 if (!access)
591 return NULL;
593 return find_access_in_subtree (access, offset, size);
596 /* Add LINK to the linked list of assign links of RACC. */
597 static void
598 add_link_to_rhs (struct access *racc, struct assign_link *link)
600 gcc_assert (link->racc == racc);
602 if (!racc->first_link)
604 gcc_assert (!racc->last_link);
605 racc->first_link = link;
607 else
608 racc->last_link->next = link;
610 racc->last_link = link;
611 link->next = NULL;
614 /* Move all link structures in their linked list in OLD_RACC to the linked list
615 in NEW_RACC. */
616 static void
617 relink_to_new_repr (struct access *new_racc, struct access *old_racc)
619 if (!old_racc->first_link)
621 gcc_assert (!old_racc->last_link);
622 return;
625 if (new_racc->first_link)
627 gcc_assert (!new_racc->last_link->next);
628 gcc_assert (!old_racc->last_link || !old_racc->last_link->next);
630 new_racc->last_link->next = old_racc->first_link;
631 new_racc->last_link = old_racc->last_link;
633 else
635 gcc_assert (!new_racc->last_link);
637 new_racc->first_link = old_racc->first_link;
638 new_racc->last_link = old_racc->last_link;
640 old_racc->first_link = old_racc->last_link = NULL;
643 /* Add ACCESS to the work queue (which is actually a stack). */
645 static void
646 add_access_to_work_queue (struct access *access)
648 if (!access->grp_queued)
650 gcc_assert (!access->next_queued);
651 access->next_queued = work_queue_head;
652 access->grp_queued = 1;
653 work_queue_head = access;
657 /* Pop an access from the work queue, and return it, assuming there is one. */
659 static struct access *
660 pop_access_from_work_queue (void)
662 struct access *access = work_queue_head;
664 work_queue_head = access->next_queued;
665 access->next_queued = NULL;
666 access->grp_queued = 0;
667 return access;
671 /* Allocate necessary structures. */
673 static void
674 sra_initialize (void)
676 candidate_bitmap = BITMAP_ALLOC (NULL);
677 candidates = new hash_table<uid_decl_hasher>
678 (vec_safe_length (cfun->local_decls) / 2);
679 should_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
680 cannot_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
681 gcc_obstack_init (&name_obstack);
682 access_pool = create_alloc_pool ("SRA accesses", sizeof (struct access), 16);
683 link_pool = create_alloc_pool ("SRA links", sizeof (struct assign_link), 16);
684 base_access_vec = new hash_map<tree, auto_vec<access_p> >;
685 memset (&sra_stats, 0, sizeof (sra_stats));
686 encountered_apply_args = false;
687 encountered_recursive_call = false;
688 encountered_unchangable_recursive_call = false;
691 /* Deallocate all general structures. */
693 static void
694 sra_deinitialize (void)
696 BITMAP_FREE (candidate_bitmap);
697 delete candidates;
698 candidates = NULL;
699 BITMAP_FREE (should_scalarize_away_bitmap);
700 BITMAP_FREE (cannot_scalarize_away_bitmap);
701 free_alloc_pool (access_pool);
702 free_alloc_pool (link_pool);
703 obstack_free (&name_obstack, NULL);
705 delete base_access_vec;
708 /* Remove DECL from candidates for SRA and write REASON to the dump file if
709 there is one. */
710 static void
711 disqualify_candidate (tree decl, const char *reason)
713 if (bitmap_clear_bit (candidate_bitmap, DECL_UID (decl)))
714 candidates->remove_elt_with_hash (decl, DECL_UID (decl));
716 if (dump_file && (dump_flags & TDF_DETAILS))
718 fprintf (dump_file, "! Disqualifying ");
719 print_generic_expr (dump_file, decl, 0);
720 fprintf (dump_file, " - %s\n", reason);
724 /* Return true iff the type contains a field or an element which does not allow
725 scalarization. */
727 static bool
728 type_internals_preclude_sra_p (tree type, const char **msg)
730 tree fld;
731 tree et;
733 switch (TREE_CODE (type))
735 case RECORD_TYPE:
736 case UNION_TYPE:
737 case QUAL_UNION_TYPE:
738 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
739 if (TREE_CODE (fld) == FIELD_DECL)
741 tree ft = TREE_TYPE (fld);
743 if (TREE_THIS_VOLATILE (fld))
745 *msg = "volatile structure field";
746 return true;
748 if (!DECL_FIELD_OFFSET (fld))
750 *msg = "no structure field offset";
751 return true;
753 if (!DECL_SIZE (fld))
755 *msg = "zero structure field size";
756 return true;
758 if (!tree_fits_uhwi_p (DECL_FIELD_OFFSET (fld)))
760 *msg = "structure field offset not fixed";
761 return true;
763 if (!tree_fits_uhwi_p (DECL_SIZE (fld)))
765 *msg = "structure field size not fixed";
766 return true;
768 if (!tree_fits_shwi_p (bit_position (fld)))
770 *msg = "structure field size too big";
771 return true;
773 if (AGGREGATE_TYPE_P (ft)
774 && int_bit_position (fld) % BITS_PER_UNIT != 0)
776 *msg = "structure field is bit field";
777 return true;
780 if (AGGREGATE_TYPE_P (ft) && type_internals_preclude_sra_p (ft, msg))
781 return true;
784 return false;
786 case ARRAY_TYPE:
787 et = TREE_TYPE (type);
789 if (TYPE_VOLATILE (et))
791 *msg = "element type is volatile";
792 return true;
795 if (AGGREGATE_TYPE_P (et) && type_internals_preclude_sra_p (et, msg))
796 return true;
798 return false;
800 default:
801 return false;
805 /* If T is an SSA_NAME, return NULL if it is not a default def or return its
806 base variable if it is. Return T if it is not an SSA_NAME. */
808 static tree
809 get_ssa_base_param (tree t)
811 if (TREE_CODE (t) == SSA_NAME)
813 if (SSA_NAME_IS_DEFAULT_DEF (t))
814 return SSA_NAME_VAR (t);
815 else
816 return NULL_TREE;
818 return t;
821 /* Mark a dereference of BASE of distance DIST in a basic block tht STMT
822 belongs to, unless the BB has already been marked as a potentially
823 final. */
825 static void
826 mark_parm_dereference (tree base, HOST_WIDE_INT dist, gimple stmt)
828 basic_block bb = gimple_bb (stmt);
829 int idx, parm_index = 0;
830 tree parm;
832 if (bitmap_bit_p (final_bbs, bb->index))
833 return;
835 for (parm = DECL_ARGUMENTS (current_function_decl);
836 parm && parm != base;
837 parm = DECL_CHAIN (parm))
838 parm_index++;
840 gcc_assert (parm_index < func_param_count);
842 idx = bb->index * func_param_count + parm_index;
843 if (bb_dereferences[idx] < dist)
844 bb_dereferences[idx] = dist;
847 /* Allocate an access structure for BASE, OFFSET and SIZE, clear it, fill in
848 the three fields. Also add it to the vector of accesses corresponding to
849 the base. Finally, return the new access. */
851 static struct access *
852 create_access_1 (tree base, HOST_WIDE_INT offset, HOST_WIDE_INT size)
854 struct access *access;
856 access = (struct access *) pool_alloc (access_pool);
857 memset (access, 0, sizeof (struct access));
858 access->base = base;
859 access->offset = offset;
860 access->size = size;
862 base_access_vec->get_or_insert (base).safe_push (access);
864 return access;
867 /* Create and insert access for EXPR. Return created access, or NULL if it is
868 not possible. */
870 static struct access *
871 create_access (tree expr, gimple stmt, bool write)
873 struct access *access;
874 HOST_WIDE_INT offset, size, max_size;
875 tree base = expr;
876 bool ptr, unscalarizable_region = false;
878 base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
880 if (sra_mode == SRA_MODE_EARLY_IPA
881 && TREE_CODE (base) == MEM_REF)
883 base = get_ssa_base_param (TREE_OPERAND (base, 0));
884 if (!base)
885 return NULL;
886 ptr = true;
888 else
889 ptr = false;
891 if (!DECL_P (base) || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
892 return NULL;
894 if (sra_mode == SRA_MODE_EARLY_IPA)
896 if (size < 0 || size != max_size)
898 disqualify_candidate (base, "Encountered a variable sized access.");
899 return NULL;
901 if (TREE_CODE (expr) == COMPONENT_REF
902 && DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
904 disqualify_candidate (base, "Encountered a bit-field access.");
905 return NULL;
907 gcc_checking_assert ((offset % BITS_PER_UNIT) == 0);
909 if (ptr)
910 mark_parm_dereference (base, offset + size, stmt);
912 else
914 if (size != max_size)
916 size = max_size;
917 unscalarizable_region = true;
919 if (size < 0)
921 disqualify_candidate (base, "Encountered an unconstrained access.");
922 return NULL;
926 access = create_access_1 (base, offset, size);
927 access->expr = expr;
928 access->type = TREE_TYPE (expr);
929 access->write = write;
930 access->grp_unscalarizable_region = unscalarizable_region;
931 access->stmt = stmt;
933 if (TREE_CODE (expr) == COMPONENT_REF
934 && DECL_NONADDRESSABLE_P (TREE_OPERAND (expr, 1)))
935 access->non_addressable = 1;
937 return access;
941 /* Return true iff TYPE is a RECORD_TYPE with fields that are either of gimple
942 register types or (recursively) records with only these two kinds of fields.
943 It also returns false if any of these records contains a bit-field. */
945 static bool
946 type_consists_of_records_p (tree type)
948 tree fld;
950 if (TREE_CODE (type) != RECORD_TYPE)
951 return false;
953 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
954 if (TREE_CODE (fld) == FIELD_DECL)
956 tree ft = TREE_TYPE (fld);
958 if (DECL_BIT_FIELD (fld))
959 return false;
961 if (!is_gimple_reg_type (ft)
962 && !type_consists_of_records_p (ft))
963 return false;
966 return true;
969 /* Create total_scalarization accesses for all scalar type fields in DECL that
970 must be of a RECORD_TYPE conforming to type_consists_of_records_p. BASE
971 must be the top-most VAR_DECL representing the variable, OFFSET must be the
972 offset of DECL within BASE. REF must be the memory reference expression for
973 the given decl. */
975 static void
976 completely_scalarize_record (tree base, tree decl, HOST_WIDE_INT offset,
977 tree ref)
979 tree fld, decl_type = TREE_TYPE (decl);
981 for (fld = TYPE_FIELDS (decl_type); fld; fld = DECL_CHAIN (fld))
982 if (TREE_CODE (fld) == FIELD_DECL)
984 HOST_WIDE_INT pos = offset + int_bit_position (fld);
985 tree ft = TREE_TYPE (fld);
986 tree nref = build3 (COMPONENT_REF, TREE_TYPE (fld), ref, fld,
987 NULL_TREE);
989 if (is_gimple_reg_type (ft))
991 struct access *access;
992 HOST_WIDE_INT size;
994 size = tree_to_uhwi (DECL_SIZE (fld));
995 access = create_access_1 (base, pos, size);
996 access->expr = nref;
997 access->type = ft;
998 access->grp_total_scalarization = 1;
999 /* Accesses for intraprocedural SRA can have their stmt NULL. */
1001 else
1002 completely_scalarize_record (base, fld, pos, nref);
1006 /* Create total_scalarization accesses for all scalar type fields in VAR and
1007 for VAR a a whole. VAR must be of a RECORD_TYPE conforming to
1008 type_consists_of_records_p. */
1010 static void
1011 completely_scalarize_var (tree var)
1013 HOST_WIDE_INT size = tree_to_uhwi (DECL_SIZE (var));
1014 struct access *access;
1016 access = create_access_1 (var, 0, size);
1017 access->expr = var;
1018 access->type = TREE_TYPE (var);
1019 access->grp_total_scalarization = 1;
1021 completely_scalarize_record (var, var, 0, var);
1024 /* Return true if REF has an VIEW_CONVERT_EXPR somewhere in it. */
1026 static inline bool
1027 contains_view_convert_expr_p (const_tree ref)
1029 while (handled_component_p (ref))
1031 if (TREE_CODE (ref) == VIEW_CONVERT_EXPR)
1032 return true;
1033 ref = TREE_OPERAND (ref, 0);
1036 return false;
1039 /* Search the given tree for a declaration by skipping handled components and
1040 exclude it from the candidates. */
1042 static void
1043 disqualify_base_of_expr (tree t, const char *reason)
1045 t = get_base_address (t);
1046 if (sra_mode == SRA_MODE_EARLY_IPA
1047 && TREE_CODE (t) == MEM_REF)
1048 t = get_ssa_base_param (TREE_OPERAND (t, 0));
1050 if (t && DECL_P (t))
1051 disqualify_candidate (t, reason);
1054 /* Scan expression EXPR and create access structures for all accesses to
1055 candidates for scalarization. Return the created access or NULL if none is
1056 created. */
1058 static struct access *
1059 build_access_from_expr_1 (tree expr, gimple stmt, bool write)
1061 struct access *ret = NULL;
1062 bool partial_ref;
1064 if (TREE_CODE (expr) == BIT_FIELD_REF
1065 || TREE_CODE (expr) == IMAGPART_EXPR
1066 || TREE_CODE (expr) == REALPART_EXPR)
1068 expr = TREE_OPERAND (expr, 0);
1069 partial_ref = true;
1071 else
1072 partial_ref = false;
1074 /* We need to dive through V_C_Es in order to get the size of its parameter
1075 and not the result type. Ada produces such statements. We are also
1076 capable of handling the topmost V_C_E but not any of those buried in other
1077 handled components. */
1078 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
1079 expr = TREE_OPERAND (expr, 0);
1081 if (contains_view_convert_expr_p (expr))
1083 disqualify_base_of_expr (expr, "V_C_E under a different handled "
1084 "component.");
1085 return NULL;
1087 if (TREE_THIS_VOLATILE (expr))
1089 disqualify_base_of_expr (expr, "part of a volatile reference.");
1090 return NULL;
1093 switch (TREE_CODE (expr))
1095 case MEM_REF:
1096 if (TREE_CODE (TREE_OPERAND (expr, 0)) != ADDR_EXPR
1097 && sra_mode != SRA_MODE_EARLY_IPA)
1098 return NULL;
1099 /* fall through */
1100 case VAR_DECL:
1101 case PARM_DECL:
1102 case RESULT_DECL:
1103 case COMPONENT_REF:
1104 case ARRAY_REF:
1105 case ARRAY_RANGE_REF:
1106 ret = create_access (expr, stmt, write);
1107 break;
1109 default:
1110 break;
1113 if (write && partial_ref && ret)
1114 ret->grp_partial_lhs = 1;
1116 return ret;
1119 /* Scan expression EXPR and create access structures for all accesses to
1120 candidates for scalarization. Return true if any access has been inserted.
1121 STMT must be the statement from which the expression is taken, WRITE must be
1122 true if the expression is a store and false otherwise. */
1124 static bool
1125 build_access_from_expr (tree expr, gimple stmt, bool write)
1127 struct access *access;
1129 access = build_access_from_expr_1 (expr, stmt, write);
1130 if (access)
1132 /* This means the aggregate is accesses as a whole in a way other than an
1133 assign statement and thus cannot be removed even if we had a scalar
1134 replacement for everything. */
1135 if (cannot_scalarize_away_bitmap)
1136 bitmap_set_bit (cannot_scalarize_away_bitmap, DECL_UID (access->base));
1137 return true;
1139 return false;
1142 /* Return the single non-EH successor edge of BB or NULL if there is none or
1143 more than one. */
1145 static edge
1146 single_non_eh_succ (basic_block bb)
1148 edge e, res = NULL;
1149 edge_iterator ei;
1151 FOR_EACH_EDGE (e, ei, bb->succs)
1152 if (!(e->flags & EDGE_EH))
1154 if (res)
1155 return NULL;
1156 res = e;
1159 return res;
1162 /* Disqualify LHS and RHS for scalarization if STMT has to terminate its BB and
1163 there is no alternative spot where to put statements SRA might need to
1164 generate after it. The spot we are looking for is an edge leading to a
1165 single non-EH successor, if it exists and is indeed single. RHS may be
1166 NULL, in that case ignore it. */
1168 static bool
1169 disqualify_if_bad_bb_terminating_stmt (gimple stmt, tree lhs, tree rhs)
1171 if ((sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
1172 && stmt_ends_bb_p (stmt))
1174 if (single_non_eh_succ (gimple_bb (stmt)))
1175 return false;
1177 disqualify_base_of_expr (lhs, "LHS of a throwing stmt.");
1178 if (rhs)
1179 disqualify_base_of_expr (rhs, "RHS of a throwing stmt.");
1180 return true;
1182 return false;
1185 /* Scan expressions occurring in STMT, create access structures for all accesses
1186 to candidates for scalarization and remove those candidates which occur in
1187 statements or expressions that prevent them from being split apart. Return
1188 true if any access has been inserted. */
1190 static bool
1191 build_accesses_from_assign (gimple stmt)
1193 tree lhs, rhs;
1194 struct access *lacc, *racc;
1196 if (!gimple_assign_single_p (stmt)
1197 /* Scope clobbers don't influence scalarization. */
1198 || gimple_clobber_p (stmt))
1199 return false;
1201 lhs = gimple_assign_lhs (stmt);
1202 rhs = gimple_assign_rhs1 (stmt);
1204 if (disqualify_if_bad_bb_terminating_stmt (stmt, lhs, rhs))
1205 return false;
1207 racc = build_access_from_expr_1 (rhs, stmt, false);
1208 lacc = build_access_from_expr_1 (lhs, stmt, true);
1210 if (lacc)
1211 lacc->grp_assignment_write = 1;
1213 if (racc)
1215 racc->grp_assignment_read = 1;
1216 if (should_scalarize_away_bitmap && !gimple_has_volatile_ops (stmt)
1217 && !is_gimple_reg_type (racc->type))
1218 bitmap_set_bit (should_scalarize_away_bitmap, DECL_UID (racc->base));
1221 if (lacc && racc
1222 && (sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
1223 && !lacc->grp_unscalarizable_region
1224 && !racc->grp_unscalarizable_region
1225 && AGGREGATE_TYPE_P (TREE_TYPE (lhs))
1226 && lacc->size == racc->size
1227 && useless_type_conversion_p (lacc->type, racc->type))
1229 struct assign_link *link;
1231 link = (struct assign_link *) pool_alloc (link_pool);
1232 memset (link, 0, sizeof (struct assign_link));
1234 link->lacc = lacc;
1235 link->racc = racc;
1237 add_link_to_rhs (racc, link);
1240 return lacc || racc;
1243 /* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine
1244 GIMPLE_ASM operands with memory constrains which cannot be scalarized. */
1246 static bool
1247 asm_visit_addr (gimple, tree op, tree, void *)
1249 op = get_base_address (op);
1250 if (op
1251 && DECL_P (op))
1252 disqualify_candidate (op, "Non-scalarizable GIMPLE_ASM operand.");
1254 return false;
1257 /* Return true iff callsite CALL has at least as many actual arguments as there
1258 are formal parameters of the function currently processed by IPA-SRA and
1259 that their types match. */
1261 static inline bool
1262 callsite_arguments_match_p (gimple call)
1264 if (gimple_call_num_args (call) < (unsigned) func_param_count)
1265 return false;
1267 tree parm;
1268 int i;
1269 for (parm = DECL_ARGUMENTS (current_function_decl), i = 0;
1270 parm;
1271 parm = DECL_CHAIN (parm), i++)
1273 tree arg = gimple_call_arg (call, i);
1274 if (!useless_type_conversion_p (TREE_TYPE (parm), TREE_TYPE (arg)))
1275 return false;
1277 return true;
1280 /* Scan function and look for interesting expressions and create access
1281 structures for them. Return true iff any access is created. */
1283 static bool
1284 scan_function (void)
1286 basic_block bb;
1287 bool ret = false;
1289 FOR_EACH_BB_FN (bb, cfun)
1291 gimple_stmt_iterator gsi;
1292 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1294 gimple stmt = gsi_stmt (gsi);
1295 tree t;
1296 unsigned i;
1298 if (final_bbs && stmt_can_throw_external (stmt))
1299 bitmap_set_bit (final_bbs, bb->index);
1300 switch (gimple_code (stmt))
1302 case GIMPLE_RETURN:
1303 t = gimple_return_retval (as_a <greturn *> (stmt));
1304 if (t != NULL_TREE)
1305 ret |= build_access_from_expr (t, stmt, false);
1306 if (final_bbs)
1307 bitmap_set_bit (final_bbs, bb->index);
1308 break;
1310 case GIMPLE_ASSIGN:
1311 ret |= build_accesses_from_assign (stmt);
1312 break;
1314 case GIMPLE_CALL:
1315 for (i = 0; i < gimple_call_num_args (stmt); i++)
1316 ret |= build_access_from_expr (gimple_call_arg (stmt, i),
1317 stmt, false);
1319 if (sra_mode == SRA_MODE_EARLY_IPA)
1321 tree dest = gimple_call_fndecl (stmt);
1322 int flags = gimple_call_flags (stmt);
1324 if (dest)
1326 if (DECL_BUILT_IN_CLASS (dest) == BUILT_IN_NORMAL
1327 && DECL_FUNCTION_CODE (dest) == BUILT_IN_APPLY_ARGS)
1328 encountered_apply_args = true;
1329 if (recursive_call_p (current_function_decl, dest))
1331 encountered_recursive_call = true;
1332 if (!callsite_arguments_match_p (stmt))
1333 encountered_unchangable_recursive_call = true;
1337 if (final_bbs
1338 && (flags & (ECF_CONST | ECF_PURE)) == 0)
1339 bitmap_set_bit (final_bbs, bb->index);
1342 t = gimple_call_lhs (stmt);
1343 if (t && !disqualify_if_bad_bb_terminating_stmt (stmt, t, NULL))
1344 ret |= build_access_from_expr (t, stmt, true);
1345 break;
1347 case GIMPLE_ASM:
1349 gasm *asm_stmt = as_a <gasm *> (stmt);
1350 walk_stmt_load_store_addr_ops (asm_stmt, NULL, NULL, NULL,
1351 asm_visit_addr);
1352 if (final_bbs)
1353 bitmap_set_bit (final_bbs, bb->index);
1355 for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
1357 t = TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
1358 ret |= build_access_from_expr (t, asm_stmt, false);
1360 for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
1362 t = TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
1363 ret |= build_access_from_expr (t, asm_stmt, true);
1366 break;
1368 default:
1369 break;
1374 return ret;
1377 /* Helper of QSORT function. There are pointers to accesses in the array. An
1378 access is considered smaller than another if it has smaller offset or if the
1379 offsets are the same but is size is bigger. */
1381 static int
1382 compare_access_positions (const void *a, const void *b)
1384 const access_p *fp1 = (const access_p *) a;
1385 const access_p *fp2 = (const access_p *) b;
1386 const access_p f1 = *fp1;
1387 const access_p f2 = *fp2;
1389 if (f1->offset != f2->offset)
1390 return f1->offset < f2->offset ? -1 : 1;
1392 if (f1->size == f2->size)
1394 if (f1->type == f2->type)
1395 return 0;
1396 /* Put any non-aggregate type before any aggregate type. */
1397 else if (!is_gimple_reg_type (f1->type)
1398 && is_gimple_reg_type (f2->type))
1399 return 1;
1400 else if (is_gimple_reg_type (f1->type)
1401 && !is_gimple_reg_type (f2->type))
1402 return -1;
1403 /* Put any complex or vector type before any other scalar type. */
1404 else if (TREE_CODE (f1->type) != COMPLEX_TYPE
1405 && TREE_CODE (f1->type) != VECTOR_TYPE
1406 && (TREE_CODE (f2->type) == COMPLEX_TYPE
1407 || TREE_CODE (f2->type) == VECTOR_TYPE))
1408 return 1;
1409 else if ((TREE_CODE (f1->type) == COMPLEX_TYPE
1410 || TREE_CODE (f1->type) == VECTOR_TYPE)
1411 && TREE_CODE (f2->type) != COMPLEX_TYPE
1412 && TREE_CODE (f2->type) != VECTOR_TYPE)
1413 return -1;
1414 /* Put the integral type with the bigger precision first. */
1415 else if (INTEGRAL_TYPE_P (f1->type)
1416 && INTEGRAL_TYPE_P (f2->type))
1417 return TYPE_PRECISION (f2->type) - TYPE_PRECISION (f1->type);
1418 /* Put any integral type with non-full precision last. */
1419 else if (INTEGRAL_TYPE_P (f1->type)
1420 && (TREE_INT_CST_LOW (TYPE_SIZE (f1->type))
1421 != TYPE_PRECISION (f1->type)))
1422 return 1;
1423 else if (INTEGRAL_TYPE_P (f2->type)
1424 && (TREE_INT_CST_LOW (TYPE_SIZE (f2->type))
1425 != TYPE_PRECISION (f2->type)))
1426 return -1;
1427 /* Stabilize the sort. */
1428 return TYPE_UID (f1->type) - TYPE_UID (f2->type);
1431 /* We want the bigger accesses first, thus the opposite operator in the next
1432 line: */
1433 return f1->size > f2->size ? -1 : 1;
1437 /* Append a name of the declaration to the name obstack. A helper function for
1438 make_fancy_name. */
1440 static void
1441 make_fancy_decl_name (tree decl)
1443 char buffer[32];
1445 tree name = DECL_NAME (decl);
1446 if (name)
1447 obstack_grow (&name_obstack, IDENTIFIER_POINTER (name),
1448 IDENTIFIER_LENGTH (name));
1449 else
1451 sprintf (buffer, "D%u", DECL_UID (decl));
1452 obstack_grow (&name_obstack, buffer, strlen (buffer));
1456 /* Helper for make_fancy_name. */
1458 static void
1459 make_fancy_name_1 (tree expr)
1461 char buffer[32];
1462 tree index;
1464 if (DECL_P (expr))
1466 make_fancy_decl_name (expr);
1467 return;
1470 switch (TREE_CODE (expr))
1472 case COMPONENT_REF:
1473 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1474 obstack_1grow (&name_obstack, '$');
1475 make_fancy_decl_name (TREE_OPERAND (expr, 1));
1476 break;
1478 case ARRAY_REF:
1479 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1480 obstack_1grow (&name_obstack, '$');
1481 /* Arrays with only one element may not have a constant as their
1482 index. */
1483 index = TREE_OPERAND (expr, 1);
1484 if (TREE_CODE (index) != INTEGER_CST)
1485 break;
1486 sprintf (buffer, HOST_WIDE_INT_PRINT_DEC, TREE_INT_CST_LOW (index));
1487 obstack_grow (&name_obstack, buffer, strlen (buffer));
1488 break;
1490 case ADDR_EXPR:
1491 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1492 break;
1494 case MEM_REF:
1495 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1496 if (!integer_zerop (TREE_OPERAND (expr, 1)))
1498 obstack_1grow (&name_obstack, '$');
1499 sprintf (buffer, HOST_WIDE_INT_PRINT_DEC,
1500 TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)));
1501 obstack_grow (&name_obstack, buffer, strlen (buffer));
1503 break;
1505 case BIT_FIELD_REF:
1506 case REALPART_EXPR:
1507 case IMAGPART_EXPR:
1508 gcc_unreachable (); /* we treat these as scalars. */
1509 break;
1510 default:
1511 break;
1515 /* Create a human readable name for replacement variable of ACCESS. */
1517 static char *
1518 make_fancy_name (tree expr)
1520 make_fancy_name_1 (expr);
1521 obstack_1grow (&name_obstack, '\0');
1522 return XOBFINISH (&name_obstack, char *);
1525 /* Construct a MEM_REF that would reference a part of aggregate BASE of type
1526 EXP_TYPE at the given OFFSET. If BASE is something for which
1527 get_addr_base_and_unit_offset returns NULL, gsi must be non-NULL and is used
1528 to insert new statements either before or below the current one as specified
1529 by INSERT_AFTER. This function is not capable of handling bitfields.
1531 BASE must be either a declaration or a memory reference that has correct
1532 alignment ifformation embeded in it (e.g. a pre-existing one in SRA). */
1534 tree
1535 build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset,
1536 tree exp_type, gimple_stmt_iterator *gsi,
1537 bool insert_after)
1539 tree prev_base = base;
1540 tree off;
1541 tree mem_ref;
1542 HOST_WIDE_INT base_offset;
1543 unsigned HOST_WIDE_INT misalign;
1544 unsigned int align;
1546 gcc_checking_assert (offset % BITS_PER_UNIT == 0);
1547 get_object_alignment_1 (base, &align, &misalign);
1548 base = get_addr_base_and_unit_offset (base, &base_offset);
1550 /* get_addr_base_and_unit_offset returns NULL for references with a variable
1551 offset such as array[var_index]. */
1552 if (!base)
1554 gassign *stmt;
1555 tree tmp, addr;
1557 gcc_checking_assert (gsi);
1558 tmp = make_ssa_name (build_pointer_type (TREE_TYPE (prev_base)));
1559 addr = build_fold_addr_expr (unshare_expr (prev_base));
1560 STRIP_USELESS_TYPE_CONVERSION (addr);
1561 stmt = gimple_build_assign (tmp, addr);
1562 gimple_set_location (stmt, loc);
1563 if (insert_after)
1564 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
1565 else
1566 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
1568 off = build_int_cst (reference_alias_ptr_type (prev_base),
1569 offset / BITS_PER_UNIT);
1570 base = tmp;
1572 else if (TREE_CODE (base) == MEM_REF)
1574 off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
1575 base_offset + offset / BITS_PER_UNIT);
1576 off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
1577 base = unshare_expr (TREE_OPERAND (base, 0));
1579 else
1581 off = build_int_cst (reference_alias_ptr_type (base),
1582 base_offset + offset / BITS_PER_UNIT);
1583 base = build_fold_addr_expr (unshare_expr (base));
1586 misalign = (misalign + offset) & (align - 1);
1587 if (misalign != 0)
1588 align = (misalign & -misalign);
1589 if (align < TYPE_ALIGN (exp_type))
1590 exp_type = build_aligned_type (exp_type, align);
1592 mem_ref = fold_build2_loc (loc, MEM_REF, exp_type, base, off);
1593 if (TREE_THIS_VOLATILE (prev_base))
1594 TREE_THIS_VOLATILE (mem_ref) = 1;
1595 if (TREE_SIDE_EFFECTS (prev_base))
1596 TREE_SIDE_EFFECTS (mem_ref) = 1;
1597 return mem_ref;
1600 /* Construct a memory reference to a part of an aggregate BASE at the given
1601 OFFSET and of the same type as MODEL. In case this is a reference to a
1602 bit-field, the function will replicate the last component_ref of model's
1603 expr to access it. GSI and INSERT_AFTER have the same meaning as in
1604 build_ref_for_offset. */
1606 static tree
1607 build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
1608 struct access *model, gimple_stmt_iterator *gsi,
1609 bool insert_after)
1611 if (TREE_CODE (model->expr) == COMPONENT_REF
1612 && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
1614 /* This access represents a bit-field. */
1615 tree t, exp_type, fld = TREE_OPERAND (model->expr, 1);
1617 offset -= int_bit_position (fld);
1618 exp_type = TREE_TYPE (TREE_OPERAND (model->expr, 0));
1619 t = build_ref_for_offset (loc, base, offset, exp_type, gsi, insert_after);
1620 return fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (fld), t, fld,
1621 NULL_TREE);
1623 else
1624 return build_ref_for_offset (loc, base, offset, model->type,
1625 gsi, insert_after);
1628 /* Attempt to build a memory reference that we could but into a gimple
1629 debug_bind statement. Similar to build_ref_for_model but punts if it has to
1630 create statements and return s NULL instead. This function also ignores
1631 alignment issues and so its results should never end up in non-debug
1632 statements. */
1634 static tree
1635 build_debug_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
1636 struct access *model)
1638 HOST_WIDE_INT base_offset;
1639 tree off;
1641 if (TREE_CODE (model->expr) == COMPONENT_REF
1642 && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
1643 return NULL_TREE;
1645 base = get_addr_base_and_unit_offset (base, &base_offset);
1646 if (!base)
1647 return NULL_TREE;
1648 if (TREE_CODE (base) == MEM_REF)
1650 off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
1651 base_offset + offset / BITS_PER_UNIT);
1652 off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
1653 base = unshare_expr (TREE_OPERAND (base, 0));
1655 else
1657 off = build_int_cst (reference_alias_ptr_type (base),
1658 base_offset + offset / BITS_PER_UNIT);
1659 base = build_fold_addr_expr (unshare_expr (base));
1662 return fold_build2_loc (loc, MEM_REF, model->type, base, off);
1665 /* Construct a memory reference consisting of component_refs and array_refs to
1666 a part of an aggregate *RES (which is of type TYPE). The requested part
1667 should have type EXP_TYPE at be the given OFFSET. This function might not
1668 succeed, it returns true when it does and only then *RES points to something
1669 meaningful. This function should be used only to build expressions that we
1670 might need to present to user (e.g. in warnings). In all other situations,
1671 build_ref_for_model or build_ref_for_offset should be used instead. */
1673 static bool
1674 build_user_friendly_ref_for_offset (tree *res, tree type, HOST_WIDE_INT offset,
1675 tree exp_type)
1677 while (1)
1679 tree fld;
1680 tree tr_size, index, minidx;
1681 HOST_WIDE_INT el_size;
1683 if (offset == 0 && exp_type
1684 && types_compatible_p (exp_type, type))
1685 return true;
1687 switch (TREE_CODE (type))
1689 case UNION_TYPE:
1690 case QUAL_UNION_TYPE:
1691 case RECORD_TYPE:
1692 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
1694 HOST_WIDE_INT pos, size;
1695 tree tr_pos, expr, *expr_ptr;
1697 if (TREE_CODE (fld) != FIELD_DECL)
1698 continue;
1700 tr_pos = bit_position (fld);
1701 if (!tr_pos || !tree_fits_uhwi_p (tr_pos))
1702 continue;
1703 pos = tree_to_uhwi (tr_pos);
1704 gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0);
1705 tr_size = DECL_SIZE (fld);
1706 if (!tr_size || !tree_fits_uhwi_p (tr_size))
1707 continue;
1708 size = tree_to_uhwi (tr_size);
1709 if (size == 0)
1711 if (pos != offset)
1712 continue;
1714 else if (pos > offset || (pos + size) <= offset)
1715 continue;
1717 expr = build3 (COMPONENT_REF, TREE_TYPE (fld), *res, fld,
1718 NULL_TREE);
1719 expr_ptr = &expr;
1720 if (build_user_friendly_ref_for_offset (expr_ptr, TREE_TYPE (fld),
1721 offset - pos, exp_type))
1723 *res = expr;
1724 return true;
1727 return false;
1729 case ARRAY_TYPE:
1730 tr_size = TYPE_SIZE (TREE_TYPE (type));
1731 if (!tr_size || !tree_fits_uhwi_p (tr_size))
1732 return false;
1733 el_size = tree_to_uhwi (tr_size);
1735 minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
1736 if (TREE_CODE (minidx) != INTEGER_CST || el_size == 0)
1737 return false;
1738 index = build_int_cst (TYPE_DOMAIN (type), offset / el_size);
1739 if (!integer_zerop (minidx))
1740 index = int_const_binop (PLUS_EXPR, index, minidx);
1741 *res = build4 (ARRAY_REF, TREE_TYPE (type), *res, index,
1742 NULL_TREE, NULL_TREE);
1743 offset = offset % el_size;
1744 type = TREE_TYPE (type);
1745 break;
1747 default:
1748 if (offset != 0)
1749 return false;
1751 if (exp_type)
1752 return false;
1753 else
1754 return true;
1759 /* Return true iff TYPE is stdarg va_list type. */
1761 static inline bool
1762 is_va_list_type (tree type)
1764 return TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (va_list_type_node);
1767 /* Print message to dump file why a variable was rejected. */
1769 static void
1770 reject (tree var, const char *msg)
1772 if (dump_file && (dump_flags & TDF_DETAILS))
1774 fprintf (dump_file, "Rejected (%d): %s: ", DECL_UID (var), msg);
1775 print_generic_expr (dump_file, var, 0);
1776 fprintf (dump_file, "\n");
1780 /* Return true if VAR is a candidate for SRA. */
1782 static bool
1783 maybe_add_sra_candidate (tree var)
1785 tree type = TREE_TYPE (var);
1786 const char *msg;
1787 tree_node **slot;
1789 if (!AGGREGATE_TYPE_P (type))
1791 reject (var, "not aggregate");
1792 return false;
1794 if (needs_to_live_in_memory (var))
1796 reject (var, "needs to live in memory");
1797 return false;
1799 if (TREE_THIS_VOLATILE (var))
1801 reject (var, "is volatile");
1802 return false;
1804 if (!COMPLETE_TYPE_P (type))
1806 reject (var, "has incomplete type");
1807 return false;
1809 if (!tree_fits_uhwi_p (TYPE_SIZE (type)))
1811 reject (var, "type size not fixed");
1812 return false;
1814 if (tree_to_uhwi (TYPE_SIZE (type)) == 0)
1816 reject (var, "type size is zero");
1817 return false;
1819 if (type_internals_preclude_sra_p (type, &msg))
1821 reject (var, msg);
1822 return false;
1824 if (/* Fix for PR 41089. tree-stdarg.c needs to have va_lists intact but
1825 we also want to schedule it rather late. Thus we ignore it in
1826 the early pass. */
1827 (sra_mode == SRA_MODE_EARLY_INTRA
1828 && is_va_list_type (type)))
1830 reject (var, "is va_list");
1831 return false;
1834 bitmap_set_bit (candidate_bitmap, DECL_UID (var));
1835 slot = candidates->find_slot_with_hash (var, DECL_UID (var), INSERT);
1836 *slot = var;
1838 if (dump_file && (dump_flags & TDF_DETAILS))
1840 fprintf (dump_file, "Candidate (%d): ", DECL_UID (var));
1841 print_generic_expr (dump_file, var, 0);
1842 fprintf (dump_file, "\n");
1845 return true;
1848 /* The very first phase of intraprocedural SRA. It marks in candidate_bitmap
1849 those with type which is suitable for scalarization. */
1851 static bool
1852 find_var_candidates (void)
1854 tree var, parm;
1855 unsigned int i;
1856 bool ret = false;
1858 for (parm = DECL_ARGUMENTS (current_function_decl);
1859 parm;
1860 parm = DECL_CHAIN (parm))
1861 ret |= maybe_add_sra_candidate (parm);
1863 FOR_EACH_LOCAL_DECL (cfun, i, var)
1865 if (TREE_CODE (var) != VAR_DECL)
1866 continue;
1868 ret |= maybe_add_sra_candidate (var);
1871 return ret;
1874 /* Sort all accesses for the given variable, check for partial overlaps and
1875 return NULL if there are any. If there are none, pick a representative for
1876 each combination of offset and size and create a linked list out of them.
1877 Return the pointer to the first representative and make sure it is the first
1878 one in the vector of accesses. */
1880 static struct access *
1881 sort_and_splice_var_accesses (tree var)
1883 int i, j, access_count;
1884 struct access *res, **prev_acc_ptr = &res;
1885 vec<access_p> *access_vec;
1886 bool first = true;
1887 HOST_WIDE_INT low = -1, high = 0;
1889 access_vec = get_base_access_vector (var);
1890 if (!access_vec)
1891 return NULL;
1892 access_count = access_vec->length ();
1894 /* Sort by <OFFSET, SIZE>. */
1895 access_vec->qsort (compare_access_positions);
1897 i = 0;
1898 while (i < access_count)
1900 struct access *access = (*access_vec)[i];
1901 bool grp_write = access->write;
1902 bool grp_read = !access->write;
1903 bool grp_scalar_write = access->write
1904 && is_gimple_reg_type (access->type);
1905 bool grp_scalar_read = !access->write
1906 && is_gimple_reg_type (access->type);
1907 bool grp_assignment_read = access->grp_assignment_read;
1908 bool grp_assignment_write = access->grp_assignment_write;
1909 bool multiple_scalar_reads = false;
1910 bool total_scalarization = access->grp_total_scalarization;
1911 bool grp_partial_lhs = access->grp_partial_lhs;
1912 bool first_scalar = is_gimple_reg_type (access->type);
1913 bool unscalarizable_region = access->grp_unscalarizable_region;
1915 if (first || access->offset >= high)
1917 first = false;
1918 low = access->offset;
1919 high = access->offset + access->size;
1921 else if (access->offset > low && access->offset + access->size > high)
1922 return NULL;
1923 else
1924 gcc_assert (access->offset >= low
1925 && access->offset + access->size <= high);
1927 j = i + 1;
1928 while (j < access_count)
1930 struct access *ac2 = (*access_vec)[j];
1931 if (ac2->offset != access->offset || ac2->size != access->size)
1932 break;
1933 if (ac2->write)
1935 grp_write = true;
1936 grp_scalar_write = (grp_scalar_write
1937 || is_gimple_reg_type (ac2->type));
1939 else
1941 grp_read = true;
1942 if (is_gimple_reg_type (ac2->type))
1944 if (grp_scalar_read)
1945 multiple_scalar_reads = true;
1946 else
1947 grp_scalar_read = true;
1950 grp_assignment_read |= ac2->grp_assignment_read;
1951 grp_assignment_write |= ac2->grp_assignment_write;
1952 grp_partial_lhs |= ac2->grp_partial_lhs;
1953 unscalarizable_region |= ac2->grp_unscalarizable_region;
1954 total_scalarization |= ac2->grp_total_scalarization;
1955 relink_to_new_repr (access, ac2);
1957 /* If there are both aggregate-type and scalar-type accesses with
1958 this combination of size and offset, the comparison function
1959 should have put the scalars first. */
1960 gcc_assert (first_scalar || !is_gimple_reg_type (ac2->type));
1961 ac2->group_representative = access;
1962 j++;
1965 i = j;
1967 access->group_representative = access;
1968 access->grp_write = grp_write;
1969 access->grp_read = grp_read;
1970 access->grp_scalar_read = grp_scalar_read;
1971 access->grp_scalar_write = grp_scalar_write;
1972 access->grp_assignment_read = grp_assignment_read;
1973 access->grp_assignment_write = grp_assignment_write;
1974 access->grp_hint = multiple_scalar_reads || total_scalarization;
1975 access->grp_total_scalarization = total_scalarization;
1976 access->grp_partial_lhs = grp_partial_lhs;
1977 access->grp_unscalarizable_region = unscalarizable_region;
1978 if (access->first_link)
1979 add_access_to_work_queue (access);
1981 *prev_acc_ptr = access;
1982 prev_acc_ptr = &access->next_grp;
1985 gcc_assert (res == (*access_vec)[0]);
1986 return res;
1989 /* Create a variable for the given ACCESS which determines the type, name and a
1990 few other properties. Return the variable declaration and store it also to
1991 ACCESS->replacement. */
1993 static tree
1994 create_access_replacement (struct access *access)
1996 tree repl;
1998 if (access->grp_to_be_debug_replaced)
2000 repl = create_tmp_var_raw (access->type);
2001 DECL_CONTEXT (repl) = current_function_decl;
2003 else
2004 repl = create_tmp_var (access->type, "SR");
2005 if (TREE_CODE (access->type) == COMPLEX_TYPE
2006 || TREE_CODE (access->type) == VECTOR_TYPE)
2008 if (!access->grp_partial_lhs)
2009 DECL_GIMPLE_REG_P (repl) = 1;
2011 else if (access->grp_partial_lhs
2012 && is_gimple_reg_type (access->type))
2013 TREE_ADDRESSABLE (repl) = 1;
2015 DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base);
2016 DECL_ARTIFICIAL (repl) = 1;
2017 DECL_IGNORED_P (repl) = DECL_IGNORED_P (access->base);
2019 if (DECL_NAME (access->base)
2020 && !DECL_IGNORED_P (access->base)
2021 && !DECL_ARTIFICIAL (access->base))
2023 char *pretty_name = make_fancy_name (access->expr);
2024 tree debug_expr = unshare_expr_without_location (access->expr), d;
2025 bool fail = false;
2027 DECL_NAME (repl) = get_identifier (pretty_name);
2028 obstack_free (&name_obstack, pretty_name);
2030 /* Get rid of any SSA_NAMEs embedded in debug_expr,
2031 as DECL_DEBUG_EXPR isn't considered when looking for still
2032 used SSA_NAMEs and thus they could be freed. All debug info
2033 generation cares is whether something is constant or variable
2034 and that get_ref_base_and_extent works properly on the
2035 expression. It cannot handle accesses at a non-constant offset
2036 though, so just give up in those cases. */
2037 for (d = debug_expr;
2038 !fail && (handled_component_p (d) || TREE_CODE (d) == MEM_REF);
2039 d = TREE_OPERAND (d, 0))
2040 switch (TREE_CODE (d))
2042 case ARRAY_REF:
2043 case ARRAY_RANGE_REF:
2044 if (TREE_OPERAND (d, 1)
2045 && TREE_CODE (TREE_OPERAND (d, 1)) != INTEGER_CST)
2046 fail = true;
2047 if (TREE_OPERAND (d, 3)
2048 && TREE_CODE (TREE_OPERAND (d, 3)) != INTEGER_CST)
2049 fail = true;
2050 /* FALLTHRU */
2051 case COMPONENT_REF:
2052 if (TREE_OPERAND (d, 2)
2053 && TREE_CODE (TREE_OPERAND (d, 2)) != INTEGER_CST)
2054 fail = true;
2055 break;
2056 case MEM_REF:
2057 if (TREE_CODE (TREE_OPERAND (d, 0)) != ADDR_EXPR)
2058 fail = true;
2059 else
2060 d = TREE_OPERAND (d, 0);
2061 break;
2062 default:
2063 break;
2065 if (!fail)
2067 SET_DECL_DEBUG_EXPR (repl, debug_expr);
2068 DECL_HAS_DEBUG_EXPR_P (repl) = 1;
2070 if (access->grp_no_warning)
2071 TREE_NO_WARNING (repl) = 1;
2072 else
2073 TREE_NO_WARNING (repl) = TREE_NO_WARNING (access->base);
2075 else
2076 TREE_NO_WARNING (repl) = 1;
2078 if (dump_file)
2080 if (access->grp_to_be_debug_replaced)
2082 fprintf (dump_file, "Created a debug-only replacement for ");
2083 print_generic_expr (dump_file, access->base, 0);
2084 fprintf (dump_file, " offset: %u, size: %u\n",
2085 (unsigned) access->offset, (unsigned) access->size);
2087 else
2089 fprintf (dump_file, "Created a replacement for ");
2090 print_generic_expr (dump_file, access->base, 0);
2091 fprintf (dump_file, " offset: %u, size: %u: ",
2092 (unsigned) access->offset, (unsigned) access->size);
2093 print_generic_expr (dump_file, repl, 0);
2094 fprintf (dump_file, "\n");
2097 sra_stats.replacements++;
2099 return repl;
2102 /* Return ACCESS scalar replacement, create it if it does not exist yet. */
2104 static inline tree
2105 get_access_replacement (struct access *access)
2107 gcc_checking_assert (access->replacement_decl);
2108 return access->replacement_decl;
2112 /* Build a subtree of accesses rooted in *ACCESS, and move the pointer in the
2113 linked list along the way. Stop when *ACCESS is NULL or the access pointed
2114 to it is not "within" the root. Return false iff some accesses partially
2115 overlap. */
2117 static bool
2118 build_access_subtree (struct access **access)
2120 struct access *root = *access, *last_child = NULL;
2121 HOST_WIDE_INT limit = root->offset + root->size;
2123 *access = (*access)->next_grp;
2124 while (*access && (*access)->offset + (*access)->size <= limit)
2126 if (!last_child)
2127 root->first_child = *access;
2128 else
2129 last_child->next_sibling = *access;
2130 last_child = *access;
2132 if (!build_access_subtree (access))
2133 return false;
2136 if (*access && (*access)->offset < limit)
2137 return false;
2139 return true;
2142 /* Build a tree of access representatives, ACCESS is the pointer to the first
2143 one, others are linked in a list by the next_grp field. Return false iff
2144 some accesses partially overlap. */
2146 static bool
2147 build_access_trees (struct access *access)
2149 while (access)
2151 struct access *root = access;
2153 if (!build_access_subtree (&access))
2154 return false;
2155 root->next_grp = access;
2157 return true;
2160 /* Return true if expr contains some ARRAY_REFs into a variable bounded
2161 array. */
2163 static bool
2164 expr_with_var_bounded_array_refs_p (tree expr)
2166 while (handled_component_p (expr))
2168 if (TREE_CODE (expr) == ARRAY_REF
2169 && !tree_fits_shwi_p (array_ref_low_bound (expr)))
2170 return true;
2171 expr = TREE_OPERAND (expr, 0);
2173 return false;
2176 /* Analyze the subtree of accesses rooted in ROOT, scheduling replacements when
2177 both seeming beneficial and when ALLOW_REPLACEMENTS allows it. Also set all
2178 sorts of access flags appropriately along the way, notably always set
2179 grp_read and grp_assign_read according to MARK_READ and grp_write when
2180 MARK_WRITE is true.
2182 Creating a replacement for a scalar access is considered beneficial if its
2183 grp_hint is set (this means we are either attempting total scalarization or
2184 there is more than one direct read access) or according to the following
2185 table:
2187 Access written to through a scalar type (once or more times)
2189 | Written to in an assignment statement
2191 | | Access read as scalar _once_
2192 | | |
2193 | | | Read in an assignment statement
2194 | | | |
2195 | | | | Scalarize Comment
2196 -----------------------------------------------------------------------------
2197 0 0 0 0 No access for the scalar
2198 0 0 0 1 No access for the scalar
2199 0 0 1 0 No Single read - won't help
2200 0 0 1 1 No The same case
2201 0 1 0 0 No access for the scalar
2202 0 1 0 1 No access for the scalar
2203 0 1 1 0 Yes s = *g; return s.i;
2204 0 1 1 1 Yes The same case as above
2205 1 0 0 0 No Won't help
2206 1 0 0 1 Yes s.i = 1; *g = s;
2207 1 0 1 0 Yes s.i = 5; g = s.i;
2208 1 0 1 1 Yes The same case as above
2209 1 1 0 0 No Won't help.
2210 1 1 0 1 Yes s.i = 1; *g = s;
2211 1 1 1 0 Yes s = *g; return s.i;
2212 1 1 1 1 Yes Any of the above yeses */
2214 static bool
2215 analyze_access_subtree (struct access *root, struct access *parent,
2216 bool allow_replacements)
2218 struct access *child;
2219 HOST_WIDE_INT limit = root->offset + root->size;
2220 HOST_WIDE_INT covered_to = root->offset;
2221 bool scalar = is_gimple_reg_type (root->type);
2222 bool hole = false, sth_created = false;
2224 if (parent)
2226 if (parent->grp_read)
2227 root->grp_read = 1;
2228 if (parent->grp_assignment_read)
2229 root->grp_assignment_read = 1;
2230 if (parent->grp_write)
2231 root->grp_write = 1;
2232 if (parent->grp_assignment_write)
2233 root->grp_assignment_write = 1;
2234 if (parent->grp_total_scalarization)
2235 root->grp_total_scalarization = 1;
2238 if (root->grp_unscalarizable_region)
2239 allow_replacements = false;
2241 if (allow_replacements && expr_with_var_bounded_array_refs_p (root->expr))
2242 allow_replacements = false;
2244 for (child = root->first_child; child; child = child->next_sibling)
2246 hole |= covered_to < child->offset;
2247 sth_created |= analyze_access_subtree (child, root,
2248 allow_replacements && !scalar);
2250 root->grp_unscalarized_data |= child->grp_unscalarized_data;
2251 root->grp_total_scalarization &= child->grp_total_scalarization;
2252 if (child->grp_covered)
2253 covered_to += child->size;
2254 else
2255 hole = true;
2258 if (allow_replacements && scalar && !root->first_child
2259 && (root->grp_hint
2260 || ((root->grp_scalar_read || root->grp_assignment_read)
2261 && (root->grp_scalar_write || root->grp_assignment_write))))
2263 /* Always create access replacements that cover the whole access.
2264 For integral types this means the precision has to match.
2265 Avoid assumptions based on the integral type kind, too. */
2266 if (INTEGRAL_TYPE_P (root->type)
2267 && (TREE_CODE (root->type) != INTEGER_TYPE
2268 || TYPE_PRECISION (root->type) != root->size)
2269 /* But leave bitfield accesses alone. */
2270 && (TREE_CODE (root->expr) != COMPONENT_REF
2271 || !DECL_BIT_FIELD (TREE_OPERAND (root->expr, 1))))
2273 tree rt = root->type;
2274 gcc_assert ((root->offset % BITS_PER_UNIT) == 0
2275 && (root->size % BITS_PER_UNIT) == 0);
2276 root->type = build_nonstandard_integer_type (root->size,
2277 TYPE_UNSIGNED (rt));
2278 root->expr = build_ref_for_offset (UNKNOWN_LOCATION,
2279 root->base, root->offset,
2280 root->type, NULL, false);
2282 if (dump_file && (dump_flags & TDF_DETAILS))
2284 fprintf (dump_file, "Changing the type of a replacement for ");
2285 print_generic_expr (dump_file, root->base, 0);
2286 fprintf (dump_file, " offset: %u, size: %u ",
2287 (unsigned) root->offset, (unsigned) root->size);
2288 fprintf (dump_file, " to an integer.\n");
2292 root->grp_to_be_replaced = 1;
2293 root->replacement_decl = create_access_replacement (root);
2294 sth_created = true;
2295 hole = false;
2297 else
2299 if (allow_replacements
2300 && scalar && !root->first_child
2301 && (root->grp_scalar_write || root->grp_assignment_write)
2302 && !bitmap_bit_p (cannot_scalarize_away_bitmap,
2303 DECL_UID (root->base)))
2305 gcc_checking_assert (!root->grp_scalar_read
2306 && !root->grp_assignment_read);
2307 sth_created = true;
2308 if (MAY_HAVE_DEBUG_STMTS)
2310 root->grp_to_be_debug_replaced = 1;
2311 root->replacement_decl = create_access_replacement (root);
2315 if (covered_to < limit)
2316 hole = true;
2317 if (scalar)
2318 root->grp_total_scalarization = 0;
2321 if (!hole || root->grp_total_scalarization)
2322 root->grp_covered = 1;
2323 else if (root->grp_write || TREE_CODE (root->base) == PARM_DECL)
2324 root->grp_unscalarized_data = 1; /* not covered and written to */
2325 return sth_created;
2328 /* Analyze all access trees linked by next_grp by the means of
2329 analyze_access_subtree. */
2330 static bool
2331 analyze_access_trees (struct access *access)
2333 bool ret = false;
2335 while (access)
2337 if (analyze_access_subtree (access, NULL, true))
2338 ret = true;
2339 access = access->next_grp;
2342 return ret;
2345 /* Return true iff a potential new child of LACC at offset OFFSET and with size
2346 SIZE would conflict with an already existing one. If exactly such a child
2347 already exists in LACC, store a pointer to it in EXACT_MATCH. */
2349 static bool
2350 child_would_conflict_in_lacc (struct access *lacc, HOST_WIDE_INT norm_offset,
2351 HOST_WIDE_INT size, struct access **exact_match)
2353 struct access *child;
2355 for (child = lacc->first_child; child; child = child->next_sibling)
2357 if (child->offset == norm_offset && child->size == size)
2359 *exact_match = child;
2360 return true;
2363 if (child->offset < norm_offset + size
2364 && child->offset + child->size > norm_offset)
2365 return true;
2368 return false;
2371 /* Create a new child access of PARENT, with all properties just like MODEL
2372 except for its offset and with its grp_write false and grp_read true.
2373 Return the new access or NULL if it cannot be created. Note that this access
2374 is created long after all splicing and sorting, it's not located in any
2375 access vector and is automatically a representative of its group. */
2377 static struct access *
2378 create_artificial_child_access (struct access *parent, struct access *model,
2379 HOST_WIDE_INT new_offset)
2381 struct access *access;
2382 struct access **child;
2383 tree expr = parent->base;
2385 gcc_assert (!model->grp_unscalarizable_region);
2387 access = (struct access *) pool_alloc (access_pool);
2388 memset (access, 0, sizeof (struct access));
2389 if (!build_user_friendly_ref_for_offset (&expr, TREE_TYPE (expr), new_offset,
2390 model->type))
2392 access->grp_no_warning = true;
2393 expr = build_ref_for_model (EXPR_LOCATION (parent->base), parent->base,
2394 new_offset, model, NULL, false);
2397 access->base = parent->base;
2398 access->expr = expr;
2399 access->offset = new_offset;
2400 access->size = model->size;
2401 access->type = model->type;
2402 access->grp_write = true;
2403 access->grp_read = false;
2405 child = &parent->first_child;
2406 while (*child && (*child)->offset < new_offset)
2407 child = &(*child)->next_sibling;
2409 access->next_sibling = *child;
2410 *child = access;
2412 return access;
2416 /* Propagate all subaccesses of RACC across an assignment link to LACC. Return
2417 true if any new subaccess was created. Additionally, if RACC is a scalar
2418 access but LACC is not, change the type of the latter, if possible. */
2420 static bool
2421 propagate_subaccesses_across_link (struct access *lacc, struct access *racc)
2423 struct access *rchild;
2424 HOST_WIDE_INT norm_delta = lacc->offset - racc->offset;
2425 bool ret = false;
2427 if (is_gimple_reg_type (lacc->type)
2428 || lacc->grp_unscalarizable_region
2429 || racc->grp_unscalarizable_region)
2430 return false;
2432 if (is_gimple_reg_type (racc->type))
2434 if (!lacc->first_child && !racc->first_child)
2436 tree t = lacc->base;
2438 lacc->type = racc->type;
2439 if (build_user_friendly_ref_for_offset (&t, TREE_TYPE (t),
2440 lacc->offset, racc->type))
2441 lacc->expr = t;
2442 else
2444 lacc->expr = build_ref_for_model (EXPR_LOCATION (lacc->base),
2445 lacc->base, lacc->offset,
2446 racc, NULL, false);
2447 lacc->grp_no_warning = true;
2450 return false;
2453 for (rchild = racc->first_child; rchild; rchild = rchild->next_sibling)
2455 struct access *new_acc = NULL;
2456 HOST_WIDE_INT norm_offset = rchild->offset + norm_delta;
2458 if (rchild->grp_unscalarizable_region)
2459 continue;
2461 if (child_would_conflict_in_lacc (lacc, norm_offset, rchild->size,
2462 &new_acc))
2464 if (new_acc)
2466 rchild->grp_hint = 1;
2467 new_acc->grp_hint |= new_acc->grp_read;
2468 if (rchild->first_child)
2469 ret |= propagate_subaccesses_across_link (new_acc, rchild);
2471 continue;
2474 rchild->grp_hint = 1;
2475 new_acc = create_artificial_child_access (lacc, rchild, norm_offset);
2476 if (new_acc)
2478 ret = true;
2479 if (racc->first_child)
2480 propagate_subaccesses_across_link (new_acc, rchild);
2484 return ret;
2487 /* Propagate all subaccesses across assignment links. */
2489 static void
2490 propagate_all_subaccesses (void)
2492 while (work_queue_head)
2494 struct access *racc = pop_access_from_work_queue ();
2495 struct assign_link *link;
2497 gcc_assert (racc->first_link);
2499 for (link = racc->first_link; link; link = link->next)
2501 struct access *lacc = link->lacc;
2503 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
2504 continue;
2505 lacc = lacc->group_representative;
2506 if (propagate_subaccesses_across_link (lacc, racc)
2507 && lacc->first_link)
2508 add_access_to_work_queue (lacc);
2513 /* Go through all accesses collected throughout the (intraprocedural) analysis
2514 stage, exclude overlapping ones, identify representatives and build trees
2515 out of them, making decisions about scalarization on the way. Return true
2516 iff there are any to-be-scalarized variables after this stage. */
2518 static bool
2519 analyze_all_variable_accesses (void)
2521 int res = 0;
2522 bitmap tmp = BITMAP_ALLOC (NULL);
2523 bitmap_iterator bi;
2524 unsigned i;
2525 unsigned max_scalarization_size
2526 = (optimize_function_for_size_p (cfun)
2527 ? PARAM_VALUE (PARAM_SRA_MAX_SCALARIZATION_SIZE_SIZE)
2528 : PARAM_VALUE (PARAM_SRA_MAX_SCALARIZATION_SIZE_SPEED))
2529 * BITS_PER_UNIT;
2531 EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
2532 if (bitmap_bit_p (should_scalarize_away_bitmap, i)
2533 && !bitmap_bit_p (cannot_scalarize_away_bitmap, i))
2535 tree var = candidate (i);
2537 if (TREE_CODE (var) == VAR_DECL
2538 && type_consists_of_records_p (TREE_TYPE (var)))
2540 if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (var)))
2541 <= max_scalarization_size)
2543 completely_scalarize_var (var);
2544 if (dump_file && (dump_flags & TDF_DETAILS))
2546 fprintf (dump_file, "Will attempt to totally scalarize ");
2547 print_generic_expr (dump_file, var, 0);
2548 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
2551 else if (dump_file && (dump_flags & TDF_DETAILS))
2553 fprintf (dump_file, "Too big to totally scalarize: ");
2554 print_generic_expr (dump_file, var, 0);
2555 fprintf (dump_file, " (UID: %u)\n", DECL_UID (var));
2560 bitmap_copy (tmp, candidate_bitmap);
2561 EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
2563 tree var = candidate (i);
2564 struct access *access;
2566 access = sort_and_splice_var_accesses (var);
2567 if (!access || !build_access_trees (access))
2568 disqualify_candidate (var,
2569 "No or inhibitingly overlapping accesses.");
2572 propagate_all_subaccesses ();
2574 bitmap_copy (tmp, candidate_bitmap);
2575 EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
2577 tree var = candidate (i);
2578 struct access *access = get_first_repr_for_decl (var);
2580 if (analyze_access_trees (access))
2582 res++;
2583 if (dump_file && (dump_flags & TDF_DETAILS))
2585 fprintf (dump_file, "\nAccess trees for ");
2586 print_generic_expr (dump_file, var, 0);
2587 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
2588 dump_access_tree (dump_file, access);
2589 fprintf (dump_file, "\n");
2592 else
2593 disqualify_candidate (var, "No scalar replacements to be created.");
2596 BITMAP_FREE (tmp);
2598 if (res)
2600 statistics_counter_event (cfun, "Scalarized aggregates", res);
2601 return true;
2603 else
2604 return false;
2607 /* Generate statements copying scalar replacements of accesses within a subtree
2608 into or out of AGG. ACCESS, all its children, siblings and their children
2609 are to be processed. AGG is an aggregate type expression (can be a
2610 declaration but does not have to be, it can for example also be a mem_ref or
2611 a series of handled components). TOP_OFFSET is the offset of the processed
2612 subtree which has to be subtracted from offsets of individual accesses to
2613 get corresponding offsets for AGG. If CHUNK_SIZE is non-null, copy only
2614 replacements in the interval <start_offset, start_offset + chunk_size>,
2615 otherwise copy all. GSI is a statement iterator used to place the new
2616 statements. WRITE should be true when the statements should write from AGG
2617 to the replacement and false if vice versa. if INSERT_AFTER is true, new
2618 statements will be added after the current statement in GSI, they will be
2619 added before the statement otherwise. */
2621 static void
2622 generate_subtree_copies (struct access *access, tree agg,
2623 HOST_WIDE_INT top_offset,
2624 HOST_WIDE_INT start_offset, HOST_WIDE_INT chunk_size,
2625 gimple_stmt_iterator *gsi, bool write,
2626 bool insert_after, location_t loc)
2630 if (chunk_size && access->offset >= start_offset + chunk_size)
2631 return;
2633 if (access->grp_to_be_replaced
2634 && (chunk_size == 0
2635 || access->offset + access->size > start_offset))
2637 tree expr, repl = get_access_replacement (access);
2638 gassign *stmt;
2640 expr = build_ref_for_model (loc, agg, access->offset - top_offset,
2641 access, gsi, insert_after);
2643 if (write)
2645 if (access->grp_partial_lhs)
2646 expr = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
2647 !insert_after,
2648 insert_after ? GSI_NEW_STMT
2649 : GSI_SAME_STMT);
2650 stmt = gimple_build_assign (repl, expr);
2652 else
2654 TREE_NO_WARNING (repl) = 1;
2655 if (access->grp_partial_lhs)
2656 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
2657 !insert_after,
2658 insert_after ? GSI_NEW_STMT
2659 : GSI_SAME_STMT);
2660 stmt = gimple_build_assign (expr, repl);
2662 gimple_set_location (stmt, loc);
2664 if (insert_after)
2665 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2666 else
2667 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2668 update_stmt (stmt);
2669 sra_stats.subtree_copies++;
2671 else if (write
2672 && access->grp_to_be_debug_replaced
2673 && (chunk_size == 0
2674 || access->offset + access->size > start_offset))
2676 gdebug *ds;
2677 tree drhs = build_debug_ref_for_model (loc, agg,
2678 access->offset - top_offset,
2679 access);
2680 ds = gimple_build_debug_bind (get_access_replacement (access),
2681 drhs, gsi_stmt (*gsi));
2682 if (insert_after)
2683 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
2684 else
2685 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
2688 if (access->first_child)
2689 generate_subtree_copies (access->first_child, agg, top_offset,
2690 start_offset, chunk_size, gsi,
2691 write, insert_after, loc);
2693 access = access->next_sibling;
2695 while (access);
2698 /* Assign zero to all scalar replacements in an access subtree. ACCESS is the
2699 the root of the subtree to be processed. GSI is the statement iterator used
2700 for inserting statements which are added after the current statement if
2701 INSERT_AFTER is true or before it otherwise. */
2703 static void
2704 init_subtree_with_zero (struct access *access, gimple_stmt_iterator *gsi,
2705 bool insert_after, location_t loc)
2708 struct access *child;
2710 if (access->grp_to_be_replaced)
2712 gassign *stmt;
2714 stmt = gimple_build_assign (get_access_replacement (access),
2715 build_zero_cst (access->type));
2716 if (insert_after)
2717 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2718 else
2719 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2720 update_stmt (stmt);
2721 gimple_set_location (stmt, loc);
2723 else if (access->grp_to_be_debug_replaced)
2725 gdebug *ds
2726 = gimple_build_debug_bind (get_access_replacement (access),
2727 build_zero_cst (access->type),
2728 gsi_stmt (*gsi));
2729 if (insert_after)
2730 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
2731 else
2732 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
2735 for (child = access->first_child; child; child = child->next_sibling)
2736 init_subtree_with_zero (child, gsi, insert_after, loc);
2739 /* Clobber all scalar replacements in an access subtree. ACCESS is the the
2740 root of the subtree to be processed. GSI is the statement iterator used
2741 for inserting statements which are added after the current statement if
2742 INSERT_AFTER is true or before it otherwise. */
2744 static void
2745 clobber_subtree (struct access *access, gimple_stmt_iterator *gsi,
2746 bool insert_after, location_t loc)
2749 struct access *child;
2751 if (access->grp_to_be_replaced)
2753 tree rep = get_access_replacement (access);
2754 tree clobber = build_constructor (access->type, NULL);
2755 TREE_THIS_VOLATILE (clobber) = 1;
2756 gimple stmt = gimple_build_assign (rep, clobber);
2758 if (insert_after)
2759 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2760 else
2761 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2762 update_stmt (stmt);
2763 gimple_set_location (stmt, loc);
2766 for (child = access->first_child; child; child = child->next_sibling)
2767 clobber_subtree (child, gsi, insert_after, loc);
2770 /* Search for an access representative for the given expression EXPR and
2771 return it or NULL if it cannot be found. */
2773 static struct access *
2774 get_access_for_expr (tree expr)
2776 HOST_WIDE_INT offset, size, max_size;
2777 tree base;
2779 /* FIXME: This should not be necessary but Ada produces V_C_Es with a type of
2780 a different size than the size of its argument and we need the latter
2781 one. */
2782 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
2783 expr = TREE_OPERAND (expr, 0);
2785 base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
2786 if (max_size == -1 || !DECL_P (base))
2787 return NULL;
2789 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
2790 return NULL;
2792 return get_var_base_offset_size_access (base, offset, max_size);
2795 /* Replace the expression EXPR with a scalar replacement if there is one and
2796 generate other statements to do type conversion or subtree copying if
2797 necessary. GSI is used to place newly created statements, WRITE is true if
2798 the expression is being written to (it is on a LHS of a statement or output
2799 in an assembly statement). */
2801 static bool
2802 sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
2804 location_t loc;
2805 struct access *access;
2806 tree type, bfr, orig_expr;
2808 if (TREE_CODE (*expr) == BIT_FIELD_REF)
2810 bfr = *expr;
2811 expr = &TREE_OPERAND (*expr, 0);
2813 else
2814 bfr = NULL_TREE;
2816 if (TREE_CODE (*expr) == REALPART_EXPR || TREE_CODE (*expr) == IMAGPART_EXPR)
2817 expr = &TREE_OPERAND (*expr, 0);
2818 access = get_access_for_expr (*expr);
2819 if (!access)
2820 return false;
2821 type = TREE_TYPE (*expr);
2822 orig_expr = *expr;
2824 loc = gimple_location (gsi_stmt (*gsi));
2825 gimple_stmt_iterator alt_gsi = gsi_none ();
2826 if (write && stmt_ends_bb_p (gsi_stmt (*gsi)))
2828 alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi)));
2829 gsi = &alt_gsi;
2832 if (access->grp_to_be_replaced)
2834 tree repl = get_access_replacement (access);
2835 /* If we replace a non-register typed access simply use the original
2836 access expression to extract the scalar component afterwards.
2837 This happens if scalarizing a function return value or parameter
2838 like in gcc.c-torture/execute/20041124-1.c, 20050316-1.c and
2839 gcc.c-torture/compile/20011217-1.c.
2841 We also want to use this when accessing a complex or vector which can
2842 be accessed as a different type too, potentially creating a need for
2843 type conversion (see PR42196) and when scalarized unions are involved
2844 in assembler statements (see PR42398). */
2845 if (!useless_type_conversion_p (type, access->type))
2847 tree ref;
2849 ref = build_ref_for_model (loc, orig_expr, 0, access, gsi, false);
2851 if (write)
2853 gassign *stmt;
2855 if (access->grp_partial_lhs)
2856 ref = force_gimple_operand_gsi (gsi, ref, true, NULL_TREE,
2857 false, GSI_NEW_STMT);
2858 stmt = gimple_build_assign (repl, ref);
2859 gimple_set_location (stmt, loc);
2860 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2862 else
2864 gassign *stmt;
2866 if (access->grp_partial_lhs)
2867 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
2868 true, GSI_SAME_STMT);
2869 stmt = gimple_build_assign (ref, repl);
2870 gimple_set_location (stmt, loc);
2871 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2874 else
2875 *expr = repl;
2876 sra_stats.exprs++;
2878 else if (write && access->grp_to_be_debug_replaced)
2880 gdebug *ds = gimple_build_debug_bind (get_access_replacement (access),
2881 NULL_TREE,
2882 gsi_stmt (*gsi));
2883 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
2886 if (access->first_child)
2888 HOST_WIDE_INT start_offset, chunk_size;
2889 if (bfr
2890 && tree_fits_uhwi_p (TREE_OPERAND (bfr, 1))
2891 && tree_fits_uhwi_p (TREE_OPERAND (bfr, 2)))
2893 chunk_size = tree_to_uhwi (TREE_OPERAND (bfr, 1));
2894 start_offset = access->offset
2895 + tree_to_uhwi (TREE_OPERAND (bfr, 2));
2897 else
2898 start_offset = chunk_size = 0;
2900 generate_subtree_copies (access->first_child, orig_expr, access->offset,
2901 start_offset, chunk_size, gsi, write, write,
2902 loc);
2904 return true;
2907 /* Where scalar replacements of the RHS have been written to when a replacement
2908 of a LHS of an assigments cannot be direclty loaded from a replacement of
2909 the RHS. */
2910 enum unscalarized_data_handling { SRA_UDH_NONE, /* Nothing done so far. */
2911 SRA_UDH_RIGHT, /* Data flushed to the RHS. */
2912 SRA_UDH_LEFT }; /* Data flushed to the LHS. */
2914 struct subreplacement_assignment_data
2916 /* Offset of the access representing the lhs of the assignment. */
2917 HOST_WIDE_INT left_offset;
2919 /* LHS and RHS of the original assignment. */
2920 tree assignment_lhs, assignment_rhs;
2922 /* Access representing the rhs of the whole assignment. */
2923 struct access *top_racc;
2925 /* Stmt iterator used for statement insertions after the original assignment.
2926 It points to the main GSI used to traverse a BB during function body
2927 modification. */
2928 gimple_stmt_iterator *new_gsi;
2930 /* Stmt iterator used for statement insertions before the original
2931 assignment. Keeps on pointing to the original statement. */
2932 gimple_stmt_iterator old_gsi;
2934 /* Location of the assignment. */
2935 location_t loc;
2937 /* Keeps the information whether we have needed to refresh replacements of
2938 the LHS and from which side of the assignments this takes place. */
2939 enum unscalarized_data_handling refreshed;
2942 /* Store all replacements in the access tree rooted in TOP_RACC either to their
2943 base aggregate if there are unscalarized data or directly to LHS of the
2944 statement that is pointed to by GSI otherwise. */
2946 static void
2947 handle_unscalarized_data_in_subtree (struct subreplacement_assignment_data *sad)
2949 tree src;
2950 if (sad->top_racc->grp_unscalarized_data)
2952 src = sad->assignment_rhs;
2953 sad->refreshed = SRA_UDH_RIGHT;
2955 else
2957 src = sad->assignment_lhs;
2958 sad->refreshed = SRA_UDH_LEFT;
2960 generate_subtree_copies (sad->top_racc->first_child, src,
2961 sad->top_racc->offset, 0, 0,
2962 &sad->old_gsi, false, false, sad->loc);
2965 /* Try to generate statements to load all sub-replacements in an access subtree
2966 formed by children of LACC from scalar replacements in the SAD->top_racc
2967 subtree. If that is not possible, refresh the SAD->top_racc base aggregate
2968 and load the accesses from it. */
2970 static void
2971 load_assign_lhs_subreplacements (struct access *lacc,
2972 struct subreplacement_assignment_data *sad)
2974 for (lacc = lacc->first_child; lacc; lacc = lacc->next_sibling)
2976 HOST_WIDE_INT offset;
2977 offset = lacc->offset - sad->left_offset + sad->top_racc->offset;
2979 if (lacc->grp_to_be_replaced)
2981 struct access *racc;
2982 gassign *stmt;
2983 tree rhs;
2985 racc = find_access_in_subtree (sad->top_racc, offset, lacc->size);
2986 if (racc && racc->grp_to_be_replaced)
2988 rhs = get_access_replacement (racc);
2989 if (!useless_type_conversion_p (lacc->type, racc->type))
2990 rhs = fold_build1_loc (sad->loc, VIEW_CONVERT_EXPR,
2991 lacc->type, rhs);
2993 if (racc->grp_partial_lhs && lacc->grp_partial_lhs)
2994 rhs = force_gimple_operand_gsi (&sad->old_gsi, rhs, true,
2995 NULL_TREE, true, GSI_SAME_STMT);
2997 else
2999 /* No suitable access on the right hand side, need to load from
3000 the aggregate. See if we have to update it first... */
3001 if (sad->refreshed == SRA_UDH_NONE)
3002 handle_unscalarized_data_in_subtree (sad);
3004 if (sad->refreshed == SRA_UDH_LEFT)
3005 rhs = build_ref_for_model (sad->loc, sad->assignment_lhs,
3006 lacc->offset - sad->left_offset,
3007 lacc, sad->new_gsi, true);
3008 else
3009 rhs = build_ref_for_model (sad->loc, sad->assignment_rhs,
3010 lacc->offset - sad->left_offset,
3011 lacc, sad->new_gsi, true);
3012 if (lacc->grp_partial_lhs)
3013 rhs = force_gimple_operand_gsi (sad->new_gsi,
3014 rhs, true, NULL_TREE,
3015 false, GSI_NEW_STMT);
3018 stmt = gimple_build_assign (get_access_replacement (lacc), rhs);
3019 gsi_insert_after (sad->new_gsi, stmt, GSI_NEW_STMT);
3020 gimple_set_location (stmt, sad->loc);
3021 update_stmt (stmt);
3022 sra_stats.subreplacements++;
3024 else
3026 if (sad->refreshed == SRA_UDH_NONE
3027 && lacc->grp_read && !lacc->grp_covered)
3028 handle_unscalarized_data_in_subtree (sad);
3030 if (lacc && lacc->grp_to_be_debug_replaced)
3032 gdebug *ds;
3033 tree drhs;
3034 struct access *racc = find_access_in_subtree (sad->top_racc,
3035 offset,
3036 lacc->size);
3038 if (racc && racc->grp_to_be_replaced)
3040 if (racc->grp_write)
3041 drhs = get_access_replacement (racc);
3042 else
3043 drhs = NULL;
3045 else if (sad->refreshed == SRA_UDH_LEFT)
3046 drhs = build_debug_ref_for_model (sad->loc, lacc->base,
3047 lacc->offset, lacc);
3048 else if (sad->refreshed == SRA_UDH_RIGHT)
3049 drhs = build_debug_ref_for_model (sad->loc, sad->top_racc->base,
3050 offset, lacc);
3051 else
3052 drhs = NULL_TREE;
3053 if (drhs
3054 && !useless_type_conversion_p (lacc->type, TREE_TYPE (drhs)))
3055 drhs = fold_build1_loc (sad->loc, VIEW_CONVERT_EXPR,
3056 lacc->type, drhs);
3057 ds = gimple_build_debug_bind (get_access_replacement (lacc),
3058 drhs, gsi_stmt (sad->old_gsi));
3059 gsi_insert_after (sad->new_gsi, ds, GSI_NEW_STMT);
3063 if (lacc->first_child)
3064 load_assign_lhs_subreplacements (lacc, sad);
3068 /* Result code for SRA assignment modification. */
3069 enum assignment_mod_result { SRA_AM_NONE, /* nothing done for the stmt */
3070 SRA_AM_MODIFIED, /* stmt changed but not
3071 removed */
3072 SRA_AM_REMOVED }; /* stmt eliminated */
3074 /* Modify assignments with a CONSTRUCTOR on their RHS. STMT contains a pointer
3075 to the assignment and GSI is the statement iterator pointing at it. Returns
3076 the same values as sra_modify_assign. */
3078 static enum assignment_mod_result
3079 sra_modify_constructor_assign (gimple stmt, gimple_stmt_iterator *gsi)
3081 tree lhs = gimple_assign_lhs (stmt);
3082 struct access *acc = get_access_for_expr (lhs);
3083 if (!acc)
3084 return SRA_AM_NONE;
3085 location_t loc = gimple_location (stmt);
3087 if (gimple_clobber_p (stmt))
3089 /* Clobber the replacement variable. */
3090 clobber_subtree (acc, gsi, !acc->grp_covered, loc);
3091 /* Remove clobbers of fully scalarized variables, they are dead. */
3092 if (acc->grp_covered)
3094 unlink_stmt_vdef (stmt);
3095 gsi_remove (gsi, true);
3096 release_defs (stmt);
3097 return SRA_AM_REMOVED;
3099 else
3100 return SRA_AM_MODIFIED;
3103 if (vec_safe_length (CONSTRUCTOR_ELTS (gimple_assign_rhs1 (stmt))) > 0)
3105 /* I have never seen this code path trigger but if it can happen the
3106 following should handle it gracefully. */
3107 if (access_has_children_p (acc))
3108 generate_subtree_copies (acc->first_child, lhs, acc->offset, 0, 0, gsi,
3109 true, true, loc);
3110 return SRA_AM_MODIFIED;
3113 if (acc->grp_covered)
3115 init_subtree_with_zero (acc, gsi, false, loc);
3116 unlink_stmt_vdef (stmt);
3117 gsi_remove (gsi, true);
3118 release_defs (stmt);
3119 return SRA_AM_REMOVED;
3121 else
3123 init_subtree_with_zero (acc, gsi, true, loc);
3124 return SRA_AM_MODIFIED;
3128 /* Create and return a new suitable default definition SSA_NAME for RACC which
3129 is an access describing an uninitialized part of an aggregate that is being
3130 loaded. */
3132 static tree
3133 get_repl_default_def_ssa_name (struct access *racc)
3135 gcc_checking_assert (!racc->grp_to_be_replaced
3136 && !racc->grp_to_be_debug_replaced);
3137 if (!racc->replacement_decl)
3138 racc->replacement_decl = create_access_replacement (racc);
3139 return get_or_create_ssa_default_def (cfun, racc->replacement_decl);
3142 /* Return true if REF has an VIEW_CONVERT_EXPR or a COMPONENT_REF with a
3143 bit-field field declaration somewhere in it. */
3145 static inline bool
3146 contains_vce_or_bfcref_p (const_tree ref)
3148 while (handled_component_p (ref))
3150 if (TREE_CODE (ref) == VIEW_CONVERT_EXPR
3151 || (TREE_CODE (ref) == COMPONENT_REF
3152 && DECL_BIT_FIELD (TREE_OPERAND (ref, 1))))
3153 return true;
3154 ref = TREE_OPERAND (ref, 0);
3157 return false;
3160 /* Examine both sides of the assignment statement pointed to by STMT, replace
3161 them with a scalare replacement if there is one and generate copying of
3162 replacements if scalarized aggregates have been used in the assignment. GSI
3163 is used to hold generated statements for type conversions and subtree
3164 copying. */
3166 static enum assignment_mod_result
3167 sra_modify_assign (gimple stmt, gimple_stmt_iterator *gsi)
3169 struct access *lacc, *racc;
3170 tree lhs, rhs;
3171 bool modify_this_stmt = false;
3172 bool force_gimple_rhs = false;
3173 location_t loc;
3174 gimple_stmt_iterator orig_gsi = *gsi;
3176 if (!gimple_assign_single_p (stmt))
3177 return SRA_AM_NONE;
3178 lhs = gimple_assign_lhs (stmt);
3179 rhs = gimple_assign_rhs1 (stmt);
3181 if (TREE_CODE (rhs) == CONSTRUCTOR)
3182 return sra_modify_constructor_assign (stmt, gsi);
3184 if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (lhs) == REALPART_EXPR
3185 || TREE_CODE (rhs) == IMAGPART_EXPR || TREE_CODE (lhs) == IMAGPART_EXPR
3186 || TREE_CODE (rhs) == BIT_FIELD_REF || TREE_CODE (lhs) == BIT_FIELD_REF)
3188 modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (stmt),
3189 gsi, false);
3190 modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (stmt),
3191 gsi, true);
3192 return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
3195 lacc = get_access_for_expr (lhs);
3196 racc = get_access_for_expr (rhs);
3197 if (!lacc && !racc)
3198 return SRA_AM_NONE;
3200 loc = gimple_location (stmt);
3201 if (lacc && lacc->grp_to_be_replaced)
3203 lhs = get_access_replacement (lacc);
3204 gimple_assign_set_lhs (stmt, lhs);
3205 modify_this_stmt = true;
3206 if (lacc->grp_partial_lhs)
3207 force_gimple_rhs = true;
3208 sra_stats.exprs++;
3211 if (racc && racc->grp_to_be_replaced)
3213 rhs = get_access_replacement (racc);
3214 modify_this_stmt = true;
3215 if (racc->grp_partial_lhs)
3216 force_gimple_rhs = true;
3217 sra_stats.exprs++;
3219 else if (racc
3220 && !racc->grp_unscalarized_data
3221 && TREE_CODE (lhs) == SSA_NAME
3222 && !access_has_replacements_p (racc))
3224 rhs = get_repl_default_def_ssa_name (racc);
3225 modify_this_stmt = true;
3226 sra_stats.exprs++;
3229 if (modify_this_stmt)
3231 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
3233 /* If we can avoid creating a VIEW_CONVERT_EXPR do so.
3234 ??? This should move to fold_stmt which we simply should
3235 call after building a VIEW_CONVERT_EXPR here. */
3236 if (AGGREGATE_TYPE_P (TREE_TYPE (lhs))
3237 && !contains_bitfld_component_ref_p (lhs))
3239 lhs = build_ref_for_model (loc, lhs, 0, racc, gsi, false);
3240 gimple_assign_set_lhs (stmt, lhs);
3242 else if (AGGREGATE_TYPE_P (TREE_TYPE (rhs))
3243 && !contains_vce_or_bfcref_p (rhs))
3244 rhs = build_ref_for_model (loc, rhs, 0, lacc, gsi, false);
3246 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
3248 rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
3249 rhs);
3250 if (is_gimple_reg_type (TREE_TYPE (lhs))
3251 && TREE_CODE (lhs) != SSA_NAME)
3252 force_gimple_rhs = true;
3257 if (lacc && lacc->grp_to_be_debug_replaced)
3259 tree dlhs = get_access_replacement (lacc);
3260 tree drhs = unshare_expr (rhs);
3261 if (!useless_type_conversion_p (TREE_TYPE (dlhs), TREE_TYPE (drhs)))
3263 if (AGGREGATE_TYPE_P (TREE_TYPE (drhs))
3264 && !contains_vce_or_bfcref_p (drhs))
3265 drhs = build_debug_ref_for_model (loc, drhs, 0, lacc);
3266 if (drhs
3267 && !useless_type_conversion_p (TREE_TYPE (dlhs),
3268 TREE_TYPE (drhs)))
3269 drhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
3270 TREE_TYPE (dlhs), drhs);
3272 gdebug *ds = gimple_build_debug_bind (dlhs, drhs, stmt);
3273 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
3276 /* From this point on, the function deals with assignments in between
3277 aggregates when at least one has scalar reductions of some of its
3278 components. There are three possible scenarios: Both the LHS and RHS have
3279 to-be-scalarized components, 2) only the RHS has or 3) only the LHS has.
3281 In the first case, we would like to load the LHS components from RHS
3282 components whenever possible. If that is not possible, we would like to
3283 read it directly from the RHS (after updating it by storing in it its own
3284 components). If there are some necessary unscalarized data in the LHS,
3285 those will be loaded by the original assignment too. If neither of these
3286 cases happen, the original statement can be removed. Most of this is done
3287 by load_assign_lhs_subreplacements.
3289 In the second case, we would like to store all RHS scalarized components
3290 directly into LHS and if they cover the aggregate completely, remove the
3291 statement too. In the third case, we want the LHS components to be loaded
3292 directly from the RHS (DSE will remove the original statement if it
3293 becomes redundant).
3295 This is a bit complex but manageable when types match and when unions do
3296 not cause confusion in a way that we cannot really load a component of LHS
3297 from the RHS or vice versa (the access representing this level can have
3298 subaccesses that are accessible only through a different union field at a
3299 higher level - different from the one used in the examined expression).
3300 Unions are fun.
3302 Therefore, I specially handle a fourth case, happening when there is a
3303 specific type cast or it is impossible to locate a scalarized subaccess on
3304 the other side of the expression. If that happens, I simply "refresh" the
3305 RHS by storing in it is scalarized components leave the original statement
3306 there to do the copying and then load the scalar replacements of the LHS.
3307 This is what the first branch does. */
3309 if (modify_this_stmt
3310 || gimple_has_volatile_ops (stmt)
3311 || contains_vce_or_bfcref_p (rhs)
3312 || contains_vce_or_bfcref_p (lhs)
3313 || stmt_ends_bb_p (stmt))
3315 if (access_has_children_p (racc))
3316 generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0,
3317 gsi, false, false, loc);
3318 if (access_has_children_p (lacc))
3320 gimple_stmt_iterator alt_gsi = gsi_none ();
3321 if (stmt_ends_bb_p (stmt))
3323 alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi)));
3324 gsi = &alt_gsi;
3326 generate_subtree_copies (lacc->first_child, lhs, lacc->offset, 0, 0,
3327 gsi, true, true, loc);
3329 sra_stats.separate_lhs_rhs_handling++;
3331 /* This gimplification must be done after generate_subtree_copies,
3332 lest we insert the subtree copies in the middle of the gimplified
3333 sequence. */
3334 if (force_gimple_rhs)
3335 rhs = force_gimple_operand_gsi (&orig_gsi, rhs, true, NULL_TREE,
3336 true, GSI_SAME_STMT);
3337 if (gimple_assign_rhs1 (stmt) != rhs)
3339 modify_this_stmt = true;
3340 gimple_assign_set_rhs_from_tree (&orig_gsi, rhs);
3341 gcc_assert (stmt == gsi_stmt (orig_gsi));
3344 return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
3346 else
3348 if (access_has_children_p (lacc)
3349 && access_has_children_p (racc)
3350 /* When an access represents an unscalarizable region, it usually
3351 represents accesses with variable offset and thus must not be used
3352 to generate new memory accesses. */
3353 && !lacc->grp_unscalarizable_region
3354 && !racc->grp_unscalarizable_region)
3356 struct subreplacement_assignment_data sad;
3358 sad.left_offset = lacc->offset;
3359 sad.assignment_lhs = lhs;
3360 sad.assignment_rhs = rhs;
3361 sad.top_racc = racc;
3362 sad.old_gsi = *gsi;
3363 sad.new_gsi = gsi;
3364 sad.loc = gimple_location (stmt);
3365 sad.refreshed = SRA_UDH_NONE;
3367 if (lacc->grp_read && !lacc->grp_covered)
3368 handle_unscalarized_data_in_subtree (&sad);
3370 load_assign_lhs_subreplacements (lacc, &sad);
3371 if (sad.refreshed != SRA_UDH_RIGHT)
3373 gsi_next (gsi);
3374 unlink_stmt_vdef (stmt);
3375 gsi_remove (&sad.old_gsi, true);
3376 release_defs (stmt);
3377 sra_stats.deleted++;
3378 return SRA_AM_REMOVED;
3381 else
3383 if (access_has_children_p (racc)
3384 && !racc->grp_unscalarized_data)
3386 if (dump_file)
3388 fprintf (dump_file, "Removing load: ");
3389 print_gimple_stmt (dump_file, stmt, 0, 0);
3391 generate_subtree_copies (racc->first_child, lhs,
3392 racc->offset, 0, 0, gsi,
3393 false, false, loc);
3394 gcc_assert (stmt == gsi_stmt (*gsi));
3395 unlink_stmt_vdef (stmt);
3396 gsi_remove (gsi, true);
3397 release_defs (stmt);
3398 sra_stats.deleted++;
3399 return SRA_AM_REMOVED;
3401 /* Restore the aggregate RHS from its components so the
3402 prevailing aggregate copy does the right thing. */
3403 if (access_has_children_p (racc))
3404 generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0,
3405 gsi, false, false, loc);
3406 /* Re-load the components of the aggregate copy destination.
3407 But use the RHS aggregate to load from to expose more
3408 optimization opportunities. */
3409 if (access_has_children_p (lacc))
3410 generate_subtree_copies (lacc->first_child, rhs, lacc->offset,
3411 0, 0, gsi, true, true, loc);
3414 return SRA_AM_NONE;
3418 /* Traverse the function body and all modifications as decided in
3419 analyze_all_variable_accesses. Return true iff the CFG has been
3420 changed. */
3422 static bool
3423 sra_modify_function_body (void)
3425 bool cfg_changed = false;
3426 basic_block bb;
3428 FOR_EACH_BB_FN (bb, cfun)
3430 gimple_stmt_iterator gsi = gsi_start_bb (bb);
3431 while (!gsi_end_p (gsi))
3433 gimple stmt = gsi_stmt (gsi);
3434 enum assignment_mod_result assign_result;
3435 bool modified = false, deleted = false;
3436 tree *t;
3437 unsigned i;
3439 switch (gimple_code (stmt))
3441 case GIMPLE_RETURN:
3442 t = gimple_return_retval_ptr (as_a <greturn *> (stmt));
3443 if (*t != NULL_TREE)
3444 modified |= sra_modify_expr (t, &gsi, false);
3445 break;
3447 case GIMPLE_ASSIGN:
3448 assign_result = sra_modify_assign (stmt, &gsi);
3449 modified |= assign_result == SRA_AM_MODIFIED;
3450 deleted = assign_result == SRA_AM_REMOVED;
3451 break;
3453 case GIMPLE_CALL:
3454 /* Operands must be processed before the lhs. */
3455 for (i = 0; i < gimple_call_num_args (stmt); i++)
3457 t = gimple_call_arg_ptr (stmt, i);
3458 modified |= sra_modify_expr (t, &gsi, false);
3461 if (gimple_call_lhs (stmt))
3463 t = gimple_call_lhs_ptr (stmt);
3464 modified |= sra_modify_expr (t, &gsi, true);
3466 break;
3468 case GIMPLE_ASM:
3470 gasm *asm_stmt = as_a <gasm *> (stmt);
3471 for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
3473 t = &TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
3474 modified |= sra_modify_expr (t, &gsi, false);
3476 for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
3478 t = &TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
3479 modified |= sra_modify_expr (t, &gsi, true);
3482 break;
3484 default:
3485 break;
3488 if (modified)
3490 update_stmt (stmt);
3491 if (maybe_clean_eh_stmt (stmt)
3492 && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
3493 cfg_changed = true;
3495 if (!deleted)
3496 gsi_next (&gsi);
3500 gsi_commit_edge_inserts ();
3501 return cfg_changed;
3504 /* Generate statements initializing scalar replacements of parts of function
3505 parameters. */
3507 static void
3508 initialize_parameter_reductions (void)
3510 gimple_stmt_iterator gsi;
3511 gimple_seq seq = NULL;
3512 tree parm;
3514 gsi = gsi_start (seq);
3515 for (parm = DECL_ARGUMENTS (current_function_decl);
3516 parm;
3517 parm = DECL_CHAIN (parm))
3519 vec<access_p> *access_vec;
3520 struct access *access;
3522 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
3523 continue;
3524 access_vec = get_base_access_vector (parm);
3525 if (!access_vec)
3526 continue;
3528 for (access = (*access_vec)[0];
3529 access;
3530 access = access->next_grp)
3531 generate_subtree_copies (access, parm, 0, 0, 0, &gsi, true, true,
3532 EXPR_LOCATION (parm));
3535 seq = gsi_seq (gsi);
3536 if (seq)
3537 gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
3540 /* The "main" function of intraprocedural SRA passes. Runs the analysis and if
3541 it reveals there are components of some aggregates to be scalarized, it runs
3542 the required transformations. */
3543 static unsigned int
3544 perform_intra_sra (void)
3546 int ret = 0;
3547 sra_initialize ();
3549 if (!find_var_candidates ())
3550 goto out;
3552 if (!scan_function ())
3553 goto out;
3555 if (!analyze_all_variable_accesses ())
3556 goto out;
3558 if (sra_modify_function_body ())
3559 ret = TODO_update_ssa | TODO_cleanup_cfg;
3560 else
3561 ret = TODO_update_ssa;
3562 initialize_parameter_reductions ();
3564 statistics_counter_event (cfun, "Scalar replacements created",
3565 sra_stats.replacements);
3566 statistics_counter_event (cfun, "Modified expressions", sra_stats.exprs);
3567 statistics_counter_event (cfun, "Subtree copy stmts",
3568 sra_stats.subtree_copies);
3569 statistics_counter_event (cfun, "Subreplacement stmts",
3570 sra_stats.subreplacements);
3571 statistics_counter_event (cfun, "Deleted stmts", sra_stats.deleted);
3572 statistics_counter_event (cfun, "Separate LHS and RHS handling",
3573 sra_stats.separate_lhs_rhs_handling);
3575 out:
3576 sra_deinitialize ();
3577 return ret;
3580 /* Perform early intraprocedural SRA. */
3581 static unsigned int
3582 early_intra_sra (void)
3584 sra_mode = SRA_MODE_EARLY_INTRA;
3585 return perform_intra_sra ();
3588 /* Perform "late" intraprocedural SRA. */
3589 static unsigned int
3590 late_intra_sra (void)
3592 sra_mode = SRA_MODE_INTRA;
3593 return perform_intra_sra ();
3597 static bool
3598 gate_intra_sra (void)
3600 return flag_tree_sra != 0 && dbg_cnt (tree_sra);
3604 namespace {
3606 const pass_data pass_data_sra_early =
3608 GIMPLE_PASS, /* type */
3609 "esra", /* name */
3610 OPTGROUP_NONE, /* optinfo_flags */
3611 TV_TREE_SRA, /* tv_id */
3612 ( PROP_cfg | PROP_ssa ), /* properties_required */
3613 0, /* properties_provided */
3614 0, /* properties_destroyed */
3615 0, /* todo_flags_start */
3616 TODO_update_ssa, /* todo_flags_finish */
3619 class pass_sra_early : public gimple_opt_pass
3621 public:
3622 pass_sra_early (gcc::context *ctxt)
3623 : gimple_opt_pass (pass_data_sra_early, ctxt)
3626 /* opt_pass methods: */
3627 virtual bool gate (function *) { return gate_intra_sra (); }
3628 virtual unsigned int execute (function *) { return early_intra_sra (); }
3630 }; // class pass_sra_early
3632 } // anon namespace
3634 gimple_opt_pass *
3635 make_pass_sra_early (gcc::context *ctxt)
3637 return new pass_sra_early (ctxt);
3640 namespace {
3642 const pass_data pass_data_sra =
3644 GIMPLE_PASS, /* type */
3645 "sra", /* name */
3646 OPTGROUP_NONE, /* optinfo_flags */
3647 TV_TREE_SRA, /* tv_id */
3648 ( PROP_cfg | PROP_ssa ), /* properties_required */
3649 0, /* properties_provided */
3650 0, /* properties_destroyed */
3651 TODO_update_address_taken, /* todo_flags_start */
3652 TODO_update_ssa, /* todo_flags_finish */
3655 class pass_sra : public gimple_opt_pass
3657 public:
3658 pass_sra (gcc::context *ctxt)
3659 : gimple_opt_pass (pass_data_sra, ctxt)
3662 /* opt_pass methods: */
3663 virtual bool gate (function *) { return gate_intra_sra (); }
3664 virtual unsigned int execute (function *) { return late_intra_sra (); }
3666 }; // class pass_sra
3668 } // anon namespace
3670 gimple_opt_pass *
3671 make_pass_sra (gcc::context *ctxt)
3673 return new pass_sra (ctxt);
3677 /* Return true iff PARM (which must be a parm_decl) is an unused scalar
3678 parameter. */
3680 static bool
3681 is_unused_scalar_param (tree parm)
3683 tree name;
3684 return (is_gimple_reg (parm)
3685 && (!(name = ssa_default_def (cfun, parm))
3686 || has_zero_uses (name)));
3689 /* Scan immediate uses of a default definition SSA name of a parameter PARM and
3690 examine whether there are any direct or otherwise infeasible ones. If so,
3691 return true, otherwise return false. PARM must be a gimple register with a
3692 non-NULL default definition. */
3694 static bool
3695 ptr_parm_has_direct_uses (tree parm)
3697 imm_use_iterator ui;
3698 gimple stmt;
3699 tree name = ssa_default_def (cfun, parm);
3700 bool ret = false;
3702 FOR_EACH_IMM_USE_STMT (stmt, ui, name)
3704 int uses_ok = 0;
3705 use_operand_p use_p;
3707 if (is_gimple_debug (stmt))
3708 continue;
3710 /* Valid uses include dereferences on the lhs and the rhs. */
3711 if (gimple_has_lhs (stmt))
3713 tree lhs = gimple_get_lhs (stmt);
3714 while (handled_component_p (lhs))
3715 lhs = TREE_OPERAND (lhs, 0);
3716 if (TREE_CODE (lhs) == MEM_REF
3717 && TREE_OPERAND (lhs, 0) == name
3718 && integer_zerop (TREE_OPERAND (lhs, 1))
3719 && types_compatible_p (TREE_TYPE (lhs),
3720 TREE_TYPE (TREE_TYPE (name)))
3721 && !TREE_THIS_VOLATILE (lhs))
3722 uses_ok++;
3724 if (gimple_assign_single_p (stmt))
3726 tree rhs = gimple_assign_rhs1 (stmt);
3727 while (handled_component_p (rhs))
3728 rhs = TREE_OPERAND (rhs, 0);
3729 if (TREE_CODE (rhs) == MEM_REF
3730 && TREE_OPERAND (rhs, 0) == name
3731 && integer_zerop (TREE_OPERAND (rhs, 1))
3732 && types_compatible_p (TREE_TYPE (rhs),
3733 TREE_TYPE (TREE_TYPE (name)))
3734 && !TREE_THIS_VOLATILE (rhs))
3735 uses_ok++;
3737 else if (is_gimple_call (stmt))
3739 unsigned i;
3740 for (i = 0; i < gimple_call_num_args (stmt); ++i)
3742 tree arg = gimple_call_arg (stmt, i);
3743 while (handled_component_p (arg))
3744 arg = TREE_OPERAND (arg, 0);
3745 if (TREE_CODE (arg) == MEM_REF
3746 && TREE_OPERAND (arg, 0) == name
3747 && integer_zerop (TREE_OPERAND (arg, 1))
3748 && types_compatible_p (TREE_TYPE (arg),
3749 TREE_TYPE (TREE_TYPE (name)))
3750 && !TREE_THIS_VOLATILE (arg))
3751 uses_ok++;
3755 /* If the number of valid uses does not match the number of
3756 uses in this stmt there is an unhandled use. */
3757 FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
3758 --uses_ok;
3760 if (uses_ok != 0)
3761 ret = true;
3763 if (ret)
3764 BREAK_FROM_IMM_USE_STMT (ui);
3767 return ret;
3770 /* Identify candidates for reduction for IPA-SRA based on their type and mark
3771 them in candidate_bitmap. Note that these do not necessarily include
3772 parameter which are unused and thus can be removed. Return true iff any
3773 such candidate has been found. */
3775 static bool
3776 find_param_candidates (void)
3778 tree parm;
3779 int count = 0;
3780 bool ret = false;
3781 const char *msg;
3783 for (parm = DECL_ARGUMENTS (current_function_decl);
3784 parm;
3785 parm = DECL_CHAIN (parm))
3787 tree type = TREE_TYPE (parm);
3788 tree_node **slot;
3790 count++;
3792 if (TREE_THIS_VOLATILE (parm)
3793 || TREE_ADDRESSABLE (parm)
3794 || (!is_gimple_reg_type (type) && is_va_list_type (type)))
3795 continue;
3797 if (is_unused_scalar_param (parm))
3799 ret = true;
3800 continue;
3803 if (POINTER_TYPE_P (type))
3805 type = TREE_TYPE (type);
3807 if (TREE_CODE (type) == FUNCTION_TYPE
3808 || TYPE_VOLATILE (type)
3809 || (TREE_CODE (type) == ARRAY_TYPE
3810 && TYPE_NONALIASED_COMPONENT (type))
3811 || !is_gimple_reg (parm)
3812 || is_va_list_type (type)
3813 || ptr_parm_has_direct_uses (parm))
3814 continue;
3816 else if (!AGGREGATE_TYPE_P (type))
3817 continue;
3819 if (!COMPLETE_TYPE_P (type)
3820 || !tree_fits_uhwi_p (TYPE_SIZE (type))
3821 || tree_to_uhwi (TYPE_SIZE (type)) == 0
3822 || (AGGREGATE_TYPE_P (type)
3823 && type_internals_preclude_sra_p (type, &msg)))
3824 continue;
3826 bitmap_set_bit (candidate_bitmap, DECL_UID (parm));
3827 slot = candidates->find_slot_with_hash (parm, DECL_UID (parm), INSERT);
3828 *slot = parm;
3830 ret = true;
3831 if (dump_file && (dump_flags & TDF_DETAILS))
3833 fprintf (dump_file, "Candidate (%d): ", DECL_UID (parm));
3834 print_generic_expr (dump_file, parm, 0);
3835 fprintf (dump_file, "\n");
3839 func_param_count = count;
3840 return ret;
3843 /* Callback of walk_aliased_vdefs, marks the access passed as DATA as
3844 maybe_modified. */
3846 static bool
3847 mark_maybe_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
3848 void *data)
3850 struct access *repr = (struct access *) data;
3852 repr->grp_maybe_modified = 1;
3853 return true;
3856 /* Analyze what representatives (in linked lists accessible from
3857 REPRESENTATIVES) can be modified by side effects of statements in the
3858 current function. */
3860 static void
3861 analyze_modified_params (vec<access_p> representatives)
3863 int i;
3865 for (i = 0; i < func_param_count; i++)
3867 struct access *repr;
3869 for (repr = representatives[i];
3870 repr;
3871 repr = repr->next_grp)
3873 struct access *access;
3874 bitmap visited;
3875 ao_ref ar;
3877 if (no_accesses_p (repr))
3878 continue;
3879 if (!POINTER_TYPE_P (TREE_TYPE (repr->base))
3880 || repr->grp_maybe_modified)
3881 continue;
3883 ao_ref_init (&ar, repr->expr);
3884 visited = BITMAP_ALLOC (NULL);
3885 for (access = repr; access; access = access->next_sibling)
3887 /* All accesses are read ones, otherwise grp_maybe_modified would
3888 be trivially set. */
3889 walk_aliased_vdefs (&ar, gimple_vuse (access->stmt),
3890 mark_maybe_modified, repr, &visited);
3891 if (repr->grp_maybe_modified)
3892 break;
3894 BITMAP_FREE (visited);
3899 /* Propagate distances in bb_dereferences in the opposite direction than the
3900 control flow edges, in each step storing the maximum of the current value
3901 and the minimum of all successors. These steps are repeated until the table
3902 stabilizes. Note that BBs which might terminate the functions (according to
3903 final_bbs bitmap) never updated in this way. */
3905 static void
3906 propagate_dereference_distances (void)
3908 basic_block bb;
3910 auto_vec<basic_block> queue (last_basic_block_for_fn (cfun));
3911 queue.quick_push (ENTRY_BLOCK_PTR_FOR_FN (cfun));
3912 FOR_EACH_BB_FN (bb, cfun)
3914 queue.quick_push (bb);
3915 bb->aux = bb;
3918 while (!queue.is_empty ())
3920 edge_iterator ei;
3921 edge e;
3922 bool change = false;
3923 int i;
3925 bb = queue.pop ();
3926 bb->aux = NULL;
3928 if (bitmap_bit_p (final_bbs, bb->index))
3929 continue;
3931 for (i = 0; i < func_param_count; i++)
3933 int idx = bb->index * func_param_count + i;
3934 bool first = true;
3935 HOST_WIDE_INT inh = 0;
3937 FOR_EACH_EDGE (e, ei, bb->succs)
3939 int succ_idx = e->dest->index * func_param_count + i;
3941 if (e->src == EXIT_BLOCK_PTR_FOR_FN (cfun))
3942 continue;
3944 if (first)
3946 first = false;
3947 inh = bb_dereferences [succ_idx];
3949 else if (bb_dereferences [succ_idx] < inh)
3950 inh = bb_dereferences [succ_idx];
3953 if (!first && bb_dereferences[idx] < inh)
3955 bb_dereferences[idx] = inh;
3956 change = true;
3960 if (change && !bitmap_bit_p (final_bbs, bb->index))
3961 FOR_EACH_EDGE (e, ei, bb->preds)
3963 if (e->src->aux)
3964 continue;
3966 e->src->aux = e->src;
3967 queue.quick_push (e->src);
3972 /* Dump a dereferences TABLE with heading STR to file F. */
3974 static void
3975 dump_dereferences_table (FILE *f, const char *str, HOST_WIDE_INT *table)
3977 basic_block bb;
3979 fprintf (dump_file, str);
3980 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun),
3981 EXIT_BLOCK_PTR_FOR_FN (cfun), next_bb)
3983 fprintf (f, "%4i %i ", bb->index, bitmap_bit_p (final_bbs, bb->index));
3984 if (bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
3986 int i;
3987 for (i = 0; i < func_param_count; i++)
3989 int idx = bb->index * func_param_count + i;
3990 fprintf (f, " %4" HOST_WIDE_INT_PRINT "d", table[idx]);
3993 fprintf (f, "\n");
3995 fprintf (dump_file, "\n");
3998 /* Determine what (parts of) parameters passed by reference that are not
3999 assigned to are not certainly dereferenced in this function and thus the
4000 dereferencing cannot be safely moved to the caller without potentially
4001 introducing a segfault. Mark such REPRESENTATIVES as
4002 grp_not_necessarilly_dereferenced.
4004 The dereferenced maximum "distance," i.e. the offset + size of the accessed
4005 part is calculated rather than simple booleans are calculated for each
4006 pointer parameter to handle cases when only a fraction of the whole
4007 aggregate is allocated (see testsuite/gcc.c-torture/execute/ipa-sra-2.c for
4008 an example).
4010 The maximum dereference distances for each pointer parameter and BB are
4011 already stored in bb_dereference. This routine simply propagates these
4012 values upwards by propagate_dereference_distances and then compares the
4013 distances of individual parameters in the ENTRY BB to the equivalent
4014 distances of each representative of a (fraction of a) parameter. */
4016 static void
4017 analyze_caller_dereference_legality (vec<access_p> representatives)
4019 int i;
4021 if (dump_file && (dump_flags & TDF_DETAILS))
4022 dump_dereferences_table (dump_file,
4023 "Dereference table before propagation:\n",
4024 bb_dereferences);
4026 propagate_dereference_distances ();
4028 if (dump_file && (dump_flags & TDF_DETAILS))
4029 dump_dereferences_table (dump_file,
4030 "Dereference table after propagation:\n",
4031 bb_dereferences);
4033 for (i = 0; i < func_param_count; i++)
4035 struct access *repr = representatives[i];
4036 int idx = ENTRY_BLOCK_PTR_FOR_FN (cfun)->index * func_param_count + i;
4038 if (!repr || no_accesses_p (repr))
4039 continue;
4043 if ((repr->offset + repr->size) > bb_dereferences[idx])
4044 repr->grp_not_necessarilly_dereferenced = 1;
4045 repr = repr->next_grp;
4047 while (repr);
4051 /* Return the representative access for the parameter declaration PARM if it is
4052 a scalar passed by reference which is not written to and the pointer value
4053 is not used directly. Thus, if it is legal to dereference it in the caller
4054 and we can rule out modifications through aliases, such parameter should be
4055 turned into one passed by value. Return NULL otherwise. */
4057 static struct access *
4058 unmodified_by_ref_scalar_representative (tree parm)
4060 int i, access_count;
4061 struct access *repr;
4062 vec<access_p> *access_vec;
4064 access_vec = get_base_access_vector (parm);
4065 gcc_assert (access_vec);
4066 repr = (*access_vec)[0];
4067 if (repr->write)
4068 return NULL;
4069 repr->group_representative = repr;
4071 access_count = access_vec->length ();
4072 for (i = 1; i < access_count; i++)
4074 struct access *access = (*access_vec)[i];
4075 if (access->write)
4076 return NULL;
4077 access->group_representative = repr;
4078 access->next_sibling = repr->next_sibling;
4079 repr->next_sibling = access;
4082 repr->grp_read = 1;
4083 repr->grp_scalar_ptr = 1;
4084 return repr;
4087 /* Return true iff this ACCESS precludes IPA-SRA of the parameter it is
4088 associated with. REQ_ALIGN is the minimum required alignment. */
4090 static bool
4091 access_precludes_ipa_sra_p (struct access *access, unsigned int req_align)
4093 unsigned int exp_align;
4094 /* Avoid issues such as the second simple testcase in PR 42025. The problem
4095 is incompatible assign in a call statement (and possibly even in asm
4096 statements). This can be relaxed by using a new temporary but only for
4097 non-TREE_ADDRESSABLE types and is probably not worth the complexity. (In
4098 intraprocedural SRA we deal with this by keeping the old aggregate around,
4099 something we cannot do in IPA-SRA.) */
4100 if (access->write
4101 && (is_gimple_call (access->stmt)
4102 || gimple_code (access->stmt) == GIMPLE_ASM))
4103 return true;
4105 exp_align = get_object_alignment (access->expr);
4106 if (exp_align < req_align)
4107 return true;
4109 return false;
4113 /* Sort collected accesses for parameter PARM, identify representatives for
4114 each accessed region and link them together. Return NULL if there are
4115 different but overlapping accesses, return the special ptr value meaning
4116 there are no accesses for this parameter if that is the case and return the
4117 first representative otherwise. Set *RO_GRP if there is a group of accesses
4118 with only read (i.e. no write) accesses. */
4120 static struct access *
4121 splice_param_accesses (tree parm, bool *ro_grp)
4123 int i, j, access_count, group_count;
4124 int agg_size, total_size = 0;
4125 struct access *access, *res, **prev_acc_ptr = &res;
4126 vec<access_p> *access_vec;
4128 access_vec = get_base_access_vector (parm);
4129 if (!access_vec)
4130 return &no_accesses_representant;
4131 access_count = access_vec->length ();
4133 access_vec->qsort (compare_access_positions);
4135 i = 0;
4136 total_size = 0;
4137 group_count = 0;
4138 while (i < access_count)
4140 bool modification;
4141 tree a1_alias_type;
4142 access = (*access_vec)[i];
4143 modification = access->write;
4144 if (access_precludes_ipa_sra_p (access, TYPE_ALIGN (access->type)))
4145 return NULL;
4146 a1_alias_type = reference_alias_ptr_type (access->expr);
4148 /* Access is about to become group representative unless we find some
4149 nasty overlap which would preclude us from breaking this parameter
4150 apart. */
4152 j = i + 1;
4153 while (j < access_count)
4155 struct access *ac2 = (*access_vec)[j];
4156 if (ac2->offset != access->offset)
4158 /* All or nothing law for parameters. */
4159 if (access->offset + access->size > ac2->offset)
4160 return NULL;
4161 else
4162 break;
4164 else if (ac2->size != access->size)
4165 return NULL;
4167 if (access_precludes_ipa_sra_p (ac2, TYPE_ALIGN (access->type))
4168 || (ac2->type != access->type
4169 && (TREE_ADDRESSABLE (ac2->type)
4170 || TREE_ADDRESSABLE (access->type)))
4171 || (reference_alias_ptr_type (ac2->expr) != a1_alias_type))
4172 return NULL;
4174 modification |= ac2->write;
4175 ac2->group_representative = access;
4176 ac2->next_sibling = access->next_sibling;
4177 access->next_sibling = ac2;
4178 j++;
4181 group_count++;
4182 access->grp_maybe_modified = modification;
4183 if (!modification)
4184 *ro_grp = true;
4185 *prev_acc_ptr = access;
4186 prev_acc_ptr = &access->next_grp;
4187 total_size += access->size;
4188 i = j;
4191 if (POINTER_TYPE_P (TREE_TYPE (parm)))
4192 agg_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))));
4193 else
4194 agg_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (parm)));
4195 if (total_size >= agg_size)
4196 return NULL;
4198 gcc_assert (group_count > 0);
4199 return res;
4202 /* Decide whether parameters with representative accesses given by REPR should
4203 be reduced into components. */
4205 static int
4206 decide_one_param_reduction (struct access *repr)
4208 int total_size, cur_parm_size, agg_size, new_param_count, parm_size_limit;
4209 bool by_ref;
4210 tree parm;
4212 parm = repr->base;
4213 cur_parm_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (parm)));
4214 gcc_assert (cur_parm_size > 0);
4216 if (POINTER_TYPE_P (TREE_TYPE (parm)))
4218 by_ref = true;
4219 agg_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))));
4221 else
4223 by_ref = false;
4224 agg_size = cur_parm_size;
4227 if (dump_file)
4229 struct access *acc;
4230 fprintf (dump_file, "Evaluating PARAM group sizes for ");
4231 print_generic_expr (dump_file, parm, 0);
4232 fprintf (dump_file, " (UID: %u): \n", DECL_UID (parm));
4233 for (acc = repr; acc; acc = acc->next_grp)
4234 dump_access (dump_file, acc, true);
4237 total_size = 0;
4238 new_param_count = 0;
4240 for (; repr; repr = repr->next_grp)
4242 gcc_assert (parm == repr->base);
4244 /* Taking the address of a non-addressable field is verboten. */
4245 if (by_ref && repr->non_addressable)
4246 return 0;
4248 /* Do not decompose a non-BLKmode param in a way that would
4249 create BLKmode params. Especially for by-reference passing
4250 (thus, pointer-type param) this is hardly worthwhile. */
4251 if (DECL_MODE (parm) != BLKmode
4252 && TYPE_MODE (repr->type) == BLKmode)
4253 return 0;
4255 if (!by_ref || (!repr->grp_maybe_modified
4256 && !repr->grp_not_necessarilly_dereferenced))
4257 total_size += repr->size;
4258 else
4259 total_size += cur_parm_size;
4261 new_param_count++;
4264 gcc_assert (new_param_count > 0);
4266 if (optimize_function_for_size_p (cfun))
4267 parm_size_limit = cur_parm_size;
4268 else
4269 parm_size_limit = (PARAM_VALUE (PARAM_IPA_SRA_PTR_GROWTH_FACTOR)
4270 * cur_parm_size);
4272 if (total_size < agg_size
4273 && total_size <= parm_size_limit)
4275 if (dump_file)
4276 fprintf (dump_file, " ....will be split into %i components\n",
4277 new_param_count);
4278 return new_param_count;
4280 else
4281 return 0;
4284 /* The order of the following enums is important, we need to do extra work for
4285 UNUSED_PARAMS, BY_VAL_ACCESSES and UNMODIF_BY_REF_ACCESSES. */
4286 enum ipa_splicing_result { NO_GOOD_ACCESS, UNUSED_PARAMS, BY_VAL_ACCESSES,
4287 MODIF_BY_REF_ACCESSES, UNMODIF_BY_REF_ACCESSES };
4289 /* Identify representatives of all accesses to all candidate parameters for
4290 IPA-SRA. Return result based on what representatives have been found. */
4292 static enum ipa_splicing_result
4293 splice_all_param_accesses (vec<access_p> &representatives)
4295 enum ipa_splicing_result result = NO_GOOD_ACCESS;
4296 tree parm;
4297 struct access *repr;
4299 representatives.create (func_param_count);
4301 for (parm = DECL_ARGUMENTS (current_function_decl);
4302 parm;
4303 parm = DECL_CHAIN (parm))
4305 if (is_unused_scalar_param (parm))
4307 representatives.quick_push (&no_accesses_representant);
4308 if (result == NO_GOOD_ACCESS)
4309 result = UNUSED_PARAMS;
4311 else if (POINTER_TYPE_P (TREE_TYPE (parm))
4312 && is_gimple_reg_type (TREE_TYPE (TREE_TYPE (parm)))
4313 && bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
4315 repr = unmodified_by_ref_scalar_representative (parm);
4316 representatives.quick_push (repr);
4317 if (repr)
4318 result = UNMODIF_BY_REF_ACCESSES;
4320 else if (bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
4322 bool ro_grp = false;
4323 repr = splice_param_accesses (parm, &ro_grp);
4324 representatives.quick_push (repr);
4326 if (repr && !no_accesses_p (repr))
4328 if (POINTER_TYPE_P (TREE_TYPE (parm)))
4330 if (ro_grp)
4331 result = UNMODIF_BY_REF_ACCESSES;
4332 else if (result < MODIF_BY_REF_ACCESSES)
4333 result = MODIF_BY_REF_ACCESSES;
4335 else if (result < BY_VAL_ACCESSES)
4336 result = BY_VAL_ACCESSES;
4338 else if (no_accesses_p (repr) && (result == NO_GOOD_ACCESS))
4339 result = UNUSED_PARAMS;
4341 else
4342 representatives.quick_push (NULL);
4345 if (result == NO_GOOD_ACCESS)
4347 representatives.release ();
4348 return NO_GOOD_ACCESS;
4351 return result;
4354 /* Return the index of BASE in PARMS. Abort if it is not found. */
4356 static inline int
4357 get_param_index (tree base, vec<tree> parms)
4359 int i, len;
4361 len = parms.length ();
4362 for (i = 0; i < len; i++)
4363 if (parms[i] == base)
4364 return i;
4365 gcc_unreachable ();
4368 /* Convert the decisions made at the representative level into compact
4369 parameter adjustments. REPRESENTATIVES are pointers to first
4370 representatives of each param accesses, ADJUSTMENTS_COUNT is the expected
4371 final number of adjustments. */
4373 static ipa_parm_adjustment_vec
4374 turn_representatives_into_adjustments (vec<access_p> representatives,
4375 int adjustments_count)
4377 vec<tree> parms;
4378 ipa_parm_adjustment_vec adjustments;
4379 tree parm;
4380 int i;
4382 gcc_assert (adjustments_count > 0);
4383 parms = ipa_get_vector_of_formal_parms (current_function_decl);
4384 adjustments.create (adjustments_count);
4385 parm = DECL_ARGUMENTS (current_function_decl);
4386 for (i = 0; i < func_param_count; i++, parm = DECL_CHAIN (parm))
4388 struct access *repr = representatives[i];
4390 if (!repr || no_accesses_p (repr))
4392 struct ipa_parm_adjustment adj;
4394 memset (&adj, 0, sizeof (adj));
4395 adj.base_index = get_param_index (parm, parms);
4396 adj.base = parm;
4397 if (!repr)
4398 adj.op = IPA_PARM_OP_COPY;
4399 else
4400 adj.op = IPA_PARM_OP_REMOVE;
4401 adj.arg_prefix = "ISRA";
4402 adjustments.quick_push (adj);
4404 else
4406 struct ipa_parm_adjustment adj;
4407 int index = get_param_index (parm, parms);
4409 for (; repr; repr = repr->next_grp)
4411 memset (&adj, 0, sizeof (adj));
4412 gcc_assert (repr->base == parm);
4413 adj.base_index = index;
4414 adj.base = repr->base;
4415 adj.type = repr->type;
4416 adj.alias_ptr_type = reference_alias_ptr_type (repr->expr);
4417 adj.offset = repr->offset;
4418 adj.by_ref = (POINTER_TYPE_P (TREE_TYPE (repr->base))
4419 && (repr->grp_maybe_modified
4420 || repr->grp_not_necessarilly_dereferenced));
4421 adj.arg_prefix = "ISRA";
4422 adjustments.quick_push (adj);
4426 parms.release ();
4427 return adjustments;
4430 /* Analyze the collected accesses and produce a plan what to do with the
4431 parameters in the form of adjustments, NULL meaning nothing. */
4433 static ipa_parm_adjustment_vec
4434 analyze_all_param_acesses (void)
4436 enum ipa_splicing_result repr_state;
4437 bool proceed = false;
4438 int i, adjustments_count = 0;
4439 vec<access_p> representatives;
4440 ipa_parm_adjustment_vec adjustments;
4442 repr_state = splice_all_param_accesses (representatives);
4443 if (repr_state == NO_GOOD_ACCESS)
4444 return ipa_parm_adjustment_vec ();
4446 /* If there are any parameters passed by reference which are not modified
4447 directly, we need to check whether they can be modified indirectly. */
4448 if (repr_state == UNMODIF_BY_REF_ACCESSES)
4450 analyze_caller_dereference_legality (representatives);
4451 analyze_modified_params (representatives);
4454 for (i = 0; i < func_param_count; i++)
4456 struct access *repr = representatives[i];
4458 if (repr && !no_accesses_p (repr))
4460 if (repr->grp_scalar_ptr)
4462 adjustments_count++;
4463 if (repr->grp_not_necessarilly_dereferenced
4464 || repr->grp_maybe_modified)
4465 representatives[i] = NULL;
4466 else
4468 proceed = true;
4469 sra_stats.scalar_by_ref_to_by_val++;
4472 else
4474 int new_components = decide_one_param_reduction (repr);
4476 if (new_components == 0)
4478 representatives[i] = NULL;
4479 adjustments_count++;
4481 else
4483 adjustments_count += new_components;
4484 sra_stats.aggregate_params_reduced++;
4485 sra_stats.param_reductions_created += new_components;
4486 proceed = true;
4490 else
4492 if (no_accesses_p (repr))
4494 proceed = true;
4495 sra_stats.deleted_unused_parameters++;
4497 adjustments_count++;
4501 if (!proceed && dump_file)
4502 fprintf (dump_file, "NOT proceeding to change params.\n");
4504 if (proceed)
4505 adjustments = turn_representatives_into_adjustments (representatives,
4506 adjustments_count);
4507 else
4508 adjustments = ipa_parm_adjustment_vec ();
4510 representatives.release ();
4511 return adjustments;
4514 /* If a parameter replacement identified by ADJ does not yet exist in the form
4515 of declaration, create it and record it, otherwise return the previously
4516 created one. */
4518 static tree
4519 get_replaced_param_substitute (struct ipa_parm_adjustment *adj)
4521 tree repl;
4522 if (!adj->new_ssa_base)
4524 char *pretty_name = make_fancy_name (adj->base);
4526 repl = create_tmp_reg (TREE_TYPE (adj->base), "ISR");
4527 DECL_NAME (repl) = get_identifier (pretty_name);
4528 obstack_free (&name_obstack, pretty_name);
4530 adj->new_ssa_base = repl;
4532 else
4533 repl = adj->new_ssa_base;
4534 return repl;
4537 /* Find the first adjustment for a particular parameter BASE in a vector of
4538 ADJUSTMENTS which is not a copy_param. Return NULL if there is no such
4539 adjustment. */
4541 static struct ipa_parm_adjustment *
4542 get_adjustment_for_base (ipa_parm_adjustment_vec adjustments, tree base)
4544 int i, len;
4546 len = adjustments.length ();
4547 for (i = 0; i < len; i++)
4549 struct ipa_parm_adjustment *adj;
4551 adj = &adjustments[i];
4552 if (adj->op != IPA_PARM_OP_COPY && adj->base == base)
4553 return adj;
4556 return NULL;
4559 /* If the statement STMT defines an SSA_NAME of a parameter which is to be
4560 removed because its value is not used, replace the SSA_NAME with a one
4561 relating to a created VAR_DECL together all of its uses and return true.
4562 ADJUSTMENTS is a pointer to an adjustments vector. */
4564 static bool
4565 replace_removed_params_ssa_names (gimple stmt,
4566 ipa_parm_adjustment_vec adjustments)
4568 struct ipa_parm_adjustment *adj;
4569 tree lhs, decl, repl, name;
4571 if (gimple_code (stmt) == GIMPLE_PHI)
4572 lhs = gimple_phi_result (stmt);
4573 else if (is_gimple_assign (stmt))
4574 lhs = gimple_assign_lhs (stmt);
4575 else if (is_gimple_call (stmt))
4576 lhs = gimple_call_lhs (stmt);
4577 else
4578 gcc_unreachable ();
4580 if (TREE_CODE (lhs) != SSA_NAME)
4581 return false;
4583 decl = SSA_NAME_VAR (lhs);
4584 if (decl == NULL_TREE
4585 || TREE_CODE (decl) != PARM_DECL)
4586 return false;
4588 adj = get_adjustment_for_base (adjustments, decl);
4589 if (!adj)
4590 return false;
4592 repl = get_replaced_param_substitute (adj);
4593 name = make_ssa_name (repl, stmt);
4595 if (dump_file)
4597 fprintf (dump_file, "replacing an SSA name of a removed param ");
4598 print_generic_expr (dump_file, lhs, 0);
4599 fprintf (dump_file, " with ");
4600 print_generic_expr (dump_file, name, 0);
4601 fprintf (dump_file, "\n");
4604 if (is_gimple_assign (stmt))
4605 gimple_assign_set_lhs (stmt, name);
4606 else if (is_gimple_call (stmt))
4607 gimple_call_set_lhs (stmt, name);
4608 else
4609 gimple_phi_set_result (as_a <gphi *> (stmt), name);
4611 replace_uses_by (lhs, name);
4612 release_ssa_name (lhs);
4613 return true;
4616 /* If the statement STMT contains any expressions that need to replaced with a
4617 different one as noted by ADJUSTMENTS, do so. Handle any potential type
4618 incompatibilities (GSI is used to accommodate conversion statements and must
4619 point to the statement). Return true iff the statement was modified. */
4621 static bool
4622 sra_ipa_modify_assign (gimple stmt, gimple_stmt_iterator *gsi,
4623 ipa_parm_adjustment_vec adjustments)
4625 tree *lhs_p, *rhs_p;
4626 bool any;
4628 if (!gimple_assign_single_p (stmt))
4629 return false;
4631 rhs_p = gimple_assign_rhs1_ptr (stmt);
4632 lhs_p = gimple_assign_lhs_ptr (stmt);
4634 any = ipa_modify_expr (rhs_p, false, adjustments);
4635 any |= ipa_modify_expr (lhs_p, false, adjustments);
4636 if (any)
4638 tree new_rhs = NULL_TREE;
4640 if (!useless_type_conversion_p (TREE_TYPE (*lhs_p), TREE_TYPE (*rhs_p)))
4642 if (TREE_CODE (*rhs_p) == CONSTRUCTOR)
4644 /* V_C_Es of constructors can cause trouble (PR 42714). */
4645 if (is_gimple_reg_type (TREE_TYPE (*lhs_p)))
4646 *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
4647 else
4648 *rhs_p = build_constructor (TREE_TYPE (*lhs_p),
4649 NULL);
4651 else
4652 new_rhs = fold_build1_loc (gimple_location (stmt),
4653 VIEW_CONVERT_EXPR, TREE_TYPE (*lhs_p),
4654 *rhs_p);
4656 else if (REFERENCE_CLASS_P (*rhs_p)
4657 && is_gimple_reg_type (TREE_TYPE (*lhs_p))
4658 && !is_gimple_reg (*lhs_p))
4659 /* This can happen when an assignment in between two single field
4660 structures is turned into an assignment in between two pointers to
4661 scalars (PR 42237). */
4662 new_rhs = *rhs_p;
4664 if (new_rhs)
4666 tree tmp = force_gimple_operand_gsi (gsi, new_rhs, true, NULL_TREE,
4667 true, GSI_SAME_STMT);
4669 gimple_assign_set_rhs_from_tree (gsi, tmp);
4672 return true;
4675 return false;
4678 /* Traverse the function body and all modifications as described in
4679 ADJUSTMENTS. Return true iff the CFG has been changed. */
4681 bool
4682 ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments)
4684 bool cfg_changed = false;
4685 basic_block bb;
4687 FOR_EACH_BB_FN (bb, cfun)
4689 gimple_stmt_iterator gsi;
4691 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4692 replace_removed_params_ssa_names (gsi_stmt (gsi), adjustments);
4694 gsi = gsi_start_bb (bb);
4695 while (!gsi_end_p (gsi))
4697 gimple stmt = gsi_stmt (gsi);
4698 bool modified = false;
4699 tree *t;
4700 unsigned i;
4702 switch (gimple_code (stmt))
4704 case GIMPLE_RETURN:
4705 t = gimple_return_retval_ptr (as_a <greturn *> (stmt));
4706 if (*t != NULL_TREE)
4707 modified |= ipa_modify_expr (t, true, adjustments);
4708 break;
4710 case GIMPLE_ASSIGN:
4711 modified |= sra_ipa_modify_assign (stmt, &gsi, adjustments);
4712 modified |= replace_removed_params_ssa_names (stmt, adjustments);
4713 break;
4715 case GIMPLE_CALL:
4716 /* Operands must be processed before the lhs. */
4717 for (i = 0; i < gimple_call_num_args (stmt); i++)
4719 t = gimple_call_arg_ptr (stmt, i);
4720 modified |= ipa_modify_expr (t, true, adjustments);
4723 if (gimple_call_lhs (stmt))
4725 t = gimple_call_lhs_ptr (stmt);
4726 modified |= ipa_modify_expr (t, false, adjustments);
4727 modified |= replace_removed_params_ssa_names (stmt,
4728 adjustments);
4730 break;
4732 case GIMPLE_ASM:
4734 gasm *asm_stmt = as_a <gasm *> (stmt);
4735 for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
4737 t = &TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
4738 modified |= ipa_modify_expr (t, true, adjustments);
4740 for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
4742 t = &TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
4743 modified |= ipa_modify_expr (t, false, adjustments);
4746 break;
4748 default:
4749 break;
4752 if (modified)
4754 update_stmt (stmt);
4755 if (maybe_clean_eh_stmt (stmt)
4756 && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
4757 cfg_changed = true;
4759 gsi_next (&gsi);
4763 return cfg_changed;
4766 /* Call gimple_debug_bind_reset_value on all debug statements describing
4767 gimple register parameters that are being removed or replaced. */
4769 static void
4770 sra_ipa_reset_debug_stmts (ipa_parm_adjustment_vec adjustments)
4772 int i, len;
4773 gimple_stmt_iterator *gsip = NULL, gsi;
4775 if (MAY_HAVE_DEBUG_STMTS && single_succ_p (ENTRY_BLOCK_PTR_FOR_FN (cfun)))
4777 gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
4778 gsip = &gsi;
4780 len = adjustments.length ();
4781 for (i = 0; i < len; i++)
4783 struct ipa_parm_adjustment *adj;
4784 imm_use_iterator ui;
4785 gimple stmt;
4786 gdebug *def_temp;
4787 tree name, vexpr, copy = NULL_TREE;
4788 use_operand_p use_p;
4790 adj = &adjustments[i];
4791 if (adj->op == IPA_PARM_OP_COPY || !is_gimple_reg (adj->base))
4792 continue;
4793 name = ssa_default_def (cfun, adj->base);
4794 vexpr = NULL;
4795 if (name)
4796 FOR_EACH_IMM_USE_STMT (stmt, ui, name)
4798 if (gimple_clobber_p (stmt))
4800 gimple_stmt_iterator cgsi = gsi_for_stmt (stmt);
4801 unlink_stmt_vdef (stmt);
4802 gsi_remove (&cgsi, true);
4803 release_defs (stmt);
4804 continue;
4806 /* All other users must have been removed by
4807 ipa_sra_modify_function_body. */
4808 gcc_assert (is_gimple_debug (stmt));
4809 if (vexpr == NULL && gsip != NULL)
4811 gcc_assert (TREE_CODE (adj->base) == PARM_DECL);
4812 vexpr = make_node (DEBUG_EXPR_DECL);
4813 def_temp = gimple_build_debug_source_bind (vexpr, adj->base,
4814 NULL);
4815 DECL_ARTIFICIAL (vexpr) = 1;
4816 TREE_TYPE (vexpr) = TREE_TYPE (name);
4817 DECL_MODE (vexpr) = DECL_MODE (adj->base);
4818 gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
4820 if (vexpr)
4822 FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
4823 SET_USE (use_p, vexpr);
4825 else
4826 gimple_debug_bind_reset_value (stmt);
4827 update_stmt (stmt);
4829 /* Create a VAR_DECL for debug info purposes. */
4830 if (!DECL_IGNORED_P (adj->base))
4832 copy = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
4833 VAR_DECL, DECL_NAME (adj->base),
4834 TREE_TYPE (adj->base));
4835 if (DECL_PT_UID_SET_P (adj->base))
4836 SET_DECL_PT_UID (copy, DECL_PT_UID (adj->base));
4837 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (adj->base);
4838 TREE_READONLY (copy) = TREE_READONLY (adj->base);
4839 TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (adj->base);
4840 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (adj->base);
4841 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (adj->base);
4842 DECL_IGNORED_P (copy) = DECL_IGNORED_P (adj->base);
4843 DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (adj->base);
4844 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
4845 SET_DECL_RTL (copy, 0);
4846 TREE_USED (copy) = 1;
4847 DECL_CONTEXT (copy) = current_function_decl;
4848 add_local_decl (cfun, copy);
4849 DECL_CHAIN (copy) =
4850 BLOCK_VARS (DECL_INITIAL (current_function_decl));
4851 BLOCK_VARS (DECL_INITIAL (current_function_decl)) = copy;
4853 if (gsip != NULL && copy && target_for_debug_bind (adj->base))
4855 gcc_assert (TREE_CODE (adj->base) == PARM_DECL);
4856 if (vexpr)
4857 def_temp = gimple_build_debug_bind (copy, vexpr, NULL);
4858 else
4859 def_temp = gimple_build_debug_source_bind (copy, adj->base,
4860 NULL);
4861 gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
4866 /* Return false if all callers have at least as many actual arguments as there
4867 are formal parameters in the current function and that their types
4868 match. */
4870 static bool
4871 some_callers_have_mismatched_arguments_p (struct cgraph_node *node,
4872 void *data ATTRIBUTE_UNUSED)
4874 struct cgraph_edge *cs;
4875 for (cs = node->callers; cs; cs = cs->next_caller)
4876 if (!callsite_arguments_match_p (cs->call_stmt))
4877 return true;
4879 return false;
4882 /* Convert all callers of NODE. */
4884 static bool
4885 convert_callers_for_node (struct cgraph_node *node,
4886 void *data)
4888 ipa_parm_adjustment_vec *adjustments = (ipa_parm_adjustment_vec *) data;
4889 bitmap recomputed_callers = BITMAP_ALLOC (NULL);
4890 struct cgraph_edge *cs;
4892 for (cs = node->callers; cs; cs = cs->next_caller)
4894 push_cfun (DECL_STRUCT_FUNCTION (cs->caller->decl));
4896 if (dump_file)
4897 fprintf (dump_file, "Adjusting call %s/%i -> %s/%i\n",
4898 xstrdup (cs->caller->name ()),
4899 cs->caller->order,
4900 xstrdup (cs->callee->name ()),
4901 cs->callee->order);
4903 ipa_modify_call_arguments (cs, cs->call_stmt, *adjustments);
4905 pop_cfun ();
4908 for (cs = node->callers; cs; cs = cs->next_caller)
4909 if (bitmap_set_bit (recomputed_callers, cs->caller->uid)
4910 && gimple_in_ssa_p (DECL_STRUCT_FUNCTION (cs->caller->decl)))
4911 compute_inline_parameters (cs->caller, true);
4912 BITMAP_FREE (recomputed_callers);
4914 return true;
4917 /* Convert all callers of NODE to pass parameters as given in ADJUSTMENTS. */
4919 static void
4920 convert_callers (struct cgraph_node *node, tree old_decl,
4921 ipa_parm_adjustment_vec adjustments)
4923 basic_block this_block;
4925 node->call_for_symbol_thunks_and_aliases (convert_callers_for_node,
4926 &adjustments, false);
4928 if (!encountered_recursive_call)
4929 return;
4931 FOR_EACH_BB_FN (this_block, cfun)
4933 gimple_stmt_iterator gsi;
4935 for (gsi = gsi_start_bb (this_block); !gsi_end_p (gsi); gsi_next (&gsi))
4937 gcall *stmt;
4938 tree call_fndecl;
4939 stmt = dyn_cast <gcall *> (gsi_stmt (gsi));
4940 if (!stmt)
4941 continue;
4942 call_fndecl = gimple_call_fndecl (stmt);
4943 if (call_fndecl == old_decl)
4945 if (dump_file)
4946 fprintf (dump_file, "Adjusting recursive call");
4947 gimple_call_set_fndecl (stmt, node->decl);
4948 ipa_modify_call_arguments (NULL, stmt, adjustments);
4953 return;
4956 /* Perform all the modification required in IPA-SRA for NODE to have parameters
4957 as given in ADJUSTMENTS. Return true iff the CFG has been changed. */
4959 static bool
4960 modify_function (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments)
4962 struct cgraph_node *new_node;
4963 bool cfg_changed;
4965 cgraph_edge::rebuild_edges ();
4966 free_dominance_info (CDI_DOMINATORS);
4967 pop_cfun ();
4969 /* This must be done after rebuilding cgraph edges for node above.
4970 Otherwise any recursive calls to node that are recorded in
4971 redirect_callers will be corrupted. */
4972 vec<cgraph_edge *> redirect_callers = node->collect_callers ();
4973 new_node = node->create_version_clone_with_body (redirect_callers, NULL,
4974 NULL, false, NULL, NULL,
4975 "isra");
4976 redirect_callers.release ();
4978 push_cfun (DECL_STRUCT_FUNCTION (new_node->decl));
4979 ipa_modify_formal_parameters (current_function_decl, adjustments);
4980 cfg_changed = ipa_sra_modify_function_body (adjustments);
4981 sra_ipa_reset_debug_stmts (adjustments);
4982 convert_callers (new_node, node->decl, adjustments);
4983 new_node->make_local ();
4984 return cfg_changed;
4987 /* If NODE has a caller, return true. */
4989 static bool
4990 has_caller_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
4992 if (node->callers)
4993 return true;
4994 return false;
4997 /* Return false the function is apparently unsuitable for IPA-SRA based on it's
4998 attributes, return true otherwise. NODE is the cgraph node of the current
4999 function. */
5001 static bool
5002 ipa_sra_preliminary_function_checks (struct cgraph_node *node)
5004 if (!node->can_be_local_p ())
5006 if (dump_file)
5007 fprintf (dump_file, "Function not local to this compilation unit.\n");
5008 return false;
5011 if (!node->local.can_change_signature)
5013 if (dump_file)
5014 fprintf (dump_file, "Function can not change signature.\n");
5015 return false;
5018 if (!tree_versionable_function_p (node->decl))
5020 if (dump_file)
5021 fprintf (dump_file, "Function is not versionable.\n");
5022 return false;
5025 if (!opt_for_fn (node->decl, optimize)
5026 || !opt_for_fn (node->decl, flag_ipa_sra))
5028 if (dump_file)
5029 fprintf (dump_file, "Function not optimized.\n");
5030 return false;
5033 if (DECL_VIRTUAL_P (current_function_decl))
5035 if (dump_file)
5036 fprintf (dump_file, "Function is a virtual method.\n");
5037 return false;
5040 if ((DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl))
5041 && inline_summaries->get (node)->size >= MAX_INLINE_INSNS_AUTO)
5043 if (dump_file)
5044 fprintf (dump_file, "Function too big to be made truly local.\n");
5045 return false;
5048 if (!node->call_for_symbol_thunks_and_aliases (has_caller_p, NULL, true))
5050 if (dump_file)
5051 fprintf (dump_file,
5052 "Function has no callers in this compilation unit.\n");
5053 return false;
5056 if (cfun->stdarg)
5058 if (dump_file)
5059 fprintf (dump_file, "Function uses stdarg. \n");
5060 return false;
5063 if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl)))
5064 return false;
5066 if (DECL_DISREGARD_INLINE_LIMITS (node->decl))
5068 if (dump_file)
5069 fprintf (dump_file, "Always inline function will be inlined "
5070 "anyway. \n");
5071 return false;
5074 return true;
5077 /* Perform early interprocedural SRA. */
5079 static unsigned int
5080 ipa_early_sra (void)
5082 struct cgraph_node *node = cgraph_node::get (current_function_decl);
5083 ipa_parm_adjustment_vec adjustments;
5084 int ret = 0;
5086 if (!ipa_sra_preliminary_function_checks (node))
5087 return 0;
5089 sra_initialize ();
5090 sra_mode = SRA_MODE_EARLY_IPA;
5092 if (!find_param_candidates ())
5094 if (dump_file)
5095 fprintf (dump_file, "Function has no IPA-SRA candidates.\n");
5096 goto simple_out;
5099 if (node->call_for_symbol_thunks_and_aliases
5100 (some_callers_have_mismatched_arguments_p, NULL, true))
5102 if (dump_file)
5103 fprintf (dump_file, "There are callers with insufficient number of "
5104 "arguments or arguments with type mismatches.\n");
5105 goto simple_out;
5108 bb_dereferences = XCNEWVEC (HOST_WIDE_INT,
5109 func_param_count
5110 * last_basic_block_for_fn (cfun));
5111 final_bbs = BITMAP_ALLOC (NULL);
5113 scan_function ();
5114 if (encountered_apply_args)
5116 if (dump_file)
5117 fprintf (dump_file, "Function calls __builtin_apply_args().\n");
5118 goto out;
5121 if (encountered_unchangable_recursive_call)
5123 if (dump_file)
5124 fprintf (dump_file, "Function calls itself with insufficient "
5125 "number of arguments.\n");
5126 goto out;
5129 adjustments = analyze_all_param_acesses ();
5130 if (!adjustments.exists ())
5131 goto out;
5132 if (dump_file)
5133 ipa_dump_param_adjustments (dump_file, adjustments, current_function_decl);
5135 if (modify_function (node, adjustments))
5136 ret = TODO_update_ssa | TODO_cleanup_cfg;
5137 else
5138 ret = TODO_update_ssa;
5139 adjustments.release ();
5141 statistics_counter_event (cfun, "Unused parameters deleted",
5142 sra_stats.deleted_unused_parameters);
5143 statistics_counter_event (cfun, "Scalar parameters converted to by-value",
5144 sra_stats.scalar_by_ref_to_by_val);
5145 statistics_counter_event (cfun, "Aggregate parameters broken up",
5146 sra_stats.aggregate_params_reduced);
5147 statistics_counter_event (cfun, "Aggregate parameter components created",
5148 sra_stats.param_reductions_created);
5150 out:
5151 BITMAP_FREE (final_bbs);
5152 free (bb_dereferences);
5153 simple_out:
5154 sra_deinitialize ();
5155 return ret;
5158 namespace {
5160 const pass_data pass_data_early_ipa_sra =
5162 GIMPLE_PASS, /* type */
5163 "eipa_sra", /* name */
5164 OPTGROUP_NONE, /* optinfo_flags */
5165 TV_IPA_SRA, /* tv_id */
5166 0, /* properties_required */
5167 0, /* properties_provided */
5168 0, /* properties_destroyed */
5169 0, /* todo_flags_start */
5170 TODO_dump_symtab, /* todo_flags_finish */
5173 class pass_early_ipa_sra : public gimple_opt_pass
5175 public:
5176 pass_early_ipa_sra (gcc::context *ctxt)
5177 : gimple_opt_pass (pass_data_early_ipa_sra, ctxt)
5180 /* opt_pass methods: */
5181 virtual bool gate (function *) { return flag_ipa_sra && dbg_cnt (eipa_sra); }
5182 virtual unsigned int execute (function *) { return ipa_early_sra (); }
5184 }; // class pass_early_ipa_sra
5186 } // anon namespace
5188 gimple_opt_pass *
5189 make_pass_early_ipa_sra (gcc::context *ctxt)
5191 return new pass_early_ipa_sra (ctxt);