* gimple-walk.h: New File. Relocate prototypes from gimple.h.
[official-gcc.git] / gcc / tree-sra.c
blob31fcdfeee3f84fbee2c4964109e1a03256388d0e
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 "gimplify.h"
82 #include "gimple-iterator.h"
83 #include "gimple-walk.h"
84 #include "bitmap.h"
85 #include "gimple-ssa.h"
86 #include "tree-cfg.h"
87 #include "tree-phinodes.h"
88 #include "ssa-iterators.h"
89 #include "tree-ssanames.h"
90 #include "tree-dfa.h"
91 #include "tree-ssa.h"
92 #include "tree-pass.h"
93 #include "ipa-prop.h"
94 #include "statistics.h"
95 #include "params.h"
96 #include "target.h"
97 #include "flags.h"
98 #include "dbgcnt.h"
99 #include "tree-inline.h"
100 #include "gimple-pretty-print.h"
101 #include "ipa-inline.h"
102 #include "ipa-utils.h"
104 /* Enumeration of all aggregate reductions we can do. */
105 enum sra_mode { SRA_MODE_EARLY_IPA, /* early call regularization */
106 SRA_MODE_EARLY_INTRA, /* early intraprocedural SRA */
107 SRA_MODE_INTRA }; /* late intraprocedural SRA */
109 /* Global variable describing which aggregate reduction we are performing at
110 the moment. */
111 static enum sra_mode sra_mode;
113 struct assign_link;
115 /* ACCESS represents each access to an aggregate variable (as a whole or a
116 part). It can also represent a group of accesses that refer to exactly the
117 same fragment of an aggregate (i.e. those that have exactly the same offset
118 and size). Such representatives for a single aggregate, once determined,
119 are linked in a linked list and have the group fields set.
121 Moreover, when doing intraprocedural SRA, a tree is built from those
122 representatives (by the means of first_child and next_sibling pointers), in
123 which all items in a subtree are "within" the root, i.e. their offset is
124 greater or equal to offset of the root and offset+size is smaller or equal
125 to offset+size of the root. Children of an access are sorted by offset.
127 Note that accesses to parts of vector and complex number types always
128 represented by an access to the whole complex number or a vector. It is a
129 duty of the modifying functions to replace them appropriately. */
131 struct access
133 /* Values returned by `get_ref_base_and_extent' for each component reference
134 If EXPR isn't a component reference just set `BASE = EXPR', `OFFSET = 0',
135 `SIZE = TREE_SIZE (TREE_TYPE (expr))'. */
136 HOST_WIDE_INT offset;
137 HOST_WIDE_INT size;
138 tree base;
140 /* Expression. It is context dependent so do not use it to create new
141 expressions to access the original aggregate. See PR 42154 for a
142 testcase. */
143 tree expr;
144 /* Type. */
145 tree type;
147 /* The statement this access belongs to. */
148 gimple stmt;
150 /* Next group representative for this aggregate. */
151 struct access *next_grp;
153 /* Pointer to the group representative. Pointer to itself if the struct is
154 the representative. */
155 struct access *group_representative;
157 /* If this access has any children (in terms of the definition above), this
158 points to the first one. */
159 struct access *first_child;
161 /* In intraprocedural SRA, pointer to the next sibling in the access tree as
162 described above. In IPA-SRA this is a pointer to the next access
163 belonging to the same group (having the same representative). */
164 struct access *next_sibling;
166 /* Pointers to the first and last element in the linked list of assign
167 links. */
168 struct assign_link *first_link, *last_link;
170 /* Pointer to the next access in the work queue. */
171 struct access *next_queued;
173 /* Replacement variable for this access "region." Never to be accessed
174 directly, always only by the means of get_access_replacement() and only
175 when grp_to_be_replaced flag is set. */
176 tree replacement_decl;
178 /* Is this particular access write access? */
179 unsigned write : 1;
181 /* Is this access an access to a non-addressable field? */
182 unsigned non_addressable : 1;
184 /* Is this access currently in the work queue? */
185 unsigned grp_queued : 1;
187 /* Does this group contain a write access? This flag is propagated down the
188 access tree. */
189 unsigned grp_write : 1;
191 /* Does this group contain a read access? This flag is propagated down the
192 access tree. */
193 unsigned grp_read : 1;
195 /* Does this group contain a read access that comes from an assignment
196 statement? This flag is propagated down the access tree. */
197 unsigned grp_assignment_read : 1;
199 /* Does this group contain a write access that comes from an assignment
200 statement? This flag is propagated down the access tree. */
201 unsigned grp_assignment_write : 1;
203 /* Does this group contain a read access through a scalar type? This flag is
204 not propagated in the access tree in any direction. */
205 unsigned grp_scalar_read : 1;
207 /* Does this group contain a write access through a scalar type? This flag
208 is not propagated in the access tree in any direction. */
209 unsigned grp_scalar_write : 1;
211 /* Is this access an artificial one created to scalarize some record
212 entirely? */
213 unsigned grp_total_scalarization : 1;
215 /* Other passes of the analysis use this bit to make function
216 analyze_access_subtree create scalar replacements for this group if
217 possible. */
218 unsigned grp_hint : 1;
220 /* Is the subtree rooted in this access fully covered by scalar
221 replacements? */
222 unsigned grp_covered : 1;
224 /* If set to true, this access and all below it in an access tree must not be
225 scalarized. */
226 unsigned grp_unscalarizable_region : 1;
228 /* Whether data have been written to parts of the aggregate covered by this
229 access which is not to be scalarized. This flag is propagated up in the
230 access tree. */
231 unsigned grp_unscalarized_data : 1;
233 /* Does this access and/or group contain a write access through a
234 BIT_FIELD_REF? */
235 unsigned grp_partial_lhs : 1;
237 /* Set when a scalar replacement should be created for this variable. */
238 unsigned grp_to_be_replaced : 1;
240 /* Set when we want a replacement for the sole purpose of having it in
241 generated debug statements. */
242 unsigned grp_to_be_debug_replaced : 1;
244 /* Should TREE_NO_WARNING of a replacement be set? */
245 unsigned grp_no_warning : 1;
247 /* Is it possible that the group refers to data which might be (directly or
248 otherwise) modified? */
249 unsigned grp_maybe_modified : 1;
251 /* Set when this is a representative of a pointer to scalar (i.e. by
252 reference) parameter which we consider for turning into a plain scalar
253 (i.e. a by value parameter). */
254 unsigned grp_scalar_ptr : 1;
256 /* Set when we discover that this pointer is not safe to dereference in the
257 caller. */
258 unsigned grp_not_necessarilly_dereferenced : 1;
261 typedef struct access *access_p;
264 /* Alloc pool for allocating access structures. */
265 static alloc_pool access_pool;
267 /* A structure linking lhs and rhs accesses from an aggregate assignment. They
268 are used to propagate subaccesses from rhs to lhs as long as they don't
269 conflict with what is already there. */
270 struct assign_link
272 struct access *lacc, *racc;
273 struct assign_link *next;
276 /* Alloc pool for allocating assign link structures. */
277 static alloc_pool link_pool;
279 /* Base (tree) -> Vector (vec<access_p> *) map. */
280 static struct pointer_map_t *base_access_vec;
282 /* Candidate hash table helpers. */
284 struct uid_decl_hasher : typed_noop_remove <tree_node>
286 typedef tree_node value_type;
287 typedef tree_node compare_type;
288 static inline hashval_t hash (const value_type *);
289 static inline bool equal (const value_type *, const compare_type *);
292 /* Hash a tree in a uid_decl_map. */
294 inline hashval_t
295 uid_decl_hasher::hash (const value_type *item)
297 return item->decl_minimal.uid;
300 /* Return true if the DECL_UID in both trees are equal. */
302 inline bool
303 uid_decl_hasher::equal (const value_type *a, const compare_type *b)
305 return (a->decl_minimal.uid == b->decl_minimal.uid);
308 /* Set of candidates. */
309 static bitmap candidate_bitmap;
310 static hash_table <uid_decl_hasher> candidates;
312 /* For a candidate UID return the candidates decl. */
314 static inline tree
315 candidate (unsigned uid)
317 tree_node t;
318 t.decl_minimal.uid = uid;
319 return candidates.find_with_hash (&t, static_cast <hashval_t> (uid));
322 /* Bitmap of candidates which we should try to entirely scalarize away and
323 those which cannot be (because they are and need be used as a whole). */
324 static bitmap should_scalarize_away_bitmap, cannot_scalarize_away_bitmap;
326 /* Obstack for creation of fancy names. */
327 static struct obstack name_obstack;
329 /* Head of a linked list of accesses that need to have its subaccesses
330 propagated to their assignment counterparts. */
331 static struct access *work_queue_head;
333 /* Number of parameters of the analyzed function when doing early ipa SRA. */
334 static int func_param_count;
336 /* scan_function sets the following to true if it encounters a call to
337 __builtin_apply_args. */
338 static bool encountered_apply_args;
340 /* Set by scan_function when it finds a recursive call. */
341 static bool encountered_recursive_call;
343 /* Set by scan_function when it finds a recursive call with less actual
344 arguments than formal parameters.. */
345 static bool encountered_unchangable_recursive_call;
347 /* This is a table in which for each basic block and parameter there is a
348 distance (offset + size) in that parameter which is dereferenced and
349 accessed in that BB. */
350 static HOST_WIDE_INT *bb_dereferences;
351 /* Bitmap of BBs that can cause the function to "stop" progressing by
352 returning, throwing externally, looping infinitely or calling a function
353 which might abort etc.. */
354 static bitmap final_bbs;
356 /* Representative of no accesses at all. */
357 static struct access no_accesses_representant;
359 /* Predicate to test the special value. */
361 static inline bool
362 no_accesses_p (struct access *access)
364 return access == &no_accesses_representant;
367 /* Dump contents of ACCESS to file F in a human friendly way. If GRP is true,
368 representative fields are dumped, otherwise those which only describe the
369 individual access are. */
371 static struct
373 /* Number of processed aggregates is readily available in
374 analyze_all_variable_accesses and so is not stored here. */
376 /* Number of created scalar replacements. */
377 int replacements;
379 /* Number of times sra_modify_expr or sra_modify_assign themselves changed an
380 expression. */
381 int exprs;
383 /* Number of statements created by generate_subtree_copies. */
384 int subtree_copies;
386 /* Number of statements created by load_assign_lhs_subreplacements. */
387 int subreplacements;
389 /* Number of times sra_modify_assign has deleted a statement. */
390 int deleted;
392 /* Number of times sra_modify_assign has to deal with subaccesses of LHS and
393 RHS reparately due to type conversions or nonexistent matching
394 references. */
395 int separate_lhs_rhs_handling;
397 /* Number of parameters that were removed because they were unused. */
398 int deleted_unused_parameters;
400 /* Number of scalars passed as parameters by reference that have been
401 converted to be passed by value. */
402 int scalar_by_ref_to_by_val;
404 /* Number of aggregate parameters that were replaced by one or more of their
405 components. */
406 int aggregate_params_reduced;
408 /* Numbber of components created when splitting aggregate parameters. */
409 int param_reductions_created;
410 } sra_stats;
412 static void
413 dump_access (FILE *f, struct access *access, bool grp)
415 fprintf (f, "access { ");
416 fprintf (f, "base = (%d)'", DECL_UID (access->base));
417 print_generic_expr (f, access->base, 0);
418 fprintf (f, "', offset = " HOST_WIDE_INT_PRINT_DEC, access->offset);
419 fprintf (f, ", size = " HOST_WIDE_INT_PRINT_DEC, access->size);
420 fprintf (f, ", expr = ");
421 print_generic_expr (f, access->expr, 0);
422 fprintf (f, ", type = ");
423 print_generic_expr (f, access->type, 0);
424 if (grp)
425 fprintf (f, ", grp_read = %d, grp_write = %d, grp_assignment_read = %d, "
426 "grp_assignment_write = %d, grp_scalar_read = %d, "
427 "grp_scalar_write = %d, grp_total_scalarization = %d, "
428 "grp_hint = %d, grp_covered = %d, "
429 "grp_unscalarizable_region = %d, grp_unscalarized_data = %d, "
430 "grp_partial_lhs = %d, grp_to_be_replaced = %d, "
431 "grp_to_be_debug_replaced = %d, grp_maybe_modified = %d, "
432 "grp_not_necessarilly_dereferenced = %d\n",
433 access->grp_read, access->grp_write, access->grp_assignment_read,
434 access->grp_assignment_write, access->grp_scalar_read,
435 access->grp_scalar_write, access->grp_total_scalarization,
436 access->grp_hint, access->grp_covered,
437 access->grp_unscalarizable_region, access->grp_unscalarized_data,
438 access->grp_partial_lhs, access->grp_to_be_replaced,
439 access->grp_to_be_debug_replaced, access->grp_maybe_modified,
440 access->grp_not_necessarilly_dereferenced);
441 else
442 fprintf (f, ", write = %d, grp_total_scalarization = %d, "
443 "grp_partial_lhs = %d\n",
444 access->write, access->grp_total_scalarization,
445 access->grp_partial_lhs);
448 /* Dump a subtree rooted in ACCESS to file F, indent by LEVEL. */
450 static void
451 dump_access_tree_1 (FILE *f, struct access *access, int level)
455 int i;
457 for (i = 0; i < level; i++)
458 fputs ("* ", dump_file);
460 dump_access (f, access, true);
462 if (access->first_child)
463 dump_access_tree_1 (f, access->first_child, level + 1);
465 access = access->next_sibling;
467 while (access);
470 /* Dump all access trees for a variable, given the pointer to the first root in
471 ACCESS. */
473 static void
474 dump_access_tree (FILE *f, struct access *access)
476 for (; access; access = access->next_grp)
477 dump_access_tree_1 (f, access, 0);
480 /* Return true iff ACC is non-NULL and has subaccesses. */
482 static inline bool
483 access_has_children_p (struct access *acc)
485 return acc && acc->first_child;
488 /* Return true iff ACC is (partly) covered by at least one replacement. */
490 static bool
491 access_has_replacements_p (struct access *acc)
493 struct access *child;
494 if (acc->grp_to_be_replaced)
495 return true;
496 for (child = acc->first_child; child; child = child->next_sibling)
497 if (access_has_replacements_p (child))
498 return true;
499 return false;
502 /* Return a vector of pointers to accesses for the variable given in BASE or
503 NULL if there is none. */
505 static vec<access_p> *
506 get_base_access_vector (tree base)
508 void **slot;
510 slot = pointer_map_contains (base_access_vec, base);
511 if (!slot)
512 return NULL;
513 else
514 return *(vec<access_p> **) slot;
517 /* Find an access with required OFFSET and SIZE in a subtree of accesses rooted
518 in ACCESS. Return NULL if it cannot be found. */
520 static struct access *
521 find_access_in_subtree (struct access *access, HOST_WIDE_INT offset,
522 HOST_WIDE_INT size)
524 while (access && (access->offset != offset || access->size != size))
526 struct access *child = access->first_child;
528 while (child && (child->offset + child->size <= offset))
529 child = child->next_sibling;
530 access = child;
533 return access;
536 /* Return the first group representative for DECL or NULL if none exists. */
538 static struct access *
539 get_first_repr_for_decl (tree base)
541 vec<access_p> *access_vec;
543 access_vec = get_base_access_vector (base);
544 if (!access_vec)
545 return NULL;
547 return (*access_vec)[0];
550 /* Find an access representative for the variable BASE and given OFFSET and
551 SIZE. Requires that access trees have already been built. Return NULL if
552 it cannot be found. */
554 static struct access *
555 get_var_base_offset_size_access (tree base, HOST_WIDE_INT offset,
556 HOST_WIDE_INT size)
558 struct access *access;
560 access = get_first_repr_for_decl (base);
561 while (access && (access->offset + access->size <= offset))
562 access = access->next_grp;
563 if (!access)
564 return NULL;
566 return find_access_in_subtree (access, offset, size);
569 /* Add LINK to the linked list of assign links of RACC. */
570 static void
571 add_link_to_rhs (struct access *racc, struct assign_link *link)
573 gcc_assert (link->racc == racc);
575 if (!racc->first_link)
577 gcc_assert (!racc->last_link);
578 racc->first_link = link;
580 else
581 racc->last_link->next = link;
583 racc->last_link = link;
584 link->next = NULL;
587 /* Move all link structures in their linked list in OLD_RACC to the linked list
588 in NEW_RACC. */
589 static void
590 relink_to_new_repr (struct access *new_racc, struct access *old_racc)
592 if (!old_racc->first_link)
594 gcc_assert (!old_racc->last_link);
595 return;
598 if (new_racc->first_link)
600 gcc_assert (!new_racc->last_link->next);
601 gcc_assert (!old_racc->last_link || !old_racc->last_link->next);
603 new_racc->last_link->next = old_racc->first_link;
604 new_racc->last_link = old_racc->last_link;
606 else
608 gcc_assert (!new_racc->last_link);
610 new_racc->first_link = old_racc->first_link;
611 new_racc->last_link = old_racc->last_link;
613 old_racc->first_link = old_racc->last_link = NULL;
616 /* Add ACCESS to the work queue (which is actually a stack). */
618 static void
619 add_access_to_work_queue (struct access *access)
621 if (!access->grp_queued)
623 gcc_assert (!access->next_queued);
624 access->next_queued = work_queue_head;
625 access->grp_queued = 1;
626 work_queue_head = access;
630 /* Pop an access from the work queue, and return it, assuming there is one. */
632 static struct access *
633 pop_access_from_work_queue (void)
635 struct access *access = work_queue_head;
637 work_queue_head = access->next_queued;
638 access->next_queued = NULL;
639 access->grp_queued = 0;
640 return access;
644 /* Allocate necessary structures. */
646 static void
647 sra_initialize (void)
649 candidate_bitmap = BITMAP_ALLOC (NULL);
650 candidates.create (vec_safe_length (cfun->local_decls) / 2);
651 should_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
652 cannot_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
653 gcc_obstack_init (&name_obstack);
654 access_pool = create_alloc_pool ("SRA accesses", sizeof (struct access), 16);
655 link_pool = create_alloc_pool ("SRA links", sizeof (struct assign_link), 16);
656 base_access_vec = pointer_map_create ();
657 memset (&sra_stats, 0, sizeof (sra_stats));
658 encountered_apply_args = false;
659 encountered_recursive_call = false;
660 encountered_unchangable_recursive_call = false;
663 /* Hook fed to pointer_map_traverse, deallocate stored vectors. */
665 static bool
666 delete_base_accesses (const void *key ATTRIBUTE_UNUSED, void **value,
667 void *data ATTRIBUTE_UNUSED)
669 vec<access_p> *access_vec = (vec<access_p> *) *value;
670 vec_free (access_vec);
671 return true;
674 /* Deallocate all general structures. */
676 static void
677 sra_deinitialize (void)
679 BITMAP_FREE (candidate_bitmap);
680 candidates.dispose ();
681 BITMAP_FREE (should_scalarize_away_bitmap);
682 BITMAP_FREE (cannot_scalarize_away_bitmap);
683 free_alloc_pool (access_pool);
684 free_alloc_pool (link_pool);
685 obstack_free (&name_obstack, NULL);
687 pointer_map_traverse (base_access_vec, delete_base_accesses, NULL);
688 pointer_map_destroy (base_access_vec);
691 /* Remove DECL from candidates for SRA and write REASON to the dump file if
692 there is one. */
693 static void
694 disqualify_candidate (tree decl, const char *reason)
696 if (bitmap_clear_bit (candidate_bitmap, DECL_UID (decl)))
697 candidates.clear_slot (candidates.find_slot_with_hash (decl,
698 DECL_UID (decl),
699 NO_INSERT));
701 if (dump_file && (dump_flags & TDF_DETAILS))
703 fprintf (dump_file, "! Disqualifying ");
704 print_generic_expr (dump_file, decl, 0);
705 fprintf (dump_file, " - %s\n", reason);
709 /* Return true iff the type contains a field or an element which does not allow
710 scalarization. */
712 static bool
713 type_internals_preclude_sra_p (tree type, const char **msg)
715 tree fld;
716 tree et;
718 switch (TREE_CODE (type))
720 case RECORD_TYPE:
721 case UNION_TYPE:
722 case QUAL_UNION_TYPE:
723 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
724 if (TREE_CODE (fld) == FIELD_DECL)
726 tree ft = TREE_TYPE (fld);
728 if (TREE_THIS_VOLATILE (fld))
730 *msg = "volatile structure field";
731 return true;
733 if (!DECL_FIELD_OFFSET (fld))
735 *msg = "no structure field offset";
736 return true;
738 if (!DECL_SIZE (fld))
740 *msg = "zero structure field size";
741 return true;
743 if (!host_integerp (DECL_FIELD_OFFSET (fld), 1))
745 *msg = "structure field offset not fixed";
746 return true;
748 if (!host_integerp (DECL_SIZE (fld), 1))
750 *msg = "structure field size not fixed";
751 return true;
753 if (!host_integerp (bit_position (fld), 0))
755 *msg = "structure field size too big";
756 return true;
758 if (AGGREGATE_TYPE_P (ft)
759 && int_bit_position (fld) % BITS_PER_UNIT != 0)
761 *msg = "structure field is bit field";
762 return true;
765 if (AGGREGATE_TYPE_P (ft) && type_internals_preclude_sra_p (ft, msg))
766 return true;
769 return false;
771 case ARRAY_TYPE:
772 et = TREE_TYPE (type);
774 if (TYPE_VOLATILE (et))
776 *msg = "element type is volatile";
777 return true;
780 if (AGGREGATE_TYPE_P (et) && type_internals_preclude_sra_p (et, msg))
781 return true;
783 return false;
785 default:
786 return false;
790 /* If T is an SSA_NAME, return NULL if it is not a default def or return its
791 base variable if it is. Return T if it is not an SSA_NAME. */
793 static tree
794 get_ssa_base_param (tree t)
796 if (TREE_CODE (t) == SSA_NAME)
798 if (SSA_NAME_IS_DEFAULT_DEF (t))
799 return SSA_NAME_VAR (t);
800 else
801 return NULL_TREE;
803 return t;
806 /* Mark a dereference of BASE of distance DIST in a basic block tht STMT
807 belongs to, unless the BB has already been marked as a potentially
808 final. */
810 static void
811 mark_parm_dereference (tree base, HOST_WIDE_INT dist, gimple stmt)
813 basic_block bb = gimple_bb (stmt);
814 int idx, parm_index = 0;
815 tree parm;
817 if (bitmap_bit_p (final_bbs, bb->index))
818 return;
820 for (parm = DECL_ARGUMENTS (current_function_decl);
821 parm && parm != base;
822 parm = DECL_CHAIN (parm))
823 parm_index++;
825 gcc_assert (parm_index < func_param_count);
827 idx = bb->index * func_param_count + parm_index;
828 if (bb_dereferences[idx] < dist)
829 bb_dereferences[idx] = dist;
832 /* Allocate an access structure for BASE, OFFSET and SIZE, clear it, fill in
833 the three fields. Also add it to the vector of accesses corresponding to
834 the base. Finally, return the new access. */
836 static struct access *
837 create_access_1 (tree base, HOST_WIDE_INT offset, HOST_WIDE_INT size)
839 vec<access_p> *v;
840 struct access *access;
841 void **slot;
843 access = (struct access *) pool_alloc (access_pool);
844 memset (access, 0, sizeof (struct access));
845 access->base = base;
846 access->offset = offset;
847 access->size = size;
849 slot = pointer_map_contains (base_access_vec, base);
850 if (slot)
851 v = (vec<access_p> *) *slot;
852 else
853 vec_alloc (v, 32);
855 v->safe_push (access);
857 *((vec<access_p> **)
858 pointer_map_insert (base_access_vec, base)) = v;
860 return access;
863 /* Create and insert access for EXPR. Return created access, or NULL if it is
864 not possible. */
866 static struct access *
867 create_access (tree expr, gimple stmt, bool write)
869 struct access *access;
870 HOST_WIDE_INT offset, size, max_size;
871 tree base = expr;
872 bool ptr, unscalarizable_region = false;
874 base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
876 if (sra_mode == SRA_MODE_EARLY_IPA
877 && TREE_CODE (base) == MEM_REF)
879 base = get_ssa_base_param (TREE_OPERAND (base, 0));
880 if (!base)
881 return NULL;
882 ptr = true;
884 else
885 ptr = false;
887 if (!DECL_P (base) || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
888 return NULL;
890 if (sra_mode == SRA_MODE_EARLY_IPA)
892 if (size < 0 || size != max_size)
894 disqualify_candidate (base, "Encountered a variable sized access.");
895 return NULL;
897 if (TREE_CODE (expr) == COMPONENT_REF
898 && DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
900 disqualify_candidate (base, "Encountered a bit-field access.");
901 return NULL;
903 gcc_checking_assert ((offset % BITS_PER_UNIT) == 0);
905 if (ptr)
906 mark_parm_dereference (base, offset + size, stmt);
908 else
910 if (size != max_size)
912 size = max_size;
913 unscalarizable_region = true;
915 if (size < 0)
917 disqualify_candidate (base, "Encountered an unconstrained access.");
918 return NULL;
922 access = create_access_1 (base, offset, size);
923 access->expr = expr;
924 access->type = TREE_TYPE (expr);
925 access->write = write;
926 access->grp_unscalarizable_region = unscalarizable_region;
927 access->stmt = stmt;
929 if (TREE_CODE (expr) == COMPONENT_REF
930 && DECL_NONADDRESSABLE_P (TREE_OPERAND (expr, 1)))
931 access->non_addressable = 1;
933 return access;
937 /* Return true iff TYPE is a RECORD_TYPE with fields that are either of gimple
938 register types or (recursively) records with only these two kinds of fields.
939 It also returns false if any of these records contains a bit-field. */
941 static bool
942 type_consists_of_records_p (tree type)
944 tree fld;
946 if (TREE_CODE (type) != RECORD_TYPE)
947 return false;
949 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
950 if (TREE_CODE (fld) == FIELD_DECL)
952 tree ft = TREE_TYPE (fld);
954 if (DECL_BIT_FIELD (fld))
955 return false;
957 if (!is_gimple_reg_type (ft)
958 && !type_consists_of_records_p (ft))
959 return false;
962 return true;
965 /* Create total_scalarization accesses for all scalar type fields in DECL that
966 must be of a RECORD_TYPE conforming to type_consists_of_records_p. BASE
967 must be the top-most VAR_DECL representing the variable, OFFSET must be the
968 offset of DECL within BASE. REF must be the memory reference expression for
969 the given decl. */
971 static void
972 completely_scalarize_record (tree base, tree decl, HOST_WIDE_INT offset,
973 tree ref)
975 tree fld, decl_type = TREE_TYPE (decl);
977 for (fld = TYPE_FIELDS (decl_type); fld; fld = DECL_CHAIN (fld))
978 if (TREE_CODE (fld) == FIELD_DECL)
980 HOST_WIDE_INT pos = offset + int_bit_position (fld);
981 tree ft = TREE_TYPE (fld);
982 tree nref = build3 (COMPONENT_REF, TREE_TYPE (fld), ref, fld,
983 NULL_TREE);
985 if (is_gimple_reg_type (ft))
987 struct access *access;
988 HOST_WIDE_INT size;
990 size = tree_low_cst (DECL_SIZE (fld), 1);
991 access = create_access_1 (base, pos, size);
992 access->expr = nref;
993 access->type = ft;
994 access->grp_total_scalarization = 1;
995 /* Accesses for intraprocedural SRA can have their stmt NULL. */
997 else
998 completely_scalarize_record (base, fld, pos, nref);
1002 /* Create total_scalarization accesses for all scalar type fields in VAR and
1003 for VAR a a whole. VAR must be of a RECORD_TYPE conforming to
1004 type_consists_of_records_p. */
1006 static void
1007 completely_scalarize_var (tree var)
1009 HOST_WIDE_INT size = tree_low_cst (DECL_SIZE (var), 1);
1010 struct access *access;
1012 access = create_access_1 (var, 0, size);
1013 access->expr = var;
1014 access->type = TREE_TYPE (var);
1015 access->grp_total_scalarization = 1;
1017 completely_scalarize_record (var, var, 0, var);
1020 /* Return true if REF has an VIEW_CONVERT_EXPR somewhere in it. */
1022 static inline bool
1023 contains_view_convert_expr_p (const_tree ref)
1025 while (handled_component_p (ref))
1027 if (TREE_CODE (ref) == VIEW_CONVERT_EXPR)
1028 return true;
1029 ref = TREE_OPERAND (ref, 0);
1032 return false;
1035 /* Search the given tree for a declaration by skipping handled components and
1036 exclude it from the candidates. */
1038 static void
1039 disqualify_base_of_expr (tree t, const char *reason)
1041 t = get_base_address (t);
1042 if (sra_mode == SRA_MODE_EARLY_IPA
1043 && TREE_CODE (t) == MEM_REF)
1044 t = get_ssa_base_param (TREE_OPERAND (t, 0));
1046 if (t && DECL_P (t))
1047 disqualify_candidate (t, reason);
1050 /* Scan expression EXPR and create access structures for all accesses to
1051 candidates for scalarization. Return the created access or NULL if none is
1052 created. */
1054 static struct access *
1055 build_access_from_expr_1 (tree expr, gimple stmt, bool write)
1057 struct access *ret = NULL;
1058 bool partial_ref;
1060 if (TREE_CODE (expr) == BIT_FIELD_REF
1061 || TREE_CODE (expr) == IMAGPART_EXPR
1062 || TREE_CODE (expr) == REALPART_EXPR)
1064 expr = TREE_OPERAND (expr, 0);
1065 partial_ref = true;
1067 else
1068 partial_ref = false;
1070 /* We need to dive through V_C_Es in order to get the size of its parameter
1071 and not the result type. Ada produces such statements. We are also
1072 capable of handling the topmost V_C_E but not any of those buried in other
1073 handled components. */
1074 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
1075 expr = TREE_OPERAND (expr, 0);
1077 if (contains_view_convert_expr_p (expr))
1079 disqualify_base_of_expr (expr, "V_C_E under a different handled "
1080 "component.");
1081 return NULL;
1084 switch (TREE_CODE (expr))
1086 case MEM_REF:
1087 if (TREE_CODE (TREE_OPERAND (expr, 0)) != ADDR_EXPR
1088 && sra_mode != SRA_MODE_EARLY_IPA)
1089 return NULL;
1090 /* fall through */
1091 case VAR_DECL:
1092 case PARM_DECL:
1093 case RESULT_DECL:
1094 case COMPONENT_REF:
1095 case ARRAY_REF:
1096 case ARRAY_RANGE_REF:
1097 ret = create_access (expr, stmt, write);
1098 break;
1100 default:
1101 break;
1104 if (write && partial_ref && ret)
1105 ret->grp_partial_lhs = 1;
1107 return ret;
1110 /* Scan expression EXPR and create access structures for all accesses to
1111 candidates for scalarization. Return true if any access has been inserted.
1112 STMT must be the statement from which the expression is taken, WRITE must be
1113 true if the expression is a store and false otherwise. */
1115 static bool
1116 build_access_from_expr (tree expr, gimple stmt, bool write)
1118 struct access *access;
1120 access = build_access_from_expr_1 (expr, stmt, write);
1121 if (access)
1123 /* This means the aggregate is accesses as a whole in a way other than an
1124 assign statement and thus cannot be removed even if we had a scalar
1125 replacement for everything. */
1126 if (cannot_scalarize_away_bitmap)
1127 bitmap_set_bit (cannot_scalarize_away_bitmap, DECL_UID (access->base));
1128 return true;
1130 return false;
1133 /* Disqualify LHS and RHS for scalarization if STMT must end its basic block in
1134 modes in which it matters, return true iff they have been disqualified. RHS
1135 may be NULL, in that case ignore it. If we scalarize an aggregate in
1136 intra-SRA we may need to add statements after each statement. This is not
1137 possible if a statement unconditionally has to end the basic block. */
1138 static bool
1139 disqualify_ops_if_throwing_stmt (gimple stmt, tree lhs, tree rhs)
1141 if ((sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
1142 && (stmt_can_throw_internal (stmt) || stmt_ends_bb_p (stmt)))
1144 disqualify_base_of_expr (lhs, "LHS of a throwing stmt.");
1145 if (rhs)
1146 disqualify_base_of_expr (rhs, "RHS of a throwing stmt.");
1147 return true;
1149 return false;
1152 /* Scan expressions occurring in STMT, create access structures for all accesses
1153 to candidates for scalarization and remove those candidates which occur in
1154 statements or expressions that prevent them from being split apart. Return
1155 true if any access has been inserted. */
1157 static bool
1158 build_accesses_from_assign (gimple stmt)
1160 tree lhs, rhs;
1161 struct access *lacc, *racc;
1163 if (!gimple_assign_single_p (stmt)
1164 /* Scope clobbers don't influence scalarization. */
1165 || gimple_clobber_p (stmt))
1166 return false;
1168 lhs = gimple_assign_lhs (stmt);
1169 rhs = gimple_assign_rhs1 (stmt);
1171 if (disqualify_ops_if_throwing_stmt (stmt, lhs, rhs))
1172 return false;
1174 racc = build_access_from_expr_1 (rhs, stmt, false);
1175 lacc = build_access_from_expr_1 (lhs, stmt, true);
1177 if (lacc)
1178 lacc->grp_assignment_write = 1;
1180 if (racc)
1182 racc->grp_assignment_read = 1;
1183 if (should_scalarize_away_bitmap && !gimple_has_volatile_ops (stmt)
1184 && !is_gimple_reg_type (racc->type))
1185 bitmap_set_bit (should_scalarize_away_bitmap, DECL_UID (racc->base));
1188 if (lacc && racc
1189 && (sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
1190 && !lacc->grp_unscalarizable_region
1191 && !racc->grp_unscalarizable_region
1192 && AGGREGATE_TYPE_P (TREE_TYPE (lhs))
1193 && lacc->size == racc->size
1194 && useless_type_conversion_p (lacc->type, racc->type))
1196 struct assign_link *link;
1198 link = (struct assign_link *) pool_alloc (link_pool);
1199 memset (link, 0, sizeof (struct assign_link));
1201 link->lacc = lacc;
1202 link->racc = racc;
1204 add_link_to_rhs (racc, link);
1207 return lacc || racc;
1210 /* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine
1211 GIMPLE_ASM operands with memory constrains which cannot be scalarized. */
1213 static bool
1214 asm_visit_addr (gimple stmt ATTRIBUTE_UNUSED, tree op,
1215 void *data ATTRIBUTE_UNUSED)
1217 op = get_base_address (op);
1218 if (op
1219 && DECL_P (op))
1220 disqualify_candidate (op, "Non-scalarizable GIMPLE_ASM operand.");
1222 return false;
1225 /* Return true iff callsite CALL has at least as many actual arguments as there
1226 are formal parameters of the function currently processed by IPA-SRA. */
1228 static inline bool
1229 callsite_has_enough_arguments_p (gimple call)
1231 return gimple_call_num_args (call) >= (unsigned) func_param_count;
1234 /* Scan function and look for interesting expressions and create access
1235 structures for them. Return true iff any access is created. */
1237 static bool
1238 scan_function (void)
1240 basic_block bb;
1241 bool ret = false;
1243 FOR_EACH_BB (bb)
1245 gimple_stmt_iterator gsi;
1246 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1248 gimple stmt = gsi_stmt (gsi);
1249 tree t;
1250 unsigned i;
1252 if (final_bbs && stmt_can_throw_external (stmt))
1253 bitmap_set_bit (final_bbs, bb->index);
1254 switch (gimple_code (stmt))
1256 case GIMPLE_RETURN:
1257 t = gimple_return_retval (stmt);
1258 if (t != NULL_TREE)
1259 ret |= build_access_from_expr (t, stmt, false);
1260 if (final_bbs)
1261 bitmap_set_bit (final_bbs, bb->index);
1262 break;
1264 case GIMPLE_ASSIGN:
1265 ret |= build_accesses_from_assign (stmt);
1266 break;
1268 case GIMPLE_CALL:
1269 for (i = 0; i < gimple_call_num_args (stmt); i++)
1270 ret |= build_access_from_expr (gimple_call_arg (stmt, i),
1271 stmt, false);
1273 if (sra_mode == SRA_MODE_EARLY_IPA)
1275 tree dest = gimple_call_fndecl (stmt);
1276 int flags = gimple_call_flags (stmt);
1278 if (dest)
1280 if (DECL_BUILT_IN_CLASS (dest) == BUILT_IN_NORMAL
1281 && DECL_FUNCTION_CODE (dest) == BUILT_IN_APPLY_ARGS)
1282 encountered_apply_args = true;
1283 if (recursive_call_p (current_function_decl, dest))
1285 encountered_recursive_call = true;
1286 if (!callsite_has_enough_arguments_p (stmt))
1287 encountered_unchangable_recursive_call = true;
1291 if (final_bbs
1292 && (flags & (ECF_CONST | ECF_PURE)) == 0)
1293 bitmap_set_bit (final_bbs, bb->index);
1296 t = gimple_call_lhs (stmt);
1297 if (t && !disqualify_ops_if_throwing_stmt (stmt, t, NULL))
1298 ret |= build_access_from_expr (t, stmt, true);
1299 break;
1301 case GIMPLE_ASM:
1302 walk_stmt_load_store_addr_ops (stmt, NULL, NULL, NULL,
1303 asm_visit_addr);
1304 if (final_bbs)
1305 bitmap_set_bit (final_bbs, bb->index);
1307 for (i = 0; i < gimple_asm_ninputs (stmt); i++)
1309 t = TREE_VALUE (gimple_asm_input_op (stmt, i));
1310 ret |= build_access_from_expr (t, stmt, false);
1312 for (i = 0; i < gimple_asm_noutputs (stmt); i++)
1314 t = TREE_VALUE (gimple_asm_output_op (stmt, i));
1315 ret |= build_access_from_expr (t, stmt, true);
1317 break;
1319 default:
1320 break;
1325 return ret;
1328 /* Helper of QSORT function. There are pointers to accesses in the array. An
1329 access is considered smaller than another if it has smaller offset or if the
1330 offsets are the same but is size is bigger. */
1332 static int
1333 compare_access_positions (const void *a, const void *b)
1335 const access_p *fp1 = (const access_p *) a;
1336 const access_p *fp2 = (const access_p *) b;
1337 const access_p f1 = *fp1;
1338 const access_p f2 = *fp2;
1340 if (f1->offset != f2->offset)
1341 return f1->offset < f2->offset ? -1 : 1;
1343 if (f1->size == f2->size)
1345 if (f1->type == f2->type)
1346 return 0;
1347 /* Put any non-aggregate type before any aggregate type. */
1348 else if (!is_gimple_reg_type (f1->type)
1349 && is_gimple_reg_type (f2->type))
1350 return 1;
1351 else if (is_gimple_reg_type (f1->type)
1352 && !is_gimple_reg_type (f2->type))
1353 return -1;
1354 /* Put any complex or vector type before any other scalar type. */
1355 else if (TREE_CODE (f1->type) != COMPLEX_TYPE
1356 && TREE_CODE (f1->type) != VECTOR_TYPE
1357 && (TREE_CODE (f2->type) == COMPLEX_TYPE
1358 || TREE_CODE (f2->type) == VECTOR_TYPE))
1359 return 1;
1360 else if ((TREE_CODE (f1->type) == COMPLEX_TYPE
1361 || TREE_CODE (f1->type) == VECTOR_TYPE)
1362 && TREE_CODE (f2->type) != COMPLEX_TYPE
1363 && TREE_CODE (f2->type) != VECTOR_TYPE)
1364 return -1;
1365 /* Put the integral type with the bigger precision first. */
1366 else if (INTEGRAL_TYPE_P (f1->type)
1367 && INTEGRAL_TYPE_P (f2->type))
1368 return TYPE_PRECISION (f2->type) - TYPE_PRECISION (f1->type);
1369 /* Put any integral type with non-full precision last. */
1370 else if (INTEGRAL_TYPE_P (f1->type)
1371 && (TREE_INT_CST_LOW (TYPE_SIZE (f1->type))
1372 != TYPE_PRECISION (f1->type)))
1373 return 1;
1374 else if (INTEGRAL_TYPE_P (f2->type)
1375 && (TREE_INT_CST_LOW (TYPE_SIZE (f2->type))
1376 != TYPE_PRECISION (f2->type)))
1377 return -1;
1378 /* Stabilize the sort. */
1379 return TYPE_UID (f1->type) - TYPE_UID (f2->type);
1382 /* We want the bigger accesses first, thus the opposite operator in the next
1383 line: */
1384 return f1->size > f2->size ? -1 : 1;
1388 /* Append a name of the declaration to the name obstack. A helper function for
1389 make_fancy_name. */
1391 static void
1392 make_fancy_decl_name (tree decl)
1394 char buffer[32];
1396 tree name = DECL_NAME (decl);
1397 if (name)
1398 obstack_grow (&name_obstack, IDENTIFIER_POINTER (name),
1399 IDENTIFIER_LENGTH (name));
1400 else
1402 sprintf (buffer, "D%u", DECL_UID (decl));
1403 obstack_grow (&name_obstack, buffer, strlen (buffer));
1407 /* Helper for make_fancy_name. */
1409 static void
1410 make_fancy_name_1 (tree expr)
1412 char buffer[32];
1413 tree index;
1415 if (DECL_P (expr))
1417 make_fancy_decl_name (expr);
1418 return;
1421 switch (TREE_CODE (expr))
1423 case COMPONENT_REF:
1424 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1425 obstack_1grow (&name_obstack, '$');
1426 make_fancy_decl_name (TREE_OPERAND (expr, 1));
1427 break;
1429 case ARRAY_REF:
1430 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1431 obstack_1grow (&name_obstack, '$');
1432 /* Arrays with only one element may not have a constant as their
1433 index. */
1434 index = TREE_OPERAND (expr, 1);
1435 if (TREE_CODE (index) != INTEGER_CST)
1436 break;
1437 sprintf (buffer, HOST_WIDE_INT_PRINT_DEC, TREE_INT_CST_LOW (index));
1438 obstack_grow (&name_obstack, buffer, strlen (buffer));
1439 break;
1441 case ADDR_EXPR:
1442 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1443 break;
1445 case MEM_REF:
1446 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1447 if (!integer_zerop (TREE_OPERAND (expr, 1)))
1449 obstack_1grow (&name_obstack, '$');
1450 sprintf (buffer, HOST_WIDE_INT_PRINT_DEC,
1451 TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)));
1452 obstack_grow (&name_obstack, buffer, strlen (buffer));
1454 break;
1456 case BIT_FIELD_REF:
1457 case REALPART_EXPR:
1458 case IMAGPART_EXPR:
1459 gcc_unreachable (); /* we treat these as scalars. */
1460 break;
1461 default:
1462 break;
1466 /* Create a human readable name for replacement variable of ACCESS. */
1468 static char *
1469 make_fancy_name (tree expr)
1471 make_fancy_name_1 (expr);
1472 obstack_1grow (&name_obstack, '\0');
1473 return XOBFINISH (&name_obstack, char *);
1476 /* Construct a MEM_REF that would reference a part of aggregate BASE of type
1477 EXP_TYPE at the given OFFSET. If BASE is something for which
1478 get_addr_base_and_unit_offset returns NULL, gsi must be non-NULL and is used
1479 to insert new statements either before or below the current one as specified
1480 by INSERT_AFTER. This function is not capable of handling bitfields.
1482 BASE must be either a declaration or a memory reference that has correct
1483 alignment ifformation embeded in it (e.g. a pre-existing one in SRA). */
1485 tree
1486 build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset,
1487 tree exp_type, gimple_stmt_iterator *gsi,
1488 bool insert_after)
1490 tree prev_base = base;
1491 tree off;
1492 tree mem_ref;
1493 HOST_WIDE_INT base_offset;
1494 unsigned HOST_WIDE_INT misalign;
1495 unsigned int align;
1497 gcc_checking_assert (offset % BITS_PER_UNIT == 0);
1498 get_object_alignment_1 (base, &align, &misalign);
1499 base = get_addr_base_and_unit_offset (base, &base_offset);
1501 /* get_addr_base_and_unit_offset returns NULL for references with a variable
1502 offset such as array[var_index]. */
1503 if (!base)
1505 gimple stmt;
1506 tree tmp, addr;
1508 gcc_checking_assert (gsi);
1509 tmp = make_ssa_name (build_pointer_type (TREE_TYPE (prev_base)), NULL);
1510 addr = build_fold_addr_expr (unshare_expr (prev_base));
1511 STRIP_USELESS_TYPE_CONVERSION (addr);
1512 stmt = gimple_build_assign (tmp, addr);
1513 gimple_set_location (stmt, loc);
1514 if (insert_after)
1515 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
1516 else
1517 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
1519 off = build_int_cst (reference_alias_ptr_type (prev_base),
1520 offset / BITS_PER_UNIT);
1521 base = tmp;
1523 else if (TREE_CODE (base) == MEM_REF)
1525 off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
1526 base_offset + offset / BITS_PER_UNIT);
1527 off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
1528 base = unshare_expr (TREE_OPERAND (base, 0));
1530 else
1532 off = build_int_cst (reference_alias_ptr_type (base),
1533 base_offset + offset / BITS_PER_UNIT);
1534 base = build_fold_addr_expr (unshare_expr (base));
1537 misalign = (misalign + offset) & (align - 1);
1538 if (misalign != 0)
1539 align = (misalign & -misalign);
1540 if (align < TYPE_ALIGN (exp_type))
1541 exp_type = build_aligned_type (exp_type, align);
1543 mem_ref = fold_build2_loc (loc, MEM_REF, exp_type, base, off);
1544 if (TREE_THIS_VOLATILE (prev_base))
1545 TREE_THIS_VOLATILE (mem_ref) = 1;
1546 if (TREE_SIDE_EFFECTS (prev_base))
1547 TREE_SIDE_EFFECTS (mem_ref) = 1;
1548 return mem_ref;
1551 /* Construct a memory reference to a part of an aggregate BASE at the given
1552 OFFSET and of the same type as MODEL. In case this is a reference to a
1553 bit-field, the function will replicate the last component_ref of model's
1554 expr to access it. GSI and INSERT_AFTER have the same meaning as in
1555 build_ref_for_offset. */
1557 static tree
1558 build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
1559 struct access *model, gimple_stmt_iterator *gsi,
1560 bool insert_after)
1562 if (TREE_CODE (model->expr) == COMPONENT_REF
1563 && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
1565 /* This access represents a bit-field. */
1566 tree t, exp_type, fld = TREE_OPERAND (model->expr, 1);
1568 offset -= int_bit_position (fld);
1569 exp_type = TREE_TYPE (TREE_OPERAND (model->expr, 0));
1570 t = build_ref_for_offset (loc, base, offset, exp_type, gsi, insert_after);
1571 return fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (fld), t, fld,
1572 NULL_TREE);
1574 else
1575 return build_ref_for_offset (loc, base, offset, model->type,
1576 gsi, insert_after);
1579 /* Attempt to build a memory reference that we could but into a gimple
1580 debug_bind statement. Similar to build_ref_for_model but punts if it has to
1581 create statements and return s NULL instead. This function also ignores
1582 alignment issues and so its results should never end up in non-debug
1583 statements. */
1585 static tree
1586 build_debug_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
1587 struct access *model)
1589 HOST_WIDE_INT base_offset;
1590 tree off;
1592 if (TREE_CODE (model->expr) == COMPONENT_REF
1593 && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
1594 return NULL_TREE;
1596 base = get_addr_base_and_unit_offset (base, &base_offset);
1597 if (!base)
1598 return NULL_TREE;
1599 if (TREE_CODE (base) == MEM_REF)
1601 off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
1602 base_offset + offset / BITS_PER_UNIT);
1603 off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
1604 base = unshare_expr (TREE_OPERAND (base, 0));
1606 else
1608 off = build_int_cst (reference_alias_ptr_type (base),
1609 base_offset + offset / BITS_PER_UNIT);
1610 base = build_fold_addr_expr (unshare_expr (base));
1613 return fold_build2_loc (loc, MEM_REF, model->type, base, off);
1616 /* Construct a memory reference consisting of component_refs and array_refs to
1617 a part of an aggregate *RES (which is of type TYPE). The requested part
1618 should have type EXP_TYPE at be the given OFFSET. This function might not
1619 succeed, it returns true when it does and only then *RES points to something
1620 meaningful. This function should be used only to build expressions that we
1621 might need to present to user (e.g. in warnings). In all other situations,
1622 build_ref_for_model or build_ref_for_offset should be used instead. */
1624 static bool
1625 build_user_friendly_ref_for_offset (tree *res, tree type, HOST_WIDE_INT offset,
1626 tree exp_type)
1628 while (1)
1630 tree fld;
1631 tree tr_size, index, minidx;
1632 HOST_WIDE_INT el_size;
1634 if (offset == 0 && exp_type
1635 && types_compatible_p (exp_type, type))
1636 return true;
1638 switch (TREE_CODE (type))
1640 case UNION_TYPE:
1641 case QUAL_UNION_TYPE:
1642 case RECORD_TYPE:
1643 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
1645 HOST_WIDE_INT pos, size;
1646 tree tr_pos, expr, *expr_ptr;
1648 if (TREE_CODE (fld) != FIELD_DECL)
1649 continue;
1651 tr_pos = bit_position (fld);
1652 if (!tr_pos || !host_integerp (tr_pos, 1))
1653 continue;
1654 pos = TREE_INT_CST_LOW (tr_pos);
1655 gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0);
1656 tr_size = DECL_SIZE (fld);
1657 if (!tr_size || !host_integerp (tr_size, 1))
1658 continue;
1659 size = TREE_INT_CST_LOW (tr_size);
1660 if (size == 0)
1662 if (pos != offset)
1663 continue;
1665 else if (pos > offset || (pos + size) <= offset)
1666 continue;
1668 expr = build3 (COMPONENT_REF, TREE_TYPE (fld), *res, fld,
1669 NULL_TREE);
1670 expr_ptr = &expr;
1671 if (build_user_friendly_ref_for_offset (expr_ptr, TREE_TYPE (fld),
1672 offset - pos, exp_type))
1674 *res = expr;
1675 return true;
1678 return false;
1680 case ARRAY_TYPE:
1681 tr_size = TYPE_SIZE (TREE_TYPE (type));
1682 if (!tr_size || !host_integerp (tr_size, 1))
1683 return false;
1684 el_size = tree_low_cst (tr_size, 1);
1686 minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
1687 if (TREE_CODE (minidx) != INTEGER_CST || el_size == 0)
1688 return false;
1689 index = build_int_cst (TYPE_DOMAIN (type), offset / el_size);
1690 if (!integer_zerop (minidx))
1691 index = int_const_binop (PLUS_EXPR, index, minidx);
1692 *res = build4 (ARRAY_REF, TREE_TYPE (type), *res, index,
1693 NULL_TREE, NULL_TREE);
1694 offset = offset % el_size;
1695 type = TREE_TYPE (type);
1696 break;
1698 default:
1699 if (offset != 0)
1700 return false;
1702 if (exp_type)
1703 return false;
1704 else
1705 return true;
1710 /* Return true iff TYPE is stdarg va_list type. */
1712 static inline bool
1713 is_va_list_type (tree type)
1715 return TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (va_list_type_node);
1718 /* Print message to dump file why a variable was rejected. */
1720 static void
1721 reject (tree var, const char *msg)
1723 if (dump_file && (dump_flags & TDF_DETAILS))
1725 fprintf (dump_file, "Rejected (%d): %s: ", DECL_UID (var), msg);
1726 print_generic_expr (dump_file, var, 0);
1727 fprintf (dump_file, "\n");
1731 /* Return true if VAR is a candidate for SRA. */
1733 static bool
1734 maybe_add_sra_candidate (tree var)
1736 tree type = TREE_TYPE (var);
1737 const char *msg;
1738 tree_node **slot;
1740 if (!AGGREGATE_TYPE_P (type))
1742 reject (var, "not aggregate");
1743 return false;
1745 if (needs_to_live_in_memory (var))
1747 reject (var, "needs to live in memory");
1748 return false;
1750 if (TREE_THIS_VOLATILE (var))
1752 reject (var, "is volatile");
1753 return false;
1755 if (!COMPLETE_TYPE_P (type))
1757 reject (var, "has incomplete type");
1758 return false;
1760 if (!host_integerp (TYPE_SIZE (type), 1))
1762 reject (var, "type size not fixed");
1763 return false;
1765 if (tree_low_cst (TYPE_SIZE (type), 1) == 0)
1767 reject (var, "type size is zero");
1768 return false;
1770 if (type_internals_preclude_sra_p (type, &msg))
1772 reject (var, msg);
1773 return false;
1775 if (/* Fix for PR 41089. tree-stdarg.c needs to have va_lists intact but
1776 we also want to schedule it rather late. Thus we ignore it in
1777 the early pass. */
1778 (sra_mode == SRA_MODE_EARLY_INTRA
1779 && is_va_list_type (type)))
1781 reject (var, "is va_list");
1782 return false;
1785 bitmap_set_bit (candidate_bitmap, DECL_UID (var));
1786 slot = candidates.find_slot_with_hash (var, DECL_UID (var), INSERT);
1787 *slot = var;
1789 if (dump_file && (dump_flags & TDF_DETAILS))
1791 fprintf (dump_file, "Candidate (%d): ", DECL_UID (var));
1792 print_generic_expr (dump_file, var, 0);
1793 fprintf (dump_file, "\n");
1796 return true;
1799 /* The very first phase of intraprocedural SRA. It marks in candidate_bitmap
1800 those with type which is suitable for scalarization. */
1802 static bool
1803 find_var_candidates (void)
1805 tree var, parm;
1806 unsigned int i;
1807 bool ret = false;
1809 for (parm = DECL_ARGUMENTS (current_function_decl);
1810 parm;
1811 parm = DECL_CHAIN (parm))
1812 ret |= maybe_add_sra_candidate (parm);
1814 FOR_EACH_LOCAL_DECL (cfun, i, var)
1816 if (TREE_CODE (var) != VAR_DECL)
1817 continue;
1819 ret |= maybe_add_sra_candidate (var);
1822 return ret;
1825 /* Sort all accesses for the given variable, check for partial overlaps and
1826 return NULL if there are any. If there are none, pick a representative for
1827 each combination of offset and size and create a linked list out of them.
1828 Return the pointer to the first representative and make sure it is the first
1829 one in the vector of accesses. */
1831 static struct access *
1832 sort_and_splice_var_accesses (tree var)
1834 int i, j, access_count;
1835 struct access *res, **prev_acc_ptr = &res;
1836 vec<access_p> *access_vec;
1837 bool first = true;
1838 HOST_WIDE_INT low = -1, high = 0;
1840 access_vec = get_base_access_vector (var);
1841 if (!access_vec)
1842 return NULL;
1843 access_count = access_vec->length ();
1845 /* Sort by <OFFSET, SIZE>. */
1846 access_vec->qsort (compare_access_positions);
1848 i = 0;
1849 while (i < access_count)
1851 struct access *access = (*access_vec)[i];
1852 bool grp_write = access->write;
1853 bool grp_read = !access->write;
1854 bool grp_scalar_write = access->write
1855 && is_gimple_reg_type (access->type);
1856 bool grp_scalar_read = !access->write
1857 && is_gimple_reg_type (access->type);
1858 bool grp_assignment_read = access->grp_assignment_read;
1859 bool grp_assignment_write = access->grp_assignment_write;
1860 bool multiple_scalar_reads = false;
1861 bool total_scalarization = access->grp_total_scalarization;
1862 bool grp_partial_lhs = access->grp_partial_lhs;
1863 bool first_scalar = is_gimple_reg_type (access->type);
1864 bool unscalarizable_region = access->grp_unscalarizable_region;
1866 if (first || access->offset >= high)
1868 first = false;
1869 low = access->offset;
1870 high = access->offset + access->size;
1872 else if (access->offset > low && access->offset + access->size > high)
1873 return NULL;
1874 else
1875 gcc_assert (access->offset >= low
1876 && access->offset + access->size <= high);
1878 j = i + 1;
1879 while (j < access_count)
1881 struct access *ac2 = (*access_vec)[j];
1882 if (ac2->offset != access->offset || ac2->size != access->size)
1883 break;
1884 if (ac2->write)
1886 grp_write = true;
1887 grp_scalar_write = (grp_scalar_write
1888 || is_gimple_reg_type (ac2->type));
1890 else
1892 grp_read = true;
1893 if (is_gimple_reg_type (ac2->type))
1895 if (grp_scalar_read)
1896 multiple_scalar_reads = true;
1897 else
1898 grp_scalar_read = true;
1901 grp_assignment_read |= ac2->grp_assignment_read;
1902 grp_assignment_write |= ac2->grp_assignment_write;
1903 grp_partial_lhs |= ac2->grp_partial_lhs;
1904 unscalarizable_region |= ac2->grp_unscalarizable_region;
1905 total_scalarization |= ac2->grp_total_scalarization;
1906 relink_to_new_repr (access, ac2);
1908 /* If there are both aggregate-type and scalar-type accesses with
1909 this combination of size and offset, the comparison function
1910 should have put the scalars first. */
1911 gcc_assert (first_scalar || !is_gimple_reg_type (ac2->type));
1912 ac2->group_representative = access;
1913 j++;
1916 i = j;
1918 access->group_representative = access;
1919 access->grp_write = grp_write;
1920 access->grp_read = grp_read;
1921 access->grp_scalar_read = grp_scalar_read;
1922 access->grp_scalar_write = grp_scalar_write;
1923 access->grp_assignment_read = grp_assignment_read;
1924 access->grp_assignment_write = grp_assignment_write;
1925 access->grp_hint = multiple_scalar_reads || total_scalarization;
1926 access->grp_total_scalarization = total_scalarization;
1927 access->grp_partial_lhs = grp_partial_lhs;
1928 access->grp_unscalarizable_region = unscalarizable_region;
1929 if (access->first_link)
1930 add_access_to_work_queue (access);
1932 *prev_acc_ptr = access;
1933 prev_acc_ptr = &access->next_grp;
1936 gcc_assert (res == (*access_vec)[0]);
1937 return res;
1940 /* Create a variable for the given ACCESS which determines the type, name and a
1941 few other properties. Return the variable declaration and store it also to
1942 ACCESS->replacement. */
1944 static tree
1945 create_access_replacement (struct access *access)
1947 tree repl;
1949 if (access->grp_to_be_debug_replaced)
1951 repl = create_tmp_var_raw (access->type, NULL);
1952 DECL_CONTEXT (repl) = current_function_decl;
1954 else
1955 repl = create_tmp_var (access->type, "SR");
1956 if (TREE_CODE (access->type) == COMPLEX_TYPE
1957 || TREE_CODE (access->type) == VECTOR_TYPE)
1959 if (!access->grp_partial_lhs)
1960 DECL_GIMPLE_REG_P (repl) = 1;
1962 else if (access->grp_partial_lhs
1963 && is_gimple_reg_type (access->type))
1964 TREE_ADDRESSABLE (repl) = 1;
1966 DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base);
1967 DECL_ARTIFICIAL (repl) = 1;
1968 DECL_IGNORED_P (repl) = DECL_IGNORED_P (access->base);
1970 if (DECL_NAME (access->base)
1971 && !DECL_IGNORED_P (access->base)
1972 && !DECL_ARTIFICIAL (access->base))
1974 char *pretty_name = make_fancy_name (access->expr);
1975 tree debug_expr = unshare_expr_without_location (access->expr), d;
1976 bool fail = false;
1978 DECL_NAME (repl) = get_identifier (pretty_name);
1979 obstack_free (&name_obstack, pretty_name);
1981 /* Get rid of any SSA_NAMEs embedded in debug_expr,
1982 as DECL_DEBUG_EXPR isn't considered when looking for still
1983 used SSA_NAMEs and thus they could be freed. All debug info
1984 generation cares is whether something is constant or variable
1985 and that get_ref_base_and_extent works properly on the
1986 expression. It cannot handle accesses at a non-constant offset
1987 though, so just give up in those cases. */
1988 for (d = debug_expr;
1989 !fail && (handled_component_p (d) || TREE_CODE (d) == MEM_REF);
1990 d = TREE_OPERAND (d, 0))
1991 switch (TREE_CODE (d))
1993 case ARRAY_REF:
1994 case ARRAY_RANGE_REF:
1995 if (TREE_OPERAND (d, 1)
1996 && TREE_CODE (TREE_OPERAND (d, 1)) != INTEGER_CST)
1997 fail = true;
1998 if (TREE_OPERAND (d, 3)
1999 && TREE_CODE (TREE_OPERAND (d, 3)) != INTEGER_CST)
2000 fail = true;
2001 /* FALLTHRU */
2002 case COMPONENT_REF:
2003 if (TREE_OPERAND (d, 2)
2004 && TREE_CODE (TREE_OPERAND (d, 2)) != INTEGER_CST)
2005 fail = true;
2006 break;
2007 case MEM_REF:
2008 if (TREE_CODE (TREE_OPERAND (d, 0)) != ADDR_EXPR)
2009 fail = true;
2010 else
2011 d = TREE_OPERAND (d, 0);
2012 break;
2013 default:
2014 break;
2016 if (!fail)
2018 SET_DECL_DEBUG_EXPR (repl, debug_expr);
2019 DECL_HAS_DEBUG_EXPR_P (repl) = 1;
2021 if (access->grp_no_warning)
2022 TREE_NO_WARNING (repl) = 1;
2023 else
2024 TREE_NO_WARNING (repl) = TREE_NO_WARNING (access->base);
2026 else
2027 TREE_NO_WARNING (repl) = 1;
2029 if (dump_file)
2031 if (access->grp_to_be_debug_replaced)
2033 fprintf (dump_file, "Created a debug-only replacement for ");
2034 print_generic_expr (dump_file, access->base, 0);
2035 fprintf (dump_file, " offset: %u, size: %u\n",
2036 (unsigned) access->offset, (unsigned) access->size);
2038 else
2040 fprintf (dump_file, "Created a replacement for ");
2041 print_generic_expr (dump_file, access->base, 0);
2042 fprintf (dump_file, " offset: %u, size: %u: ",
2043 (unsigned) access->offset, (unsigned) access->size);
2044 print_generic_expr (dump_file, repl, 0);
2045 fprintf (dump_file, "\n");
2048 sra_stats.replacements++;
2050 return repl;
2053 /* Return ACCESS scalar replacement, create it if it does not exist yet. */
2055 static inline tree
2056 get_access_replacement (struct access *access)
2058 gcc_checking_assert (access->replacement_decl);
2059 return access->replacement_decl;
2063 /* Build a subtree of accesses rooted in *ACCESS, and move the pointer in the
2064 linked list along the way. Stop when *ACCESS is NULL or the access pointed
2065 to it is not "within" the root. Return false iff some accesses partially
2066 overlap. */
2068 static bool
2069 build_access_subtree (struct access **access)
2071 struct access *root = *access, *last_child = NULL;
2072 HOST_WIDE_INT limit = root->offset + root->size;
2074 *access = (*access)->next_grp;
2075 while (*access && (*access)->offset + (*access)->size <= limit)
2077 if (!last_child)
2078 root->first_child = *access;
2079 else
2080 last_child->next_sibling = *access;
2081 last_child = *access;
2083 if (!build_access_subtree (access))
2084 return false;
2087 if (*access && (*access)->offset < limit)
2088 return false;
2090 return true;
2093 /* Build a tree of access representatives, ACCESS is the pointer to the first
2094 one, others are linked in a list by the next_grp field. Return false iff
2095 some accesses partially overlap. */
2097 static bool
2098 build_access_trees (struct access *access)
2100 while (access)
2102 struct access *root = access;
2104 if (!build_access_subtree (&access))
2105 return false;
2106 root->next_grp = access;
2108 return true;
2111 /* Return true if expr contains some ARRAY_REFs into a variable bounded
2112 array. */
2114 static bool
2115 expr_with_var_bounded_array_refs_p (tree expr)
2117 while (handled_component_p (expr))
2119 if (TREE_CODE (expr) == ARRAY_REF
2120 && !host_integerp (array_ref_low_bound (expr), 0))
2121 return true;
2122 expr = TREE_OPERAND (expr, 0);
2124 return false;
2127 /* Analyze the subtree of accesses rooted in ROOT, scheduling replacements when
2128 both seeming beneficial and when ALLOW_REPLACEMENTS allows it. Also set all
2129 sorts of access flags appropriately along the way, notably always set
2130 grp_read and grp_assign_read according to MARK_READ and grp_write when
2131 MARK_WRITE is true.
2133 Creating a replacement for a scalar access is considered beneficial if its
2134 grp_hint is set (this means we are either attempting total scalarization or
2135 there is more than one direct read access) or according to the following
2136 table:
2138 Access written to through a scalar type (once or more times)
2140 | Written to in an assignment statement
2142 | | Access read as scalar _once_
2143 | | |
2144 | | | Read in an assignment statement
2145 | | | |
2146 | | | | Scalarize Comment
2147 -----------------------------------------------------------------------------
2148 0 0 0 0 No access for the scalar
2149 0 0 0 1 No access for the scalar
2150 0 0 1 0 No Single read - won't help
2151 0 0 1 1 No The same case
2152 0 1 0 0 No access for the scalar
2153 0 1 0 1 No access for the scalar
2154 0 1 1 0 Yes s = *g; return s.i;
2155 0 1 1 1 Yes The same case as above
2156 1 0 0 0 No Won't help
2157 1 0 0 1 Yes s.i = 1; *g = s;
2158 1 0 1 0 Yes s.i = 5; g = s.i;
2159 1 0 1 1 Yes The same case as above
2160 1 1 0 0 No Won't help.
2161 1 1 0 1 Yes s.i = 1; *g = s;
2162 1 1 1 0 Yes s = *g; return s.i;
2163 1 1 1 1 Yes Any of the above yeses */
2165 static bool
2166 analyze_access_subtree (struct access *root, struct access *parent,
2167 bool allow_replacements)
2169 struct access *child;
2170 HOST_WIDE_INT limit = root->offset + root->size;
2171 HOST_WIDE_INT covered_to = root->offset;
2172 bool scalar = is_gimple_reg_type (root->type);
2173 bool hole = false, sth_created = false;
2175 if (parent)
2177 if (parent->grp_read)
2178 root->grp_read = 1;
2179 if (parent->grp_assignment_read)
2180 root->grp_assignment_read = 1;
2181 if (parent->grp_write)
2182 root->grp_write = 1;
2183 if (parent->grp_assignment_write)
2184 root->grp_assignment_write = 1;
2185 if (parent->grp_total_scalarization)
2186 root->grp_total_scalarization = 1;
2189 if (root->grp_unscalarizable_region)
2190 allow_replacements = false;
2192 if (allow_replacements && expr_with_var_bounded_array_refs_p (root->expr))
2193 allow_replacements = false;
2195 for (child = root->first_child; child; child = child->next_sibling)
2197 hole |= covered_to < child->offset;
2198 sth_created |= analyze_access_subtree (child, root,
2199 allow_replacements && !scalar);
2201 root->grp_unscalarized_data |= child->grp_unscalarized_data;
2202 root->grp_total_scalarization &= child->grp_total_scalarization;
2203 if (child->grp_covered)
2204 covered_to += child->size;
2205 else
2206 hole = true;
2209 if (allow_replacements && scalar && !root->first_child
2210 && (root->grp_hint
2211 || ((root->grp_scalar_read || root->grp_assignment_read)
2212 && (root->grp_scalar_write || root->grp_assignment_write))))
2214 /* Always create access replacements that cover the whole access.
2215 For integral types this means the precision has to match.
2216 Avoid assumptions based on the integral type kind, too. */
2217 if (INTEGRAL_TYPE_P (root->type)
2218 && (TREE_CODE (root->type) != INTEGER_TYPE
2219 || TYPE_PRECISION (root->type) != root->size)
2220 /* But leave bitfield accesses alone. */
2221 && (TREE_CODE (root->expr) != COMPONENT_REF
2222 || !DECL_BIT_FIELD (TREE_OPERAND (root->expr, 1))))
2224 tree rt = root->type;
2225 gcc_assert ((root->offset % BITS_PER_UNIT) == 0
2226 && (root->size % BITS_PER_UNIT) == 0);
2227 root->type = build_nonstandard_integer_type (root->size,
2228 TYPE_UNSIGNED (rt));
2229 root->expr = build_ref_for_offset (UNKNOWN_LOCATION,
2230 root->base, root->offset,
2231 root->type, NULL, false);
2233 if (dump_file && (dump_flags & TDF_DETAILS))
2235 fprintf (dump_file, "Changing the type of a replacement for ");
2236 print_generic_expr (dump_file, root->base, 0);
2237 fprintf (dump_file, " offset: %u, size: %u ",
2238 (unsigned) root->offset, (unsigned) root->size);
2239 fprintf (dump_file, " to an integer.\n");
2243 root->grp_to_be_replaced = 1;
2244 root->replacement_decl = create_access_replacement (root);
2245 sth_created = true;
2246 hole = false;
2248 else
2250 if (allow_replacements
2251 && scalar && !root->first_child
2252 && (root->grp_scalar_write || root->grp_assignment_write)
2253 && !bitmap_bit_p (cannot_scalarize_away_bitmap,
2254 DECL_UID (root->base)))
2256 gcc_checking_assert (!root->grp_scalar_read
2257 && !root->grp_assignment_read);
2258 sth_created = true;
2259 if (MAY_HAVE_DEBUG_STMTS)
2261 root->grp_to_be_debug_replaced = 1;
2262 root->replacement_decl = create_access_replacement (root);
2266 if (covered_to < limit)
2267 hole = true;
2268 if (scalar)
2269 root->grp_total_scalarization = 0;
2272 if (!hole || root->grp_total_scalarization)
2273 root->grp_covered = 1;
2274 else if (root->grp_write || TREE_CODE (root->base) == PARM_DECL)
2275 root->grp_unscalarized_data = 1; /* not covered and written to */
2276 return sth_created;
2279 /* Analyze all access trees linked by next_grp by the means of
2280 analyze_access_subtree. */
2281 static bool
2282 analyze_access_trees (struct access *access)
2284 bool ret = false;
2286 while (access)
2288 if (analyze_access_subtree (access, NULL, true))
2289 ret = true;
2290 access = access->next_grp;
2293 return ret;
2296 /* Return true iff a potential new child of LACC at offset OFFSET and with size
2297 SIZE would conflict with an already existing one. If exactly such a child
2298 already exists in LACC, store a pointer to it in EXACT_MATCH. */
2300 static bool
2301 child_would_conflict_in_lacc (struct access *lacc, HOST_WIDE_INT norm_offset,
2302 HOST_WIDE_INT size, struct access **exact_match)
2304 struct access *child;
2306 for (child = lacc->first_child; child; child = child->next_sibling)
2308 if (child->offset == norm_offset && child->size == size)
2310 *exact_match = child;
2311 return true;
2314 if (child->offset < norm_offset + size
2315 && child->offset + child->size > norm_offset)
2316 return true;
2319 return false;
2322 /* Create a new child access of PARENT, with all properties just like MODEL
2323 except for its offset and with its grp_write false and grp_read true.
2324 Return the new access or NULL if it cannot be created. Note that this access
2325 is created long after all splicing and sorting, it's not located in any
2326 access vector and is automatically a representative of its group. */
2328 static struct access *
2329 create_artificial_child_access (struct access *parent, struct access *model,
2330 HOST_WIDE_INT new_offset)
2332 struct access *access;
2333 struct access **child;
2334 tree expr = parent->base;
2336 gcc_assert (!model->grp_unscalarizable_region);
2338 access = (struct access *) pool_alloc (access_pool);
2339 memset (access, 0, sizeof (struct access));
2340 if (!build_user_friendly_ref_for_offset (&expr, TREE_TYPE (expr), new_offset,
2341 model->type))
2343 access->grp_no_warning = true;
2344 expr = build_ref_for_model (EXPR_LOCATION (parent->base), parent->base,
2345 new_offset, model, NULL, false);
2348 access->base = parent->base;
2349 access->expr = expr;
2350 access->offset = new_offset;
2351 access->size = model->size;
2352 access->type = model->type;
2353 access->grp_write = true;
2354 access->grp_read = false;
2356 child = &parent->first_child;
2357 while (*child && (*child)->offset < new_offset)
2358 child = &(*child)->next_sibling;
2360 access->next_sibling = *child;
2361 *child = access;
2363 return access;
2367 /* Propagate all subaccesses of RACC across an assignment link to LACC. Return
2368 true if any new subaccess was created. Additionally, if RACC is a scalar
2369 access but LACC is not, change the type of the latter, if possible. */
2371 static bool
2372 propagate_subaccesses_across_link (struct access *lacc, struct access *racc)
2374 struct access *rchild;
2375 HOST_WIDE_INT norm_delta = lacc->offset - racc->offset;
2376 bool ret = false;
2378 if (is_gimple_reg_type (lacc->type)
2379 || lacc->grp_unscalarizable_region
2380 || racc->grp_unscalarizable_region)
2381 return false;
2383 if (is_gimple_reg_type (racc->type))
2385 if (!lacc->first_child && !racc->first_child)
2387 tree t = lacc->base;
2389 lacc->type = racc->type;
2390 if (build_user_friendly_ref_for_offset (&t, TREE_TYPE (t),
2391 lacc->offset, racc->type))
2392 lacc->expr = t;
2393 else
2395 lacc->expr = build_ref_for_model (EXPR_LOCATION (lacc->base),
2396 lacc->base, lacc->offset,
2397 racc, NULL, false);
2398 lacc->grp_no_warning = true;
2401 return false;
2404 for (rchild = racc->first_child; rchild; rchild = rchild->next_sibling)
2406 struct access *new_acc = NULL;
2407 HOST_WIDE_INT norm_offset = rchild->offset + norm_delta;
2409 if (rchild->grp_unscalarizable_region)
2410 continue;
2412 if (child_would_conflict_in_lacc (lacc, norm_offset, rchild->size,
2413 &new_acc))
2415 if (new_acc)
2417 rchild->grp_hint = 1;
2418 new_acc->grp_hint |= new_acc->grp_read;
2419 if (rchild->first_child)
2420 ret |= propagate_subaccesses_across_link (new_acc, rchild);
2422 continue;
2425 rchild->grp_hint = 1;
2426 new_acc = create_artificial_child_access (lacc, rchild, norm_offset);
2427 if (new_acc)
2429 ret = true;
2430 if (racc->first_child)
2431 propagate_subaccesses_across_link (new_acc, rchild);
2435 return ret;
2438 /* Propagate all subaccesses across assignment links. */
2440 static void
2441 propagate_all_subaccesses (void)
2443 while (work_queue_head)
2445 struct access *racc = pop_access_from_work_queue ();
2446 struct assign_link *link;
2448 gcc_assert (racc->first_link);
2450 for (link = racc->first_link; link; link = link->next)
2452 struct access *lacc = link->lacc;
2454 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
2455 continue;
2456 lacc = lacc->group_representative;
2457 if (propagate_subaccesses_across_link (lacc, racc)
2458 && lacc->first_link)
2459 add_access_to_work_queue (lacc);
2464 /* Go through all accesses collected throughout the (intraprocedural) analysis
2465 stage, exclude overlapping ones, identify representatives and build trees
2466 out of them, making decisions about scalarization on the way. Return true
2467 iff there are any to-be-scalarized variables after this stage. */
2469 static bool
2470 analyze_all_variable_accesses (void)
2472 int res = 0;
2473 bitmap tmp = BITMAP_ALLOC (NULL);
2474 bitmap_iterator bi;
2475 unsigned i, max_total_scalarization_size;
2477 max_total_scalarization_size = UNITS_PER_WORD * BITS_PER_UNIT
2478 * MOVE_RATIO (optimize_function_for_speed_p (cfun));
2480 EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
2481 if (bitmap_bit_p (should_scalarize_away_bitmap, i)
2482 && !bitmap_bit_p (cannot_scalarize_away_bitmap, i))
2484 tree var = candidate (i);
2486 if (TREE_CODE (var) == VAR_DECL
2487 && type_consists_of_records_p (TREE_TYPE (var)))
2489 if ((unsigned) tree_low_cst (TYPE_SIZE (TREE_TYPE (var)), 1)
2490 <= max_total_scalarization_size)
2492 completely_scalarize_var (var);
2493 if (dump_file && (dump_flags & TDF_DETAILS))
2495 fprintf (dump_file, "Will attempt to totally scalarize ");
2496 print_generic_expr (dump_file, var, 0);
2497 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
2500 else if (dump_file && (dump_flags & TDF_DETAILS))
2502 fprintf (dump_file, "Too big to totally scalarize: ");
2503 print_generic_expr (dump_file, var, 0);
2504 fprintf (dump_file, " (UID: %u)\n", DECL_UID (var));
2509 bitmap_copy (tmp, candidate_bitmap);
2510 EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
2512 tree var = candidate (i);
2513 struct access *access;
2515 access = sort_and_splice_var_accesses (var);
2516 if (!access || !build_access_trees (access))
2517 disqualify_candidate (var,
2518 "No or inhibitingly overlapping accesses.");
2521 propagate_all_subaccesses ();
2523 bitmap_copy (tmp, candidate_bitmap);
2524 EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
2526 tree var = candidate (i);
2527 struct access *access = get_first_repr_for_decl (var);
2529 if (analyze_access_trees (access))
2531 res++;
2532 if (dump_file && (dump_flags & TDF_DETAILS))
2534 fprintf (dump_file, "\nAccess trees for ");
2535 print_generic_expr (dump_file, var, 0);
2536 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
2537 dump_access_tree (dump_file, access);
2538 fprintf (dump_file, "\n");
2541 else
2542 disqualify_candidate (var, "No scalar replacements to be created.");
2545 BITMAP_FREE (tmp);
2547 if (res)
2549 statistics_counter_event (cfun, "Scalarized aggregates", res);
2550 return true;
2552 else
2553 return false;
2556 /* Generate statements copying scalar replacements of accesses within a subtree
2557 into or out of AGG. ACCESS, all its children, siblings and their children
2558 are to be processed. AGG is an aggregate type expression (can be a
2559 declaration but does not have to be, it can for example also be a mem_ref or
2560 a series of handled components). TOP_OFFSET is the offset of the processed
2561 subtree which has to be subtracted from offsets of individual accesses to
2562 get corresponding offsets for AGG. If CHUNK_SIZE is non-null, copy only
2563 replacements in the interval <start_offset, start_offset + chunk_size>,
2564 otherwise copy all. GSI is a statement iterator used to place the new
2565 statements. WRITE should be true when the statements should write from AGG
2566 to the replacement and false if vice versa. if INSERT_AFTER is true, new
2567 statements will be added after the current statement in GSI, they will be
2568 added before the statement otherwise. */
2570 static void
2571 generate_subtree_copies (struct access *access, tree agg,
2572 HOST_WIDE_INT top_offset,
2573 HOST_WIDE_INT start_offset, HOST_WIDE_INT chunk_size,
2574 gimple_stmt_iterator *gsi, bool write,
2575 bool insert_after, location_t loc)
2579 if (chunk_size && access->offset >= start_offset + chunk_size)
2580 return;
2582 if (access->grp_to_be_replaced
2583 && (chunk_size == 0
2584 || access->offset + access->size > start_offset))
2586 tree expr, repl = get_access_replacement (access);
2587 gimple stmt;
2589 expr = build_ref_for_model (loc, agg, access->offset - top_offset,
2590 access, gsi, insert_after);
2592 if (write)
2594 if (access->grp_partial_lhs)
2595 expr = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
2596 !insert_after,
2597 insert_after ? GSI_NEW_STMT
2598 : GSI_SAME_STMT);
2599 stmt = gimple_build_assign (repl, expr);
2601 else
2603 TREE_NO_WARNING (repl) = 1;
2604 if (access->grp_partial_lhs)
2605 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
2606 !insert_after,
2607 insert_after ? GSI_NEW_STMT
2608 : GSI_SAME_STMT);
2609 stmt = gimple_build_assign (expr, repl);
2611 gimple_set_location (stmt, loc);
2613 if (insert_after)
2614 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2615 else
2616 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2617 update_stmt (stmt);
2618 sra_stats.subtree_copies++;
2620 else if (write
2621 && access->grp_to_be_debug_replaced
2622 && (chunk_size == 0
2623 || access->offset + access->size > start_offset))
2625 gimple ds;
2626 tree drhs = build_debug_ref_for_model (loc, agg,
2627 access->offset - top_offset,
2628 access);
2629 ds = gimple_build_debug_bind (get_access_replacement (access),
2630 drhs, gsi_stmt (*gsi));
2631 if (insert_after)
2632 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
2633 else
2634 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
2637 if (access->first_child)
2638 generate_subtree_copies (access->first_child, agg, top_offset,
2639 start_offset, chunk_size, gsi,
2640 write, insert_after, loc);
2642 access = access->next_sibling;
2644 while (access);
2647 /* Assign zero to all scalar replacements in an access subtree. ACCESS is the
2648 the root of the subtree to be processed. GSI is the statement iterator used
2649 for inserting statements which are added after the current statement if
2650 INSERT_AFTER is true or before it otherwise. */
2652 static void
2653 init_subtree_with_zero (struct access *access, gimple_stmt_iterator *gsi,
2654 bool insert_after, location_t loc)
2657 struct access *child;
2659 if (access->grp_to_be_replaced)
2661 gimple stmt;
2663 stmt = gimple_build_assign (get_access_replacement (access),
2664 build_zero_cst (access->type));
2665 if (insert_after)
2666 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2667 else
2668 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2669 update_stmt (stmt);
2670 gimple_set_location (stmt, loc);
2672 else if (access->grp_to_be_debug_replaced)
2674 gimple ds = gimple_build_debug_bind (get_access_replacement (access),
2675 build_zero_cst (access->type),
2676 gsi_stmt (*gsi));
2677 if (insert_after)
2678 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
2679 else
2680 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
2683 for (child = access->first_child; child; child = child->next_sibling)
2684 init_subtree_with_zero (child, gsi, insert_after, loc);
2687 /* Search for an access representative for the given expression EXPR and
2688 return it or NULL if it cannot be found. */
2690 static struct access *
2691 get_access_for_expr (tree expr)
2693 HOST_WIDE_INT offset, size, max_size;
2694 tree base;
2696 /* FIXME: This should not be necessary but Ada produces V_C_Es with a type of
2697 a different size than the size of its argument and we need the latter
2698 one. */
2699 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
2700 expr = TREE_OPERAND (expr, 0);
2702 base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
2703 if (max_size == -1 || !DECL_P (base))
2704 return NULL;
2706 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
2707 return NULL;
2709 return get_var_base_offset_size_access (base, offset, max_size);
2712 /* Replace the expression EXPR with a scalar replacement if there is one and
2713 generate other statements to do type conversion or subtree copying if
2714 necessary. GSI is used to place newly created statements, WRITE is true if
2715 the expression is being written to (it is on a LHS of a statement or output
2716 in an assembly statement). */
2718 static bool
2719 sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
2721 location_t loc;
2722 struct access *access;
2723 tree type, bfr;
2725 if (TREE_CODE (*expr) == BIT_FIELD_REF)
2727 bfr = *expr;
2728 expr = &TREE_OPERAND (*expr, 0);
2730 else
2731 bfr = NULL_TREE;
2733 if (TREE_CODE (*expr) == REALPART_EXPR || TREE_CODE (*expr) == IMAGPART_EXPR)
2734 expr = &TREE_OPERAND (*expr, 0);
2735 access = get_access_for_expr (*expr);
2736 if (!access)
2737 return false;
2738 type = TREE_TYPE (*expr);
2740 loc = gimple_location (gsi_stmt (*gsi));
2741 if (access->grp_to_be_replaced)
2743 tree repl = get_access_replacement (access);
2744 /* If we replace a non-register typed access simply use the original
2745 access expression to extract the scalar component afterwards.
2746 This happens if scalarizing a function return value or parameter
2747 like in gcc.c-torture/execute/20041124-1.c, 20050316-1.c and
2748 gcc.c-torture/compile/20011217-1.c.
2750 We also want to use this when accessing a complex or vector which can
2751 be accessed as a different type too, potentially creating a need for
2752 type conversion (see PR42196) and when scalarized unions are involved
2753 in assembler statements (see PR42398). */
2754 if (!useless_type_conversion_p (type, access->type))
2756 tree ref;
2758 ref = build_ref_for_model (loc, access->base, access->offset, access,
2759 NULL, false);
2761 if (write)
2763 gimple stmt;
2765 if (access->grp_partial_lhs)
2766 ref = force_gimple_operand_gsi (gsi, ref, true, NULL_TREE,
2767 false, GSI_NEW_STMT);
2768 stmt = gimple_build_assign (repl, ref);
2769 gimple_set_location (stmt, loc);
2770 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2772 else
2774 gimple stmt;
2776 if (access->grp_partial_lhs)
2777 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
2778 true, GSI_SAME_STMT);
2779 stmt = gimple_build_assign (ref, repl);
2780 gimple_set_location (stmt, loc);
2781 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2784 else
2785 *expr = repl;
2786 sra_stats.exprs++;
2788 else if (write && access->grp_to_be_debug_replaced)
2790 gimple ds = gimple_build_debug_bind (get_access_replacement (access),
2791 NULL_TREE,
2792 gsi_stmt (*gsi));
2793 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
2796 if (access->first_child)
2798 HOST_WIDE_INT start_offset, chunk_size;
2799 if (bfr
2800 && host_integerp (TREE_OPERAND (bfr, 1), 1)
2801 && host_integerp (TREE_OPERAND (bfr, 2), 1))
2803 chunk_size = tree_low_cst (TREE_OPERAND (bfr, 1), 1);
2804 start_offset = access->offset
2805 + tree_low_cst (TREE_OPERAND (bfr, 2), 1);
2807 else
2808 start_offset = chunk_size = 0;
2810 generate_subtree_copies (access->first_child, access->base, 0,
2811 start_offset, chunk_size, gsi, write, write,
2812 loc);
2814 return true;
2817 /* Where scalar replacements of the RHS have been written to when a replacement
2818 of a LHS of an assigments cannot be direclty loaded from a replacement of
2819 the RHS. */
2820 enum unscalarized_data_handling { SRA_UDH_NONE, /* Nothing done so far. */
2821 SRA_UDH_RIGHT, /* Data flushed to the RHS. */
2822 SRA_UDH_LEFT }; /* Data flushed to the LHS. */
2824 /* Store all replacements in the access tree rooted in TOP_RACC either to their
2825 base aggregate if there are unscalarized data or directly to LHS of the
2826 statement that is pointed to by GSI otherwise. */
2828 static enum unscalarized_data_handling
2829 handle_unscalarized_data_in_subtree (struct access *top_racc,
2830 gimple_stmt_iterator *gsi)
2832 if (top_racc->grp_unscalarized_data)
2834 generate_subtree_copies (top_racc->first_child, top_racc->base, 0, 0, 0,
2835 gsi, false, false,
2836 gimple_location (gsi_stmt (*gsi)));
2837 return SRA_UDH_RIGHT;
2839 else
2841 tree lhs = gimple_assign_lhs (gsi_stmt (*gsi));
2842 generate_subtree_copies (top_racc->first_child, lhs, top_racc->offset,
2843 0, 0, gsi, false, false,
2844 gimple_location (gsi_stmt (*gsi)));
2845 return SRA_UDH_LEFT;
2850 /* Try to generate statements to load all sub-replacements in an access subtree
2851 formed by children of LACC from scalar replacements in the TOP_RACC subtree.
2852 If that is not possible, refresh the TOP_RACC base aggregate and load the
2853 accesses from it. LEFT_OFFSET is the offset of the left whole subtree being
2854 copied. NEW_GSI is stmt iterator used for statement insertions after the
2855 original assignment, OLD_GSI is used to insert statements before the
2856 assignment. *REFRESHED keeps the information whether we have needed to
2857 refresh replacements of the LHS and from which side of the assignments this
2858 takes place. */
2860 static void
2861 load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc,
2862 HOST_WIDE_INT left_offset,
2863 gimple_stmt_iterator *old_gsi,
2864 gimple_stmt_iterator *new_gsi,
2865 enum unscalarized_data_handling *refreshed)
2867 location_t loc = gimple_location (gsi_stmt (*old_gsi));
2868 for (lacc = lacc->first_child; lacc; lacc = lacc->next_sibling)
2870 HOST_WIDE_INT offset = lacc->offset - left_offset + top_racc->offset;
2872 if (lacc->grp_to_be_replaced)
2874 struct access *racc;
2875 gimple stmt;
2876 tree rhs;
2878 racc = find_access_in_subtree (top_racc, offset, lacc->size);
2879 if (racc && racc->grp_to_be_replaced)
2881 rhs = get_access_replacement (racc);
2882 if (!useless_type_conversion_p (lacc->type, racc->type))
2883 rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, lacc->type, rhs);
2885 if (racc->grp_partial_lhs && lacc->grp_partial_lhs)
2886 rhs = force_gimple_operand_gsi (old_gsi, rhs, true, NULL_TREE,
2887 true, GSI_SAME_STMT);
2889 else
2891 /* No suitable access on the right hand side, need to load from
2892 the aggregate. See if we have to update it first... */
2893 if (*refreshed == SRA_UDH_NONE)
2894 *refreshed = handle_unscalarized_data_in_subtree (top_racc,
2895 old_gsi);
2897 if (*refreshed == SRA_UDH_LEFT)
2898 rhs = build_ref_for_model (loc, lacc->base, lacc->offset, lacc,
2899 new_gsi, true);
2900 else
2901 rhs = build_ref_for_model (loc, top_racc->base, offset, lacc,
2902 new_gsi, true);
2903 if (lacc->grp_partial_lhs)
2904 rhs = force_gimple_operand_gsi (new_gsi, rhs, true, NULL_TREE,
2905 false, GSI_NEW_STMT);
2908 stmt = gimple_build_assign (get_access_replacement (lacc), rhs);
2909 gsi_insert_after (new_gsi, stmt, GSI_NEW_STMT);
2910 gimple_set_location (stmt, loc);
2911 update_stmt (stmt);
2912 sra_stats.subreplacements++;
2914 else
2916 if (*refreshed == SRA_UDH_NONE
2917 && lacc->grp_read && !lacc->grp_covered)
2918 *refreshed = handle_unscalarized_data_in_subtree (top_racc,
2919 old_gsi);
2920 if (lacc && lacc->grp_to_be_debug_replaced)
2922 gimple ds;
2923 tree drhs;
2924 struct access *racc = find_access_in_subtree (top_racc, offset,
2925 lacc->size);
2927 if (racc && racc->grp_to_be_replaced)
2929 if (racc->grp_write)
2930 drhs = get_access_replacement (racc);
2931 else
2932 drhs = NULL;
2934 else if (*refreshed == SRA_UDH_LEFT)
2935 drhs = build_debug_ref_for_model (loc, lacc->base, lacc->offset,
2936 lacc);
2937 else if (*refreshed == SRA_UDH_RIGHT)
2938 drhs = build_debug_ref_for_model (loc, top_racc->base, offset,
2939 lacc);
2940 else
2941 drhs = NULL_TREE;
2942 ds = gimple_build_debug_bind (get_access_replacement (lacc),
2943 drhs, gsi_stmt (*old_gsi));
2944 gsi_insert_after (new_gsi, ds, GSI_NEW_STMT);
2948 if (lacc->first_child)
2949 load_assign_lhs_subreplacements (lacc, top_racc, left_offset,
2950 old_gsi, new_gsi, refreshed);
2954 /* Result code for SRA assignment modification. */
2955 enum assignment_mod_result { SRA_AM_NONE, /* nothing done for the stmt */
2956 SRA_AM_MODIFIED, /* stmt changed but not
2957 removed */
2958 SRA_AM_REMOVED }; /* stmt eliminated */
2960 /* Modify assignments with a CONSTRUCTOR on their RHS. STMT contains a pointer
2961 to the assignment and GSI is the statement iterator pointing at it. Returns
2962 the same values as sra_modify_assign. */
2964 static enum assignment_mod_result
2965 sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
2967 tree lhs = gimple_assign_lhs (*stmt);
2968 struct access *acc;
2969 location_t loc;
2971 acc = get_access_for_expr (lhs);
2972 if (!acc)
2973 return SRA_AM_NONE;
2975 if (gimple_clobber_p (*stmt))
2977 /* Remove clobbers of fully scalarized variables, otherwise
2978 do nothing. */
2979 if (acc->grp_covered)
2981 unlink_stmt_vdef (*stmt);
2982 gsi_remove (gsi, true);
2983 release_defs (*stmt);
2984 return SRA_AM_REMOVED;
2986 else
2987 return SRA_AM_NONE;
2990 loc = gimple_location (*stmt);
2991 if (vec_safe_length (CONSTRUCTOR_ELTS (gimple_assign_rhs1 (*stmt))) > 0)
2993 /* I have never seen this code path trigger but if it can happen the
2994 following should handle it gracefully. */
2995 if (access_has_children_p (acc))
2996 generate_subtree_copies (acc->first_child, acc->base, 0, 0, 0, gsi,
2997 true, true, loc);
2998 return SRA_AM_MODIFIED;
3001 if (acc->grp_covered)
3003 init_subtree_with_zero (acc, gsi, false, loc);
3004 unlink_stmt_vdef (*stmt);
3005 gsi_remove (gsi, true);
3006 release_defs (*stmt);
3007 return SRA_AM_REMOVED;
3009 else
3011 init_subtree_with_zero (acc, gsi, true, loc);
3012 return SRA_AM_MODIFIED;
3016 /* Create and return a new suitable default definition SSA_NAME for RACC which
3017 is an access describing an uninitialized part of an aggregate that is being
3018 loaded. */
3020 static tree
3021 get_repl_default_def_ssa_name (struct access *racc)
3023 gcc_checking_assert (!racc->grp_to_be_replaced
3024 && !racc->grp_to_be_debug_replaced);
3025 if (!racc->replacement_decl)
3026 racc->replacement_decl = create_access_replacement (racc);
3027 return get_or_create_ssa_default_def (cfun, racc->replacement_decl);
3030 /* Return true if REF has an VIEW_CONVERT_EXPR or a COMPONENT_REF with a
3031 bit-field field declaration somewhere in it. */
3033 static inline bool
3034 contains_vce_or_bfcref_p (const_tree ref)
3036 while (handled_component_p (ref))
3038 if (TREE_CODE (ref) == VIEW_CONVERT_EXPR
3039 || (TREE_CODE (ref) == COMPONENT_REF
3040 && DECL_BIT_FIELD (TREE_OPERAND (ref, 1))))
3041 return true;
3042 ref = TREE_OPERAND (ref, 0);
3045 return false;
3048 /* Examine both sides of the assignment statement pointed to by STMT, replace
3049 them with a scalare replacement if there is one and generate copying of
3050 replacements if scalarized aggregates have been used in the assignment. GSI
3051 is used to hold generated statements for type conversions and subtree
3052 copying. */
3054 static enum assignment_mod_result
3055 sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi)
3057 struct access *lacc, *racc;
3058 tree lhs, rhs;
3059 bool modify_this_stmt = false;
3060 bool force_gimple_rhs = false;
3061 location_t loc;
3062 gimple_stmt_iterator orig_gsi = *gsi;
3064 if (!gimple_assign_single_p (*stmt))
3065 return SRA_AM_NONE;
3066 lhs = gimple_assign_lhs (*stmt);
3067 rhs = gimple_assign_rhs1 (*stmt);
3069 if (TREE_CODE (rhs) == CONSTRUCTOR)
3070 return sra_modify_constructor_assign (stmt, gsi);
3072 if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (lhs) == REALPART_EXPR
3073 || TREE_CODE (rhs) == IMAGPART_EXPR || TREE_CODE (lhs) == IMAGPART_EXPR
3074 || TREE_CODE (rhs) == BIT_FIELD_REF || TREE_CODE (lhs) == BIT_FIELD_REF)
3076 modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (*stmt),
3077 gsi, false);
3078 modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (*stmt),
3079 gsi, true);
3080 return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
3083 lacc = get_access_for_expr (lhs);
3084 racc = get_access_for_expr (rhs);
3085 if (!lacc && !racc)
3086 return SRA_AM_NONE;
3088 loc = gimple_location (*stmt);
3089 if (lacc && lacc->grp_to_be_replaced)
3091 lhs = get_access_replacement (lacc);
3092 gimple_assign_set_lhs (*stmt, lhs);
3093 modify_this_stmt = true;
3094 if (lacc->grp_partial_lhs)
3095 force_gimple_rhs = true;
3096 sra_stats.exprs++;
3099 if (racc && racc->grp_to_be_replaced)
3101 rhs = get_access_replacement (racc);
3102 modify_this_stmt = true;
3103 if (racc->grp_partial_lhs)
3104 force_gimple_rhs = true;
3105 sra_stats.exprs++;
3107 else if (racc
3108 && !racc->grp_unscalarized_data
3109 && TREE_CODE (lhs) == SSA_NAME
3110 && !access_has_replacements_p (racc))
3112 rhs = get_repl_default_def_ssa_name (racc);
3113 modify_this_stmt = true;
3114 sra_stats.exprs++;
3117 if (modify_this_stmt)
3119 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
3121 /* If we can avoid creating a VIEW_CONVERT_EXPR do so.
3122 ??? This should move to fold_stmt which we simply should
3123 call after building a VIEW_CONVERT_EXPR here. */
3124 if (AGGREGATE_TYPE_P (TREE_TYPE (lhs))
3125 && !contains_bitfld_component_ref_p (lhs))
3127 lhs = build_ref_for_model (loc, lhs, 0, racc, gsi, false);
3128 gimple_assign_set_lhs (*stmt, lhs);
3130 else if (AGGREGATE_TYPE_P (TREE_TYPE (rhs))
3131 && !contains_vce_or_bfcref_p (rhs))
3132 rhs = build_ref_for_model (loc, rhs, 0, lacc, gsi, false);
3134 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
3136 rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
3137 rhs);
3138 if (is_gimple_reg_type (TREE_TYPE (lhs))
3139 && TREE_CODE (lhs) != SSA_NAME)
3140 force_gimple_rhs = true;
3145 if (lacc && lacc->grp_to_be_debug_replaced)
3147 tree dlhs = get_access_replacement (lacc);
3148 tree drhs = unshare_expr (rhs);
3149 if (!useless_type_conversion_p (TREE_TYPE (dlhs), TREE_TYPE (drhs)))
3151 if (AGGREGATE_TYPE_P (TREE_TYPE (drhs))
3152 && !contains_vce_or_bfcref_p (drhs))
3153 drhs = build_debug_ref_for_model (loc, drhs, 0, lacc);
3154 if (drhs
3155 && !useless_type_conversion_p (TREE_TYPE (dlhs),
3156 TREE_TYPE (drhs)))
3157 drhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
3158 TREE_TYPE (dlhs), drhs);
3160 gimple ds = gimple_build_debug_bind (dlhs, drhs, *stmt);
3161 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
3164 /* From this point on, the function deals with assignments in between
3165 aggregates when at least one has scalar reductions of some of its
3166 components. There are three possible scenarios: Both the LHS and RHS have
3167 to-be-scalarized components, 2) only the RHS has or 3) only the LHS has.
3169 In the first case, we would like to load the LHS components from RHS
3170 components whenever possible. If that is not possible, we would like to
3171 read it directly from the RHS (after updating it by storing in it its own
3172 components). If there are some necessary unscalarized data in the LHS,
3173 those will be loaded by the original assignment too. If neither of these
3174 cases happen, the original statement can be removed. Most of this is done
3175 by load_assign_lhs_subreplacements.
3177 In the second case, we would like to store all RHS scalarized components
3178 directly into LHS and if they cover the aggregate completely, remove the
3179 statement too. In the third case, we want the LHS components to be loaded
3180 directly from the RHS (DSE will remove the original statement if it
3181 becomes redundant).
3183 This is a bit complex but manageable when types match and when unions do
3184 not cause confusion in a way that we cannot really load a component of LHS
3185 from the RHS or vice versa (the access representing this level can have
3186 subaccesses that are accessible only through a different union field at a
3187 higher level - different from the one used in the examined expression).
3188 Unions are fun.
3190 Therefore, I specially handle a fourth case, happening when there is a
3191 specific type cast or it is impossible to locate a scalarized subaccess on
3192 the other side of the expression. If that happens, I simply "refresh" the
3193 RHS by storing in it is scalarized components leave the original statement
3194 there to do the copying and then load the scalar replacements of the LHS.
3195 This is what the first branch does. */
3197 if (modify_this_stmt
3198 || gimple_has_volatile_ops (*stmt)
3199 || contains_vce_or_bfcref_p (rhs)
3200 || contains_vce_or_bfcref_p (lhs))
3202 if (access_has_children_p (racc))
3203 generate_subtree_copies (racc->first_child, racc->base, 0, 0, 0,
3204 gsi, false, false, loc);
3205 if (access_has_children_p (lacc))
3206 generate_subtree_copies (lacc->first_child, lacc->base, 0, 0, 0,
3207 gsi, true, true, loc);
3208 sra_stats.separate_lhs_rhs_handling++;
3210 /* This gimplification must be done after generate_subtree_copies,
3211 lest we insert the subtree copies in the middle of the gimplified
3212 sequence. */
3213 if (force_gimple_rhs)
3214 rhs = force_gimple_operand_gsi (&orig_gsi, rhs, true, NULL_TREE,
3215 true, GSI_SAME_STMT);
3216 if (gimple_assign_rhs1 (*stmt) != rhs)
3218 modify_this_stmt = true;
3219 gimple_assign_set_rhs_from_tree (&orig_gsi, rhs);
3220 gcc_assert (*stmt == gsi_stmt (orig_gsi));
3223 return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
3225 else
3227 if (access_has_children_p (lacc)
3228 && access_has_children_p (racc)
3229 /* When an access represents an unscalarizable region, it usually
3230 represents accesses with variable offset and thus must not be used
3231 to generate new memory accesses. */
3232 && !lacc->grp_unscalarizable_region
3233 && !racc->grp_unscalarizable_region)
3235 gimple_stmt_iterator orig_gsi = *gsi;
3236 enum unscalarized_data_handling refreshed;
3238 if (lacc->grp_read && !lacc->grp_covered)
3239 refreshed = handle_unscalarized_data_in_subtree (racc, gsi);
3240 else
3241 refreshed = SRA_UDH_NONE;
3243 load_assign_lhs_subreplacements (lacc, racc, lacc->offset,
3244 &orig_gsi, gsi, &refreshed);
3245 if (refreshed != SRA_UDH_RIGHT)
3247 gsi_next (gsi);
3248 unlink_stmt_vdef (*stmt);
3249 gsi_remove (&orig_gsi, true);
3250 release_defs (*stmt);
3251 sra_stats.deleted++;
3252 return SRA_AM_REMOVED;
3255 else
3257 if (access_has_children_p (racc)
3258 && !racc->grp_unscalarized_data)
3260 if (dump_file)
3262 fprintf (dump_file, "Removing load: ");
3263 print_gimple_stmt (dump_file, *stmt, 0, 0);
3265 generate_subtree_copies (racc->first_child, lhs,
3266 racc->offset, 0, 0, gsi,
3267 false, false, loc);
3268 gcc_assert (*stmt == gsi_stmt (*gsi));
3269 unlink_stmt_vdef (*stmt);
3270 gsi_remove (gsi, true);
3271 release_defs (*stmt);
3272 sra_stats.deleted++;
3273 return SRA_AM_REMOVED;
3275 /* Restore the aggregate RHS from its components so the
3276 prevailing aggregate copy does the right thing. */
3277 if (access_has_children_p (racc))
3278 generate_subtree_copies (racc->first_child, racc->base, 0, 0, 0,
3279 gsi, false, false, loc);
3280 /* Re-load the components of the aggregate copy destination.
3281 But use the RHS aggregate to load from to expose more
3282 optimization opportunities. */
3283 if (access_has_children_p (lacc))
3284 generate_subtree_copies (lacc->first_child, rhs, lacc->offset,
3285 0, 0, gsi, true, true, loc);
3288 return SRA_AM_NONE;
3292 /* Traverse the function body and all modifications as decided in
3293 analyze_all_variable_accesses. Return true iff the CFG has been
3294 changed. */
3296 static bool
3297 sra_modify_function_body (void)
3299 bool cfg_changed = false;
3300 basic_block bb;
3302 FOR_EACH_BB (bb)
3304 gimple_stmt_iterator gsi = gsi_start_bb (bb);
3305 while (!gsi_end_p (gsi))
3307 gimple stmt = gsi_stmt (gsi);
3308 enum assignment_mod_result assign_result;
3309 bool modified = false, deleted = false;
3310 tree *t;
3311 unsigned i;
3313 switch (gimple_code (stmt))
3315 case GIMPLE_RETURN:
3316 t = gimple_return_retval_ptr (stmt);
3317 if (*t != NULL_TREE)
3318 modified |= sra_modify_expr (t, &gsi, false);
3319 break;
3321 case GIMPLE_ASSIGN:
3322 assign_result = sra_modify_assign (&stmt, &gsi);
3323 modified |= assign_result == SRA_AM_MODIFIED;
3324 deleted = assign_result == SRA_AM_REMOVED;
3325 break;
3327 case GIMPLE_CALL:
3328 /* Operands must be processed before the lhs. */
3329 for (i = 0; i < gimple_call_num_args (stmt); i++)
3331 t = gimple_call_arg_ptr (stmt, i);
3332 modified |= sra_modify_expr (t, &gsi, false);
3335 if (gimple_call_lhs (stmt))
3337 t = gimple_call_lhs_ptr (stmt);
3338 modified |= sra_modify_expr (t, &gsi, true);
3340 break;
3342 case GIMPLE_ASM:
3343 for (i = 0; i < gimple_asm_ninputs (stmt); i++)
3345 t = &TREE_VALUE (gimple_asm_input_op (stmt, i));
3346 modified |= sra_modify_expr (t, &gsi, false);
3348 for (i = 0; i < gimple_asm_noutputs (stmt); i++)
3350 t = &TREE_VALUE (gimple_asm_output_op (stmt, i));
3351 modified |= sra_modify_expr (t, &gsi, true);
3353 break;
3355 default:
3356 break;
3359 if (modified)
3361 update_stmt (stmt);
3362 if (maybe_clean_eh_stmt (stmt)
3363 && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
3364 cfg_changed = true;
3366 if (!deleted)
3367 gsi_next (&gsi);
3371 return cfg_changed;
3374 /* Generate statements initializing scalar replacements of parts of function
3375 parameters. */
3377 static void
3378 initialize_parameter_reductions (void)
3380 gimple_stmt_iterator gsi;
3381 gimple_seq seq = NULL;
3382 tree parm;
3384 gsi = gsi_start (seq);
3385 for (parm = DECL_ARGUMENTS (current_function_decl);
3386 parm;
3387 parm = DECL_CHAIN (parm))
3389 vec<access_p> *access_vec;
3390 struct access *access;
3392 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
3393 continue;
3394 access_vec = get_base_access_vector (parm);
3395 if (!access_vec)
3396 continue;
3398 for (access = (*access_vec)[0];
3399 access;
3400 access = access->next_grp)
3401 generate_subtree_copies (access, parm, 0, 0, 0, &gsi, true, true,
3402 EXPR_LOCATION (parm));
3405 seq = gsi_seq (gsi);
3406 if (seq)
3407 gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR), seq);
3410 /* The "main" function of intraprocedural SRA passes. Runs the analysis and if
3411 it reveals there are components of some aggregates to be scalarized, it runs
3412 the required transformations. */
3413 static unsigned int
3414 perform_intra_sra (void)
3416 int ret = 0;
3417 sra_initialize ();
3419 if (!find_var_candidates ())
3420 goto out;
3422 if (!scan_function ())
3423 goto out;
3425 if (!analyze_all_variable_accesses ())
3426 goto out;
3428 if (sra_modify_function_body ())
3429 ret = TODO_update_ssa | TODO_cleanup_cfg;
3430 else
3431 ret = TODO_update_ssa;
3432 initialize_parameter_reductions ();
3434 statistics_counter_event (cfun, "Scalar replacements created",
3435 sra_stats.replacements);
3436 statistics_counter_event (cfun, "Modified expressions", sra_stats.exprs);
3437 statistics_counter_event (cfun, "Subtree copy stmts",
3438 sra_stats.subtree_copies);
3439 statistics_counter_event (cfun, "Subreplacement stmts",
3440 sra_stats.subreplacements);
3441 statistics_counter_event (cfun, "Deleted stmts", sra_stats.deleted);
3442 statistics_counter_event (cfun, "Separate LHS and RHS handling",
3443 sra_stats.separate_lhs_rhs_handling);
3445 out:
3446 sra_deinitialize ();
3447 return ret;
3450 /* Perform early intraprocedural SRA. */
3451 static unsigned int
3452 early_intra_sra (void)
3454 sra_mode = SRA_MODE_EARLY_INTRA;
3455 return perform_intra_sra ();
3458 /* Perform "late" intraprocedural SRA. */
3459 static unsigned int
3460 late_intra_sra (void)
3462 sra_mode = SRA_MODE_INTRA;
3463 return perform_intra_sra ();
3467 static bool
3468 gate_intra_sra (void)
3470 return flag_tree_sra != 0 && dbg_cnt (tree_sra);
3474 namespace {
3476 const pass_data pass_data_sra_early =
3478 GIMPLE_PASS, /* type */
3479 "esra", /* name */
3480 OPTGROUP_NONE, /* optinfo_flags */
3481 true, /* has_gate */
3482 true, /* has_execute */
3483 TV_TREE_SRA, /* tv_id */
3484 ( PROP_cfg | PROP_ssa ), /* properties_required */
3485 0, /* properties_provided */
3486 0, /* properties_destroyed */
3487 0, /* todo_flags_start */
3488 ( TODO_update_ssa | TODO_verify_ssa ), /* todo_flags_finish */
3491 class pass_sra_early : public gimple_opt_pass
3493 public:
3494 pass_sra_early (gcc::context *ctxt)
3495 : gimple_opt_pass (pass_data_sra_early, ctxt)
3498 /* opt_pass methods: */
3499 bool gate () { return gate_intra_sra (); }
3500 unsigned int execute () { return early_intra_sra (); }
3502 }; // class pass_sra_early
3504 } // anon namespace
3506 gimple_opt_pass *
3507 make_pass_sra_early (gcc::context *ctxt)
3509 return new pass_sra_early (ctxt);
3512 namespace {
3514 const pass_data pass_data_sra =
3516 GIMPLE_PASS, /* type */
3517 "sra", /* name */
3518 OPTGROUP_NONE, /* optinfo_flags */
3519 true, /* has_gate */
3520 true, /* has_execute */
3521 TV_TREE_SRA, /* tv_id */
3522 ( PROP_cfg | PROP_ssa ), /* properties_required */
3523 0, /* properties_provided */
3524 0, /* properties_destroyed */
3525 TODO_update_address_taken, /* todo_flags_start */
3526 ( TODO_update_ssa | TODO_verify_ssa ), /* todo_flags_finish */
3529 class pass_sra : public gimple_opt_pass
3531 public:
3532 pass_sra (gcc::context *ctxt)
3533 : gimple_opt_pass (pass_data_sra, ctxt)
3536 /* opt_pass methods: */
3537 bool gate () { return gate_intra_sra (); }
3538 unsigned int execute () { return late_intra_sra (); }
3540 }; // class pass_sra
3542 } // anon namespace
3544 gimple_opt_pass *
3545 make_pass_sra (gcc::context *ctxt)
3547 return new pass_sra (ctxt);
3551 /* Return true iff PARM (which must be a parm_decl) is an unused scalar
3552 parameter. */
3554 static bool
3555 is_unused_scalar_param (tree parm)
3557 tree name;
3558 return (is_gimple_reg (parm)
3559 && (!(name = ssa_default_def (cfun, parm))
3560 || has_zero_uses (name)));
3563 /* Scan immediate uses of a default definition SSA name of a parameter PARM and
3564 examine whether there are any direct or otherwise infeasible ones. If so,
3565 return true, otherwise return false. PARM must be a gimple register with a
3566 non-NULL default definition. */
3568 static bool
3569 ptr_parm_has_direct_uses (tree parm)
3571 imm_use_iterator ui;
3572 gimple stmt;
3573 tree name = ssa_default_def (cfun, parm);
3574 bool ret = false;
3576 FOR_EACH_IMM_USE_STMT (stmt, ui, name)
3578 int uses_ok = 0;
3579 use_operand_p use_p;
3581 if (is_gimple_debug (stmt))
3582 continue;
3584 /* Valid uses include dereferences on the lhs and the rhs. */
3585 if (gimple_has_lhs (stmt))
3587 tree lhs = gimple_get_lhs (stmt);
3588 while (handled_component_p (lhs))
3589 lhs = TREE_OPERAND (lhs, 0);
3590 if (TREE_CODE (lhs) == MEM_REF
3591 && TREE_OPERAND (lhs, 0) == name
3592 && integer_zerop (TREE_OPERAND (lhs, 1))
3593 && types_compatible_p (TREE_TYPE (lhs),
3594 TREE_TYPE (TREE_TYPE (name)))
3595 && !TREE_THIS_VOLATILE (lhs))
3596 uses_ok++;
3598 if (gimple_assign_single_p (stmt))
3600 tree rhs = gimple_assign_rhs1 (stmt);
3601 while (handled_component_p (rhs))
3602 rhs = TREE_OPERAND (rhs, 0);
3603 if (TREE_CODE (rhs) == MEM_REF
3604 && TREE_OPERAND (rhs, 0) == name
3605 && integer_zerop (TREE_OPERAND (rhs, 1))
3606 && types_compatible_p (TREE_TYPE (rhs),
3607 TREE_TYPE (TREE_TYPE (name)))
3608 && !TREE_THIS_VOLATILE (rhs))
3609 uses_ok++;
3611 else if (is_gimple_call (stmt))
3613 unsigned i;
3614 for (i = 0; i < gimple_call_num_args (stmt); ++i)
3616 tree arg = gimple_call_arg (stmt, i);
3617 while (handled_component_p (arg))
3618 arg = TREE_OPERAND (arg, 0);
3619 if (TREE_CODE (arg) == MEM_REF
3620 && TREE_OPERAND (arg, 0) == name
3621 && integer_zerop (TREE_OPERAND (arg, 1))
3622 && types_compatible_p (TREE_TYPE (arg),
3623 TREE_TYPE (TREE_TYPE (name)))
3624 && !TREE_THIS_VOLATILE (arg))
3625 uses_ok++;
3629 /* If the number of valid uses does not match the number of
3630 uses in this stmt there is an unhandled use. */
3631 FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
3632 --uses_ok;
3634 if (uses_ok != 0)
3635 ret = true;
3637 if (ret)
3638 BREAK_FROM_IMM_USE_STMT (ui);
3641 return ret;
3644 /* Identify candidates for reduction for IPA-SRA based on their type and mark
3645 them in candidate_bitmap. Note that these do not necessarily include
3646 parameter which are unused and thus can be removed. Return true iff any
3647 such candidate has been found. */
3649 static bool
3650 find_param_candidates (void)
3652 tree parm;
3653 int count = 0;
3654 bool ret = false;
3655 const char *msg;
3657 for (parm = DECL_ARGUMENTS (current_function_decl);
3658 parm;
3659 parm = DECL_CHAIN (parm))
3661 tree type = TREE_TYPE (parm);
3662 tree_node **slot;
3664 count++;
3666 if (TREE_THIS_VOLATILE (parm)
3667 || TREE_ADDRESSABLE (parm)
3668 || (!is_gimple_reg_type (type) && is_va_list_type (type)))
3669 continue;
3671 if (is_unused_scalar_param (parm))
3673 ret = true;
3674 continue;
3677 if (POINTER_TYPE_P (type))
3679 type = TREE_TYPE (type);
3681 if (TREE_CODE (type) == FUNCTION_TYPE
3682 || TYPE_VOLATILE (type)
3683 || (TREE_CODE (type) == ARRAY_TYPE
3684 && TYPE_NONALIASED_COMPONENT (type))
3685 || !is_gimple_reg (parm)
3686 || is_va_list_type (type)
3687 || ptr_parm_has_direct_uses (parm))
3688 continue;
3690 else if (!AGGREGATE_TYPE_P (type))
3691 continue;
3693 if (!COMPLETE_TYPE_P (type)
3694 || !host_integerp (TYPE_SIZE (type), 1)
3695 || tree_low_cst (TYPE_SIZE (type), 1) == 0
3696 || (AGGREGATE_TYPE_P (type)
3697 && type_internals_preclude_sra_p (type, &msg)))
3698 continue;
3700 bitmap_set_bit (candidate_bitmap, DECL_UID (parm));
3701 slot = candidates.find_slot_with_hash (parm, DECL_UID (parm), INSERT);
3702 *slot = parm;
3704 ret = true;
3705 if (dump_file && (dump_flags & TDF_DETAILS))
3707 fprintf (dump_file, "Candidate (%d): ", DECL_UID (parm));
3708 print_generic_expr (dump_file, parm, 0);
3709 fprintf (dump_file, "\n");
3713 func_param_count = count;
3714 return ret;
3717 /* Callback of walk_aliased_vdefs, marks the access passed as DATA as
3718 maybe_modified. */
3720 static bool
3721 mark_maybe_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
3722 void *data)
3724 struct access *repr = (struct access *) data;
3726 repr->grp_maybe_modified = 1;
3727 return true;
3730 /* Analyze what representatives (in linked lists accessible from
3731 REPRESENTATIVES) can be modified by side effects of statements in the
3732 current function. */
3734 static void
3735 analyze_modified_params (vec<access_p> representatives)
3737 int i;
3739 for (i = 0; i < func_param_count; i++)
3741 struct access *repr;
3743 for (repr = representatives[i];
3744 repr;
3745 repr = repr->next_grp)
3747 struct access *access;
3748 bitmap visited;
3749 ao_ref ar;
3751 if (no_accesses_p (repr))
3752 continue;
3753 if (!POINTER_TYPE_P (TREE_TYPE (repr->base))
3754 || repr->grp_maybe_modified)
3755 continue;
3757 ao_ref_init (&ar, repr->expr);
3758 visited = BITMAP_ALLOC (NULL);
3759 for (access = repr; access; access = access->next_sibling)
3761 /* All accesses are read ones, otherwise grp_maybe_modified would
3762 be trivially set. */
3763 walk_aliased_vdefs (&ar, gimple_vuse (access->stmt),
3764 mark_maybe_modified, repr, &visited);
3765 if (repr->grp_maybe_modified)
3766 break;
3768 BITMAP_FREE (visited);
3773 /* Propagate distances in bb_dereferences in the opposite direction than the
3774 control flow edges, in each step storing the maximum of the current value
3775 and the minimum of all successors. These steps are repeated until the table
3776 stabilizes. Note that BBs which might terminate the functions (according to
3777 final_bbs bitmap) never updated in this way. */
3779 static void
3780 propagate_dereference_distances (void)
3782 vec<basic_block> queue;
3783 basic_block bb;
3785 queue.create (last_basic_block_for_function (cfun));
3786 queue.quick_push (ENTRY_BLOCK_PTR);
3787 FOR_EACH_BB (bb)
3789 queue.quick_push (bb);
3790 bb->aux = bb;
3793 while (!queue.is_empty ())
3795 edge_iterator ei;
3796 edge e;
3797 bool change = false;
3798 int i;
3800 bb = queue.pop ();
3801 bb->aux = NULL;
3803 if (bitmap_bit_p (final_bbs, bb->index))
3804 continue;
3806 for (i = 0; i < func_param_count; i++)
3808 int idx = bb->index * func_param_count + i;
3809 bool first = true;
3810 HOST_WIDE_INT inh = 0;
3812 FOR_EACH_EDGE (e, ei, bb->succs)
3814 int succ_idx = e->dest->index * func_param_count + i;
3816 if (e->src == EXIT_BLOCK_PTR)
3817 continue;
3819 if (first)
3821 first = false;
3822 inh = bb_dereferences [succ_idx];
3824 else if (bb_dereferences [succ_idx] < inh)
3825 inh = bb_dereferences [succ_idx];
3828 if (!first && bb_dereferences[idx] < inh)
3830 bb_dereferences[idx] = inh;
3831 change = true;
3835 if (change && !bitmap_bit_p (final_bbs, bb->index))
3836 FOR_EACH_EDGE (e, ei, bb->preds)
3838 if (e->src->aux)
3839 continue;
3841 e->src->aux = e->src;
3842 queue.quick_push (e->src);
3846 queue.release ();
3849 /* Dump a dereferences TABLE with heading STR to file F. */
3851 static void
3852 dump_dereferences_table (FILE *f, const char *str, HOST_WIDE_INT *table)
3854 basic_block bb;
3856 fprintf (dump_file, str);
3857 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
3859 fprintf (f, "%4i %i ", bb->index, bitmap_bit_p (final_bbs, bb->index));
3860 if (bb != EXIT_BLOCK_PTR)
3862 int i;
3863 for (i = 0; i < func_param_count; i++)
3865 int idx = bb->index * func_param_count + i;
3866 fprintf (f, " %4" HOST_WIDE_INT_PRINT "d", table[idx]);
3869 fprintf (f, "\n");
3871 fprintf (dump_file, "\n");
3874 /* Determine what (parts of) parameters passed by reference that are not
3875 assigned to are not certainly dereferenced in this function and thus the
3876 dereferencing cannot be safely moved to the caller without potentially
3877 introducing a segfault. Mark such REPRESENTATIVES as
3878 grp_not_necessarilly_dereferenced.
3880 The dereferenced maximum "distance," i.e. the offset + size of the accessed
3881 part is calculated rather than simple booleans are calculated for each
3882 pointer parameter to handle cases when only a fraction of the whole
3883 aggregate is allocated (see testsuite/gcc.c-torture/execute/ipa-sra-2.c for
3884 an example).
3886 The maximum dereference distances for each pointer parameter and BB are
3887 already stored in bb_dereference. This routine simply propagates these
3888 values upwards by propagate_dereference_distances and then compares the
3889 distances of individual parameters in the ENTRY BB to the equivalent
3890 distances of each representative of a (fraction of a) parameter. */
3892 static void
3893 analyze_caller_dereference_legality (vec<access_p> representatives)
3895 int i;
3897 if (dump_file && (dump_flags & TDF_DETAILS))
3898 dump_dereferences_table (dump_file,
3899 "Dereference table before propagation:\n",
3900 bb_dereferences);
3902 propagate_dereference_distances ();
3904 if (dump_file && (dump_flags & TDF_DETAILS))
3905 dump_dereferences_table (dump_file,
3906 "Dereference table after propagation:\n",
3907 bb_dereferences);
3909 for (i = 0; i < func_param_count; i++)
3911 struct access *repr = representatives[i];
3912 int idx = ENTRY_BLOCK_PTR->index * func_param_count + i;
3914 if (!repr || no_accesses_p (repr))
3915 continue;
3919 if ((repr->offset + repr->size) > bb_dereferences[idx])
3920 repr->grp_not_necessarilly_dereferenced = 1;
3921 repr = repr->next_grp;
3923 while (repr);
3927 /* Return the representative access for the parameter declaration PARM if it is
3928 a scalar passed by reference which is not written to and the pointer value
3929 is not used directly. Thus, if it is legal to dereference it in the caller
3930 and we can rule out modifications through aliases, such parameter should be
3931 turned into one passed by value. Return NULL otherwise. */
3933 static struct access *
3934 unmodified_by_ref_scalar_representative (tree parm)
3936 int i, access_count;
3937 struct access *repr;
3938 vec<access_p> *access_vec;
3940 access_vec = get_base_access_vector (parm);
3941 gcc_assert (access_vec);
3942 repr = (*access_vec)[0];
3943 if (repr->write)
3944 return NULL;
3945 repr->group_representative = repr;
3947 access_count = access_vec->length ();
3948 for (i = 1; i < access_count; i++)
3950 struct access *access = (*access_vec)[i];
3951 if (access->write)
3952 return NULL;
3953 access->group_representative = repr;
3954 access->next_sibling = repr->next_sibling;
3955 repr->next_sibling = access;
3958 repr->grp_read = 1;
3959 repr->grp_scalar_ptr = 1;
3960 return repr;
3963 /* Return true iff this ACCESS precludes IPA-SRA of the parameter it is
3964 associated with. REQ_ALIGN is the minimum required alignment. */
3966 static bool
3967 access_precludes_ipa_sra_p (struct access *access, unsigned int req_align)
3969 unsigned int exp_align;
3970 /* Avoid issues such as the second simple testcase in PR 42025. The problem
3971 is incompatible assign in a call statement (and possibly even in asm
3972 statements). This can be relaxed by using a new temporary but only for
3973 non-TREE_ADDRESSABLE types and is probably not worth the complexity. (In
3974 intraprocedural SRA we deal with this by keeping the old aggregate around,
3975 something we cannot do in IPA-SRA.) */
3976 if (access->write
3977 && (is_gimple_call (access->stmt)
3978 || gimple_code (access->stmt) == GIMPLE_ASM))
3979 return true;
3981 exp_align = get_object_alignment (access->expr);
3982 if (exp_align < req_align)
3983 return true;
3985 return false;
3989 /* Sort collected accesses for parameter PARM, identify representatives for
3990 each accessed region and link them together. Return NULL if there are
3991 different but overlapping accesses, return the special ptr value meaning
3992 there are no accesses for this parameter if that is the case and return the
3993 first representative otherwise. Set *RO_GRP if there is a group of accesses
3994 with only read (i.e. no write) accesses. */
3996 static struct access *
3997 splice_param_accesses (tree parm, bool *ro_grp)
3999 int i, j, access_count, group_count;
4000 int agg_size, total_size = 0;
4001 struct access *access, *res, **prev_acc_ptr = &res;
4002 vec<access_p> *access_vec;
4004 access_vec = get_base_access_vector (parm);
4005 if (!access_vec)
4006 return &no_accesses_representant;
4007 access_count = access_vec->length ();
4009 access_vec->qsort (compare_access_positions);
4011 i = 0;
4012 total_size = 0;
4013 group_count = 0;
4014 while (i < access_count)
4016 bool modification;
4017 tree a1_alias_type;
4018 access = (*access_vec)[i];
4019 modification = access->write;
4020 if (access_precludes_ipa_sra_p (access, TYPE_ALIGN (access->type)))
4021 return NULL;
4022 a1_alias_type = reference_alias_ptr_type (access->expr);
4024 /* Access is about to become group representative unless we find some
4025 nasty overlap which would preclude us from breaking this parameter
4026 apart. */
4028 j = i + 1;
4029 while (j < access_count)
4031 struct access *ac2 = (*access_vec)[j];
4032 if (ac2->offset != access->offset)
4034 /* All or nothing law for parameters. */
4035 if (access->offset + access->size > ac2->offset)
4036 return NULL;
4037 else
4038 break;
4040 else if (ac2->size != access->size)
4041 return NULL;
4043 if (access_precludes_ipa_sra_p (ac2, TYPE_ALIGN (access->type))
4044 || (ac2->type != access->type
4045 && (TREE_ADDRESSABLE (ac2->type)
4046 || TREE_ADDRESSABLE (access->type)))
4047 || (reference_alias_ptr_type (ac2->expr) != a1_alias_type))
4048 return NULL;
4050 modification |= ac2->write;
4051 ac2->group_representative = access;
4052 ac2->next_sibling = access->next_sibling;
4053 access->next_sibling = ac2;
4054 j++;
4057 group_count++;
4058 access->grp_maybe_modified = modification;
4059 if (!modification)
4060 *ro_grp = true;
4061 *prev_acc_ptr = access;
4062 prev_acc_ptr = &access->next_grp;
4063 total_size += access->size;
4064 i = j;
4067 if (POINTER_TYPE_P (TREE_TYPE (parm)))
4068 agg_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))), 1);
4069 else
4070 agg_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (parm)), 1);
4071 if (total_size >= agg_size)
4072 return NULL;
4074 gcc_assert (group_count > 0);
4075 return res;
4078 /* Decide whether parameters with representative accesses given by REPR should
4079 be reduced into components. */
4081 static int
4082 decide_one_param_reduction (struct access *repr)
4084 int total_size, cur_parm_size, agg_size, new_param_count, parm_size_limit;
4085 bool by_ref;
4086 tree parm;
4088 parm = repr->base;
4089 cur_parm_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (parm)), 1);
4090 gcc_assert (cur_parm_size > 0);
4092 if (POINTER_TYPE_P (TREE_TYPE (parm)))
4094 by_ref = true;
4095 agg_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))), 1);
4097 else
4099 by_ref = false;
4100 agg_size = cur_parm_size;
4103 if (dump_file)
4105 struct access *acc;
4106 fprintf (dump_file, "Evaluating PARAM group sizes for ");
4107 print_generic_expr (dump_file, parm, 0);
4108 fprintf (dump_file, " (UID: %u): \n", DECL_UID (parm));
4109 for (acc = repr; acc; acc = acc->next_grp)
4110 dump_access (dump_file, acc, true);
4113 total_size = 0;
4114 new_param_count = 0;
4116 for (; repr; repr = repr->next_grp)
4118 gcc_assert (parm == repr->base);
4120 /* Taking the address of a non-addressable field is verboten. */
4121 if (by_ref && repr->non_addressable)
4122 return 0;
4124 /* Do not decompose a non-BLKmode param in a way that would
4125 create BLKmode params. Especially for by-reference passing
4126 (thus, pointer-type param) this is hardly worthwhile. */
4127 if (DECL_MODE (parm) != BLKmode
4128 && TYPE_MODE (repr->type) == BLKmode)
4129 return 0;
4131 if (!by_ref || (!repr->grp_maybe_modified
4132 && !repr->grp_not_necessarilly_dereferenced))
4133 total_size += repr->size;
4134 else
4135 total_size += cur_parm_size;
4137 new_param_count++;
4140 gcc_assert (new_param_count > 0);
4142 if (optimize_function_for_size_p (cfun))
4143 parm_size_limit = cur_parm_size;
4144 else
4145 parm_size_limit = (PARAM_VALUE (PARAM_IPA_SRA_PTR_GROWTH_FACTOR)
4146 * cur_parm_size);
4148 if (total_size < agg_size
4149 && total_size <= parm_size_limit)
4151 if (dump_file)
4152 fprintf (dump_file, " ....will be split into %i components\n",
4153 new_param_count);
4154 return new_param_count;
4156 else
4157 return 0;
4160 /* The order of the following enums is important, we need to do extra work for
4161 UNUSED_PARAMS, BY_VAL_ACCESSES and UNMODIF_BY_REF_ACCESSES. */
4162 enum ipa_splicing_result { NO_GOOD_ACCESS, UNUSED_PARAMS, BY_VAL_ACCESSES,
4163 MODIF_BY_REF_ACCESSES, UNMODIF_BY_REF_ACCESSES };
4165 /* Identify representatives of all accesses to all candidate parameters for
4166 IPA-SRA. Return result based on what representatives have been found. */
4168 static enum ipa_splicing_result
4169 splice_all_param_accesses (vec<access_p> &representatives)
4171 enum ipa_splicing_result result = NO_GOOD_ACCESS;
4172 tree parm;
4173 struct access *repr;
4175 representatives.create (func_param_count);
4177 for (parm = DECL_ARGUMENTS (current_function_decl);
4178 parm;
4179 parm = DECL_CHAIN (parm))
4181 if (is_unused_scalar_param (parm))
4183 representatives.quick_push (&no_accesses_representant);
4184 if (result == NO_GOOD_ACCESS)
4185 result = UNUSED_PARAMS;
4187 else if (POINTER_TYPE_P (TREE_TYPE (parm))
4188 && is_gimple_reg_type (TREE_TYPE (TREE_TYPE (parm)))
4189 && bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
4191 repr = unmodified_by_ref_scalar_representative (parm);
4192 representatives.quick_push (repr);
4193 if (repr)
4194 result = UNMODIF_BY_REF_ACCESSES;
4196 else if (bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
4198 bool ro_grp = false;
4199 repr = splice_param_accesses (parm, &ro_grp);
4200 representatives.quick_push (repr);
4202 if (repr && !no_accesses_p (repr))
4204 if (POINTER_TYPE_P (TREE_TYPE (parm)))
4206 if (ro_grp)
4207 result = UNMODIF_BY_REF_ACCESSES;
4208 else if (result < MODIF_BY_REF_ACCESSES)
4209 result = MODIF_BY_REF_ACCESSES;
4211 else if (result < BY_VAL_ACCESSES)
4212 result = BY_VAL_ACCESSES;
4214 else if (no_accesses_p (repr) && (result == NO_GOOD_ACCESS))
4215 result = UNUSED_PARAMS;
4217 else
4218 representatives.quick_push (NULL);
4221 if (result == NO_GOOD_ACCESS)
4223 representatives.release ();
4224 return NO_GOOD_ACCESS;
4227 return result;
4230 /* Return the index of BASE in PARMS. Abort if it is not found. */
4232 static inline int
4233 get_param_index (tree base, vec<tree> parms)
4235 int i, len;
4237 len = parms.length ();
4238 for (i = 0; i < len; i++)
4239 if (parms[i] == base)
4240 return i;
4241 gcc_unreachable ();
4244 /* Convert the decisions made at the representative level into compact
4245 parameter adjustments. REPRESENTATIVES are pointers to first
4246 representatives of each param accesses, ADJUSTMENTS_COUNT is the expected
4247 final number of adjustments. */
4249 static ipa_parm_adjustment_vec
4250 turn_representatives_into_adjustments (vec<access_p> representatives,
4251 int adjustments_count)
4253 vec<tree> parms;
4254 ipa_parm_adjustment_vec adjustments;
4255 tree parm;
4256 int i;
4258 gcc_assert (adjustments_count > 0);
4259 parms = ipa_get_vector_of_formal_parms (current_function_decl);
4260 adjustments.create (adjustments_count);
4261 parm = DECL_ARGUMENTS (current_function_decl);
4262 for (i = 0; i < func_param_count; i++, parm = DECL_CHAIN (parm))
4264 struct access *repr = representatives[i];
4266 if (!repr || no_accesses_p (repr))
4268 struct ipa_parm_adjustment adj;
4270 memset (&adj, 0, sizeof (adj));
4271 adj.base_index = get_param_index (parm, parms);
4272 adj.base = parm;
4273 if (!repr)
4274 adj.copy_param = 1;
4275 else
4276 adj.remove_param = 1;
4277 adjustments.quick_push (adj);
4279 else
4281 struct ipa_parm_adjustment adj;
4282 int index = get_param_index (parm, parms);
4284 for (; repr; repr = repr->next_grp)
4286 memset (&adj, 0, sizeof (adj));
4287 gcc_assert (repr->base == parm);
4288 adj.base_index = index;
4289 adj.base = repr->base;
4290 adj.type = repr->type;
4291 adj.alias_ptr_type = reference_alias_ptr_type (repr->expr);
4292 adj.offset = repr->offset;
4293 adj.by_ref = (POINTER_TYPE_P (TREE_TYPE (repr->base))
4294 && (repr->grp_maybe_modified
4295 || repr->grp_not_necessarilly_dereferenced));
4296 adjustments.quick_push (adj);
4300 parms.release ();
4301 return adjustments;
4304 /* Analyze the collected accesses and produce a plan what to do with the
4305 parameters in the form of adjustments, NULL meaning nothing. */
4307 static ipa_parm_adjustment_vec
4308 analyze_all_param_acesses (void)
4310 enum ipa_splicing_result repr_state;
4311 bool proceed = false;
4312 int i, adjustments_count = 0;
4313 vec<access_p> representatives;
4314 ipa_parm_adjustment_vec adjustments;
4316 repr_state = splice_all_param_accesses (representatives);
4317 if (repr_state == NO_GOOD_ACCESS)
4318 return ipa_parm_adjustment_vec ();
4320 /* If there are any parameters passed by reference which are not modified
4321 directly, we need to check whether they can be modified indirectly. */
4322 if (repr_state == UNMODIF_BY_REF_ACCESSES)
4324 analyze_caller_dereference_legality (representatives);
4325 analyze_modified_params (representatives);
4328 for (i = 0; i < func_param_count; i++)
4330 struct access *repr = representatives[i];
4332 if (repr && !no_accesses_p (repr))
4334 if (repr->grp_scalar_ptr)
4336 adjustments_count++;
4337 if (repr->grp_not_necessarilly_dereferenced
4338 || repr->grp_maybe_modified)
4339 representatives[i] = NULL;
4340 else
4342 proceed = true;
4343 sra_stats.scalar_by_ref_to_by_val++;
4346 else
4348 int new_components = decide_one_param_reduction (repr);
4350 if (new_components == 0)
4352 representatives[i] = NULL;
4353 adjustments_count++;
4355 else
4357 adjustments_count += new_components;
4358 sra_stats.aggregate_params_reduced++;
4359 sra_stats.param_reductions_created += new_components;
4360 proceed = true;
4364 else
4366 if (no_accesses_p (repr))
4368 proceed = true;
4369 sra_stats.deleted_unused_parameters++;
4371 adjustments_count++;
4375 if (!proceed && dump_file)
4376 fprintf (dump_file, "NOT proceeding to change params.\n");
4378 if (proceed)
4379 adjustments = turn_representatives_into_adjustments (representatives,
4380 adjustments_count);
4381 else
4382 adjustments = ipa_parm_adjustment_vec ();
4384 representatives.release ();
4385 return adjustments;
4388 /* If a parameter replacement identified by ADJ does not yet exist in the form
4389 of declaration, create it and record it, otherwise return the previously
4390 created one. */
4392 static tree
4393 get_replaced_param_substitute (struct ipa_parm_adjustment *adj)
4395 tree repl;
4396 if (!adj->new_ssa_base)
4398 char *pretty_name = make_fancy_name (adj->base);
4400 repl = create_tmp_reg (TREE_TYPE (adj->base), "ISR");
4401 DECL_NAME (repl) = get_identifier (pretty_name);
4402 obstack_free (&name_obstack, pretty_name);
4404 adj->new_ssa_base = repl;
4406 else
4407 repl = adj->new_ssa_base;
4408 return repl;
4411 /* Find the first adjustment for a particular parameter BASE in a vector of
4412 ADJUSTMENTS which is not a copy_param. Return NULL if there is no such
4413 adjustment. */
4415 static struct ipa_parm_adjustment *
4416 get_adjustment_for_base (ipa_parm_adjustment_vec adjustments, tree base)
4418 int i, len;
4420 len = adjustments.length ();
4421 for (i = 0; i < len; i++)
4423 struct ipa_parm_adjustment *adj;
4425 adj = &adjustments[i];
4426 if (!adj->copy_param && adj->base == base)
4427 return adj;
4430 return NULL;
4433 /* If the statement STMT defines an SSA_NAME of a parameter which is to be
4434 removed because its value is not used, replace the SSA_NAME with a one
4435 relating to a created VAR_DECL together all of its uses and return true.
4436 ADJUSTMENTS is a pointer to an adjustments vector. */
4438 static bool
4439 replace_removed_params_ssa_names (gimple stmt,
4440 ipa_parm_adjustment_vec adjustments)
4442 struct ipa_parm_adjustment *adj;
4443 tree lhs, decl, repl, name;
4445 if (gimple_code (stmt) == GIMPLE_PHI)
4446 lhs = gimple_phi_result (stmt);
4447 else if (is_gimple_assign (stmt))
4448 lhs = gimple_assign_lhs (stmt);
4449 else if (is_gimple_call (stmt))
4450 lhs = gimple_call_lhs (stmt);
4451 else
4452 gcc_unreachable ();
4454 if (TREE_CODE (lhs) != SSA_NAME)
4455 return false;
4457 decl = SSA_NAME_VAR (lhs);
4458 if (decl == NULL_TREE
4459 || TREE_CODE (decl) != PARM_DECL)
4460 return false;
4462 adj = get_adjustment_for_base (adjustments, decl);
4463 if (!adj)
4464 return false;
4466 repl = get_replaced_param_substitute (adj);
4467 name = make_ssa_name (repl, stmt);
4469 if (dump_file)
4471 fprintf (dump_file, "replacing an SSA name of a removed param ");
4472 print_generic_expr (dump_file, lhs, 0);
4473 fprintf (dump_file, " with ");
4474 print_generic_expr (dump_file, name, 0);
4475 fprintf (dump_file, "\n");
4478 if (is_gimple_assign (stmt))
4479 gimple_assign_set_lhs (stmt, name);
4480 else if (is_gimple_call (stmt))
4481 gimple_call_set_lhs (stmt, name);
4482 else
4483 gimple_phi_set_result (stmt, name);
4485 replace_uses_by (lhs, name);
4486 release_ssa_name (lhs);
4487 return true;
4490 /* If the expression *EXPR should be replaced by a reduction of a parameter, do
4491 so. ADJUSTMENTS is a pointer to a vector of adjustments. CONVERT
4492 specifies whether the function should care about type incompatibility the
4493 current and new expressions. If it is false, the function will leave
4494 incompatibility issues to the caller. Return true iff the expression
4495 was modified. */
4497 static bool
4498 sra_ipa_modify_expr (tree *expr, bool convert,
4499 ipa_parm_adjustment_vec adjustments)
4501 int i, len;
4502 struct ipa_parm_adjustment *adj, *cand = NULL;
4503 HOST_WIDE_INT offset, size, max_size;
4504 tree base, src;
4506 len = adjustments.length ();
4508 if (TREE_CODE (*expr) == BIT_FIELD_REF
4509 || TREE_CODE (*expr) == IMAGPART_EXPR
4510 || TREE_CODE (*expr) == REALPART_EXPR)
4512 expr = &TREE_OPERAND (*expr, 0);
4513 convert = true;
4516 base = get_ref_base_and_extent (*expr, &offset, &size, &max_size);
4517 if (!base || size == -1 || max_size == -1)
4518 return false;
4520 if (TREE_CODE (base) == MEM_REF)
4522 offset += mem_ref_offset (base).low * BITS_PER_UNIT;
4523 base = TREE_OPERAND (base, 0);
4526 base = get_ssa_base_param (base);
4527 if (!base || TREE_CODE (base) != PARM_DECL)
4528 return false;
4530 for (i = 0; i < len; i++)
4532 adj = &adjustments[i];
4534 if (adj->base == base
4535 && (adj->offset == offset || adj->remove_param))
4537 cand = adj;
4538 break;
4541 if (!cand || cand->copy_param || cand->remove_param)
4542 return false;
4544 if (cand->by_ref)
4545 src = build_simple_mem_ref (cand->reduction);
4546 else
4547 src = cand->reduction;
4549 if (dump_file && (dump_flags & TDF_DETAILS))
4551 fprintf (dump_file, "About to replace expr ");
4552 print_generic_expr (dump_file, *expr, 0);
4553 fprintf (dump_file, " with ");
4554 print_generic_expr (dump_file, src, 0);
4555 fprintf (dump_file, "\n");
4558 if (convert && !useless_type_conversion_p (TREE_TYPE (*expr), cand->type))
4560 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*expr), src);
4561 *expr = vce;
4563 else
4564 *expr = src;
4565 return true;
4568 /* If the statement pointed to by STMT_PTR contains any expressions that need
4569 to replaced with a different one as noted by ADJUSTMENTS, do so. Handle any
4570 potential type incompatibilities (GSI is used to accommodate conversion
4571 statements and must point to the statement). Return true iff the statement
4572 was modified. */
4574 static bool
4575 sra_ipa_modify_assign (gimple *stmt_ptr, gimple_stmt_iterator *gsi,
4576 ipa_parm_adjustment_vec adjustments)
4578 gimple stmt = *stmt_ptr;
4579 tree *lhs_p, *rhs_p;
4580 bool any;
4582 if (!gimple_assign_single_p (stmt))
4583 return false;
4585 rhs_p = gimple_assign_rhs1_ptr (stmt);
4586 lhs_p = gimple_assign_lhs_ptr (stmt);
4588 any = sra_ipa_modify_expr (rhs_p, false, adjustments);
4589 any |= sra_ipa_modify_expr (lhs_p, false, adjustments);
4590 if (any)
4592 tree new_rhs = NULL_TREE;
4594 if (!useless_type_conversion_p (TREE_TYPE (*lhs_p), TREE_TYPE (*rhs_p)))
4596 if (TREE_CODE (*rhs_p) == CONSTRUCTOR)
4598 /* V_C_Es of constructors can cause trouble (PR 42714). */
4599 if (is_gimple_reg_type (TREE_TYPE (*lhs_p)))
4600 *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
4601 else
4602 *rhs_p = build_constructor (TREE_TYPE (*lhs_p),
4603 NULL);
4605 else
4606 new_rhs = fold_build1_loc (gimple_location (stmt),
4607 VIEW_CONVERT_EXPR, TREE_TYPE (*lhs_p),
4608 *rhs_p);
4610 else if (REFERENCE_CLASS_P (*rhs_p)
4611 && is_gimple_reg_type (TREE_TYPE (*lhs_p))
4612 && !is_gimple_reg (*lhs_p))
4613 /* This can happen when an assignment in between two single field
4614 structures is turned into an assignment in between two pointers to
4615 scalars (PR 42237). */
4616 new_rhs = *rhs_p;
4618 if (new_rhs)
4620 tree tmp = force_gimple_operand_gsi (gsi, new_rhs, true, NULL_TREE,
4621 true, GSI_SAME_STMT);
4623 gimple_assign_set_rhs_from_tree (gsi, tmp);
4626 return true;
4629 return false;
4632 /* Traverse the function body and all modifications as described in
4633 ADJUSTMENTS. Return true iff the CFG has been changed. */
4635 static bool
4636 ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments)
4638 bool cfg_changed = false;
4639 basic_block bb;
4641 FOR_EACH_BB (bb)
4643 gimple_stmt_iterator gsi;
4645 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4646 replace_removed_params_ssa_names (gsi_stmt (gsi), adjustments);
4648 gsi = gsi_start_bb (bb);
4649 while (!gsi_end_p (gsi))
4651 gimple stmt = gsi_stmt (gsi);
4652 bool modified = false;
4653 tree *t;
4654 unsigned i;
4656 switch (gimple_code (stmt))
4658 case GIMPLE_RETURN:
4659 t = gimple_return_retval_ptr (stmt);
4660 if (*t != NULL_TREE)
4661 modified |= sra_ipa_modify_expr (t, true, adjustments);
4662 break;
4664 case GIMPLE_ASSIGN:
4665 modified |= sra_ipa_modify_assign (&stmt, &gsi, adjustments);
4666 modified |= replace_removed_params_ssa_names (stmt, adjustments);
4667 break;
4669 case GIMPLE_CALL:
4670 /* Operands must be processed before the lhs. */
4671 for (i = 0; i < gimple_call_num_args (stmt); i++)
4673 t = gimple_call_arg_ptr (stmt, i);
4674 modified |= sra_ipa_modify_expr (t, true, adjustments);
4677 if (gimple_call_lhs (stmt))
4679 t = gimple_call_lhs_ptr (stmt);
4680 modified |= sra_ipa_modify_expr (t, false, adjustments);
4681 modified |= replace_removed_params_ssa_names (stmt,
4682 adjustments);
4684 break;
4686 case GIMPLE_ASM:
4687 for (i = 0; i < gimple_asm_ninputs (stmt); i++)
4689 t = &TREE_VALUE (gimple_asm_input_op (stmt, i));
4690 modified |= sra_ipa_modify_expr (t, true, adjustments);
4692 for (i = 0; i < gimple_asm_noutputs (stmt); i++)
4694 t = &TREE_VALUE (gimple_asm_output_op (stmt, i));
4695 modified |= sra_ipa_modify_expr (t, false, adjustments);
4697 break;
4699 default:
4700 break;
4703 if (modified)
4705 update_stmt (stmt);
4706 if (maybe_clean_eh_stmt (stmt)
4707 && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
4708 cfg_changed = true;
4710 gsi_next (&gsi);
4714 return cfg_changed;
4717 /* Call gimple_debug_bind_reset_value on all debug statements describing
4718 gimple register parameters that are being removed or replaced. */
4720 static void
4721 sra_ipa_reset_debug_stmts (ipa_parm_adjustment_vec adjustments)
4723 int i, len;
4724 gimple_stmt_iterator *gsip = NULL, gsi;
4726 if (MAY_HAVE_DEBUG_STMTS && single_succ_p (ENTRY_BLOCK_PTR))
4728 gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
4729 gsip = &gsi;
4731 len = adjustments.length ();
4732 for (i = 0; i < len; i++)
4734 struct ipa_parm_adjustment *adj;
4735 imm_use_iterator ui;
4736 gimple stmt, def_temp;
4737 tree name, vexpr, copy = NULL_TREE;
4738 use_operand_p use_p;
4740 adj = &adjustments[i];
4741 if (adj->copy_param || !is_gimple_reg (adj->base))
4742 continue;
4743 name = ssa_default_def (cfun, adj->base);
4744 vexpr = NULL;
4745 if (name)
4746 FOR_EACH_IMM_USE_STMT (stmt, ui, name)
4748 if (gimple_clobber_p (stmt))
4750 gimple_stmt_iterator cgsi = gsi_for_stmt (stmt);
4751 unlink_stmt_vdef (stmt);
4752 gsi_remove (&cgsi, true);
4753 release_defs (stmt);
4754 continue;
4756 /* All other users must have been removed by
4757 ipa_sra_modify_function_body. */
4758 gcc_assert (is_gimple_debug (stmt));
4759 if (vexpr == NULL && gsip != NULL)
4761 gcc_assert (TREE_CODE (adj->base) == PARM_DECL);
4762 vexpr = make_node (DEBUG_EXPR_DECL);
4763 def_temp = gimple_build_debug_source_bind (vexpr, adj->base,
4764 NULL);
4765 DECL_ARTIFICIAL (vexpr) = 1;
4766 TREE_TYPE (vexpr) = TREE_TYPE (name);
4767 DECL_MODE (vexpr) = DECL_MODE (adj->base);
4768 gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
4770 if (vexpr)
4772 FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
4773 SET_USE (use_p, vexpr);
4775 else
4776 gimple_debug_bind_reset_value (stmt);
4777 update_stmt (stmt);
4779 /* Create a VAR_DECL for debug info purposes. */
4780 if (!DECL_IGNORED_P (adj->base))
4782 copy = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
4783 VAR_DECL, DECL_NAME (adj->base),
4784 TREE_TYPE (adj->base));
4785 if (DECL_PT_UID_SET_P (adj->base))
4786 SET_DECL_PT_UID (copy, DECL_PT_UID (adj->base));
4787 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (adj->base);
4788 TREE_READONLY (copy) = TREE_READONLY (adj->base);
4789 TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (adj->base);
4790 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (adj->base);
4791 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (adj->base);
4792 DECL_IGNORED_P (copy) = DECL_IGNORED_P (adj->base);
4793 DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (adj->base);
4794 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
4795 SET_DECL_RTL (copy, 0);
4796 TREE_USED (copy) = 1;
4797 DECL_CONTEXT (copy) = current_function_decl;
4798 add_local_decl (cfun, copy);
4799 DECL_CHAIN (copy) =
4800 BLOCK_VARS (DECL_INITIAL (current_function_decl));
4801 BLOCK_VARS (DECL_INITIAL (current_function_decl)) = copy;
4803 if (gsip != NULL && copy && target_for_debug_bind (adj->base))
4805 gcc_assert (TREE_CODE (adj->base) == PARM_DECL);
4806 if (vexpr)
4807 def_temp = gimple_build_debug_bind (copy, vexpr, NULL);
4808 else
4809 def_temp = gimple_build_debug_source_bind (copy, adj->base,
4810 NULL);
4811 gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
4816 /* Return false iff all callers have at least as many actual arguments as there
4817 are formal parameters in the current function. */
4819 static bool
4820 not_all_callers_have_enough_arguments_p (struct cgraph_node *node,
4821 void *data ATTRIBUTE_UNUSED)
4823 struct cgraph_edge *cs;
4824 for (cs = node->callers; cs; cs = cs->next_caller)
4825 if (!callsite_has_enough_arguments_p (cs->call_stmt))
4826 return true;
4828 return false;
4831 /* Convert all callers of NODE. */
4833 static bool
4834 convert_callers_for_node (struct cgraph_node *node,
4835 void *data)
4837 ipa_parm_adjustment_vec *adjustments = (ipa_parm_adjustment_vec *) data;
4838 bitmap recomputed_callers = BITMAP_ALLOC (NULL);
4839 struct cgraph_edge *cs;
4841 for (cs = node->callers; cs; cs = cs->next_caller)
4843 push_cfun (DECL_STRUCT_FUNCTION (cs->caller->decl));
4845 if (dump_file)
4846 fprintf (dump_file, "Adjusting call %s/%i -> %s/%i\n",
4847 xstrdup (cgraph_node_name (cs->caller)),
4848 cs->caller->order,
4849 xstrdup (cgraph_node_name (cs->callee)),
4850 cs->callee->order);
4852 ipa_modify_call_arguments (cs, cs->call_stmt, *adjustments);
4854 pop_cfun ();
4857 for (cs = node->callers; cs; cs = cs->next_caller)
4858 if (bitmap_set_bit (recomputed_callers, cs->caller->uid)
4859 && gimple_in_ssa_p (DECL_STRUCT_FUNCTION (cs->caller->decl)))
4860 compute_inline_parameters (cs->caller, true);
4861 BITMAP_FREE (recomputed_callers);
4863 return true;
4866 /* Convert all callers of NODE to pass parameters as given in ADJUSTMENTS. */
4868 static void
4869 convert_callers (struct cgraph_node *node, tree old_decl,
4870 ipa_parm_adjustment_vec adjustments)
4872 basic_block this_block;
4874 cgraph_for_node_and_aliases (node, convert_callers_for_node,
4875 &adjustments, false);
4877 if (!encountered_recursive_call)
4878 return;
4880 FOR_EACH_BB (this_block)
4882 gimple_stmt_iterator gsi;
4884 for (gsi = gsi_start_bb (this_block); !gsi_end_p (gsi); gsi_next (&gsi))
4886 gimple stmt = gsi_stmt (gsi);
4887 tree call_fndecl;
4888 if (gimple_code (stmt) != GIMPLE_CALL)
4889 continue;
4890 call_fndecl = gimple_call_fndecl (stmt);
4891 if (call_fndecl == old_decl)
4893 if (dump_file)
4894 fprintf (dump_file, "Adjusting recursive call");
4895 gimple_call_set_fndecl (stmt, node->decl);
4896 ipa_modify_call_arguments (NULL, stmt, adjustments);
4901 return;
4904 /* Perform all the modification required in IPA-SRA for NODE to have parameters
4905 as given in ADJUSTMENTS. Return true iff the CFG has been changed. */
4907 static bool
4908 modify_function (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments)
4910 struct cgraph_node *new_node;
4911 bool cfg_changed;
4912 vec<cgraph_edge_p> redirect_callers = collect_callers_of_node (node);
4914 rebuild_cgraph_edges ();
4915 free_dominance_info (CDI_DOMINATORS);
4916 pop_cfun ();
4918 new_node = cgraph_function_versioning (node, redirect_callers,
4919 NULL,
4920 NULL, false, NULL, NULL, "isra");
4921 redirect_callers.release ();
4923 push_cfun (DECL_STRUCT_FUNCTION (new_node->decl));
4924 ipa_modify_formal_parameters (current_function_decl, adjustments, "ISRA");
4925 cfg_changed = ipa_sra_modify_function_body (adjustments);
4926 sra_ipa_reset_debug_stmts (adjustments);
4927 convert_callers (new_node, node->decl, adjustments);
4928 cgraph_make_node_local (new_node);
4929 return cfg_changed;
4932 /* If NODE has a caller, return true. */
4934 static bool
4935 has_caller_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
4937 if (node->callers)
4938 return true;
4939 return false;
4942 /* Return false the function is apparently unsuitable for IPA-SRA based on it's
4943 attributes, return true otherwise. NODE is the cgraph node of the current
4944 function. */
4946 static bool
4947 ipa_sra_preliminary_function_checks (struct cgraph_node *node)
4949 if (!cgraph_node_can_be_local_p (node))
4951 if (dump_file)
4952 fprintf (dump_file, "Function not local to this compilation unit.\n");
4953 return false;
4956 if (!node->local.can_change_signature)
4958 if (dump_file)
4959 fprintf (dump_file, "Function can not change signature.\n");
4960 return false;
4963 if (!tree_versionable_function_p (node->decl))
4965 if (dump_file)
4966 fprintf (dump_file, "Function is not versionable.\n");
4967 return false;
4970 if (DECL_VIRTUAL_P (current_function_decl))
4972 if (dump_file)
4973 fprintf (dump_file, "Function is a virtual method.\n");
4974 return false;
4977 if ((DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl))
4978 && inline_summary (node)->size >= MAX_INLINE_INSNS_AUTO)
4980 if (dump_file)
4981 fprintf (dump_file, "Function too big to be made truly local.\n");
4982 return false;
4985 if (!cgraph_for_node_and_aliases (node, has_caller_p, NULL, true))
4987 if (dump_file)
4988 fprintf (dump_file,
4989 "Function has no callers in this compilation unit.\n");
4990 return false;
4993 if (cfun->stdarg)
4995 if (dump_file)
4996 fprintf (dump_file, "Function uses stdarg. \n");
4997 return false;
5000 if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl)))
5001 return false;
5003 return true;
5006 /* Perform early interprocedural SRA. */
5008 static unsigned int
5009 ipa_early_sra (void)
5011 struct cgraph_node *node = cgraph_get_node (current_function_decl);
5012 ipa_parm_adjustment_vec adjustments;
5013 int ret = 0;
5015 if (!ipa_sra_preliminary_function_checks (node))
5016 return 0;
5018 sra_initialize ();
5019 sra_mode = SRA_MODE_EARLY_IPA;
5021 if (!find_param_candidates ())
5023 if (dump_file)
5024 fprintf (dump_file, "Function has no IPA-SRA candidates.\n");
5025 goto simple_out;
5028 if (cgraph_for_node_and_aliases (node, not_all_callers_have_enough_arguments_p,
5029 NULL, true))
5031 if (dump_file)
5032 fprintf (dump_file, "There are callers with insufficient number of "
5033 "arguments.\n");
5034 goto simple_out;
5037 bb_dereferences = XCNEWVEC (HOST_WIDE_INT,
5038 func_param_count
5039 * last_basic_block_for_function (cfun));
5040 final_bbs = BITMAP_ALLOC (NULL);
5042 scan_function ();
5043 if (encountered_apply_args)
5045 if (dump_file)
5046 fprintf (dump_file, "Function calls __builtin_apply_args().\n");
5047 goto out;
5050 if (encountered_unchangable_recursive_call)
5052 if (dump_file)
5053 fprintf (dump_file, "Function calls itself with insufficient "
5054 "number of arguments.\n");
5055 goto out;
5058 adjustments = analyze_all_param_acesses ();
5059 if (!adjustments.exists ())
5060 goto out;
5061 if (dump_file)
5062 ipa_dump_param_adjustments (dump_file, adjustments, current_function_decl);
5064 if (modify_function (node, adjustments))
5065 ret = TODO_update_ssa | TODO_cleanup_cfg;
5066 else
5067 ret = TODO_update_ssa;
5068 adjustments.release ();
5070 statistics_counter_event (cfun, "Unused parameters deleted",
5071 sra_stats.deleted_unused_parameters);
5072 statistics_counter_event (cfun, "Scalar parameters converted to by-value",
5073 sra_stats.scalar_by_ref_to_by_val);
5074 statistics_counter_event (cfun, "Aggregate parameters broken up",
5075 sra_stats.aggregate_params_reduced);
5076 statistics_counter_event (cfun, "Aggregate parameter components created",
5077 sra_stats.param_reductions_created);
5079 out:
5080 BITMAP_FREE (final_bbs);
5081 free (bb_dereferences);
5082 simple_out:
5083 sra_deinitialize ();
5084 return ret;
5087 /* Return if early ipa sra shall be performed. */
5088 static bool
5089 ipa_early_sra_gate (void)
5091 return flag_ipa_sra && dbg_cnt (eipa_sra);
5094 namespace {
5096 const pass_data pass_data_early_ipa_sra =
5098 GIMPLE_PASS, /* type */
5099 "eipa_sra", /* name */
5100 OPTGROUP_NONE, /* optinfo_flags */
5101 true, /* has_gate */
5102 true, /* has_execute */
5103 TV_IPA_SRA, /* tv_id */
5104 0, /* properties_required */
5105 0, /* properties_provided */
5106 0, /* properties_destroyed */
5107 0, /* todo_flags_start */
5108 TODO_dump_symtab, /* todo_flags_finish */
5111 class pass_early_ipa_sra : public gimple_opt_pass
5113 public:
5114 pass_early_ipa_sra (gcc::context *ctxt)
5115 : gimple_opt_pass (pass_data_early_ipa_sra, ctxt)
5118 /* opt_pass methods: */
5119 bool gate () { return ipa_early_sra_gate (); }
5120 unsigned int execute () { return ipa_early_sra (); }
5122 }; // class pass_early_ipa_sra
5124 } // anon namespace
5126 gimple_opt_pass *
5127 make_pass_early_ipa_sra (gcc::context *ctxt)
5129 return new pass_early_ipa_sra (ctxt);