* tree-pass.h (register_pass_info): New structure.
[official-gcc.git] / gcc / tree-sra.c
blob92dab57a2f8582b3c61e23cdd60c74b0bd2dbe89
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, 2009 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 "alloc-pool.h"
78 #include "tm.h"
79 #include "tree.h"
80 #include "gimple.h"
81 #include "cgraph.h"
82 #include "tree-flow.h"
83 #include "ipa-prop.h"
84 #include "diagnostic.h"
85 #include "statistics.h"
86 #include "tree-dump.h"
87 #include "timevar.h"
88 #include "params.h"
89 #include "target.h"
90 #include "flags.h"
92 /* Enumeration of all aggregate reductions we can do. */
93 enum sra_mode { SRA_MODE_EARLY_IPA, /* early call regularization */
94 SRA_MODE_EARLY_INTRA, /* early intraprocedural SRA */
95 SRA_MODE_INTRA }; /* late intraprocedural SRA */
97 /* Global variable describing which aggregate reduction we are performing at
98 the moment. */
99 static enum sra_mode sra_mode;
101 struct assign_link;
103 /* ACCESS represents each access to an aggregate variable (as a whole or a
104 part). It can also represent a group of accesses that refer to exactly the
105 same fragment of an aggregate (i.e. those that have exactly the same offset
106 and size). Such representatives for a single aggregate, once determined,
107 are linked in a linked list and have the group fields set.
109 Moreover, when doing intraprocedural SRA, a tree is built from those
110 representatives (by the means of first_child and next_sibling pointers), in
111 which all items in a subtree are "within" the root, i.e. their offset is
112 greater or equal to offset of the root and offset+size is smaller or equal
113 to offset+size of the root. Children of an access are sorted by offset.
115 Note that accesses to parts of vector and complex number types always
116 represented by an access to the whole complex number or a vector. It is a
117 duty of the modifying functions to replace them appropriately. */
119 struct access
121 /* Values returned by `get_ref_base_and_extent' for each component reference
122 If EXPR isn't a component reference just set `BASE = EXPR', `OFFSET = 0',
123 `SIZE = TREE_SIZE (TREE_TYPE (expr))'. */
124 HOST_WIDE_INT offset;
125 HOST_WIDE_INT size;
126 tree base;
128 /* Expression. */
129 tree expr;
130 /* Type. */
131 tree type;
133 /* The statement this access belongs to. */
134 gimple stmt;
136 /* Next group representative for this aggregate. */
137 struct access *next_grp;
139 /* Pointer to the group representative. Pointer to itself if the struct is
140 the representative. */
141 struct access *group_representative;
143 /* If this access has any children (in terms of the definition above), this
144 points to the first one. */
145 struct access *first_child;
147 /* Pointer to the next sibling in the access tree as described above. */
148 struct access *next_sibling;
150 /* Pointers to the first and last element in the linked list of assign
151 links. */
152 struct assign_link *first_link, *last_link;
154 /* Pointer to the next access in the work queue. */
155 struct access *next_queued;
157 /* Replacement variable for this access "region." Never to be accessed
158 directly, always only by the means of get_access_replacement() and only
159 when grp_to_be_replaced flag is set. */
160 tree replacement_decl;
162 /* Is this particular access write access? */
163 unsigned write : 1;
165 /* Is this access currently in the work queue? */
166 unsigned grp_queued : 1;
168 /* Does this group contain a write access? This flag is propagated down the
169 access tree. */
170 unsigned grp_write : 1;
172 /* Does this group contain a read access? This flag is propagated down the
173 access tree. */
174 unsigned grp_read : 1;
176 /* Other passes of the analysis use this bit to make function
177 analyze_access_subtree create scalar replacements for this group if
178 possible. */
179 unsigned grp_hint : 1;
181 /* Is the subtree rooted in this access fully covered by scalar
182 replacements? */
183 unsigned grp_covered : 1;
185 /* If set to true, this access and all below it in an access tree must not be
186 scalarized. */
187 unsigned grp_unscalarizable_region : 1;
189 /* Whether data have been written to parts of the aggregate covered by this
190 access which is not to be scalarized. This flag is propagated up in the
191 access tree. */
192 unsigned grp_unscalarized_data : 1;
194 /* Does this access and/or group contain a write access through a
195 BIT_FIELD_REF? */
196 unsigned grp_partial_lhs : 1;
198 /* Set when a scalar replacement should be created for this variable. We do
199 the decision and creation at different places because create_tmp_var
200 cannot be called from within FOR_EACH_REFERENCED_VAR. */
201 unsigned grp_to_be_replaced : 1;
203 /* Is it possible that the group refers to data which might be (directly or
204 otherwise) modified? */
205 unsigned grp_maybe_modified : 1;
207 /* Set when this is a representative of a pointer to scalar (i.e. by
208 reference) parameter which we consider for turning into a plain scalar
209 (i.e. a by value parameter). */
210 unsigned grp_scalar_ptr : 1;
212 /* Set when we discover that this pointer is not safe to dereference in the
213 caller. */
214 unsigned grp_not_necessarilly_dereferenced : 1;
217 typedef struct access *access_p;
219 DEF_VEC_P (access_p);
220 DEF_VEC_ALLOC_P (access_p, heap);
222 /* Alloc pool for allocating access structures. */
223 static alloc_pool access_pool;
225 /* A structure linking lhs and rhs accesses from an aggregate assignment. They
226 are used to propagate subaccesses from rhs to lhs as long as they don't
227 conflict with what is already there. */
228 struct assign_link
230 struct access *lacc, *racc;
231 struct assign_link *next;
234 /* Alloc pool for allocating assign link structures. */
235 static alloc_pool link_pool;
237 /* Base (tree) -> Vector (VEC(access_p,heap) *) map. */
238 static struct pointer_map_t *base_access_vec;
240 /* Bitmap of candidates. */
241 static bitmap candidate_bitmap;
243 /* Obstack for creation of fancy names. */
244 static struct obstack name_obstack;
246 /* Head of a linked list of accesses that need to have its subaccesses
247 propagated to their assignment counterparts. */
248 static struct access *work_queue_head;
250 /* Number of parameters of the analyzed function when doing early ipa SRA. */
251 static int func_param_count;
253 /* scan_function sets the following to true if it encounters a call to
254 __builtin_apply_args. */
255 static bool encountered_apply_args;
257 /* This is a table in which for each basic block and parameter there is a
258 distance (offset + size) in that parameter which is dereferenced and
259 accessed in that BB. */
260 static HOST_WIDE_INT *bb_dereferences;
261 /* Bitmap of BBs that can cause the function to "stop" progressing by
262 returning, throwing externally, looping infinitely or calling a function
263 which might abort etc.. */
264 static bitmap final_bbs;
266 /* Representative of no accesses at all. */
267 static struct access no_accesses_representant;
269 /* Predicate to test the special value. */
271 static inline bool
272 no_accesses_p (struct access *access)
274 return access == &no_accesses_representant;
277 /* Dump contents of ACCESS to file F in a human friendly way. If GRP is true,
278 representative fields are dumped, otherwise those which only describe the
279 individual access are. */
281 static struct
283 /* Number of processed aggregates is readily available in
284 analyze_all_variable_accesses and so is not stored here. */
286 /* Number of created scalar replacements. */
287 int replacements;
289 /* Number of times sra_modify_expr or sra_modify_assign themselves changed an
290 expression. */
291 int exprs;
293 /* Number of statements created by generate_subtree_copies. */
294 int subtree_copies;
296 /* Number of statements created by load_assign_lhs_subreplacements. */
297 int subreplacements;
299 /* Number of times sra_modify_assign has deleted a statement. */
300 int deleted;
302 /* Number of times sra_modify_assign has to deal with subaccesses of LHS and
303 RHS reparately due to type conversions or nonexistent matching
304 references. */
305 int separate_lhs_rhs_handling;
307 /* Number of parameters that were removed because they were unused. */
308 int deleted_unused_parameters;
310 /* Number of scalars passed as parameters by reference that have been
311 converted to be passed by value. */
312 int scalar_by_ref_to_by_val;
314 /* Number of aggregate parameters that were replaced by one or more of their
315 components. */
316 int aggregate_params_reduced;
318 /* Numbber of components created when splitting aggregate parameters. */
319 int param_reductions_created;
320 } sra_stats;
322 static void
323 dump_access (FILE *f, struct access *access, bool grp)
325 fprintf (f, "access { ");
326 fprintf (f, "base = (%d)'", DECL_UID (access->base));
327 print_generic_expr (f, access->base, 0);
328 fprintf (f, "', offset = " HOST_WIDE_INT_PRINT_DEC, access->offset);
329 fprintf (f, ", size = " HOST_WIDE_INT_PRINT_DEC, access->size);
330 fprintf (f, ", expr = ");
331 print_generic_expr (f, access->expr, 0);
332 fprintf (f, ", type = ");
333 print_generic_expr (f, access->type, 0);
334 if (grp)
335 fprintf (f, ", grp_write = %d, grp_read = %d, grp_hint = %d, "
336 "grp_covered = %d, grp_unscalarizable_region = %d, "
337 "grp_unscalarized_data = %d, grp_partial_lhs = %d, "
338 "grp_to_be_replaced = %d\n grp_maybe_modified = %d, "
339 "grp_not_necessarilly_dereferenced = %d\n",
340 access->grp_write, access->grp_read, access->grp_hint,
341 access->grp_covered, access->grp_unscalarizable_region,
342 access->grp_unscalarized_data, access->grp_partial_lhs,
343 access->grp_to_be_replaced, access->grp_maybe_modified,
344 access->grp_not_necessarilly_dereferenced);
345 else
346 fprintf (f, ", write = %d, grp_partial_lhs = %d\n", access->write,
347 access->grp_partial_lhs);
350 /* Dump a subtree rooted in ACCESS to file F, indent by LEVEL. */
352 static void
353 dump_access_tree_1 (FILE *f, struct access *access, int level)
357 int i;
359 for (i = 0; i < level; i++)
360 fputs ("* ", dump_file);
362 dump_access (f, access, true);
364 if (access->first_child)
365 dump_access_tree_1 (f, access->first_child, level + 1);
367 access = access->next_sibling;
369 while (access);
372 /* Dump all access trees for a variable, given the pointer to the first root in
373 ACCESS. */
375 static void
376 dump_access_tree (FILE *f, struct access *access)
378 for (; access; access = access->next_grp)
379 dump_access_tree_1 (f, access, 0);
382 /* Return true iff ACC is non-NULL and has subaccesses. */
384 static inline bool
385 access_has_children_p (struct access *acc)
387 return acc && acc->first_child;
390 /* Return a vector of pointers to accesses for the variable given in BASE or
391 NULL if there is none. */
393 static VEC (access_p, heap) *
394 get_base_access_vector (tree base)
396 void **slot;
398 slot = pointer_map_contains (base_access_vec, base);
399 if (!slot)
400 return NULL;
401 else
402 return *(VEC (access_p, heap) **) slot;
405 /* Find an access with required OFFSET and SIZE in a subtree of accesses rooted
406 in ACCESS. Return NULL if it cannot be found. */
408 static struct access *
409 find_access_in_subtree (struct access *access, HOST_WIDE_INT offset,
410 HOST_WIDE_INT size)
412 while (access && (access->offset != offset || access->size != size))
414 struct access *child = access->first_child;
416 while (child && (child->offset + child->size <= offset))
417 child = child->next_sibling;
418 access = child;
421 return access;
424 /* Return the first group representative for DECL or NULL if none exists. */
426 static struct access *
427 get_first_repr_for_decl (tree base)
429 VEC (access_p, heap) *access_vec;
431 access_vec = get_base_access_vector (base);
432 if (!access_vec)
433 return NULL;
435 return VEC_index (access_p, access_vec, 0);
438 /* Find an access representative for the variable BASE and given OFFSET and
439 SIZE. Requires that access trees have already been built. Return NULL if
440 it cannot be found. */
442 static struct access *
443 get_var_base_offset_size_access (tree base, HOST_WIDE_INT offset,
444 HOST_WIDE_INT size)
446 struct access *access;
448 access = get_first_repr_for_decl (base);
449 while (access && (access->offset + access->size <= offset))
450 access = access->next_grp;
451 if (!access)
452 return NULL;
454 return find_access_in_subtree (access, offset, size);
457 /* Add LINK to the linked list of assign links of RACC. */
458 static void
459 add_link_to_rhs (struct access *racc, struct assign_link *link)
461 gcc_assert (link->racc == racc);
463 if (!racc->first_link)
465 gcc_assert (!racc->last_link);
466 racc->first_link = link;
468 else
469 racc->last_link->next = link;
471 racc->last_link = link;
472 link->next = NULL;
475 /* Move all link structures in their linked list in OLD_RACC to the linked list
476 in NEW_RACC. */
477 static void
478 relink_to_new_repr (struct access *new_racc, struct access *old_racc)
480 if (!old_racc->first_link)
482 gcc_assert (!old_racc->last_link);
483 return;
486 if (new_racc->first_link)
488 gcc_assert (!new_racc->last_link->next);
489 gcc_assert (!old_racc->last_link || !old_racc->last_link->next);
491 new_racc->last_link->next = old_racc->first_link;
492 new_racc->last_link = old_racc->last_link;
494 else
496 gcc_assert (!new_racc->last_link);
498 new_racc->first_link = old_racc->first_link;
499 new_racc->last_link = old_racc->last_link;
501 old_racc->first_link = old_racc->last_link = NULL;
504 /* Add ACCESS to the work queue (which is actually a stack). */
506 static void
507 add_access_to_work_queue (struct access *access)
509 if (!access->grp_queued)
511 gcc_assert (!access->next_queued);
512 access->next_queued = work_queue_head;
513 access->grp_queued = 1;
514 work_queue_head = access;
518 /* Pop an access from the work queue, and return it, assuming there is one. */
520 static struct access *
521 pop_access_from_work_queue (void)
523 struct access *access = work_queue_head;
525 work_queue_head = access->next_queued;
526 access->next_queued = NULL;
527 access->grp_queued = 0;
528 return access;
532 /* Allocate necessary structures. */
534 static void
535 sra_initialize (void)
537 candidate_bitmap = BITMAP_ALLOC (NULL);
538 gcc_obstack_init (&name_obstack);
539 access_pool = create_alloc_pool ("SRA accesses", sizeof (struct access), 16);
540 link_pool = create_alloc_pool ("SRA links", sizeof (struct assign_link), 16);
541 base_access_vec = pointer_map_create ();
542 memset (&sra_stats, 0, sizeof (sra_stats));
543 encountered_apply_args = false;
546 /* Hook fed to pointer_map_traverse, deallocate stored vectors. */
548 static bool
549 delete_base_accesses (const void *key ATTRIBUTE_UNUSED, void **value,
550 void *data ATTRIBUTE_UNUSED)
552 VEC (access_p, heap) *access_vec;
553 access_vec = (VEC (access_p, heap) *) *value;
554 VEC_free (access_p, heap, access_vec);
556 return true;
559 /* Deallocate all general structures. */
561 static void
562 sra_deinitialize (void)
564 BITMAP_FREE (candidate_bitmap);
565 free_alloc_pool (access_pool);
566 free_alloc_pool (link_pool);
567 obstack_free (&name_obstack, NULL);
569 pointer_map_traverse (base_access_vec, delete_base_accesses, NULL);
570 pointer_map_destroy (base_access_vec);
573 /* Remove DECL from candidates for SRA and write REASON to the dump file if
574 there is one. */
575 static void
576 disqualify_candidate (tree decl, const char *reason)
578 bitmap_clear_bit (candidate_bitmap, DECL_UID (decl));
580 if (dump_file && (dump_flags & TDF_DETAILS))
582 fprintf (dump_file, "! Disqualifying ");
583 print_generic_expr (dump_file, decl, 0);
584 fprintf (dump_file, " - %s\n", reason);
588 /* Return true iff the type contains a field or an element which does not allow
589 scalarization. */
591 static bool
592 type_internals_preclude_sra_p (tree type)
594 tree fld;
595 tree et;
597 switch (TREE_CODE (type))
599 case RECORD_TYPE:
600 case UNION_TYPE:
601 case QUAL_UNION_TYPE:
602 for (fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
603 if (TREE_CODE (fld) == FIELD_DECL)
605 tree ft = TREE_TYPE (fld);
607 if (TREE_THIS_VOLATILE (fld)
608 || !DECL_FIELD_OFFSET (fld) || !DECL_SIZE (fld)
609 || !host_integerp (DECL_FIELD_OFFSET (fld), 1)
610 || !host_integerp (DECL_SIZE (fld), 1))
611 return true;
613 if (AGGREGATE_TYPE_P (ft)
614 && type_internals_preclude_sra_p (ft))
615 return true;
618 return false;
620 case ARRAY_TYPE:
621 et = TREE_TYPE (type);
623 if (AGGREGATE_TYPE_P (et))
624 return type_internals_preclude_sra_p (et);
625 else
626 return false;
628 default:
629 return false;
633 /* If T is an SSA_NAME, return NULL if it is not a default def or return its
634 base variable if it is. Return T if it is not an SSA_NAME. */
636 static tree
637 get_ssa_base_param (tree t)
639 if (TREE_CODE (t) == SSA_NAME)
641 if (SSA_NAME_IS_DEFAULT_DEF (t))
642 return SSA_NAME_VAR (t);
643 else
644 return NULL_TREE;
646 return t;
649 /* Mark a dereference of BASE of distance DIST in a basic block tht STMT
650 belongs to, unless the BB has already been marked as a potentially
651 final. */
653 static void
654 mark_parm_dereference (tree base, HOST_WIDE_INT dist, gimple stmt)
656 basic_block bb = gimple_bb (stmt);
657 int idx, parm_index = 0;
658 tree parm;
660 if (bitmap_bit_p (final_bbs, bb->index))
661 return;
663 for (parm = DECL_ARGUMENTS (current_function_decl);
664 parm && parm != base;
665 parm = TREE_CHAIN (parm))
666 parm_index++;
668 gcc_assert (parm_index < func_param_count);
670 idx = bb->index * func_param_count + parm_index;
671 if (bb_dereferences[idx] < dist)
672 bb_dereferences[idx] = dist;
675 /* Create and insert access for EXPR. Return created access, or NULL if it is
676 not possible. */
678 static struct access *
679 create_access (tree expr, gimple stmt, bool write)
681 struct access *access;
682 void **slot;
683 VEC (access_p,heap) *vec;
684 HOST_WIDE_INT offset, size, max_size;
685 tree base = expr;
686 bool ptr, unscalarizable_region = false;
688 base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
690 if (sra_mode == SRA_MODE_EARLY_IPA && INDIRECT_REF_P (base))
692 base = get_ssa_base_param (TREE_OPERAND (base, 0));
693 if (!base)
694 return NULL;
695 ptr = true;
697 else
698 ptr = false;
700 if (!DECL_P (base) || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
701 return NULL;
703 if (sra_mode == SRA_MODE_EARLY_IPA)
705 if (size < 0 || size != max_size)
707 disqualify_candidate (base, "Encountered a variable sized access.");
708 return NULL;
710 if ((offset % BITS_PER_UNIT) != 0 || (size % BITS_PER_UNIT) != 0)
712 disqualify_candidate (base,
713 "Encountered an acces not aligned to a byte.");
714 return NULL;
717 if (ptr)
718 mark_parm_dereference (base, offset + size, stmt);
720 else
722 if (size != max_size)
724 size = max_size;
725 unscalarizable_region = true;
727 if (size < 0)
729 disqualify_candidate (base, "Encountered an unconstrained access.");
730 return NULL;
734 access = (struct access *) pool_alloc (access_pool);
735 memset (access, 0, sizeof (struct access));
737 access->base = base;
738 access->offset = offset;
739 access->size = size;
740 access->expr = expr;
741 access->type = TREE_TYPE (expr);
742 access->write = write;
743 access->grp_unscalarizable_region = unscalarizable_region;
744 access->stmt = stmt;
746 slot = pointer_map_contains (base_access_vec, base);
747 if (slot)
748 vec = (VEC (access_p, heap) *) *slot;
749 else
750 vec = VEC_alloc (access_p, heap, 32);
752 VEC_safe_push (access_p, heap, vec, access);
754 *((struct VEC (access_p,heap) **)
755 pointer_map_insert (base_access_vec, base)) = vec;
757 return access;
761 /* Search the given tree for a declaration by skipping handled components and
762 exclude it from the candidates. */
764 static void
765 disqualify_base_of_expr (tree t, const char *reason)
767 while (handled_component_p (t))
768 t = TREE_OPERAND (t, 0);
770 if (sra_mode == SRA_MODE_EARLY_IPA)
772 if (INDIRECT_REF_P (t))
773 t = TREE_OPERAND (t, 0);
774 t = get_ssa_base_param (t);
777 if (t && DECL_P (t))
778 disqualify_candidate (t, reason);
781 /* Scan expression EXPR and create access structures for all accesses to
782 candidates for scalarization. Return the created access or NULL if none is
783 created. */
785 static struct access *
786 build_access_from_expr_1 (tree *expr_ptr, gimple stmt, bool write)
788 struct access *ret = NULL;
789 tree expr = *expr_ptr;
790 bool partial_ref;
792 if (TREE_CODE (expr) == BIT_FIELD_REF
793 || TREE_CODE (expr) == IMAGPART_EXPR
794 || TREE_CODE (expr) == REALPART_EXPR)
796 expr = TREE_OPERAND (expr, 0);
797 partial_ref = true;
799 else
800 partial_ref = false;
802 /* We need to dive through V_C_Es in order to get the size of its parameter
803 and not the result type. Ada produces such statements. We are also
804 capable of handling the topmost V_C_E but not any of those buried in other
805 handled components. */
806 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
807 expr = TREE_OPERAND (expr, 0);
809 if (contains_view_convert_expr_p (expr))
811 disqualify_base_of_expr (expr, "V_C_E under a different handled "
812 "component.");
813 return NULL;
816 switch (TREE_CODE (expr))
818 case INDIRECT_REF:
819 if (sra_mode != SRA_MODE_EARLY_IPA)
820 return NULL;
821 /* fall through */
822 case VAR_DECL:
823 case PARM_DECL:
824 case RESULT_DECL:
825 case COMPONENT_REF:
826 case ARRAY_REF:
827 case ARRAY_RANGE_REF:
828 ret = create_access (expr, stmt, write);
829 break;
831 default:
832 break;
835 if (write && partial_ref && ret)
836 ret->grp_partial_lhs = 1;
838 return ret;
841 /* Callback of scan_function. Scan expression EXPR and create access
842 structures for all accesses to candidates for scalarization. Return true if
843 any access has been inserted. */
845 static bool
846 build_access_from_expr (tree *expr_ptr,
847 gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED, bool write,
848 void *data ATTRIBUTE_UNUSED)
850 return build_access_from_expr_1 (expr_ptr, gsi_stmt (*gsi), write) != NULL;
853 /* Disqualify LHS and RHS for scalarization if STMT must end its basic block in
854 modes in which it matters, return true iff they have been disqualified. RHS
855 may be NULL, in that case ignore it. If we scalarize an aggregate in
856 intra-SRA we may need to add statements after each statement. This is not
857 possible if a statement unconditionally has to end the basic block. */
858 static bool
859 disqualify_ops_if_throwing_stmt (gimple stmt, tree lhs, tree rhs)
861 if ((sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
862 && (stmt_can_throw_internal (stmt) || stmt_ends_bb_p (stmt)))
864 disqualify_base_of_expr (lhs, "LHS of a throwing stmt.");
865 if (rhs)
866 disqualify_base_of_expr (rhs, "RHS of a throwing stmt.");
867 return true;
869 return false;
873 /* Result code for scan_assign callback for scan_function. */
874 enum scan_assign_result { SRA_SA_NONE, /* nothing done for the stmt */
875 SRA_SA_PROCESSED, /* stmt analyzed/changed */
876 SRA_SA_REMOVED }; /* stmt redundant and eliminated */
879 /* Callback of scan_function. Scan expressions occuring in the statement
880 pointed to by STMT_EXPR, create access structures for all accesses to
881 candidates for scalarization and remove those candidates which occur in
882 statements or expressions that prevent them from being split apart. Return
883 true if any access has been inserted. */
885 static enum scan_assign_result
886 build_accesses_from_assign (gimple *stmt_ptr,
887 gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED,
888 void *data ATTRIBUTE_UNUSED)
890 gimple stmt = *stmt_ptr;
891 tree *lhs_ptr, *rhs_ptr;
892 struct access *lacc, *racc;
894 if (!gimple_assign_single_p (stmt))
895 return SRA_SA_NONE;
897 lhs_ptr = gimple_assign_lhs_ptr (stmt);
898 rhs_ptr = gimple_assign_rhs1_ptr (stmt);
900 if (disqualify_ops_if_throwing_stmt (stmt, *lhs_ptr, *rhs_ptr))
901 return SRA_SA_NONE;
903 racc = build_access_from_expr_1 (rhs_ptr, stmt, false);
904 lacc = build_access_from_expr_1 (lhs_ptr, stmt, true);
906 if (lacc && racc
907 && (sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
908 && !lacc->grp_unscalarizable_region
909 && !racc->grp_unscalarizable_region
910 && AGGREGATE_TYPE_P (TREE_TYPE (*lhs_ptr))
911 /* FIXME: Turn the following line into an assert after PR 40058 is
912 fixed. */
913 && lacc->size == racc->size
914 && useless_type_conversion_p (lacc->type, racc->type))
916 struct assign_link *link;
918 link = (struct assign_link *) pool_alloc (link_pool);
919 memset (link, 0, sizeof (struct assign_link));
921 link->lacc = lacc;
922 link->racc = racc;
924 add_link_to_rhs (racc, link);
927 return (lacc || racc) ? SRA_SA_PROCESSED : SRA_SA_NONE;
930 /* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine
931 GIMPLE_ASM operands with memory constrains which cannot be scalarized. */
933 static bool
934 asm_visit_addr (gimple stmt ATTRIBUTE_UNUSED, tree op,
935 void *data ATTRIBUTE_UNUSED)
937 if (DECL_P (op))
938 disqualify_candidate (op, "Non-scalarizable GIMPLE_ASM operand.");
940 return false;
944 /* Scan function and look for interesting statements. Return true if any has
945 been found or processed, as indicated by callbacks. SCAN_EXPR is a callback
946 called on all expressions within statements except assign statements and
947 those deemed entirely unsuitable for some reason (all operands in such
948 statements and expression are removed from candidate_bitmap). SCAN_ASSIGN
949 is a callback called on all assign statements, HANDLE_SSA_DEFS is a callback
950 called on assign statements and those call statements which have a lhs, it
951 can be NULL. ANALYSIS_STAGE is true when running in the analysis stage of a
952 pass and thus no statement is being modified. DATA is a pointer passed to
953 all callbacks. If any single callback returns true, this function also
954 returns true, otherwise it returns false. */
956 static bool
957 scan_function (bool (*scan_expr) (tree *, gimple_stmt_iterator *, bool, void *),
958 enum scan_assign_result (*scan_assign) (gimple *,
959 gimple_stmt_iterator *,
960 void *),
961 bool (*handle_ssa_defs)(gimple, void *),
962 bool analysis_stage, void *data)
964 gimple_stmt_iterator gsi;
965 basic_block bb;
966 unsigned i;
967 tree *t;
968 bool ret = false;
970 FOR_EACH_BB (bb)
972 bool bb_changed = false;
974 if (handle_ssa_defs)
975 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
976 ret |= handle_ssa_defs (gsi_stmt (gsi), data);
978 gsi = gsi_start_bb (bb);
979 while (!gsi_end_p (gsi))
981 gimple stmt = gsi_stmt (gsi);
982 enum scan_assign_result assign_result;
983 bool any = false, deleted = false;
985 if (analysis_stage && final_bbs && stmt_can_throw_external (stmt))
986 bitmap_set_bit (final_bbs, bb->index);
987 switch (gimple_code (stmt))
989 case GIMPLE_RETURN:
990 t = gimple_return_retval_ptr (stmt);
991 if (*t != NULL_TREE)
992 any |= scan_expr (t, &gsi, false, data);
993 if (analysis_stage && final_bbs)
994 bitmap_set_bit (final_bbs, bb->index);
995 break;
997 case GIMPLE_ASSIGN:
998 assign_result = scan_assign (&stmt, &gsi, data);
999 any |= assign_result == SRA_SA_PROCESSED;
1000 deleted = assign_result == SRA_SA_REMOVED;
1001 if (handle_ssa_defs && assign_result != SRA_SA_REMOVED)
1002 any |= handle_ssa_defs (stmt, data);
1003 break;
1005 case GIMPLE_CALL:
1006 /* Operands must be processed before the lhs. */
1007 for (i = 0; i < gimple_call_num_args (stmt); i++)
1009 tree *argp = gimple_call_arg_ptr (stmt, i);
1010 any |= scan_expr (argp, &gsi, false, data);
1013 if (analysis_stage)
1015 tree dest = gimple_call_fndecl (stmt);
1016 int flags = gimple_call_flags (stmt);
1018 if (dest
1019 && DECL_BUILT_IN_CLASS (dest) == BUILT_IN_NORMAL
1020 && DECL_FUNCTION_CODE (dest) == BUILT_IN_APPLY_ARGS)
1021 encountered_apply_args = true;
1023 if (final_bbs
1024 && (flags & (ECF_CONST | ECF_PURE)) == 0)
1025 bitmap_set_bit (final_bbs, bb->index);
1028 if (gimple_call_lhs (stmt))
1030 tree *lhs_ptr = gimple_call_lhs_ptr (stmt);
1031 if (!analysis_stage
1032 || !disqualify_ops_if_throwing_stmt (stmt,
1033 *lhs_ptr, NULL))
1035 any |= scan_expr (lhs_ptr, &gsi, true, data);
1036 if (handle_ssa_defs)
1037 any |= handle_ssa_defs (stmt, data);
1040 break;
1042 case GIMPLE_ASM:
1043 if (analysis_stage)
1045 walk_stmt_load_store_addr_ops (stmt, NULL, NULL, NULL,
1046 asm_visit_addr);
1047 if (final_bbs)
1048 bitmap_set_bit (final_bbs, bb->index);
1050 for (i = 0; i < gimple_asm_ninputs (stmt); i++)
1052 tree *op = &TREE_VALUE (gimple_asm_input_op (stmt, i));
1053 any |= scan_expr (op, &gsi, false, data);
1055 for (i = 0; i < gimple_asm_noutputs (stmt); i++)
1057 tree *op = &TREE_VALUE (gimple_asm_output_op (stmt, i));
1058 any |= scan_expr (op, &gsi, true, data);
1060 break;
1062 default:
1063 break;
1066 if (any)
1068 ret = true;
1070 if (!analysis_stage)
1072 bb_changed = true;
1073 update_stmt (stmt);
1074 maybe_clean_eh_stmt (stmt);
1077 if (deleted)
1078 bb_changed = true;
1079 else
1081 gsi_next (&gsi);
1082 ret = true;
1085 if (!analysis_stage && bb_changed && sra_mode == SRA_MODE_EARLY_IPA)
1086 gimple_purge_dead_eh_edges (bb);
1089 return ret;
1092 /* Helper of QSORT function. There are pointers to accesses in the array. An
1093 access is considered smaller than another if it has smaller offset or if the
1094 offsets are the same but is size is bigger. */
1096 static int
1097 compare_access_positions (const void *a, const void *b)
1099 const access_p *fp1 = (const access_p *) a;
1100 const access_p *fp2 = (const access_p *) b;
1101 const access_p f1 = *fp1;
1102 const access_p f2 = *fp2;
1104 if (f1->offset != f2->offset)
1105 return f1->offset < f2->offset ? -1 : 1;
1107 if (f1->size == f2->size)
1109 /* Put any non-aggregate type before any aggregate type. */
1110 if (!is_gimple_reg_type (f1->type)
1111 && is_gimple_reg_type (f2->type))
1112 return 1;
1113 else if (is_gimple_reg_type (f1->type)
1114 && !is_gimple_reg_type (f2->type))
1115 return -1;
1116 /* Put the integral type with the bigger precision first. */
1117 else if (INTEGRAL_TYPE_P (f1->type)
1118 && INTEGRAL_TYPE_P (f2->type))
1119 return TYPE_PRECISION (f1->type) > TYPE_PRECISION (f2->type) ? -1 : 1;
1120 /* Put any integral type with non-full precision last. */
1121 else if (INTEGRAL_TYPE_P (f1->type)
1122 && (TREE_INT_CST_LOW (TYPE_SIZE (f1->type))
1123 != TYPE_PRECISION (f1->type)))
1124 return 1;
1125 else if (INTEGRAL_TYPE_P (f2->type)
1126 && (TREE_INT_CST_LOW (TYPE_SIZE (f2->type))
1127 != TYPE_PRECISION (f2->type)))
1128 return -1;
1129 /* Stabilize the sort. */
1130 return TYPE_UID (f1->type) - TYPE_UID (f2->type);
1133 /* We want the bigger accesses first, thus the opposite operator in the next
1134 line: */
1135 return f1->size > f2->size ? -1 : 1;
1139 /* Append a name of the declaration to the name obstack. A helper function for
1140 make_fancy_name. */
1142 static void
1143 make_fancy_decl_name (tree decl)
1145 char buffer[32];
1147 tree name = DECL_NAME (decl);
1148 if (name)
1149 obstack_grow (&name_obstack, IDENTIFIER_POINTER (name),
1150 IDENTIFIER_LENGTH (name));
1151 else
1153 sprintf (buffer, "D%u", DECL_UID (decl));
1154 obstack_grow (&name_obstack, buffer, strlen (buffer));
1158 /* Helper for make_fancy_name. */
1160 static void
1161 make_fancy_name_1 (tree expr)
1163 char buffer[32];
1164 tree index;
1166 if (DECL_P (expr))
1168 make_fancy_decl_name (expr);
1169 return;
1172 switch (TREE_CODE (expr))
1174 case COMPONENT_REF:
1175 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1176 obstack_1grow (&name_obstack, '$');
1177 make_fancy_decl_name (TREE_OPERAND (expr, 1));
1178 break;
1180 case ARRAY_REF:
1181 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1182 obstack_1grow (&name_obstack, '$');
1183 /* Arrays with only one element may not have a constant as their
1184 index. */
1185 index = TREE_OPERAND (expr, 1);
1186 if (TREE_CODE (index) != INTEGER_CST)
1187 break;
1188 sprintf (buffer, HOST_WIDE_INT_PRINT_DEC, TREE_INT_CST_LOW (index));
1189 obstack_grow (&name_obstack, buffer, strlen (buffer));
1191 break;
1193 case BIT_FIELD_REF:
1194 case REALPART_EXPR:
1195 case IMAGPART_EXPR:
1196 gcc_unreachable (); /* we treat these as scalars. */
1197 break;
1198 default:
1199 break;
1203 /* Create a human readable name for replacement variable of ACCESS. */
1205 static char *
1206 make_fancy_name (tree expr)
1208 make_fancy_name_1 (expr);
1209 obstack_1grow (&name_obstack, '\0');
1210 return XOBFINISH (&name_obstack, char *);
1213 /* Helper function for build_ref_for_offset. */
1215 static bool
1216 build_ref_for_offset_1 (tree *res, tree type, HOST_WIDE_INT offset,
1217 tree exp_type)
1219 while (1)
1221 tree fld;
1222 tree tr_size, index, minidx;
1223 HOST_WIDE_INT el_size;
1225 if (offset == 0 && exp_type
1226 && types_compatible_p (exp_type, type))
1227 return true;
1229 switch (TREE_CODE (type))
1231 case UNION_TYPE:
1232 case QUAL_UNION_TYPE:
1233 case RECORD_TYPE:
1234 /* Some ADA records are half-unions, treat all of them the same. */
1235 for (fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
1237 HOST_WIDE_INT pos, size;
1238 tree expr, *expr_ptr;
1240 if (TREE_CODE (fld) != FIELD_DECL)
1241 continue;
1243 pos = int_bit_position (fld);
1244 gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0);
1245 size = tree_low_cst (DECL_SIZE (fld), 1);
1246 if (pos > offset || (pos + size) <= offset)
1247 continue;
1249 if (res)
1251 expr = build3 (COMPONENT_REF, TREE_TYPE (fld), *res, fld,
1252 NULL_TREE);
1253 expr_ptr = &expr;
1255 else
1256 expr_ptr = NULL;
1257 if (build_ref_for_offset_1 (expr_ptr, TREE_TYPE (fld),
1258 offset - pos, exp_type))
1260 if (res)
1261 *res = expr;
1262 return true;
1265 return false;
1267 case ARRAY_TYPE:
1268 tr_size = TYPE_SIZE (TREE_TYPE (type));
1269 if (!tr_size || !host_integerp (tr_size, 1))
1270 return false;
1271 el_size = tree_low_cst (tr_size, 1);
1273 minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
1274 if (TREE_CODE (minidx) != INTEGER_CST)
1275 return false;
1276 if (res)
1278 index = build_int_cst (TYPE_DOMAIN (type), offset / el_size);
1279 if (!integer_zerop (minidx))
1280 index = int_const_binop (PLUS_EXPR, index, minidx, 0);
1281 *res = build4 (ARRAY_REF, TREE_TYPE (type), *res, index,
1282 NULL_TREE, NULL_TREE);
1284 offset = offset % el_size;
1285 type = TREE_TYPE (type);
1286 break;
1288 default:
1289 if (offset != 0)
1290 return false;
1292 if (exp_type)
1293 return false;
1294 else
1295 return true;
1300 /* Construct an expression that would reference a part of aggregate *EXPR of
1301 type TYPE at the given OFFSET of the type EXP_TYPE. If EXPR is NULL, the
1302 function only determines whether it can build such a reference without
1303 actually doing it.
1305 FIXME: Eventually this should be replaced with
1306 maybe_fold_offset_to_reference() from tree-ssa-ccp.c but that requires a
1307 minor rewrite of fold_stmt.
1310 bool
1311 build_ref_for_offset (tree *expr, tree type, HOST_WIDE_INT offset,
1312 tree exp_type, bool allow_ptr)
1314 location_t loc = expr ? EXPR_LOCATION (*expr) : UNKNOWN_LOCATION;
1316 if (allow_ptr && POINTER_TYPE_P (type))
1318 type = TREE_TYPE (type);
1319 if (expr)
1320 *expr = fold_build1_loc (loc, INDIRECT_REF, type, *expr);
1323 return build_ref_for_offset_1 (expr, type, offset, exp_type);
1326 /* The very first phase of intraprocedural SRA. It marks in candidate_bitmap
1327 those with type which is suitable for scalarization. */
1329 static bool
1330 find_var_candidates (void)
1332 tree var, type;
1333 referenced_var_iterator rvi;
1334 bool ret = false;
1336 FOR_EACH_REFERENCED_VAR (var, rvi)
1338 if (TREE_CODE (var) != VAR_DECL && TREE_CODE (var) != PARM_DECL)
1339 continue;
1340 type = TREE_TYPE (var);
1342 if (!AGGREGATE_TYPE_P (type)
1343 || needs_to_live_in_memory (var)
1344 || TREE_THIS_VOLATILE (var)
1345 || !COMPLETE_TYPE_P (type)
1346 || !host_integerp (TYPE_SIZE (type), 1)
1347 || tree_low_cst (TYPE_SIZE (type), 1) == 0
1348 || type_internals_preclude_sra_p (type)
1349 /* Fix for PR 41089. tree-stdarg.c needs to have va_lists intact but
1350 we also want to schedule it rather late. Thus we ignore it in
1351 the early pass. */
1352 || (sra_mode == SRA_MODE_EARLY_INTRA
1353 && (TYPE_MAIN_VARIANT (TREE_TYPE (var))
1354 == TYPE_MAIN_VARIANT (va_list_type_node))))
1355 continue;
1357 bitmap_set_bit (candidate_bitmap, DECL_UID (var));
1359 if (dump_file && (dump_flags & TDF_DETAILS))
1361 fprintf (dump_file, "Candidate (%d): ", DECL_UID (var));
1362 print_generic_expr (dump_file, var, 0);
1363 fprintf (dump_file, "\n");
1365 ret = true;
1368 return ret;
1371 /* Sort all accesses for the given variable, check for partial overlaps and
1372 return NULL if there are any. If there are none, pick a representative for
1373 each combination of offset and size and create a linked list out of them.
1374 Return the pointer to the first representative and make sure it is the first
1375 one in the vector of accesses. */
1377 static struct access *
1378 sort_and_splice_var_accesses (tree var)
1380 int i, j, access_count;
1381 struct access *res, **prev_acc_ptr = &res;
1382 VEC (access_p, heap) *access_vec;
1383 bool first = true;
1384 HOST_WIDE_INT low = -1, high = 0;
1386 access_vec = get_base_access_vector (var);
1387 if (!access_vec)
1388 return NULL;
1389 access_count = VEC_length (access_p, access_vec);
1391 /* Sort by <OFFSET, SIZE>. */
1392 qsort (VEC_address (access_p, access_vec), access_count, sizeof (access_p),
1393 compare_access_positions);
1395 i = 0;
1396 while (i < access_count)
1398 struct access *access = VEC_index (access_p, access_vec, i);
1399 bool grp_write = access->write;
1400 bool grp_read = !access->write;
1401 bool multiple_reads = false;
1402 bool grp_partial_lhs = access->grp_partial_lhs;
1403 bool first_scalar = is_gimple_reg_type (access->type);
1404 bool unscalarizable_region = access->grp_unscalarizable_region;
1406 if (first || access->offset >= high)
1408 first = false;
1409 low = access->offset;
1410 high = access->offset + access->size;
1412 else if (access->offset > low && access->offset + access->size > high)
1413 return NULL;
1414 else
1415 gcc_assert (access->offset >= low
1416 && access->offset + access->size <= high);
1418 j = i + 1;
1419 while (j < access_count)
1421 struct access *ac2 = VEC_index (access_p, access_vec, j);
1422 if (ac2->offset != access->offset || ac2->size != access->size)
1423 break;
1424 if (ac2->write)
1425 grp_write = true;
1426 else
1428 if (grp_read)
1429 multiple_reads = true;
1430 else
1431 grp_read = true;
1433 grp_partial_lhs |= ac2->grp_partial_lhs;
1434 unscalarizable_region |= ac2->grp_unscalarizable_region;
1435 relink_to_new_repr (access, ac2);
1437 /* If there are both aggregate-type and scalar-type accesses with
1438 this combination of size and offset, the comparison function
1439 should have put the scalars first. */
1440 gcc_assert (first_scalar || !is_gimple_reg_type (ac2->type));
1441 ac2->group_representative = access;
1442 j++;
1445 i = j;
1447 access->group_representative = access;
1448 access->grp_write = grp_write;
1449 access->grp_read = grp_read;
1450 access->grp_hint = multiple_reads;
1451 access->grp_partial_lhs = grp_partial_lhs;
1452 access->grp_unscalarizable_region = unscalarizable_region;
1453 if (access->first_link)
1454 add_access_to_work_queue (access);
1456 *prev_acc_ptr = access;
1457 prev_acc_ptr = &access->next_grp;
1460 gcc_assert (res == VEC_index (access_p, access_vec, 0));
1461 return res;
1464 /* Create a variable for the given ACCESS which determines the type, name and a
1465 few other properties. Return the variable declaration and store it also to
1466 ACCESS->replacement. */
1468 static tree
1469 create_access_replacement (struct access *access)
1471 tree repl;
1473 repl = create_tmp_var (access->type, "SR");
1474 get_var_ann (repl);
1475 add_referenced_var (repl);
1476 mark_sym_for_renaming (repl);
1478 if (!access->grp_partial_lhs
1479 && (TREE_CODE (access->type) == COMPLEX_TYPE
1480 || TREE_CODE (access->type) == VECTOR_TYPE))
1481 DECL_GIMPLE_REG_P (repl) = 1;
1483 DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base);
1484 DECL_ARTIFICIAL (repl) = 1;
1486 if (DECL_NAME (access->base)
1487 && !DECL_IGNORED_P (access->base)
1488 && !DECL_ARTIFICIAL (access->base))
1490 char *pretty_name = make_fancy_name (access->expr);
1492 DECL_NAME (repl) = get_identifier (pretty_name);
1493 obstack_free (&name_obstack, pretty_name);
1495 SET_DECL_DEBUG_EXPR (repl, access->expr);
1496 DECL_DEBUG_EXPR_IS_FROM (repl) = 1;
1497 DECL_IGNORED_P (repl) = 0;
1500 DECL_IGNORED_P (repl) = DECL_IGNORED_P (access->base);
1501 TREE_NO_WARNING (repl) = TREE_NO_WARNING (access->base);
1503 if (dump_file)
1505 fprintf (dump_file, "Created a replacement for ");
1506 print_generic_expr (dump_file, access->base, 0);
1507 fprintf (dump_file, " offset: %u, size: %u: ",
1508 (unsigned) access->offset, (unsigned) access->size);
1509 print_generic_expr (dump_file, repl, 0);
1510 fprintf (dump_file, "\n");
1512 sra_stats.replacements++;
1514 return repl;
1517 /* Return ACCESS scalar replacement, create it if it does not exist yet. */
1519 static inline tree
1520 get_access_replacement (struct access *access)
1522 gcc_assert (access->grp_to_be_replaced);
1524 if (!access->replacement_decl)
1525 access->replacement_decl = create_access_replacement (access);
1526 return access->replacement_decl;
1529 /* Build a subtree of accesses rooted in *ACCESS, and move the pointer in the
1530 linked list along the way. Stop when *ACCESS is NULL or the access pointed
1531 to it is not "within" the root. */
1533 static void
1534 build_access_subtree (struct access **access)
1536 struct access *root = *access, *last_child = NULL;
1537 HOST_WIDE_INT limit = root->offset + root->size;
1539 *access = (*access)->next_grp;
1540 while (*access && (*access)->offset + (*access)->size <= limit)
1542 if (!last_child)
1543 root->first_child = *access;
1544 else
1545 last_child->next_sibling = *access;
1546 last_child = *access;
1548 build_access_subtree (access);
1552 /* Build a tree of access representatives, ACCESS is the pointer to the first
1553 one, others are linked in a list by the next_grp field. Decide about scalar
1554 replacements on the way, return true iff any are to be created. */
1556 static void
1557 build_access_trees (struct access *access)
1559 while (access)
1561 struct access *root = access;
1563 build_access_subtree (&access);
1564 root->next_grp = access;
1568 /* Return true if expr contains some ARRAY_REFs into a variable bounded
1569 array. */
1571 static bool
1572 expr_with_var_bounded_array_refs_p (tree expr)
1574 while (handled_component_p (expr))
1576 if (TREE_CODE (expr) == ARRAY_REF
1577 && !host_integerp (array_ref_low_bound (expr), 0))
1578 return true;
1579 expr = TREE_OPERAND (expr, 0);
1581 return false;
1584 /* Analyze the subtree of accesses rooted in ROOT, scheduling replacements when
1585 both seeming beneficial and when ALLOW_REPLACEMENTS allows it. Also set
1586 all sorts of access flags appropriately along the way, notably always ser
1587 grp_read when MARK_READ is true and grp_write when MARK_WRITE is true. */
1589 static bool
1590 analyze_access_subtree (struct access *root, bool allow_replacements,
1591 bool mark_read, bool mark_write)
1593 struct access *child;
1594 HOST_WIDE_INT limit = root->offset + root->size;
1595 HOST_WIDE_INT covered_to = root->offset;
1596 bool scalar = is_gimple_reg_type (root->type);
1597 bool hole = false, sth_created = false;
1598 bool direct_read = root->grp_read;
1600 if (mark_read)
1601 root->grp_read = true;
1602 else if (root->grp_read)
1603 mark_read = true;
1605 if (mark_write)
1606 root->grp_write = true;
1607 else if (root->grp_write)
1608 mark_write = true;
1610 if (root->grp_unscalarizable_region)
1611 allow_replacements = false;
1613 if (allow_replacements && expr_with_var_bounded_array_refs_p (root->expr))
1614 allow_replacements = false;
1616 for (child = root->first_child; child; child = child->next_sibling)
1618 if (!hole && child->offset < covered_to)
1619 hole = true;
1620 else
1621 covered_to += child->size;
1623 sth_created |= analyze_access_subtree (child, allow_replacements,
1624 mark_read, mark_write);
1626 root->grp_unscalarized_data |= child->grp_unscalarized_data;
1627 hole |= !child->grp_covered;
1630 if (allow_replacements && scalar && !root->first_child
1631 && (root->grp_hint
1632 || (direct_read && root->grp_write)))
1634 if (dump_file && (dump_flags & TDF_DETAILS))
1636 fprintf (dump_file, "Marking ");
1637 print_generic_expr (dump_file, root->base, 0);
1638 fprintf (dump_file, " offset: %u, size: %u: ",
1639 (unsigned) root->offset, (unsigned) root->size);
1640 fprintf (dump_file, " to be replaced.\n");
1643 root->grp_to_be_replaced = 1;
1644 sth_created = true;
1645 hole = false;
1647 else if (covered_to < limit)
1648 hole = true;
1650 if (sth_created && !hole)
1652 root->grp_covered = 1;
1653 return true;
1655 if (root->grp_write || TREE_CODE (root->base) == PARM_DECL)
1656 root->grp_unscalarized_data = 1; /* not covered and written to */
1657 if (sth_created)
1658 return true;
1659 return false;
1662 /* Analyze all access trees linked by next_grp by the means of
1663 analyze_access_subtree. */
1664 static bool
1665 analyze_access_trees (struct access *access)
1667 bool ret = false;
1669 while (access)
1671 if (analyze_access_subtree (access, true, false, false))
1672 ret = true;
1673 access = access->next_grp;
1676 return ret;
1679 /* Return true iff a potential new child of LACC at offset OFFSET and with size
1680 SIZE would conflict with an already existing one. If exactly such a child
1681 already exists in LACC, store a pointer to it in EXACT_MATCH. */
1683 static bool
1684 child_would_conflict_in_lacc (struct access *lacc, HOST_WIDE_INT norm_offset,
1685 HOST_WIDE_INT size, struct access **exact_match)
1687 struct access *child;
1689 for (child = lacc->first_child; child; child = child->next_sibling)
1691 if (child->offset == norm_offset && child->size == size)
1693 *exact_match = child;
1694 return true;
1697 if (child->offset < norm_offset + size
1698 && child->offset + child->size > norm_offset)
1699 return true;
1702 return false;
1705 /* Create a new child access of PARENT, with all properties just like MODEL
1706 except for its offset and with its grp_write false and grp_read true.
1707 Return the new access or NULL if it cannot be created. Note that this access
1708 is created long after all splicing and sorting, it's not located in any
1709 access vector and is automatically a representative of its group. */
1711 static struct access *
1712 create_artificial_child_access (struct access *parent, struct access *model,
1713 HOST_WIDE_INT new_offset)
1715 struct access *access;
1716 struct access **child;
1717 tree expr = parent->base;;
1719 gcc_assert (!model->grp_unscalarizable_region);
1721 if (!build_ref_for_offset (&expr, TREE_TYPE (expr), new_offset,
1722 model->type, false))
1723 return NULL;
1725 access = (struct access *) pool_alloc (access_pool);
1726 memset (access, 0, sizeof (struct access));
1727 access->base = parent->base;
1728 access->expr = expr;
1729 access->offset = new_offset;
1730 access->size = model->size;
1731 access->type = model->type;
1732 access->grp_write = true;
1733 access->grp_read = false;
1735 child = &parent->first_child;
1736 while (*child && (*child)->offset < new_offset)
1737 child = &(*child)->next_sibling;
1739 access->next_sibling = *child;
1740 *child = access;
1742 return access;
1746 /* Propagate all subaccesses of RACC across an assignment link to LACC. Return
1747 true if any new subaccess was created. Additionally, if RACC is a scalar
1748 access but LACC is not, change the type of the latter, if possible. */
1750 static bool
1751 propagate_subacesses_accross_link (struct access *lacc, struct access *racc)
1753 struct access *rchild;
1754 HOST_WIDE_INT norm_delta = lacc->offset - racc->offset;
1755 bool ret = false;
1757 if (is_gimple_reg_type (lacc->type)
1758 || lacc->grp_unscalarizable_region
1759 || racc->grp_unscalarizable_region)
1760 return false;
1762 if (!lacc->first_child && !racc->first_child
1763 && is_gimple_reg_type (racc->type))
1765 tree t = lacc->base;
1767 if (build_ref_for_offset (&t, TREE_TYPE (t), lacc->offset, racc->type,
1768 false))
1770 lacc->expr = t;
1771 lacc->type = racc->type;
1773 return false;
1776 for (rchild = racc->first_child; rchild; rchild = rchild->next_sibling)
1778 struct access *new_acc = NULL;
1779 HOST_WIDE_INT norm_offset = rchild->offset + norm_delta;
1781 if (rchild->grp_unscalarizable_region)
1782 continue;
1784 if (child_would_conflict_in_lacc (lacc, norm_offset, rchild->size,
1785 &new_acc))
1787 if (new_acc)
1789 rchild->grp_hint = 1;
1790 new_acc->grp_hint |= new_acc->grp_read;
1791 if (rchild->first_child)
1792 ret |= propagate_subacesses_accross_link (new_acc, rchild);
1794 continue;
1797 /* If a (part of) a union field is on the RHS of an assignment, it can
1798 have sub-accesses which do not make sense on the LHS (PR 40351).
1799 Check that this is not the case. */
1800 if (!build_ref_for_offset (NULL, TREE_TYPE (lacc->base), norm_offset,
1801 rchild->type, false))
1802 continue;
1804 rchild->grp_hint = 1;
1805 new_acc = create_artificial_child_access (lacc, rchild, norm_offset);
1806 if (new_acc)
1808 ret = true;
1809 if (racc->first_child)
1810 propagate_subacesses_accross_link (new_acc, rchild);
1814 return ret;
1817 /* Propagate all subaccesses across assignment links. */
1819 static void
1820 propagate_all_subaccesses (void)
1822 while (work_queue_head)
1824 struct access *racc = pop_access_from_work_queue ();
1825 struct assign_link *link;
1827 gcc_assert (racc->first_link);
1829 for (link = racc->first_link; link; link = link->next)
1831 struct access *lacc = link->lacc;
1833 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
1834 continue;
1835 lacc = lacc->group_representative;
1836 if (propagate_subacesses_accross_link (lacc, racc)
1837 && lacc->first_link)
1838 add_access_to_work_queue (lacc);
1843 /* Go through all accesses collected throughout the (intraprocedural) analysis
1844 stage, exclude overlapping ones, identify representatives and build trees
1845 out of them, making decisions about scalarization on the way. Return true
1846 iff there are any to-be-scalarized variables after this stage. */
1848 static bool
1849 analyze_all_variable_accesses (void)
1851 tree var;
1852 referenced_var_iterator rvi;
1853 int res = 0;
1855 FOR_EACH_REFERENCED_VAR (var, rvi)
1856 if (bitmap_bit_p (candidate_bitmap, DECL_UID (var)))
1858 struct access *access;
1860 access = sort_and_splice_var_accesses (var);
1861 if (access)
1862 build_access_trees (access);
1863 else
1864 disqualify_candidate (var,
1865 "No or inhibitingly overlapping accesses.");
1868 propagate_all_subaccesses ();
1870 FOR_EACH_REFERENCED_VAR (var, rvi)
1871 if (bitmap_bit_p (candidate_bitmap, DECL_UID (var)))
1873 struct access *access = get_first_repr_for_decl (var);
1875 if (analyze_access_trees (access))
1877 res++;
1878 if (dump_file && (dump_flags & TDF_DETAILS))
1880 fprintf (dump_file, "\nAccess trees for ");
1881 print_generic_expr (dump_file, var, 0);
1882 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
1883 dump_access_tree (dump_file, access);
1884 fprintf (dump_file, "\n");
1887 else
1888 disqualify_candidate (var, "No scalar replacements to be created.");
1891 if (res)
1893 statistics_counter_event (cfun, "Scalarized aggregates", res);
1894 return true;
1896 else
1897 return false;
1900 /* Return true iff a reference statement into aggregate AGG can be built for
1901 every single to-be-replaced accesses that is a child of ACCESS, its sibling
1902 or a child of its sibling. TOP_OFFSET is the offset from the processed
1903 access subtree that has to be subtracted from offset of each access. */
1905 static bool
1906 ref_expr_for_all_replacements_p (struct access *access, tree agg,
1907 HOST_WIDE_INT top_offset)
1911 if (access->grp_to_be_replaced
1912 && !build_ref_for_offset (NULL, TREE_TYPE (agg),
1913 access->offset - top_offset,
1914 access->type, false))
1915 return false;
1917 if (access->first_child
1918 && !ref_expr_for_all_replacements_p (access->first_child, agg,
1919 top_offset))
1920 return false;
1922 access = access->next_sibling;
1924 while (access);
1926 return true;
1929 /* Generate statements copying scalar replacements of accesses within a subtree
1930 into or out of AGG. ACCESS is the first child of the root of the subtree to
1931 be processed. AGG is an aggregate type expression (can be a declaration but
1932 does not have to be, it can for example also be an indirect_ref).
1933 TOP_OFFSET is the offset of the processed subtree which has to be subtracted
1934 from offsets of individual accesses to get corresponding offsets for AGG.
1935 If CHUNK_SIZE is non-null, copy only replacements in the interval
1936 <start_offset, start_offset + chunk_size>, otherwise copy all. GSI is a
1937 statement iterator used to place the new statements. WRITE should be true
1938 when the statements should write from AGG to the replacement and false if
1939 vice versa. if INSERT_AFTER is true, new statements will be added after the
1940 current statement in GSI, they will be added before the statement
1941 otherwise. */
1943 static void
1944 generate_subtree_copies (struct access *access, tree agg,
1945 HOST_WIDE_INT top_offset,
1946 HOST_WIDE_INT start_offset, HOST_WIDE_INT chunk_size,
1947 gimple_stmt_iterator *gsi, bool write,
1948 bool insert_after)
1952 tree expr = unshare_expr (agg);
1954 if (chunk_size && access->offset >= start_offset + chunk_size)
1955 return;
1957 if (access->grp_to_be_replaced
1958 && (chunk_size == 0
1959 || access->offset + access->size > start_offset))
1961 tree repl = get_access_replacement (access);
1962 bool ref_found;
1963 gimple stmt;
1965 ref_found = build_ref_for_offset (&expr, TREE_TYPE (agg),
1966 access->offset - top_offset,
1967 access->type, false);
1968 gcc_assert (ref_found);
1970 if (write)
1972 if (access->grp_partial_lhs)
1973 expr = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
1974 !insert_after,
1975 insert_after ? GSI_NEW_STMT
1976 : GSI_SAME_STMT);
1977 stmt = gimple_build_assign (repl, expr);
1979 else
1981 TREE_NO_WARNING (repl) = 1;
1982 if (access->grp_partial_lhs)
1983 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
1984 !insert_after,
1985 insert_after ? GSI_NEW_STMT
1986 : GSI_SAME_STMT);
1987 stmt = gimple_build_assign (expr, repl);
1990 if (insert_after)
1991 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
1992 else
1993 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
1994 update_stmt (stmt);
1995 sra_stats.subtree_copies++;
1998 if (access->first_child)
1999 generate_subtree_copies (access->first_child, agg, top_offset,
2000 start_offset, chunk_size, gsi,
2001 write, insert_after);
2003 access = access->next_sibling;
2005 while (access);
2008 /* Assign zero to all scalar replacements in an access subtree. ACCESS is the
2009 the root of the subtree to be processed. GSI is the statement iterator used
2010 for inserting statements which are added after the current statement if
2011 INSERT_AFTER is true or before it otherwise. */
2013 static void
2014 init_subtree_with_zero (struct access *access, gimple_stmt_iterator *gsi,
2015 bool insert_after)
2018 struct access *child;
2020 if (access->grp_to_be_replaced)
2022 gimple stmt;
2024 stmt = gimple_build_assign (get_access_replacement (access),
2025 fold_convert (access->type,
2026 integer_zero_node));
2027 if (insert_after)
2028 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2029 else
2030 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2031 update_stmt (stmt);
2034 for (child = access->first_child; child; child = child->next_sibling)
2035 init_subtree_with_zero (child, gsi, insert_after);
2038 /* Search for an access representative for the given expression EXPR and
2039 return it or NULL if it cannot be found. */
2041 static struct access *
2042 get_access_for_expr (tree expr)
2044 HOST_WIDE_INT offset, size, max_size;
2045 tree base;
2047 /* FIXME: This should not be necessary but Ada produces V_C_Es with a type of
2048 a different size than the size of its argument and we need the latter
2049 one. */
2050 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
2051 expr = TREE_OPERAND (expr, 0);
2053 base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
2054 if (max_size == -1 || !DECL_P (base))
2055 return NULL;
2057 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
2058 return NULL;
2060 return get_var_base_offset_size_access (base, offset, max_size);
2063 /* Callback for scan_function. Replace the expression EXPR with a scalar
2064 replacement if there is one and generate other statements to do type
2065 conversion or subtree copying if necessary. GSI is used to place newly
2066 created statements, WRITE is true if the expression is being written to (it
2067 is on a LHS of a statement or output in an assembly statement). */
2069 static bool
2070 sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write,
2071 void *data ATTRIBUTE_UNUSED)
2073 struct access *access;
2074 tree type, bfr;
2076 if (TREE_CODE (*expr) == BIT_FIELD_REF)
2078 bfr = *expr;
2079 expr = &TREE_OPERAND (*expr, 0);
2081 else
2082 bfr = NULL_TREE;
2084 if (TREE_CODE (*expr) == REALPART_EXPR || TREE_CODE (*expr) == IMAGPART_EXPR)
2085 expr = &TREE_OPERAND (*expr, 0);
2086 access = get_access_for_expr (*expr);
2087 if (!access)
2088 return false;
2089 type = TREE_TYPE (*expr);
2091 if (access->grp_to_be_replaced)
2093 tree repl = get_access_replacement (access);
2094 /* If we replace a non-register typed access simply use the original
2095 access expression to extract the scalar component afterwards.
2096 This happens if scalarizing a function return value or parameter
2097 like in gcc.c-torture/execute/20041124-1.c, 20050316-1.c and
2098 gcc.c-torture/compile/20011217-1.c. */
2099 if (!is_gimple_reg_type (type))
2101 gimple stmt;
2102 if (write)
2104 tree ref = unshare_expr (access->expr);
2105 if (access->grp_partial_lhs)
2106 ref = force_gimple_operand_gsi (gsi, ref, true, NULL_TREE,
2107 false, GSI_NEW_STMT);
2108 stmt = gimple_build_assign (repl, ref);
2109 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2111 else
2113 if (access->grp_partial_lhs)
2114 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
2115 true, GSI_SAME_STMT);
2116 stmt = gimple_build_assign (unshare_expr (access->expr), repl);
2117 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2120 else
2122 gcc_assert (useless_type_conversion_p (type, access->type));
2123 *expr = repl;
2125 sra_stats.exprs++;
2128 if (access->first_child)
2130 HOST_WIDE_INT start_offset, chunk_size;
2131 if (bfr
2132 && host_integerp (TREE_OPERAND (bfr, 1), 1)
2133 && host_integerp (TREE_OPERAND (bfr, 2), 1))
2135 chunk_size = tree_low_cst (TREE_OPERAND (bfr, 1), 1);
2136 start_offset = access->offset
2137 + tree_low_cst (TREE_OPERAND (bfr, 2), 1);
2139 else
2140 start_offset = chunk_size = 0;
2142 generate_subtree_copies (access->first_child, access->base, 0,
2143 start_offset, chunk_size, gsi, write, write);
2145 return true;
2148 /* Where scalar replacements of the RHS have been written to when a replacement
2149 of a LHS of an assigments cannot be direclty loaded from a replacement of
2150 the RHS. */
2151 enum unscalarized_data_handling { SRA_UDH_NONE, /* Nothing done so far. */
2152 SRA_UDH_RIGHT, /* Data flushed to the RHS. */
2153 SRA_UDH_LEFT }; /* Data flushed to the LHS. */
2155 /* Store all replacements in the access tree rooted in TOP_RACC either to their
2156 base aggregate if there are unscalarized data or directly to LHS
2157 otherwise. */
2159 static enum unscalarized_data_handling
2160 handle_unscalarized_data_in_subtree (struct access *top_racc, tree lhs,
2161 gimple_stmt_iterator *gsi)
2163 if (top_racc->grp_unscalarized_data)
2165 generate_subtree_copies (top_racc->first_child, top_racc->base, 0, 0, 0,
2166 gsi, false, false);
2167 return SRA_UDH_RIGHT;
2169 else
2171 generate_subtree_copies (top_racc->first_child, lhs, top_racc->offset,
2172 0, 0, gsi, false, false);
2173 return SRA_UDH_LEFT;
2178 /* Try to generate statements to load all sub-replacements in an access
2179 (sub)tree (LACC is the first child) from scalar replacements in the TOP_RACC
2180 (sub)tree. If that is not possible, refresh the TOP_RACC base aggregate and
2181 load the accesses from it. LEFT_OFFSET is the offset of the left whole
2182 subtree being copied, RIGHT_OFFSET is the same thing for the right subtree.
2183 GSI is stmt iterator used for statement insertions. *REFRESHED is true iff
2184 the rhs top aggregate has already been refreshed by contents of its scalar
2185 reductions and is set to true if this function has to do it. */
2187 static void
2188 load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc,
2189 HOST_WIDE_INT left_offset,
2190 HOST_WIDE_INT right_offset,
2191 gimple_stmt_iterator *old_gsi,
2192 gimple_stmt_iterator *new_gsi,
2193 enum unscalarized_data_handling *refreshed,
2194 tree lhs)
2196 location_t loc = EXPR_LOCATION (lacc->expr);
2199 if (lacc->grp_to_be_replaced)
2201 struct access *racc;
2202 HOST_WIDE_INT offset = lacc->offset - left_offset + right_offset;
2203 gimple stmt;
2204 tree rhs;
2206 racc = find_access_in_subtree (top_racc, offset, lacc->size);
2207 if (racc && racc->grp_to_be_replaced)
2209 rhs = get_access_replacement (racc);
2210 if (!useless_type_conversion_p (lacc->type, racc->type))
2211 rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, lacc->type, rhs);
2213 else
2215 bool repl_found;
2217 /* No suitable access on the right hand side, need to load from
2218 the aggregate. See if we have to update it first... */
2219 if (*refreshed == SRA_UDH_NONE)
2220 *refreshed = handle_unscalarized_data_in_subtree (top_racc,
2221 lhs, old_gsi);
2223 if (*refreshed == SRA_UDH_LEFT)
2224 rhs = unshare_expr (lacc->expr);
2225 else
2227 rhs = unshare_expr (top_racc->base);
2228 repl_found = build_ref_for_offset (&rhs,
2229 TREE_TYPE (top_racc->base),
2230 offset, lacc->type, false);
2231 gcc_assert (repl_found);
2235 stmt = gimple_build_assign (get_access_replacement (lacc), rhs);
2236 gsi_insert_after (new_gsi, stmt, GSI_NEW_STMT);
2237 update_stmt (stmt);
2238 sra_stats.subreplacements++;
2240 else if (*refreshed == SRA_UDH_NONE
2241 && lacc->grp_read && !lacc->grp_covered)
2242 *refreshed = handle_unscalarized_data_in_subtree (top_racc, lhs,
2243 old_gsi);
2245 if (lacc->first_child)
2246 load_assign_lhs_subreplacements (lacc->first_child, top_racc,
2247 left_offset, right_offset,
2248 old_gsi, new_gsi, refreshed, lhs);
2249 lacc = lacc->next_sibling;
2251 while (lacc);
2254 /* Modify assignments with a CONSTRUCTOR on their RHS. STMT contains a pointer
2255 to the assignment and GSI is the statement iterator pointing at it. Returns
2256 the same values as sra_modify_assign. */
2258 static enum scan_assign_result
2259 sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
2261 tree lhs = gimple_assign_lhs (*stmt);
2262 struct access *acc;
2264 acc = get_access_for_expr (lhs);
2265 if (!acc)
2266 return SRA_SA_NONE;
2268 if (VEC_length (constructor_elt,
2269 CONSTRUCTOR_ELTS (gimple_assign_rhs1 (*stmt))) > 0)
2271 /* I have never seen this code path trigger but if it can happen the
2272 following should handle it gracefully. */
2273 if (access_has_children_p (acc))
2274 generate_subtree_copies (acc->first_child, acc->base, 0, 0, 0, gsi,
2275 true, true);
2276 return SRA_SA_PROCESSED;
2279 if (acc->grp_covered)
2281 init_subtree_with_zero (acc, gsi, false);
2282 unlink_stmt_vdef (*stmt);
2283 gsi_remove (gsi, true);
2284 return SRA_SA_REMOVED;
2286 else
2288 init_subtree_with_zero (acc, gsi, true);
2289 return SRA_SA_PROCESSED;
2294 /* Callback of scan_function to process assign statements. It examines both
2295 sides of the statement, replaces them with a scalare replacement if there is
2296 one and generating copying of replacements if scalarized aggregates have been
2297 used in the assignment. STMT is a pointer to the assign statement, GSI is
2298 used to hold generated statements for type conversions and subtree
2299 copying. */
2301 static enum scan_assign_result
2302 sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi,
2303 void *data ATTRIBUTE_UNUSED)
2305 struct access *lacc, *racc;
2306 tree lhs, rhs;
2307 bool modify_this_stmt = false;
2308 bool force_gimple_rhs = false;
2309 location_t loc = gimple_location (*stmt);
2311 if (!gimple_assign_single_p (*stmt))
2312 return SRA_SA_NONE;
2313 lhs = gimple_assign_lhs (*stmt);
2314 rhs = gimple_assign_rhs1 (*stmt);
2316 if (TREE_CODE (rhs) == CONSTRUCTOR)
2317 return sra_modify_constructor_assign (stmt, gsi);
2319 if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (lhs) == REALPART_EXPR
2320 || TREE_CODE (rhs) == IMAGPART_EXPR || TREE_CODE (lhs) == IMAGPART_EXPR
2321 || TREE_CODE (rhs) == BIT_FIELD_REF || TREE_CODE (lhs) == BIT_FIELD_REF)
2323 modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (*stmt),
2324 gsi, false, data);
2325 modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (*stmt),
2326 gsi, true, data);
2327 return modify_this_stmt ? SRA_SA_PROCESSED : SRA_SA_NONE;
2330 lacc = get_access_for_expr (lhs);
2331 racc = get_access_for_expr (rhs);
2332 if (!lacc && !racc)
2333 return SRA_SA_NONE;
2335 if (lacc && lacc->grp_to_be_replaced)
2337 lhs = get_access_replacement (lacc);
2338 gimple_assign_set_lhs (*stmt, lhs);
2339 modify_this_stmt = true;
2340 if (lacc->grp_partial_lhs)
2341 force_gimple_rhs = true;
2342 sra_stats.exprs++;
2345 if (racc && racc->grp_to_be_replaced)
2347 rhs = get_access_replacement (racc);
2348 modify_this_stmt = true;
2349 if (racc->grp_partial_lhs)
2350 force_gimple_rhs = true;
2351 sra_stats.exprs++;
2354 if (modify_this_stmt)
2356 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
2358 /* If we can avoid creating a VIEW_CONVERT_EXPR do so.
2359 ??? This should move to fold_stmt which we simply should
2360 call after building a VIEW_CONVERT_EXPR here. */
2361 if (AGGREGATE_TYPE_P (TREE_TYPE (lhs))
2362 && !access_has_children_p (lacc))
2364 tree expr = unshare_expr (lhs);
2365 if (build_ref_for_offset (&expr, TREE_TYPE (lhs), 0,
2366 TREE_TYPE (rhs), false))
2368 lhs = expr;
2369 gimple_assign_set_lhs (*stmt, expr);
2372 else if (AGGREGATE_TYPE_P (TREE_TYPE (rhs))
2373 && !access_has_children_p (racc))
2375 tree expr = unshare_expr (rhs);
2376 if (build_ref_for_offset (&expr, TREE_TYPE (rhs), 0,
2377 TREE_TYPE (lhs), false))
2378 rhs = expr;
2380 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
2382 rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), rhs);
2383 if (!is_gimple_reg (lhs))
2384 force_gimple_rhs = true;
2388 if (force_gimple_rhs)
2389 rhs = force_gimple_operand_gsi (gsi, rhs, true, NULL_TREE,
2390 true, GSI_SAME_STMT);
2391 if (gimple_assign_rhs1 (*stmt) != rhs)
2393 gimple_assign_set_rhs_from_tree (gsi, rhs);
2394 gcc_assert (*stmt == gsi_stmt (*gsi));
2398 /* From this point on, the function deals with assignments in between
2399 aggregates when at least one has scalar reductions of some of its
2400 components. There are three possible scenarios: Both the LHS and RHS have
2401 to-be-scalarized components, 2) only the RHS has or 3) only the LHS has.
2403 In the first case, we would like to load the LHS components from RHS
2404 components whenever possible. If that is not possible, we would like to
2405 read it directly from the RHS (after updating it by storing in it its own
2406 components). If there are some necessary unscalarized data in the LHS,
2407 those will be loaded by the original assignment too. If neither of these
2408 cases happen, the original statement can be removed. Most of this is done
2409 by load_assign_lhs_subreplacements.
2411 In the second case, we would like to store all RHS scalarized components
2412 directly into LHS and if they cover the aggregate completely, remove the
2413 statement too. In the third case, we want the LHS components to be loaded
2414 directly from the RHS (DSE will remove the original statement if it
2415 becomes redundant).
2417 This is a bit complex but manageable when types match and when unions do
2418 not cause confusion in a way that we cannot really load a component of LHS
2419 from the RHS or vice versa (the access representing this level can have
2420 subaccesses that are accessible only through a different union field at a
2421 higher level - different from the one used in the examined expression).
2422 Unions are fun.
2424 Therefore, I specially handle a fourth case, happening when there is a
2425 specific type cast or it is impossible to locate a scalarized subaccess on
2426 the other side of the expression. If that happens, I simply "refresh" the
2427 RHS by storing in it is scalarized components leave the original statement
2428 there to do the copying and then load the scalar replacements of the LHS.
2429 This is what the first branch does. */
2431 if (contains_view_convert_expr_p (rhs) || contains_view_convert_expr_p (lhs)
2432 || (access_has_children_p (racc)
2433 && !ref_expr_for_all_replacements_p (racc, lhs, racc->offset))
2434 || (access_has_children_p (lacc)
2435 && !ref_expr_for_all_replacements_p (lacc, rhs, lacc->offset)))
2437 if (access_has_children_p (racc))
2438 generate_subtree_copies (racc->first_child, racc->base, 0, 0, 0,
2439 gsi, false, false);
2440 if (access_has_children_p (lacc))
2441 generate_subtree_copies (lacc->first_child, lacc->base, 0, 0, 0,
2442 gsi, true, true);
2443 sra_stats.separate_lhs_rhs_handling++;
2445 else
2447 if (access_has_children_p (lacc) && access_has_children_p (racc))
2449 gimple_stmt_iterator orig_gsi = *gsi;
2450 enum unscalarized_data_handling refreshed;
2452 if (lacc->grp_read && !lacc->grp_covered)
2453 refreshed = handle_unscalarized_data_in_subtree (racc, lhs, gsi);
2454 else
2455 refreshed = SRA_UDH_NONE;
2457 load_assign_lhs_subreplacements (lacc->first_child, racc,
2458 lacc->offset, racc->offset,
2459 &orig_gsi, gsi, &refreshed, lhs);
2460 if (refreshed != SRA_UDH_RIGHT)
2462 if (*stmt == gsi_stmt (*gsi))
2463 gsi_next (gsi);
2465 unlink_stmt_vdef (*stmt);
2466 gsi_remove (&orig_gsi, true);
2467 sra_stats.deleted++;
2468 return SRA_SA_REMOVED;
2471 else
2473 if (access_has_children_p (racc))
2475 if (!racc->grp_unscalarized_data)
2477 generate_subtree_copies (racc->first_child, lhs,
2478 racc->offset, 0, 0, gsi,
2479 false, false);
2480 gcc_assert (*stmt == gsi_stmt (*gsi));
2481 unlink_stmt_vdef (*stmt);
2482 gsi_remove (gsi, true);
2483 sra_stats.deleted++;
2484 return SRA_SA_REMOVED;
2486 else
2487 generate_subtree_copies (racc->first_child, lhs,
2488 racc->offset, 0, 0, gsi, false, true);
2490 else if (access_has_children_p (lacc))
2491 generate_subtree_copies (lacc->first_child, rhs, lacc->offset,
2492 0, 0, gsi, true, true);
2495 return modify_this_stmt ? SRA_SA_PROCESSED : SRA_SA_NONE;
2498 /* Generate statements initializing scalar replacements of parts of function
2499 parameters. */
2501 static void
2502 initialize_parameter_reductions (void)
2504 gimple_stmt_iterator gsi;
2505 gimple_seq seq = NULL;
2506 tree parm;
2508 for (parm = DECL_ARGUMENTS (current_function_decl);
2509 parm;
2510 parm = TREE_CHAIN (parm))
2512 VEC (access_p, heap) *access_vec;
2513 struct access *access;
2515 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
2516 continue;
2517 access_vec = get_base_access_vector (parm);
2518 if (!access_vec)
2519 continue;
2521 if (!seq)
2523 seq = gimple_seq_alloc ();
2524 gsi = gsi_start (seq);
2527 for (access = VEC_index (access_p, access_vec, 0);
2528 access;
2529 access = access->next_grp)
2530 generate_subtree_copies (access, parm, 0, 0, 0, &gsi, true, true);
2533 if (seq)
2534 gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR), seq);
2537 /* The "main" function of intraprocedural SRA passes. Runs the analysis and if
2538 it reveals there are components of some aggregates to be scalarized, it runs
2539 the required transformations. */
2540 static unsigned int
2541 perform_intra_sra (void)
2543 int ret = 0;
2544 sra_initialize ();
2546 if (!find_var_candidates ())
2547 goto out;
2549 if (!scan_function (build_access_from_expr, build_accesses_from_assign, NULL,
2550 true, NULL))
2551 goto out;
2553 if (!analyze_all_variable_accesses ())
2554 goto out;
2556 scan_function (sra_modify_expr, sra_modify_assign, NULL, false, NULL);
2557 initialize_parameter_reductions ();
2559 statistics_counter_event (cfun, "Scalar replacements created",
2560 sra_stats.replacements);
2561 statistics_counter_event (cfun, "Modified expressions", sra_stats.exprs);
2562 statistics_counter_event (cfun, "Subtree copy stmts",
2563 sra_stats.subtree_copies);
2564 statistics_counter_event (cfun, "Subreplacement stmts",
2565 sra_stats.subreplacements);
2566 statistics_counter_event (cfun, "Deleted stmts", sra_stats.deleted);
2567 statistics_counter_event (cfun, "Separate LHS and RHS handling",
2568 sra_stats.separate_lhs_rhs_handling);
2570 ret = TODO_update_ssa;
2572 out:
2573 sra_deinitialize ();
2574 return ret;
2577 /* Perform early intraprocedural SRA. */
2578 static unsigned int
2579 early_intra_sra (void)
2581 sra_mode = SRA_MODE_EARLY_INTRA;
2582 return perform_intra_sra ();
2585 /* Perform "late" intraprocedural SRA. */
2586 static unsigned int
2587 late_intra_sra (void)
2589 sra_mode = SRA_MODE_INTRA;
2590 return perform_intra_sra ();
2594 static bool
2595 gate_intra_sra (void)
2597 return flag_tree_sra != 0;
2601 struct gimple_opt_pass pass_sra_early =
2604 GIMPLE_PASS,
2605 "esra", /* name */
2606 gate_intra_sra, /* gate */
2607 early_intra_sra, /* execute */
2608 NULL, /* sub */
2609 NULL, /* next */
2610 0, /* static_pass_number */
2611 TV_TREE_SRA, /* tv_id */
2612 PROP_cfg | PROP_ssa, /* properties_required */
2613 0, /* properties_provided */
2614 0, /* properties_destroyed */
2615 0, /* todo_flags_start */
2616 TODO_dump_func
2617 | TODO_update_ssa
2618 | TODO_ggc_collect
2619 | TODO_verify_ssa /* todo_flags_finish */
2623 struct gimple_opt_pass pass_sra =
2626 GIMPLE_PASS,
2627 "sra", /* name */
2628 gate_intra_sra, /* gate */
2629 late_intra_sra, /* execute */
2630 NULL, /* sub */
2631 NULL, /* next */
2632 0, /* static_pass_number */
2633 TV_TREE_SRA, /* tv_id */
2634 PROP_cfg | PROP_ssa, /* properties_required */
2635 0, /* properties_provided */
2636 0, /* properties_destroyed */
2637 TODO_update_address_taken, /* todo_flags_start */
2638 TODO_dump_func
2639 | TODO_update_ssa
2640 | TODO_ggc_collect
2641 | TODO_verify_ssa /* todo_flags_finish */
2646 /* Return true iff PARM (which must be a parm_decl) is an unused scalar
2647 parameter. */
2649 static bool
2650 is_unused_scalar_param (tree parm)
2652 tree name;
2653 return (is_gimple_reg (parm)
2654 && (!(name = gimple_default_def (cfun, parm))
2655 || has_zero_uses (name)));
2658 /* Scan immediate uses of a default definition SSA name of a parameter PARM and
2659 examine whether there are any direct or otherwise infeasible ones. If so,
2660 return true, otherwise return false. PARM must be a gimple register with a
2661 non-NULL default definition. */
2663 static bool
2664 ptr_parm_has_direct_uses (tree parm)
2666 imm_use_iterator ui;
2667 gimple stmt;
2668 tree name = gimple_default_def (cfun, parm);
2669 bool ret = false;
2671 FOR_EACH_IMM_USE_STMT (stmt, ui, name)
2673 if (gimple_assign_single_p (stmt))
2675 tree rhs = gimple_assign_rhs1 (stmt);
2676 if (rhs == name)
2677 ret = true;
2678 else if (TREE_CODE (rhs) == ADDR_EXPR)
2682 rhs = TREE_OPERAND (rhs, 0);
2684 while (handled_component_p (rhs));
2685 if (INDIRECT_REF_P (rhs) && TREE_OPERAND (rhs, 0) == name)
2686 ret = true;
2689 else if (gimple_code (stmt) == GIMPLE_RETURN)
2691 tree t = gimple_return_retval (stmt);
2692 if (t == name)
2693 ret = true;
2695 else if (is_gimple_call (stmt))
2697 unsigned i;
2698 for (i = 0; i < gimple_call_num_args (stmt); i++)
2700 tree arg = gimple_call_arg (stmt, i);
2701 if (arg == name)
2703 ret = true;
2704 break;
2708 else if (!is_gimple_debug (stmt))
2709 ret = true;
2711 if (ret)
2712 BREAK_FROM_IMM_USE_STMT (ui);
2715 return ret;
2718 /* Identify candidates for reduction for IPA-SRA based on their type and mark
2719 them in candidate_bitmap. Note that these do not necessarily include
2720 parameter which are unused and thus can be removed. Return true iff any
2721 such candidate has been found. */
2723 static bool
2724 find_param_candidates (void)
2726 tree parm;
2727 int count = 0;
2728 bool ret = false;
2730 for (parm = DECL_ARGUMENTS (current_function_decl);
2731 parm;
2732 parm = TREE_CHAIN (parm))
2734 tree type;
2736 count++;
2737 if (TREE_THIS_VOLATILE (parm)
2738 || TREE_ADDRESSABLE (parm))
2739 continue;
2741 if (is_unused_scalar_param (parm))
2743 ret = true;
2744 continue;
2747 type = TREE_TYPE (parm);
2748 if (POINTER_TYPE_P (type))
2750 type = TREE_TYPE (type);
2752 if (TREE_CODE (type) == FUNCTION_TYPE
2753 || TYPE_VOLATILE (type)
2754 || !is_gimple_reg (parm)
2755 || ptr_parm_has_direct_uses (parm))
2756 continue;
2758 else if (!AGGREGATE_TYPE_P (type))
2759 continue;
2761 if (!COMPLETE_TYPE_P (type)
2762 || !host_integerp (TYPE_SIZE (type), 1)
2763 || tree_low_cst (TYPE_SIZE (type), 1) == 0
2764 || (AGGREGATE_TYPE_P (type)
2765 && type_internals_preclude_sra_p (type)))
2766 continue;
2768 bitmap_set_bit (candidate_bitmap, DECL_UID (parm));
2769 ret = true;
2770 if (dump_file && (dump_flags & TDF_DETAILS))
2772 fprintf (dump_file, "Candidate (%d): ", DECL_UID (parm));
2773 print_generic_expr (dump_file, parm, 0);
2774 fprintf (dump_file, "\n");
2778 func_param_count = count;
2779 return ret;
2782 /* Callback of walk_aliased_vdefs, marks the access passed as DATA as
2783 maybe_modified. */
2785 static bool
2786 mark_maybe_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
2787 void *data)
2789 struct access *repr = (struct access *) data;
2791 repr->grp_maybe_modified = 1;
2792 return true;
2795 /* Analyze what representatives (in linked lists accessible from
2796 REPRESENTATIVES) can be modified by side effects of statements in the
2797 current function. */
2799 static void
2800 analyze_modified_params (VEC (access_p, heap) *representatives)
2802 int i;
2804 for (i = 0; i < func_param_count; i++)
2806 struct access *repr = VEC_index (access_p, representatives, i);
2807 VEC (access_p, heap) *access_vec;
2808 int j, access_count;
2809 tree parm;
2811 if (!repr || no_accesses_p (repr))
2812 continue;
2813 parm = repr->base;
2814 if (!POINTER_TYPE_P (TREE_TYPE (parm))
2815 || repr->grp_maybe_modified)
2816 continue;
2818 access_vec = get_base_access_vector (parm);
2819 access_count = VEC_length (access_p, access_vec);
2820 for (j = 0; j < access_count; j++)
2822 struct access *access;
2823 ao_ref ar;
2825 /* All accesses are read ones, otherwise grp_maybe_modified would be
2826 trivially set. */
2827 access = VEC_index (access_p, access_vec, j);
2828 ao_ref_init (&ar, access->expr);
2829 walk_aliased_vdefs (&ar, gimple_vuse (access->stmt),
2830 mark_maybe_modified, repr, NULL);
2831 if (repr->grp_maybe_modified)
2832 break;
2837 /* Propagate distances in bb_dereferences in the opposite direction than the
2838 control flow edges, in each step storing the maximum of the current value
2839 and the minimum of all successors. These steps are repeated until the table
2840 stabilizes. Note that BBs which might terminate the functions (according to
2841 final_bbs bitmap) never updated in this way. */
2843 static void
2844 propagate_dereference_distances (void)
2846 VEC (basic_block, heap) *queue;
2847 basic_block bb;
2849 queue = VEC_alloc (basic_block, heap, last_basic_block_for_function (cfun));
2850 VEC_quick_push (basic_block, queue, ENTRY_BLOCK_PTR);
2851 FOR_EACH_BB (bb)
2853 VEC_quick_push (basic_block, queue, bb);
2854 bb->aux = bb;
2857 while (!VEC_empty (basic_block, queue))
2859 edge_iterator ei;
2860 edge e;
2861 bool change = false;
2862 int i;
2864 bb = VEC_pop (basic_block, queue);
2865 bb->aux = NULL;
2867 if (bitmap_bit_p (final_bbs, bb->index))
2868 continue;
2870 for (i = 0; i < func_param_count; i++)
2872 int idx = bb->index * func_param_count + i;
2873 bool first = true;
2874 HOST_WIDE_INT inh = 0;
2876 FOR_EACH_EDGE (e, ei, bb->succs)
2878 int succ_idx = e->dest->index * func_param_count + i;
2880 if (e->src == EXIT_BLOCK_PTR)
2881 continue;
2883 if (first)
2885 first = false;
2886 inh = bb_dereferences [succ_idx];
2888 else if (bb_dereferences [succ_idx] < inh)
2889 inh = bb_dereferences [succ_idx];
2892 if (!first && bb_dereferences[idx] < inh)
2894 bb_dereferences[idx] = inh;
2895 change = true;
2899 if (change && !bitmap_bit_p (final_bbs, bb->index))
2900 FOR_EACH_EDGE (e, ei, bb->preds)
2902 if (e->src->aux)
2903 continue;
2905 e->src->aux = e->src;
2906 VEC_quick_push (basic_block, queue, e->src);
2910 VEC_free (basic_block, heap, queue);
2913 /* Dump a dereferences TABLE with heading STR to file F. */
2915 static void
2916 dump_dereferences_table (FILE *f, const char *str, HOST_WIDE_INT *table)
2918 basic_block bb;
2920 fprintf (dump_file, str);
2921 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
2923 fprintf (f, "%4i %i ", bb->index, bitmap_bit_p (final_bbs, bb->index));
2924 if (bb != EXIT_BLOCK_PTR)
2926 int i;
2927 for (i = 0; i < func_param_count; i++)
2929 int idx = bb->index * func_param_count + i;
2930 fprintf (f, " %4" HOST_WIDE_INT_PRINT "d", table[idx]);
2933 fprintf (f, "\n");
2935 fprintf (dump_file, "\n");
2938 /* Determine what (parts of) parameters passed by reference that are not
2939 assigned to are not certainly dereferenced in this function and thus the
2940 dereferencing cannot be safely moved to the caller without potentially
2941 introducing a segfault. Mark such REPRESENTATIVES as
2942 grp_not_necessarilly_dereferenced.
2944 The dereferenced maximum "distance," i.e. the offset + size of the accessed
2945 part is calculated rather than simple booleans are calculated for each
2946 pointer parameter to handle cases when only a fraction of the whole
2947 aggregate is allocated (see testsuite/gcc.c-torture/execute/ipa-sra-2.c for
2948 an example).
2950 The maximum dereference distances for each pointer parameter and BB are
2951 already stored in bb_dereference. This routine simply propagates these
2952 values upwards by propagate_dereference_distances and then compares the
2953 distances of individual parameters in the ENTRY BB to the equivalent
2954 distances of each representative of a (fraction of a) parameter. */
2956 static void
2957 analyze_caller_dereference_legality (VEC (access_p, heap) *representatives)
2959 int i;
2961 if (dump_file && (dump_flags & TDF_DETAILS))
2962 dump_dereferences_table (dump_file,
2963 "Dereference table before propagation:\n",
2964 bb_dereferences);
2966 propagate_dereference_distances ();
2968 if (dump_file && (dump_flags & TDF_DETAILS))
2969 dump_dereferences_table (dump_file,
2970 "Dereference table after propagation:\n",
2971 bb_dereferences);
2973 for (i = 0; i < func_param_count; i++)
2975 struct access *repr = VEC_index (access_p, representatives, i);
2976 int idx = ENTRY_BLOCK_PTR->index * func_param_count + i;
2978 if (!repr || no_accesses_p (repr))
2979 continue;
2983 if ((repr->offset + repr->size) > bb_dereferences[idx])
2984 repr->grp_not_necessarilly_dereferenced = 1;
2985 repr = repr->next_grp;
2987 while (repr);
2991 /* Return the representative access for the parameter declaration PARM if it is
2992 a scalar passed by reference which is not written to and the pointer value
2993 is not used directly. Thus, if it is legal to dereference it in the caller
2994 and we can rule out modifications through aliases, such parameter should be
2995 turned into one passed by value. Return NULL otherwise. */
2997 static struct access *
2998 unmodified_by_ref_scalar_representative (tree parm)
3000 int i, access_count;
3001 struct access *access;
3002 VEC (access_p, heap) *access_vec;
3004 access_vec = get_base_access_vector (parm);
3005 gcc_assert (access_vec);
3006 access_count = VEC_length (access_p, access_vec);
3008 for (i = 0; i < access_count; i++)
3010 access = VEC_index (access_p, access_vec, i);
3011 if (access->write)
3012 return NULL;
3015 access = VEC_index (access_p, access_vec, 0);
3016 access->grp_read = 1;
3017 access->grp_scalar_ptr = 1;
3018 return access;
3021 /* Sort collected accesses for parameter PARM, identify representatives for
3022 each accessed region and link them together. Return NULL if there are
3023 different but overlapping accesses, return the special ptr value meaning
3024 there are no accesses for this parameter if that is the case and return the
3025 first representative otherwise. Set *RO_GRP if there is a group of accesses
3026 with only read (i.e. no write) accesses. */
3028 static struct access *
3029 splice_param_accesses (tree parm, bool *ro_grp)
3031 int i, j, access_count, group_count;
3032 int agg_size, total_size = 0;
3033 struct access *access, *res, **prev_acc_ptr = &res;
3034 VEC (access_p, heap) *access_vec;
3036 access_vec = get_base_access_vector (parm);
3037 if (!access_vec)
3038 return &no_accesses_representant;
3039 access_count = VEC_length (access_p, access_vec);
3041 qsort (VEC_address (access_p, access_vec), access_count, sizeof (access_p),
3042 compare_access_positions);
3044 i = 0;
3045 total_size = 0;
3046 group_count = 0;
3047 while (i < access_count)
3049 bool modification;
3050 access = VEC_index (access_p, access_vec, i);
3051 modification = access->write;
3053 /* Access is about to become group representative unless we find some
3054 nasty overlap which would preclude us from breaking this parameter
3055 apart. */
3057 j = i + 1;
3058 while (j < access_count)
3060 struct access *ac2 = VEC_index (access_p, access_vec, j);
3061 if (ac2->offset != access->offset)
3063 /* All or nothing law for parameters. */
3064 if (access->offset + access->size > ac2->offset)
3065 return NULL;
3066 else
3067 break;
3069 else if (ac2->size != access->size)
3070 return NULL;
3072 modification |= ac2->write;
3073 j++;
3076 group_count++;
3077 access->grp_maybe_modified = modification;
3078 if (!modification)
3079 *ro_grp = true;
3080 *prev_acc_ptr = access;
3081 prev_acc_ptr = &access->next_grp;
3082 total_size += access->size;
3083 i = j;
3086 if (POINTER_TYPE_P (TREE_TYPE (parm)))
3087 agg_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))), 1);
3088 else
3089 agg_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (parm)), 1);
3090 if (total_size >= agg_size)
3091 return NULL;
3093 gcc_assert (group_count > 0);
3094 return res;
3097 /* Decide whether parameters with representative accesses given by REPR should
3098 be reduced into components. */
3100 static int
3101 decide_one_param_reduction (struct access *repr)
3103 int total_size, cur_parm_size, agg_size, new_param_count, parm_size_limit;
3104 bool by_ref;
3105 tree parm;
3107 parm = repr->base;
3108 cur_parm_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (parm)), 1);
3109 gcc_assert (cur_parm_size > 0);
3111 if (POINTER_TYPE_P (TREE_TYPE (parm)))
3113 by_ref = true;
3114 agg_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))), 1);
3116 else
3118 by_ref = false;
3119 agg_size = cur_parm_size;
3122 if (dump_file)
3124 struct access *acc;
3125 fprintf (dump_file, "Evaluating PARAM group sizes for ");
3126 print_generic_expr (dump_file, parm, 0);
3127 fprintf (dump_file, " (UID: %u): \n", DECL_UID (parm));
3128 for (acc = repr; acc; acc = acc->next_grp)
3129 dump_access (dump_file, acc, true);
3132 total_size = 0;
3133 new_param_count = 0;
3135 for (; repr; repr = repr->next_grp)
3137 gcc_assert (parm == repr->base);
3138 new_param_count++;
3140 if (!by_ref || (!repr->grp_maybe_modified
3141 && !repr->grp_not_necessarilly_dereferenced))
3142 total_size += repr->size;
3143 else
3144 total_size += cur_parm_size;
3147 gcc_assert (new_param_count > 0);
3149 if (optimize_function_for_size_p (cfun))
3150 parm_size_limit = cur_parm_size;
3151 else
3152 parm_size_limit = (PARAM_VALUE (PARAM_IPA_SRA_PTR_GROWTH_FACTOR)
3153 * cur_parm_size);
3155 if (total_size < agg_size
3156 && total_size <= parm_size_limit)
3158 if (dump_file)
3159 fprintf (dump_file, " ....will be split into %i components\n",
3160 new_param_count);
3161 return new_param_count;
3163 else
3164 return 0;
3167 /* The order of the following enums is important, we need to do extra work for
3168 UNUSED_PARAMS, BY_VAL_ACCESSES and UNMODIF_BY_REF_ACCESSES. */
3169 enum ipa_splicing_result { NO_GOOD_ACCESS, UNUSED_PARAMS, BY_VAL_ACCESSES,
3170 MODIF_BY_REF_ACCESSES, UNMODIF_BY_REF_ACCESSES };
3172 /* Identify representatives of all accesses to all candidate parameters for
3173 IPA-SRA. Return result based on what representatives have been found. */
3175 static enum ipa_splicing_result
3176 splice_all_param_accesses (VEC (access_p, heap) **representatives)
3178 enum ipa_splicing_result result = NO_GOOD_ACCESS;
3179 tree parm;
3180 struct access *repr;
3182 *representatives = VEC_alloc (access_p, heap, func_param_count);
3184 for (parm = DECL_ARGUMENTS (current_function_decl);
3185 parm;
3186 parm = TREE_CHAIN (parm))
3188 if (is_unused_scalar_param (parm))
3190 VEC_quick_push (access_p, *representatives,
3191 &no_accesses_representant);
3192 if (result == NO_GOOD_ACCESS)
3193 result = UNUSED_PARAMS;
3195 else if (POINTER_TYPE_P (TREE_TYPE (parm))
3196 && is_gimple_reg_type (TREE_TYPE (TREE_TYPE (parm)))
3197 && bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
3199 repr = unmodified_by_ref_scalar_representative (parm);
3200 VEC_quick_push (access_p, *representatives, repr);
3201 if (repr)
3202 result = UNMODIF_BY_REF_ACCESSES;
3204 else if (bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
3206 bool ro_grp = false;
3207 repr = splice_param_accesses (parm, &ro_grp);
3208 VEC_quick_push (access_p, *representatives, repr);
3210 if (repr && !no_accesses_p (repr))
3212 if (POINTER_TYPE_P (TREE_TYPE (parm)))
3214 if (ro_grp)
3215 result = UNMODIF_BY_REF_ACCESSES;
3216 else if (result < MODIF_BY_REF_ACCESSES)
3217 result = MODIF_BY_REF_ACCESSES;
3219 else if (result < BY_VAL_ACCESSES)
3220 result = BY_VAL_ACCESSES;
3222 else if (no_accesses_p (repr) && (result == NO_GOOD_ACCESS))
3223 result = UNUSED_PARAMS;
3225 else
3226 VEC_quick_push (access_p, *representatives, NULL);
3229 if (result == NO_GOOD_ACCESS)
3231 VEC_free (access_p, heap, *representatives);
3232 *representatives = NULL;
3233 return NO_GOOD_ACCESS;
3236 return result;
3239 /* Return the index of BASE in PARMS. Abort if it is not found. */
3241 static inline int
3242 get_param_index (tree base, VEC(tree, heap) *parms)
3244 int i, len;
3246 len = VEC_length (tree, parms);
3247 for (i = 0; i < len; i++)
3248 if (VEC_index (tree, parms, i) == base)
3249 return i;
3250 gcc_unreachable ();
3253 /* Convert the decisions made at the representative level into compact
3254 parameter adjustments. REPRESENTATIVES are pointers to first
3255 representatives of each param accesses, ADJUSTMENTS_COUNT is the expected
3256 final number of adjustments. */
3258 static ipa_parm_adjustment_vec
3259 turn_representatives_into_adjustments (VEC (access_p, heap) *representatives,
3260 int adjustments_count)
3262 VEC (tree, heap) *parms;
3263 ipa_parm_adjustment_vec adjustments;
3264 tree parm;
3265 int i;
3267 gcc_assert (adjustments_count > 0);
3268 parms = ipa_get_vector_of_formal_parms (current_function_decl);
3269 adjustments = VEC_alloc (ipa_parm_adjustment_t, heap, adjustments_count);
3270 parm = DECL_ARGUMENTS (current_function_decl);
3271 for (i = 0; i < func_param_count; i++, parm = TREE_CHAIN (parm))
3273 struct access *repr = VEC_index (access_p, representatives, i);
3275 if (!repr || no_accesses_p (repr))
3277 struct ipa_parm_adjustment *adj;
3279 adj = VEC_quick_push (ipa_parm_adjustment_t, adjustments, NULL);
3280 memset (adj, 0, sizeof (*adj));
3281 adj->base_index = get_param_index (parm, parms);
3282 adj->base = parm;
3283 if (!repr)
3284 adj->copy_param = 1;
3285 else
3286 adj->remove_param = 1;
3288 else
3290 struct ipa_parm_adjustment *adj;
3291 int index = get_param_index (parm, parms);
3293 for (; repr; repr = repr->next_grp)
3295 adj = VEC_quick_push (ipa_parm_adjustment_t, adjustments, NULL);
3296 memset (adj, 0, sizeof (*adj));
3297 gcc_assert (repr->base == parm);
3298 adj->base_index = index;
3299 adj->base = repr->base;
3300 adj->type = repr->type;
3301 adj->offset = repr->offset;
3302 adj->by_ref = (POINTER_TYPE_P (TREE_TYPE (repr->base))
3303 && (repr->grp_maybe_modified
3304 || repr->grp_not_necessarilly_dereferenced));
3309 VEC_free (tree, heap, parms);
3310 return adjustments;
3313 /* Analyze the collected accesses and produce a plan what to do with the
3314 parameters in the form of adjustments, NULL meaning nothing. */
3316 static ipa_parm_adjustment_vec
3317 analyze_all_param_acesses (void)
3319 enum ipa_splicing_result repr_state;
3320 bool proceed = false;
3321 int i, adjustments_count = 0;
3322 VEC (access_p, heap) *representatives;
3323 ipa_parm_adjustment_vec adjustments;
3325 repr_state = splice_all_param_accesses (&representatives);
3326 if (repr_state == NO_GOOD_ACCESS)
3327 return NULL;
3329 /* If there are any parameters passed by reference which are not modified
3330 directly, we need to check whether they can be modified indirectly. */
3331 if (repr_state == UNMODIF_BY_REF_ACCESSES)
3333 analyze_caller_dereference_legality (representatives);
3334 analyze_modified_params (representatives);
3337 for (i = 0; i < func_param_count; i++)
3339 struct access *repr = VEC_index (access_p, representatives, i);
3341 if (repr && !no_accesses_p (repr))
3343 if (repr->grp_scalar_ptr)
3345 adjustments_count++;
3346 if (repr->grp_not_necessarilly_dereferenced
3347 || repr->grp_maybe_modified)
3348 VEC_replace (access_p, representatives, i, NULL);
3349 else
3351 proceed = true;
3352 sra_stats.scalar_by_ref_to_by_val++;
3355 else
3357 int new_components = decide_one_param_reduction (repr);
3359 if (new_components == 0)
3361 VEC_replace (access_p, representatives, i, NULL);
3362 adjustments_count++;
3364 else
3366 adjustments_count += new_components;
3367 sra_stats.aggregate_params_reduced++;
3368 sra_stats.param_reductions_created += new_components;
3369 proceed = true;
3373 else
3375 if (no_accesses_p (repr))
3377 proceed = true;
3378 sra_stats.deleted_unused_parameters++;
3380 adjustments_count++;
3384 if (!proceed && dump_file)
3385 fprintf (dump_file, "NOT proceeding to change params.\n");
3387 if (proceed)
3388 adjustments = turn_representatives_into_adjustments (representatives,
3389 adjustments_count);
3390 else
3391 adjustments = NULL;
3393 VEC_free (access_p, heap, representatives);
3394 return adjustments;
3397 /* If a parameter replacement identified by ADJ does not yet exist in the form
3398 of declaration, create it and record it, otherwise return the previously
3399 created one. */
3401 static tree
3402 get_replaced_param_substitute (struct ipa_parm_adjustment *adj)
3404 tree repl;
3405 if (!adj->new_ssa_base)
3407 char *pretty_name = make_fancy_name (adj->base);
3409 repl = make_rename_temp (TREE_TYPE (adj->base), "ISR");
3410 DECL_NAME (repl) = get_identifier (pretty_name);
3411 obstack_free (&name_obstack, pretty_name);
3413 get_var_ann (repl);
3414 add_referenced_var (repl);
3415 adj->new_ssa_base = repl;
3417 else
3418 repl = adj->new_ssa_base;
3419 return repl;
3422 /* Find the first adjustment for a particular parameter BASE in a vector of
3423 ADJUSTMENTS which is not a copy_param. Return NULL if there is no such
3424 adjustment. */
3426 static struct ipa_parm_adjustment *
3427 get_adjustment_for_base (ipa_parm_adjustment_vec adjustments, tree base)
3429 int i, len;
3431 len = VEC_length (ipa_parm_adjustment_t, adjustments);
3432 for (i = 0; i < len; i++)
3434 struct ipa_parm_adjustment *adj;
3436 adj = VEC_index (ipa_parm_adjustment_t, adjustments, i);
3437 if (!adj->copy_param && adj->base == base)
3438 return adj;
3441 return NULL;
3444 /* Callback for scan_function. If the statement STMT defines an SSA_NAME of a
3445 parameter which is to be removed because its value is not used, replace the
3446 SSA_NAME with a one relating to a created VAR_DECL and replace all of its
3447 uses too. DATA is a pointer to an adjustments vector. */
3449 static bool
3450 replace_removed_params_ssa_names (gimple stmt, void *data)
3452 VEC (ipa_parm_adjustment_t, heap) *adjustments;
3453 struct ipa_parm_adjustment *adj;
3454 tree lhs, decl, repl, name;
3456 adjustments = (VEC (ipa_parm_adjustment_t, heap) *) data;
3457 if (gimple_code (stmt) == GIMPLE_PHI)
3458 lhs = gimple_phi_result (stmt);
3459 else if (is_gimple_assign (stmt))
3460 lhs = gimple_assign_lhs (stmt);
3461 else if (is_gimple_call (stmt))
3462 lhs = gimple_call_lhs (stmt);
3463 else
3464 gcc_unreachable ();
3466 if (TREE_CODE (lhs) != SSA_NAME)
3467 return false;
3468 decl = SSA_NAME_VAR (lhs);
3469 if (TREE_CODE (decl) != PARM_DECL)
3470 return false;
3472 adj = get_adjustment_for_base (adjustments, decl);
3473 if (!adj)
3474 return false;
3476 repl = get_replaced_param_substitute (adj);
3477 name = make_ssa_name (repl, stmt);
3479 if (dump_file)
3481 fprintf (dump_file, "replacing an SSA name of a removed param ");
3482 print_generic_expr (dump_file, lhs, 0);
3483 fprintf (dump_file, " with ");
3484 print_generic_expr (dump_file, name, 0);
3485 fprintf (dump_file, "\n");
3488 if (is_gimple_assign (stmt))
3489 gimple_assign_set_lhs (stmt, name);
3490 else if (is_gimple_call (stmt))
3491 gimple_call_set_lhs (stmt, name);
3492 else
3493 gimple_phi_set_result (stmt, name);
3495 replace_uses_by (lhs, name);
3496 return true;
3499 /* Callback for scan_function. If the expression *EXPR should be replaced by a
3500 reduction of a parameter, do so. DATA is a pointer to a vector of
3501 adjustments. */
3503 static bool
3504 sra_ipa_modify_expr (tree *expr, gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED,
3505 bool write ATTRIBUTE_UNUSED, void *data)
3507 ipa_parm_adjustment_vec adjustments;
3508 int i, len;
3509 struct ipa_parm_adjustment *adj, *cand = NULL;
3510 HOST_WIDE_INT offset, size, max_size;
3511 tree base, src;
3513 adjustments = (VEC (ipa_parm_adjustment_t, heap) *) data;
3514 len = VEC_length (ipa_parm_adjustment_t, adjustments);
3516 if (TREE_CODE (*expr) == BIT_FIELD_REF
3517 || TREE_CODE (*expr) == IMAGPART_EXPR
3518 || TREE_CODE (*expr) == REALPART_EXPR)
3519 expr = &TREE_OPERAND (*expr, 0);
3520 while (TREE_CODE (*expr) == NOP_EXPR
3521 || TREE_CODE (*expr) == VIEW_CONVERT_EXPR)
3522 expr = &TREE_OPERAND (*expr, 0);
3524 base = get_ref_base_and_extent (*expr, &offset, &size, &max_size);
3525 if (!base || size == -1 || max_size == -1)
3526 return false;
3528 if (INDIRECT_REF_P (base))
3529 base = TREE_OPERAND (base, 0);
3531 base = get_ssa_base_param (base);
3532 if (!base || TREE_CODE (base) != PARM_DECL)
3533 return false;
3535 for (i = 0; i < len; i++)
3537 adj = VEC_index (ipa_parm_adjustment_t, adjustments, i);
3539 if (adj->base == base &&
3540 (adj->offset == offset || adj->remove_param))
3542 cand = adj;
3543 break;
3546 if (!cand || cand->copy_param || cand->remove_param)
3547 return false;
3549 if (cand->by_ref)
3551 tree folded;
3552 src = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (cand->reduction)),
3553 cand->reduction);
3554 folded = gimple_fold_indirect_ref (src);
3555 if (folded)
3556 src = folded;
3558 else
3559 src = cand->reduction;
3561 if (dump_file && (dump_flags & TDF_DETAILS))
3563 fprintf (dump_file, "About to replace expr ");
3564 print_generic_expr (dump_file, *expr, 0);
3565 fprintf (dump_file, " with ");
3566 print_generic_expr (dump_file, src, 0);
3567 fprintf (dump_file, "\n");
3570 if (!useless_type_conversion_p (TREE_TYPE (*expr), cand->type))
3572 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*expr), src);
3573 *expr = vce;
3575 else
3576 *expr = src;
3577 return true;
3580 /* Callback for scan_function to process assign statements. Performs
3581 essentially the same function like sra_ipa_modify_expr. */
3583 static enum scan_assign_result
3584 sra_ipa_modify_assign (gimple *stmt_ptr,
3585 gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED, void *data)
3587 gimple stmt = *stmt_ptr;
3588 bool any = false;
3590 if (!gimple_assign_single_p (stmt))
3591 return SRA_SA_NONE;
3593 any |= sra_ipa_modify_expr (gimple_assign_rhs1_ptr (stmt), gsi, false,
3594 data);
3595 any |= sra_ipa_modify_expr (gimple_assign_lhs_ptr (stmt), gsi, true, data);
3597 return any ? SRA_SA_PROCESSED : SRA_SA_NONE;
3600 /* Call gimple_debug_bind_reset_value on all debug statements describing
3601 gimple register parameters that are being removed or replaced. */
3603 static void
3604 sra_ipa_reset_debug_stmts (ipa_parm_adjustment_vec adjustments)
3606 int i, len;
3608 len = VEC_length (ipa_parm_adjustment_t, adjustments);
3609 for (i = 0; i < len; i++)
3611 struct ipa_parm_adjustment *adj;
3612 imm_use_iterator ui;
3613 gimple stmt;
3614 tree name;
3616 adj = VEC_index (ipa_parm_adjustment_t, adjustments, i);
3617 if (adj->copy_param || !is_gimple_reg (adj->base))
3618 continue;
3619 name = gimple_default_def (cfun, adj->base);
3620 if (!name)
3621 continue;
3622 FOR_EACH_IMM_USE_STMT (stmt, ui, name)
3624 /* All other users must have been removed by scan_function. */
3625 gcc_assert (is_gimple_debug (stmt));
3626 gimple_debug_bind_reset_value (stmt);
3627 update_stmt (stmt);
3632 /* Convert all callers of NODE to pass parameters as given in ADJUSTMENTS. */
3634 static void
3635 convert_callers (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments)
3637 tree old_cur_fndecl = current_function_decl;
3638 struct cgraph_edge *cs;
3639 basic_block this_block;
3641 for (cs = node->callers; cs; cs = cs->next_caller)
3643 current_function_decl = cs->caller->decl;
3644 push_cfun (DECL_STRUCT_FUNCTION (cs->caller->decl));
3646 if (dump_file)
3647 fprintf (dump_file, "Adjusting call %s -> %s\n",
3648 cgraph_node_name (cs->caller),
3649 cgraph_node_name (cs->callee));
3651 ipa_modify_call_arguments (cs, cs->call_stmt, adjustments);
3652 compute_inline_parameters (cs->caller);
3654 pop_cfun ();
3656 current_function_decl = old_cur_fndecl;
3657 FOR_EACH_BB (this_block)
3659 gimple_stmt_iterator gsi;
3661 for (gsi = gsi_start_bb (this_block); !gsi_end_p (gsi); gsi_next (&gsi))
3663 gimple stmt = gsi_stmt (gsi);
3664 if (gimple_code (stmt) == GIMPLE_CALL
3665 && gimple_call_fndecl (stmt) == node->decl)
3667 if (dump_file)
3668 fprintf (dump_file, "Adjusting recursive call");
3669 ipa_modify_call_arguments (NULL, stmt, adjustments);
3674 return;
3677 /* Perform all the modification required in IPA-SRA for NODE to have parameters
3678 as given in ADJUSTMENTS. */
3680 static void
3681 modify_function (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments)
3683 ipa_modify_formal_parameters (current_function_decl, adjustments, "ISRA");
3684 scan_function (sra_ipa_modify_expr, sra_ipa_modify_assign,
3685 replace_removed_params_ssa_names, false, adjustments);
3686 sra_ipa_reset_debug_stmts (adjustments);
3687 convert_callers (node, adjustments);
3688 cgraph_make_node_local (node);
3689 return;
3692 /* Return false the function is apparently unsuitable for IPA-SRA based on it's
3693 attributes, return true otherwise. NODE is the cgraph node of the current
3694 function. */
3696 static bool
3697 ipa_sra_preliminary_function_checks (struct cgraph_node *node)
3699 if (!cgraph_node_can_be_local_p (node))
3701 if (dump_file)
3702 fprintf (dump_file, "Function not local to this compilation unit.\n");
3703 return false;
3706 if (DECL_VIRTUAL_P (current_function_decl))
3708 if (dump_file)
3709 fprintf (dump_file, "Function is a virtual method.\n");
3710 return false;
3713 if ((DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl))
3714 && node->global.size >= MAX_INLINE_INSNS_AUTO)
3716 if (dump_file)
3717 fprintf (dump_file, "Function too big to be made truly local.\n");
3718 return false;
3721 if (!node->callers)
3723 if (dump_file)
3724 fprintf (dump_file,
3725 "Function has no callers in this compilation unit.\n");
3726 return false;
3729 if (cfun->stdarg)
3731 if (dump_file)
3732 fprintf (dump_file, "Function uses stdarg. \n");
3733 return false;
3736 return true;
3739 /* Perform early interprocedural SRA. */
3741 static unsigned int
3742 ipa_early_sra (void)
3744 struct cgraph_node *node = cgraph_node (current_function_decl);
3745 ipa_parm_adjustment_vec adjustments;
3746 int ret = 0;
3748 if (!ipa_sra_preliminary_function_checks (node))
3749 return 0;
3751 sra_initialize ();
3752 sra_mode = SRA_MODE_EARLY_IPA;
3754 if (!find_param_candidates ())
3756 if (dump_file)
3757 fprintf (dump_file, "Function has no IPA-SRA candidates.\n");
3758 goto simple_out;
3761 bb_dereferences = XCNEWVEC (HOST_WIDE_INT,
3762 func_param_count
3763 * last_basic_block_for_function (cfun));
3764 final_bbs = BITMAP_ALLOC (NULL);
3766 scan_function (build_access_from_expr, build_accesses_from_assign,
3767 NULL, true, NULL);
3768 if (encountered_apply_args)
3770 if (dump_file)
3771 fprintf (dump_file, "Function calls __builtin_apply_args().\n");
3772 goto out;
3775 adjustments = analyze_all_param_acesses ();
3776 if (!adjustments)
3777 goto out;
3778 if (dump_file)
3779 ipa_dump_param_adjustments (dump_file, adjustments, current_function_decl);
3781 modify_function (node, adjustments);
3782 VEC_free (ipa_parm_adjustment_t, heap, adjustments);
3783 ret = TODO_update_ssa;
3785 statistics_counter_event (cfun, "Unused parameters deleted",
3786 sra_stats.deleted_unused_parameters);
3787 statistics_counter_event (cfun, "Scalar parameters converted to by-value",
3788 sra_stats.scalar_by_ref_to_by_val);
3789 statistics_counter_event (cfun, "Aggregate parameters broken up",
3790 sra_stats.aggregate_params_reduced);
3791 statistics_counter_event (cfun, "Aggregate parameter components created",
3792 sra_stats.param_reductions_created);
3794 out:
3795 BITMAP_FREE (final_bbs);
3796 free (bb_dereferences);
3797 simple_out:
3798 sra_deinitialize ();
3799 return ret;
3802 /* Return if early ipa sra shall be performed. */
3803 static bool
3804 ipa_early_sra_gate (void)
3806 return flag_ipa_sra;
3809 struct gimple_opt_pass pass_early_ipa_sra =
3812 GIMPLE_PASS,
3813 "eipa_sra", /* name */
3814 ipa_early_sra_gate, /* gate */
3815 ipa_early_sra, /* execute */
3816 NULL, /* sub */
3817 NULL, /* next */
3818 0, /* static_pass_number */
3819 TV_IPA_SRA, /* tv_id */
3820 0, /* properties_required */
3821 0, /* properties_provided */
3822 0, /* properties_destroyed */
3823 0, /* todo_flags_start */
3824 TODO_dump_func | TODO_dump_cgraph /* todo_flags_finish */