PR libstdc++/66354
[official-gcc.git] / gcc / tree-sra.c
blobd799751da30796e24a1f2079eb0b74c84ac8aea5
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 "mem-stats.h"
78 #include "hash-map.h"
79 #include "hash-table.h"
80 #include "alloc-pool.h"
81 #include "tm.h"
82 #include "hash-set.h"
83 #include "machmode.h"
84 #include "vec.h"
85 #include "double-int.h"
86 #include "input.h"
87 #include "alias.h"
88 #include "symtab.h"
89 #include "wide-int.h"
90 #include "inchash.h"
91 #include "tree.h"
92 #include "fold-const.h"
93 #include "predict.h"
94 #include "hard-reg-set.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 "hashtab.h"
118 #include "rtl.h"
119 #include "flags.h"
120 #include "statistics.h"
121 #include "real.h"
122 #include "fixed-value.h"
123 #include "insn-config.h"
124 #include "expmed.h"
125 #include "dojump.h"
126 #include "explow.h"
127 #include "calls.h"
128 #include "emit-rtl.h"
129 #include "varasm.h"
130 #include "stmt.h"
131 #include "expr.h"
132 #include "tree-dfa.h"
133 #include "tree-ssa.h"
134 #include "tree-pass.h"
135 #include "plugin-api.h"
136 #include "ipa-ref.h"
137 #include "cgraph.h"
138 #include "symbol-summary.h"
139 #include "ipa-prop.h"
140 #include "params.h"
141 #include "target.h"
142 #include "dbgcnt.h"
143 #include "tree-inline.h"
144 #include "gimple-pretty-print.h"
145 #include "ipa-inline.h"
146 #include "ipa-utils.h"
147 #include "builtins.h"
149 /* Enumeration of all aggregate reductions we can do. */
150 enum sra_mode { SRA_MODE_EARLY_IPA, /* early call regularization */
151 SRA_MODE_EARLY_INTRA, /* early intraprocedural SRA */
152 SRA_MODE_INTRA }; /* late intraprocedural SRA */
154 /* Global variable describing which aggregate reduction we are performing at
155 the moment. */
156 static enum sra_mode sra_mode;
158 struct assign_link;
160 /* ACCESS represents each access to an aggregate variable (as a whole or a
161 part). It can also represent a group of accesses that refer to exactly the
162 same fragment of an aggregate (i.e. those that have exactly the same offset
163 and size). Such representatives for a single aggregate, once determined,
164 are linked in a linked list and have the group fields set.
166 Moreover, when doing intraprocedural SRA, a tree is built from those
167 representatives (by the means of first_child and next_sibling pointers), in
168 which all items in a subtree are "within" the root, i.e. their offset is
169 greater or equal to offset of the root and offset+size is smaller or equal
170 to offset+size of the root. Children of an access are sorted by offset.
172 Note that accesses to parts of vector and complex number types always
173 represented by an access to the whole complex number or a vector. It is a
174 duty of the modifying functions to replace them appropriately. */
176 struct access
178 /* Values returned by `get_ref_base_and_extent' for each component reference
179 If EXPR isn't a component reference just set `BASE = EXPR', `OFFSET = 0',
180 `SIZE = TREE_SIZE (TREE_TYPE (expr))'. */
181 HOST_WIDE_INT offset;
182 HOST_WIDE_INT size;
183 tree base;
185 /* Expression. It is context dependent so do not use it to create new
186 expressions to access the original aggregate. See PR 42154 for a
187 testcase. */
188 tree expr;
189 /* Type. */
190 tree type;
192 /* The statement this access belongs to. */
193 gimple stmt;
195 /* Next group representative for this aggregate. */
196 struct access *next_grp;
198 /* Pointer to the group representative. Pointer to itself if the struct is
199 the representative. */
200 struct access *group_representative;
202 /* If this access has any children (in terms of the definition above), this
203 points to the first one. */
204 struct access *first_child;
206 /* In intraprocedural SRA, pointer to the next sibling in the access tree as
207 described above. In IPA-SRA this is a pointer to the next access
208 belonging to the same group (having the same representative). */
209 struct access *next_sibling;
211 /* Pointers to the first and last element in the linked list of assign
212 links. */
213 struct assign_link *first_link, *last_link;
215 /* Pointer to the next access in the work queue. */
216 struct access *next_queued;
218 /* Replacement variable for this access "region." Never to be accessed
219 directly, always only by the means of get_access_replacement() and only
220 when grp_to_be_replaced flag is set. */
221 tree replacement_decl;
223 /* Is this particular access write access? */
224 unsigned write : 1;
226 /* Is this access an access to a non-addressable field? */
227 unsigned non_addressable : 1;
229 /* Is this access currently in the work queue? */
230 unsigned grp_queued : 1;
232 /* Does this group contain a write access? This flag is propagated down the
233 access tree. */
234 unsigned grp_write : 1;
236 /* Does this group contain a read access? This flag is propagated down the
237 access tree. */
238 unsigned grp_read : 1;
240 /* Does this group contain a read access that comes from an assignment
241 statement? This flag is propagated down the access tree. */
242 unsigned grp_assignment_read : 1;
244 /* Does this group contain a write access that comes from an assignment
245 statement? This flag is propagated down the access tree. */
246 unsigned grp_assignment_write : 1;
248 /* Does this group contain a read access through a scalar type? This flag is
249 not propagated in the access tree in any direction. */
250 unsigned grp_scalar_read : 1;
252 /* Does this group contain a write access through a scalar type? This flag
253 is not propagated in the access tree in any direction. */
254 unsigned grp_scalar_write : 1;
256 /* Is this access an artificial one created to scalarize some record
257 entirely? */
258 unsigned grp_total_scalarization : 1;
260 /* Other passes of the analysis use this bit to make function
261 analyze_access_subtree create scalar replacements for this group if
262 possible. */
263 unsigned grp_hint : 1;
265 /* Is the subtree rooted in this access fully covered by scalar
266 replacements? */
267 unsigned grp_covered : 1;
269 /* If set to true, this access and all below it in an access tree must not be
270 scalarized. */
271 unsigned grp_unscalarizable_region : 1;
273 /* Whether data have been written to parts of the aggregate covered by this
274 access which is not to be scalarized. This flag is propagated up in the
275 access tree. */
276 unsigned grp_unscalarized_data : 1;
278 /* Does this access and/or group contain a write access through a
279 BIT_FIELD_REF? */
280 unsigned grp_partial_lhs : 1;
282 /* Set when a scalar replacement should be created for this variable. */
283 unsigned grp_to_be_replaced : 1;
285 /* Set when we want a replacement for the sole purpose of having it in
286 generated debug statements. */
287 unsigned grp_to_be_debug_replaced : 1;
289 /* Should TREE_NO_WARNING of a replacement be set? */
290 unsigned grp_no_warning : 1;
292 /* Is it possible that the group refers to data which might be (directly or
293 otherwise) modified? */
294 unsigned grp_maybe_modified : 1;
296 /* Set when this is a representative of a pointer to scalar (i.e. by
297 reference) parameter which we consider for turning into a plain scalar
298 (i.e. a by value parameter). */
299 unsigned grp_scalar_ptr : 1;
301 /* Set when we discover that this pointer is not safe to dereference in the
302 caller. */
303 unsigned grp_not_necessarilly_dereferenced : 1;
306 typedef struct access *access_p;
309 /* Alloc pool for allocating access structures. */
310 static alloc_pool access_pool;
312 /* A structure linking lhs and rhs accesses from an aggregate assignment. They
313 are used to propagate subaccesses from rhs to lhs as long as they don't
314 conflict with what is already there. */
315 struct assign_link
317 struct access *lacc, *racc;
318 struct assign_link *next;
321 /* Alloc pool for allocating assign link structures. */
322 static alloc_pool link_pool;
324 /* Base (tree) -> Vector (vec<access_p> *) map. */
325 static hash_map<tree, auto_vec<access_p> > *base_access_vec;
327 /* Candidate hash table helpers. */
329 struct uid_decl_hasher : typed_noop_remove <tree_node>
331 typedef tree_node *value_type;
332 typedef tree_node *compare_type;
333 static inline hashval_t hash (const tree_node *);
334 static inline bool equal (const tree_node *, const tree_node *);
337 /* Hash a tree in a uid_decl_map. */
339 inline hashval_t
340 uid_decl_hasher::hash (const tree_node *item)
342 return item->decl_minimal.uid;
345 /* Return true if the DECL_UID in both trees are equal. */
347 inline bool
348 uid_decl_hasher::equal (const tree_node *a, const tree_node *b)
350 return (a->decl_minimal.uid == b->decl_minimal.uid);
353 /* Set of candidates. */
354 static bitmap candidate_bitmap;
355 static hash_table<uid_decl_hasher> *candidates;
357 /* For a candidate UID return the candidates decl. */
359 static inline tree
360 candidate (unsigned uid)
362 tree_node t;
363 t.decl_minimal.uid = uid;
364 return candidates->find_with_hash (&t, static_cast <hashval_t> (uid));
367 /* Bitmap of candidates which we should try to entirely scalarize away and
368 those which cannot be (because they are and need be used as a whole). */
369 static bitmap should_scalarize_away_bitmap, cannot_scalarize_away_bitmap;
371 /* Obstack for creation of fancy names. */
372 static struct obstack name_obstack;
374 /* Head of a linked list of accesses that need to have its subaccesses
375 propagated to their assignment counterparts. */
376 static struct access *work_queue_head;
378 /* Number of parameters of the analyzed function when doing early ipa SRA. */
379 static int func_param_count;
381 /* scan_function sets the following to true if it encounters a call to
382 __builtin_apply_args. */
383 static bool encountered_apply_args;
385 /* Set by scan_function when it finds a recursive call. */
386 static bool encountered_recursive_call;
388 /* Set by scan_function when it finds a recursive call with less actual
389 arguments than formal parameters.. */
390 static bool encountered_unchangable_recursive_call;
392 /* This is a table in which for each basic block and parameter there is a
393 distance (offset + size) in that parameter which is dereferenced and
394 accessed in that BB. */
395 static HOST_WIDE_INT *bb_dereferences;
396 /* Bitmap of BBs that can cause the function to "stop" progressing by
397 returning, throwing externally, looping infinitely or calling a function
398 which might abort etc.. */
399 static bitmap final_bbs;
401 /* Representative of no accesses at all. */
402 static struct access no_accesses_representant;
404 /* Predicate to test the special value. */
406 static inline bool
407 no_accesses_p (struct access *access)
409 return access == &no_accesses_representant;
412 /* Dump contents of ACCESS to file F in a human friendly way. If GRP is true,
413 representative fields are dumped, otherwise those which only describe the
414 individual access are. */
416 static struct
418 /* Number of processed aggregates is readily available in
419 analyze_all_variable_accesses and so is not stored here. */
421 /* Number of created scalar replacements. */
422 int replacements;
424 /* Number of times sra_modify_expr or sra_modify_assign themselves changed an
425 expression. */
426 int exprs;
428 /* Number of statements created by generate_subtree_copies. */
429 int subtree_copies;
431 /* Number of statements created by load_assign_lhs_subreplacements. */
432 int subreplacements;
434 /* Number of times sra_modify_assign has deleted a statement. */
435 int deleted;
437 /* Number of times sra_modify_assign has to deal with subaccesses of LHS and
438 RHS reparately due to type conversions or nonexistent matching
439 references. */
440 int separate_lhs_rhs_handling;
442 /* Number of parameters that were removed because they were unused. */
443 int deleted_unused_parameters;
445 /* Number of scalars passed as parameters by reference that have been
446 converted to be passed by value. */
447 int scalar_by_ref_to_by_val;
449 /* Number of aggregate parameters that were replaced by one or more of their
450 components. */
451 int aggregate_params_reduced;
453 /* Numbber of components created when splitting aggregate parameters. */
454 int param_reductions_created;
455 } sra_stats;
457 static void
458 dump_access (FILE *f, struct access *access, bool grp)
460 fprintf (f, "access { ");
461 fprintf (f, "base = (%d)'", DECL_UID (access->base));
462 print_generic_expr (f, access->base, 0);
463 fprintf (f, "', offset = " HOST_WIDE_INT_PRINT_DEC, access->offset);
464 fprintf (f, ", size = " HOST_WIDE_INT_PRINT_DEC, access->size);
465 fprintf (f, ", expr = ");
466 print_generic_expr (f, access->expr, 0);
467 fprintf (f, ", type = ");
468 print_generic_expr (f, access->type, 0);
469 if (grp)
470 fprintf (f, ", grp_read = %d, grp_write = %d, grp_assignment_read = %d, "
471 "grp_assignment_write = %d, grp_scalar_read = %d, "
472 "grp_scalar_write = %d, grp_total_scalarization = %d, "
473 "grp_hint = %d, grp_covered = %d, "
474 "grp_unscalarizable_region = %d, grp_unscalarized_data = %d, "
475 "grp_partial_lhs = %d, grp_to_be_replaced = %d, "
476 "grp_to_be_debug_replaced = %d, grp_maybe_modified = %d, "
477 "grp_not_necessarilly_dereferenced = %d\n",
478 access->grp_read, access->grp_write, access->grp_assignment_read,
479 access->grp_assignment_write, access->grp_scalar_read,
480 access->grp_scalar_write, access->grp_total_scalarization,
481 access->grp_hint, access->grp_covered,
482 access->grp_unscalarizable_region, access->grp_unscalarized_data,
483 access->grp_partial_lhs, access->grp_to_be_replaced,
484 access->grp_to_be_debug_replaced, access->grp_maybe_modified,
485 access->grp_not_necessarilly_dereferenced);
486 else
487 fprintf (f, ", write = %d, grp_total_scalarization = %d, "
488 "grp_partial_lhs = %d\n",
489 access->write, access->grp_total_scalarization,
490 access->grp_partial_lhs);
493 /* Dump a subtree rooted in ACCESS to file F, indent by LEVEL. */
495 static void
496 dump_access_tree_1 (FILE *f, struct access *access, int level)
500 int i;
502 for (i = 0; i < level; i++)
503 fputs ("* ", dump_file);
505 dump_access (f, access, true);
507 if (access->first_child)
508 dump_access_tree_1 (f, access->first_child, level + 1);
510 access = access->next_sibling;
512 while (access);
515 /* Dump all access trees for a variable, given the pointer to the first root in
516 ACCESS. */
518 static void
519 dump_access_tree (FILE *f, struct access *access)
521 for (; access; access = access->next_grp)
522 dump_access_tree_1 (f, access, 0);
525 /* Return true iff ACC is non-NULL and has subaccesses. */
527 static inline bool
528 access_has_children_p (struct access *acc)
530 return acc && acc->first_child;
533 /* Return true iff ACC is (partly) covered by at least one replacement. */
535 static bool
536 access_has_replacements_p (struct access *acc)
538 struct access *child;
539 if (acc->grp_to_be_replaced)
540 return true;
541 for (child = acc->first_child; child; child = child->next_sibling)
542 if (access_has_replacements_p (child))
543 return true;
544 return false;
547 /* Return a vector of pointers to accesses for the variable given in BASE or
548 NULL if there is none. */
550 static vec<access_p> *
551 get_base_access_vector (tree base)
553 return base_access_vec->get (base);
556 /* Find an access with required OFFSET and SIZE in a subtree of accesses rooted
557 in ACCESS. Return NULL if it cannot be found. */
559 static struct access *
560 find_access_in_subtree (struct access *access, HOST_WIDE_INT offset,
561 HOST_WIDE_INT size)
563 while (access && (access->offset != offset || access->size != size))
565 struct access *child = access->first_child;
567 while (child && (child->offset + child->size <= offset))
568 child = child->next_sibling;
569 access = child;
572 return access;
575 /* Return the first group representative for DECL or NULL if none exists. */
577 static struct access *
578 get_first_repr_for_decl (tree base)
580 vec<access_p> *access_vec;
582 access_vec = get_base_access_vector (base);
583 if (!access_vec)
584 return NULL;
586 return (*access_vec)[0];
589 /* Find an access representative for the variable BASE and given OFFSET and
590 SIZE. Requires that access trees have already been built. Return NULL if
591 it cannot be found. */
593 static struct access *
594 get_var_base_offset_size_access (tree base, HOST_WIDE_INT offset,
595 HOST_WIDE_INT size)
597 struct access *access;
599 access = get_first_repr_for_decl (base);
600 while (access && (access->offset + access->size <= offset))
601 access = access->next_grp;
602 if (!access)
603 return NULL;
605 return find_access_in_subtree (access, offset, size);
608 /* Add LINK to the linked list of assign links of RACC. */
609 static void
610 add_link_to_rhs (struct access *racc, struct assign_link *link)
612 gcc_assert (link->racc == racc);
614 if (!racc->first_link)
616 gcc_assert (!racc->last_link);
617 racc->first_link = link;
619 else
620 racc->last_link->next = link;
622 racc->last_link = link;
623 link->next = NULL;
626 /* Move all link structures in their linked list in OLD_RACC to the linked list
627 in NEW_RACC. */
628 static void
629 relink_to_new_repr (struct access *new_racc, struct access *old_racc)
631 if (!old_racc->first_link)
633 gcc_assert (!old_racc->last_link);
634 return;
637 if (new_racc->first_link)
639 gcc_assert (!new_racc->last_link->next);
640 gcc_assert (!old_racc->last_link || !old_racc->last_link->next);
642 new_racc->last_link->next = old_racc->first_link;
643 new_racc->last_link = old_racc->last_link;
645 else
647 gcc_assert (!new_racc->last_link);
649 new_racc->first_link = old_racc->first_link;
650 new_racc->last_link = old_racc->last_link;
652 old_racc->first_link = old_racc->last_link = NULL;
655 /* Add ACCESS to the work queue (which is actually a stack). */
657 static void
658 add_access_to_work_queue (struct access *access)
660 if (!access->grp_queued)
662 gcc_assert (!access->next_queued);
663 access->next_queued = work_queue_head;
664 access->grp_queued = 1;
665 work_queue_head = access;
669 /* Pop an access from the work queue, and return it, assuming there is one. */
671 static struct access *
672 pop_access_from_work_queue (void)
674 struct access *access = work_queue_head;
676 work_queue_head = access->next_queued;
677 access->next_queued = NULL;
678 access->grp_queued = 0;
679 return access;
683 /* Allocate necessary structures. */
685 static void
686 sra_initialize (void)
688 candidate_bitmap = BITMAP_ALLOC (NULL);
689 candidates = new hash_table<uid_decl_hasher>
690 (vec_safe_length (cfun->local_decls) / 2);
691 should_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
692 cannot_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
693 gcc_obstack_init (&name_obstack);
694 access_pool = create_alloc_pool ("SRA accesses", sizeof (struct access), 16);
695 link_pool = create_alloc_pool ("SRA links", sizeof (struct assign_link), 16);
696 base_access_vec = new hash_map<tree, auto_vec<access_p> >;
697 memset (&sra_stats, 0, sizeof (sra_stats));
698 encountered_apply_args = false;
699 encountered_recursive_call = false;
700 encountered_unchangable_recursive_call = false;
703 /* Deallocate all general structures. */
705 static void
706 sra_deinitialize (void)
708 BITMAP_FREE (candidate_bitmap);
709 delete candidates;
710 candidates = NULL;
711 BITMAP_FREE (should_scalarize_away_bitmap);
712 BITMAP_FREE (cannot_scalarize_away_bitmap);
713 free_alloc_pool (access_pool);
714 free_alloc_pool (link_pool);
715 obstack_free (&name_obstack, NULL);
717 delete base_access_vec;
720 /* Remove DECL from candidates for SRA and write REASON to the dump file if
721 there is one. */
722 static void
723 disqualify_candidate (tree decl, const char *reason)
725 if (bitmap_clear_bit (candidate_bitmap, DECL_UID (decl)))
726 candidates->remove_elt_with_hash (decl, DECL_UID (decl));
728 if (dump_file && (dump_flags & TDF_DETAILS))
730 fprintf (dump_file, "! Disqualifying ");
731 print_generic_expr (dump_file, decl, 0);
732 fprintf (dump_file, " - %s\n", reason);
736 /* Return true iff the type contains a field or an element which does not allow
737 scalarization. */
739 static bool
740 type_internals_preclude_sra_p (tree type, const char **msg)
742 tree fld;
743 tree et;
745 switch (TREE_CODE (type))
747 case RECORD_TYPE:
748 case UNION_TYPE:
749 case QUAL_UNION_TYPE:
750 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
751 if (TREE_CODE (fld) == FIELD_DECL)
753 tree ft = TREE_TYPE (fld);
755 if (TREE_THIS_VOLATILE (fld))
757 *msg = "volatile structure field";
758 return true;
760 if (!DECL_FIELD_OFFSET (fld))
762 *msg = "no structure field offset";
763 return true;
765 if (!DECL_SIZE (fld))
767 *msg = "zero structure field size";
768 return true;
770 if (!tree_fits_uhwi_p (DECL_FIELD_OFFSET (fld)))
772 *msg = "structure field offset not fixed";
773 return true;
775 if (!tree_fits_uhwi_p (DECL_SIZE (fld)))
777 *msg = "structure field size not fixed";
778 return true;
780 if (!tree_fits_shwi_p (bit_position (fld)))
782 *msg = "structure field size too big";
783 return true;
785 if (AGGREGATE_TYPE_P (ft)
786 && int_bit_position (fld) % BITS_PER_UNIT != 0)
788 *msg = "structure field is bit field";
789 return true;
792 if (AGGREGATE_TYPE_P (ft) && type_internals_preclude_sra_p (ft, msg))
793 return true;
796 return false;
798 case ARRAY_TYPE:
799 et = TREE_TYPE (type);
801 if (TYPE_VOLATILE (et))
803 *msg = "element type is volatile";
804 return true;
807 if (AGGREGATE_TYPE_P (et) && type_internals_preclude_sra_p (et, msg))
808 return true;
810 return false;
812 default:
813 return false;
817 /* If T is an SSA_NAME, return NULL if it is not a default def or return its
818 base variable if it is. Return T if it is not an SSA_NAME. */
820 static tree
821 get_ssa_base_param (tree t)
823 if (TREE_CODE (t) == SSA_NAME)
825 if (SSA_NAME_IS_DEFAULT_DEF (t))
826 return SSA_NAME_VAR (t);
827 else
828 return NULL_TREE;
830 return t;
833 /* Mark a dereference of BASE of distance DIST in a basic block tht STMT
834 belongs to, unless the BB has already been marked as a potentially
835 final. */
837 static void
838 mark_parm_dereference (tree base, HOST_WIDE_INT dist, gimple stmt)
840 basic_block bb = gimple_bb (stmt);
841 int idx, parm_index = 0;
842 tree parm;
844 if (bitmap_bit_p (final_bbs, bb->index))
845 return;
847 for (parm = DECL_ARGUMENTS (current_function_decl);
848 parm && parm != base;
849 parm = DECL_CHAIN (parm))
850 parm_index++;
852 gcc_assert (parm_index < func_param_count);
854 idx = bb->index * func_param_count + parm_index;
855 if (bb_dereferences[idx] < dist)
856 bb_dereferences[idx] = dist;
859 /* Allocate an access structure for BASE, OFFSET and SIZE, clear it, fill in
860 the three fields. Also add it to the vector of accesses corresponding to
861 the base. Finally, return the new access. */
863 static struct access *
864 create_access_1 (tree base, HOST_WIDE_INT offset, HOST_WIDE_INT size)
866 struct access *access;
868 access = (struct access *) pool_alloc (access_pool);
869 memset (access, 0, sizeof (struct access));
870 access->base = base;
871 access->offset = offset;
872 access->size = size;
874 base_access_vec->get_or_insert (base).safe_push (access);
876 return access;
879 /* Create and insert access for EXPR. Return created access, or NULL if it is
880 not possible. */
882 static struct access *
883 create_access (tree expr, gimple stmt, bool write)
885 struct access *access;
886 HOST_WIDE_INT offset, size, max_size;
887 tree base = expr;
888 bool ptr, unscalarizable_region = false;
890 base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
892 if (sra_mode == SRA_MODE_EARLY_IPA
893 && TREE_CODE (base) == MEM_REF)
895 base = get_ssa_base_param (TREE_OPERAND (base, 0));
896 if (!base)
897 return NULL;
898 ptr = true;
900 else
901 ptr = false;
903 if (!DECL_P (base) || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
904 return NULL;
906 if (sra_mode == SRA_MODE_EARLY_IPA)
908 if (size < 0 || size != max_size)
910 disqualify_candidate (base, "Encountered a variable sized access.");
911 return NULL;
913 if (TREE_CODE (expr) == COMPONENT_REF
914 && DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
916 disqualify_candidate (base, "Encountered a bit-field access.");
917 return NULL;
919 gcc_checking_assert ((offset % BITS_PER_UNIT) == 0);
921 if (ptr)
922 mark_parm_dereference (base, offset + size, stmt);
924 else
926 if (size != max_size)
928 size = max_size;
929 unscalarizable_region = true;
931 if (size < 0)
933 disqualify_candidate (base, "Encountered an unconstrained access.");
934 return NULL;
938 access = create_access_1 (base, offset, size);
939 access->expr = expr;
940 access->type = TREE_TYPE (expr);
941 access->write = write;
942 access->grp_unscalarizable_region = unscalarizable_region;
943 access->stmt = stmt;
945 if (TREE_CODE (expr) == COMPONENT_REF
946 && DECL_NONADDRESSABLE_P (TREE_OPERAND (expr, 1)))
947 access->non_addressable = 1;
949 return access;
953 /* Return true iff TYPE is a RECORD_TYPE with fields that are either of gimple
954 register types or (recursively) records with only these two kinds of fields.
955 It also returns false if any of these records contains a bit-field. */
957 static bool
958 type_consists_of_records_p (tree type)
960 tree fld;
962 if (TREE_CODE (type) != RECORD_TYPE)
963 return false;
965 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
966 if (TREE_CODE (fld) == FIELD_DECL)
968 tree ft = TREE_TYPE (fld);
970 if (DECL_BIT_FIELD (fld))
971 return false;
973 if (!is_gimple_reg_type (ft)
974 && !type_consists_of_records_p (ft))
975 return false;
978 return true;
981 /* Create total_scalarization accesses for all scalar type fields in DECL that
982 must be of a RECORD_TYPE conforming to type_consists_of_records_p. BASE
983 must be the top-most VAR_DECL representing the variable, OFFSET must be the
984 offset of DECL within BASE. REF must be the memory reference expression for
985 the given decl. */
987 static void
988 completely_scalarize_record (tree base, tree decl, HOST_WIDE_INT offset,
989 tree ref)
991 tree fld, decl_type = TREE_TYPE (decl);
993 for (fld = TYPE_FIELDS (decl_type); fld; fld = DECL_CHAIN (fld))
994 if (TREE_CODE (fld) == FIELD_DECL)
996 HOST_WIDE_INT pos = offset + int_bit_position (fld);
997 tree ft = TREE_TYPE (fld);
998 tree nref = build3 (COMPONENT_REF, TREE_TYPE (fld), ref, fld,
999 NULL_TREE);
1001 if (is_gimple_reg_type (ft))
1003 struct access *access;
1004 HOST_WIDE_INT size;
1006 size = tree_to_uhwi (DECL_SIZE (fld));
1007 access = create_access_1 (base, pos, size);
1008 access->expr = nref;
1009 access->type = ft;
1010 access->grp_total_scalarization = 1;
1011 /* Accesses for intraprocedural SRA can have their stmt NULL. */
1013 else
1014 completely_scalarize_record (base, fld, pos, nref);
1018 /* Create total_scalarization accesses for all scalar type fields in VAR and
1019 for VAR a a whole. VAR must be of a RECORD_TYPE conforming to
1020 type_consists_of_records_p. */
1022 static void
1023 completely_scalarize_var (tree var)
1025 HOST_WIDE_INT size = tree_to_uhwi (DECL_SIZE (var));
1026 struct access *access;
1028 access = create_access_1 (var, 0, size);
1029 access->expr = var;
1030 access->type = TREE_TYPE (var);
1031 access->grp_total_scalarization = 1;
1033 completely_scalarize_record (var, var, 0, var);
1036 /* Return true if REF has an VIEW_CONVERT_EXPR somewhere in it. */
1038 static inline bool
1039 contains_view_convert_expr_p (const_tree ref)
1041 while (handled_component_p (ref))
1043 if (TREE_CODE (ref) == VIEW_CONVERT_EXPR)
1044 return true;
1045 ref = TREE_OPERAND (ref, 0);
1048 return false;
1051 /* Search the given tree for a declaration by skipping handled components and
1052 exclude it from the candidates. */
1054 static void
1055 disqualify_base_of_expr (tree t, const char *reason)
1057 t = get_base_address (t);
1058 if (sra_mode == SRA_MODE_EARLY_IPA
1059 && TREE_CODE (t) == MEM_REF)
1060 t = get_ssa_base_param (TREE_OPERAND (t, 0));
1062 if (t && DECL_P (t))
1063 disqualify_candidate (t, reason);
1066 /* Scan expression EXPR and create access structures for all accesses to
1067 candidates for scalarization. Return the created access or NULL if none is
1068 created. */
1070 static struct access *
1071 build_access_from_expr_1 (tree expr, gimple stmt, bool write)
1073 struct access *ret = NULL;
1074 bool partial_ref;
1076 if (TREE_CODE (expr) == BIT_FIELD_REF
1077 || TREE_CODE (expr) == IMAGPART_EXPR
1078 || TREE_CODE (expr) == REALPART_EXPR)
1080 expr = TREE_OPERAND (expr, 0);
1081 partial_ref = true;
1083 else
1084 partial_ref = false;
1086 /* We need to dive through V_C_Es in order to get the size of its parameter
1087 and not the result type. Ada produces such statements. We are also
1088 capable of handling the topmost V_C_E but not any of those buried in other
1089 handled components. */
1090 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
1091 expr = TREE_OPERAND (expr, 0);
1093 if (contains_view_convert_expr_p (expr))
1095 disqualify_base_of_expr (expr, "V_C_E under a different handled "
1096 "component.");
1097 return NULL;
1099 if (TREE_THIS_VOLATILE (expr))
1101 disqualify_base_of_expr (expr, "part of a volatile reference.");
1102 return NULL;
1105 switch (TREE_CODE (expr))
1107 case MEM_REF:
1108 if (TREE_CODE (TREE_OPERAND (expr, 0)) != ADDR_EXPR
1109 && sra_mode != SRA_MODE_EARLY_IPA)
1110 return NULL;
1111 /* fall through */
1112 case VAR_DECL:
1113 case PARM_DECL:
1114 case RESULT_DECL:
1115 case COMPONENT_REF:
1116 case ARRAY_REF:
1117 case ARRAY_RANGE_REF:
1118 ret = create_access (expr, stmt, write);
1119 break;
1121 default:
1122 break;
1125 if (write && partial_ref && ret)
1126 ret->grp_partial_lhs = 1;
1128 return ret;
1131 /* Scan expression EXPR and create access structures for all accesses to
1132 candidates for scalarization. Return true if any access has been inserted.
1133 STMT must be the statement from which the expression is taken, WRITE must be
1134 true if the expression is a store and false otherwise. */
1136 static bool
1137 build_access_from_expr (tree expr, gimple stmt, bool write)
1139 struct access *access;
1141 access = build_access_from_expr_1 (expr, stmt, write);
1142 if (access)
1144 /* This means the aggregate is accesses as a whole in a way other than an
1145 assign statement and thus cannot be removed even if we had a scalar
1146 replacement for everything. */
1147 if (cannot_scalarize_away_bitmap)
1148 bitmap_set_bit (cannot_scalarize_away_bitmap, DECL_UID (access->base));
1149 return true;
1151 return false;
1154 /* Return the single non-EH successor edge of BB or NULL if there is none or
1155 more than one. */
1157 static edge
1158 single_non_eh_succ (basic_block bb)
1160 edge e, res = NULL;
1161 edge_iterator ei;
1163 FOR_EACH_EDGE (e, ei, bb->succs)
1164 if (!(e->flags & EDGE_EH))
1166 if (res)
1167 return NULL;
1168 res = e;
1171 return res;
1174 /* Disqualify LHS and RHS for scalarization if STMT has to terminate its BB and
1175 there is no alternative spot where to put statements SRA might need to
1176 generate after it. The spot we are looking for is an edge leading to a
1177 single non-EH successor, if it exists and is indeed single. RHS may be
1178 NULL, in that case ignore it. */
1180 static bool
1181 disqualify_if_bad_bb_terminating_stmt (gimple stmt, tree lhs, tree rhs)
1183 if ((sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
1184 && stmt_ends_bb_p (stmt))
1186 if (single_non_eh_succ (gimple_bb (stmt)))
1187 return false;
1189 disqualify_base_of_expr (lhs, "LHS of a throwing stmt.");
1190 if (rhs)
1191 disqualify_base_of_expr (rhs, "RHS of a throwing stmt.");
1192 return true;
1194 return false;
1197 /* Scan expressions occurring in STMT, create access structures for all accesses
1198 to candidates for scalarization and remove those candidates which occur in
1199 statements or expressions that prevent them from being split apart. Return
1200 true if any access has been inserted. */
1202 static bool
1203 build_accesses_from_assign (gimple stmt)
1205 tree lhs, rhs;
1206 struct access *lacc, *racc;
1208 if (!gimple_assign_single_p (stmt)
1209 /* Scope clobbers don't influence scalarization. */
1210 || gimple_clobber_p (stmt))
1211 return false;
1213 lhs = gimple_assign_lhs (stmt);
1214 rhs = gimple_assign_rhs1 (stmt);
1216 if (disqualify_if_bad_bb_terminating_stmt (stmt, lhs, rhs))
1217 return false;
1219 racc = build_access_from_expr_1 (rhs, stmt, false);
1220 lacc = build_access_from_expr_1 (lhs, stmt, true);
1222 if (lacc)
1223 lacc->grp_assignment_write = 1;
1225 if (racc)
1227 racc->grp_assignment_read = 1;
1228 if (should_scalarize_away_bitmap && !gimple_has_volatile_ops (stmt)
1229 && !is_gimple_reg_type (racc->type))
1230 bitmap_set_bit (should_scalarize_away_bitmap, DECL_UID (racc->base));
1233 if (lacc && racc
1234 && (sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
1235 && !lacc->grp_unscalarizable_region
1236 && !racc->grp_unscalarizable_region
1237 && AGGREGATE_TYPE_P (TREE_TYPE (lhs))
1238 && lacc->size == racc->size
1239 && useless_type_conversion_p (lacc->type, racc->type))
1241 struct assign_link *link;
1243 link = (struct assign_link *) pool_alloc (link_pool);
1244 memset (link, 0, sizeof (struct assign_link));
1246 link->lacc = lacc;
1247 link->racc = racc;
1249 add_link_to_rhs (racc, link);
1252 return lacc || racc;
1255 /* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine
1256 GIMPLE_ASM operands with memory constrains which cannot be scalarized. */
1258 static bool
1259 asm_visit_addr (gimple, tree op, tree, void *)
1261 op = get_base_address (op);
1262 if (op
1263 && DECL_P (op))
1264 disqualify_candidate (op, "Non-scalarizable GIMPLE_ASM operand.");
1266 return false;
1269 /* Return true iff callsite CALL has at least as many actual arguments as there
1270 are formal parameters of the function currently processed by IPA-SRA and
1271 that their types match. */
1273 static inline bool
1274 callsite_arguments_match_p (gimple call)
1276 if (gimple_call_num_args (call) < (unsigned) func_param_count)
1277 return false;
1279 tree parm;
1280 int i;
1281 for (parm = DECL_ARGUMENTS (current_function_decl), i = 0;
1282 parm;
1283 parm = DECL_CHAIN (parm), i++)
1285 tree arg = gimple_call_arg (call, i);
1286 if (!useless_type_conversion_p (TREE_TYPE (parm), TREE_TYPE (arg)))
1287 return false;
1289 return true;
1292 /* Scan function and look for interesting expressions and create access
1293 structures for them. Return true iff any access is created. */
1295 static bool
1296 scan_function (void)
1298 basic_block bb;
1299 bool ret = false;
1301 FOR_EACH_BB_FN (bb, cfun)
1303 gimple_stmt_iterator gsi;
1304 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1306 gimple stmt = gsi_stmt (gsi);
1307 tree t;
1308 unsigned i;
1310 if (final_bbs && stmt_can_throw_external (stmt))
1311 bitmap_set_bit (final_bbs, bb->index);
1312 switch (gimple_code (stmt))
1314 case GIMPLE_RETURN:
1315 t = gimple_return_retval (as_a <greturn *> (stmt));
1316 if (t != NULL_TREE)
1317 ret |= build_access_from_expr (t, stmt, false);
1318 if (final_bbs)
1319 bitmap_set_bit (final_bbs, bb->index);
1320 break;
1322 case GIMPLE_ASSIGN:
1323 ret |= build_accesses_from_assign (stmt);
1324 break;
1326 case GIMPLE_CALL:
1327 for (i = 0; i < gimple_call_num_args (stmt); i++)
1328 ret |= build_access_from_expr (gimple_call_arg (stmt, i),
1329 stmt, false);
1331 if (sra_mode == SRA_MODE_EARLY_IPA)
1333 tree dest = gimple_call_fndecl (stmt);
1334 int flags = gimple_call_flags (stmt);
1336 if (dest)
1338 if (DECL_BUILT_IN_CLASS (dest) == BUILT_IN_NORMAL
1339 && DECL_FUNCTION_CODE (dest) == BUILT_IN_APPLY_ARGS)
1340 encountered_apply_args = true;
1341 if (recursive_call_p (current_function_decl, dest))
1343 encountered_recursive_call = true;
1344 if (!callsite_arguments_match_p (stmt))
1345 encountered_unchangable_recursive_call = true;
1349 if (final_bbs
1350 && (flags & (ECF_CONST | ECF_PURE)) == 0)
1351 bitmap_set_bit (final_bbs, bb->index);
1354 t = gimple_call_lhs (stmt);
1355 if (t && !disqualify_if_bad_bb_terminating_stmt (stmt, t, NULL))
1356 ret |= build_access_from_expr (t, stmt, true);
1357 break;
1359 case GIMPLE_ASM:
1361 gasm *asm_stmt = as_a <gasm *> (stmt);
1362 walk_stmt_load_store_addr_ops (asm_stmt, NULL, NULL, NULL,
1363 asm_visit_addr);
1364 if (final_bbs)
1365 bitmap_set_bit (final_bbs, bb->index);
1367 for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
1369 t = TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
1370 ret |= build_access_from_expr (t, asm_stmt, false);
1372 for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
1374 t = TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
1375 ret |= build_access_from_expr (t, asm_stmt, true);
1378 break;
1380 default:
1381 break;
1386 return ret;
1389 /* Helper of QSORT function. There are pointers to accesses in the array. An
1390 access is considered smaller than another if it has smaller offset or if the
1391 offsets are the same but is size is bigger. */
1393 static int
1394 compare_access_positions (const void *a, const void *b)
1396 const access_p *fp1 = (const access_p *) a;
1397 const access_p *fp2 = (const access_p *) b;
1398 const access_p f1 = *fp1;
1399 const access_p f2 = *fp2;
1401 if (f1->offset != f2->offset)
1402 return f1->offset < f2->offset ? -1 : 1;
1404 if (f1->size == f2->size)
1406 if (f1->type == f2->type)
1407 return 0;
1408 /* Put any non-aggregate type before any aggregate type. */
1409 else if (!is_gimple_reg_type (f1->type)
1410 && is_gimple_reg_type (f2->type))
1411 return 1;
1412 else if (is_gimple_reg_type (f1->type)
1413 && !is_gimple_reg_type (f2->type))
1414 return -1;
1415 /* Put any complex or vector type before any other scalar type. */
1416 else if (TREE_CODE (f1->type) != COMPLEX_TYPE
1417 && TREE_CODE (f1->type) != VECTOR_TYPE
1418 && (TREE_CODE (f2->type) == COMPLEX_TYPE
1419 || TREE_CODE (f2->type) == VECTOR_TYPE))
1420 return 1;
1421 else if ((TREE_CODE (f1->type) == COMPLEX_TYPE
1422 || TREE_CODE (f1->type) == VECTOR_TYPE)
1423 && TREE_CODE (f2->type) != COMPLEX_TYPE
1424 && TREE_CODE (f2->type) != VECTOR_TYPE)
1425 return -1;
1426 /* Put the integral type with the bigger precision first. */
1427 else if (INTEGRAL_TYPE_P (f1->type)
1428 && INTEGRAL_TYPE_P (f2->type))
1429 return TYPE_PRECISION (f2->type) - TYPE_PRECISION (f1->type);
1430 /* Put any integral type with non-full precision last. */
1431 else if (INTEGRAL_TYPE_P (f1->type)
1432 && (TREE_INT_CST_LOW (TYPE_SIZE (f1->type))
1433 != TYPE_PRECISION (f1->type)))
1434 return 1;
1435 else if (INTEGRAL_TYPE_P (f2->type)
1436 && (TREE_INT_CST_LOW (TYPE_SIZE (f2->type))
1437 != TYPE_PRECISION (f2->type)))
1438 return -1;
1439 /* Stabilize the sort. */
1440 return TYPE_UID (f1->type) - TYPE_UID (f2->type);
1443 /* We want the bigger accesses first, thus the opposite operator in the next
1444 line: */
1445 return f1->size > f2->size ? -1 : 1;
1449 /* Append a name of the declaration to the name obstack. A helper function for
1450 make_fancy_name. */
1452 static void
1453 make_fancy_decl_name (tree decl)
1455 char buffer[32];
1457 tree name = DECL_NAME (decl);
1458 if (name)
1459 obstack_grow (&name_obstack, IDENTIFIER_POINTER (name),
1460 IDENTIFIER_LENGTH (name));
1461 else
1463 sprintf (buffer, "D%u", DECL_UID (decl));
1464 obstack_grow (&name_obstack, buffer, strlen (buffer));
1468 /* Helper for make_fancy_name. */
1470 static void
1471 make_fancy_name_1 (tree expr)
1473 char buffer[32];
1474 tree index;
1476 if (DECL_P (expr))
1478 make_fancy_decl_name (expr);
1479 return;
1482 switch (TREE_CODE (expr))
1484 case COMPONENT_REF:
1485 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1486 obstack_1grow (&name_obstack, '$');
1487 make_fancy_decl_name (TREE_OPERAND (expr, 1));
1488 break;
1490 case ARRAY_REF:
1491 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1492 obstack_1grow (&name_obstack, '$');
1493 /* Arrays with only one element may not have a constant as their
1494 index. */
1495 index = TREE_OPERAND (expr, 1);
1496 if (TREE_CODE (index) != INTEGER_CST)
1497 break;
1498 sprintf (buffer, HOST_WIDE_INT_PRINT_DEC, TREE_INT_CST_LOW (index));
1499 obstack_grow (&name_obstack, buffer, strlen (buffer));
1500 break;
1502 case ADDR_EXPR:
1503 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1504 break;
1506 case MEM_REF:
1507 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1508 if (!integer_zerop (TREE_OPERAND (expr, 1)))
1510 obstack_1grow (&name_obstack, '$');
1511 sprintf (buffer, HOST_WIDE_INT_PRINT_DEC,
1512 TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)));
1513 obstack_grow (&name_obstack, buffer, strlen (buffer));
1515 break;
1517 case BIT_FIELD_REF:
1518 case REALPART_EXPR:
1519 case IMAGPART_EXPR:
1520 gcc_unreachable (); /* we treat these as scalars. */
1521 break;
1522 default:
1523 break;
1527 /* Create a human readable name for replacement variable of ACCESS. */
1529 static char *
1530 make_fancy_name (tree expr)
1532 make_fancy_name_1 (expr);
1533 obstack_1grow (&name_obstack, '\0');
1534 return XOBFINISH (&name_obstack, char *);
1537 /* Construct a MEM_REF that would reference a part of aggregate BASE of type
1538 EXP_TYPE at the given OFFSET. If BASE is something for which
1539 get_addr_base_and_unit_offset returns NULL, gsi must be non-NULL and is used
1540 to insert new statements either before or below the current one as specified
1541 by INSERT_AFTER. This function is not capable of handling bitfields.
1543 BASE must be either a declaration or a memory reference that has correct
1544 alignment ifformation embeded in it (e.g. a pre-existing one in SRA). */
1546 tree
1547 build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset,
1548 tree exp_type, gimple_stmt_iterator *gsi,
1549 bool insert_after)
1551 tree prev_base = base;
1552 tree off;
1553 tree mem_ref;
1554 HOST_WIDE_INT base_offset;
1555 unsigned HOST_WIDE_INT misalign;
1556 unsigned int align;
1558 gcc_checking_assert (offset % BITS_PER_UNIT == 0);
1559 get_object_alignment_1 (base, &align, &misalign);
1560 base = get_addr_base_and_unit_offset (base, &base_offset);
1562 /* get_addr_base_and_unit_offset returns NULL for references with a variable
1563 offset such as array[var_index]. */
1564 if (!base)
1566 gassign *stmt;
1567 tree tmp, addr;
1569 gcc_checking_assert (gsi);
1570 tmp = make_ssa_name (build_pointer_type (TREE_TYPE (prev_base)));
1571 addr = build_fold_addr_expr (unshare_expr (prev_base));
1572 STRIP_USELESS_TYPE_CONVERSION (addr);
1573 stmt = gimple_build_assign (tmp, addr);
1574 gimple_set_location (stmt, loc);
1575 if (insert_after)
1576 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
1577 else
1578 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
1580 off = build_int_cst (reference_alias_ptr_type (prev_base),
1581 offset / BITS_PER_UNIT);
1582 base = tmp;
1584 else if (TREE_CODE (base) == MEM_REF)
1586 off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
1587 base_offset + offset / BITS_PER_UNIT);
1588 off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
1589 base = unshare_expr (TREE_OPERAND (base, 0));
1591 else
1593 off = build_int_cst (reference_alias_ptr_type (base),
1594 base_offset + offset / BITS_PER_UNIT);
1595 base = build_fold_addr_expr (unshare_expr (base));
1598 misalign = (misalign + offset) & (align - 1);
1599 if (misalign != 0)
1600 align = (misalign & -misalign);
1601 if (align != TYPE_ALIGN (exp_type))
1602 exp_type = build_aligned_type (exp_type, align);
1604 mem_ref = fold_build2_loc (loc, MEM_REF, exp_type, base, off);
1605 if (TREE_THIS_VOLATILE (prev_base))
1606 TREE_THIS_VOLATILE (mem_ref) = 1;
1607 if (TREE_SIDE_EFFECTS (prev_base))
1608 TREE_SIDE_EFFECTS (mem_ref) = 1;
1609 return mem_ref;
1612 /* Construct a memory reference to a part of an aggregate BASE at the given
1613 OFFSET and of the same type as MODEL. In case this is a reference to a
1614 bit-field, the function will replicate the last component_ref of model's
1615 expr to access it. GSI and INSERT_AFTER have the same meaning as in
1616 build_ref_for_offset. */
1618 static tree
1619 build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
1620 struct access *model, gimple_stmt_iterator *gsi,
1621 bool insert_after)
1623 if (TREE_CODE (model->expr) == COMPONENT_REF
1624 && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
1626 /* This access represents a bit-field. */
1627 tree t, exp_type, fld = TREE_OPERAND (model->expr, 1);
1629 offset -= int_bit_position (fld);
1630 exp_type = TREE_TYPE (TREE_OPERAND (model->expr, 0));
1631 t = build_ref_for_offset (loc, base, offset, exp_type, gsi, insert_after);
1632 return fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (fld), t, fld,
1633 NULL_TREE);
1635 else
1636 return build_ref_for_offset (loc, base, offset, model->type,
1637 gsi, insert_after);
1640 /* Attempt to build a memory reference that we could but into a gimple
1641 debug_bind statement. Similar to build_ref_for_model but punts if it has to
1642 create statements and return s NULL instead. This function also ignores
1643 alignment issues and so its results should never end up in non-debug
1644 statements. */
1646 static tree
1647 build_debug_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
1648 struct access *model)
1650 HOST_WIDE_INT base_offset;
1651 tree off;
1653 if (TREE_CODE (model->expr) == COMPONENT_REF
1654 && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
1655 return NULL_TREE;
1657 base = get_addr_base_and_unit_offset (base, &base_offset);
1658 if (!base)
1659 return NULL_TREE;
1660 if (TREE_CODE (base) == MEM_REF)
1662 off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
1663 base_offset + offset / BITS_PER_UNIT);
1664 off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
1665 base = unshare_expr (TREE_OPERAND (base, 0));
1667 else
1669 off = build_int_cst (reference_alias_ptr_type (base),
1670 base_offset + offset / BITS_PER_UNIT);
1671 base = build_fold_addr_expr (unshare_expr (base));
1674 return fold_build2_loc (loc, MEM_REF, model->type, base, off);
1677 /* Construct a memory reference consisting of component_refs and array_refs to
1678 a part of an aggregate *RES (which is of type TYPE). The requested part
1679 should have type EXP_TYPE at be the given OFFSET. This function might not
1680 succeed, it returns true when it does and only then *RES points to something
1681 meaningful. This function should be used only to build expressions that we
1682 might need to present to user (e.g. in warnings). In all other situations,
1683 build_ref_for_model or build_ref_for_offset should be used instead. */
1685 static bool
1686 build_user_friendly_ref_for_offset (tree *res, tree type, HOST_WIDE_INT offset,
1687 tree exp_type)
1689 while (1)
1691 tree fld;
1692 tree tr_size, index, minidx;
1693 HOST_WIDE_INT el_size;
1695 if (offset == 0 && exp_type
1696 && types_compatible_p (exp_type, type))
1697 return true;
1699 switch (TREE_CODE (type))
1701 case UNION_TYPE:
1702 case QUAL_UNION_TYPE:
1703 case RECORD_TYPE:
1704 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
1706 HOST_WIDE_INT pos, size;
1707 tree tr_pos, expr, *expr_ptr;
1709 if (TREE_CODE (fld) != FIELD_DECL)
1710 continue;
1712 tr_pos = bit_position (fld);
1713 if (!tr_pos || !tree_fits_uhwi_p (tr_pos))
1714 continue;
1715 pos = tree_to_uhwi (tr_pos);
1716 gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0);
1717 tr_size = DECL_SIZE (fld);
1718 if (!tr_size || !tree_fits_uhwi_p (tr_size))
1719 continue;
1720 size = tree_to_uhwi (tr_size);
1721 if (size == 0)
1723 if (pos != offset)
1724 continue;
1726 else if (pos > offset || (pos + size) <= offset)
1727 continue;
1729 expr = build3 (COMPONENT_REF, TREE_TYPE (fld), *res, fld,
1730 NULL_TREE);
1731 expr_ptr = &expr;
1732 if (build_user_friendly_ref_for_offset (expr_ptr, TREE_TYPE (fld),
1733 offset - pos, exp_type))
1735 *res = expr;
1736 return true;
1739 return false;
1741 case ARRAY_TYPE:
1742 tr_size = TYPE_SIZE (TREE_TYPE (type));
1743 if (!tr_size || !tree_fits_uhwi_p (tr_size))
1744 return false;
1745 el_size = tree_to_uhwi (tr_size);
1747 minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
1748 if (TREE_CODE (minidx) != INTEGER_CST || el_size == 0)
1749 return false;
1750 index = build_int_cst (TYPE_DOMAIN (type), offset / el_size);
1751 if (!integer_zerop (minidx))
1752 index = int_const_binop (PLUS_EXPR, index, minidx);
1753 *res = build4 (ARRAY_REF, TREE_TYPE (type), *res, index,
1754 NULL_TREE, NULL_TREE);
1755 offset = offset % el_size;
1756 type = TREE_TYPE (type);
1757 break;
1759 default:
1760 if (offset != 0)
1761 return false;
1763 if (exp_type)
1764 return false;
1765 else
1766 return true;
1771 /* Return true iff TYPE is stdarg va_list type. */
1773 static inline bool
1774 is_va_list_type (tree type)
1776 return TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (va_list_type_node);
1779 /* Print message to dump file why a variable was rejected. */
1781 static void
1782 reject (tree var, const char *msg)
1784 if (dump_file && (dump_flags & TDF_DETAILS))
1786 fprintf (dump_file, "Rejected (%d): %s: ", DECL_UID (var), msg);
1787 print_generic_expr (dump_file, var, 0);
1788 fprintf (dump_file, "\n");
1792 /* Return true if VAR is a candidate for SRA. */
1794 static bool
1795 maybe_add_sra_candidate (tree var)
1797 tree type = TREE_TYPE (var);
1798 const char *msg;
1799 tree_node **slot;
1801 if (!AGGREGATE_TYPE_P (type))
1803 reject (var, "not aggregate");
1804 return false;
1806 if (needs_to_live_in_memory (var))
1808 reject (var, "needs to live in memory");
1809 return false;
1811 if (TREE_THIS_VOLATILE (var))
1813 reject (var, "is volatile");
1814 return false;
1816 if (!COMPLETE_TYPE_P (type))
1818 reject (var, "has incomplete type");
1819 return false;
1821 if (!tree_fits_uhwi_p (TYPE_SIZE (type)))
1823 reject (var, "type size not fixed");
1824 return false;
1826 if (tree_to_uhwi (TYPE_SIZE (type)) == 0)
1828 reject (var, "type size is zero");
1829 return false;
1831 if (type_internals_preclude_sra_p (type, &msg))
1833 reject (var, msg);
1834 return false;
1836 if (/* Fix for PR 41089. tree-stdarg.c needs to have va_lists intact but
1837 we also want to schedule it rather late. Thus we ignore it in
1838 the early pass. */
1839 (sra_mode == SRA_MODE_EARLY_INTRA
1840 && is_va_list_type (type)))
1842 reject (var, "is va_list");
1843 return false;
1846 bitmap_set_bit (candidate_bitmap, DECL_UID (var));
1847 slot = candidates->find_slot_with_hash (var, DECL_UID (var), INSERT);
1848 *slot = var;
1850 if (dump_file && (dump_flags & TDF_DETAILS))
1852 fprintf (dump_file, "Candidate (%d): ", DECL_UID (var));
1853 print_generic_expr (dump_file, var, 0);
1854 fprintf (dump_file, "\n");
1857 return true;
1860 /* The very first phase of intraprocedural SRA. It marks in candidate_bitmap
1861 those with type which is suitable for scalarization. */
1863 static bool
1864 find_var_candidates (void)
1866 tree var, parm;
1867 unsigned int i;
1868 bool ret = false;
1870 for (parm = DECL_ARGUMENTS (current_function_decl);
1871 parm;
1872 parm = DECL_CHAIN (parm))
1873 ret |= maybe_add_sra_candidate (parm);
1875 FOR_EACH_LOCAL_DECL (cfun, i, var)
1877 if (TREE_CODE (var) != VAR_DECL)
1878 continue;
1880 ret |= maybe_add_sra_candidate (var);
1883 return ret;
1886 /* Sort all accesses for the given variable, check for partial overlaps and
1887 return NULL if there are any. If there are none, pick a representative for
1888 each combination of offset and size and create a linked list out of them.
1889 Return the pointer to the first representative and make sure it is the first
1890 one in the vector of accesses. */
1892 static struct access *
1893 sort_and_splice_var_accesses (tree var)
1895 int i, j, access_count;
1896 struct access *res, **prev_acc_ptr = &res;
1897 vec<access_p> *access_vec;
1898 bool first = true;
1899 HOST_WIDE_INT low = -1, high = 0;
1901 access_vec = get_base_access_vector (var);
1902 if (!access_vec)
1903 return NULL;
1904 access_count = access_vec->length ();
1906 /* Sort by <OFFSET, SIZE>. */
1907 access_vec->qsort (compare_access_positions);
1909 i = 0;
1910 while (i < access_count)
1912 struct access *access = (*access_vec)[i];
1913 bool grp_write = access->write;
1914 bool grp_read = !access->write;
1915 bool grp_scalar_write = access->write
1916 && is_gimple_reg_type (access->type);
1917 bool grp_scalar_read = !access->write
1918 && is_gimple_reg_type (access->type);
1919 bool grp_assignment_read = access->grp_assignment_read;
1920 bool grp_assignment_write = access->grp_assignment_write;
1921 bool multiple_scalar_reads = false;
1922 bool total_scalarization = access->grp_total_scalarization;
1923 bool grp_partial_lhs = access->grp_partial_lhs;
1924 bool first_scalar = is_gimple_reg_type (access->type);
1925 bool unscalarizable_region = access->grp_unscalarizable_region;
1927 if (first || access->offset >= high)
1929 first = false;
1930 low = access->offset;
1931 high = access->offset + access->size;
1933 else if (access->offset > low && access->offset + access->size > high)
1934 return NULL;
1935 else
1936 gcc_assert (access->offset >= low
1937 && access->offset + access->size <= high);
1939 j = i + 1;
1940 while (j < access_count)
1942 struct access *ac2 = (*access_vec)[j];
1943 if (ac2->offset != access->offset || ac2->size != access->size)
1944 break;
1945 if (ac2->write)
1947 grp_write = true;
1948 grp_scalar_write = (grp_scalar_write
1949 || is_gimple_reg_type (ac2->type));
1951 else
1953 grp_read = true;
1954 if (is_gimple_reg_type (ac2->type))
1956 if (grp_scalar_read)
1957 multiple_scalar_reads = true;
1958 else
1959 grp_scalar_read = true;
1962 grp_assignment_read |= ac2->grp_assignment_read;
1963 grp_assignment_write |= ac2->grp_assignment_write;
1964 grp_partial_lhs |= ac2->grp_partial_lhs;
1965 unscalarizable_region |= ac2->grp_unscalarizable_region;
1966 total_scalarization |= ac2->grp_total_scalarization;
1967 relink_to_new_repr (access, ac2);
1969 /* If there are both aggregate-type and scalar-type accesses with
1970 this combination of size and offset, the comparison function
1971 should have put the scalars first. */
1972 gcc_assert (first_scalar || !is_gimple_reg_type (ac2->type));
1973 ac2->group_representative = access;
1974 j++;
1977 i = j;
1979 access->group_representative = access;
1980 access->grp_write = grp_write;
1981 access->grp_read = grp_read;
1982 access->grp_scalar_read = grp_scalar_read;
1983 access->grp_scalar_write = grp_scalar_write;
1984 access->grp_assignment_read = grp_assignment_read;
1985 access->grp_assignment_write = grp_assignment_write;
1986 access->grp_hint = multiple_scalar_reads || total_scalarization;
1987 access->grp_total_scalarization = total_scalarization;
1988 access->grp_partial_lhs = grp_partial_lhs;
1989 access->grp_unscalarizable_region = unscalarizable_region;
1990 if (access->first_link)
1991 add_access_to_work_queue (access);
1993 *prev_acc_ptr = access;
1994 prev_acc_ptr = &access->next_grp;
1997 gcc_assert (res == (*access_vec)[0]);
1998 return res;
2001 /* Create a variable for the given ACCESS which determines the type, name and a
2002 few other properties. Return the variable declaration and store it also to
2003 ACCESS->replacement. */
2005 static tree
2006 create_access_replacement (struct access *access)
2008 tree repl;
2010 if (access->grp_to_be_debug_replaced)
2012 repl = create_tmp_var_raw (access->type);
2013 DECL_CONTEXT (repl) = current_function_decl;
2015 else
2016 /* Drop any special alignment on the type if it's not on the main
2017 variant. This avoids issues with weirdo ABIs like AAPCS. */
2018 repl = create_tmp_var (build_qualified_type
2019 (TYPE_MAIN_VARIANT (access->type),
2020 TYPE_QUALS (access->type)), "SR");
2021 if (TREE_CODE (access->type) == COMPLEX_TYPE
2022 || TREE_CODE (access->type) == VECTOR_TYPE)
2024 if (!access->grp_partial_lhs)
2025 DECL_GIMPLE_REG_P (repl) = 1;
2027 else if (access->grp_partial_lhs
2028 && is_gimple_reg_type (access->type))
2029 TREE_ADDRESSABLE (repl) = 1;
2031 DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base);
2032 DECL_ARTIFICIAL (repl) = 1;
2033 DECL_IGNORED_P (repl) = DECL_IGNORED_P (access->base);
2035 if (DECL_NAME (access->base)
2036 && !DECL_IGNORED_P (access->base)
2037 && !DECL_ARTIFICIAL (access->base))
2039 char *pretty_name = make_fancy_name (access->expr);
2040 tree debug_expr = unshare_expr_without_location (access->expr), d;
2041 bool fail = false;
2043 DECL_NAME (repl) = get_identifier (pretty_name);
2044 obstack_free (&name_obstack, pretty_name);
2046 /* Get rid of any SSA_NAMEs embedded in debug_expr,
2047 as DECL_DEBUG_EXPR isn't considered when looking for still
2048 used SSA_NAMEs and thus they could be freed. All debug info
2049 generation cares is whether something is constant or variable
2050 and that get_ref_base_and_extent works properly on the
2051 expression. It cannot handle accesses at a non-constant offset
2052 though, so just give up in those cases. */
2053 for (d = debug_expr;
2054 !fail && (handled_component_p (d) || TREE_CODE (d) == MEM_REF);
2055 d = TREE_OPERAND (d, 0))
2056 switch (TREE_CODE (d))
2058 case ARRAY_REF:
2059 case ARRAY_RANGE_REF:
2060 if (TREE_OPERAND (d, 1)
2061 && TREE_CODE (TREE_OPERAND (d, 1)) != INTEGER_CST)
2062 fail = true;
2063 if (TREE_OPERAND (d, 3)
2064 && TREE_CODE (TREE_OPERAND (d, 3)) != INTEGER_CST)
2065 fail = true;
2066 /* FALLTHRU */
2067 case COMPONENT_REF:
2068 if (TREE_OPERAND (d, 2)
2069 && TREE_CODE (TREE_OPERAND (d, 2)) != INTEGER_CST)
2070 fail = true;
2071 break;
2072 case MEM_REF:
2073 if (TREE_CODE (TREE_OPERAND (d, 0)) != ADDR_EXPR)
2074 fail = true;
2075 else
2076 d = TREE_OPERAND (d, 0);
2077 break;
2078 default:
2079 break;
2081 if (!fail)
2083 SET_DECL_DEBUG_EXPR (repl, debug_expr);
2084 DECL_HAS_DEBUG_EXPR_P (repl) = 1;
2086 if (access->grp_no_warning)
2087 TREE_NO_WARNING (repl) = 1;
2088 else
2089 TREE_NO_WARNING (repl) = TREE_NO_WARNING (access->base);
2091 else
2092 TREE_NO_WARNING (repl) = 1;
2094 if (dump_file)
2096 if (access->grp_to_be_debug_replaced)
2098 fprintf (dump_file, "Created a debug-only replacement for ");
2099 print_generic_expr (dump_file, access->base, 0);
2100 fprintf (dump_file, " offset: %u, size: %u\n",
2101 (unsigned) access->offset, (unsigned) access->size);
2103 else
2105 fprintf (dump_file, "Created a replacement for ");
2106 print_generic_expr (dump_file, access->base, 0);
2107 fprintf (dump_file, " offset: %u, size: %u: ",
2108 (unsigned) access->offset, (unsigned) access->size);
2109 print_generic_expr (dump_file, repl, 0);
2110 fprintf (dump_file, "\n");
2113 sra_stats.replacements++;
2115 return repl;
2118 /* Return ACCESS scalar replacement, create it if it does not exist yet. */
2120 static inline tree
2121 get_access_replacement (struct access *access)
2123 gcc_checking_assert (access->replacement_decl);
2124 return access->replacement_decl;
2128 /* Build a subtree of accesses rooted in *ACCESS, and move the pointer in the
2129 linked list along the way. Stop when *ACCESS is NULL or the access pointed
2130 to it is not "within" the root. Return false iff some accesses partially
2131 overlap. */
2133 static bool
2134 build_access_subtree (struct access **access)
2136 struct access *root = *access, *last_child = NULL;
2137 HOST_WIDE_INT limit = root->offset + root->size;
2139 *access = (*access)->next_grp;
2140 while (*access && (*access)->offset + (*access)->size <= limit)
2142 if (!last_child)
2143 root->first_child = *access;
2144 else
2145 last_child->next_sibling = *access;
2146 last_child = *access;
2148 if (!build_access_subtree (access))
2149 return false;
2152 if (*access && (*access)->offset < limit)
2153 return false;
2155 return true;
2158 /* Build a tree of access representatives, ACCESS is the pointer to the first
2159 one, others are linked in a list by the next_grp field. Return false iff
2160 some accesses partially overlap. */
2162 static bool
2163 build_access_trees (struct access *access)
2165 while (access)
2167 struct access *root = access;
2169 if (!build_access_subtree (&access))
2170 return false;
2171 root->next_grp = access;
2173 return true;
2176 /* Return true if expr contains some ARRAY_REFs into a variable bounded
2177 array. */
2179 static bool
2180 expr_with_var_bounded_array_refs_p (tree expr)
2182 while (handled_component_p (expr))
2184 if (TREE_CODE (expr) == ARRAY_REF
2185 && !tree_fits_shwi_p (array_ref_low_bound (expr)))
2186 return true;
2187 expr = TREE_OPERAND (expr, 0);
2189 return false;
2192 /* Analyze the subtree of accesses rooted in ROOT, scheduling replacements when
2193 both seeming beneficial and when ALLOW_REPLACEMENTS allows it. Also set all
2194 sorts of access flags appropriately along the way, notably always set
2195 grp_read and grp_assign_read according to MARK_READ and grp_write when
2196 MARK_WRITE is true.
2198 Creating a replacement for a scalar access is considered beneficial if its
2199 grp_hint is set (this means we are either attempting total scalarization or
2200 there is more than one direct read access) or according to the following
2201 table:
2203 Access written to through a scalar type (once or more times)
2205 | Written to in an assignment statement
2207 | | Access read as scalar _once_
2208 | | |
2209 | | | Read in an assignment statement
2210 | | | |
2211 | | | | Scalarize Comment
2212 -----------------------------------------------------------------------------
2213 0 0 0 0 No access for the scalar
2214 0 0 0 1 No access for the scalar
2215 0 0 1 0 No Single read - won't help
2216 0 0 1 1 No The same case
2217 0 1 0 0 No access for the scalar
2218 0 1 0 1 No access for the scalar
2219 0 1 1 0 Yes s = *g; return s.i;
2220 0 1 1 1 Yes The same case as above
2221 1 0 0 0 No Won't help
2222 1 0 0 1 Yes s.i = 1; *g = s;
2223 1 0 1 0 Yes s.i = 5; g = s.i;
2224 1 0 1 1 Yes The same case as above
2225 1 1 0 0 No Won't help.
2226 1 1 0 1 Yes s.i = 1; *g = s;
2227 1 1 1 0 Yes s = *g; return s.i;
2228 1 1 1 1 Yes Any of the above yeses */
2230 static bool
2231 analyze_access_subtree (struct access *root, struct access *parent,
2232 bool allow_replacements)
2234 struct access *child;
2235 HOST_WIDE_INT limit = root->offset + root->size;
2236 HOST_WIDE_INT covered_to = root->offset;
2237 bool scalar = is_gimple_reg_type (root->type);
2238 bool hole = false, sth_created = false;
2240 if (parent)
2242 if (parent->grp_read)
2243 root->grp_read = 1;
2244 if (parent->grp_assignment_read)
2245 root->grp_assignment_read = 1;
2246 if (parent->grp_write)
2247 root->grp_write = 1;
2248 if (parent->grp_assignment_write)
2249 root->grp_assignment_write = 1;
2250 if (parent->grp_total_scalarization)
2251 root->grp_total_scalarization = 1;
2254 if (root->grp_unscalarizable_region)
2255 allow_replacements = false;
2257 if (allow_replacements && expr_with_var_bounded_array_refs_p (root->expr))
2258 allow_replacements = false;
2260 for (child = root->first_child; child; child = child->next_sibling)
2262 hole |= covered_to < child->offset;
2263 sth_created |= analyze_access_subtree (child, root,
2264 allow_replacements && !scalar);
2266 root->grp_unscalarized_data |= child->grp_unscalarized_data;
2267 root->grp_total_scalarization &= child->grp_total_scalarization;
2268 if (child->grp_covered)
2269 covered_to += child->size;
2270 else
2271 hole = true;
2274 if (allow_replacements && scalar && !root->first_child
2275 && (root->grp_hint
2276 || ((root->grp_scalar_read || root->grp_assignment_read)
2277 && (root->grp_scalar_write || root->grp_assignment_write))))
2279 /* Always create access replacements that cover the whole access.
2280 For integral types this means the precision has to match.
2281 Avoid assumptions based on the integral type kind, too. */
2282 if (INTEGRAL_TYPE_P (root->type)
2283 && (TREE_CODE (root->type) != INTEGER_TYPE
2284 || TYPE_PRECISION (root->type) != root->size)
2285 /* But leave bitfield accesses alone. */
2286 && (TREE_CODE (root->expr) != COMPONENT_REF
2287 || !DECL_BIT_FIELD (TREE_OPERAND (root->expr, 1))))
2289 tree rt = root->type;
2290 gcc_assert ((root->offset % BITS_PER_UNIT) == 0
2291 && (root->size % BITS_PER_UNIT) == 0);
2292 root->type = build_nonstandard_integer_type (root->size,
2293 TYPE_UNSIGNED (rt));
2294 root->expr = build_ref_for_offset (UNKNOWN_LOCATION,
2295 root->base, root->offset,
2296 root->type, NULL, false);
2298 if (dump_file && (dump_flags & TDF_DETAILS))
2300 fprintf (dump_file, "Changing the type of a replacement for ");
2301 print_generic_expr (dump_file, root->base, 0);
2302 fprintf (dump_file, " offset: %u, size: %u ",
2303 (unsigned) root->offset, (unsigned) root->size);
2304 fprintf (dump_file, " to an integer.\n");
2308 root->grp_to_be_replaced = 1;
2309 root->replacement_decl = create_access_replacement (root);
2310 sth_created = true;
2311 hole = false;
2313 else
2315 if (allow_replacements
2316 && scalar && !root->first_child
2317 && (root->grp_scalar_write || root->grp_assignment_write)
2318 && !bitmap_bit_p (cannot_scalarize_away_bitmap,
2319 DECL_UID (root->base)))
2321 gcc_checking_assert (!root->grp_scalar_read
2322 && !root->grp_assignment_read);
2323 sth_created = true;
2324 if (MAY_HAVE_DEBUG_STMTS)
2326 root->grp_to_be_debug_replaced = 1;
2327 root->replacement_decl = create_access_replacement (root);
2331 if (covered_to < limit)
2332 hole = true;
2333 if (scalar)
2334 root->grp_total_scalarization = 0;
2337 if (!hole || root->grp_total_scalarization)
2338 root->grp_covered = 1;
2339 else if (root->grp_write || TREE_CODE (root->base) == PARM_DECL)
2340 root->grp_unscalarized_data = 1; /* not covered and written to */
2341 return sth_created;
2344 /* Analyze all access trees linked by next_grp by the means of
2345 analyze_access_subtree. */
2346 static bool
2347 analyze_access_trees (struct access *access)
2349 bool ret = false;
2351 while (access)
2353 if (analyze_access_subtree (access, NULL, true))
2354 ret = true;
2355 access = access->next_grp;
2358 return ret;
2361 /* Return true iff a potential new child of LACC at offset OFFSET and with size
2362 SIZE would conflict with an already existing one. If exactly such a child
2363 already exists in LACC, store a pointer to it in EXACT_MATCH. */
2365 static bool
2366 child_would_conflict_in_lacc (struct access *lacc, HOST_WIDE_INT norm_offset,
2367 HOST_WIDE_INT size, struct access **exact_match)
2369 struct access *child;
2371 for (child = lacc->first_child; child; child = child->next_sibling)
2373 if (child->offset == norm_offset && child->size == size)
2375 *exact_match = child;
2376 return true;
2379 if (child->offset < norm_offset + size
2380 && child->offset + child->size > norm_offset)
2381 return true;
2384 return false;
2387 /* Create a new child access of PARENT, with all properties just like MODEL
2388 except for its offset and with its grp_write false and grp_read true.
2389 Return the new access or NULL if it cannot be created. Note that this access
2390 is created long after all splicing and sorting, it's not located in any
2391 access vector and is automatically a representative of its group. */
2393 static struct access *
2394 create_artificial_child_access (struct access *parent, struct access *model,
2395 HOST_WIDE_INT new_offset)
2397 struct access *access;
2398 struct access **child;
2399 tree expr = parent->base;
2401 gcc_assert (!model->grp_unscalarizable_region);
2403 access = (struct access *) pool_alloc (access_pool);
2404 memset (access, 0, sizeof (struct access));
2405 if (!build_user_friendly_ref_for_offset (&expr, TREE_TYPE (expr), new_offset,
2406 model->type))
2408 access->grp_no_warning = true;
2409 expr = build_ref_for_model (EXPR_LOCATION (parent->base), parent->base,
2410 new_offset, model, NULL, false);
2413 access->base = parent->base;
2414 access->expr = expr;
2415 access->offset = new_offset;
2416 access->size = model->size;
2417 access->type = model->type;
2418 access->grp_write = true;
2419 access->grp_read = false;
2421 child = &parent->first_child;
2422 while (*child && (*child)->offset < new_offset)
2423 child = &(*child)->next_sibling;
2425 access->next_sibling = *child;
2426 *child = access;
2428 return access;
2432 /* Propagate all subaccesses of RACC across an assignment link to LACC. Return
2433 true if any new subaccess was created. Additionally, if RACC is a scalar
2434 access but LACC is not, change the type of the latter, if possible. */
2436 static bool
2437 propagate_subaccesses_across_link (struct access *lacc, struct access *racc)
2439 struct access *rchild;
2440 HOST_WIDE_INT norm_delta = lacc->offset - racc->offset;
2441 bool ret = false;
2443 if (is_gimple_reg_type (lacc->type)
2444 || lacc->grp_unscalarizable_region
2445 || racc->grp_unscalarizable_region)
2446 return false;
2448 if (is_gimple_reg_type (racc->type))
2450 if (!lacc->first_child && !racc->first_child)
2452 tree t = lacc->base;
2454 lacc->type = racc->type;
2455 if (build_user_friendly_ref_for_offset (&t, TREE_TYPE (t),
2456 lacc->offset, racc->type))
2457 lacc->expr = t;
2458 else
2460 lacc->expr = build_ref_for_model (EXPR_LOCATION (lacc->base),
2461 lacc->base, lacc->offset,
2462 racc, NULL, false);
2463 lacc->grp_no_warning = true;
2466 return false;
2469 for (rchild = racc->first_child; rchild; rchild = rchild->next_sibling)
2471 struct access *new_acc = NULL;
2472 HOST_WIDE_INT norm_offset = rchild->offset + norm_delta;
2474 if (rchild->grp_unscalarizable_region)
2475 continue;
2477 if (child_would_conflict_in_lacc (lacc, norm_offset, rchild->size,
2478 &new_acc))
2480 if (new_acc)
2482 rchild->grp_hint = 1;
2483 new_acc->grp_hint |= new_acc->grp_read;
2484 if (rchild->first_child)
2485 ret |= propagate_subaccesses_across_link (new_acc, rchild);
2487 continue;
2490 rchild->grp_hint = 1;
2491 new_acc = create_artificial_child_access (lacc, rchild, norm_offset);
2492 if (new_acc)
2494 ret = true;
2495 if (racc->first_child)
2496 propagate_subaccesses_across_link (new_acc, rchild);
2500 return ret;
2503 /* Propagate all subaccesses across assignment links. */
2505 static void
2506 propagate_all_subaccesses (void)
2508 while (work_queue_head)
2510 struct access *racc = pop_access_from_work_queue ();
2511 struct assign_link *link;
2513 gcc_assert (racc->first_link);
2515 for (link = racc->first_link; link; link = link->next)
2517 struct access *lacc = link->lacc;
2519 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
2520 continue;
2521 lacc = lacc->group_representative;
2522 if (propagate_subaccesses_across_link (lacc, racc)
2523 && lacc->first_link)
2524 add_access_to_work_queue (lacc);
2529 /* Go through all accesses collected throughout the (intraprocedural) analysis
2530 stage, exclude overlapping ones, identify representatives and build trees
2531 out of them, making decisions about scalarization on the way. Return true
2532 iff there are any to-be-scalarized variables after this stage. */
2534 static bool
2535 analyze_all_variable_accesses (void)
2537 int res = 0;
2538 bitmap tmp = BITMAP_ALLOC (NULL);
2539 bitmap_iterator bi;
2540 unsigned i;
2541 unsigned max_scalarization_size
2542 = (optimize_function_for_size_p (cfun)
2543 ? PARAM_VALUE (PARAM_SRA_MAX_SCALARIZATION_SIZE_SIZE)
2544 : PARAM_VALUE (PARAM_SRA_MAX_SCALARIZATION_SIZE_SPEED))
2545 * BITS_PER_UNIT;
2547 EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
2548 if (bitmap_bit_p (should_scalarize_away_bitmap, i)
2549 && !bitmap_bit_p (cannot_scalarize_away_bitmap, i))
2551 tree var = candidate (i);
2553 if (TREE_CODE (var) == VAR_DECL
2554 && type_consists_of_records_p (TREE_TYPE (var)))
2556 if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (var)))
2557 <= max_scalarization_size)
2559 completely_scalarize_var (var);
2560 if (dump_file && (dump_flags & TDF_DETAILS))
2562 fprintf (dump_file, "Will attempt to totally scalarize ");
2563 print_generic_expr (dump_file, var, 0);
2564 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
2567 else if (dump_file && (dump_flags & TDF_DETAILS))
2569 fprintf (dump_file, "Too big to totally scalarize: ");
2570 print_generic_expr (dump_file, var, 0);
2571 fprintf (dump_file, " (UID: %u)\n", DECL_UID (var));
2576 bitmap_copy (tmp, candidate_bitmap);
2577 EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
2579 tree var = candidate (i);
2580 struct access *access;
2582 access = sort_and_splice_var_accesses (var);
2583 if (!access || !build_access_trees (access))
2584 disqualify_candidate (var,
2585 "No or inhibitingly overlapping accesses.");
2588 propagate_all_subaccesses ();
2590 bitmap_copy (tmp, candidate_bitmap);
2591 EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
2593 tree var = candidate (i);
2594 struct access *access = get_first_repr_for_decl (var);
2596 if (analyze_access_trees (access))
2598 res++;
2599 if (dump_file && (dump_flags & TDF_DETAILS))
2601 fprintf (dump_file, "\nAccess trees for ");
2602 print_generic_expr (dump_file, var, 0);
2603 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
2604 dump_access_tree (dump_file, access);
2605 fprintf (dump_file, "\n");
2608 else
2609 disqualify_candidate (var, "No scalar replacements to be created.");
2612 BITMAP_FREE (tmp);
2614 if (res)
2616 statistics_counter_event (cfun, "Scalarized aggregates", res);
2617 return true;
2619 else
2620 return false;
2623 /* Generate statements copying scalar replacements of accesses within a subtree
2624 into or out of AGG. ACCESS, all its children, siblings and their children
2625 are to be processed. AGG is an aggregate type expression (can be a
2626 declaration but does not have to be, it can for example also be a mem_ref or
2627 a series of handled components). TOP_OFFSET is the offset of the processed
2628 subtree which has to be subtracted from offsets of individual accesses to
2629 get corresponding offsets for AGG. If CHUNK_SIZE is non-null, copy only
2630 replacements in the interval <start_offset, start_offset + chunk_size>,
2631 otherwise copy all. GSI is a statement iterator used to place the new
2632 statements. WRITE should be true when the statements should write from AGG
2633 to the replacement and false if vice versa. if INSERT_AFTER is true, new
2634 statements will be added after the current statement in GSI, they will be
2635 added before the statement otherwise. */
2637 static void
2638 generate_subtree_copies (struct access *access, tree agg,
2639 HOST_WIDE_INT top_offset,
2640 HOST_WIDE_INT start_offset, HOST_WIDE_INT chunk_size,
2641 gimple_stmt_iterator *gsi, bool write,
2642 bool insert_after, location_t loc)
2646 if (chunk_size && access->offset >= start_offset + chunk_size)
2647 return;
2649 if (access->grp_to_be_replaced
2650 && (chunk_size == 0
2651 || access->offset + access->size > start_offset))
2653 tree expr, repl = get_access_replacement (access);
2654 gassign *stmt;
2656 expr = build_ref_for_model (loc, agg, access->offset - top_offset,
2657 access, gsi, insert_after);
2659 if (write)
2661 if (access->grp_partial_lhs)
2662 expr = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
2663 !insert_after,
2664 insert_after ? GSI_NEW_STMT
2665 : GSI_SAME_STMT);
2666 stmt = gimple_build_assign (repl, expr);
2668 else
2670 TREE_NO_WARNING (repl) = 1;
2671 if (access->grp_partial_lhs)
2672 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
2673 !insert_after,
2674 insert_after ? GSI_NEW_STMT
2675 : GSI_SAME_STMT);
2676 stmt = gimple_build_assign (expr, repl);
2678 gimple_set_location (stmt, loc);
2680 if (insert_after)
2681 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2682 else
2683 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2684 update_stmt (stmt);
2685 sra_stats.subtree_copies++;
2687 else if (write
2688 && access->grp_to_be_debug_replaced
2689 && (chunk_size == 0
2690 || access->offset + access->size > start_offset))
2692 gdebug *ds;
2693 tree drhs = build_debug_ref_for_model (loc, agg,
2694 access->offset - top_offset,
2695 access);
2696 ds = gimple_build_debug_bind (get_access_replacement (access),
2697 drhs, gsi_stmt (*gsi));
2698 if (insert_after)
2699 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
2700 else
2701 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
2704 if (access->first_child)
2705 generate_subtree_copies (access->first_child, agg, top_offset,
2706 start_offset, chunk_size, gsi,
2707 write, insert_after, loc);
2709 access = access->next_sibling;
2711 while (access);
2714 /* Assign zero to all scalar replacements in an access subtree. ACCESS is the
2715 the root of the subtree to be processed. GSI is the statement iterator used
2716 for inserting statements which are added after the current statement if
2717 INSERT_AFTER is true or before it otherwise. */
2719 static void
2720 init_subtree_with_zero (struct access *access, gimple_stmt_iterator *gsi,
2721 bool insert_after, location_t loc)
2724 struct access *child;
2726 if (access->grp_to_be_replaced)
2728 gassign *stmt;
2730 stmt = gimple_build_assign (get_access_replacement (access),
2731 build_zero_cst (access->type));
2732 if (insert_after)
2733 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2734 else
2735 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2736 update_stmt (stmt);
2737 gimple_set_location (stmt, loc);
2739 else if (access->grp_to_be_debug_replaced)
2741 gdebug *ds
2742 = gimple_build_debug_bind (get_access_replacement (access),
2743 build_zero_cst (access->type),
2744 gsi_stmt (*gsi));
2745 if (insert_after)
2746 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
2747 else
2748 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
2751 for (child = access->first_child; child; child = child->next_sibling)
2752 init_subtree_with_zero (child, gsi, insert_after, loc);
2755 /* Clobber all scalar replacements in an access subtree. ACCESS is the the
2756 root of the subtree to be processed. GSI is the statement iterator used
2757 for inserting statements which are added after the current statement if
2758 INSERT_AFTER is true or before it otherwise. */
2760 static void
2761 clobber_subtree (struct access *access, gimple_stmt_iterator *gsi,
2762 bool insert_after, location_t loc)
2765 struct access *child;
2767 if (access->grp_to_be_replaced)
2769 tree rep = get_access_replacement (access);
2770 tree clobber = build_constructor (access->type, NULL);
2771 TREE_THIS_VOLATILE (clobber) = 1;
2772 gimple stmt = gimple_build_assign (rep, clobber);
2774 if (insert_after)
2775 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2776 else
2777 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2778 update_stmt (stmt);
2779 gimple_set_location (stmt, loc);
2782 for (child = access->first_child; child; child = child->next_sibling)
2783 clobber_subtree (child, gsi, insert_after, loc);
2786 /* Search for an access representative for the given expression EXPR and
2787 return it or NULL if it cannot be found. */
2789 static struct access *
2790 get_access_for_expr (tree expr)
2792 HOST_WIDE_INT offset, size, max_size;
2793 tree base;
2795 /* FIXME: This should not be necessary but Ada produces V_C_Es with a type of
2796 a different size than the size of its argument and we need the latter
2797 one. */
2798 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
2799 expr = TREE_OPERAND (expr, 0);
2801 base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
2802 if (max_size == -1 || !DECL_P (base))
2803 return NULL;
2805 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
2806 return NULL;
2808 return get_var_base_offset_size_access (base, offset, max_size);
2811 /* Replace the expression EXPR with a scalar replacement if there is one and
2812 generate other statements to do type conversion or subtree copying if
2813 necessary. GSI is used to place newly created statements, WRITE is true if
2814 the expression is being written to (it is on a LHS of a statement or output
2815 in an assembly statement). */
2817 static bool
2818 sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
2820 location_t loc;
2821 struct access *access;
2822 tree type, bfr, orig_expr;
2824 if (TREE_CODE (*expr) == BIT_FIELD_REF)
2826 bfr = *expr;
2827 expr = &TREE_OPERAND (*expr, 0);
2829 else
2830 bfr = NULL_TREE;
2832 if (TREE_CODE (*expr) == REALPART_EXPR || TREE_CODE (*expr) == IMAGPART_EXPR)
2833 expr = &TREE_OPERAND (*expr, 0);
2834 access = get_access_for_expr (*expr);
2835 if (!access)
2836 return false;
2837 type = TREE_TYPE (*expr);
2838 orig_expr = *expr;
2840 loc = gimple_location (gsi_stmt (*gsi));
2841 gimple_stmt_iterator alt_gsi = gsi_none ();
2842 if (write && stmt_ends_bb_p (gsi_stmt (*gsi)))
2844 alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi)));
2845 gsi = &alt_gsi;
2848 if (access->grp_to_be_replaced)
2850 tree repl = get_access_replacement (access);
2851 /* If we replace a non-register typed access simply use the original
2852 access expression to extract the scalar component afterwards.
2853 This happens if scalarizing a function return value or parameter
2854 like in gcc.c-torture/execute/20041124-1.c, 20050316-1.c and
2855 gcc.c-torture/compile/20011217-1.c.
2857 We also want to use this when accessing a complex or vector which can
2858 be accessed as a different type too, potentially creating a need for
2859 type conversion (see PR42196) and when scalarized unions are involved
2860 in assembler statements (see PR42398). */
2861 if (!useless_type_conversion_p (type, access->type))
2863 tree ref;
2865 ref = build_ref_for_model (loc, orig_expr, 0, access, gsi, false);
2867 if (write)
2869 gassign *stmt;
2871 if (access->grp_partial_lhs)
2872 ref = force_gimple_operand_gsi (gsi, ref, true, NULL_TREE,
2873 false, GSI_NEW_STMT);
2874 stmt = gimple_build_assign (repl, ref);
2875 gimple_set_location (stmt, loc);
2876 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2878 else
2880 gassign *stmt;
2882 if (access->grp_partial_lhs)
2883 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
2884 true, GSI_SAME_STMT);
2885 stmt = gimple_build_assign (ref, repl);
2886 gimple_set_location (stmt, loc);
2887 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2890 else
2891 *expr = repl;
2892 sra_stats.exprs++;
2894 else if (write && access->grp_to_be_debug_replaced)
2896 gdebug *ds = gimple_build_debug_bind (get_access_replacement (access),
2897 NULL_TREE,
2898 gsi_stmt (*gsi));
2899 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
2902 if (access->first_child)
2904 HOST_WIDE_INT start_offset, chunk_size;
2905 if (bfr
2906 && tree_fits_uhwi_p (TREE_OPERAND (bfr, 1))
2907 && tree_fits_uhwi_p (TREE_OPERAND (bfr, 2)))
2909 chunk_size = tree_to_uhwi (TREE_OPERAND (bfr, 1));
2910 start_offset = access->offset
2911 + tree_to_uhwi (TREE_OPERAND (bfr, 2));
2913 else
2914 start_offset = chunk_size = 0;
2916 generate_subtree_copies (access->first_child, orig_expr, access->offset,
2917 start_offset, chunk_size, gsi, write, write,
2918 loc);
2920 return true;
2923 /* Where scalar replacements of the RHS have been written to when a replacement
2924 of a LHS of an assigments cannot be direclty loaded from a replacement of
2925 the RHS. */
2926 enum unscalarized_data_handling { SRA_UDH_NONE, /* Nothing done so far. */
2927 SRA_UDH_RIGHT, /* Data flushed to the RHS. */
2928 SRA_UDH_LEFT }; /* Data flushed to the LHS. */
2930 struct subreplacement_assignment_data
2932 /* Offset of the access representing the lhs of the assignment. */
2933 HOST_WIDE_INT left_offset;
2935 /* LHS and RHS of the original assignment. */
2936 tree assignment_lhs, assignment_rhs;
2938 /* Access representing the rhs of the whole assignment. */
2939 struct access *top_racc;
2941 /* Stmt iterator used for statement insertions after the original assignment.
2942 It points to the main GSI used to traverse a BB during function body
2943 modification. */
2944 gimple_stmt_iterator *new_gsi;
2946 /* Stmt iterator used for statement insertions before the original
2947 assignment. Keeps on pointing to the original statement. */
2948 gimple_stmt_iterator old_gsi;
2950 /* Location of the assignment. */
2951 location_t loc;
2953 /* Keeps the information whether we have needed to refresh replacements of
2954 the LHS and from which side of the assignments this takes place. */
2955 enum unscalarized_data_handling refreshed;
2958 /* Store all replacements in the access tree rooted in TOP_RACC either to their
2959 base aggregate if there are unscalarized data or directly to LHS of the
2960 statement that is pointed to by GSI otherwise. */
2962 static void
2963 handle_unscalarized_data_in_subtree (struct subreplacement_assignment_data *sad)
2965 tree src;
2966 if (sad->top_racc->grp_unscalarized_data)
2968 src = sad->assignment_rhs;
2969 sad->refreshed = SRA_UDH_RIGHT;
2971 else
2973 src = sad->assignment_lhs;
2974 sad->refreshed = SRA_UDH_LEFT;
2976 generate_subtree_copies (sad->top_racc->first_child, src,
2977 sad->top_racc->offset, 0, 0,
2978 &sad->old_gsi, false, false, sad->loc);
2981 /* Try to generate statements to load all sub-replacements in an access subtree
2982 formed by children of LACC from scalar replacements in the SAD->top_racc
2983 subtree. If that is not possible, refresh the SAD->top_racc base aggregate
2984 and load the accesses from it. */
2986 static void
2987 load_assign_lhs_subreplacements (struct access *lacc,
2988 struct subreplacement_assignment_data *sad)
2990 for (lacc = lacc->first_child; lacc; lacc = lacc->next_sibling)
2992 HOST_WIDE_INT offset;
2993 offset = lacc->offset - sad->left_offset + sad->top_racc->offset;
2995 if (lacc->grp_to_be_replaced)
2997 struct access *racc;
2998 gassign *stmt;
2999 tree rhs;
3001 racc = find_access_in_subtree (sad->top_racc, offset, lacc->size);
3002 if (racc && racc->grp_to_be_replaced)
3004 rhs = get_access_replacement (racc);
3005 if (!useless_type_conversion_p (lacc->type, racc->type))
3006 rhs = fold_build1_loc (sad->loc, VIEW_CONVERT_EXPR,
3007 lacc->type, rhs);
3009 if (racc->grp_partial_lhs && lacc->grp_partial_lhs)
3010 rhs = force_gimple_operand_gsi (&sad->old_gsi, rhs, true,
3011 NULL_TREE, true, GSI_SAME_STMT);
3013 else
3015 /* No suitable access on the right hand side, need to load from
3016 the aggregate. See if we have to update it first... */
3017 if (sad->refreshed == SRA_UDH_NONE)
3018 handle_unscalarized_data_in_subtree (sad);
3020 if (sad->refreshed == SRA_UDH_LEFT)
3021 rhs = build_ref_for_model (sad->loc, sad->assignment_lhs,
3022 lacc->offset - sad->left_offset,
3023 lacc, sad->new_gsi, true);
3024 else
3025 rhs = build_ref_for_model (sad->loc, sad->assignment_rhs,
3026 lacc->offset - sad->left_offset,
3027 lacc, sad->new_gsi, true);
3028 if (lacc->grp_partial_lhs)
3029 rhs = force_gimple_operand_gsi (sad->new_gsi,
3030 rhs, true, NULL_TREE,
3031 false, GSI_NEW_STMT);
3034 stmt = gimple_build_assign (get_access_replacement (lacc), rhs);
3035 gsi_insert_after (sad->new_gsi, stmt, GSI_NEW_STMT);
3036 gimple_set_location (stmt, sad->loc);
3037 update_stmt (stmt);
3038 sra_stats.subreplacements++;
3040 else
3042 if (sad->refreshed == SRA_UDH_NONE
3043 && lacc->grp_read && !lacc->grp_covered)
3044 handle_unscalarized_data_in_subtree (sad);
3046 if (lacc && lacc->grp_to_be_debug_replaced)
3048 gdebug *ds;
3049 tree drhs;
3050 struct access *racc = find_access_in_subtree (sad->top_racc,
3051 offset,
3052 lacc->size);
3054 if (racc && racc->grp_to_be_replaced)
3056 if (racc->grp_write)
3057 drhs = get_access_replacement (racc);
3058 else
3059 drhs = NULL;
3061 else if (sad->refreshed == SRA_UDH_LEFT)
3062 drhs = build_debug_ref_for_model (sad->loc, lacc->base,
3063 lacc->offset, lacc);
3064 else if (sad->refreshed == SRA_UDH_RIGHT)
3065 drhs = build_debug_ref_for_model (sad->loc, sad->top_racc->base,
3066 offset, lacc);
3067 else
3068 drhs = NULL_TREE;
3069 if (drhs
3070 && !useless_type_conversion_p (lacc->type, TREE_TYPE (drhs)))
3071 drhs = fold_build1_loc (sad->loc, VIEW_CONVERT_EXPR,
3072 lacc->type, drhs);
3073 ds = gimple_build_debug_bind (get_access_replacement (lacc),
3074 drhs, gsi_stmt (sad->old_gsi));
3075 gsi_insert_after (sad->new_gsi, ds, GSI_NEW_STMT);
3079 if (lacc->first_child)
3080 load_assign_lhs_subreplacements (lacc, sad);
3084 /* Result code for SRA assignment modification. */
3085 enum assignment_mod_result { SRA_AM_NONE, /* nothing done for the stmt */
3086 SRA_AM_MODIFIED, /* stmt changed but not
3087 removed */
3088 SRA_AM_REMOVED }; /* stmt eliminated */
3090 /* Modify assignments with a CONSTRUCTOR on their RHS. STMT contains a pointer
3091 to the assignment and GSI is the statement iterator pointing at it. Returns
3092 the same values as sra_modify_assign. */
3094 static enum assignment_mod_result
3095 sra_modify_constructor_assign (gimple stmt, gimple_stmt_iterator *gsi)
3097 tree lhs = gimple_assign_lhs (stmt);
3098 struct access *acc = get_access_for_expr (lhs);
3099 if (!acc)
3100 return SRA_AM_NONE;
3101 location_t loc = gimple_location (stmt);
3103 if (gimple_clobber_p (stmt))
3105 /* Clobber the replacement variable. */
3106 clobber_subtree (acc, gsi, !acc->grp_covered, loc);
3107 /* Remove clobbers of fully scalarized variables, they are dead. */
3108 if (acc->grp_covered)
3110 unlink_stmt_vdef (stmt);
3111 gsi_remove (gsi, true);
3112 release_defs (stmt);
3113 return SRA_AM_REMOVED;
3115 else
3116 return SRA_AM_MODIFIED;
3119 if (vec_safe_length (CONSTRUCTOR_ELTS (gimple_assign_rhs1 (stmt))) > 0)
3121 /* I have never seen this code path trigger but if it can happen the
3122 following should handle it gracefully. */
3123 if (access_has_children_p (acc))
3124 generate_subtree_copies (acc->first_child, lhs, acc->offset, 0, 0, gsi,
3125 true, true, loc);
3126 return SRA_AM_MODIFIED;
3129 if (acc->grp_covered)
3131 init_subtree_with_zero (acc, gsi, false, loc);
3132 unlink_stmt_vdef (stmt);
3133 gsi_remove (gsi, true);
3134 release_defs (stmt);
3135 return SRA_AM_REMOVED;
3137 else
3139 init_subtree_with_zero (acc, gsi, true, loc);
3140 return SRA_AM_MODIFIED;
3144 /* Create and return a new suitable default definition SSA_NAME for RACC which
3145 is an access describing an uninitialized part of an aggregate that is being
3146 loaded. */
3148 static tree
3149 get_repl_default_def_ssa_name (struct access *racc)
3151 gcc_checking_assert (!racc->grp_to_be_replaced
3152 && !racc->grp_to_be_debug_replaced);
3153 if (!racc->replacement_decl)
3154 racc->replacement_decl = create_access_replacement (racc);
3155 return get_or_create_ssa_default_def (cfun, racc->replacement_decl);
3158 /* Return true if REF has an VIEW_CONVERT_EXPR or a COMPONENT_REF with a
3159 bit-field field declaration somewhere in it. */
3161 static inline bool
3162 contains_vce_or_bfcref_p (const_tree ref)
3164 while (handled_component_p (ref))
3166 if (TREE_CODE (ref) == VIEW_CONVERT_EXPR
3167 || (TREE_CODE (ref) == COMPONENT_REF
3168 && DECL_BIT_FIELD (TREE_OPERAND (ref, 1))))
3169 return true;
3170 ref = TREE_OPERAND (ref, 0);
3173 return false;
3176 /* Examine both sides of the assignment statement pointed to by STMT, replace
3177 them with a scalare replacement if there is one and generate copying of
3178 replacements if scalarized aggregates have been used in the assignment. GSI
3179 is used to hold generated statements for type conversions and subtree
3180 copying. */
3182 static enum assignment_mod_result
3183 sra_modify_assign (gimple stmt, gimple_stmt_iterator *gsi)
3185 struct access *lacc, *racc;
3186 tree lhs, rhs;
3187 bool modify_this_stmt = false;
3188 bool force_gimple_rhs = false;
3189 location_t loc;
3190 gimple_stmt_iterator orig_gsi = *gsi;
3192 if (!gimple_assign_single_p (stmt))
3193 return SRA_AM_NONE;
3194 lhs = gimple_assign_lhs (stmt);
3195 rhs = gimple_assign_rhs1 (stmt);
3197 if (TREE_CODE (rhs) == CONSTRUCTOR)
3198 return sra_modify_constructor_assign (stmt, gsi);
3200 if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (lhs) == REALPART_EXPR
3201 || TREE_CODE (rhs) == IMAGPART_EXPR || TREE_CODE (lhs) == IMAGPART_EXPR
3202 || TREE_CODE (rhs) == BIT_FIELD_REF || TREE_CODE (lhs) == BIT_FIELD_REF)
3204 modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (stmt),
3205 gsi, false);
3206 modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (stmt),
3207 gsi, true);
3208 return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
3211 lacc = get_access_for_expr (lhs);
3212 racc = get_access_for_expr (rhs);
3213 if (!lacc && !racc)
3214 return SRA_AM_NONE;
3216 loc = gimple_location (stmt);
3217 if (lacc && lacc->grp_to_be_replaced)
3219 lhs = get_access_replacement (lacc);
3220 gimple_assign_set_lhs (stmt, lhs);
3221 modify_this_stmt = true;
3222 if (lacc->grp_partial_lhs)
3223 force_gimple_rhs = true;
3224 sra_stats.exprs++;
3227 if (racc && racc->grp_to_be_replaced)
3229 rhs = get_access_replacement (racc);
3230 modify_this_stmt = true;
3231 if (racc->grp_partial_lhs)
3232 force_gimple_rhs = true;
3233 sra_stats.exprs++;
3235 else if (racc
3236 && !racc->grp_unscalarized_data
3237 && TREE_CODE (lhs) == SSA_NAME
3238 && !access_has_replacements_p (racc))
3240 rhs = get_repl_default_def_ssa_name (racc);
3241 modify_this_stmt = true;
3242 sra_stats.exprs++;
3245 if (modify_this_stmt)
3247 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
3249 /* If we can avoid creating a VIEW_CONVERT_EXPR do so.
3250 ??? This should move to fold_stmt which we simply should
3251 call after building a VIEW_CONVERT_EXPR here. */
3252 if (AGGREGATE_TYPE_P (TREE_TYPE (lhs))
3253 && !contains_bitfld_component_ref_p (lhs))
3255 lhs = build_ref_for_model (loc, lhs, 0, racc, gsi, false);
3256 gimple_assign_set_lhs (stmt, lhs);
3258 else if (AGGREGATE_TYPE_P (TREE_TYPE (rhs))
3259 && !contains_vce_or_bfcref_p (rhs))
3260 rhs = build_ref_for_model (loc, rhs, 0, lacc, gsi, false);
3262 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
3264 rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
3265 rhs);
3266 if (is_gimple_reg_type (TREE_TYPE (lhs))
3267 && TREE_CODE (lhs) != SSA_NAME)
3268 force_gimple_rhs = true;
3273 if (lacc && lacc->grp_to_be_debug_replaced)
3275 tree dlhs = get_access_replacement (lacc);
3276 tree drhs = unshare_expr (rhs);
3277 if (!useless_type_conversion_p (TREE_TYPE (dlhs), TREE_TYPE (drhs)))
3279 if (AGGREGATE_TYPE_P (TREE_TYPE (drhs))
3280 && !contains_vce_or_bfcref_p (drhs))
3281 drhs = build_debug_ref_for_model (loc, drhs, 0, lacc);
3282 if (drhs
3283 && !useless_type_conversion_p (TREE_TYPE (dlhs),
3284 TREE_TYPE (drhs)))
3285 drhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
3286 TREE_TYPE (dlhs), drhs);
3288 gdebug *ds = gimple_build_debug_bind (dlhs, drhs, stmt);
3289 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
3292 /* From this point on, the function deals with assignments in between
3293 aggregates when at least one has scalar reductions of some of its
3294 components. There are three possible scenarios: Both the LHS and RHS have
3295 to-be-scalarized components, 2) only the RHS has or 3) only the LHS has.
3297 In the first case, we would like to load the LHS components from RHS
3298 components whenever possible. If that is not possible, we would like to
3299 read it directly from the RHS (after updating it by storing in it its own
3300 components). If there are some necessary unscalarized data in the LHS,
3301 those will be loaded by the original assignment too. If neither of these
3302 cases happen, the original statement can be removed. Most of this is done
3303 by load_assign_lhs_subreplacements.
3305 In the second case, we would like to store all RHS scalarized components
3306 directly into LHS and if they cover the aggregate completely, remove the
3307 statement too. In the third case, we want the LHS components to be loaded
3308 directly from the RHS (DSE will remove the original statement if it
3309 becomes redundant).
3311 This is a bit complex but manageable when types match and when unions do
3312 not cause confusion in a way that we cannot really load a component of LHS
3313 from the RHS or vice versa (the access representing this level can have
3314 subaccesses that are accessible only through a different union field at a
3315 higher level - different from the one used in the examined expression).
3316 Unions are fun.
3318 Therefore, I specially handle a fourth case, happening when there is a
3319 specific type cast or it is impossible to locate a scalarized subaccess on
3320 the other side of the expression. If that happens, I simply "refresh" the
3321 RHS by storing in it is scalarized components leave the original statement
3322 there to do the copying and then load the scalar replacements of the LHS.
3323 This is what the first branch does. */
3325 if (modify_this_stmt
3326 || gimple_has_volatile_ops (stmt)
3327 || contains_vce_or_bfcref_p (rhs)
3328 || contains_vce_or_bfcref_p (lhs)
3329 || stmt_ends_bb_p (stmt))
3331 if (access_has_children_p (racc))
3332 generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0,
3333 gsi, false, false, loc);
3334 if (access_has_children_p (lacc))
3336 gimple_stmt_iterator alt_gsi = gsi_none ();
3337 if (stmt_ends_bb_p (stmt))
3339 alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi)));
3340 gsi = &alt_gsi;
3342 generate_subtree_copies (lacc->first_child, lhs, lacc->offset, 0, 0,
3343 gsi, true, true, loc);
3345 sra_stats.separate_lhs_rhs_handling++;
3347 /* This gimplification must be done after generate_subtree_copies,
3348 lest we insert the subtree copies in the middle of the gimplified
3349 sequence. */
3350 if (force_gimple_rhs)
3351 rhs = force_gimple_operand_gsi (&orig_gsi, rhs, true, NULL_TREE,
3352 true, GSI_SAME_STMT);
3353 if (gimple_assign_rhs1 (stmt) != rhs)
3355 modify_this_stmt = true;
3356 gimple_assign_set_rhs_from_tree (&orig_gsi, rhs);
3357 gcc_assert (stmt == gsi_stmt (orig_gsi));
3360 return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
3362 else
3364 if (access_has_children_p (lacc)
3365 && access_has_children_p (racc)
3366 /* When an access represents an unscalarizable region, it usually
3367 represents accesses with variable offset and thus must not be used
3368 to generate new memory accesses. */
3369 && !lacc->grp_unscalarizable_region
3370 && !racc->grp_unscalarizable_region)
3372 struct subreplacement_assignment_data sad;
3374 sad.left_offset = lacc->offset;
3375 sad.assignment_lhs = lhs;
3376 sad.assignment_rhs = rhs;
3377 sad.top_racc = racc;
3378 sad.old_gsi = *gsi;
3379 sad.new_gsi = gsi;
3380 sad.loc = gimple_location (stmt);
3381 sad.refreshed = SRA_UDH_NONE;
3383 if (lacc->grp_read && !lacc->grp_covered)
3384 handle_unscalarized_data_in_subtree (&sad);
3386 load_assign_lhs_subreplacements (lacc, &sad);
3387 if (sad.refreshed != SRA_UDH_RIGHT)
3389 gsi_next (gsi);
3390 unlink_stmt_vdef (stmt);
3391 gsi_remove (&sad.old_gsi, true);
3392 release_defs (stmt);
3393 sra_stats.deleted++;
3394 return SRA_AM_REMOVED;
3397 else
3399 if (access_has_children_p (racc)
3400 && !racc->grp_unscalarized_data)
3402 if (dump_file)
3404 fprintf (dump_file, "Removing load: ");
3405 print_gimple_stmt (dump_file, stmt, 0, 0);
3407 generate_subtree_copies (racc->first_child, lhs,
3408 racc->offset, 0, 0, gsi,
3409 false, false, loc);
3410 gcc_assert (stmt == gsi_stmt (*gsi));
3411 unlink_stmt_vdef (stmt);
3412 gsi_remove (gsi, true);
3413 release_defs (stmt);
3414 sra_stats.deleted++;
3415 return SRA_AM_REMOVED;
3417 /* Restore the aggregate RHS from its components so the
3418 prevailing aggregate copy does the right thing. */
3419 if (access_has_children_p (racc))
3420 generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0,
3421 gsi, false, false, loc);
3422 /* Re-load the components of the aggregate copy destination.
3423 But use the RHS aggregate to load from to expose more
3424 optimization opportunities. */
3425 if (access_has_children_p (lacc))
3426 generate_subtree_copies (lacc->first_child, rhs, lacc->offset,
3427 0, 0, gsi, true, true, loc);
3430 return SRA_AM_NONE;
3434 /* Traverse the function body and all modifications as decided in
3435 analyze_all_variable_accesses. Return true iff the CFG has been
3436 changed. */
3438 static bool
3439 sra_modify_function_body (void)
3441 bool cfg_changed = false;
3442 basic_block bb;
3444 FOR_EACH_BB_FN (bb, cfun)
3446 gimple_stmt_iterator gsi = gsi_start_bb (bb);
3447 while (!gsi_end_p (gsi))
3449 gimple stmt = gsi_stmt (gsi);
3450 enum assignment_mod_result assign_result;
3451 bool modified = false, deleted = false;
3452 tree *t;
3453 unsigned i;
3455 switch (gimple_code (stmt))
3457 case GIMPLE_RETURN:
3458 t = gimple_return_retval_ptr (as_a <greturn *> (stmt));
3459 if (*t != NULL_TREE)
3460 modified |= sra_modify_expr (t, &gsi, false);
3461 break;
3463 case GIMPLE_ASSIGN:
3464 assign_result = sra_modify_assign (stmt, &gsi);
3465 modified |= assign_result == SRA_AM_MODIFIED;
3466 deleted = assign_result == SRA_AM_REMOVED;
3467 break;
3469 case GIMPLE_CALL:
3470 /* Operands must be processed before the lhs. */
3471 for (i = 0; i < gimple_call_num_args (stmt); i++)
3473 t = gimple_call_arg_ptr (stmt, i);
3474 modified |= sra_modify_expr (t, &gsi, false);
3477 if (gimple_call_lhs (stmt))
3479 t = gimple_call_lhs_ptr (stmt);
3480 modified |= sra_modify_expr (t, &gsi, true);
3482 break;
3484 case GIMPLE_ASM:
3486 gasm *asm_stmt = as_a <gasm *> (stmt);
3487 for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
3489 t = &TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
3490 modified |= sra_modify_expr (t, &gsi, false);
3492 for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
3494 t = &TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
3495 modified |= sra_modify_expr (t, &gsi, true);
3498 break;
3500 default:
3501 break;
3504 if (modified)
3506 update_stmt (stmt);
3507 if (maybe_clean_eh_stmt (stmt)
3508 && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
3509 cfg_changed = true;
3511 if (!deleted)
3512 gsi_next (&gsi);
3516 gsi_commit_edge_inserts ();
3517 return cfg_changed;
3520 /* Generate statements initializing scalar replacements of parts of function
3521 parameters. */
3523 static void
3524 initialize_parameter_reductions (void)
3526 gimple_stmt_iterator gsi;
3527 gimple_seq seq = NULL;
3528 tree parm;
3530 gsi = gsi_start (seq);
3531 for (parm = DECL_ARGUMENTS (current_function_decl);
3532 parm;
3533 parm = DECL_CHAIN (parm))
3535 vec<access_p> *access_vec;
3536 struct access *access;
3538 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
3539 continue;
3540 access_vec = get_base_access_vector (parm);
3541 if (!access_vec)
3542 continue;
3544 for (access = (*access_vec)[0];
3545 access;
3546 access = access->next_grp)
3547 generate_subtree_copies (access, parm, 0, 0, 0, &gsi, true, true,
3548 EXPR_LOCATION (parm));
3551 seq = gsi_seq (gsi);
3552 if (seq)
3553 gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
3556 /* The "main" function of intraprocedural SRA passes. Runs the analysis and if
3557 it reveals there are components of some aggregates to be scalarized, it runs
3558 the required transformations. */
3559 static unsigned int
3560 perform_intra_sra (void)
3562 int ret = 0;
3563 sra_initialize ();
3565 if (!find_var_candidates ())
3566 goto out;
3568 if (!scan_function ())
3569 goto out;
3571 if (!analyze_all_variable_accesses ())
3572 goto out;
3574 if (sra_modify_function_body ())
3575 ret = TODO_update_ssa | TODO_cleanup_cfg;
3576 else
3577 ret = TODO_update_ssa;
3578 initialize_parameter_reductions ();
3580 statistics_counter_event (cfun, "Scalar replacements created",
3581 sra_stats.replacements);
3582 statistics_counter_event (cfun, "Modified expressions", sra_stats.exprs);
3583 statistics_counter_event (cfun, "Subtree copy stmts",
3584 sra_stats.subtree_copies);
3585 statistics_counter_event (cfun, "Subreplacement stmts",
3586 sra_stats.subreplacements);
3587 statistics_counter_event (cfun, "Deleted stmts", sra_stats.deleted);
3588 statistics_counter_event (cfun, "Separate LHS and RHS handling",
3589 sra_stats.separate_lhs_rhs_handling);
3591 out:
3592 sra_deinitialize ();
3593 return ret;
3596 /* Perform early intraprocedural SRA. */
3597 static unsigned int
3598 early_intra_sra (void)
3600 sra_mode = SRA_MODE_EARLY_INTRA;
3601 return perform_intra_sra ();
3604 /* Perform "late" intraprocedural SRA. */
3605 static unsigned int
3606 late_intra_sra (void)
3608 sra_mode = SRA_MODE_INTRA;
3609 return perform_intra_sra ();
3613 static bool
3614 gate_intra_sra (void)
3616 return flag_tree_sra != 0 && dbg_cnt (tree_sra);
3620 namespace {
3622 const pass_data pass_data_sra_early =
3624 GIMPLE_PASS, /* type */
3625 "esra", /* name */
3626 OPTGROUP_NONE, /* optinfo_flags */
3627 TV_TREE_SRA, /* tv_id */
3628 ( PROP_cfg | PROP_ssa ), /* properties_required */
3629 0, /* properties_provided */
3630 0, /* properties_destroyed */
3631 0, /* todo_flags_start */
3632 TODO_update_ssa, /* todo_flags_finish */
3635 class pass_sra_early : public gimple_opt_pass
3637 public:
3638 pass_sra_early (gcc::context *ctxt)
3639 : gimple_opt_pass (pass_data_sra_early, ctxt)
3642 /* opt_pass methods: */
3643 virtual bool gate (function *) { return gate_intra_sra (); }
3644 virtual unsigned int execute (function *) { return early_intra_sra (); }
3646 }; // class pass_sra_early
3648 } // anon namespace
3650 gimple_opt_pass *
3651 make_pass_sra_early (gcc::context *ctxt)
3653 return new pass_sra_early (ctxt);
3656 namespace {
3658 const pass_data pass_data_sra =
3660 GIMPLE_PASS, /* type */
3661 "sra", /* name */
3662 OPTGROUP_NONE, /* optinfo_flags */
3663 TV_TREE_SRA, /* tv_id */
3664 ( PROP_cfg | PROP_ssa ), /* properties_required */
3665 0, /* properties_provided */
3666 0, /* properties_destroyed */
3667 TODO_update_address_taken, /* todo_flags_start */
3668 TODO_update_ssa, /* todo_flags_finish */
3671 class pass_sra : public gimple_opt_pass
3673 public:
3674 pass_sra (gcc::context *ctxt)
3675 : gimple_opt_pass (pass_data_sra, ctxt)
3678 /* opt_pass methods: */
3679 virtual bool gate (function *) { return gate_intra_sra (); }
3680 virtual unsigned int execute (function *) { return late_intra_sra (); }
3682 }; // class pass_sra
3684 } // anon namespace
3686 gimple_opt_pass *
3687 make_pass_sra (gcc::context *ctxt)
3689 return new pass_sra (ctxt);
3693 /* Return true iff PARM (which must be a parm_decl) is an unused scalar
3694 parameter. */
3696 static bool
3697 is_unused_scalar_param (tree parm)
3699 tree name;
3700 return (is_gimple_reg (parm)
3701 && (!(name = ssa_default_def (cfun, parm))
3702 || has_zero_uses (name)));
3705 /* Scan immediate uses of a default definition SSA name of a parameter PARM and
3706 examine whether there are any direct or otherwise infeasible ones. If so,
3707 return true, otherwise return false. PARM must be a gimple register with a
3708 non-NULL default definition. */
3710 static bool
3711 ptr_parm_has_direct_uses (tree parm)
3713 imm_use_iterator ui;
3714 gimple stmt;
3715 tree name = ssa_default_def (cfun, parm);
3716 bool ret = false;
3718 FOR_EACH_IMM_USE_STMT (stmt, ui, name)
3720 int uses_ok = 0;
3721 use_operand_p use_p;
3723 if (is_gimple_debug (stmt))
3724 continue;
3726 /* Valid uses include dereferences on the lhs and the rhs. */
3727 if (gimple_has_lhs (stmt))
3729 tree lhs = gimple_get_lhs (stmt);
3730 while (handled_component_p (lhs))
3731 lhs = TREE_OPERAND (lhs, 0);
3732 if (TREE_CODE (lhs) == MEM_REF
3733 && TREE_OPERAND (lhs, 0) == name
3734 && integer_zerop (TREE_OPERAND (lhs, 1))
3735 && types_compatible_p (TREE_TYPE (lhs),
3736 TREE_TYPE (TREE_TYPE (name)))
3737 && !TREE_THIS_VOLATILE (lhs))
3738 uses_ok++;
3740 if (gimple_assign_single_p (stmt))
3742 tree rhs = gimple_assign_rhs1 (stmt);
3743 while (handled_component_p (rhs))
3744 rhs = TREE_OPERAND (rhs, 0);
3745 if (TREE_CODE (rhs) == MEM_REF
3746 && TREE_OPERAND (rhs, 0) == name
3747 && integer_zerop (TREE_OPERAND (rhs, 1))
3748 && types_compatible_p (TREE_TYPE (rhs),
3749 TREE_TYPE (TREE_TYPE (name)))
3750 && !TREE_THIS_VOLATILE (rhs))
3751 uses_ok++;
3753 else if (is_gimple_call (stmt))
3755 unsigned i;
3756 for (i = 0; i < gimple_call_num_args (stmt); ++i)
3758 tree arg = gimple_call_arg (stmt, i);
3759 while (handled_component_p (arg))
3760 arg = TREE_OPERAND (arg, 0);
3761 if (TREE_CODE (arg) == MEM_REF
3762 && TREE_OPERAND (arg, 0) == name
3763 && integer_zerop (TREE_OPERAND (arg, 1))
3764 && types_compatible_p (TREE_TYPE (arg),
3765 TREE_TYPE (TREE_TYPE (name)))
3766 && !TREE_THIS_VOLATILE (arg))
3767 uses_ok++;
3771 /* If the number of valid uses does not match the number of
3772 uses in this stmt there is an unhandled use. */
3773 FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
3774 --uses_ok;
3776 if (uses_ok != 0)
3777 ret = true;
3779 if (ret)
3780 BREAK_FROM_IMM_USE_STMT (ui);
3783 return ret;
3786 /* Identify candidates for reduction for IPA-SRA based on their type and mark
3787 them in candidate_bitmap. Note that these do not necessarily include
3788 parameter which are unused and thus can be removed. Return true iff any
3789 such candidate has been found. */
3791 static bool
3792 find_param_candidates (void)
3794 tree parm;
3795 int count = 0;
3796 bool ret = false;
3797 const char *msg;
3799 for (parm = DECL_ARGUMENTS (current_function_decl);
3800 parm;
3801 parm = DECL_CHAIN (parm))
3803 tree type = TREE_TYPE (parm);
3804 tree_node **slot;
3806 count++;
3808 if (TREE_THIS_VOLATILE (parm)
3809 || TREE_ADDRESSABLE (parm)
3810 || (!is_gimple_reg_type (type) && is_va_list_type (type)))
3811 continue;
3813 if (is_unused_scalar_param (parm))
3815 ret = true;
3816 continue;
3819 if (POINTER_TYPE_P (type))
3821 type = TREE_TYPE (type);
3823 if (TREE_CODE (type) == FUNCTION_TYPE
3824 || TYPE_VOLATILE (type)
3825 || (TREE_CODE (type) == ARRAY_TYPE
3826 && TYPE_NONALIASED_COMPONENT (type))
3827 || !is_gimple_reg (parm)
3828 || is_va_list_type (type)
3829 || ptr_parm_has_direct_uses (parm))
3830 continue;
3832 else if (!AGGREGATE_TYPE_P (type))
3833 continue;
3835 if (!COMPLETE_TYPE_P (type)
3836 || !tree_fits_uhwi_p (TYPE_SIZE (type))
3837 || tree_to_uhwi (TYPE_SIZE (type)) == 0
3838 || (AGGREGATE_TYPE_P (type)
3839 && type_internals_preclude_sra_p (type, &msg)))
3840 continue;
3842 bitmap_set_bit (candidate_bitmap, DECL_UID (parm));
3843 slot = candidates->find_slot_with_hash (parm, DECL_UID (parm), INSERT);
3844 *slot = parm;
3846 ret = true;
3847 if (dump_file && (dump_flags & TDF_DETAILS))
3849 fprintf (dump_file, "Candidate (%d): ", DECL_UID (parm));
3850 print_generic_expr (dump_file, parm, 0);
3851 fprintf (dump_file, "\n");
3855 func_param_count = count;
3856 return ret;
3859 /* Callback of walk_aliased_vdefs, marks the access passed as DATA as
3860 maybe_modified. */
3862 static bool
3863 mark_maybe_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
3864 void *data)
3866 struct access *repr = (struct access *) data;
3868 repr->grp_maybe_modified = 1;
3869 return true;
3872 /* Analyze what representatives (in linked lists accessible from
3873 REPRESENTATIVES) can be modified by side effects of statements in the
3874 current function. */
3876 static void
3877 analyze_modified_params (vec<access_p> representatives)
3879 int i;
3881 for (i = 0; i < func_param_count; i++)
3883 struct access *repr;
3885 for (repr = representatives[i];
3886 repr;
3887 repr = repr->next_grp)
3889 struct access *access;
3890 bitmap visited;
3891 ao_ref ar;
3893 if (no_accesses_p (repr))
3894 continue;
3895 if (!POINTER_TYPE_P (TREE_TYPE (repr->base))
3896 || repr->grp_maybe_modified)
3897 continue;
3899 ao_ref_init (&ar, repr->expr);
3900 visited = BITMAP_ALLOC (NULL);
3901 for (access = repr; access; access = access->next_sibling)
3903 /* All accesses are read ones, otherwise grp_maybe_modified would
3904 be trivially set. */
3905 walk_aliased_vdefs (&ar, gimple_vuse (access->stmt),
3906 mark_maybe_modified, repr, &visited);
3907 if (repr->grp_maybe_modified)
3908 break;
3910 BITMAP_FREE (visited);
3915 /* Propagate distances in bb_dereferences in the opposite direction than the
3916 control flow edges, in each step storing the maximum of the current value
3917 and the minimum of all successors. These steps are repeated until the table
3918 stabilizes. Note that BBs which might terminate the functions (according to
3919 final_bbs bitmap) never updated in this way. */
3921 static void
3922 propagate_dereference_distances (void)
3924 basic_block bb;
3926 auto_vec<basic_block> queue (last_basic_block_for_fn (cfun));
3927 queue.quick_push (ENTRY_BLOCK_PTR_FOR_FN (cfun));
3928 FOR_EACH_BB_FN (bb, cfun)
3930 queue.quick_push (bb);
3931 bb->aux = bb;
3934 while (!queue.is_empty ())
3936 edge_iterator ei;
3937 edge e;
3938 bool change = false;
3939 int i;
3941 bb = queue.pop ();
3942 bb->aux = NULL;
3944 if (bitmap_bit_p (final_bbs, bb->index))
3945 continue;
3947 for (i = 0; i < func_param_count; i++)
3949 int idx = bb->index * func_param_count + i;
3950 bool first = true;
3951 HOST_WIDE_INT inh = 0;
3953 FOR_EACH_EDGE (e, ei, bb->succs)
3955 int succ_idx = e->dest->index * func_param_count + i;
3957 if (e->src == EXIT_BLOCK_PTR_FOR_FN (cfun))
3958 continue;
3960 if (first)
3962 first = false;
3963 inh = bb_dereferences [succ_idx];
3965 else if (bb_dereferences [succ_idx] < inh)
3966 inh = bb_dereferences [succ_idx];
3969 if (!first && bb_dereferences[idx] < inh)
3971 bb_dereferences[idx] = inh;
3972 change = true;
3976 if (change && !bitmap_bit_p (final_bbs, bb->index))
3977 FOR_EACH_EDGE (e, ei, bb->preds)
3979 if (e->src->aux)
3980 continue;
3982 e->src->aux = e->src;
3983 queue.quick_push (e->src);
3988 /* Dump a dereferences TABLE with heading STR to file F. */
3990 static void
3991 dump_dereferences_table (FILE *f, const char *str, HOST_WIDE_INT *table)
3993 basic_block bb;
3995 fprintf (dump_file, "%s", str);
3996 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun),
3997 EXIT_BLOCK_PTR_FOR_FN (cfun), next_bb)
3999 fprintf (f, "%4i %i ", bb->index, bitmap_bit_p (final_bbs, bb->index));
4000 if (bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
4002 int i;
4003 for (i = 0; i < func_param_count; i++)
4005 int idx = bb->index * func_param_count + i;
4006 fprintf (f, " %4" HOST_WIDE_INT_PRINT "d", table[idx]);
4009 fprintf (f, "\n");
4011 fprintf (dump_file, "\n");
4014 /* Determine what (parts of) parameters passed by reference that are not
4015 assigned to are not certainly dereferenced in this function and thus the
4016 dereferencing cannot be safely moved to the caller without potentially
4017 introducing a segfault. Mark such REPRESENTATIVES as
4018 grp_not_necessarilly_dereferenced.
4020 The dereferenced maximum "distance," i.e. the offset + size of the accessed
4021 part is calculated rather than simple booleans are calculated for each
4022 pointer parameter to handle cases when only a fraction of the whole
4023 aggregate is allocated (see testsuite/gcc.c-torture/execute/ipa-sra-2.c for
4024 an example).
4026 The maximum dereference distances for each pointer parameter and BB are
4027 already stored in bb_dereference. This routine simply propagates these
4028 values upwards by propagate_dereference_distances and then compares the
4029 distances of individual parameters in the ENTRY BB to the equivalent
4030 distances of each representative of a (fraction of a) parameter. */
4032 static void
4033 analyze_caller_dereference_legality (vec<access_p> representatives)
4035 int i;
4037 if (dump_file && (dump_flags & TDF_DETAILS))
4038 dump_dereferences_table (dump_file,
4039 "Dereference table before propagation:\n",
4040 bb_dereferences);
4042 propagate_dereference_distances ();
4044 if (dump_file && (dump_flags & TDF_DETAILS))
4045 dump_dereferences_table (dump_file,
4046 "Dereference table after propagation:\n",
4047 bb_dereferences);
4049 for (i = 0; i < func_param_count; i++)
4051 struct access *repr = representatives[i];
4052 int idx = ENTRY_BLOCK_PTR_FOR_FN (cfun)->index * func_param_count + i;
4054 if (!repr || no_accesses_p (repr))
4055 continue;
4059 if ((repr->offset + repr->size) > bb_dereferences[idx])
4060 repr->grp_not_necessarilly_dereferenced = 1;
4061 repr = repr->next_grp;
4063 while (repr);
4067 /* Return the representative access for the parameter declaration PARM if it is
4068 a scalar passed by reference which is not written to and the pointer value
4069 is not used directly. Thus, if it is legal to dereference it in the caller
4070 and we can rule out modifications through aliases, such parameter should be
4071 turned into one passed by value. Return NULL otherwise. */
4073 static struct access *
4074 unmodified_by_ref_scalar_representative (tree parm)
4076 int i, access_count;
4077 struct access *repr;
4078 vec<access_p> *access_vec;
4080 access_vec = get_base_access_vector (parm);
4081 gcc_assert (access_vec);
4082 repr = (*access_vec)[0];
4083 if (repr->write)
4084 return NULL;
4085 repr->group_representative = repr;
4087 access_count = access_vec->length ();
4088 for (i = 1; i < access_count; i++)
4090 struct access *access = (*access_vec)[i];
4091 if (access->write)
4092 return NULL;
4093 access->group_representative = repr;
4094 access->next_sibling = repr->next_sibling;
4095 repr->next_sibling = access;
4098 repr->grp_read = 1;
4099 repr->grp_scalar_ptr = 1;
4100 return repr;
4103 /* Return true iff this ACCESS precludes IPA-SRA of the parameter it is
4104 associated with. REQ_ALIGN is the minimum required alignment. */
4106 static bool
4107 access_precludes_ipa_sra_p (struct access *access, unsigned int req_align)
4109 unsigned int exp_align;
4110 /* Avoid issues such as the second simple testcase in PR 42025. The problem
4111 is incompatible assign in a call statement (and possibly even in asm
4112 statements). This can be relaxed by using a new temporary but only for
4113 non-TREE_ADDRESSABLE types and is probably not worth the complexity. (In
4114 intraprocedural SRA we deal with this by keeping the old aggregate around,
4115 something we cannot do in IPA-SRA.) */
4116 if (access->write
4117 && (is_gimple_call (access->stmt)
4118 || gimple_code (access->stmt) == GIMPLE_ASM))
4119 return true;
4121 exp_align = get_object_alignment (access->expr);
4122 if (exp_align < req_align)
4123 return true;
4125 return false;
4129 /* Sort collected accesses for parameter PARM, identify representatives for
4130 each accessed region and link them together. Return NULL if there are
4131 different but overlapping accesses, return the special ptr value meaning
4132 there are no accesses for this parameter if that is the case and return the
4133 first representative otherwise. Set *RO_GRP if there is a group of accesses
4134 with only read (i.e. no write) accesses. */
4136 static struct access *
4137 splice_param_accesses (tree parm, bool *ro_grp)
4139 int i, j, access_count, group_count;
4140 int agg_size, total_size = 0;
4141 struct access *access, *res, **prev_acc_ptr = &res;
4142 vec<access_p> *access_vec;
4144 access_vec = get_base_access_vector (parm);
4145 if (!access_vec)
4146 return &no_accesses_representant;
4147 access_count = access_vec->length ();
4149 access_vec->qsort (compare_access_positions);
4151 i = 0;
4152 total_size = 0;
4153 group_count = 0;
4154 while (i < access_count)
4156 bool modification;
4157 tree a1_alias_type;
4158 access = (*access_vec)[i];
4159 modification = access->write;
4160 if (access_precludes_ipa_sra_p (access, TYPE_ALIGN (access->type)))
4161 return NULL;
4162 a1_alias_type = reference_alias_ptr_type (access->expr);
4164 /* Access is about to become group representative unless we find some
4165 nasty overlap which would preclude us from breaking this parameter
4166 apart. */
4168 j = i + 1;
4169 while (j < access_count)
4171 struct access *ac2 = (*access_vec)[j];
4172 if (ac2->offset != access->offset)
4174 /* All or nothing law for parameters. */
4175 if (access->offset + access->size > ac2->offset)
4176 return NULL;
4177 else
4178 break;
4180 else if (ac2->size != access->size)
4181 return NULL;
4183 if (access_precludes_ipa_sra_p (ac2, TYPE_ALIGN (access->type))
4184 || (ac2->type != access->type
4185 && (TREE_ADDRESSABLE (ac2->type)
4186 || TREE_ADDRESSABLE (access->type)))
4187 || (reference_alias_ptr_type (ac2->expr) != a1_alias_type))
4188 return NULL;
4190 modification |= ac2->write;
4191 ac2->group_representative = access;
4192 ac2->next_sibling = access->next_sibling;
4193 access->next_sibling = ac2;
4194 j++;
4197 group_count++;
4198 access->grp_maybe_modified = modification;
4199 if (!modification)
4200 *ro_grp = true;
4201 *prev_acc_ptr = access;
4202 prev_acc_ptr = &access->next_grp;
4203 total_size += access->size;
4204 i = j;
4207 if (POINTER_TYPE_P (TREE_TYPE (parm)))
4208 agg_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))));
4209 else
4210 agg_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (parm)));
4211 if (total_size >= agg_size)
4212 return NULL;
4214 gcc_assert (group_count > 0);
4215 return res;
4218 /* Decide whether parameters with representative accesses given by REPR should
4219 be reduced into components. */
4221 static int
4222 decide_one_param_reduction (struct access *repr)
4224 int total_size, cur_parm_size, agg_size, new_param_count, parm_size_limit;
4225 bool by_ref;
4226 tree parm;
4228 parm = repr->base;
4229 cur_parm_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (parm)));
4230 gcc_assert (cur_parm_size > 0);
4232 if (POINTER_TYPE_P (TREE_TYPE (parm)))
4234 by_ref = true;
4235 agg_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))));
4237 else
4239 by_ref = false;
4240 agg_size = cur_parm_size;
4243 if (dump_file)
4245 struct access *acc;
4246 fprintf (dump_file, "Evaluating PARAM group sizes for ");
4247 print_generic_expr (dump_file, parm, 0);
4248 fprintf (dump_file, " (UID: %u): \n", DECL_UID (parm));
4249 for (acc = repr; acc; acc = acc->next_grp)
4250 dump_access (dump_file, acc, true);
4253 total_size = 0;
4254 new_param_count = 0;
4256 for (; repr; repr = repr->next_grp)
4258 gcc_assert (parm == repr->base);
4260 /* Taking the address of a non-addressable field is verboten. */
4261 if (by_ref && repr->non_addressable)
4262 return 0;
4264 /* Do not decompose a non-BLKmode param in a way that would
4265 create BLKmode params. Especially for by-reference passing
4266 (thus, pointer-type param) this is hardly worthwhile. */
4267 if (DECL_MODE (parm) != BLKmode
4268 && TYPE_MODE (repr->type) == BLKmode)
4269 return 0;
4271 if (!by_ref || (!repr->grp_maybe_modified
4272 && !repr->grp_not_necessarilly_dereferenced))
4273 total_size += repr->size;
4274 else
4275 total_size += cur_parm_size;
4277 new_param_count++;
4280 gcc_assert (new_param_count > 0);
4282 if (optimize_function_for_size_p (cfun))
4283 parm_size_limit = cur_parm_size;
4284 else
4285 parm_size_limit = (PARAM_VALUE (PARAM_IPA_SRA_PTR_GROWTH_FACTOR)
4286 * cur_parm_size);
4288 if (total_size < agg_size
4289 && total_size <= parm_size_limit)
4291 if (dump_file)
4292 fprintf (dump_file, " ....will be split into %i components\n",
4293 new_param_count);
4294 return new_param_count;
4296 else
4297 return 0;
4300 /* The order of the following enums is important, we need to do extra work for
4301 UNUSED_PARAMS, BY_VAL_ACCESSES and UNMODIF_BY_REF_ACCESSES. */
4302 enum ipa_splicing_result { NO_GOOD_ACCESS, UNUSED_PARAMS, BY_VAL_ACCESSES,
4303 MODIF_BY_REF_ACCESSES, UNMODIF_BY_REF_ACCESSES };
4305 /* Identify representatives of all accesses to all candidate parameters for
4306 IPA-SRA. Return result based on what representatives have been found. */
4308 static enum ipa_splicing_result
4309 splice_all_param_accesses (vec<access_p> &representatives)
4311 enum ipa_splicing_result result = NO_GOOD_ACCESS;
4312 tree parm;
4313 struct access *repr;
4315 representatives.create (func_param_count);
4317 for (parm = DECL_ARGUMENTS (current_function_decl);
4318 parm;
4319 parm = DECL_CHAIN (parm))
4321 if (is_unused_scalar_param (parm))
4323 representatives.quick_push (&no_accesses_representant);
4324 if (result == NO_GOOD_ACCESS)
4325 result = UNUSED_PARAMS;
4327 else if (POINTER_TYPE_P (TREE_TYPE (parm))
4328 && is_gimple_reg_type (TREE_TYPE (TREE_TYPE (parm)))
4329 && bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
4331 repr = unmodified_by_ref_scalar_representative (parm);
4332 representatives.quick_push (repr);
4333 if (repr)
4334 result = UNMODIF_BY_REF_ACCESSES;
4336 else if (bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
4338 bool ro_grp = false;
4339 repr = splice_param_accesses (parm, &ro_grp);
4340 representatives.quick_push (repr);
4342 if (repr && !no_accesses_p (repr))
4344 if (POINTER_TYPE_P (TREE_TYPE (parm)))
4346 if (ro_grp)
4347 result = UNMODIF_BY_REF_ACCESSES;
4348 else if (result < MODIF_BY_REF_ACCESSES)
4349 result = MODIF_BY_REF_ACCESSES;
4351 else if (result < BY_VAL_ACCESSES)
4352 result = BY_VAL_ACCESSES;
4354 else if (no_accesses_p (repr) && (result == NO_GOOD_ACCESS))
4355 result = UNUSED_PARAMS;
4357 else
4358 representatives.quick_push (NULL);
4361 if (result == NO_GOOD_ACCESS)
4363 representatives.release ();
4364 return NO_GOOD_ACCESS;
4367 return result;
4370 /* Return the index of BASE in PARMS. Abort if it is not found. */
4372 static inline int
4373 get_param_index (tree base, vec<tree> parms)
4375 int i, len;
4377 len = parms.length ();
4378 for (i = 0; i < len; i++)
4379 if (parms[i] == base)
4380 return i;
4381 gcc_unreachable ();
4384 /* Convert the decisions made at the representative level into compact
4385 parameter adjustments. REPRESENTATIVES are pointers to first
4386 representatives of each param accesses, ADJUSTMENTS_COUNT is the expected
4387 final number of adjustments. */
4389 static ipa_parm_adjustment_vec
4390 turn_representatives_into_adjustments (vec<access_p> representatives,
4391 int adjustments_count)
4393 vec<tree> parms;
4394 ipa_parm_adjustment_vec adjustments;
4395 tree parm;
4396 int i;
4398 gcc_assert (adjustments_count > 0);
4399 parms = ipa_get_vector_of_formal_parms (current_function_decl);
4400 adjustments.create (adjustments_count);
4401 parm = DECL_ARGUMENTS (current_function_decl);
4402 for (i = 0; i < func_param_count; i++, parm = DECL_CHAIN (parm))
4404 struct access *repr = representatives[i];
4406 if (!repr || no_accesses_p (repr))
4408 struct ipa_parm_adjustment adj;
4410 memset (&adj, 0, sizeof (adj));
4411 adj.base_index = get_param_index (parm, parms);
4412 adj.base = parm;
4413 if (!repr)
4414 adj.op = IPA_PARM_OP_COPY;
4415 else
4416 adj.op = IPA_PARM_OP_REMOVE;
4417 adj.arg_prefix = "ISRA";
4418 adjustments.quick_push (adj);
4420 else
4422 struct ipa_parm_adjustment adj;
4423 int index = get_param_index (parm, parms);
4425 for (; repr; repr = repr->next_grp)
4427 memset (&adj, 0, sizeof (adj));
4428 gcc_assert (repr->base == parm);
4429 adj.base_index = index;
4430 adj.base = repr->base;
4431 adj.type = repr->type;
4432 adj.alias_ptr_type = reference_alias_ptr_type (repr->expr);
4433 adj.offset = repr->offset;
4434 adj.by_ref = (POINTER_TYPE_P (TREE_TYPE (repr->base))
4435 && (repr->grp_maybe_modified
4436 || repr->grp_not_necessarilly_dereferenced));
4437 adj.arg_prefix = "ISRA";
4438 adjustments.quick_push (adj);
4442 parms.release ();
4443 return adjustments;
4446 /* Analyze the collected accesses and produce a plan what to do with the
4447 parameters in the form of adjustments, NULL meaning nothing. */
4449 static ipa_parm_adjustment_vec
4450 analyze_all_param_acesses (void)
4452 enum ipa_splicing_result repr_state;
4453 bool proceed = false;
4454 int i, adjustments_count = 0;
4455 vec<access_p> representatives;
4456 ipa_parm_adjustment_vec adjustments;
4458 repr_state = splice_all_param_accesses (representatives);
4459 if (repr_state == NO_GOOD_ACCESS)
4460 return ipa_parm_adjustment_vec ();
4462 /* If there are any parameters passed by reference which are not modified
4463 directly, we need to check whether they can be modified indirectly. */
4464 if (repr_state == UNMODIF_BY_REF_ACCESSES)
4466 analyze_caller_dereference_legality (representatives);
4467 analyze_modified_params (representatives);
4470 for (i = 0; i < func_param_count; i++)
4472 struct access *repr = representatives[i];
4474 if (repr && !no_accesses_p (repr))
4476 if (repr->grp_scalar_ptr)
4478 adjustments_count++;
4479 if (repr->grp_not_necessarilly_dereferenced
4480 || repr->grp_maybe_modified)
4481 representatives[i] = NULL;
4482 else
4484 proceed = true;
4485 sra_stats.scalar_by_ref_to_by_val++;
4488 else
4490 int new_components = decide_one_param_reduction (repr);
4492 if (new_components == 0)
4494 representatives[i] = NULL;
4495 adjustments_count++;
4497 else
4499 adjustments_count += new_components;
4500 sra_stats.aggregate_params_reduced++;
4501 sra_stats.param_reductions_created += new_components;
4502 proceed = true;
4506 else
4508 if (no_accesses_p (repr))
4510 proceed = true;
4511 sra_stats.deleted_unused_parameters++;
4513 adjustments_count++;
4517 if (!proceed && dump_file)
4518 fprintf (dump_file, "NOT proceeding to change params.\n");
4520 if (proceed)
4521 adjustments = turn_representatives_into_adjustments (representatives,
4522 adjustments_count);
4523 else
4524 adjustments = ipa_parm_adjustment_vec ();
4526 representatives.release ();
4527 return adjustments;
4530 /* If a parameter replacement identified by ADJ does not yet exist in the form
4531 of declaration, create it and record it, otherwise return the previously
4532 created one. */
4534 static tree
4535 get_replaced_param_substitute (struct ipa_parm_adjustment *adj)
4537 tree repl;
4538 if (!adj->new_ssa_base)
4540 char *pretty_name = make_fancy_name (adj->base);
4542 repl = create_tmp_reg (TREE_TYPE (adj->base), "ISR");
4543 DECL_NAME (repl) = get_identifier (pretty_name);
4544 obstack_free (&name_obstack, pretty_name);
4546 adj->new_ssa_base = repl;
4548 else
4549 repl = adj->new_ssa_base;
4550 return repl;
4553 /* Find the first adjustment for a particular parameter BASE in a vector of
4554 ADJUSTMENTS which is not a copy_param. Return NULL if there is no such
4555 adjustment. */
4557 static struct ipa_parm_adjustment *
4558 get_adjustment_for_base (ipa_parm_adjustment_vec adjustments, tree base)
4560 int i, len;
4562 len = adjustments.length ();
4563 for (i = 0; i < len; i++)
4565 struct ipa_parm_adjustment *adj;
4567 adj = &adjustments[i];
4568 if (adj->op != IPA_PARM_OP_COPY && adj->base == base)
4569 return adj;
4572 return NULL;
4575 /* If the statement STMT defines an SSA_NAME of a parameter which is to be
4576 removed because its value is not used, replace the SSA_NAME with a one
4577 relating to a created VAR_DECL together all of its uses and return true.
4578 ADJUSTMENTS is a pointer to an adjustments vector. */
4580 static bool
4581 replace_removed_params_ssa_names (gimple stmt,
4582 ipa_parm_adjustment_vec adjustments)
4584 struct ipa_parm_adjustment *adj;
4585 tree lhs, decl, repl, name;
4587 if (gimple_code (stmt) == GIMPLE_PHI)
4588 lhs = gimple_phi_result (stmt);
4589 else if (is_gimple_assign (stmt))
4590 lhs = gimple_assign_lhs (stmt);
4591 else if (is_gimple_call (stmt))
4592 lhs = gimple_call_lhs (stmt);
4593 else
4594 gcc_unreachable ();
4596 if (TREE_CODE (lhs) != SSA_NAME)
4597 return false;
4599 decl = SSA_NAME_VAR (lhs);
4600 if (decl == NULL_TREE
4601 || TREE_CODE (decl) != PARM_DECL)
4602 return false;
4604 adj = get_adjustment_for_base (adjustments, decl);
4605 if (!adj)
4606 return false;
4608 repl = get_replaced_param_substitute (adj);
4609 name = make_ssa_name (repl, stmt);
4611 if (dump_file)
4613 fprintf (dump_file, "replacing an SSA name of a removed param ");
4614 print_generic_expr (dump_file, lhs, 0);
4615 fprintf (dump_file, " with ");
4616 print_generic_expr (dump_file, name, 0);
4617 fprintf (dump_file, "\n");
4620 if (is_gimple_assign (stmt))
4621 gimple_assign_set_lhs (stmt, name);
4622 else if (is_gimple_call (stmt))
4623 gimple_call_set_lhs (stmt, name);
4624 else
4625 gimple_phi_set_result (as_a <gphi *> (stmt), name);
4627 replace_uses_by (lhs, name);
4628 release_ssa_name (lhs);
4629 return true;
4632 /* If the statement STMT contains any expressions that need to replaced with a
4633 different one as noted by ADJUSTMENTS, do so. Handle any potential type
4634 incompatibilities (GSI is used to accommodate conversion statements and must
4635 point to the statement). Return true iff the statement was modified. */
4637 static bool
4638 sra_ipa_modify_assign (gimple stmt, gimple_stmt_iterator *gsi,
4639 ipa_parm_adjustment_vec adjustments)
4641 tree *lhs_p, *rhs_p;
4642 bool any;
4644 if (!gimple_assign_single_p (stmt))
4645 return false;
4647 rhs_p = gimple_assign_rhs1_ptr (stmt);
4648 lhs_p = gimple_assign_lhs_ptr (stmt);
4650 any = ipa_modify_expr (rhs_p, false, adjustments);
4651 any |= ipa_modify_expr (lhs_p, false, adjustments);
4652 if (any)
4654 tree new_rhs = NULL_TREE;
4656 if (!useless_type_conversion_p (TREE_TYPE (*lhs_p), TREE_TYPE (*rhs_p)))
4658 if (TREE_CODE (*rhs_p) == CONSTRUCTOR)
4660 /* V_C_Es of constructors can cause trouble (PR 42714). */
4661 if (is_gimple_reg_type (TREE_TYPE (*lhs_p)))
4662 *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
4663 else
4664 *rhs_p = build_constructor (TREE_TYPE (*lhs_p),
4665 NULL);
4667 else
4668 new_rhs = fold_build1_loc (gimple_location (stmt),
4669 VIEW_CONVERT_EXPR, TREE_TYPE (*lhs_p),
4670 *rhs_p);
4672 else if (REFERENCE_CLASS_P (*rhs_p)
4673 && is_gimple_reg_type (TREE_TYPE (*lhs_p))
4674 && !is_gimple_reg (*lhs_p))
4675 /* This can happen when an assignment in between two single field
4676 structures is turned into an assignment in between two pointers to
4677 scalars (PR 42237). */
4678 new_rhs = *rhs_p;
4680 if (new_rhs)
4682 tree tmp = force_gimple_operand_gsi (gsi, new_rhs, true, NULL_TREE,
4683 true, GSI_SAME_STMT);
4685 gimple_assign_set_rhs_from_tree (gsi, tmp);
4688 return true;
4691 return false;
4694 /* Traverse the function body and all modifications as described in
4695 ADJUSTMENTS. Return true iff the CFG has been changed. */
4697 bool
4698 ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments)
4700 bool cfg_changed = false;
4701 basic_block bb;
4703 FOR_EACH_BB_FN (bb, cfun)
4705 gimple_stmt_iterator gsi;
4707 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4708 replace_removed_params_ssa_names (gsi_stmt (gsi), adjustments);
4710 gsi = gsi_start_bb (bb);
4711 while (!gsi_end_p (gsi))
4713 gimple stmt = gsi_stmt (gsi);
4714 bool modified = false;
4715 tree *t;
4716 unsigned i;
4718 switch (gimple_code (stmt))
4720 case GIMPLE_RETURN:
4721 t = gimple_return_retval_ptr (as_a <greturn *> (stmt));
4722 if (*t != NULL_TREE)
4723 modified |= ipa_modify_expr (t, true, adjustments);
4724 break;
4726 case GIMPLE_ASSIGN:
4727 modified |= sra_ipa_modify_assign (stmt, &gsi, adjustments);
4728 modified |= replace_removed_params_ssa_names (stmt, adjustments);
4729 break;
4731 case GIMPLE_CALL:
4732 /* Operands must be processed before the lhs. */
4733 for (i = 0; i < gimple_call_num_args (stmt); i++)
4735 t = gimple_call_arg_ptr (stmt, i);
4736 modified |= ipa_modify_expr (t, true, adjustments);
4739 if (gimple_call_lhs (stmt))
4741 t = gimple_call_lhs_ptr (stmt);
4742 modified |= ipa_modify_expr (t, false, adjustments);
4743 modified |= replace_removed_params_ssa_names (stmt,
4744 adjustments);
4746 break;
4748 case GIMPLE_ASM:
4750 gasm *asm_stmt = as_a <gasm *> (stmt);
4751 for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
4753 t = &TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
4754 modified |= ipa_modify_expr (t, true, adjustments);
4756 for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
4758 t = &TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
4759 modified |= ipa_modify_expr (t, false, adjustments);
4762 break;
4764 default:
4765 break;
4768 if (modified)
4770 update_stmt (stmt);
4771 if (maybe_clean_eh_stmt (stmt)
4772 && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
4773 cfg_changed = true;
4775 gsi_next (&gsi);
4779 return cfg_changed;
4782 /* Call gimple_debug_bind_reset_value on all debug statements describing
4783 gimple register parameters that are being removed or replaced. */
4785 static void
4786 sra_ipa_reset_debug_stmts (ipa_parm_adjustment_vec adjustments)
4788 int i, len;
4789 gimple_stmt_iterator *gsip = NULL, gsi;
4791 if (MAY_HAVE_DEBUG_STMTS && single_succ_p (ENTRY_BLOCK_PTR_FOR_FN (cfun)))
4793 gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
4794 gsip = &gsi;
4796 len = adjustments.length ();
4797 for (i = 0; i < len; i++)
4799 struct ipa_parm_adjustment *adj;
4800 imm_use_iterator ui;
4801 gimple stmt;
4802 gdebug *def_temp;
4803 tree name, vexpr, copy = NULL_TREE;
4804 use_operand_p use_p;
4806 adj = &adjustments[i];
4807 if (adj->op == IPA_PARM_OP_COPY || !is_gimple_reg (adj->base))
4808 continue;
4809 name = ssa_default_def (cfun, adj->base);
4810 vexpr = NULL;
4811 if (name)
4812 FOR_EACH_IMM_USE_STMT (stmt, ui, name)
4814 if (gimple_clobber_p (stmt))
4816 gimple_stmt_iterator cgsi = gsi_for_stmt (stmt);
4817 unlink_stmt_vdef (stmt);
4818 gsi_remove (&cgsi, true);
4819 release_defs (stmt);
4820 continue;
4822 /* All other users must have been removed by
4823 ipa_sra_modify_function_body. */
4824 gcc_assert (is_gimple_debug (stmt));
4825 if (vexpr == NULL && gsip != NULL)
4827 gcc_assert (TREE_CODE (adj->base) == PARM_DECL);
4828 vexpr = make_node (DEBUG_EXPR_DECL);
4829 def_temp = gimple_build_debug_source_bind (vexpr, adj->base,
4830 NULL);
4831 DECL_ARTIFICIAL (vexpr) = 1;
4832 TREE_TYPE (vexpr) = TREE_TYPE (name);
4833 DECL_MODE (vexpr) = DECL_MODE (adj->base);
4834 gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
4836 if (vexpr)
4838 FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
4839 SET_USE (use_p, vexpr);
4841 else
4842 gimple_debug_bind_reset_value (stmt);
4843 update_stmt (stmt);
4845 /* Create a VAR_DECL for debug info purposes. */
4846 if (!DECL_IGNORED_P (adj->base))
4848 copy = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
4849 VAR_DECL, DECL_NAME (adj->base),
4850 TREE_TYPE (adj->base));
4851 if (DECL_PT_UID_SET_P (adj->base))
4852 SET_DECL_PT_UID (copy, DECL_PT_UID (adj->base));
4853 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (adj->base);
4854 TREE_READONLY (copy) = TREE_READONLY (adj->base);
4855 TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (adj->base);
4856 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (adj->base);
4857 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (adj->base);
4858 DECL_IGNORED_P (copy) = DECL_IGNORED_P (adj->base);
4859 DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (adj->base);
4860 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
4861 SET_DECL_RTL (copy, 0);
4862 TREE_USED (copy) = 1;
4863 DECL_CONTEXT (copy) = current_function_decl;
4864 add_local_decl (cfun, copy);
4865 DECL_CHAIN (copy) =
4866 BLOCK_VARS (DECL_INITIAL (current_function_decl));
4867 BLOCK_VARS (DECL_INITIAL (current_function_decl)) = copy;
4869 if (gsip != NULL && copy && target_for_debug_bind (adj->base))
4871 gcc_assert (TREE_CODE (adj->base) == PARM_DECL);
4872 if (vexpr)
4873 def_temp = gimple_build_debug_bind (copy, vexpr, NULL);
4874 else
4875 def_temp = gimple_build_debug_source_bind (copy, adj->base,
4876 NULL);
4877 gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
4882 /* Return false if all callers have at least as many actual arguments as there
4883 are formal parameters in the current function and that their types
4884 match. */
4886 static bool
4887 some_callers_have_mismatched_arguments_p (struct cgraph_node *node,
4888 void *data ATTRIBUTE_UNUSED)
4890 struct cgraph_edge *cs;
4891 for (cs = node->callers; cs; cs = cs->next_caller)
4892 if (!cs->call_stmt || !callsite_arguments_match_p (cs->call_stmt))
4893 return true;
4895 return false;
4898 /* Return false if all callers have vuse attached to a call statement. */
4900 static bool
4901 some_callers_have_no_vuse_p (struct cgraph_node *node,
4902 void *data ATTRIBUTE_UNUSED)
4904 struct cgraph_edge *cs;
4905 for (cs = node->callers; cs; cs = cs->next_caller)
4906 if (!cs->call_stmt || !gimple_vuse (cs->call_stmt))
4907 return true;
4909 return false;
4912 /* Convert all callers of NODE. */
4914 static bool
4915 convert_callers_for_node (struct cgraph_node *node,
4916 void *data)
4918 ipa_parm_adjustment_vec *adjustments = (ipa_parm_adjustment_vec *) data;
4919 bitmap recomputed_callers = BITMAP_ALLOC (NULL);
4920 struct cgraph_edge *cs;
4922 for (cs = node->callers; cs; cs = cs->next_caller)
4924 push_cfun (DECL_STRUCT_FUNCTION (cs->caller->decl));
4926 if (dump_file)
4927 fprintf (dump_file, "Adjusting call %s/%i -> %s/%i\n",
4928 xstrdup (cs->caller->name ()),
4929 cs->caller->order,
4930 xstrdup (cs->callee->name ()),
4931 cs->callee->order);
4933 ipa_modify_call_arguments (cs, cs->call_stmt, *adjustments);
4935 pop_cfun ();
4938 for (cs = node->callers; cs; cs = cs->next_caller)
4939 if (bitmap_set_bit (recomputed_callers, cs->caller->uid)
4940 && gimple_in_ssa_p (DECL_STRUCT_FUNCTION (cs->caller->decl)))
4941 compute_inline_parameters (cs->caller, true);
4942 BITMAP_FREE (recomputed_callers);
4944 return true;
4947 /* Convert all callers of NODE to pass parameters as given in ADJUSTMENTS. */
4949 static void
4950 convert_callers (struct cgraph_node *node, tree old_decl,
4951 ipa_parm_adjustment_vec adjustments)
4953 basic_block this_block;
4955 node->call_for_symbol_and_aliases (convert_callers_for_node,
4956 &adjustments, false);
4958 if (!encountered_recursive_call)
4959 return;
4961 FOR_EACH_BB_FN (this_block, cfun)
4963 gimple_stmt_iterator gsi;
4965 for (gsi = gsi_start_bb (this_block); !gsi_end_p (gsi); gsi_next (&gsi))
4967 gcall *stmt;
4968 tree call_fndecl;
4969 stmt = dyn_cast <gcall *> (gsi_stmt (gsi));
4970 if (!stmt)
4971 continue;
4972 call_fndecl = gimple_call_fndecl (stmt);
4973 if (call_fndecl == old_decl)
4975 if (dump_file)
4976 fprintf (dump_file, "Adjusting recursive call");
4977 gimple_call_set_fndecl (stmt, node->decl);
4978 ipa_modify_call_arguments (NULL, stmt, adjustments);
4983 return;
4986 /* Perform all the modification required in IPA-SRA for NODE to have parameters
4987 as given in ADJUSTMENTS. Return true iff the CFG has been changed. */
4989 static bool
4990 modify_function (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments)
4992 struct cgraph_node *new_node;
4993 bool cfg_changed;
4995 cgraph_edge::rebuild_edges ();
4996 free_dominance_info (CDI_DOMINATORS);
4997 pop_cfun ();
4999 /* This must be done after rebuilding cgraph edges for node above.
5000 Otherwise any recursive calls to node that are recorded in
5001 redirect_callers will be corrupted. */
5002 vec<cgraph_edge *> redirect_callers = node->collect_callers ();
5003 new_node = node->create_version_clone_with_body (redirect_callers, NULL,
5004 NULL, false, NULL, NULL,
5005 "isra");
5006 redirect_callers.release ();
5008 push_cfun (DECL_STRUCT_FUNCTION (new_node->decl));
5009 ipa_modify_formal_parameters (current_function_decl, adjustments);
5010 cfg_changed = ipa_sra_modify_function_body (adjustments);
5011 sra_ipa_reset_debug_stmts (adjustments);
5012 convert_callers (new_node, node->decl, adjustments);
5013 new_node->make_local ();
5014 return cfg_changed;
5017 /* Means of communication between ipa_sra_check_caller and
5018 ipa_sra_preliminary_function_checks. */
5020 struct ipa_sra_check_caller_data
5022 bool has_callers;
5023 bool bad_arg_alignment;
5024 bool has_thunk;
5027 /* If NODE has a caller, mark that fact in DATA which is pointer to
5028 ipa_sra_check_caller_data. Also check all aggregate arguments in all known
5029 calls if they are unit aligned and if not, set the appropriate flag in DATA
5030 too. */
5032 static bool
5033 ipa_sra_check_caller (struct cgraph_node *node, void *data)
5035 if (!node->callers)
5036 return false;
5038 struct ipa_sra_check_caller_data *iscc;
5039 iscc = (struct ipa_sra_check_caller_data *) data;
5040 iscc->has_callers = true;
5042 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
5044 if (cs->caller->thunk.thunk_p)
5046 iscc->has_thunk = true;
5047 return true;
5049 gimple call_stmt = cs->call_stmt;
5050 unsigned count = gimple_call_num_args (call_stmt);
5051 for (unsigned i = 0; i < count; i++)
5053 tree arg = gimple_call_arg (call_stmt, i);
5054 if (is_gimple_reg (arg))
5055 continue;
5057 tree offset;
5058 HOST_WIDE_INT bitsize, bitpos;
5059 machine_mode mode;
5060 int unsignedp, volatilep = 0;
5061 get_inner_reference (arg, &bitsize, &bitpos, &offset, &mode,
5062 &unsignedp, &volatilep, false);
5063 if (bitpos % BITS_PER_UNIT)
5065 iscc->bad_arg_alignment = true;
5066 return true;
5071 return false;
5074 /* Return false the function is apparently unsuitable for IPA-SRA based on it's
5075 attributes, return true otherwise. NODE is the cgraph node of the current
5076 function. */
5078 static bool
5079 ipa_sra_preliminary_function_checks (struct cgraph_node *node)
5081 if (!node->can_be_local_p ())
5083 if (dump_file)
5084 fprintf (dump_file, "Function not local to this compilation unit.\n");
5085 return false;
5088 if (!node->local.can_change_signature)
5090 if (dump_file)
5091 fprintf (dump_file, "Function can not change signature.\n");
5092 return false;
5095 if (!tree_versionable_function_p (node->decl))
5097 if (dump_file)
5098 fprintf (dump_file, "Function is not versionable.\n");
5099 return false;
5102 if (!opt_for_fn (node->decl, optimize)
5103 || !opt_for_fn (node->decl, flag_ipa_sra))
5105 if (dump_file)
5106 fprintf (dump_file, "Function not optimized.\n");
5107 return false;
5110 if (DECL_VIRTUAL_P (current_function_decl))
5112 if (dump_file)
5113 fprintf (dump_file, "Function is a virtual method.\n");
5114 return false;
5117 if ((DECL_ONE_ONLY (node->decl) || DECL_EXTERNAL (node->decl))
5118 && inline_summaries->get (node)->size >= MAX_INLINE_INSNS_AUTO)
5120 if (dump_file)
5121 fprintf (dump_file, "Function too big to be made truly local.\n");
5122 return false;
5125 if (cfun->stdarg)
5127 if (dump_file)
5128 fprintf (dump_file, "Function uses stdarg. \n");
5129 return false;
5132 if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl)))
5133 return false;
5135 if (DECL_DISREGARD_INLINE_LIMITS (node->decl))
5137 if (dump_file)
5138 fprintf (dump_file, "Always inline function will be inlined "
5139 "anyway. \n");
5140 return false;
5143 struct ipa_sra_check_caller_data iscc;
5144 memset (&iscc, 0, sizeof(iscc));
5145 node->call_for_symbol_and_aliases (ipa_sra_check_caller, &iscc, true);
5146 if (!iscc.has_callers)
5148 if (dump_file)
5149 fprintf (dump_file,
5150 "Function has no callers in this compilation unit.\n");
5151 return false;
5154 if (iscc.bad_arg_alignment)
5156 if (dump_file)
5157 fprintf (dump_file,
5158 "A function call has an argument with non-unit alignment.\n");
5159 return false;
5162 if (iscc.has_thunk)
5164 if (dump_file)
5165 fprintf (dump_file,
5166 "A has thunk.\n");
5167 return false;
5170 return true;
5173 /* Perform early interprocedural SRA. */
5175 static unsigned int
5176 ipa_early_sra (void)
5178 struct cgraph_node *node = cgraph_node::get (current_function_decl);
5179 ipa_parm_adjustment_vec adjustments;
5180 int ret = 0;
5182 if (!ipa_sra_preliminary_function_checks (node))
5183 return 0;
5185 sra_initialize ();
5186 sra_mode = SRA_MODE_EARLY_IPA;
5188 if (!find_param_candidates ())
5190 if (dump_file)
5191 fprintf (dump_file, "Function has no IPA-SRA candidates.\n");
5192 goto simple_out;
5195 if (node->call_for_symbol_and_aliases
5196 (some_callers_have_mismatched_arguments_p, NULL, true))
5198 if (dump_file)
5199 fprintf (dump_file, "There are callers with insufficient number of "
5200 "arguments or arguments with type mismatches.\n");
5201 goto simple_out;
5204 if (node->call_for_symbol_and_aliases
5205 (some_callers_have_no_vuse_p, NULL, true))
5207 if (dump_file)
5208 fprintf (dump_file, "There are callers with no VUSE attached "
5209 "to a call stmt.\n");
5210 goto simple_out;
5213 bb_dereferences = XCNEWVEC (HOST_WIDE_INT,
5214 func_param_count
5215 * last_basic_block_for_fn (cfun));
5216 final_bbs = BITMAP_ALLOC (NULL);
5218 scan_function ();
5219 if (encountered_apply_args)
5221 if (dump_file)
5222 fprintf (dump_file, "Function calls __builtin_apply_args().\n");
5223 goto out;
5226 if (encountered_unchangable_recursive_call)
5228 if (dump_file)
5229 fprintf (dump_file, "Function calls itself with insufficient "
5230 "number of arguments.\n");
5231 goto out;
5234 adjustments = analyze_all_param_acesses ();
5235 if (!adjustments.exists ())
5236 goto out;
5237 if (dump_file)
5238 ipa_dump_param_adjustments (dump_file, adjustments, current_function_decl);
5240 if (modify_function (node, adjustments))
5241 ret = TODO_update_ssa | TODO_cleanup_cfg;
5242 else
5243 ret = TODO_update_ssa;
5244 adjustments.release ();
5246 statistics_counter_event (cfun, "Unused parameters deleted",
5247 sra_stats.deleted_unused_parameters);
5248 statistics_counter_event (cfun, "Scalar parameters converted to by-value",
5249 sra_stats.scalar_by_ref_to_by_val);
5250 statistics_counter_event (cfun, "Aggregate parameters broken up",
5251 sra_stats.aggregate_params_reduced);
5252 statistics_counter_event (cfun, "Aggregate parameter components created",
5253 sra_stats.param_reductions_created);
5255 out:
5256 BITMAP_FREE (final_bbs);
5257 free (bb_dereferences);
5258 simple_out:
5259 sra_deinitialize ();
5260 return ret;
5263 namespace {
5265 const pass_data pass_data_early_ipa_sra =
5267 GIMPLE_PASS, /* type */
5268 "eipa_sra", /* name */
5269 OPTGROUP_NONE, /* optinfo_flags */
5270 TV_IPA_SRA, /* tv_id */
5271 0, /* properties_required */
5272 0, /* properties_provided */
5273 0, /* properties_destroyed */
5274 0, /* todo_flags_start */
5275 TODO_dump_symtab, /* todo_flags_finish */
5278 class pass_early_ipa_sra : public gimple_opt_pass
5280 public:
5281 pass_early_ipa_sra (gcc::context *ctxt)
5282 : gimple_opt_pass (pass_data_early_ipa_sra, ctxt)
5285 /* opt_pass methods: */
5286 virtual bool gate (function *) { return flag_ipa_sra && dbg_cnt (eipa_sra); }
5287 virtual unsigned int execute (function *) { return ipa_early_sra (); }
5289 }; // class pass_early_ipa_sra
5291 } // anon namespace
5293 gimple_opt_pass *
5294 make_pass_early_ipa_sra (gcc::context *ctxt)
5296 return new pass_early_ipa_sra (ctxt);