* gcc.dg/c11-complex-1.c: Use dg-add-options ieee.
[official-gcc.git] / gcc / tree-sra.c
blobb4b17882d2a9e602cd8b80a61ee1e7caccc04831
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-2013 Free Software Foundation, Inc.
5 Contributed by Martin Jambor <mjambor@suse.cz>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* This file implements Scalar Reduction of Aggregates (SRA). SRA is run
24 twice, once in the early stages of compilation (early SRA) and once in the
25 late stages (late SRA). The aim of both is to turn references to scalar
26 parts of aggregates into uses of independent scalar variables.
28 The two passes are nearly identical, the only difference is that early SRA
29 does not scalarize unions which are used as the result in a GIMPLE_RETURN
30 statement because together with inlining this can lead to weird type
31 conversions.
33 Both passes operate in four stages:
35 1. The declarations that have properties which make them candidates for
36 scalarization are identified in function find_var_candidates(). The
37 candidates are stored in candidate_bitmap.
39 2. The function body is scanned. In the process, declarations which are
40 used in a manner that prevent their scalarization are removed from the
41 candidate bitmap. More importantly, for every access into an aggregate,
42 an access structure (struct access) is created by create_access() and
43 stored in a vector associated with the aggregate. Among other
44 information, the aggregate declaration, the offset and size of the access
45 and its type are stored in the structure.
47 On a related note, assign_link structures are created for every assign
48 statement between candidate aggregates and attached to the related
49 accesses.
51 3. The vectors of accesses are analyzed. They are first sorted according to
52 their offset and size and then scanned for partially overlapping accesses
53 (i.e. those which overlap but one is not entirely within another). Such
54 an access disqualifies the whole aggregate from being scalarized.
56 If there is no such inhibiting overlap, a representative access structure
57 is chosen for every unique combination of offset and size. Afterwards,
58 the pass builds a set of trees from these structures, in which children
59 of an access are within their parent (in terms of offset and size).
61 Then accesses are propagated whenever possible (i.e. in cases when it
62 does not create a partially overlapping access) across assign_links from
63 the right hand side to the left hand side.
65 Then the set of trees for each declaration is traversed again and those
66 accesses which should be replaced by a scalar are identified.
68 4. The function is traversed again, and for every reference into an
69 aggregate that has some component which is about to be scalarized,
70 statements are amended and new statements are created as necessary.
71 Finally, if a parameter got scalarized, the scalar replacements are
72 initialized with values from respective parameter aggregates. */
74 #include "config.h"
75 #include "system.h"
76 #include "coretypes.h"
77 #include "hash-table.h"
78 #include "alloc-pool.h"
79 #include "tm.h"
80 #include "tree.h"
81 #include "gimple.h"
82 #include "gimplify.h"
83 #include "gimple-iterator.h"
84 #include "gimplify-me.h"
85 #include "gimple-walk.h"
86 #include "bitmap.h"
87 #include "gimple-ssa.h"
88 #include "tree-cfg.h"
89 #include "tree-phinodes.h"
90 #include "ssa-iterators.h"
91 #include "tree-ssanames.h"
92 #include "tree-dfa.h"
93 #include "tree-ssa.h"
94 #include "tree-pass.h"
95 #include "ipa-prop.h"
96 #include "statistics.h"
97 #include "params.h"
98 #include "target.h"
99 #include "flags.h"
100 #include "dbgcnt.h"
101 #include "tree-inline.h"
102 #include "gimple-pretty-print.h"
103 #include "ipa-inline.h"
104 #include "ipa-utils.h"
106 /* Enumeration of all aggregate reductions we can do. */
107 enum sra_mode { SRA_MODE_EARLY_IPA, /* early call regularization */
108 SRA_MODE_EARLY_INTRA, /* early intraprocedural SRA */
109 SRA_MODE_INTRA }; /* late intraprocedural SRA */
111 /* Global variable describing which aggregate reduction we are performing at
112 the moment. */
113 static enum sra_mode sra_mode;
115 struct assign_link;
117 /* ACCESS represents each access to an aggregate variable (as a whole or a
118 part). It can also represent a group of accesses that refer to exactly the
119 same fragment of an aggregate (i.e. those that have exactly the same offset
120 and size). Such representatives for a single aggregate, once determined,
121 are linked in a linked list and have the group fields set.
123 Moreover, when doing intraprocedural SRA, a tree is built from those
124 representatives (by the means of first_child and next_sibling pointers), in
125 which all items in a subtree are "within" the root, i.e. their offset is
126 greater or equal to offset of the root and offset+size is smaller or equal
127 to offset+size of the root. Children of an access are sorted by offset.
129 Note that accesses to parts of vector and complex number types always
130 represented by an access to the whole complex number or a vector. It is a
131 duty of the modifying functions to replace them appropriately. */
133 struct access
135 /* Values returned by `get_ref_base_and_extent' for each component reference
136 If EXPR isn't a component reference just set `BASE = EXPR', `OFFSET = 0',
137 `SIZE = TREE_SIZE (TREE_TYPE (expr))'. */
138 HOST_WIDE_INT offset;
139 HOST_WIDE_INT size;
140 tree base;
142 /* Expression. It is context dependent so do not use it to create new
143 expressions to access the original aggregate. See PR 42154 for a
144 testcase. */
145 tree expr;
146 /* Type. */
147 tree type;
149 /* The statement this access belongs to. */
150 gimple stmt;
152 /* Next group representative for this aggregate. */
153 struct access *next_grp;
155 /* Pointer to the group representative. Pointer to itself if the struct is
156 the representative. */
157 struct access *group_representative;
159 /* If this access has any children (in terms of the definition above), this
160 points to the first one. */
161 struct access *first_child;
163 /* In intraprocedural SRA, pointer to the next sibling in the access tree as
164 described above. In IPA-SRA this is a pointer to the next access
165 belonging to the same group (having the same representative). */
166 struct access *next_sibling;
168 /* Pointers to the first and last element in the linked list of assign
169 links. */
170 struct assign_link *first_link, *last_link;
172 /* Pointer to the next access in the work queue. */
173 struct access *next_queued;
175 /* Replacement variable for this access "region." Never to be accessed
176 directly, always only by the means of get_access_replacement() and only
177 when grp_to_be_replaced flag is set. */
178 tree replacement_decl;
180 /* Is this particular access write access? */
181 unsigned write : 1;
183 /* Is this access an access to a non-addressable field? */
184 unsigned non_addressable : 1;
186 /* Is this access currently in the work queue? */
187 unsigned grp_queued : 1;
189 /* Does this group contain a write access? This flag is propagated down the
190 access tree. */
191 unsigned grp_write : 1;
193 /* Does this group contain a read access? This flag is propagated down the
194 access tree. */
195 unsigned grp_read : 1;
197 /* Does this group contain a read access that comes from an assignment
198 statement? This flag is propagated down the access tree. */
199 unsigned grp_assignment_read : 1;
201 /* Does this group contain a write access that comes from an assignment
202 statement? This flag is propagated down the access tree. */
203 unsigned grp_assignment_write : 1;
205 /* Does this group contain a read access through a scalar type? This flag is
206 not propagated in the access tree in any direction. */
207 unsigned grp_scalar_read : 1;
209 /* Does this group contain a write access through a scalar type? This flag
210 is not propagated in the access tree in any direction. */
211 unsigned grp_scalar_write : 1;
213 /* Is this access an artificial one created to scalarize some record
214 entirely? */
215 unsigned grp_total_scalarization : 1;
217 /* Other passes of the analysis use this bit to make function
218 analyze_access_subtree create scalar replacements for this group if
219 possible. */
220 unsigned grp_hint : 1;
222 /* Is the subtree rooted in this access fully covered by scalar
223 replacements? */
224 unsigned grp_covered : 1;
226 /* If set to true, this access and all below it in an access tree must not be
227 scalarized. */
228 unsigned grp_unscalarizable_region : 1;
230 /* Whether data have been written to parts of the aggregate covered by this
231 access which is not to be scalarized. This flag is propagated up in the
232 access tree. */
233 unsigned grp_unscalarized_data : 1;
235 /* Does this access and/or group contain a write access through a
236 BIT_FIELD_REF? */
237 unsigned grp_partial_lhs : 1;
239 /* Set when a scalar replacement should be created for this variable. */
240 unsigned grp_to_be_replaced : 1;
242 /* Set when we want a replacement for the sole purpose of having it in
243 generated debug statements. */
244 unsigned grp_to_be_debug_replaced : 1;
246 /* Should TREE_NO_WARNING of a replacement be set? */
247 unsigned grp_no_warning : 1;
249 /* Is it possible that the group refers to data which might be (directly or
250 otherwise) modified? */
251 unsigned grp_maybe_modified : 1;
253 /* Set when this is a representative of a pointer to scalar (i.e. by
254 reference) parameter which we consider for turning into a plain scalar
255 (i.e. a by value parameter). */
256 unsigned grp_scalar_ptr : 1;
258 /* Set when we discover that this pointer is not safe to dereference in the
259 caller. */
260 unsigned grp_not_necessarilly_dereferenced : 1;
263 typedef struct access *access_p;
266 /* Alloc pool for allocating access structures. */
267 static alloc_pool access_pool;
269 /* A structure linking lhs and rhs accesses from an aggregate assignment. They
270 are used to propagate subaccesses from rhs to lhs as long as they don't
271 conflict with what is already there. */
272 struct assign_link
274 struct access *lacc, *racc;
275 struct assign_link *next;
278 /* Alloc pool for allocating assign link structures. */
279 static alloc_pool link_pool;
281 /* Base (tree) -> Vector (vec<access_p> *) map. */
282 static struct pointer_map_t *base_access_vec;
284 /* Candidate hash table helpers. */
286 struct uid_decl_hasher : typed_noop_remove <tree_node>
288 typedef tree_node value_type;
289 typedef tree_node compare_type;
290 static inline hashval_t hash (const value_type *);
291 static inline bool equal (const value_type *, const compare_type *);
294 /* Hash a tree in a uid_decl_map. */
296 inline hashval_t
297 uid_decl_hasher::hash (const value_type *item)
299 return item->decl_minimal.uid;
302 /* Return true if the DECL_UID in both trees are equal. */
304 inline bool
305 uid_decl_hasher::equal (const value_type *a, const compare_type *b)
307 return (a->decl_minimal.uid == b->decl_minimal.uid);
310 /* Set of candidates. */
311 static bitmap candidate_bitmap;
312 static hash_table <uid_decl_hasher> candidates;
314 /* For a candidate UID return the candidates decl. */
316 static inline tree
317 candidate (unsigned uid)
319 tree_node t;
320 t.decl_minimal.uid = uid;
321 return candidates.find_with_hash (&t, static_cast <hashval_t> (uid));
324 /* Bitmap of candidates which we should try to entirely scalarize away and
325 those which cannot be (because they are and need be used as a whole). */
326 static bitmap should_scalarize_away_bitmap, cannot_scalarize_away_bitmap;
328 /* Obstack for creation of fancy names. */
329 static struct obstack name_obstack;
331 /* Head of a linked list of accesses that need to have its subaccesses
332 propagated to their assignment counterparts. */
333 static struct access *work_queue_head;
335 /* Number of parameters of the analyzed function when doing early ipa SRA. */
336 static int func_param_count;
338 /* scan_function sets the following to true if it encounters a call to
339 __builtin_apply_args. */
340 static bool encountered_apply_args;
342 /* Set by scan_function when it finds a recursive call. */
343 static bool encountered_recursive_call;
345 /* Set by scan_function when it finds a recursive call with less actual
346 arguments than formal parameters.. */
347 static bool encountered_unchangable_recursive_call;
349 /* This is a table in which for each basic block and parameter there is a
350 distance (offset + size) in that parameter which is dereferenced and
351 accessed in that BB. */
352 static HOST_WIDE_INT *bb_dereferences;
353 /* Bitmap of BBs that can cause the function to "stop" progressing by
354 returning, throwing externally, looping infinitely or calling a function
355 which might abort etc.. */
356 static bitmap final_bbs;
358 /* Representative of no accesses at all. */
359 static struct access no_accesses_representant;
361 /* Predicate to test the special value. */
363 static inline bool
364 no_accesses_p (struct access *access)
366 return access == &no_accesses_representant;
369 /* Dump contents of ACCESS to file F in a human friendly way. If GRP is true,
370 representative fields are dumped, otherwise those which only describe the
371 individual access are. */
373 static struct
375 /* Number of processed aggregates is readily available in
376 analyze_all_variable_accesses and so is not stored here. */
378 /* Number of created scalar replacements. */
379 int replacements;
381 /* Number of times sra_modify_expr or sra_modify_assign themselves changed an
382 expression. */
383 int exprs;
385 /* Number of statements created by generate_subtree_copies. */
386 int subtree_copies;
388 /* Number of statements created by load_assign_lhs_subreplacements. */
389 int subreplacements;
391 /* Number of times sra_modify_assign has deleted a statement. */
392 int deleted;
394 /* Number of times sra_modify_assign has to deal with subaccesses of LHS and
395 RHS reparately due to type conversions or nonexistent matching
396 references. */
397 int separate_lhs_rhs_handling;
399 /* Number of parameters that were removed because they were unused. */
400 int deleted_unused_parameters;
402 /* Number of scalars passed as parameters by reference that have been
403 converted to be passed by value. */
404 int scalar_by_ref_to_by_val;
406 /* Number of aggregate parameters that were replaced by one or more of their
407 components. */
408 int aggregate_params_reduced;
410 /* Numbber of components created when splitting aggregate parameters. */
411 int param_reductions_created;
412 } sra_stats;
414 static void
415 dump_access (FILE *f, struct access *access, bool grp)
417 fprintf (f, "access { ");
418 fprintf (f, "base = (%d)'", DECL_UID (access->base));
419 print_generic_expr (f, access->base, 0);
420 fprintf (f, "', offset = " HOST_WIDE_INT_PRINT_DEC, access->offset);
421 fprintf (f, ", size = " HOST_WIDE_INT_PRINT_DEC, access->size);
422 fprintf (f, ", expr = ");
423 print_generic_expr (f, access->expr, 0);
424 fprintf (f, ", type = ");
425 print_generic_expr (f, access->type, 0);
426 if (grp)
427 fprintf (f, ", grp_read = %d, grp_write = %d, grp_assignment_read = %d, "
428 "grp_assignment_write = %d, grp_scalar_read = %d, "
429 "grp_scalar_write = %d, grp_total_scalarization = %d, "
430 "grp_hint = %d, grp_covered = %d, "
431 "grp_unscalarizable_region = %d, grp_unscalarized_data = %d, "
432 "grp_partial_lhs = %d, grp_to_be_replaced = %d, "
433 "grp_to_be_debug_replaced = %d, grp_maybe_modified = %d, "
434 "grp_not_necessarilly_dereferenced = %d\n",
435 access->grp_read, access->grp_write, access->grp_assignment_read,
436 access->grp_assignment_write, access->grp_scalar_read,
437 access->grp_scalar_write, access->grp_total_scalarization,
438 access->grp_hint, access->grp_covered,
439 access->grp_unscalarizable_region, access->grp_unscalarized_data,
440 access->grp_partial_lhs, access->grp_to_be_replaced,
441 access->grp_to_be_debug_replaced, access->grp_maybe_modified,
442 access->grp_not_necessarilly_dereferenced);
443 else
444 fprintf (f, ", write = %d, grp_total_scalarization = %d, "
445 "grp_partial_lhs = %d\n",
446 access->write, access->grp_total_scalarization,
447 access->grp_partial_lhs);
450 /* Dump a subtree rooted in ACCESS to file F, indent by LEVEL. */
452 static void
453 dump_access_tree_1 (FILE *f, struct access *access, int level)
457 int i;
459 for (i = 0; i < level; i++)
460 fputs ("* ", dump_file);
462 dump_access (f, access, true);
464 if (access->first_child)
465 dump_access_tree_1 (f, access->first_child, level + 1);
467 access = access->next_sibling;
469 while (access);
472 /* Dump all access trees for a variable, given the pointer to the first root in
473 ACCESS. */
475 static void
476 dump_access_tree (FILE *f, struct access *access)
478 for (; access; access = access->next_grp)
479 dump_access_tree_1 (f, access, 0);
482 /* Return true iff ACC is non-NULL and has subaccesses. */
484 static inline bool
485 access_has_children_p (struct access *acc)
487 return acc && acc->first_child;
490 /* Return true iff ACC is (partly) covered by at least one replacement. */
492 static bool
493 access_has_replacements_p (struct access *acc)
495 struct access *child;
496 if (acc->grp_to_be_replaced)
497 return true;
498 for (child = acc->first_child; child; child = child->next_sibling)
499 if (access_has_replacements_p (child))
500 return true;
501 return false;
504 /* Return a vector of pointers to accesses for the variable given in BASE or
505 NULL if there is none. */
507 static vec<access_p> *
508 get_base_access_vector (tree base)
510 void **slot;
512 slot = pointer_map_contains (base_access_vec, base);
513 if (!slot)
514 return NULL;
515 else
516 return *(vec<access_p> **) slot;
519 /* Find an access with required OFFSET and SIZE in a subtree of accesses rooted
520 in ACCESS. Return NULL if it cannot be found. */
522 static struct access *
523 find_access_in_subtree (struct access *access, HOST_WIDE_INT offset,
524 HOST_WIDE_INT size)
526 while (access && (access->offset != offset || access->size != size))
528 struct access *child = access->first_child;
530 while (child && (child->offset + child->size <= offset))
531 child = child->next_sibling;
532 access = child;
535 return access;
538 /* Return the first group representative for DECL or NULL if none exists. */
540 static struct access *
541 get_first_repr_for_decl (tree base)
543 vec<access_p> *access_vec;
545 access_vec = get_base_access_vector (base);
546 if (!access_vec)
547 return NULL;
549 return (*access_vec)[0];
552 /* Find an access representative for the variable BASE and given OFFSET and
553 SIZE. Requires that access trees have already been built. Return NULL if
554 it cannot be found. */
556 static struct access *
557 get_var_base_offset_size_access (tree base, HOST_WIDE_INT offset,
558 HOST_WIDE_INT size)
560 struct access *access;
562 access = get_first_repr_for_decl (base);
563 while (access && (access->offset + access->size <= offset))
564 access = access->next_grp;
565 if (!access)
566 return NULL;
568 return find_access_in_subtree (access, offset, size);
571 /* Add LINK to the linked list of assign links of RACC. */
572 static void
573 add_link_to_rhs (struct access *racc, struct assign_link *link)
575 gcc_assert (link->racc == racc);
577 if (!racc->first_link)
579 gcc_assert (!racc->last_link);
580 racc->first_link = link;
582 else
583 racc->last_link->next = link;
585 racc->last_link = link;
586 link->next = NULL;
589 /* Move all link structures in their linked list in OLD_RACC to the linked list
590 in NEW_RACC. */
591 static void
592 relink_to_new_repr (struct access *new_racc, struct access *old_racc)
594 if (!old_racc->first_link)
596 gcc_assert (!old_racc->last_link);
597 return;
600 if (new_racc->first_link)
602 gcc_assert (!new_racc->last_link->next);
603 gcc_assert (!old_racc->last_link || !old_racc->last_link->next);
605 new_racc->last_link->next = old_racc->first_link;
606 new_racc->last_link = old_racc->last_link;
608 else
610 gcc_assert (!new_racc->last_link);
612 new_racc->first_link = old_racc->first_link;
613 new_racc->last_link = old_racc->last_link;
615 old_racc->first_link = old_racc->last_link = NULL;
618 /* Add ACCESS to the work queue (which is actually a stack). */
620 static void
621 add_access_to_work_queue (struct access *access)
623 if (!access->grp_queued)
625 gcc_assert (!access->next_queued);
626 access->next_queued = work_queue_head;
627 access->grp_queued = 1;
628 work_queue_head = access;
632 /* Pop an access from the work queue, and return it, assuming there is one. */
634 static struct access *
635 pop_access_from_work_queue (void)
637 struct access *access = work_queue_head;
639 work_queue_head = access->next_queued;
640 access->next_queued = NULL;
641 access->grp_queued = 0;
642 return access;
646 /* Allocate necessary structures. */
648 static void
649 sra_initialize (void)
651 candidate_bitmap = BITMAP_ALLOC (NULL);
652 candidates.create (vec_safe_length (cfun->local_decls) / 2);
653 should_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
654 cannot_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
655 gcc_obstack_init (&name_obstack);
656 access_pool = create_alloc_pool ("SRA accesses", sizeof (struct access), 16);
657 link_pool = create_alloc_pool ("SRA links", sizeof (struct assign_link), 16);
658 base_access_vec = pointer_map_create ();
659 memset (&sra_stats, 0, sizeof (sra_stats));
660 encountered_apply_args = false;
661 encountered_recursive_call = false;
662 encountered_unchangable_recursive_call = false;
665 /* Hook fed to pointer_map_traverse, deallocate stored vectors. */
667 static bool
668 delete_base_accesses (const void *key ATTRIBUTE_UNUSED, void **value,
669 void *data ATTRIBUTE_UNUSED)
671 vec<access_p> *access_vec = (vec<access_p> *) *value;
672 vec_free (access_vec);
673 return true;
676 /* Deallocate all general structures. */
678 static void
679 sra_deinitialize (void)
681 BITMAP_FREE (candidate_bitmap);
682 candidates.dispose ();
683 BITMAP_FREE (should_scalarize_away_bitmap);
684 BITMAP_FREE (cannot_scalarize_away_bitmap);
685 free_alloc_pool (access_pool);
686 free_alloc_pool (link_pool);
687 obstack_free (&name_obstack, NULL);
689 pointer_map_traverse (base_access_vec, delete_base_accesses, NULL);
690 pointer_map_destroy (base_access_vec);
693 /* Remove DECL from candidates for SRA and write REASON to the dump file if
694 there is one. */
695 static void
696 disqualify_candidate (tree decl, const char *reason)
698 if (bitmap_clear_bit (candidate_bitmap, DECL_UID (decl)))
699 candidates.clear_slot (candidates.find_slot_with_hash (decl,
700 DECL_UID (decl),
701 NO_INSERT));
703 if (dump_file && (dump_flags & TDF_DETAILS))
705 fprintf (dump_file, "! Disqualifying ");
706 print_generic_expr (dump_file, decl, 0);
707 fprintf (dump_file, " - %s\n", reason);
711 /* Return true iff the type contains a field or an element which does not allow
712 scalarization. */
714 static bool
715 type_internals_preclude_sra_p (tree type, const char **msg)
717 tree fld;
718 tree et;
720 switch (TREE_CODE (type))
722 case RECORD_TYPE:
723 case UNION_TYPE:
724 case QUAL_UNION_TYPE:
725 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
726 if (TREE_CODE (fld) == FIELD_DECL)
728 tree ft = TREE_TYPE (fld);
730 if (TREE_THIS_VOLATILE (fld))
732 *msg = "volatile structure field";
733 return true;
735 if (!DECL_FIELD_OFFSET (fld))
737 *msg = "no structure field offset";
738 return true;
740 if (!DECL_SIZE (fld))
742 *msg = "zero structure field size";
743 return true;
745 if (!tree_fits_uhwi_p (DECL_FIELD_OFFSET (fld)))
747 *msg = "structure field offset not fixed";
748 return true;
750 if (!tree_fits_uhwi_p (DECL_SIZE (fld)))
752 *msg = "structure field size not fixed";
753 return true;
755 if (!tree_fits_shwi_p (bit_position (fld)))
757 *msg = "structure field size too big";
758 return true;
760 if (AGGREGATE_TYPE_P (ft)
761 && int_bit_position (fld) % BITS_PER_UNIT != 0)
763 *msg = "structure field is bit field";
764 return true;
767 if (AGGREGATE_TYPE_P (ft) && type_internals_preclude_sra_p (ft, msg))
768 return true;
771 return false;
773 case ARRAY_TYPE:
774 et = TREE_TYPE (type);
776 if (TYPE_VOLATILE (et))
778 *msg = "element type is volatile";
779 return true;
782 if (AGGREGATE_TYPE_P (et) && type_internals_preclude_sra_p (et, msg))
783 return true;
785 return false;
787 default:
788 return false;
792 /* If T is an SSA_NAME, return NULL if it is not a default def or return its
793 base variable if it is. Return T if it is not an SSA_NAME. */
795 static tree
796 get_ssa_base_param (tree t)
798 if (TREE_CODE (t) == SSA_NAME)
800 if (SSA_NAME_IS_DEFAULT_DEF (t))
801 return SSA_NAME_VAR (t);
802 else
803 return NULL_TREE;
805 return t;
808 /* Mark a dereference of BASE of distance DIST in a basic block tht STMT
809 belongs to, unless the BB has already been marked as a potentially
810 final. */
812 static void
813 mark_parm_dereference (tree base, HOST_WIDE_INT dist, gimple stmt)
815 basic_block bb = gimple_bb (stmt);
816 int idx, parm_index = 0;
817 tree parm;
819 if (bitmap_bit_p (final_bbs, bb->index))
820 return;
822 for (parm = DECL_ARGUMENTS (current_function_decl);
823 parm && parm != base;
824 parm = DECL_CHAIN (parm))
825 parm_index++;
827 gcc_assert (parm_index < func_param_count);
829 idx = bb->index * func_param_count + parm_index;
830 if (bb_dereferences[idx] < dist)
831 bb_dereferences[idx] = dist;
834 /* Allocate an access structure for BASE, OFFSET and SIZE, clear it, fill in
835 the three fields. Also add it to the vector of accesses corresponding to
836 the base. Finally, return the new access. */
838 static struct access *
839 create_access_1 (tree base, HOST_WIDE_INT offset, HOST_WIDE_INT size)
841 vec<access_p> *v;
842 struct access *access;
843 void **slot;
845 access = (struct access *) pool_alloc (access_pool);
846 memset (access, 0, sizeof (struct access));
847 access->base = base;
848 access->offset = offset;
849 access->size = size;
851 slot = pointer_map_contains (base_access_vec, base);
852 if (slot)
853 v = (vec<access_p> *) *slot;
854 else
855 vec_alloc (v, 32);
857 v->safe_push (access);
859 *((vec<access_p> **)
860 pointer_map_insert (base_access_vec, base)) = v;
862 return access;
865 /* Create and insert access for EXPR. Return created access, or NULL if it is
866 not possible. */
868 static struct access *
869 create_access (tree expr, gimple stmt, bool write)
871 struct access *access;
872 HOST_WIDE_INT offset, size, max_size;
873 tree base = expr;
874 bool ptr, unscalarizable_region = false;
876 base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
878 if (sra_mode == SRA_MODE_EARLY_IPA
879 && TREE_CODE (base) == MEM_REF)
881 base = get_ssa_base_param (TREE_OPERAND (base, 0));
882 if (!base)
883 return NULL;
884 ptr = true;
886 else
887 ptr = false;
889 if (!DECL_P (base) || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
890 return NULL;
892 if (sra_mode == SRA_MODE_EARLY_IPA)
894 if (size < 0 || size != max_size)
896 disqualify_candidate (base, "Encountered a variable sized access.");
897 return NULL;
899 if (TREE_CODE (expr) == COMPONENT_REF
900 && DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
902 disqualify_candidate (base, "Encountered a bit-field access.");
903 return NULL;
905 gcc_checking_assert ((offset % BITS_PER_UNIT) == 0);
907 if (ptr)
908 mark_parm_dereference (base, offset + size, stmt);
910 else
912 if (size != max_size)
914 size = max_size;
915 unscalarizable_region = true;
917 if (size < 0)
919 disqualify_candidate (base, "Encountered an unconstrained access.");
920 return NULL;
924 access = create_access_1 (base, offset, size);
925 access->expr = expr;
926 access->type = TREE_TYPE (expr);
927 access->write = write;
928 access->grp_unscalarizable_region = unscalarizable_region;
929 access->stmt = stmt;
931 if (TREE_CODE (expr) == COMPONENT_REF
932 && DECL_NONADDRESSABLE_P (TREE_OPERAND (expr, 1)))
933 access->non_addressable = 1;
935 return access;
939 /* Return true iff TYPE is a RECORD_TYPE with fields that are either of gimple
940 register types or (recursively) records with only these two kinds of fields.
941 It also returns false if any of these records contains a bit-field. */
943 static bool
944 type_consists_of_records_p (tree type)
946 tree fld;
948 if (TREE_CODE (type) != RECORD_TYPE)
949 return false;
951 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
952 if (TREE_CODE (fld) == FIELD_DECL)
954 tree ft = TREE_TYPE (fld);
956 if (DECL_BIT_FIELD (fld))
957 return false;
959 if (!is_gimple_reg_type (ft)
960 && !type_consists_of_records_p (ft))
961 return false;
964 return true;
967 /* Create total_scalarization accesses for all scalar type fields in DECL that
968 must be of a RECORD_TYPE conforming to type_consists_of_records_p. BASE
969 must be the top-most VAR_DECL representing the variable, OFFSET must be the
970 offset of DECL within BASE. REF must be the memory reference expression for
971 the given decl. */
973 static void
974 completely_scalarize_record (tree base, tree decl, HOST_WIDE_INT offset,
975 tree ref)
977 tree fld, decl_type = TREE_TYPE (decl);
979 for (fld = TYPE_FIELDS (decl_type); fld; fld = DECL_CHAIN (fld))
980 if (TREE_CODE (fld) == FIELD_DECL)
982 HOST_WIDE_INT pos = offset + int_bit_position (fld);
983 tree ft = TREE_TYPE (fld);
984 tree nref = build3 (COMPONENT_REF, TREE_TYPE (fld), ref, fld,
985 NULL_TREE);
987 if (is_gimple_reg_type (ft))
989 struct access *access;
990 HOST_WIDE_INT size;
992 size = tree_to_uhwi (DECL_SIZE (fld));
993 access = create_access_1 (base, pos, size);
994 access->expr = nref;
995 access->type = ft;
996 access->grp_total_scalarization = 1;
997 /* Accesses for intraprocedural SRA can have their stmt NULL. */
999 else
1000 completely_scalarize_record (base, fld, pos, nref);
1004 /* Create total_scalarization accesses for all scalar type fields in VAR and
1005 for VAR a a whole. VAR must be of a RECORD_TYPE conforming to
1006 type_consists_of_records_p. */
1008 static void
1009 completely_scalarize_var (tree var)
1011 HOST_WIDE_INT size = tree_to_uhwi (DECL_SIZE (var));
1012 struct access *access;
1014 access = create_access_1 (var, 0, size);
1015 access->expr = var;
1016 access->type = TREE_TYPE (var);
1017 access->grp_total_scalarization = 1;
1019 completely_scalarize_record (var, var, 0, var);
1022 /* Return true if REF has an VIEW_CONVERT_EXPR somewhere in it. */
1024 static inline bool
1025 contains_view_convert_expr_p (const_tree ref)
1027 while (handled_component_p (ref))
1029 if (TREE_CODE (ref) == VIEW_CONVERT_EXPR)
1030 return true;
1031 ref = TREE_OPERAND (ref, 0);
1034 return false;
1037 /* Search the given tree for a declaration by skipping handled components and
1038 exclude it from the candidates. */
1040 static void
1041 disqualify_base_of_expr (tree t, const char *reason)
1043 t = get_base_address (t);
1044 if (sra_mode == SRA_MODE_EARLY_IPA
1045 && TREE_CODE (t) == MEM_REF)
1046 t = get_ssa_base_param (TREE_OPERAND (t, 0));
1048 if (t && DECL_P (t))
1049 disqualify_candidate (t, reason);
1052 /* Scan expression EXPR and create access structures for all accesses to
1053 candidates for scalarization. Return the created access or NULL if none is
1054 created. */
1056 static struct access *
1057 build_access_from_expr_1 (tree expr, gimple stmt, bool write)
1059 struct access *ret = NULL;
1060 bool partial_ref;
1062 if (TREE_CODE (expr) == BIT_FIELD_REF
1063 || TREE_CODE (expr) == IMAGPART_EXPR
1064 || TREE_CODE (expr) == REALPART_EXPR)
1066 expr = TREE_OPERAND (expr, 0);
1067 partial_ref = true;
1069 else
1070 partial_ref = false;
1072 /* We need to dive through V_C_Es in order to get the size of its parameter
1073 and not the result type. Ada produces such statements. We are also
1074 capable of handling the topmost V_C_E but not any of those buried in other
1075 handled components. */
1076 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
1077 expr = TREE_OPERAND (expr, 0);
1079 if (contains_view_convert_expr_p (expr))
1081 disqualify_base_of_expr (expr, "V_C_E under a different handled "
1082 "component.");
1083 return NULL;
1086 switch (TREE_CODE (expr))
1088 case MEM_REF:
1089 if (TREE_CODE (TREE_OPERAND (expr, 0)) != ADDR_EXPR
1090 && sra_mode != SRA_MODE_EARLY_IPA)
1091 return NULL;
1092 /* fall through */
1093 case VAR_DECL:
1094 case PARM_DECL:
1095 case RESULT_DECL:
1096 case COMPONENT_REF:
1097 case ARRAY_REF:
1098 case ARRAY_RANGE_REF:
1099 ret = create_access (expr, stmt, write);
1100 break;
1102 default:
1103 break;
1106 if (write && partial_ref && ret)
1107 ret->grp_partial_lhs = 1;
1109 return ret;
1112 /* Scan expression EXPR and create access structures for all accesses to
1113 candidates for scalarization. Return true if any access has been inserted.
1114 STMT must be the statement from which the expression is taken, WRITE must be
1115 true if the expression is a store and false otherwise. */
1117 static bool
1118 build_access_from_expr (tree expr, gimple stmt, bool write)
1120 struct access *access;
1122 access = build_access_from_expr_1 (expr, stmt, write);
1123 if (access)
1125 /* This means the aggregate is accesses as a whole in a way other than an
1126 assign statement and thus cannot be removed even if we had a scalar
1127 replacement for everything. */
1128 if (cannot_scalarize_away_bitmap)
1129 bitmap_set_bit (cannot_scalarize_away_bitmap, DECL_UID (access->base));
1130 return true;
1132 return false;
1135 /* Disqualify LHS and RHS for scalarization if STMT must end its basic block in
1136 modes in which it matters, return true iff they have been disqualified. RHS
1137 may be NULL, in that case ignore it. If we scalarize an aggregate in
1138 intra-SRA we may need to add statements after each statement. This is not
1139 possible if a statement unconditionally has to end the basic block. */
1140 static bool
1141 disqualify_ops_if_throwing_stmt (gimple stmt, tree lhs, tree rhs)
1143 if ((sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
1144 && (stmt_can_throw_internal (stmt) || stmt_ends_bb_p (stmt)))
1146 disqualify_base_of_expr (lhs, "LHS of a throwing stmt.");
1147 if (rhs)
1148 disqualify_base_of_expr (rhs, "RHS of a throwing stmt.");
1149 return true;
1151 return false;
1154 /* Scan expressions occurring in STMT, create access structures for all accesses
1155 to candidates for scalarization and remove those candidates which occur in
1156 statements or expressions that prevent them from being split apart. Return
1157 true if any access has been inserted. */
1159 static bool
1160 build_accesses_from_assign (gimple stmt)
1162 tree lhs, rhs;
1163 struct access *lacc, *racc;
1165 if (!gimple_assign_single_p (stmt)
1166 /* Scope clobbers don't influence scalarization. */
1167 || gimple_clobber_p (stmt))
1168 return false;
1170 lhs = gimple_assign_lhs (stmt);
1171 rhs = gimple_assign_rhs1 (stmt);
1173 if (disqualify_ops_if_throwing_stmt (stmt, lhs, rhs))
1174 return false;
1176 racc = build_access_from_expr_1 (rhs, stmt, false);
1177 lacc = build_access_from_expr_1 (lhs, stmt, true);
1179 if (lacc)
1180 lacc->grp_assignment_write = 1;
1182 if (racc)
1184 racc->grp_assignment_read = 1;
1185 if (should_scalarize_away_bitmap && !gimple_has_volatile_ops (stmt)
1186 && !is_gimple_reg_type (racc->type))
1187 bitmap_set_bit (should_scalarize_away_bitmap, DECL_UID (racc->base));
1190 if (lacc && racc
1191 && (sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
1192 && !lacc->grp_unscalarizable_region
1193 && !racc->grp_unscalarizable_region
1194 && AGGREGATE_TYPE_P (TREE_TYPE (lhs))
1195 && lacc->size == racc->size
1196 && useless_type_conversion_p (lacc->type, racc->type))
1198 struct assign_link *link;
1200 link = (struct assign_link *) pool_alloc (link_pool);
1201 memset (link, 0, sizeof (struct assign_link));
1203 link->lacc = lacc;
1204 link->racc = racc;
1206 add_link_to_rhs (racc, link);
1209 return lacc || racc;
1212 /* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine
1213 GIMPLE_ASM operands with memory constrains which cannot be scalarized. */
1215 static bool
1216 asm_visit_addr (gimple stmt ATTRIBUTE_UNUSED, tree op,
1217 void *data ATTRIBUTE_UNUSED)
1219 op = get_base_address (op);
1220 if (op
1221 && DECL_P (op))
1222 disqualify_candidate (op, "Non-scalarizable GIMPLE_ASM operand.");
1224 return false;
1227 /* Return true iff callsite CALL has at least as many actual arguments as there
1228 are formal parameters of the function currently processed by IPA-SRA. */
1230 static inline bool
1231 callsite_has_enough_arguments_p (gimple call)
1233 return gimple_call_num_args (call) >= (unsigned) func_param_count;
1236 /* Scan function and look for interesting expressions and create access
1237 structures for them. Return true iff any access is created. */
1239 static bool
1240 scan_function (void)
1242 basic_block bb;
1243 bool ret = false;
1245 FOR_EACH_BB (bb)
1247 gimple_stmt_iterator gsi;
1248 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1250 gimple stmt = gsi_stmt (gsi);
1251 tree t;
1252 unsigned i;
1254 if (final_bbs && stmt_can_throw_external (stmt))
1255 bitmap_set_bit (final_bbs, bb->index);
1256 switch (gimple_code (stmt))
1258 case GIMPLE_RETURN:
1259 t = gimple_return_retval (stmt);
1260 if (t != NULL_TREE)
1261 ret |= build_access_from_expr (t, stmt, false);
1262 if (final_bbs)
1263 bitmap_set_bit (final_bbs, bb->index);
1264 break;
1266 case GIMPLE_ASSIGN:
1267 ret |= build_accesses_from_assign (stmt);
1268 break;
1270 case GIMPLE_CALL:
1271 for (i = 0; i < gimple_call_num_args (stmt); i++)
1272 ret |= build_access_from_expr (gimple_call_arg (stmt, i),
1273 stmt, false);
1275 if (sra_mode == SRA_MODE_EARLY_IPA)
1277 tree dest = gimple_call_fndecl (stmt);
1278 int flags = gimple_call_flags (stmt);
1280 if (dest)
1282 if (DECL_BUILT_IN_CLASS (dest) == BUILT_IN_NORMAL
1283 && DECL_FUNCTION_CODE (dest) == BUILT_IN_APPLY_ARGS)
1284 encountered_apply_args = true;
1285 if (recursive_call_p (current_function_decl, dest))
1287 encountered_recursive_call = true;
1288 if (!callsite_has_enough_arguments_p (stmt))
1289 encountered_unchangable_recursive_call = true;
1293 if (final_bbs
1294 && (flags & (ECF_CONST | ECF_PURE)) == 0)
1295 bitmap_set_bit (final_bbs, bb->index);
1298 t = gimple_call_lhs (stmt);
1299 if (t && !disqualify_ops_if_throwing_stmt (stmt, t, NULL))
1300 ret |= build_access_from_expr (t, stmt, true);
1301 break;
1303 case GIMPLE_ASM:
1304 walk_stmt_load_store_addr_ops (stmt, NULL, NULL, NULL,
1305 asm_visit_addr);
1306 if (final_bbs)
1307 bitmap_set_bit (final_bbs, bb->index);
1309 for (i = 0; i < gimple_asm_ninputs (stmt); i++)
1311 t = TREE_VALUE (gimple_asm_input_op (stmt, i));
1312 ret |= build_access_from_expr (t, stmt, false);
1314 for (i = 0; i < gimple_asm_noutputs (stmt); i++)
1316 t = TREE_VALUE (gimple_asm_output_op (stmt, i));
1317 ret |= build_access_from_expr (t, stmt, true);
1319 break;
1321 default:
1322 break;
1327 return ret;
1330 /* Helper of QSORT function. There are pointers to accesses in the array. An
1331 access is considered smaller than another if it has smaller offset or if the
1332 offsets are the same but is size is bigger. */
1334 static int
1335 compare_access_positions (const void *a, const void *b)
1337 const access_p *fp1 = (const access_p *) a;
1338 const access_p *fp2 = (const access_p *) b;
1339 const access_p f1 = *fp1;
1340 const access_p f2 = *fp2;
1342 if (f1->offset != f2->offset)
1343 return f1->offset < f2->offset ? -1 : 1;
1345 if (f1->size == f2->size)
1347 if (f1->type == f2->type)
1348 return 0;
1349 /* Put any non-aggregate type before any aggregate type. */
1350 else if (!is_gimple_reg_type (f1->type)
1351 && is_gimple_reg_type (f2->type))
1352 return 1;
1353 else if (is_gimple_reg_type (f1->type)
1354 && !is_gimple_reg_type (f2->type))
1355 return -1;
1356 /* Put any complex or vector type before any other scalar type. */
1357 else if (TREE_CODE (f1->type) != COMPLEX_TYPE
1358 && TREE_CODE (f1->type) != VECTOR_TYPE
1359 && (TREE_CODE (f2->type) == COMPLEX_TYPE
1360 || TREE_CODE (f2->type) == VECTOR_TYPE))
1361 return 1;
1362 else if ((TREE_CODE (f1->type) == COMPLEX_TYPE
1363 || TREE_CODE (f1->type) == VECTOR_TYPE)
1364 && TREE_CODE (f2->type) != COMPLEX_TYPE
1365 && TREE_CODE (f2->type) != VECTOR_TYPE)
1366 return -1;
1367 /* Put the integral type with the bigger precision first. */
1368 else if (INTEGRAL_TYPE_P (f1->type)
1369 && INTEGRAL_TYPE_P (f2->type))
1370 return TYPE_PRECISION (f2->type) - TYPE_PRECISION (f1->type);
1371 /* Put any integral type with non-full precision last. */
1372 else if (INTEGRAL_TYPE_P (f1->type)
1373 && (TREE_INT_CST_LOW (TYPE_SIZE (f1->type))
1374 != TYPE_PRECISION (f1->type)))
1375 return 1;
1376 else if (INTEGRAL_TYPE_P (f2->type)
1377 && (TREE_INT_CST_LOW (TYPE_SIZE (f2->type))
1378 != TYPE_PRECISION (f2->type)))
1379 return -1;
1380 /* Stabilize the sort. */
1381 return TYPE_UID (f1->type) - TYPE_UID (f2->type);
1384 /* We want the bigger accesses first, thus the opposite operator in the next
1385 line: */
1386 return f1->size > f2->size ? -1 : 1;
1390 /* Append a name of the declaration to the name obstack. A helper function for
1391 make_fancy_name. */
1393 static void
1394 make_fancy_decl_name (tree decl)
1396 char buffer[32];
1398 tree name = DECL_NAME (decl);
1399 if (name)
1400 obstack_grow (&name_obstack, IDENTIFIER_POINTER (name),
1401 IDENTIFIER_LENGTH (name));
1402 else
1404 sprintf (buffer, "D%u", DECL_UID (decl));
1405 obstack_grow (&name_obstack, buffer, strlen (buffer));
1409 /* Helper for make_fancy_name. */
1411 static void
1412 make_fancy_name_1 (tree expr)
1414 char buffer[32];
1415 tree index;
1417 if (DECL_P (expr))
1419 make_fancy_decl_name (expr);
1420 return;
1423 switch (TREE_CODE (expr))
1425 case COMPONENT_REF:
1426 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1427 obstack_1grow (&name_obstack, '$');
1428 make_fancy_decl_name (TREE_OPERAND (expr, 1));
1429 break;
1431 case ARRAY_REF:
1432 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1433 obstack_1grow (&name_obstack, '$');
1434 /* Arrays with only one element may not have a constant as their
1435 index. */
1436 index = TREE_OPERAND (expr, 1);
1437 if (TREE_CODE (index) != INTEGER_CST)
1438 break;
1439 sprintf (buffer, HOST_WIDE_INT_PRINT_DEC, TREE_INT_CST_LOW (index));
1440 obstack_grow (&name_obstack, buffer, strlen (buffer));
1441 break;
1443 case ADDR_EXPR:
1444 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1445 break;
1447 case MEM_REF:
1448 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1449 if (!integer_zerop (TREE_OPERAND (expr, 1)))
1451 obstack_1grow (&name_obstack, '$');
1452 sprintf (buffer, HOST_WIDE_INT_PRINT_DEC,
1453 TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)));
1454 obstack_grow (&name_obstack, buffer, strlen (buffer));
1456 break;
1458 case BIT_FIELD_REF:
1459 case REALPART_EXPR:
1460 case IMAGPART_EXPR:
1461 gcc_unreachable (); /* we treat these as scalars. */
1462 break;
1463 default:
1464 break;
1468 /* Create a human readable name for replacement variable of ACCESS. */
1470 static char *
1471 make_fancy_name (tree expr)
1473 make_fancy_name_1 (expr);
1474 obstack_1grow (&name_obstack, '\0');
1475 return XOBFINISH (&name_obstack, char *);
1478 /* Construct a MEM_REF that would reference a part of aggregate BASE of type
1479 EXP_TYPE at the given OFFSET. If BASE is something for which
1480 get_addr_base_and_unit_offset returns NULL, gsi must be non-NULL and is used
1481 to insert new statements either before or below the current one as specified
1482 by INSERT_AFTER. This function is not capable of handling bitfields.
1484 BASE must be either a declaration or a memory reference that has correct
1485 alignment ifformation embeded in it (e.g. a pre-existing one in SRA). */
1487 tree
1488 build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset,
1489 tree exp_type, gimple_stmt_iterator *gsi,
1490 bool insert_after)
1492 tree prev_base = base;
1493 tree off;
1494 tree mem_ref;
1495 HOST_WIDE_INT base_offset;
1496 unsigned HOST_WIDE_INT misalign;
1497 unsigned int align;
1499 gcc_checking_assert (offset % BITS_PER_UNIT == 0);
1500 get_object_alignment_1 (base, &align, &misalign);
1501 base = get_addr_base_and_unit_offset (base, &base_offset);
1503 /* get_addr_base_and_unit_offset returns NULL for references with a variable
1504 offset such as array[var_index]. */
1505 if (!base)
1507 gimple stmt;
1508 tree tmp, addr;
1510 gcc_checking_assert (gsi);
1511 tmp = make_ssa_name (build_pointer_type (TREE_TYPE (prev_base)), NULL);
1512 addr = build_fold_addr_expr (unshare_expr (prev_base));
1513 STRIP_USELESS_TYPE_CONVERSION (addr);
1514 stmt = gimple_build_assign (tmp, addr);
1515 gimple_set_location (stmt, loc);
1516 if (insert_after)
1517 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
1518 else
1519 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
1521 off = build_int_cst (reference_alias_ptr_type (prev_base),
1522 offset / BITS_PER_UNIT);
1523 base = tmp;
1525 else if (TREE_CODE (base) == MEM_REF)
1527 off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
1528 base_offset + offset / BITS_PER_UNIT);
1529 off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
1530 base = unshare_expr (TREE_OPERAND (base, 0));
1532 else
1534 off = build_int_cst (reference_alias_ptr_type (base),
1535 base_offset + offset / BITS_PER_UNIT);
1536 base = build_fold_addr_expr (unshare_expr (base));
1539 misalign = (misalign + offset) & (align - 1);
1540 if (misalign != 0)
1541 align = (misalign & -misalign);
1542 if (align < TYPE_ALIGN (exp_type))
1543 exp_type = build_aligned_type (exp_type, align);
1545 mem_ref = fold_build2_loc (loc, MEM_REF, exp_type, base, off);
1546 if (TREE_THIS_VOLATILE (prev_base))
1547 TREE_THIS_VOLATILE (mem_ref) = 1;
1548 if (TREE_SIDE_EFFECTS (prev_base))
1549 TREE_SIDE_EFFECTS (mem_ref) = 1;
1550 return mem_ref;
1553 /* Construct a memory reference to a part of an aggregate BASE at the given
1554 OFFSET and of the same type as MODEL. In case this is a reference to a
1555 bit-field, the function will replicate the last component_ref of model's
1556 expr to access it. GSI and INSERT_AFTER have the same meaning as in
1557 build_ref_for_offset. */
1559 static tree
1560 build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
1561 struct access *model, gimple_stmt_iterator *gsi,
1562 bool insert_after)
1564 if (TREE_CODE (model->expr) == COMPONENT_REF
1565 && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
1567 /* This access represents a bit-field. */
1568 tree t, exp_type, fld = TREE_OPERAND (model->expr, 1);
1570 offset -= int_bit_position (fld);
1571 exp_type = TREE_TYPE (TREE_OPERAND (model->expr, 0));
1572 t = build_ref_for_offset (loc, base, offset, exp_type, gsi, insert_after);
1573 return fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (fld), t, fld,
1574 NULL_TREE);
1576 else
1577 return build_ref_for_offset (loc, base, offset, model->type,
1578 gsi, insert_after);
1581 /* Attempt to build a memory reference that we could but into a gimple
1582 debug_bind statement. Similar to build_ref_for_model but punts if it has to
1583 create statements and return s NULL instead. This function also ignores
1584 alignment issues and so its results should never end up in non-debug
1585 statements. */
1587 static tree
1588 build_debug_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
1589 struct access *model)
1591 HOST_WIDE_INT base_offset;
1592 tree off;
1594 if (TREE_CODE (model->expr) == COMPONENT_REF
1595 && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
1596 return NULL_TREE;
1598 base = get_addr_base_and_unit_offset (base, &base_offset);
1599 if (!base)
1600 return NULL_TREE;
1601 if (TREE_CODE (base) == MEM_REF)
1603 off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
1604 base_offset + offset / BITS_PER_UNIT);
1605 off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
1606 base = unshare_expr (TREE_OPERAND (base, 0));
1608 else
1610 off = build_int_cst (reference_alias_ptr_type (base),
1611 base_offset + offset / BITS_PER_UNIT);
1612 base = build_fold_addr_expr (unshare_expr (base));
1615 return fold_build2_loc (loc, MEM_REF, model->type, base, off);
1618 /* Construct a memory reference consisting of component_refs and array_refs to
1619 a part of an aggregate *RES (which is of type TYPE). The requested part
1620 should have type EXP_TYPE at be the given OFFSET. This function might not
1621 succeed, it returns true when it does and only then *RES points to something
1622 meaningful. This function should be used only to build expressions that we
1623 might need to present to user (e.g. in warnings). In all other situations,
1624 build_ref_for_model or build_ref_for_offset should be used instead. */
1626 static bool
1627 build_user_friendly_ref_for_offset (tree *res, tree type, HOST_WIDE_INT offset,
1628 tree exp_type)
1630 while (1)
1632 tree fld;
1633 tree tr_size, index, minidx;
1634 HOST_WIDE_INT el_size;
1636 if (offset == 0 && exp_type
1637 && types_compatible_p (exp_type, type))
1638 return true;
1640 switch (TREE_CODE (type))
1642 case UNION_TYPE:
1643 case QUAL_UNION_TYPE:
1644 case RECORD_TYPE:
1645 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
1647 HOST_WIDE_INT pos, size;
1648 tree tr_pos, expr, *expr_ptr;
1650 if (TREE_CODE (fld) != FIELD_DECL)
1651 continue;
1653 tr_pos = bit_position (fld);
1654 if (!tr_pos || !tree_fits_uhwi_p (tr_pos))
1655 continue;
1656 pos = TREE_INT_CST_LOW (tr_pos);
1657 gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0);
1658 tr_size = DECL_SIZE (fld);
1659 if (!tr_size || !tree_fits_uhwi_p (tr_size))
1660 continue;
1661 size = TREE_INT_CST_LOW (tr_size);
1662 if (size == 0)
1664 if (pos != offset)
1665 continue;
1667 else if (pos > offset || (pos + size) <= offset)
1668 continue;
1670 expr = build3 (COMPONENT_REF, TREE_TYPE (fld), *res, fld,
1671 NULL_TREE);
1672 expr_ptr = &expr;
1673 if (build_user_friendly_ref_for_offset (expr_ptr, TREE_TYPE (fld),
1674 offset - pos, exp_type))
1676 *res = expr;
1677 return true;
1680 return false;
1682 case ARRAY_TYPE:
1683 tr_size = TYPE_SIZE (TREE_TYPE (type));
1684 if (!tr_size || !tree_fits_uhwi_p (tr_size))
1685 return false;
1686 el_size = tree_to_uhwi (tr_size);
1688 minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
1689 if (TREE_CODE (minidx) != INTEGER_CST || el_size == 0)
1690 return false;
1691 index = build_int_cst (TYPE_DOMAIN (type), offset / el_size);
1692 if (!integer_zerop (minidx))
1693 index = int_const_binop (PLUS_EXPR, index, minidx);
1694 *res = build4 (ARRAY_REF, TREE_TYPE (type), *res, index,
1695 NULL_TREE, NULL_TREE);
1696 offset = offset % el_size;
1697 type = TREE_TYPE (type);
1698 break;
1700 default:
1701 if (offset != 0)
1702 return false;
1704 if (exp_type)
1705 return false;
1706 else
1707 return true;
1712 /* Return true iff TYPE is stdarg va_list type. */
1714 static inline bool
1715 is_va_list_type (tree type)
1717 return TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (va_list_type_node);
1720 /* Print message to dump file why a variable was rejected. */
1722 static void
1723 reject (tree var, const char *msg)
1725 if (dump_file && (dump_flags & TDF_DETAILS))
1727 fprintf (dump_file, "Rejected (%d): %s: ", DECL_UID (var), msg);
1728 print_generic_expr (dump_file, var, 0);
1729 fprintf (dump_file, "\n");
1733 /* Return true if VAR is a candidate for SRA. */
1735 static bool
1736 maybe_add_sra_candidate (tree var)
1738 tree type = TREE_TYPE (var);
1739 const char *msg;
1740 tree_node **slot;
1742 if (!AGGREGATE_TYPE_P (type))
1744 reject (var, "not aggregate");
1745 return false;
1747 if (needs_to_live_in_memory (var))
1749 reject (var, "needs to live in memory");
1750 return false;
1752 if (TREE_THIS_VOLATILE (var))
1754 reject (var, "is volatile");
1755 return false;
1757 if (!COMPLETE_TYPE_P (type))
1759 reject (var, "has incomplete type");
1760 return false;
1762 if (!tree_fits_uhwi_p (TYPE_SIZE (type)))
1764 reject (var, "type size not fixed");
1765 return false;
1767 if (tree_to_uhwi (TYPE_SIZE (type)) == 0)
1769 reject (var, "type size is zero");
1770 return false;
1772 if (type_internals_preclude_sra_p (type, &msg))
1774 reject (var, msg);
1775 return false;
1777 if (/* Fix for PR 41089. tree-stdarg.c needs to have va_lists intact but
1778 we also want to schedule it rather late. Thus we ignore it in
1779 the early pass. */
1780 (sra_mode == SRA_MODE_EARLY_INTRA
1781 && is_va_list_type (type)))
1783 reject (var, "is va_list");
1784 return false;
1787 bitmap_set_bit (candidate_bitmap, DECL_UID (var));
1788 slot = candidates.find_slot_with_hash (var, DECL_UID (var), INSERT);
1789 *slot = var;
1791 if (dump_file && (dump_flags & TDF_DETAILS))
1793 fprintf (dump_file, "Candidate (%d): ", DECL_UID (var));
1794 print_generic_expr (dump_file, var, 0);
1795 fprintf (dump_file, "\n");
1798 return true;
1801 /* The very first phase of intraprocedural SRA. It marks in candidate_bitmap
1802 those with type which is suitable for scalarization. */
1804 static bool
1805 find_var_candidates (void)
1807 tree var, parm;
1808 unsigned int i;
1809 bool ret = false;
1811 for (parm = DECL_ARGUMENTS (current_function_decl);
1812 parm;
1813 parm = DECL_CHAIN (parm))
1814 ret |= maybe_add_sra_candidate (parm);
1816 FOR_EACH_LOCAL_DECL (cfun, i, var)
1818 if (TREE_CODE (var) != VAR_DECL)
1819 continue;
1821 ret |= maybe_add_sra_candidate (var);
1824 return ret;
1827 /* Sort all accesses for the given variable, check for partial overlaps and
1828 return NULL if there are any. If there are none, pick a representative for
1829 each combination of offset and size and create a linked list out of them.
1830 Return the pointer to the first representative and make sure it is the first
1831 one in the vector of accesses. */
1833 static struct access *
1834 sort_and_splice_var_accesses (tree var)
1836 int i, j, access_count;
1837 struct access *res, **prev_acc_ptr = &res;
1838 vec<access_p> *access_vec;
1839 bool first = true;
1840 HOST_WIDE_INT low = -1, high = 0;
1842 access_vec = get_base_access_vector (var);
1843 if (!access_vec)
1844 return NULL;
1845 access_count = access_vec->length ();
1847 /* Sort by <OFFSET, SIZE>. */
1848 access_vec->qsort (compare_access_positions);
1850 i = 0;
1851 while (i < access_count)
1853 struct access *access = (*access_vec)[i];
1854 bool grp_write = access->write;
1855 bool grp_read = !access->write;
1856 bool grp_scalar_write = access->write
1857 && is_gimple_reg_type (access->type);
1858 bool grp_scalar_read = !access->write
1859 && is_gimple_reg_type (access->type);
1860 bool grp_assignment_read = access->grp_assignment_read;
1861 bool grp_assignment_write = access->grp_assignment_write;
1862 bool multiple_scalar_reads = false;
1863 bool total_scalarization = access->grp_total_scalarization;
1864 bool grp_partial_lhs = access->grp_partial_lhs;
1865 bool first_scalar = is_gimple_reg_type (access->type);
1866 bool unscalarizable_region = access->grp_unscalarizable_region;
1868 if (first || access->offset >= high)
1870 first = false;
1871 low = access->offset;
1872 high = access->offset + access->size;
1874 else if (access->offset > low && access->offset + access->size > high)
1875 return NULL;
1876 else
1877 gcc_assert (access->offset >= low
1878 && access->offset + access->size <= high);
1880 j = i + 1;
1881 while (j < access_count)
1883 struct access *ac2 = (*access_vec)[j];
1884 if (ac2->offset != access->offset || ac2->size != access->size)
1885 break;
1886 if (ac2->write)
1888 grp_write = true;
1889 grp_scalar_write = (grp_scalar_write
1890 || is_gimple_reg_type (ac2->type));
1892 else
1894 grp_read = true;
1895 if (is_gimple_reg_type (ac2->type))
1897 if (grp_scalar_read)
1898 multiple_scalar_reads = true;
1899 else
1900 grp_scalar_read = true;
1903 grp_assignment_read |= ac2->grp_assignment_read;
1904 grp_assignment_write |= ac2->grp_assignment_write;
1905 grp_partial_lhs |= ac2->grp_partial_lhs;
1906 unscalarizable_region |= ac2->grp_unscalarizable_region;
1907 total_scalarization |= ac2->grp_total_scalarization;
1908 relink_to_new_repr (access, ac2);
1910 /* If there are both aggregate-type and scalar-type accesses with
1911 this combination of size and offset, the comparison function
1912 should have put the scalars first. */
1913 gcc_assert (first_scalar || !is_gimple_reg_type (ac2->type));
1914 ac2->group_representative = access;
1915 j++;
1918 i = j;
1920 access->group_representative = access;
1921 access->grp_write = grp_write;
1922 access->grp_read = grp_read;
1923 access->grp_scalar_read = grp_scalar_read;
1924 access->grp_scalar_write = grp_scalar_write;
1925 access->grp_assignment_read = grp_assignment_read;
1926 access->grp_assignment_write = grp_assignment_write;
1927 access->grp_hint = multiple_scalar_reads || total_scalarization;
1928 access->grp_total_scalarization = total_scalarization;
1929 access->grp_partial_lhs = grp_partial_lhs;
1930 access->grp_unscalarizable_region = unscalarizable_region;
1931 if (access->first_link)
1932 add_access_to_work_queue (access);
1934 *prev_acc_ptr = access;
1935 prev_acc_ptr = &access->next_grp;
1938 gcc_assert (res == (*access_vec)[0]);
1939 return res;
1942 /* Create a variable for the given ACCESS which determines the type, name and a
1943 few other properties. Return the variable declaration and store it also to
1944 ACCESS->replacement. */
1946 static tree
1947 create_access_replacement (struct access *access)
1949 tree repl;
1951 if (access->grp_to_be_debug_replaced)
1953 repl = create_tmp_var_raw (access->type, NULL);
1954 DECL_CONTEXT (repl) = current_function_decl;
1956 else
1957 repl = create_tmp_var (access->type, "SR");
1958 if (TREE_CODE (access->type) == COMPLEX_TYPE
1959 || TREE_CODE (access->type) == VECTOR_TYPE)
1961 if (!access->grp_partial_lhs)
1962 DECL_GIMPLE_REG_P (repl) = 1;
1964 else if (access->grp_partial_lhs
1965 && is_gimple_reg_type (access->type))
1966 TREE_ADDRESSABLE (repl) = 1;
1968 DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base);
1969 DECL_ARTIFICIAL (repl) = 1;
1970 DECL_IGNORED_P (repl) = DECL_IGNORED_P (access->base);
1972 if (DECL_NAME (access->base)
1973 && !DECL_IGNORED_P (access->base)
1974 && !DECL_ARTIFICIAL (access->base))
1976 char *pretty_name = make_fancy_name (access->expr);
1977 tree debug_expr = unshare_expr_without_location (access->expr), d;
1978 bool fail = false;
1980 DECL_NAME (repl) = get_identifier (pretty_name);
1981 obstack_free (&name_obstack, pretty_name);
1983 /* Get rid of any SSA_NAMEs embedded in debug_expr,
1984 as DECL_DEBUG_EXPR isn't considered when looking for still
1985 used SSA_NAMEs and thus they could be freed. All debug info
1986 generation cares is whether something is constant or variable
1987 and that get_ref_base_and_extent works properly on the
1988 expression. It cannot handle accesses at a non-constant offset
1989 though, so just give up in those cases. */
1990 for (d = debug_expr;
1991 !fail && (handled_component_p (d) || TREE_CODE (d) == MEM_REF);
1992 d = TREE_OPERAND (d, 0))
1993 switch (TREE_CODE (d))
1995 case ARRAY_REF:
1996 case ARRAY_RANGE_REF:
1997 if (TREE_OPERAND (d, 1)
1998 && TREE_CODE (TREE_OPERAND (d, 1)) != INTEGER_CST)
1999 fail = true;
2000 if (TREE_OPERAND (d, 3)
2001 && TREE_CODE (TREE_OPERAND (d, 3)) != INTEGER_CST)
2002 fail = true;
2003 /* FALLTHRU */
2004 case COMPONENT_REF:
2005 if (TREE_OPERAND (d, 2)
2006 && TREE_CODE (TREE_OPERAND (d, 2)) != INTEGER_CST)
2007 fail = true;
2008 break;
2009 case MEM_REF:
2010 if (TREE_CODE (TREE_OPERAND (d, 0)) != ADDR_EXPR)
2011 fail = true;
2012 else
2013 d = TREE_OPERAND (d, 0);
2014 break;
2015 default:
2016 break;
2018 if (!fail)
2020 SET_DECL_DEBUG_EXPR (repl, debug_expr);
2021 DECL_HAS_DEBUG_EXPR_P (repl) = 1;
2023 if (access->grp_no_warning)
2024 TREE_NO_WARNING (repl) = 1;
2025 else
2026 TREE_NO_WARNING (repl) = TREE_NO_WARNING (access->base);
2028 else
2029 TREE_NO_WARNING (repl) = 1;
2031 if (dump_file)
2033 if (access->grp_to_be_debug_replaced)
2035 fprintf (dump_file, "Created a debug-only replacement for ");
2036 print_generic_expr (dump_file, access->base, 0);
2037 fprintf (dump_file, " offset: %u, size: %u\n",
2038 (unsigned) access->offset, (unsigned) access->size);
2040 else
2042 fprintf (dump_file, "Created a replacement for ");
2043 print_generic_expr (dump_file, access->base, 0);
2044 fprintf (dump_file, " offset: %u, size: %u: ",
2045 (unsigned) access->offset, (unsigned) access->size);
2046 print_generic_expr (dump_file, repl, 0);
2047 fprintf (dump_file, "\n");
2050 sra_stats.replacements++;
2052 return repl;
2055 /* Return ACCESS scalar replacement, create it if it does not exist yet. */
2057 static inline tree
2058 get_access_replacement (struct access *access)
2060 gcc_checking_assert (access->replacement_decl);
2061 return access->replacement_decl;
2065 /* Build a subtree of accesses rooted in *ACCESS, and move the pointer in the
2066 linked list along the way. Stop when *ACCESS is NULL or the access pointed
2067 to it is not "within" the root. Return false iff some accesses partially
2068 overlap. */
2070 static bool
2071 build_access_subtree (struct access **access)
2073 struct access *root = *access, *last_child = NULL;
2074 HOST_WIDE_INT limit = root->offset + root->size;
2076 *access = (*access)->next_grp;
2077 while (*access && (*access)->offset + (*access)->size <= limit)
2079 if (!last_child)
2080 root->first_child = *access;
2081 else
2082 last_child->next_sibling = *access;
2083 last_child = *access;
2085 if (!build_access_subtree (access))
2086 return false;
2089 if (*access && (*access)->offset < limit)
2090 return false;
2092 return true;
2095 /* Build a tree of access representatives, ACCESS is the pointer to the first
2096 one, others are linked in a list by the next_grp field. Return false iff
2097 some accesses partially overlap. */
2099 static bool
2100 build_access_trees (struct access *access)
2102 while (access)
2104 struct access *root = access;
2106 if (!build_access_subtree (&access))
2107 return false;
2108 root->next_grp = access;
2110 return true;
2113 /* Return true if expr contains some ARRAY_REFs into a variable bounded
2114 array. */
2116 static bool
2117 expr_with_var_bounded_array_refs_p (tree expr)
2119 while (handled_component_p (expr))
2121 if (TREE_CODE (expr) == ARRAY_REF
2122 && !tree_fits_shwi_p (array_ref_low_bound (expr)))
2123 return true;
2124 expr = TREE_OPERAND (expr, 0);
2126 return false;
2129 /* Analyze the subtree of accesses rooted in ROOT, scheduling replacements when
2130 both seeming beneficial and when ALLOW_REPLACEMENTS allows it. Also set all
2131 sorts of access flags appropriately along the way, notably always set
2132 grp_read and grp_assign_read according to MARK_READ and grp_write when
2133 MARK_WRITE is true.
2135 Creating a replacement for a scalar access is considered beneficial if its
2136 grp_hint is set (this means we are either attempting total scalarization or
2137 there is more than one direct read access) or according to the following
2138 table:
2140 Access written to through a scalar type (once or more times)
2142 | Written to in an assignment statement
2144 | | Access read as scalar _once_
2145 | | |
2146 | | | Read in an assignment statement
2147 | | | |
2148 | | | | Scalarize Comment
2149 -----------------------------------------------------------------------------
2150 0 0 0 0 No access for the scalar
2151 0 0 0 1 No access for the scalar
2152 0 0 1 0 No Single read - won't help
2153 0 0 1 1 No The same case
2154 0 1 0 0 No access for the scalar
2155 0 1 0 1 No access for the scalar
2156 0 1 1 0 Yes s = *g; return s.i;
2157 0 1 1 1 Yes The same case as above
2158 1 0 0 0 No Won't help
2159 1 0 0 1 Yes s.i = 1; *g = s;
2160 1 0 1 0 Yes s.i = 5; g = s.i;
2161 1 0 1 1 Yes The same case as above
2162 1 1 0 0 No Won't help.
2163 1 1 0 1 Yes s.i = 1; *g = s;
2164 1 1 1 0 Yes s = *g; return s.i;
2165 1 1 1 1 Yes Any of the above yeses */
2167 static bool
2168 analyze_access_subtree (struct access *root, struct access *parent,
2169 bool allow_replacements)
2171 struct access *child;
2172 HOST_WIDE_INT limit = root->offset + root->size;
2173 HOST_WIDE_INT covered_to = root->offset;
2174 bool scalar = is_gimple_reg_type (root->type);
2175 bool hole = false, sth_created = false;
2177 if (parent)
2179 if (parent->grp_read)
2180 root->grp_read = 1;
2181 if (parent->grp_assignment_read)
2182 root->grp_assignment_read = 1;
2183 if (parent->grp_write)
2184 root->grp_write = 1;
2185 if (parent->grp_assignment_write)
2186 root->grp_assignment_write = 1;
2187 if (parent->grp_total_scalarization)
2188 root->grp_total_scalarization = 1;
2191 if (root->grp_unscalarizable_region)
2192 allow_replacements = false;
2194 if (allow_replacements && expr_with_var_bounded_array_refs_p (root->expr))
2195 allow_replacements = false;
2197 for (child = root->first_child; child; child = child->next_sibling)
2199 hole |= covered_to < child->offset;
2200 sth_created |= analyze_access_subtree (child, root,
2201 allow_replacements && !scalar);
2203 root->grp_unscalarized_data |= child->grp_unscalarized_data;
2204 root->grp_total_scalarization &= child->grp_total_scalarization;
2205 if (child->grp_covered)
2206 covered_to += child->size;
2207 else
2208 hole = true;
2211 if (allow_replacements && scalar && !root->first_child
2212 && (root->grp_hint
2213 || ((root->grp_scalar_read || root->grp_assignment_read)
2214 && (root->grp_scalar_write || root->grp_assignment_write))))
2216 /* Always create access replacements that cover the whole access.
2217 For integral types this means the precision has to match.
2218 Avoid assumptions based on the integral type kind, too. */
2219 if (INTEGRAL_TYPE_P (root->type)
2220 && (TREE_CODE (root->type) != INTEGER_TYPE
2221 || TYPE_PRECISION (root->type) != root->size)
2222 /* But leave bitfield accesses alone. */
2223 && (TREE_CODE (root->expr) != COMPONENT_REF
2224 || !DECL_BIT_FIELD (TREE_OPERAND (root->expr, 1))))
2226 tree rt = root->type;
2227 gcc_assert ((root->offset % BITS_PER_UNIT) == 0
2228 && (root->size % BITS_PER_UNIT) == 0);
2229 root->type = build_nonstandard_integer_type (root->size,
2230 TYPE_UNSIGNED (rt));
2231 root->expr = build_ref_for_offset (UNKNOWN_LOCATION,
2232 root->base, root->offset,
2233 root->type, NULL, false);
2235 if (dump_file && (dump_flags & TDF_DETAILS))
2237 fprintf (dump_file, "Changing the type of a replacement for ");
2238 print_generic_expr (dump_file, root->base, 0);
2239 fprintf (dump_file, " offset: %u, size: %u ",
2240 (unsigned) root->offset, (unsigned) root->size);
2241 fprintf (dump_file, " to an integer.\n");
2245 root->grp_to_be_replaced = 1;
2246 root->replacement_decl = create_access_replacement (root);
2247 sth_created = true;
2248 hole = false;
2250 else
2252 if (allow_replacements
2253 && scalar && !root->first_child
2254 && (root->grp_scalar_write || root->grp_assignment_write)
2255 && !bitmap_bit_p (cannot_scalarize_away_bitmap,
2256 DECL_UID (root->base)))
2258 gcc_checking_assert (!root->grp_scalar_read
2259 && !root->grp_assignment_read);
2260 sth_created = true;
2261 if (MAY_HAVE_DEBUG_STMTS)
2263 root->grp_to_be_debug_replaced = 1;
2264 root->replacement_decl = create_access_replacement (root);
2268 if (covered_to < limit)
2269 hole = true;
2270 if (scalar)
2271 root->grp_total_scalarization = 0;
2274 if (!hole || root->grp_total_scalarization)
2275 root->grp_covered = 1;
2276 else if (root->grp_write || TREE_CODE (root->base) == PARM_DECL)
2277 root->grp_unscalarized_data = 1; /* not covered and written to */
2278 return sth_created;
2281 /* Analyze all access trees linked by next_grp by the means of
2282 analyze_access_subtree. */
2283 static bool
2284 analyze_access_trees (struct access *access)
2286 bool ret = false;
2288 while (access)
2290 if (analyze_access_subtree (access, NULL, true))
2291 ret = true;
2292 access = access->next_grp;
2295 return ret;
2298 /* Return true iff a potential new child of LACC at offset OFFSET and with size
2299 SIZE would conflict with an already existing one. If exactly such a child
2300 already exists in LACC, store a pointer to it in EXACT_MATCH. */
2302 static bool
2303 child_would_conflict_in_lacc (struct access *lacc, HOST_WIDE_INT norm_offset,
2304 HOST_WIDE_INT size, struct access **exact_match)
2306 struct access *child;
2308 for (child = lacc->first_child; child; child = child->next_sibling)
2310 if (child->offset == norm_offset && child->size == size)
2312 *exact_match = child;
2313 return true;
2316 if (child->offset < norm_offset + size
2317 && child->offset + child->size > norm_offset)
2318 return true;
2321 return false;
2324 /* Create a new child access of PARENT, with all properties just like MODEL
2325 except for its offset and with its grp_write false and grp_read true.
2326 Return the new access or NULL if it cannot be created. Note that this access
2327 is created long after all splicing and sorting, it's not located in any
2328 access vector and is automatically a representative of its group. */
2330 static struct access *
2331 create_artificial_child_access (struct access *parent, struct access *model,
2332 HOST_WIDE_INT new_offset)
2334 struct access *access;
2335 struct access **child;
2336 tree expr = parent->base;
2338 gcc_assert (!model->grp_unscalarizable_region);
2340 access = (struct access *) pool_alloc (access_pool);
2341 memset (access, 0, sizeof (struct access));
2342 if (!build_user_friendly_ref_for_offset (&expr, TREE_TYPE (expr), new_offset,
2343 model->type))
2345 access->grp_no_warning = true;
2346 expr = build_ref_for_model (EXPR_LOCATION (parent->base), parent->base,
2347 new_offset, model, NULL, false);
2350 access->base = parent->base;
2351 access->expr = expr;
2352 access->offset = new_offset;
2353 access->size = model->size;
2354 access->type = model->type;
2355 access->grp_write = true;
2356 access->grp_read = false;
2358 child = &parent->first_child;
2359 while (*child && (*child)->offset < new_offset)
2360 child = &(*child)->next_sibling;
2362 access->next_sibling = *child;
2363 *child = access;
2365 return access;
2369 /* Propagate all subaccesses of RACC across an assignment link to LACC. Return
2370 true if any new subaccess was created. Additionally, if RACC is a scalar
2371 access but LACC is not, change the type of the latter, if possible. */
2373 static bool
2374 propagate_subaccesses_across_link (struct access *lacc, struct access *racc)
2376 struct access *rchild;
2377 HOST_WIDE_INT norm_delta = lacc->offset - racc->offset;
2378 bool ret = false;
2380 if (is_gimple_reg_type (lacc->type)
2381 || lacc->grp_unscalarizable_region
2382 || racc->grp_unscalarizable_region)
2383 return false;
2385 if (is_gimple_reg_type (racc->type))
2387 if (!lacc->first_child && !racc->first_child)
2389 tree t = lacc->base;
2391 lacc->type = racc->type;
2392 if (build_user_friendly_ref_for_offset (&t, TREE_TYPE (t),
2393 lacc->offset, racc->type))
2394 lacc->expr = t;
2395 else
2397 lacc->expr = build_ref_for_model (EXPR_LOCATION (lacc->base),
2398 lacc->base, lacc->offset,
2399 racc, NULL, false);
2400 lacc->grp_no_warning = true;
2403 return false;
2406 for (rchild = racc->first_child; rchild; rchild = rchild->next_sibling)
2408 struct access *new_acc = NULL;
2409 HOST_WIDE_INT norm_offset = rchild->offset + norm_delta;
2411 if (rchild->grp_unscalarizable_region)
2412 continue;
2414 if (child_would_conflict_in_lacc (lacc, norm_offset, rchild->size,
2415 &new_acc))
2417 if (new_acc)
2419 rchild->grp_hint = 1;
2420 new_acc->grp_hint |= new_acc->grp_read;
2421 if (rchild->first_child)
2422 ret |= propagate_subaccesses_across_link (new_acc, rchild);
2424 continue;
2427 rchild->grp_hint = 1;
2428 new_acc = create_artificial_child_access (lacc, rchild, norm_offset);
2429 if (new_acc)
2431 ret = true;
2432 if (racc->first_child)
2433 propagate_subaccesses_across_link (new_acc, rchild);
2437 return ret;
2440 /* Propagate all subaccesses across assignment links. */
2442 static void
2443 propagate_all_subaccesses (void)
2445 while (work_queue_head)
2447 struct access *racc = pop_access_from_work_queue ();
2448 struct assign_link *link;
2450 gcc_assert (racc->first_link);
2452 for (link = racc->first_link; link; link = link->next)
2454 struct access *lacc = link->lacc;
2456 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
2457 continue;
2458 lacc = lacc->group_representative;
2459 if (propagate_subaccesses_across_link (lacc, racc)
2460 && lacc->first_link)
2461 add_access_to_work_queue (lacc);
2466 /* Go through all accesses collected throughout the (intraprocedural) analysis
2467 stage, exclude overlapping ones, identify representatives and build trees
2468 out of them, making decisions about scalarization on the way. Return true
2469 iff there are any to-be-scalarized variables after this stage. */
2471 static bool
2472 analyze_all_variable_accesses (void)
2474 int res = 0;
2475 bitmap tmp = BITMAP_ALLOC (NULL);
2476 bitmap_iterator bi;
2477 unsigned i, max_total_scalarization_size;
2479 max_total_scalarization_size = UNITS_PER_WORD * BITS_PER_UNIT
2480 * MOVE_RATIO (optimize_function_for_speed_p (cfun));
2482 EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
2483 if (bitmap_bit_p (should_scalarize_away_bitmap, i)
2484 && !bitmap_bit_p (cannot_scalarize_away_bitmap, i))
2486 tree var = candidate (i);
2488 if (TREE_CODE (var) == VAR_DECL
2489 && type_consists_of_records_p (TREE_TYPE (var)))
2491 if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (var)))
2492 <= max_total_scalarization_size)
2494 completely_scalarize_var (var);
2495 if (dump_file && (dump_flags & TDF_DETAILS))
2497 fprintf (dump_file, "Will attempt to totally scalarize ");
2498 print_generic_expr (dump_file, var, 0);
2499 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
2502 else if (dump_file && (dump_flags & TDF_DETAILS))
2504 fprintf (dump_file, "Too big to totally scalarize: ");
2505 print_generic_expr (dump_file, var, 0);
2506 fprintf (dump_file, " (UID: %u)\n", DECL_UID (var));
2511 bitmap_copy (tmp, candidate_bitmap);
2512 EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
2514 tree var = candidate (i);
2515 struct access *access;
2517 access = sort_and_splice_var_accesses (var);
2518 if (!access || !build_access_trees (access))
2519 disqualify_candidate (var,
2520 "No or inhibitingly overlapping accesses.");
2523 propagate_all_subaccesses ();
2525 bitmap_copy (tmp, candidate_bitmap);
2526 EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
2528 tree var = candidate (i);
2529 struct access *access = get_first_repr_for_decl (var);
2531 if (analyze_access_trees (access))
2533 res++;
2534 if (dump_file && (dump_flags & TDF_DETAILS))
2536 fprintf (dump_file, "\nAccess trees for ");
2537 print_generic_expr (dump_file, var, 0);
2538 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
2539 dump_access_tree (dump_file, access);
2540 fprintf (dump_file, "\n");
2543 else
2544 disqualify_candidate (var, "No scalar replacements to be created.");
2547 BITMAP_FREE (tmp);
2549 if (res)
2551 statistics_counter_event (cfun, "Scalarized aggregates", res);
2552 return true;
2554 else
2555 return false;
2558 /* Generate statements copying scalar replacements of accesses within a subtree
2559 into or out of AGG. ACCESS, all its children, siblings and their children
2560 are to be processed. AGG is an aggregate type expression (can be a
2561 declaration but does not have to be, it can for example also be a mem_ref or
2562 a series of handled components). TOP_OFFSET is the offset of the processed
2563 subtree which has to be subtracted from offsets of individual accesses to
2564 get corresponding offsets for AGG. If CHUNK_SIZE is non-null, copy only
2565 replacements in the interval <start_offset, start_offset + chunk_size>,
2566 otherwise copy all. GSI is a statement iterator used to place the new
2567 statements. WRITE should be true when the statements should write from AGG
2568 to the replacement and false if vice versa. if INSERT_AFTER is true, new
2569 statements will be added after the current statement in GSI, they will be
2570 added before the statement otherwise. */
2572 static void
2573 generate_subtree_copies (struct access *access, tree agg,
2574 HOST_WIDE_INT top_offset,
2575 HOST_WIDE_INT start_offset, HOST_WIDE_INT chunk_size,
2576 gimple_stmt_iterator *gsi, bool write,
2577 bool insert_after, location_t loc)
2581 if (chunk_size && access->offset >= start_offset + chunk_size)
2582 return;
2584 if (access->grp_to_be_replaced
2585 && (chunk_size == 0
2586 || access->offset + access->size > start_offset))
2588 tree expr, repl = get_access_replacement (access);
2589 gimple stmt;
2591 expr = build_ref_for_model (loc, agg, access->offset - top_offset,
2592 access, gsi, insert_after);
2594 if (write)
2596 if (access->grp_partial_lhs)
2597 expr = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
2598 !insert_after,
2599 insert_after ? GSI_NEW_STMT
2600 : GSI_SAME_STMT);
2601 stmt = gimple_build_assign (repl, expr);
2603 else
2605 TREE_NO_WARNING (repl) = 1;
2606 if (access->grp_partial_lhs)
2607 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
2608 !insert_after,
2609 insert_after ? GSI_NEW_STMT
2610 : GSI_SAME_STMT);
2611 stmt = gimple_build_assign (expr, repl);
2613 gimple_set_location (stmt, loc);
2615 if (insert_after)
2616 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2617 else
2618 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2619 update_stmt (stmt);
2620 sra_stats.subtree_copies++;
2622 else if (write
2623 && access->grp_to_be_debug_replaced
2624 && (chunk_size == 0
2625 || access->offset + access->size > start_offset))
2627 gimple ds;
2628 tree drhs = build_debug_ref_for_model (loc, agg,
2629 access->offset - top_offset,
2630 access);
2631 ds = gimple_build_debug_bind (get_access_replacement (access),
2632 drhs, gsi_stmt (*gsi));
2633 if (insert_after)
2634 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
2635 else
2636 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
2639 if (access->first_child)
2640 generate_subtree_copies (access->first_child, agg, top_offset,
2641 start_offset, chunk_size, gsi,
2642 write, insert_after, loc);
2644 access = access->next_sibling;
2646 while (access);
2649 /* Assign zero to all scalar replacements in an access subtree. ACCESS is the
2650 the root of the subtree to be processed. GSI is the statement iterator used
2651 for inserting statements which are added after the current statement if
2652 INSERT_AFTER is true or before it otherwise. */
2654 static void
2655 init_subtree_with_zero (struct access *access, gimple_stmt_iterator *gsi,
2656 bool insert_after, location_t loc)
2659 struct access *child;
2661 if (access->grp_to_be_replaced)
2663 gimple stmt;
2665 stmt = gimple_build_assign (get_access_replacement (access),
2666 build_zero_cst (access->type));
2667 if (insert_after)
2668 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2669 else
2670 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2671 update_stmt (stmt);
2672 gimple_set_location (stmt, loc);
2674 else if (access->grp_to_be_debug_replaced)
2676 gimple ds = gimple_build_debug_bind (get_access_replacement (access),
2677 build_zero_cst (access->type),
2678 gsi_stmt (*gsi));
2679 if (insert_after)
2680 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
2681 else
2682 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
2685 for (child = access->first_child; child; child = child->next_sibling)
2686 init_subtree_with_zero (child, gsi, insert_after, loc);
2689 /* Search for an access representative for the given expression EXPR and
2690 return it or NULL if it cannot be found. */
2692 static struct access *
2693 get_access_for_expr (tree expr)
2695 HOST_WIDE_INT offset, size, max_size;
2696 tree base;
2698 /* FIXME: This should not be necessary but Ada produces V_C_Es with a type of
2699 a different size than the size of its argument and we need the latter
2700 one. */
2701 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
2702 expr = TREE_OPERAND (expr, 0);
2704 base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
2705 if (max_size == -1 || !DECL_P (base))
2706 return NULL;
2708 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
2709 return NULL;
2711 return get_var_base_offset_size_access (base, offset, max_size);
2714 /* Replace the expression EXPR with a scalar replacement if there is one and
2715 generate other statements to do type conversion or subtree copying if
2716 necessary. GSI is used to place newly created statements, WRITE is true if
2717 the expression is being written to (it is on a LHS of a statement or output
2718 in an assembly statement). */
2720 static bool
2721 sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
2723 location_t loc;
2724 struct access *access;
2725 tree type, bfr;
2727 if (TREE_CODE (*expr) == BIT_FIELD_REF)
2729 bfr = *expr;
2730 expr = &TREE_OPERAND (*expr, 0);
2732 else
2733 bfr = NULL_TREE;
2735 if (TREE_CODE (*expr) == REALPART_EXPR || TREE_CODE (*expr) == IMAGPART_EXPR)
2736 expr = &TREE_OPERAND (*expr, 0);
2737 access = get_access_for_expr (*expr);
2738 if (!access)
2739 return false;
2740 type = TREE_TYPE (*expr);
2742 loc = gimple_location (gsi_stmt (*gsi));
2743 if (access->grp_to_be_replaced)
2745 tree repl = get_access_replacement (access);
2746 /* If we replace a non-register typed access simply use the original
2747 access expression to extract the scalar component afterwards.
2748 This happens if scalarizing a function return value or parameter
2749 like in gcc.c-torture/execute/20041124-1.c, 20050316-1.c and
2750 gcc.c-torture/compile/20011217-1.c.
2752 We also want to use this when accessing a complex or vector which can
2753 be accessed as a different type too, potentially creating a need for
2754 type conversion (see PR42196) and when scalarized unions are involved
2755 in assembler statements (see PR42398). */
2756 if (!useless_type_conversion_p (type, access->type))
2758 tree ref;
2760 ref = build_ref_for_model (loc, access->base, access->offset, access,
2761 NULL, false);
2763 if (write)
2765 gimple stmt;
2767 if (access->grp_partial_lhs)
2768 ref = force_gimple_operand_gsi (gsi, ref, true, NULL_TREE,
2769 false, GSI_NEW_STMT);
2770 stmt = gimple_build_assign (repl, ref);
2771 gimple_set_location (stmt, loc);
2772 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2774 else
2776 gimple stmt;
2778 if (access->grp_partial_lhs)
2779 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
2780 true, GSI_SAME_STMT);
2781 stmt = gimple_build_assign (ref, repl);
2782 gimple_set_location (stmt, loc);
2783 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2786 else
2787 *expr = repl;
2788 sra_stats.exprs++;
2790 else if (write && access->grp_to_be_debug_replaced)
2792 gimple ds = gimple_build_debug_bind (get_access_replacement (access),
2793 NULL_TREE,
2794 gsi_stmt (*gsi));
2795 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
2798 if (access->first_child)
2800 HOST_WIDE_INT start_offset, chunk_size;
2801 if (bfr
2802 && tree_fits_uhwi_p (TREE_OPERAND (bfr, 1))
2803 && tree_fits_uhwi_p (TREE_OPERAND (bfr, 2)))
2805 chunk_size = tree_to_uhwi (TREE_OPERAND (bfr, 1));
2806 start_offset = access->offset
2807 + tree_to_uhwi (TREE_OPERAND (bfr, 2));
2809 else
2810 start_offset = chunk_size = 0;
2812 generate_subtree_copies (access->first_child, access->base, 0,
2813 start_offset, chunk_size, gsi, write, write,
2814 loc);
2816 return true;
2819 /* Where scalar replacements of the RHS have been written to when a replacement
2820 of a LHS of an assigments cannot be direclty loaded from a replacement of
2821 the RHS. */
2822 enum unscalarized_data_handling { SRA_UDH_NONE, /* Nothing done so far. */
2823 SRA_UDH_RIGHT, /* Data flushed to the RHS. */
2824 SRA_UDH_LEFT }; /* Data flushed to the LHS. */
2826 /* Store all replacements in the access tree rooted in TOP_RACC either to their
2827 base aggregate if there are unscalarized data or directly to LHS of the
2828 statement that is pointed to by GSI otherwise. */
2830 static enum unscalarized_data_handling
2831 handle_unscalarized_data_in_subtree (struct access *top_racc,
2832 gimple_stmt_iterator *gsi)
2834 if (top_racc->grp_unscalarized_data)
2836 generate_subtree_copies (top_racc->first_child, top_racc->base, 0, 0, 0,
2837 gsi, false, false,
2838 gimple_location (gsi_stmt (*gsi)));
2839 return SRA_UDH_RIGHT;
2841 else
2843 tree lhs = gimple_assign_lhs (gsi_stmt (*gsi));
2844 generate_subtree_copies (top_racc->first_child, lhs, top_racc->offset,
2845 0, 0, gsi, false, false,
2846 gimple_location (gsi_stmt (*gsi)));
2847 return SRA_UDH_LEFT;
2852 /* Try to generate statements to load all sub-replacements in an access subtree
2853 formed by children of LACC from scalar replacements in the TOP_RACC subtree.
2854 If that is not possible, refresh the TOP_RACC base aggregate and load the
2855 accesses from it. LEFT_OFFSET is the offset of the left whole subtree being
2856 copied. NEW_GSI is stmt iterator used for statement insertions after the
2857 original assignment, OLD_GSI is used to insert statements before the
2858 assignment. *REFRESHED keeps the information whether we have needed to
2859 refresh replacements of the LHS and from which side of the assignments this
2860 takes place. */
2862 static void
2863 load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc,
2864 HOST_WIDE_INT left_offset,
2865 gimple_stmt_iterator *old_gsi,
2866 gimple_stmt_iterator *new_gsi,
2867 enum unscalarized_data_handling *refreshed)
2869 location_t loc = gimple_location (gsi_stmt (*old_gsi));
2870 for (lacc = lacc->first_child; lacc; lacc = lacc->next_sibling)
2872 HOST_WIDE_INT offset = lacc->offset - left_offset + top_racc->offset;
2874 if (lacc->grp_to_be_replaced)
2876 struct access *racc;
2877 gimple stmt;
2878 tree rhs;
2880 racc = find_access_in_subtree (top_racc, offset, lacc->size);
2881 if (racc && racc->grp_to_be_replaced)
2883 rhs = get_access_replacement (racc);
2884 if (!useless_type_conversion_p (lacc->type, racc->type))
2885 rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, lacc->type, rhs);
2887 if (racc->grp_partial_lhs && lacc->grp_partial_lhs)
2888 rhs = force_gimple_operand_gsi (old_gsi, rhs, true, NULL_TREE,
2889 true, GSI_SAME_STMT);
2891 else
2893 /* No suitable access on the right hand side, need to load from
2894 the aggregate. See if we have to update it first... */
2895 if (*refreshed == SRA_UDH_NONE)
2896 *refreshed = handle_unscalarized_data_in_subtree (top_racc,
2897 old_gsi);
2899 if (*refreshed == SRA_UDH_LEFT)
2900 rhs = build_ref_for_model (loc, lacc->base, lacc->offset, lacc,
2901 new_gsi, true);
2902 else
2903 rhs = build_ref_for_model (loc, top_racc->base, offset, lacc,
2904 new_gsi, true);
2905 if (lacc->grp_partial_lhs)
2906 rhs = force_gimple_operand_gsi (new_gsi, rhs, true, NULL_TREE,
2907 false, GSI_NEW_STMT);
2910 stmt = gimple_build_assign (get_access_replacement (lacc), rhs);
2911 gsi_insert_after (new_gsi, stmt, GSI_NEW_STMT);
2912 gimple_set_location (stmt, loc);
2913 update_stmt (stmt);
2914 sra_stats.subreplacements++;
2916 else
2918 if (*refreshed == SRA_UDH_NONE
2919 && lacc->grp_read && !lacc->grp_covered)
2920 *refreshed = handle_unscalarized_data_in_subtree (top_racc,
2921 old_gsi);
2922 if (lacc && lacc->grp_to_be_debug_replaced)
2924 gimple ds;
2925 tree drhs;
2926 struct access *racc = find_access_in_subtree (top_racc, offset,
2927 lacc->size);
2929 if (racc && racc->grp_to_be_replaced)
2931 if (racc->grp_write)
2932 drhs = get_access_replacement (racc);
2933 else
2934 drhs = NULL;
2936 else if (*refreshed == SRA_UDH_LEFT)
2937 drhs = build_debug_ref_for_model (loc, lacc->base, lacc->offset,
2938 lacc);
2939 else if (*refreshed == SRA_UDH_RIGHT)
2940 drhs = build_debug_ref_for_model (loc, top_racc->base, offset,
2941 lacc);
2942 else
2943 drhs = NULL_TREE;
2944 ds = gimple_build_debug_bind (get_access_replacement (lacc),
2945 drhs, gsi_stmt (*old_gsi));
2946 gsi_insert_after (new_gsi, ds, GSI_NEW_STMT);
2950 if (lacc->first_child)
2951 load_assign_lhs_subreplacements (lacc, top_racc, left_offset,
2952 old_gsi, new_gsi, refreshed);
2956 /* Result code for SRA assignment modification. */
2957 enum assignment_mod_result { SRA_AM_NONE, /* nothing done for the stmt */
2958 SRA_AM_MODIFIED, /* stmt changed but not
2959 removed */
2960 SRA_AM_REMOVED }; /* stmt eliminated */
2962 /* Modify assignments with a CONSTRUCTOR on their RHS. STMT contains a pointer
2963 to the assignment and GSI is the statement iterator pointing at it. Returns
2964 the same values as sra_modify_assign. */
2966 static enum assignment_mod_result
2967 sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
2969 tree lhs = gimple_assign_lhs (*stmt);
2970 struct access *acc;
2971 location_t loc;
2973 acc = get_access_for_expr (lhs);
2974 if (!acc)
2975 return SRA_AM_NONE;
2977 if (gimple_clobber_p (*stmt))
2979 /* Remove clobbers of fully scalarized variables, otherwise
2980 do nothing. */
2981 if (acc->grp_covered)
2983 unlink_stmt_vdef (*stmt);
2984 gsi_remove (gsi, true);
2985 release_defs (*stmt);
2986 return SRA_AM_REMOVED;
2988 else
2989 return SRA_AM_NONE;
2992 loc = gimple_location (*stmt);
2993 if (vec_safe_length (CONSTRUCTOR_ELTS (gimple_assign_rhs1 (*stmt))) > 0)
2995 /* I have never seen this code path trigger but if it can happen the
2996 following should handle it gracefully. */
2997 if (access_has_children_p (acc))
2998 generate_subtree_copies (acc->first_child, acc->base, 0, 0, 0, gsi,
2999 true, true, loc);
3000 return SRA_AM_MODIFIED;
3003 if (acc->grp_covered)
3005 init_subtree_with_zero (acc, gsi, false, loc);
3006 unlink_stmt_vdef (*stmt);
3007 gsi_remove (gsi, true);
3008 release_defs (*stmt);
3009 return SRA_AM_REMOVED;
3011 else
3013 init_subtree_with_zero (acc, gsi, true, loc);
3014 return SRA_AM_MODIFIED;
3018 /* Create and return a new suitable default definition SSA_NAME for RACC which
3019 is an access describing an uninitialized part of an aggregate that is being
3020 loaded. */
3022 static tree
3023 get_repl_default_def_ssa_name (struct access *racc)
3025 gcc_checking_assert (!racc->grp_to_be_replaced
3026 && !racc->grp_to_be_debug_replaced);
3027 if (!racc->replacement_decl)
3028 racc->replacement_decl = create_access_replacement (racc);
3029 return get_or_create_ssa_default_def (cfun, racc->replacement_decl);
3032 /* Return true if REF has an VIEW_CONVERT_EXPR or a COMPONENT_REF with a
3033 bit-field field declaration somewhere in it. */
3035 static inline bool
3036 contains_vce_or_bfcref_p (const_tree ref)
3038 while (handled_component_p (ref))
3040 if (TREE_CODE (ref) == VIEW_CONVERT_EXPR
3041 || (TREE_CODE (ref) == COMPONENT_REF
3042 && DECL_BIT_FIELD (TREE_OPERAND (ref, 1))))
3043 return true;
3044 ref = TREE_OPERAND (ref, 0);
3047 return false;
3050 /* Examine both sides of the assignment statement pointed to by STMT, replace
3051 them with a scalare replacement if there is one and generate copying of
3052 replacements if scalarized aggregates have been used in the assignment. GSI
3053 is used to hold generated statements for type conversions and subtree
3054 copying. */
3056 static enum assignment_mod_result
3057 sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi)
3059 struct access *lacc, *racc;
3060 tree lhs, rhs;
3061 bool modify_this_stmt = false;
3062 bool force_gimple_rhs = false;
3063 location_t loc;
3064 gimple_stmt_iterator orig_gsi = *gsi;
3066 if (!gimple_assign_single_p (*stmt))
3067 return SRA_AM_NONE;
3068 lhs = gimple_assign_lhs (*stmt);
3069 rhs = gimple_assign_rhs1 (*stmt);
3071 if (TREE_CODE (rhs) == CONSTRUCTOR)
3072 return sra_modify_constructor_assign (stmt, gsi);
3074 if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (lhs) == REALPART_EXPR
3075 || TREE_CODE (rhs) == IMAGPART_EXPR || TREE_CODE (lhs) == IMAGPART_EXPR
3076 || TREE_CODE (rhs) == BIT_FIELD_REF || TREE_CODE (lhs) == BIT_FIELD_REF)
3078 modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (*stmt),
3079 gsi, false);
3080 modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (*stmt),
3081 gsi, true);
3082 return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
3085 lacc = get_access_for_expr (lhs);
3086 racc = get_access_for_expr (rhs);
3087 if (!lacc && !racc)
3088 return SRA_AM_NONE;
3090 loc = gimple_location (*stmt);
3091 if (lacc && lacc->grp_to_be_replaced)
3093 lhs = get_access_replacement (lacc);
3094 gimple_assign_set_lhs (*stmt, lhs);
3095 modify_this_stmt = true;
3096 if (lacc->grp_partial_lhs)
3097 force_gimple_rhs = true;
3098 sra_stats.exprs++;
3101 if (racc && racc->grp_to_be_replaced)
3103 rhs = get_access_replacement (racc);
3104 modify_this_stmt = true;
3105 if (racc->grp_partial_lhs)
3106 force_gimple_rhs = true;
3107 sra_stats.exprs++;
3109 else if (racc
3110 && !racc->grp_unscalarized_data
3111 && TREE_CODE (lhs) == SSA_NAME
3112 && !access_has_replacements_p (racc))
3114 rhs = get_repl_default_def_ssa_name (racc);
3115 modify_this_stmt = true;
3116 sra_stats.exprs++;
3119 if (modify_this_stmt)
3121 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
3123 /* If we can avoid creating a VIEW_CONVERT_EXPR do so.
3124 ??? This should move to fold_stmt which we simply should
3125 call after building a VIEW_CONVERT_EXPR here. */
3126 if (AGGREGATE_TYPE_P (TREE_TYPE (lhs))
3127 && !contains_bitfld_component_ref_p (lhs))
3129 lhs = build_ref_for_model (loc, lhs, 0, racc, gsi, false);
3130 gimple_assign_set_lhs (*stmt, lhs);
3132 else if (AGGREGATE_TYPE_P (TREE_TYPE (rhs))
3133 && !contains_vce_or_bfcref_p (rhs))
3134 rhs = build_ref_for_model (loc, rhs, 0, lacc, gsi, false);
3136 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
3138 rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
3139 rhs);
3140 if (is_gimple_reg_type (TREE_TYPE (lhs))
3141 && TREE_CODE (lhs) != SSA_NAME)
3142 force_gimple_rhs = true;
3147 if (lacc && lacc->grp_to_be_debug_replaced)
3149 tree dlhs = get_access_replacement (lacc);
3150 tree drhs = unshare_expr (rhs);
3151 if (!useless_type_conversion_p (TREE_TYPE (dlhs), TREE_TYPE (drhs)))
3153 if (AGGREGATE_TYPE_P (TREE_TYPE (drhs))
3154 && !contains_vce_or_bfcref_p (drhs))
3155 drhs = build_debug_ref_for_model (loc, drhs, 0, lacc);
3156 if (drhs
3157 && !useless_type_conversion_p (TREE_TYPE (dlhs),
3158 TREE_TYPE (drhs)))
3159 drhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
3160 TREE_TYPE (dlhs), drhs);
3162 gimple ds = gimple_build_debug_bind (dlhs, drhs, *stmt);
3163 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
3166 /* From this point on, the function deals with assignments in between
3167 aggregates when at least one has scalar reductions of some of its
3168 components. There are three possible scenarios: Both the LHS and RHS have
3169 to-be-scalarized components, 2) only the RHS has or 3) only the LHS has.
3171 In the first case, we would like to load the LHS components from RHS
3172 components whenever possible. If that is not possible, we would like to
3173 read it directly from the RHS (after updating it by storing in it its own
3174 components). If there are some necessary unscalarized data in the LHS,
3175 those will be loaded by the original assignment too. If neither of these
3176 cases happen, the original statement can be removed. Most of this is done
3177 by load_assign_lhs_subreplacements.
3179 In the second case, we would like to store all RHS scalarized components
3180 directly into LHS and if they cover the aggregate completely, remove the
3181 statement too. In the third case, we want the LHS components to be loaded
3182 directly from the RHS (DSE will remove the original statement if it
3183 becomes redundant).
3185 This is a bit complex but manageable when types match and when unions do
3186 not cause confusion in a way that we cannot really load a component of LHS
3187 from the RHS or vice versa (the access representing this level can have
3188 subaccesses that are accessible only through a different union field at a
3189 higher level - different from the one used in the examined expression).
3190 Unions are fun.
3192 Therefore, I specially handle a fourth case, happening when there is a
3193 specific type cast or it is impossible to locate a scalarized subaccess on
3194 the other side of the expression. If that happens, I simply "refresh" the
3195 RHS by storing in it is scalarized components leave the original statement
3196 there to do the copying and then load the scalar replacements of the LHS.
3197 This is what the first branch does. */
3199 if (modify_this_stmt
3200 || gimple_has_volatile_ops (*stmt)
3201 || contains_vce_or_bfcref_p (rhs)
3202 || contains_vce_or_bfcref_p (lhs))
3204 if (access_has_children_p (racc))
3205 generate_subtree_copies (racc->first_child, racc->base, 0, 0, 0,
3206 gsi, false, false, loc);
3207 if (access_has_children_p (lacc))
3208 generate_subtree_copies (lacc->first_child, lacc->base, 0, 0, 0,
3209 gsi, true, true, loc);
3210 sra_stats.separate_lhs_rhs_handling++;
3212 /* This gimplification must be done after generate_subtree_copies,
3213 lest we insert the subtree copies in the middle of the gimplified
3214 sequence. */
3215 if (force_gimple_rhs)
3216 rhs = force_gimple_operand_gsi (&orig_gsi, rhs, true, NULL_TREE,
3217 true, GSI_SAME_STMT);
3218 if (gimple_assign_rhs1 (*stmt) != rhs)
3220 modify_this_stmt = true;
3221 gimple_assign_set_rhs_from_tree (&orig_gsi, rhs);
3222 gcc_assert (*stmt == gsi_stmt (orig_gsi));
3225 return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
3227 else
3229 if (access_has_children_p (lacc)
3230 && access_has_children_p (racc)
3231 /* When an access represents an unscalarizable region, it usually
3232 represents accesses with variable offset and thus must not be used
3233 to generate new memory accesses. */
3234 && !lacc->grp_unscalarizable_region
3235 && !racc->grp_unscalarizable_region)
3237 gimple_stmt_iterator orig_gsi = *gsi;
3238 enum unscalarized_data_handling refreshed;
3240 if (lacc->grp_read && !lacc->grp_covered)
3241 refreshed = handle_unscalarized_data_in_subtree (racc, gsi);
3242 else
3243 refreshed = SRA_UDH_NONE;
3245 load_assign_lhs_subreplacements (lacc, racc, lacc->offset,
3246 &orig_gsi, gsi, &refreshed);
3247 if (refreshed != SRA_UDH_RIGHT)
3249 gsi_next (gsi);
3250 unlink_stmt_vdef (*stmt);
3251 gsi_remove (&orig_gsi, true);
3252 release_defs (*stmt);
3253 sra_stats.deleted++;
3254 return SRA_AM_REMOVED;
3257 else
3259 if (access_has_children_p (racc)
3260 && !racc->grp_unscalarized_data)
3262 if (dump_file)
3264 fprintf (dump_file, "Removing load: ");
3265 print_gimple_stmt (dump_file, *stmt, 0, 0);
3267 generate_subtree_copies (racc->first_child, lhs,
3268 racc->offset, 0, 0, gsi,
3269 false, false, loc);
3270 gcc_assert (*stmt == gsi_stmt (*gsi));
3271 unlink_stmt_vdef (*stmt);
3272 gsi_remove (gsi, true);
3273 release_defs (*stmt);
3274 sra_stats.deleted++;
3275 return SRA_AM_REMOVED;
3277 /* Restore the aggregate RHS from its components so the
3278 prevailing aggregate copy does the right thing. */
3279 if (access_has_children_p (racc))
3280 generate_subtree_copies (racc->first_child, racc->base, 0, 0, 0,
3281 gsi, false, false, loc);
3282 /* Re-load the components of the aggregate copy destination.
3283 But use the RHS aggregate to load from to expose more
3284 optimization opportunities. */
3285 if (access_has_children_p (lacc))
3286 generate_subtree_copies (lacc->first_child, rhs, lacc->offset,
3287 0, 0, gsi, true, true, loc);
3290 return SRA_AM_NONE;
3294 /* Traverse the function body and all modifications as decided in
3295 analyze_all_variable_accesses. Return true iff the CFG has been
3296 changed. */
3298 static bool
3299 sra_modify_function_body (void)
3301 bool cfg_changed = false;
3302 basic_block bb;
3304 FOR_EACH_BB (bb)
3306 gimple_stmt_iterator gsi = gsi_start_bb (bb);
3307 while (!gsi_end_p (gsi))
3309 gimple stmt = gsi_stmt (gsi);
3310 enum assignment_mod_result assign_result;
3311 bool modified = false, deleted = false;
3312 tree *t;
3313 unsigned i;
3315 switch (gimple_code (stmt))
3317 case GIMPLE_RETURN:
3318 t = gimple_return_retval_ptr (stmt);
3319 if (*t != NULL_TREE)
3320 modified |= sra_modify_expr (t, &gsi, false);
3321 break;
3323 case GIMPLE_ASSIGN:
3324 assign_result = sra_modify_assign (&stmt, &gsi);
3325 modified |= assign_result == SRA_AM_MODIFIED;
3326 deleted = assign_result == SRA_AM_REMOVED;
3327 break;
3329 case GIMPLE_CALL:
3330 /* Operands must be processed before the lhs. */
3331 for (i = 0; i < gimple_call_num_args (stmt); i++)
3333 t = gimple_call_arg_ptr (stmt, i);
3334 modified |= sra_modify_expr (t, &gsi, false);
3337 if (gimple_call_lhs (stmt))
3339 t = gimple_call_lhs_ptr (stmt);
3340 modified |= sra_modify_expr (t, &gsi, true);
3342 break;
3344 case GIMPLE_ASM:
3345 for (i = 0; i < gimple_asm_ninputs (stmt); i++)
3347 t = &TREE_VALUE (gimple_asm_input_op (stmt, i));
3348 modified |= sra_modify_expr (t, &gsi, false);
3350 for (i = 0; i < gimple_asm_noutputs (stmt); i++)
3352 t = &TREE_VALUE (gimple_asm_output_op (stmt, i));
3353 modified |= sra_modify_expr (t, &gsi, true);
3355 break;
3357 default:
3358 break;
3361 if (modified)
3363 update_stmt (stmt);
3364 if (maybe_clean_eh_stmt (stmt)
3365 && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
3366 cfg_changed = true;
3368 if (!deleted)
3369 gsi_next (&gsi);
3373 return cfg_changed;
3376 /* Generate statements initializing scalar replacements of parts of function
3377 parameters. */
3379 static void
3380 initialize_parameter_reductions (void)
3382 gimple_stmt_iterator gsi;
3383 gimple_seq seq = NULL;
3384 tree parm;
3386 gsi = gsi_start (seq);
3387 for (parm = DECL_ARGUMENTS (current_function_decl);
3388 parm;
3389 parm = DECL_CHAIN (parm))
3391 vec<access_p> *access_vec;
3392 struct access *access;
3394 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
3395 continue;
3396 access_vec = get_base_access_vector (parm);
3397 if (!access_vec)
3398 continue;
3400 for (access = (*access_vec)[0];
3401 access;
3402 access = access->next_grp)
3403 generate_subtree_copies (access, parm, 0, 0, 0, &gsi, true, true,
3404 EXPR_LOCATION (parm));
3407 seq = gsi_seq (gsi);
3408 if (seq)
3409 gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR), seq);
3412 /* The "main" function of intraprocedural SRA passes. Runs the analysis and if
3413 it reveals there are components of some aggregates to be scalarized, it runs
3414 the required transformations. */
3415 static unsigned int
3416 perform_intra_sra (void)
3418 int ret = 0;
3419 sra_initialize ();
3421 if (!find_var_candidates ())
3422 goto out;
3424 if (!scan_function ())
3425 goto out;
3427 if (!analyze_all_variable_accesses ())
3428 goto out;
3430 if (sra_modify_function_body ())
3431 ret = TODO_update_ssa | TODO_cleanup_cfg;
3432 else
3433 ret = TODO_update_ssa;
3434 initialize_parameter_reductions ();
3436 statistics_counter_event (cfun, "Scalar replacements created",
3437 sra_stats.replacements);
3438 statistics_counter_event (cfun, "Modified expressions", sra_stats.exprs);
3439 statistics_counter_event (cfun, "Subtree copy stmts",
3440 sra_stats.subtree_copies);
3441 statistics_counter_event (cfun, "Subreplacement stmts",
3442 sra_stats.subreplacements);
3443 statistics_counter_event (cfun, "Deleted stmts", sra_stats.deleted);
3444 statistics_counter_event (cfun, "Separate LHS and RHS handling",
3445 sra_stats.separate_lhs_rhs_handling);
3447 out:
3448 sra_deinitialize ();
3449 return ret;
3452 /* Perform early intraprocedural SRA. */
3453 static unsigned int
3454 early_intra_sra (void)
3456 sra_mode = SRA_MODE_EARLY_INTRA;
3457 return perform_intra_sra ();
3460 /* Perform "late" intraprocedural SRA. */
3461 static unsigned int
3462 late_intra_sra (void)
3464 sra_mode = SRA_MODE_INTRA;
3465 return perform_intra_sra ();
3469 static bool
3470 gate_intra_sra (void)
3472 return flag_tree_sra != 0 && dbg_cnt (tree_sra);
3476 namespace {
3478 const pass_data pass_data_sra_early =
3480 GIMPLE_PASS, /* type */
3481 "esra", /* name */
3482 OPTGROUP_NONE, /* optinfo_flags */
3483 true, /* has_gate */
3484 true, /* has_execute */
3485 TV_TREE_SRA, /* tv_id */
3486 ( PROP_cfg | PROP_ssa ), /* properties_required */
3487 0, /* properties_provided */
3488 0, /* properties_destroyed */
3489 0, /* todo_flags_start */
3490 ( TODO_update_ssa | TODO_verify_ssa ), /* todo_flags_finish */
3493 class pass_sra_early : public gimple_opt_pass
3495 public:
3496 pass_sra_early (gcc::context *ctxt)
3497 : gimple_opt_pass (pass_data_sra_early, ctxt)
3500 /* opt_pass methods: */
3501 bool gate () { return gate_intra_sra (); }
3502 unsigned int execute () { return early_intra_sra (); }
3504 }; // class pass_sra_early
3506 } // anon namespace
3508 gimple_opt_pass *
3509 make_pass_sra_early (gcc::context *ctxt)
3511 return new pass_sra_early (ctxt);
3514 namespace {
3516 const pass_data pass_data_sra =
3518 GIMPLE_PASS, /* type */
3519 "sra", /* name */
3520 OPTGROUP_NONE, /* optinfo_flags */
3521 true, /* has_gate */
3522 true, /* has_execute */
3523 TV_TREE_SRA, /* tv_id */
3524 ( PROP_cfg | PROP_ssa ), /* properties_required */
3525 0, /* properties_provided */
3526 0, /* properties_destroyed */
3527 TODO_update_address_taken, /* todo_flags_start */
3528 ( TODO_update_ssa | TODO_verify_ssa ), /* todo_flags_finish */
3531 class pass_sra : public gimple_opt_pass
3533 public:
3534 pass_sra (gcc::context *ctxt)
3535 : gimple_opt_pass (pass_data_sra, ctxt)
3538 /* opt_pass methods: */
3539 bool gate () { return gate_intra_sra (); }
3540 unsigned int execute () { return late_intra_sra (); }
3542 }; // class pass_sra
3544 } // anon namespace
3546 gimple_opt_pass *
3547 make_pass_sra (gcc::context *ctxt)
3549 return new pass_sra (ctxt);
3553 /* Return true iff PARM (which must be a parm_decl) is an unused scalar
3554 parameter. */
3556 static bool
3557 is_unused_scalar_param (tree parm)
3559 tree name;
3560 return (is_gimple_reg (parm)
3561 && (!(name = ssa_default_def (cfun, parm))
3562 || has_zero_uses (name)));
3565 /* Scan immediate uses of a default definition SSA name of a parameter PARM and
3566 examine whether there are any direct or otherwise infeasible ones. If so,
3567 return true, otherwise return false. PARM must be a gimple register with a
3568 non-NULL default definition. */
3570 static bool
3571 ptr_parm_has_direct_uses (tree parm)
3573 imm_use_iterator ui;
3574 gimple stmt;
3575 tree name = ssa_default_def (cfun, parm);
3576 bool ret = false;
3578 FOR_EACH_IMM_USE_STMT (stmt, ui, name)
3580 int uses_ok = 0;
3581 use_operand_p use_p;
3583 if (is_gimple_debug (stmt))
3584 continue;
3586 /* Valid uses include dereferences on the lhs and the rhs. */
3587 if (gimple_has_lhs (stmt))
3589 tree lhs = gimple_get_lhs (stmt);
3590 while (handled_component_p (lhs))
3591 lhs = TREE_OPERAND (lhs, 0);
3592 if (TREE_CODE (lhs) == MEM_REF
3593 && TREE_OPERAND (lhs, 0) == name
3594 && integer_zerop (TREE_OPERAND (lhs, 1))
3595 && types_compatible_p (TREE_TYPE (lhs),
3596 TREE_TYPE (TREE_TYPE (name)))
3597 && !TREE_THIS_VOLATILE (lhs))
3598 uses_ok++;
3600 if (gimple_assign_single_p (stmt))
3602 tree rhs = gimple_assign_rhs1 (stmt);
3603 while (handled_component_p (rhs))
3604 rhs = TREE_OPERAND (rhs, 0);
3605 if (TREE_CODE (rhs) == MEM_REF
3606 && TREE_OPERAND (rhs, 0) == name
3607 && integer_zerop (TREE_OPERAND (rhs, 1))
3608 && types_compatible_p (TREE_TYPE (rhs),
3609 TREE_TYPE (TREE_TYPE (name)))
3610 && !TREE_THIS_VOLATILE (rhs))
3611 uses_ok++;
3613 else if (is_gimple_call (stmt))
3615 unsigned i;
3616 for (i = 0; i < gimple_call_num_args (stmt); ++i)
3618 tree arg = gimple_call_arg (stmt, i);
3619 while (handled_component_p (arg))
3620 arg = TREE_OPERAND (arg, 0);
3621 if (TREE_CODE (arg) == MEM_REF
3622 && TREE_OPERAND (arg, 0) == name
3623 && integer_zerop (TREE_OPERAND (arg, 1))
3624 && types_compatible_p (TREE_TYPE (arg),
3625 TREE_TYPE (TREE_TYPE (name)))
3626 && !TREE_THIS_VOLATILE (arg))
3627 uses_ok++;
3631 /* If the number of valid uses does not match the number of
3632 uses in this stmt there is an unhandled use. */
3633 FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
3634 --uses_ok;
3636 if (uses_ok != 0)
3637 ret = true;
3639 if (ret)
3640 BREAK_FROM_IMM_USE_STMT (ui);
3643 return ret;
3646 /* Identify candidates for reduction for IPA-SRA based on their type and mark
3647 them in candidate_bitmap. Note that these do not necessarily include
3648 parameter which are unused and thus can be removed. Return true iff any
3649 such candidate has been found. */
3651 static bool
3652 find_param_candidates (void)
3654 tree parm;
3655 int count = 0;
3656 bool ret = false;
3657 const char *msg;
3659 for (parm = DECL_ARGUMENTS (current_function_decl);
3660 parm;
3661 parm = DECL_CHAIN (parm))
3663 tree type = TREE_TYPE (parm);
3664 tree_node **slot;
3666 count++;
3668 if (TREE_THIS_VOLATILE (parm)
3669 || TREE_ADDRESSABLE (parm)
3670 || (!is_gimple_reg_type (type) && is_va_list_type (type)))
3671 continue;
3673 if (is_unused_scalar_param (parm))
3675 ret = true;
3676 continue;
3679 if (POINTER_TYPE_P (type))
3681 type = TREE_TYPE (type);
3683 if (TREE_CODE (type) == FUNCTION_TYPE
3684 || TYPE_VOLATILE (type)
3685 || (TREE_CODE (type) == ARRAY_TYPE
3686 && TYPE_NONALIASED_COMPONENT (type))
3687 || !is_gimple_reg (parm)
3688 || is_va_list_type (type)
3689 || ptr_parm_has_direct_uses (parm))
3690 continue;
3692 else if (!AGGREGATE_TYPE_P (type))
3693 continue;
3695 if (!COMPLETE_TYPE_P (type)
3696 || !tree_fits_uhwi_p (TYPE_SIZE (type))
3697 || tree_to_uhwi (TYPE_SIZE (type)) == 0
3698 || (AGGREGATE_TYPE_P (type)
3699 && type_internals_preclude_sra_p (type, &msg)))
3700 continue;
3702 bitmap_set_bit (candidate_bitmap, DECL_UID (parm));
3703 slot = candidates.find_slot_with_hash (parm, DECL_UID (parm), INSERT);
3704 *slot = parm;
3706 ret = true;
3707 if (dump_file && (dump_flags & TDF_DETAILS))
3709 fprintf (dump_file, "Candidate (%d): ", DECL_UID (parm));
3710 print_generic_expr (dump_file, parm, 0);
3711 fprintf (dump_file, "\n");
3715 func_param_count = count;
3716 return ret;
3719 /* Callback of walk_aliased_vdefs, marks the access passed as DATA as
3720 maybe_modified. */
3722 static bool
3723 mark_maybe_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
3724 void *data)
3726 struct access *repr = (struct access *) data;
3728 repr->grp_maybe_modified = 1;
3729 return true;
3732 /* Analyze what representatives (in linked lists accessible from
3733 REPRESENTATIVES) can be modified by side effects of statements in the
3734 current function. */
3736 static void
3737 analyze_modified_params (vec<access_p> representatives)
3739 int i;
3741 for (i = 0; i < func_param_count; i++)
3743 struct access *repr;
3745 for (repr = representatives[i];
3746 repr;
3747 repr = repr->next_grp)
3749 struct access *access;
3750 bitmap visited;
3751 ao_ref ar;
3753 if (no_accesses_p (repr))
3754 continue;
3755 if (!POINTER_TYPE_P (TREE_TYPE (repr->base))
3756 || repr->grp_maybe_modified)
3757 continue;
3759 ao_ref_init (&ar, repr->expr);
3760 visited = BITMAP_ALLOC (NULL);
3761 for (access = repr; access; access = access->next_sibling)
3763 /* All accesses are read ones, otherwise grp_maybe_modified would
3764 be trivially set. */
3765 walk_aliased_vdefs (&ar, gimple_vuse (access->stmt),
3766 mark_maybe_modified, repr, &visited);
3767 if (repr->grp_maybe_modified)
3768 break;
3770 BITMAP_FREE (visited);
3775 /* Propagate distances in bb_dereferences in the opposite direction than the
3776 control flow edges, in each step storing the maximum of the current value
3777 and the minimum of all successors. These steps are repeated until the table
3778 stabilizes. Note that BBs which might terminate the functions (according to
3779 final_bbs bitmap) never updated in this way. */
3781 static void
3782 propagate_dereference_distances (void)
3784 vec<basic_block> queue;
3785 basic_block bb;
3787 queue.create (last_basic_block_for_function (cfun));
3788 queue.quick_push (ENTRY_BLOCK_PTR);
3789 FOR_EACH_BB (bb)
3791 queue.quick_push (bb);
3792 bb->aux = bb;
3795 while (!queue.is_empty ())
3797 edge_iterator ei;
3798 edge e;
3799 bool change = false;
3800 int i;
3802 bb = queue.pop ();
3803 bb->aux = NULL;
3805 if (bitmap_bit_p (final_bbs, bb->index))
3806 continue;
3808 for (i = 0; i < func_param_count; i++)
3810 int idx = bb->index * func_param_count + i;
3811 bool first = true;
3812 HOST_WIDE_INT inh = 0;
3814 FOR_EACH_EDGE (e, ei, bb->succs)
3816 int succ_idx = e->dest->index * func_param_count + i;
3818 if (e->src == EXIT_BLOCK_PTR)
3819 continue;
3821 if (first)
3823 first = false;
3824 inh = bb_dereferences [succ_idx];
3826 else if (bb_dereferences [succ_idx] < inh)
3827 inh = bb_dereferences [succ_idx];
3830 if (!first && bb_dereferences[idx] < inh)
3832 bb_dereferences[idx] = inh;
3833 change = true;
3837 if (change && !bitmap_bit_p (final_bbs, bb->index))
3838 FOR_EACH_EDGE (e, ei, bb->preds)
3840 if (e->src->aux)
3841 continue;
3843 e->src->aux = e->src;
3844 queue.quick_push (e->src);
3848 queue.release ();
3851 /* Dump a dereferences TABLE with heading STR to file F. */
3853 static void
3854 dump_dereferences_table (FILE *f, const char *str, HOST_WIDE_INT *table)
3856 basic_block bb;
3858 fprintf (dump_file, str);
3859 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
3861 fprintf (f, "%4i %i ", bb->index, bitmap_bit_p (final_bbs, bb->index));
3862 if (bb != EXIT_BLOCK_PTR)
3864 int i;
3865 for (i = 0; i < func_param_count; i++)
3867 int idx = bb->index * func_param_count + i;
3868 fprintf (f, " %4" HOST_WIDE_INT_PRINT "d", table[idx]);
3871 fprintf (f, "\n");
3873 fprintf (dump_file, "\n");
3876 /* Determine what (parts of) parameters passed by reference that are not
3877 assigned to are not certainly dereferenced in this function and thus the
3878 dereferencing cannot be safely moved to the caller without potentially
3879 introducing a segfault. Mark such REPRESENTATIVES as
3880 grp_not_necessarilly_dereferenced.
3882 The dereferenced maximum "distance," i.e. the offset + size of the accessed
3883 part is calculated rather than simple booleans are calculated for each
3884 pointer parameter to handle cases when only a fraction of the whole
3885 aggregate is allocated (see testsuite/gcc.c-torture/execute/ipa-sra-2.c for
3886 an example).
3888 The maximum dereference distances for each pointer parameter and BB are
3889 already stored in bb_dereference. This routine simply propagates these
3890 values upwards by propagate_dereference_distances and then compares the
3891 distances of individual parameters in the ENTRY BB to the equivalent
3892 distances of each representative of a (fraction of a) parameter. */
3894 static void
3895 analyze_caller_dereference_legality (vec<access_p> representatives)
3897 int i;
3899 if (dump_file && (dump_flags & TDF_DETAILS))
3900 dump_dereferences_table (dump_file,
3901 "Dereference table before propagation:\n",
3902 bb_dereferences);
3904 propagate_dereference_distances ();
3906 if (dump_file && (dump_flags & TDF_DETAILS))
3907 dump_dereferences_table (dump_file,
3908 "Dereference table after propagation:\n",
3909 bb_dereferences);
3911 for (i = 0; i < func_param_count; i++)
3913 struct access *repr = representatives[i];
3914 int idx = ENTRY_BLOCK_PTR->index * func_param_count + i;
3916 if (!repr || no_accesses_p (repr))
3917 continue;
3921 if ((repr->offset + repr->size) > bb_dereferences[idx])
3922 repr->grp_not_necessarilly_dereferenced = 1;
3923 repr = repr->next_grp;
3925 while (repr);
3929 /* Return the representative access for the parameter declaration PARM if it is
3930 a scalar passed by reference which is not written to and the pointer value
3931 is not used directly. Thus, if it is legal to dereference it in the caller
3932 and we can rule out modifications through aliases, such parameter should be
3933 turned into one passed by value. Return NULL otherwise. */
3935 static struct access *
3936 unmodified_by_ref_scalar_representative (tree parm)
3938 int i, access_count;
3939 struct access *repr;
3940 vec<access_p> *access_vec;
3942 access_vec = get_base_access_vector (parm);
3943 gcc_assert (access_vec);
3944 repr = (*access_vec)[0];
3945 if (repr->write)
3946 return NULL;
3947 repr->group_representative = repr;
3949 access_count = access_vec->length ();
3950 for (i = 1; i < access_count; i++)
3952 struct access *access = (*access_vec)[i];
3953 if (access->write)
3954 return NULL;
3955 access->group_representative = repr;
3956 access->next_sibling = repr->next_sibling;
3957 repr->next_sibling = access;
3960 repr->grp_read = 1;
3961 repr->grp_scalar_ptr = 1;
3962 return repr;
3965 /* Return true iff this ACCESS precludes IPA-SRA of the parameter it is
3966 associated with. REQ_ALIGN is the minimum required alignment. */
3968 static bool
3969 access_precludes_ipa_sra_p (struct access *access, unsigned int req_align)
3971 unsigned int exp_align;
3972 /* Avoid issues such as the second simple testcase in PR 42025. The problem
3973 is incompatible assign in a call statement (and possibly even in asm
3974 statements). This can be relaxed by using a new temporary but only for
3975 non-TREE_ADDRESSABLE types and is probably not worth the complexity. (In
3976 intraprocedural SRA we deal with this by keeping the old aggregate around,
3977 something we cannot do in IPA-SRA.) */
3978 if (access->write
3979 && (is_gimple_call (access->stmt)
3980 || gimple_code (access->stmt) == GIMPLE_ASM))
3981 return true;
3983 exp_align = get_object_alignment (access->expr);
3984 if (exp_align < req_align)
3985 return true;
3987 return false;
3991 /* Sort collected accesses for parameter PARM, identify representatives for
3992 each accessed region and link them together. Return NULL if there are
3993 different but overlapping accesses, return the special ptr value meaning
3994 there are no accesses for this parameter if that is the case and return the
3995 first representative otherwise. Set *RO_GRP if there is a group of accesses
3996 with only read (i.e. no write) accesses. */
3998 static struct access *
3999 splice_param_accesses (tree parm, bool *ro_grp)
4001 int i, j, access_count, group_count;
4002 int agg_size, total_size = 0;
4003 struct access *access, *res, **prev_acc_ptr = &res;
4004 vec<access_p> *access_vec;
4006 access_vec = get_base_access_vector (parm);
4007 if (!access_vec)
4008 return &no_accesses_representant;
4009 access_count = access_vec->length ();
4011 access_vec->qsort (compare_access_positions);
4013 i = 0;
4014 total_size = 0;
4015 group_count = 0;
4016 while (i < access_count)
4018 bool modification;
4019 tree a1_alias_type;
4020 access = (*access_vec)[i];
4021 modification = access->write;
4022 if (access_precludes_ipa_sra_p (access, TYPE_ALIGN (access->type)))
4023 return NULL;
4024 a1_alias_type = reference_alias_ptr_type (access->expr);
4026 /* Access is about to become group representative unless we find some
4027 nasty overlap which would preclude us from breaking this parameter
4028 apart. */
4030 j = i + 1;
4031 while (j < access_count)
4033 struct access *ac2 = (*access_vec)[j];
4034 if (ac2->offset != access->offset)
4036 /* All or nothing law for parameters. */
4037 if (access->offset + access->size > ac2->offset)
4038 return NULL;
4039 else
4040 break;
4042 else if (ac2->size != access->size)
4043 return NULL;
4045 if (access_precludes_ipa_sra_p (ac2, TYPE_ALIGN (access->type))
4046 || (ac2->type != access->type
4047 && (TREE_ADDRESSABLE (ac2->type)
4048 || TREE_ADDRESSABLE (access->type)))
4049 || (reference_alias_ptr_type (ac2->expr) != a1_alias_type))
4050 return NULL;
4052 modification |= ac2->write;
4053 ac2->group_representative = access;
4054 ac2->next_sibling = access->next_sibling;
4055 access->next_sibling = ac2;
4056 j++;
4059 group_count++;
4060 access->grp_maybe_modified = modification;
4061 if (!modification)
4062 *ro_grp = true;
4063 *prev_acc_ptr = access;
4064 prev_acc_ptr = &access->next_grp;
4065 total_size += access->size;
4066 i = j;
4069 if (POINTER_TYPE_P (TREE_TYPE (parm)))
4070 agg_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))));
4071 else
4072 agg_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (parm)));
4073 if (total_size >= agg_size)
4074 return NULL;
4076 gcc_assert (group_count > 0);
4077 return res;
4080 /* Decide whether parameters with representative accesses given by REPR should
4081 be reduced into components. */
4083 static int
4084 decide_one_param_reduction (struct access *repr)
4086 int total_size, cur_parm_size, agg_size, new_param_count, parm_size_limit;
4087 bool by_ref;
4088 tree parm;
4090 parm = repr->base;
4091 cur_parm_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (parm)));
4092 gcc_assert (cur_parm_size > 0);
4094 if (POINTER_TYPE_P (TREE_TYPE (parm)))
4096 by_ref = true;
4097 agg_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))));
4099 else
4101 by_ref = false;
4102 agg_size = cur_parm_size;
4105 if (dump_file)
4107 struct access *acc;
4108 fprintf (dump_file, "Evaluating PARAM group sizes for ");
4109 print_generic_expr (dump_file, parm, 0);
4110 fprintf (dump_file, " (UID: %u): \n", DECL_UID (parm));
4111 for (acc = repr; acc; acc = acc->next_grp)
4112 dump_access (dump_file, acc, true);
4115 total_size = 0;
4116 new_param_count = 0;
4118 for (; repr; repr = repr->next_grp)
4120 gcc_assert (parm == repr->base);
4122 /* Taking the address of a non-addressable field is verboten. */
4123 if (by_ref && repr->non_addressable)
4124 return 0;
4126 /* Do not decompose a non-BLKmode param in a way that would
4127 create BLKmode params. Especially for by-reference passing
4128 (thus, pointer-type param) this is hardly worthwhile. */
4129 if (DECL_MODE (parm) != BLKmode
4130 && TYPE_MODE (repr->type) == BLKmode)
4131 return 0;
4133 if (!by_ref || (!repr->grp_maybe_modified
4134 && !repr->grp_not_necessarilly_dereferenced))
4135 total_size += repr->size;
4136 else
4137 total_size += cur_parm_size;
4139 new_param_count++;
4142 gcc_assert (new_param_count > 0);
4144 if (optimize_function_for_size_p (cfun))
4145 parm_size_limit = cur_parm_size;
4146 else
4147 parm_size_limit = (PARAM_VALUE (PARAM_IPA_SRA_PTR_GROWTH_FACTOR)
4148 * cur_parm_size);
4150 if (total_size < agg_size
4151 && total_size <= parm_size_limit)
4153 if (dump_file)
4154 fprintf (dump_file, " ....will be split into %i components\n",
4155 new_param_count);
4156 return new_param_count;
4158 else
4159 return 0;
4162 /* The order of the following enums is important, we need to do extra work for
4163 UNUSED_PARAMS, BY_VAL_ACCESSES and UNMODIF_BY_REF_ACCESSES. */
4164 enum ipa_splicing_result { NO_GOOD_ACCESS, UNUSED_PARAMS, BY_VAL_ACCESSES,
4165 MODIF_BY_REF_ACCESSES, UNMODIF_BY_REF_ACCESSES };
4167 /* Identify representatives of all accesses to all candidate parameters for
4168 IPA-SRA. Return result based on what representatives have been found. */
4170 static enum ipa_splicing_result
4171 splice_all_param_accesses (vec<access_p> &representatives)
4173 enum ipa_splicing_result result = NO_GOOD_ACCESS;
4174 tree parm;
4175 struct access *repr;
4177 representatives.create (func_param_count);
4179 for (parm = DECL_ARGUMENTS (current_function_decl);
4180 parm;
4181 parm = DECL_CHAIN (parm))
4183 if (is_unused_scalar_param (parm))
4185 representatives.quick_push (&no_accesses_representant);
4186 if (result == NO_GOOD_ACCESS)
4187 result = UNUSED_PARAMS;
4189 else if (POINTER_TYPE_P (TREE_TYPE (parm))
4190 && is_gimple_reg_type (TREE_TYPE (TREE_TYPE (parm)))
4191 && bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
4193 repr = unmodified_by_ref_scalar_representative (parm);
4194 representatives.quick_push (repr);
4195 if (repr)
4196 result = UNMODIF_BY_REF_ACCESSES;
4198 else if (bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
4200 bool ro_grp = false;
4201 repr = splice_param_accesses (parm, &ro_grp);
4202 representatives.quick_push (repr);
4204 if (repr && !no_accesses_p (repr))
4206 if (POINTER_TYPE_P (TREE_TYPE (parm)))
4208 if (ro_grp)
4209 result = UNMODIF_BY_REF_ACCESSES;
4210 else if (result < MODIF_BY_REF_ACCESSES)
4211 result = MODIF_BY_REF_ACCESSES;
4213 else if (result < BY_VAL_ACCESSES)
4214 result = BY_VAL_ACCESSES;
4216 else if (no_accesses_p (repr) && (result == NO_GOOD_ACCESS))
4217 result = UNUSED_PARAMS;
4219 else
4220 representatives.quick_push (NULL);
4223 if (result == NO_GOOD_ACCESS)
4225 representatives.release ();
4226 return NO_GOOD_ACCESS;
4229 return result;
4232 /* Return the index of BASE in PARMS. Abort if it is not found. */
4234 static inline int
4235 get_param_index (tree base, vec<tree> parms)
4237 int i, len;
4239 len = parms.length ();
4240 for (i = 0; i < len; i++)
4241 if (parms[i] == base)
4242 return i;
4243 gcc_unreachable ();
4246 /* Convert the decisions made at the representative level into compact
4247 parameter adjustments. REPRESENTATIVES are pointers to first
4248 representatives of each param accesses, ADJUSTMENTS_COUNT is the expected
4249 final number of adjustments. */
4251 static ipa_parm_adjustment_vec
4252 turn_representatives_into_adjustments (vec<access_p> representatives,
4253 int adjustments_count)
4255 vec<tree> parms;
4256 ipa_parm_adjustment_vec adjustments;
4257 tree parm;
4258 int i;
4260 gcc_assert (adjustments_count > 0);
4261 parms = ipa_get_vector_of_formal_parms (current_function_decl);
4262 adjustments.create (adjustments_count);
4263 parm = DECL_ARGUMENTS (current_function_decl);
4264 for (i = 0; i < func_param_count; i++, parm = DECL_CHAIN (parm))
4266 struct access *repr = representatives[i];
4268 if (!repr || no_accesses_p (repr))
4270 struct ipa_parm_adjustment adj;
4272 memset (&adj, 0, sizeof (adj));
4273 adj.base_index = get_param_index (parm, parms);
4274 adj.base = parm;
4275 if (!repr)
4276 adj.copy_param = 1;
4277 else
4278 adj.remove_param = 1;
4279 adjustments.quick_push (adj);
4281 else
4283 struct ipa_parm_adjustment adj;
4284 int index = get_param_index (parm, parms);
4286 for (; repr; repr = repr->next_grp)
4288 memset (&adj, 0, sizeof (adj));
4289 gcc_assert (repr->base == parm);
4290 adj.base_index = index;
4291 adj.base = repr->base;
4292 adj.type = repr->type;
4293 adj.alias_ptr_type = reference_alias_ptr_type (repr->expr);
4294 adj.offset = repr->offset;
4295 adj.by_ref = (POINTER_TYPE_P (TREE_TYPE (repr->base))
4296 && (repr->grp_maybe_modified
4297 || repr->grp_not_necessarilly_dereferenced));
4298 adjustments.quick_push (adj);
4302 parms.release ();
4303 return adjustments;
4306 /* Analyze the collected accesses and produce a plan what to do with the
4307 parameters in the form of adjustments, NULL meaning nothing. */
4309 static ipa_parm_adjustment_vec
4310 analyze_all_param_acesses (void)
4312 enum ipa_splicing_result repr_state;
4313 bool proceed = false;
4314 int i, adjustments_count = 0;
4315 vec<access_p> representatives;
4316 ipa_parm_adjustment_vec adjustments;
4318 repr_state = splice_all_param_accesses (representatives);
4319 if (repr_state == NO_GOOD_ACCESS)
4320 return ipa_parm_adjustment_vec ();
4322 /* If there are any parameters passed by reference which are not modified
4323 directly, we need to check whether they can be modified indirectly. */
4324 if (repr_state == UNMODIF_BY_REF_ACCESSES)
4326 analyze_caller_dereference_legality (representatives);
4327 analyze_modified_params (representatives);
4330 for (i = 0; i < func_param_count; i++)
4332 struct access *repr = representatives[i];
4334 if (repr && !no_accesses_p (repr))
4336 if (repr->grp_scalar_ptr)
4338 adjustments_count++;
4339 if (repr->grp_not_necessarilly_dereferenced
4340 || repr->grp_maybe_modified)
4341 representatives[i] = NULL;
4342 else
4344 proceed = true;
4345 sra_stats.scalar_by_ref_to_by_val++;
4348 else
4350 int new_components = decide_one_param_reduction (repr);
4352 if (new_components == 0)
4354 representatives[i] = NULL;
4355 adjustments_count++;
4357 else
4359 adjustments_count += new_components;
4360 sra_stats.aggregate_params_reduced++;
4361 sra_stats.param_reductions_created += new_components;
4362 proceed = true;
4366 else
4368 if (no_accesses_p (repr))
4370 proceed = true;
4371 sra_stats.deleted_unused_parameters++;
4373 adjustments_count++;
4377 if (!proceed && dump_file)
4378 fprintf (dump_file, "NOT proceeding to change params.\n");
4380 if (proceed)
4381 adjustments = turn_representatives_into_adjustments (representatives,
4382 adjustments_count);
4383 else
4384 adjustments = ipa_parm_adjustment_vec ();
4386 representatives.release ();
4387 return adjustments;
4390 /* If a parameter replacement identified by ADJ does not yet exist in the form
4391 of declaration, create it and record it, otherwise return the previously
4392 created one. */
4394 static tree
4395 get_replaced_param_substitute (struct ipa_parm_adjustment *adj)
4397 tree repl;
4398 if (!adj->new_ssa_base)
4400 char *pretty_name = make_fancy_name (adj->base);
4402 repl = create_tmp_reg (TREE_TYPE (adj->base), "ISR");
4403 DECL_NAME (repl) = get_identifier (pretty_name);
4404 obstack_free (&name_obstack, pretty_name);
4406 adj->new_ssa_base = repl;
4408 else
4409 repl = adj->new_ssa_base;
4410 return repl;
4413 /* Find the first adjustment for a particular parameter BASE in a vector of
4414 ADJUSTMENTS which is not a copy_param. Return NULL if there is no such
4415 adjustment. */
4417 static struct ipa_parm_adjustment *
4418 get_adjustment_for_base (ipa_parm_adjustment_vec adjustments, tree base)
4420 int i, len;
4422 len = adjustments.length ();
4423 for (i = 0; i < len; i++)
4425 struct ipa_parm_adjustment *adj;
4427 adj = &adjustments[i];
4428 if (!adj->copy_param && adj->base == base)
4429 return adj;
4432 return NULL;
4435 /* If the statement STMT defines an SSA_NAME of a parameter which is to be
4436 removed because its value is not used, replace the SSA_NAME with a one
4437 relating to a created VAR_DECL together all of its uses and return true.
4438 ADJUSTMENTS is a pointer to an adjustments vector. */
4440 static bool
4441 replace_removed_params_ssa_names (gimple stmt,
4442 ipa_parm_adjustment_vec adjustments)
4444 struct ipa_parm_adjustment *adj;
4445 tree lhs, decl, repl, name;
4447 if (gimple_code (stmt) == GIMPLE_PHI)
4448 lhs = gimple_phi_result (stmt);
4449 else if (is_gimple_assign (stmt))
4450 lhs = gimple_assign_lhs (stmt);
4451 else if (is_gimple_call (stmt))
4452 lhs = gimple_call_lhs (stmt);
4453 else
4454 gcc_unreachable ();
4456 if (TREE_CODE (lhs) != SSA_NAME)
4457 return false;
4459 decl = SSA_NAME_VAR (lhs);
4460 if (decl == NULL_TREE
4461 || TREE_CODE (decl) != PARM_DECL)
4462 return false;
4464 adj = get_adjustment_for_base (adjustments, decl);
4465 if (!adj)
4466 return false;
4468 repl = get_replaced_param_substitute (adj);
4469 name = make_ssa_name (repl, stmt);
4471 if (dump_file)
4473 fprintf (dump_file, "replacing an SSA name of a removed param ");
4474 print_generic_expr (dump_file, lhs, 0);
4475 fprintf (dump_file, " with ");
4476 print_generic_expr (dump_file, name, 0);
4477 fprintf (dump_file, "\n");
4480 if (is_gimple_assign (stmt))
4481 gimple_assign_set_lhs (stmt, name);
4482 else if (is_gimple_call (stmt))
4483 gimple_call_set_lhs (stmt, name);
4484 else
4485 gimple_phi_set_result (stmt, name);
4487 replace_uses_by (lhs, name);
4488 release_ssa_name (lhs);
4489 return true;
4492 /* If the expression *EXPR should be replaced by a reduction of a parameter, do
4493 so. ADJUSTMENTS is a pointer to a vector of adjustments. CONVERT
4494 specifies whether the function should care about type incompatibility the
4495 current and new expressions. If it is false, the function will leave
4496 incompatibility issues to the caller. Return true iff the expression
4497 was modified. */
4499 static bool
4500 sra_ipa_modify_expr (tree *expr, bool convert,
4501 ipa_parm_adjustment_vec adjustments)
4503 int i, len;
4504 struct ipa_parm_adjustment *adj, *cand = NULL;
4505 HOST_WIDE_INT offset, size, max_size;
4506 tree base, src;
4508 len = adjustments.length ();
4510 if (TREE_CODE (*expr) == BIT_FIELD_REF
4511 || TREE_CODE (*expr) == IMAGPART_EXPR
4512 || TREE_CODE (*expr) == REALPART_EXPR)
4514 expr = &TREE_OPERAND (*expr, 0);
4515 convert = true;
4518 base = get_ref_base_and_extent (*expr, &offset, &size, &max_size);
4519 if (!base || size == -1 || max_size == -1)
4520 return false;
4522 if (TREE_CODE (base) == MEM_REF)
4524 offset += mem_ref_offset (base).low * BITS_PER_UNIT;
4525 base = TREE_OPERAND (base, 0);
4528 base = get_ssa_base_param (base);
4529 if (!base || TREE_CODE (base) != PARM_DECL)
4530 return false;
4532 for (i = 0; i < len; i++)
4534 adj = &adjustments[i];
4536 if (adj->base == base
4537 && (adj->offset == offset || adj->remove_param))
4539 cand = adj;
4540 break;
4543 if (!cand || cand->copy_param || cand->remove_param)
4544 return false;
4546 if (cand->by_ref)
4547 src = build_simple_mem_ref (cand->reduction);
4548 else
4549 src = cand->reduction;
4551 if (dump_file && (dump_flags & TDF_DETAILS))
4553 fprintf (dump_file, "About to replace expr ");
4554 print_generic_expr (dump_file, *expr, 0);
4555 fprintf (dump_file, " with ");
4556 print_generic_expr (dump_file, src, 0);
4557 fprintf (dump_file, "\n");
4560 if (convert && !useless_type_conversion_p (TREE_TYPE (*expr), cand->type))
4562 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*expr), src);
4563 *expr = vce;
4565 else
4566 *expr = src;
4567 return true;
4570 /* If the statement pointed to by STMT_PTR contains any expressions that need
4571 to replaced with a different one as noted by ADJUSTMENTS, do so. Handle any
4572 potential type incompatibilities (GSI is used to accommodate conversion
4573 statements and must point to the statement). Return true iff the statement
4574 was modified. */
4576 static bool
4577 sra_ipa_modify_assign (gimple *stmt_ptr, gimple_stmt_iterator *gsi,
4578 ipa_parm_adjustment_vec adjustments)
4580 gimple stmt = *stmt_ptr;
4581 tree *lhs_p, *rhs_p;
4582 bool any;
4584 if (!gimple_assign_single_p (stmt))
4585 return false;
4587 rhs_p = gimple_assign_rhs1_ptr (stmt);
4588 lhs_p = gimple_assign_lhs_ptr (stmt);
4590 any = sra_ipa_modify_expr (rhs_p, false, adjustments);
4591 any |= sra_ipa_modify_expr (lhs_p, false, adjustments);
4592 if (any)
4594 tree new_rhs = NULL_TREE;
4596 if (!useless_type_conversion_p (TREE_TYPE (*lhs_p), TREE_TYPE (*rhs_p)))
4598 if (TREE_CODE (*rhs_p) == CONSTRUCTOR)
4600 /* V_C_Es of constructors can cause trouble (PR 42714). */
4601 if (is_gimple_reg_type (TREE_TYPE (*lhs_p)))
4602 *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
4603 else
4604 *rhs_p = build_constructor (TREE_TYPE (*lhs_p),
4605 NULL);
4607 else
4608 new_rhs = fold_build1_loc (gimple_location (stmt),
4609 VIEW_CONVERT_EXPR, TREE_TYPE (*lhs_p),
4610 *rhs_p);
4612 else if (REFERENCE_CLASS_P (*rhs_p)
4613 && is_gimple_reg_type (TREE_TYPE (*lhs_p))
4614 && !is_gimple_reg (*lhs_p))
4615 /* This can happen when an assignment in between two single field
4616 structures is turned into an assignment in between two pointers to
4617 scalars (PR 42237). */
4618 new_rhs = *rhs_p;
4620 if (new_rhs)
4622 tree tmp = force_gimple_operand_gsi (gsi, new_rhs, true, NULL_TREE,
4623 true, GSI_SAME_STMT);
4625 gimple_assign_set_rhs_from_tree (gsi, tmp);
4628 return true;
4631 return false;
4634 /* Traverse the function body and all modifications as described in
4635 ADJUSTMENTS. Return true iff the CFG has been changed. */
4637 static bool
4638 ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments)
4640 bool cfg_changed = false;
4641 basic_block bb;
4643 FOR_EACH_BB (bb)
4645 gimple_stmt_iterator gsi;
4647 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4648 replace_removed_params_ssa_names (gsi_stmt (gsi), adjustments);
4650 gsi = gsi_start_bb (bb);
4651 while (!gsi_end_p (gsi))
4653 gimple stmt = gsi_stmt (gsi);
4654 bool modified = false;
4655 tree *t;
4656 unsigned i;
4658 switch (gimple_code (stmt))
4660 case GIMPLE_RETURN:
4661 t = gimple_return_retval_ptr (stmt);
4662 if (*t != NULL_TREE)
4663 modified |= sra_ipa_modify_expr (t, true, adjustments);
4664 break;
4666 case GIMPLE_ASSIGN:
4667 modified |= sra_ipa_modify_assign (&stmt, &gsi, adjustments);
4668 modified |= replace_removed_params_ssa_names (stmt, adjustments);
4669 break;
4671 case GIMPLE_CALL:
4672 /* Operands must be processed before the lhs. */
4673 for (i = 0; i < gimple_call_num_args (stmt); i++)
4675 t = gimple_call_arg_ptr (stmt, i);
4676 modified |= sra_ipa_modify_expr (t, true, adjustments);
4679 if (gimple_call_lhs (stmt))
4681 t = gimple_call_lhs_ptr (stmt);
4682 modified |= sra_ipa_modify_expr (t, false, adjustments);
4683 modified |= replace_removed_params_ssa_names (stmt,
4684 adjustments);
4686 break;
4688 case GIMPLE_ASM:
4689 for (i = 0; i < gimple_asm_ninputs (stmt); i++)
4691 t = &TREE_VALUE (gimple_asm_input_op (stmt, i));
4692 modified |= sra_ipa_modify_expr (t, true, adjustments);
4694 for (i = 0; i < gimple_asm_noutputs (stmt); i++)
4696 t = &TREE_VALUE (gimple_asm_output_op (stmt, i));
4697 modified |= sra_ipa_modify_expr (t, false, adjustments);
4699 break;
4701 default:
4702 break;
4705 if (modified)
4707 update_stmt (stmt);
4708 if (maybe_clean_eh_stmt (stmt)
4709 && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
4710 cfg_changed = true;
4712 gsi_next (&gsi);
4716 return cfg_changed;
4719 /* Call gimple_debug_bind_reset_value on all debug statements describing
4720 gimple register parameters that are being removed or replaced. */
4722 static void
4723 sra_ipa_reset_debug_stmts (ipa_parm_adjustment_vec adjustments)
4725 int i, len;
4726 gimple_stmt_iterator *gsip = NULL, gsi;
4728 if (MAY_HAVE_DEBUG_STMTS && single_succ_p (ENTRY_BLOCK_PTR))
4730 gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
4731 gsip = &gsi;
4733 len = adjustments.length ();
4734 for (i = 0; i < len; i++)
4736 struct ipa_parm_adjustment *adj;
4737 imm_use_iterator ui;
4738 gimple stmt, def_temp;
4739 tree name, vexpr, copy = NULL_TREE;
4740 use_operand_p use_p;
4742 adj = &adjustments[i];
4743 if (adj->copy_param || !is_gimple_reg (adj->base))
4744 continue;
4745 name = ssa_default_def (cfun, adj->base);
4746 vexpr = NULL;
4747 if (name)
4748 FOR_EACH_IMM_USE_STMT (stmt, ui, name)
4750 if (gimple_clobber_p (stmt))
4752 gimple_stmt_iterator cgsi = gsi_for_stmt (stmt);
4753 unlink_stmt_vdef (stmt);
4754 gsi_remove (&cgsi, true);
4755 release_defs (stmt);
4756 continue;
4758 /* All other users must have been removed by
4759 ipa_sra_modify_function_body. */
4760 gcc_assert (is_gimple_debug (stmt));
4761 if (vexpr == NULL && gsip != NULL)
4763 gcc_assert (TREE_CODE (adj->base) == PARM_DECL);
4764 vexpr = make_node (DEBUG_EXPR_DECL);
4765 def_temp = gimple_build_debug_source_bind (vexpr, adj->base,
4766 NULL);
4767 DECL_ARTIFICIAL (vexpr) = 1;
4768 TREE_TYPE (vexpr) = TREE_TYPE (name);
4769 DECL_MODE (vexpr) = DECL_MODE (adj->base);
4770 gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
4772 if (vexpr)
4774 FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
4775 SET_USE (use_p, vexpr);
4777 else
4778 gimple_debug_bind_reset_value (stmt);
4779 update_stmt (stmt);
4781 /* Create a VAR_DECL for debug info purposes. */
4782 if (!DECL_IGNORED_P (adj->base))
4784 copy = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
4785 VAR_DECL, DECL_NAME (adj->base),
4786 TREE_TYPE (adj->base));
4787 if (DECL_PT_UID_SET_P (adj->base))
4788 SET_DECL_PT_UID (copy, DECL_PT_UID (adj->base));
4789 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (adj->base);
4790 TREE_READONLY (copy) = TREE_READONLY (adj->base);
4791 TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (adj->base);
4792 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (adj->base);
4793 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (adj->base);
4794 DECL_IGNORED_P (copy) = DECL_IGNORED_P (adj->base);
4795 DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (adj->base);
4796 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
4797 SET_DECL_RTL (copy, 0);
4798 TREE_USED (copy) = 1;
4799 DECL_CONTEXT (copy) = current_function_decl;
4800 add_local_decl (cfun, copy);
4801 DECL_CHAIN (copy) =
4802 BLOCK_VARS (DECL_INITIAL (current_function_decl));
4803 BLOCK_VARS (DECL_INITIAL (current_function_decl)) = copy;
4805 if (gsip != NULL && copy && target_for_debug_bind (adj->base))
4807 gcc_assert (TREE_CODE (adj->base) == PARM_DECL);
4808 if (vexpr)
4809 def_temp = gimple_build_debug_bind (copy, vexpr, NULL);
4810 else
4811 def_temp = gimple_build_debug_source_bind (copy, adj->base,
4812 NULL);
4813 gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
4818 /* Return false iff all callers have at least as many actual arguments as there
4819 are formal parameters in the current function. */
4821 static bool
4822 not_all_callers_have_enough_arguments_p (struct cgraph_node *node,
4823 void *data ATTRIBUTE_UNUSED)
4825 struct cgraph_edge *cs;
4826 for (cs = node->callers; cs; cs = cs->next_caller)
4827 if (!callsite_has_enough_arguments_p (cs->call_stmt))
4828 return true;
4830 return false;
4833 /* Convert all callers of NODE. */
4835 static bool
4836 convert_callers_for_node (struct cgraph_node *node,
4837 void *data)
4839 ipa_parm_adjustment_vec *adjustments = (ipa_parm_adjustment_vec *) data;
4840 bitmap recomputed_callers = BITMAP_ALLOC (NULL);
4841 struct cgraph_edge *cs;
4843 for (cs = node->callers; cs; cs = cs->next_caller)
4845 push_cfun (DECL_STRUCT_FUNCTION (cs->caller->decl));
4847 if (dump_file)
4848 fprintf (dump_file, "Adjusting call %s/%i -> %s/%i\n",
4849 xstrdup (cs->caller->name ()),
4850 cs->caller->order,
4851 xstrdup (cs->callee->name ()),
4852 cs->callee->order);
4854 ipa_modify_call_arguments (cs, cs->call_stmt, *adjustments);
4856 pop_cfun ();
4859 for (cs = node->callers; cs; cs = cs->next_caller)
4860 if (bitmap_set_bit (recomputed_callers, cs->caller->uid)
4861 && gimple_in_ssa_p (DECL_STRUCT_FUNCTION (cs->caller->decl)))
4862 compute_inline_parameters (cs->caller, true);
4863 BITMAP_FREE (recomputed_callers);
4865 return true;
4868 /* Convert all callers of NODE to pass parameters as given in ADJUSTMENTS. */
4870 static void
4871 convert_callers (struct cgraph_node *node, tree old_decl,
4872 ipa_parm_adjustment_vec adjustments)
4874 basic_block this_block;
4876 cgraph_for_node_and_aliases (node, convert_callers_for_node,
4877 &adjustments, false);
4879 if (!encountered_recursive_call)
4880 return;
4882 FOR_EACH_BB (this_block)
4884 gimple_stmt_iterator gsi;
4886 for (gsi = gsi_start_bb (this_block); !gsi_end_p (gsi); gsi_next (&gsi))
4888 gimple stmt = gsi_stmt (gsi);
4889 tree call_fndecl;
4890 if (gimple_code (stmt) != GIMPLE_CALL)
4891 continue;
4892 call_fndecl = gimple_call_fndecl (stmt);
4893 if (call_fndecl == old_decl)
4895 if (dump_file)
4896 fprintf (dump_file, "Adjusting recursive call");
4897 gimple_call_set_fndecl (stmt, node->decl);
4898 ipa_modify_call_arguments (NULL, stmt, adjustments);
4903 return;
4906 /* Perform all the modification required in IPA-SRA for NODE to have parameters
4907 as given in ADJUSTMENTS. Return true iff the CFG has been changed. */
4909 static bool
4910 modify_function (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments)
4912 struct cgraph_node *new_node;
4913 bool cfg_changed;
4914 vec<cgraph_edge_p> redirect_callers = collect_callers_of_node (node);
4916 rebuild_cgraph_edges ();
4917 free_dominance_info (CDI_DOMINATORS);
4918 pop_cfun ();
4920 new_node = cgraph_function_versioning (node, redirect_callers,
4921 NULL,
4922 NULL, false, NULL, NULL, "isra");
4923 redirect_callers.release ();
4925 push_cfun (DECL_STRUCT_FUNCTION (new_node->decl));
4926 ipa_modify_formal_parameters (current_function_decl, adjustments, "ISRA");
4927 cfg_changed = ipa_sra_modify_function_body (adjustments);
4928 sra_ipa_reset_debug_stmts (adjustments);
4929 convert_callers (new_node, node->decl, adjustments);
4930 cgraph_make_node_local (new_node);
4931 return cfg_changed;
4934 /* If NODE has a caller, return true. */
4936 static bool
4937 has_caller_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
4939 if (node->callers)
4940 return true;
4941 return false;
4944 /* Return false the function is apparently unsuitable for IPA-SRA based on it's
4945 attributes, return true otherwise. NODE is the cgraph node of the current
4946 function. */
4948 static bool
4949 ipa_sra_preliminary_function_checks (struct cgraph_node *node)
4951 if (!cgraph_node_can_be_local_p (node))
4953 if (dump_file)
4954 fprintf (dump_file, "Function not local to this compilation unit.\n");
4955 return false;
4958 if (!node->local.can_change_signature)
4960 if (dump_file)
4961 fprintf (dump_file, "Function can not change signature.\n");
4962 return false;
4965 if (!tree_versionable_function_p (node->decl))
4967 if (dump_file)
4968 fprintf (dump_file, "Function is not versionable.\n");
4969 return false;
4972 if (DECL_VIRTUAL_P (current_function_decl))
4974 if (dump_file)
4975 fprintf (dump_file, "Function is a virtual method.\n");
4976 return false;
4979 if ((DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl))
4980 && inline_summary (node)->size >= MAX_INLINE_INSNS_AUTO)
4982 if (dump_file)
4983 fprintf (dump_file, "Function too big to be made truly local.\n");
4984 return false;
4987 if (!cgraph_for_node_and_aliases (node, has_caller_p, NULL, true))
4989 if (dump_file)
4990 fprintf (dump_file,
4991 "Function has no callers in this compilation unit.\n");
4992 return false;
4995 if (cfun->stdarg)
4997 if (dump_file)
4998 fprintf (dump_file, "Function uses stdarg. \n");
4999 return false;
5002 if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl)))
5003 return false;
5005 return true;
5008 /* Perform early interprocedural SRA. */
5010 static unsigned int
5011 ipa_early_sra (void)
5013 struct cgraph_node *node = cgraph_get_node (current_function_decl);
5014 ipa_parm_adjustment_vec adjustments;
5015 int ret = 0;
5017 if (!ipa_sra_preliminary_function_checks (node))
5018 return 0;
5020 sra_initialize ();
5021 sra_mode = SRA_MODE_EARLY_IPA;
5023 if (!find_param_candidates ())
5025 if (dump_file)
5026 fprintf (dump_file, "Function has no IPA-SRA candidates.\n");
5027 goto simple_out;
5030 if (cgraph_for_node_and_aliases (node, not_all_callers_have_enough_arguments_p,
5031 NULL, true))
5033 if (dump_file)
5034 fprintf (dump_file, "There are callers with insufficient number of "
5035 "arguments.\n");
5036 goto simple_out;
5039 bb_dereferences = XCNEWVEC (HOST_WIDE_INT,
5040 func_param_count
5041 * last_basic_block_for_function (cfun));
5042 final_bbs = BITMAP_ALLOC (NULL);
5044 scan_function ();
5045 if (encountered_apply_args)
5047 if (dump_file)
5048 fprintf (dump_file, "Function calls __builtin_apply_args().\n");
5049 goto out;
5052 if (encountered_unchangable_recursive_call)
5054 if (dump_file)
5055 fprintf (dump_file, "Function calls itself with insufficient "
5056 "number of arguments.\n");
5057 goto out;
5060 adjustments = analyze_all_param_acesses ();
5061 if (!adjustments.exists ())
5062 goto out;
5063 if (dump_file)
5064 ipa_dump_param_adjustments (dump_file, adjustments, current_function_decl);
5066 if (modify_function (node, adjustments))
5067 ret = TODO_update_ssa | TODO_cleanup_cfg;
5068 else
5069 ret = TODO_update_ssa;
5070 adjustments.release ();
5072 statistics_counter_event (cfun, "Unused parameters deleted",
5073 sra_stats.deleted_unused_parameters);
5074 statistics_counter_event (cfun, "Scalar parameters converted to by-value",
5075 sra_stats.scalar_by_ref_to_by_val);
5076 statistics_counter_event (cfun, "Aggregate parameters broken up",
5077 sra_stats.aggregate_params_reduced);
5078 statistics_counter_event (cfun, "Aggregate parameter components created",
5079 sra_stats.param_reductions_created);
5081 out:
5082 BITMAP_FREE (final_bbs);
5083 free (bb_dereferences);
5084 simple_out:
5085 sra_deinitialize ();
5086 return ret;
5089 /* Return if early ipa sra shall be performed. */
5090 static bool
5091 ipa_early_sra_gate (void)
5093 return flag_ipa_sra && dbg_cnt (eipa_sra);
5096 namespace {
5098 const pass_data pass_data_early_ipa_sra =
5100 GIMPLE_PASS, /* type */
5101 "eipa_sra", /* name */
5102 OPTGROUP_NONE, /* optinfo_flags */
5103 true, /* has_gate */
5104 true, /* has_execute */
5105 TV_IPA_SRA, /* tv_id */
5106 0, /* properties_required */
5107 0, /* properties_provided */
5108 0, /* properties_destroyed */
5109 0, /* todo_flags_start */
5110 TODO_dump_symtab, /* todo_flags_finish */
5113 class pass_early_ipa_sra : public gimple_opt_pass
5115 public:
5116 pass_early_ipa_sra (gcc::context *ctxt)
5117 : gimple_opt_pass (pass_data_early_ipa_sra, ctxt)
5120 /* opt_pass methods: */
5121 bool gate () { return ipa_early_sra_gate (); }
5122 unsigned int execute () { return ipa_early_sra (); }
5124 }; // class pass_early_ipa_sra
5126 } // anon namespace
5128 gimple_opt_pass *
5129 make_pass_early_ipa_sra (gcc::context *ctxt)
5131 return new pass_early_ipa_sra (ctxt);