Mark SLP failures for vect_variable_length
[official-gcc.git] / gcc / tree-sra.c
blobb513676152fc96f4d02baa806aad0b4a9659f13a
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-2018 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 "backend.h"
78 #include "target.h"
79 #include "rtl.h"
80 #include "tree.h"
81 #include "gimple.h"
82 #include "predict.h"
83 #include "alloc-pool.h"
84 #include "tree-pass.h"
85 #include "ssa.h"
86 #include "cgraph.h"
87 #include "gimple-pretty-print.h"
88 #include "alias.h"
89 #include "fold-const.h"
90 #include "tree-eh.h"
91 #include "stor-layout.h"
92 #include "gimplify.h"
93 #include "gimple-iterator.h"
94 #include "gimplify-me.h"
95 #include "gimple-walk.h"
96 #include "tree-cfg.h"
97 #include "tree-dfa.h"
98 #include "tree-ssa.h"
99 #include "symbol-summary.h"
100 #include "ipa-param-manipulation.h"
101 #include "ipa-prop.h"
102 #include "params.h"
103 #include "dbgcnt.h"
104 #include "tree-inline.h"
105 #include "ipa-fnsummary.h"
106 #include "ipa-utils.h"
107 #include "builtins.h"
109 /* Enumeration of all aggregate reductions we can do. */
110 enum sra_mode { SRA_MODE_EARLY_IPA, /* early call regularization */
111 SRA_MODE_EARLY_INTRA, /* early intraprocedural SRA */
112 SRA_MODE_INTRA }; /* late intraprocedural SRA */
114 /* Global variable describing which aggregate reduction we are performing at
115 the moment. */
116 static enum sra_mode sra_mode;
118 struct assign_link;
120 /* ACCESS represents each access to an aggregate variable (as a whole or a
121 part). It can also represent a group of accesses that refer to exactly the
122 same fragment of an aggregate (i.e. those that have exactly the same offset
123 and size). Such representatives for a single aggregate, once determined,
124 are linked in a linked list and have the group fields set.
126 Moreover, when doing intraprocedural SRA, a tree is built from those
127 representatives (by the means of first_child and next_sibling pointers), in
128 which all items in a subtree are "within" the root, i.e. their offset is
129 greater or equal to offset of the root and offset+size is smaller or equal
130 to offset+size of the root. Children of an access are sorted by offset.
132 Note that accesses to parts of vector and complex number types always
133 represented by an access to the whole complex number or a vector. It is a
134 duty of the modifying functions to replace them appropriately. */
136 struct access
138 /* Values returned by `get_ref_base_and_extent' for each component reference
139 If EXPR isn't a component reference just set `BASE = EXPR', `OFFSET = 0',
140 `SIZE = TREE_SIZE (TREE_TYPE (expr))'. */
141 HOST_WIDE_INT offset;
142 HOST_WIDE_INT size;
143 tree base;
145 /* Expression. It is context dependent so do not use it to create new
146 expressions to access the original aggregate. See PR 42154 for a
147 testcase. */
148 tree expr;
149 /* Type. */
150 tree type;
152 /* The statement this access belongs to. */
153 gimple *stmt;
155 /* Next group representative for this aggregate. */
156 struct access *next_grp;
158 /* Pointer to the group representative. Pointer to itself if the struct is
159 the representative. */
160 struct access *group_representative;
162 /* After access tree has been constructed, this points to the parent of the
163 current access, if there is one. NULL for roots. */
164 struct access *parent;
166 /* If this access has any children (in terms of the definition above), this
167 points to the first one. */
168 struct access *first_child;
170 /* In intraprocedural SRA, pointer to the next sibling in the access tree as
171 described above. In IPA-SRA this is a pointer to the next access
172 belonging to the same group (having the same representative). */
173 struct access *next_sibling;
175 /* Pointers to the first and last element in the linked list of assign
176 links. */
177 struct assign_link *first_link, *last_link;
179 /* Pointer to the next access in the work queue. */
180 struct access *next_queued;
182 /* Replacement variable for this access "region." Never to be accessed
183 directly, always only by the means of get_access_replacement() and only
184 when grp_to_be_replaced flag is set. */
185 tree replacement_decl;
187 /* Is this access an access to a non-addressable field? */
188 unsigned non_addressable : 1;
190 /* Is this access made in reverse storage order? */
191 unsigned reverse : 1;
193 /* Is this particular access write access? */
194 unsigned write : 1;
196 /* Is this access currently in the work queue? */
197 unsigned grp_queued : 1;
199 /* Does this group contain a write access? This flag is propagated down the
200 access tree. */
201 unsigned grp_write : 1;
203 /* Does this group contain a read access? This flag is propagated down the
204 access tree. */
205 unsigned grp_read : 1;
207 /* Does this group contain a read access that comes from an assignment
208 statement? This flag is propagated down the access tree. */
209 unsigned grp_assignment_read : 1;
211 /* Does this group contain a write access that comes from an assignment
212 statement? This flag is propagated down the access tree. */
213 unsigned grp_assignment_write : 1;
215 /* Does this group contain a read access through a scalar type? This flag is
216 not propagated in the access tree in any direction. */
217 unsigned grp_scalar_read : 1;
219 /* Does this group contain a write access through a scalar type? This flag
220 is not propagated in the access tree in any direction. */
221 unsigned grp_scalar_write : 1;
223 /* Is this access an artificial one created to scalarize some record
224 entirely? */
225 unsigned grp_total_scalarization : 1;
227 /* Other passes of the analysis use this bit to make function
228 analyze_access_subtree create scalar replacements for this group if
229 possible. */
230 unsigned grp_hint : 1;
232 /* Is the subtree rooted in this access fully covered by scalar
233 replacements? */
234 unsigned grp_covered : 1;
236 /* If set to true, this access and all below it in an access tree must not be
237 scalarized. */
238 unsigned grp_unscalarizable_region : 1;
240 /* Whether data have been written to parts of the aggregate covered by this
241 access which is not to be scalarized. This flag is propagated up in the
242 access tree. */
243 unsigned grp_unscalarized_data : 1;
245 /* Does this access and/or group contain a write access through a
246 BIT_FIELD_REF? */
247 unsigned grp_partial_lhs : 1;
249 /* Set when a scalar replacement should be created for this variable. */
250 unsigned grp_to_be_replaced : 1;
252 /* Set when we want a replacement for the sole purpose of having it in
253 generated debug statements. */
254 unsigned grp_to_be_debug_replaced : 1;
256 /* Should TREE_NO_WARNING of a replacement be set? */
257 unsigned grp_no_warning : 1;
259 /* Is it possible that the group refers to data which might be (directly or
260 otherwise) modified? */
261 unsigned grp_maybe_modified : 1;
263 /* Set when this is a representative of a pointer to scalar (i.e. by
264 reference) parameter which we consider for turning into a plain scalar
265 (i.e. a by value parameter). */
266 unsigned grp_scalar_ptr : 1;
268 /* Set when we discover that this pointer is not safe to dereference in the
269 caller. */
270 unsigned grp_not_necessarilly_dereferenced : 1;
273 typedef struct access *access_p;
276 /* Alloc pool for allocating access structures. */
277 static object_allocator<struct access> access_pool ("SRA accesses");
279 /* A structure linking lhs and rhs accesses from an aggregate assignment. They
280 are used to propagate subaccesses from rhs to lhs as long as they don't
281 conflict with what is already there. */
282 struct assign_link
284 struct access *lacc, *racc;
285 struct assign_link *next;
288 /* Alloc pool for allocating assign link structures. */
289 static object_allocator<assign_link> assign_link_pool ("SRA links");
291 /* Base (tree) -> Vector (vec<access_p> *) map. */
292 static hash_map<tree, auto_vec<access_p> > *base_access_vec;
294 /* Candidate hash table helpers. */
296 struct uid_decl_hasher : nofree_ptr_hash <tree_node>
298 static inline hashval_t hash (const tree_node *);
299 static inline bool equal (const tree_node *, const tree_node *);
302 /* Hash a tree in a uid_decl_map. */
304 inline hashval_t
305 uid_decl_hasher::hash (const tree_node *item)
307 return item->decl_minimal.uid;
310 /* Return true if the DECL_UID in both trees are equal. */
312 inline bool
313 uid_decl_hasher::equal (const tree_node *a, const tree_node *b)
315 return (a->decl_minimal.uid == b->decl_minimal.uid);
318 /* Set of candidates. */
319 static bitmap candidate_bitmap;
320 static hash_table<uid_decl_hasher> *candidates;
322 /* For a candidate UID return the candidates decl. */
324 static inline tree
325 candidate (unsigned uid)
327 tree_node t;
328 t.decl_minimal.uid = uid;
329 return candidates->find_with_hash (&t, static_cast <hashval_t> (uid));
332 /* Bitmap of candidates which we should try to entirely scalarize away and
333 those which cannot be (because they are and need be used as a whole). */
334 static bitmap should_scalarize_away_bitmap, cannot_scalarize_away_bitmap;
336 /* Bitmap of candidates in the constant pool, which cannot be scalarized
337 because this would produce non-constant expressions (e.g. Ada). */
338 static bitmap disqualified_constants;
340 /* Obstack for creation of fancy names. */
341 static struct obstack name_obstack;
343 /* Head of a linked list of accesses that need to have its subaccesses
344 propagated to their assignment counterparts. */
345 static struct access *work_queue_head;
347 /* Number of parameters of the analyzed function when doing early ipa SRA. */
348 static int func_param_count;
350 /* scan_function sets the following to true if it encounters a call to
351 __builtin_apply_args. */
352 static bool encountered_apply_args;
354 /* Set by scan_function when it finds a recursive call. */
355 static bool encountered_recursive_call;
357 /* Set by scan_function when it finds a recursive call with less actual
358 arguments than formal parameters.. */
359 static bool encountered_unchangable_recursive_call;
361 /* This is a table in which for each basic block and parameter there is a
362 distance (offset + size) in that parameter which is dereferenced and
363 accessed in that BB. */
364 static HOST_WIDE_INT *bb_dereferences;
365 /* Bitmap of BBs that can cause the function to "stop" progressing by
366 returning, throwing externally, looping infinitely or calling a function
367 which might abort etc.. */
368 static bitmap final_bbs;
370 /* Representative of no accesses at all. */
371 static struct access no_accesses_representant;
373 /* Predicate to test the special value. */
375 static inline bool
376 no_accesses_p (struct access *access)
378 return access == &no_accesses_representant;
381 /* Dump contents of ACCESS to file F in a human friendly way. If GRP is true,
382 representative fields are dumped, otherwise those which only describe the
383 individual access are. */
385 static struct
387 /* Number of processed aggregates is readily available in
388 analyze_all_variable_accesses and so is not stored here. */
390 /* Number of created scalar replacements. */
391 int replacements;
393 /* Number of times sra_modify_expr or sra_modify_assign themselves changed an
394 expression. */
395 int exprs;
397 /* Number of statements created by generate_subtree_copies. */
398 int subtree_copies;
400 /* Number of statements created by load_assign_lhs_subreplacements. */
401 int subreplacements;
403 /* Number of times sra_modify_assign has deleted a statement. */
404 int deleted;
406 /* Number of times sra_modify_assign has to deal with subaccesses of LHS and
407 RHS reparately due to type conversions or nonexistent matching
408 references. */
409 int separate_lhs_rhs_handling;
411 /* Number of parameters that were removed because they were unused. */
412 int deleted_unused_parameters;
414 /* Number of scalars passed as parameters by reference that have been
415 converted to be passed by value. */
416 int scalar_by_ref_to_by_val;
418 /* Number of aggregate parameters that were replaced by one or more of their
419 components. */
420 int aggregate_params_reduced;
422 /* Numbber of components created when splitting aggregate parameters. */
423 int param_reductions_created;
424 } sra_stats;
426 static void
427 dump_access (FILE *f, struct access *access, bool grp)
429 fprintf (f, "access { ");
430 fprintf (f, "base = (%d)'", DECL_UID (access->base));
431 print_generic_expr (f, access->base);
432 fprintf (f, "', offset = " HOST_WIDE_INT_PRINT_DEC, access->offset);
433 fprintf (f, ", size = " HOST_WIDE_INT_PRINT_DEC, access->size);
434 fprintf (f, ", expr = ");
435 print_generic_expr (f, access->expr);
436 fprintf (f, ", type = ");
437 print_generic_expr (f, access->type);
438 fprintf (f, ", non_addressable = %d, reverse = %d",
439 access->non_addressable, access->reverse);
440 if (grp)
441 fprintf (f, ", grp_read = %d, grp_write = %d, grp_assignment_read = %d, "
442 "grp_assignment_write = %d, grp_scalar_read = %d, "
443 "grp_scalar_write = %d, grp_total_scalarization = %d, "
444 "grp_hint = %d, grp_covered = %d, "
445 "grp_unscalarizable_region = %d, grp_unscalarized_data = %d, "
446 "grp_partial_lhs = %d, grp_to_be_replaced = %d, "
447 "grp_to_be_debug_replaced = %d, grp_maybe_modified = %d, "
448 "grp_not_necessarilly_dereferenced = %d\n",
449 access->grp_read, access->grp_write, access->grp_assignment_read,
450 access->grp_assignment_write, access->grp_scalar_read,
451 access->grp_scalar_write, access->grp_total_scalarization,
452 access->grp_hint, access->grp_covered,
453 access->grp_unscalarizable_region, access->grp_unscalarized_data,
454 access->grp_partial_lhs, access->grp_to_be_replaced,
455 access->grp_to_be_debug_replaced, access->grp_maybe_modified,
456 access->grp_not_necessarilly_dereferenced);
457 else
458 fprintf (f, ", write = %d, grp_total_scalarization = %d, "
459 "grp_partial_lhs = %d\n",
460 access->write, access->grp_total_scalarization,
461 access->grp_partial_lhs);
464 /* Dump a subtree rooted in ACCESS to file F, indent by LEVEL. */
466 static void
467 dump_access_tree_1 (FILE *f, struct access *access, int level)
471 int i;
473 for (i = 0; i < level; i++)
474 fputs ("* ", f);
476 dump_access (f, access, true);
478 if (access->first_child)
479 dump_access_tree_1 (f, access->first_child, level + 1);
481 access = access->next_sibling;
483 while (access);
486 /* Dump all access trees for a variable, given the pointer to the first root in
487 ACCESS. */
489 static void
490 dump_access_tree (FILE *f, struct access *access)
492 for (; access; access = access->next_grp)
493 dump_access_tree_1 (f, access, 0);
496 /* Return true iff ACC is non-NULL and has subaccesses. */
498 static inline bool
499 access_has_children_p (struct access *acc)
501 return acc && acc->first_child;
504 /* Return true iff ACC is (partly) covered by at least one replacement. */
506 static bool
507 access_has_replacements_p (struct access *acc)
509 struct access *child;
510 if (acc->grp_to_be_replaced)
511 return true;
512 for (child = acc->first_child; child; child = child->next_sibling)
513 if (access_has_replacements_p (child))
514 return true;
515 return false;
518 /* Return a vector of pointers to accesses for the variable given in BASE or
519 NULL if there is none. */
521 static vec<access_p> *
522 get_base_access_vector (tree base)
524 return base_access_vec->get (base);
527 /* Find an access with required OFFSET and SIZE in a subtree of accesses rooted
528 in ACCESS. Return NULL if it cannot be found. */
530 static struct access *
531 find_access_in_subtree (struct access *access, HOST_WIDE_INT offset,
532 HOST_WIDE_INT size)
534 while (access && (access->offset != offset || access->size != size))
536 struct access *child = access->first_child;
538 while (child && (child->offset + child->size <= offset))
539 child = child->next_sibling;
540 access = child;
543 return access;
546 /* Return the first group representative for DECL or NULL if none exists. */
548 static struct access *
549 get_first_repr_for_decl (tree base)
551 vec<access_p> *access_vec;
553 access_vec = get_base_access_vector (base);
554 if (!access_vec)
555 return NULL;
557 return (*access_vec)[0];
560 /* Find an access representative for the variable BASE and given OFFSET and
561 SIZE. Requires that access trees have already been built. Return NULL if
562 it cannot be found. */
564 static struct access *
565 get_var_base_offset_size_access (tree base, HOST_WIDE_INT offset,
566 HOST_WIDE_INT size)
568 struct access *access;
570 access = get_first_repr_for_decl (base);
571 while (access && (access->offset + access->size <= offset))
572 access = access->next_grp;
573 if (!access)
574 return NULL;
576 return find_access_in_subtree (access, offset, size);
579 /* Add LINK to the linked list of assign links of RACC. */
580 static void
581 add_link_to_rhs (struct access *racc, struct assign_link *link)
583 gcc_assert (link->racc == racc);
585 if (!racc->first_link)
587 gcc_assert (!racc->last_link);
588 racc->first_link = link;
590 else
591 racc->last_link->next = link;
593 racc->last_link = link;
594 link->next = NULL;
597 /* Move all link structures in their linked list in OLD_RACC to the linked list
598 in NEW_RACC. */
599 static void
600 relink_to_new_repr (struct access *new_racc, struct access *old_racc)
602 if (!old_racc->first_link)
604 gcc_assert (!old_racc->last_link);
605 return;
608 if (new_racc->first_link)
610 gcc_assert (!new_racc->last_link->next);
611 gcc_assert (!old_racc->last_link || !old_racc->last_link->next);
613 new_racc->last_link->next = old_racc->first_link;
614 new_racc->last_link = old_racc->last_link;
616 else
618 gcc_assert (!new_racc->last_link);
620 new_racc->first_link = old_racc->first_link;
621 new_racc->last_link = old_racc->last_link;
623 old_racc->first_link = old_racc->last_link = NULL;
626 /* Add ACCESS to the work queue (which is actually a stack). */
628 static void
629 add_access_to_work_queue (struct access *access)
631 if (access->first_link && !access->grp_queued)
633 gcc_assert (!access->next_queued);
634 access->next_queued = work_queue_head;
635 access->grp_queued = 1;
636 work_queue_head = access;
640 /* Pop an access from the work queue, and return it, assuming there is one. */
642 static struct access *
643 pop_access_from_work_queue (void)
645 struct access *access = work_queue_head;
647 work_queue_head = access->next_queued;
648 access->next_queued = NULL;
649 access->grp_queued = 0;
650 return access;
654 /* Allocate necessary structures. */
656 static void
657 sra_initialize (void)
659 candidate_bitmap = BITMAP_ALLOC (NULL);
660 candidates = new hash_table<uid_decl_hasher>
661 (vec_safe_length (cfun->local_decls) / 2);
662 should_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
663 cannot_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
664 disqualified_constants = BITMAP_ALLOC (NULL);
665 gcc_obstack_init (&name_obstack);
666 base_access_vec = new hash_map<tree, auto_vec<access_p> >;
667 memset (&sra_stats, 0, sizeof (sra_stats));
668 encountered_apply_args = false;
669 encountered_recursive_call = false;
670 encountered_unchangable_recursive_call = false;
673 /* Deallocate all general structures. */
675 static void
676 sra_deinitialize (void)
678 BITMAP_FREE (candidate_bitmap);
679 delete candidates;
680 candidates = NULL;
681 BITMAP_FREE (should_scalarize_away_bitmap);
682 BITMAP_FREE (cannot_scalarize_away_bitmap);
683 BITMAP_FREE (disqualified_constants);
684 access_pool.release ();
685 assign_link_pool.release ();
686 obstack_free (&name_obstack, NULL);
688 delete base_access_vec;
691 /* Return true if DECL is a VAR_DECL in the constant pool, false otherwise. */
693 static bool constant_decl_p (tree decl)
695 return VAR_P (decl) && DECL_IN_CONSTANT_POOL (decl);
698 /* Remove DECL from candidates for SRA and write REASON to the dump file if
699 there is one. */
701 static void
702 disqualify_candidate (tree decl, const char *reason)
704 if (bitmap_clear_bit (candidate_bitmap, DECL_UID (decl)))
705 candidates->remove_elt_with_hash (decl, DECL_UID (decl));
706 if (constant_decl_p (decl))
707 bitmap_set_bit (disqualified_constants, DECL_UID (decl));
709 if (dump_file && (dump_flags & TDF_DETAILS))
711 fprintf (dump_file, "! Disqualifying ");
712 print_generic_expr (dump_file, decl);
713 fprintf (dump_file, " - %s\n", reason);
717 /* Return true iff the type contains a field or an element which does not allow
718 scalarization. */
720 static bool
721 type_internals_preclude_sra_p (tree type, const char **msg)
723 tree fld;
724 tree et;
726 switch (TREE_CODE (type))
728 case RECORD_TYPE:
729 case UNION_TYPE:
730 case QUAL_UNION_TYPE:
731 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
732 if (TREE_CODE (fld) == FIELD_DECL)
734 tree ft = TREE_TYPE (fld);
736 if (TREE_THIS_VOLATILE (fld))
738 *msg = "volatile structure field";
739 return true;
741 if (!DECL_FIELD_OFFSET (fld))
743 *msg = "no structure field offset";
744 return true;
746 if (!DECL_SIZE (fld))
748 *msg = "zero structure field size";
749 return true;
751 if (!tree_fits_uhwi_p (DECL_FIELD_OFFSET (fld)))
753 *msg = "structure field offset not fixed";
754 return true;
756 if (!tree_fits_uhwi_p (DECL_SIZE (fld)))
758 *msg = "structure field size not fixed";
759 return true;
761 if (!tree_fits_shwi_p (bit_position (fld)))
763 *msg = "structure field size too big";
764 return true;
766 if (AGGREGATE_TYPE_P (ft)
767 && int_bit_position (fld) % BITS_PER_UNIT != 0)
769 *msg = "structure field is bit field";
770 return true;
773 if (AGGREGATE_TYPE_P (ft) && type_internals_preclude_sra_p (ft, msg))
774 return true;
777 return false;
779 case ARRAY_TYPE:
780 et = TREE_TYPE (type);
782 if (TYPE_VOLATILE (et))
784 *msg = "element type is volatile";
785 return true;
788 if (AGGREGATE_TYPE_P (et) && type_internals_preclude_sra_p (et, msg))
789 return true;
791 return false;
793 default:
794 return false;
798 /* If T is an SSA_NAME, return NULL if it is not a default def or return its
799 base variable if it is. Return T if it is not an SSA_NAME. */
801 static tree
802 get_ssa_base_param (tree t)
804 if (TREE_CODE (t) == SSA_NAME)
806 if (SSA_NAME_IS_DEFAULT_DEF (t))
807 return SSA_NAME_VAR (t);
808 else
809 return NULL_TREE;
811 return t;
814 /* Mark a dereference of BASE of distance DIST in a basic block tht STMT
815 belongs to, unless the BB has already been marked as a potentially
816 final. */
818 static void
819 mark_parm_dereference (tree base, HOST_WIDE_INT dist, gimple *stmt)
821 basic_block bb = gimple_bb (stmt);
822 int idx, parm_index = 0;
823 tree parm;
825 if (bitmap_bit_p (final_bbs, bb->index))
826 return;
828 for (parm = DECL_ARGUMENTS (current_function_decl);
829 parm && parm != base;
830 parm = DECL_CHAIN (parm))
831 parm_index++;
833 gcc_assert (parm_index < func_param_count);
835 idx = bb->index * func_param_count + parm_index;
836 if (bb_dereferences[idx] < dist)
837 bb_dereferences[idx] = dist;
840 /* Allocate an access structure for BASE, OFFSET and SIZE, clear it, fill in
841 the three fields. Also add it to the vector of accesses corresponding to
842 the base. Finally, return the new access. */
844 static struct access *
845 create_access_1 (tree base, HOST_WIDE_INT offset, HOST_WIDE_INT size)
847 struct access *access = access_pool.allocate ();
849 memset (access, 0, sizeof (struct access));
850 access->base = base;
851 access->offset = offset;
852 access->size = size;
854 base_access_vec->get_or_insert (base).safe_push (access);
856 return access;
859 static bool maybe_add_sra_candidate (tree);
861 /* Create and insert access for EXPR. Return created access, or NULL if it is
862 not possible. Also scan for uses of constant pool as we go along and add
863 to candidates. */
865 static struct access *
866 create_access (tree expr, gimple *stmt, bool write)
868 struct access *access;
869 poly_int64 poffset, psize, pmax_size;
870 HOST_WIDE_INT offset, size, max_size;
871 tree base = expr;
872 bool reverse, ptr, unscalarizable_region = false;
874 base = get_ref_base_and_extent (expr, &poffset, &psize, &pmax_size,
875 &reverse);
876 if (!poffset.is_constant (&offset)
877 || !psize.is_constant (&size)
878 || !pmax_size.is_constant (&max_size))
880 disqualify_candidate (base, "Encountered a polynomial-sized access.");
881 return NULL;
884 if (sra_mode == SRA_MODE_EARLY_IPA
885 && TREE_CODE (base) == MEM_REF)
887 base = get_ssa_base_param (TREE_OPERAND (base, 0));
888 if (!base)
889 return NULL;
890 ptr = true;
892 else
893 ptr = false;
895 /* For constant-pool entries, check we can substitute the constant value. */
896 if (constant_decl_p (base)
897 && (sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA))
899 gcc_assert (!bitmap_bit_p (disqualified_constants, DECL_UID (base)));
900 if (expr != base
901 && !is_gimple_reg_type (TREE_TYPE (expr))
902 && dump_file && (dump_flags & TDF_DETAILS))
904 /* This occurs in Ada with accesses to ARRAY_RANGE_REFs,
905 and elements of multidimensional arrays (which are
906 multi-element arrays in their own right). */
907 fprintf (dump_file, "Allowing non-reg-type load of part"
908 " of constant-pool entry: ");
909 print_generic_expr (dump_file, expr);
911 maybe_add_sra_candidate (base);
914 if (!DECL_P (base) || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
915 return NULL;
917 if (sra_mode == SRA_MODE_EARLY_IPA)
919 if (size < 0 || size != max_size)
921 disqualify_candidate (base, "Encountered a variable sized access.");
922 return NULL;
924 if (TREE_CODE (expr) == COMPONENT_REF
925 && DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
927 disqualify_candidate (base, "Encountered a bit-field access.");
928 return NULL;
930 gcc_checking_assert ((offset % BITS_PER_UNIT) == 0);
932 if (ptr)
933 mark_parm_dereference (base, offset + size, stmt);
935 else
937 if (size != max_size)
939 size = max_size;
940 unscalarizable_region = true;
942 if (size < 0)
944 disqualify_candidate (base, "Encountered an unconstrained access.");
945 return NULL;
949 access = create_access_1 (base, offset, size);
950 access->expr = expr;
951 access->type = TREE_TYPE (expr);
952 access->write = write;
953 access->grp_unscalarizable_region = unscalarizable_region;
954 access->stmt = stmt;
955 access->reverse = reverse;
957 if (TREE_CODE (expr) == COMPONENT_REF
958 && DECL_NONADDRESSABLE_P (TREE_OPERAND (expr, 1)))
959 access->non_addressable = 1;
961 return access;
965 /* Return true iff TYPE is scalarizable - i.e. a RECORD_TYPE or fixed-length
966 ARRAY_TYPE with fields that are either of gimple register types (excluding
967 bit-fields) or (recursively) scalarizable types. CONST_DECL must be true if
968 we are considering a decl from constant pool. If it is false, char arrays
969 will be refused. */
971 static bool
972 scalarizable_type_p (tree type, bool const_decl)
974 gcc_assert (!is_gimple_reg_type (type));
975 if (type_contains_placeholder_p (type))
976 return false;
978 switch (TREE_CODE (type))
980 case RECORD_TYPE:
981 for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
982 if (TREE_CODE (fld) == FIELD_DECL)
984 tree ft = TREE_TYPE (fld);
986 if (DECL_BIT_FIELD (fld))
987 return false;
989 if (!is_gimple_reg_type (ft)
990 && !scalarizable_type_p (ft, const_decl))
991 return false;
994 return true;
996 case ARRAY_TYPE:
998 HOST_WIDE_INT min_elem_size;
999 if (const_decl)
1000 min_elem_size = 0;
1001 else
1002 min_elem_size = BITS_PER_UNIT;
1004 if (TYPE_DOMAIN (type) == NULL_TREE
1005 || !tree_fits_shwi_p (TYPE_SIZE (type))
1006 || !tree_fits_shwi_p (TYPE_SIZE (TREE_TYPE (type)))
1007 || (tree_to_shwi (TYPE_SIZE (TREE_TYPE (type))) <= min_elem_size)
1008 || !tree_fits_shwi_p (TYPE_MIN_VALUE (TYPE_DOMAIN (type))))
1009 return false;
1010 if (tree_to_shwi (TYPE_SIZE (type)) == 0
1011 && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE)
1012 /* Zero-element array, should not prevent scalarization. */
1014 else if ((tree_to_shwi (TYPE_SIZE (type)) <= 0)
1015 || !tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
1016 /* Variable-length array, do not allow scalarization. */
1017 return false;
1019 tree elem = TREE_TYPE (type);
1020 if (!is_gimple_reg_type (elem)
1021 && !scalarizable_type_p (elem, const_decl))
1022 return false;
1023 return true;
1025 default:
1026 return false;
1030 static void scalarize_elem (tree, HOST_WIDE_INT, HOST_WIDE_INT, bool, tree, tree);
1032 /* Create total_scalarization accesses for all scalar fields of a member
1033 of type DECL_TYPE conforming to scalarizable_type_p. BASE
1034 must be the top-most VAR_DECL representing the variable; within that,
1035 OFFSET locates the member and REF must be the memory reference expression for
1036 the member. */
1038 static void
1039 completely_scalarize (tree base, tree decl_type, HOST_WIDE_INT offset, tree ref)
1041 switch (TREE_CODE (decl_type))
1043 case RECORD_TYPE:
1044 for (tree fld = TYPE_FIELDS (decl_type); fld; fld = DECL_CHAIN (fld))
1045 if (TREE_CODE (fld) == FIELD_DECL)
1047 HOST_WIDE_INT pos = offset + int_bit_position (fld);
1048 tree ft = TREE_TYPE (fld);
1049 tree nref = build3 (COMPONENT_REF, ft, ref, fld, NULL_TREE);
1051 scalarize_elem (base, pos, tree_to_uhwi (DECL_SIZE (fld)),
1052 TYPE_REVERSE_STORAGE_ORDER (decl_type),
1053 nref, ft);
1055 break;
1056 case ARRAY_TYPE:
1058 tree elemtype = TREE_TYPE (decl_type);
1059 tree elem_size = TYPE_SIZE (elemtype);
1060 gcc_assert (elem_size && tree_fits_shwi_p (elem_size));
1061 HOST_WIDE_INT el_size = tree_to_shwi (elem_size);
1062 gcc_assert (el_size > 0);
1064 tree minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (decl_type));
1065 gcc_assert (TREE_CODE (minidx) == INTEGER_CST);
1066 tree maxidx = TYPE_MAX_VALUE (TYPE_DOMAIN (decl_type));
1067 /* Skip (some) zero-length arrays; others have MAXIDX == MINIDX - 1. */
1068 if (maxidx)
1070 gcc_assert (TREE_CODE (maxidx) == INTEGER_CST);
1071 tree domain = TYPE_DOMAIN (decl_type);
1072 /* MINIDX and MAXIDX are inclusive, and must be interpreted in
1073 DOMAIN (e.g. signed int, whereas min/max may be size_int). */
1074 offset_int idx = wi::to_offset (minidx);
1075 offset_int max = wi::to_offset (maxidx);
1076 if (!TYPE_UNSIGNED (domain))
1078 idx = wi::sext (idx, TYPE_PRECISION (domain));
1079 max = wi::sext (max, TYPE_PRECISION (domain));
1081 for (int el_off = offset; idx <= max; ++idx)
1083 tree nref = build4 (ARRAY_REF, elemtype,
1084 ref,
1085 wide_int_to_tree (domain, idx),
1086 NULL_TREE, NULL_TREE);
1087 scalarize_elem (base, el_off, el_size,
1088 TYPE_REVERSE_STORAGE_ORDER (decl_type),
1089 nref, elemtype);
1090 el_off += el_size;
1094 break;
1095 default:
1096 gcc_unreachable ();
1100 /* Create total_scalarization accesses for a member of type TYPE, which must
1101 satisfy either is_gimple_reg_type or scalarizable_type_p. BASE must be the
1102 top-most VAR_DECL representing the variable; within that, POS and SIZE locate
1103 the member, REVERSE gives its torage order. and REF must be the reference
1104 expression for it. */
1106 static void
1107 scalarize_elem (tree base, HOST_WIDE_INT pos, HOST_WIDE_INT size, bool reverse,
1108 tree ref, tree type)
1110 if (is_gimple_reg_type (type))
1112 struct access *access = create_access_1 (base, pos, size);
1113 access->expr = ref;
1114 access->type = type;
1115 access->grp_total_scalarization = 1;
1116 access->reverse = reverse;
1117 /* Accesses for intraprocedural SRA can have their stmt NULL. */
1119 else
1120 completely_scalarize (base, type, pos, ref);
1123 /* Create a total_scalarization access for VAR as a whole. VAR must be of a
1124 RECORD_TYPE or ARRAY_TYPE conforming to scalarizable_type_p. */
1126 static void
1127 create_total_scalarization_access (tree var)
1129 HOST_WIDE_INT size = tree_to_uhwi (DECL_SIZE (var));
1130 struct access *access;
1132 access = create_access_1 (var, 0, size);
1133 access->expr = var;
1134 access->type = TREE_TYPE (var);
1135 access->grp_total_scalarization = 1;
1138 /* Return true if REF has an VIEW_CONVERT_EXPR somewhere in it. */
1140 static inline bool
1141 contains_view_convert_expr_p (const_tree ref)
1143 while (handled_component_p (ref))
1145 if (TREE_CODE (ref) == VIEW_CONVERT_EXPR)
1146 return true;
1147 ref = TREE_OPERAND (ref, 0);
1150 return false;
1153 /* Return true if REF contains a VIEW_CONVERT_EXPR or a MEM_REF that performs
1154 type conversion or a COMPONENT_REF with a bit-field field declaration. */
1156 static bool
1157 contains_vce_or_bfcref_p (const_tree ref)
1159 while (handled_component_p (ref))
1161 if (TREE_CODE (ref) == VIEW_CONVERT_EXPR
1162 || (TREE_CODE (ref) == COMPONENT_REF
1163 && DECL_BIT_FIELD (TREE_OPERAND (ref, 1))))
1164 return true;
1165 ref = TREE_OPERAND (ref, 0);
1168 if (TREE_CODE (ref) != MEM_REF
1169 || TREE_CODE (TREE_OPERAND (ref, 0)) != ADDR_EXPR)
1170 return false;
1172 tree mem = TREE_OPERAND (TREE_OPERAND (ref, 0), 0);
1173 if (TYPE_MAIN_VARIANT (TREE_TYPE (ref))
1174 != TYPE_MAIN_VARIANT (TREE_TYPE (mem)))
1175 return true;
1177 return false;
1180 /* Search the given tree for a declaration by skipping handled components and
1181 exclude it from the candidates. */
1183 static void
1184 disqualify_base_of_expr (tree t, const char *reason)
1186 t = get_base_address (t);
1187 if (sra_mode == SRA_MODE_EARLY_IPA
1188 && TREE_CODE (t) == MEM_REF)
1189 t = get_ssa_base_param (TREE_OPERAND (t, 0));
1191 if (t && DECL_P (t))
1192 disqualify_candidate (t, reason);
1195 /* Scan expression EXPR and create access structures for all accesses to
1196 candidates for scalarization. Return the created access or NULL if none is
1197 created. */
1199 static struct access *
1200 build_access_from_expr_1 (tree expr, gimple *stmt, bool write)
1202 struct access *ret = NULL;
1203 bool partial_ref;
1205 if (TREE_CODE (expr) == BIT_FIELD_REF
1206 || TREE_CODE (expr) == IMAGPART_EXPR
1207 || TREE_CODE (expr) == REALPART_EXPR)
1209 expr = TREE_OPERAND (expr, 0);
1210 partial_ref = true;
1212 else
1213 partial_ref = false;
1215 if (storage_order_barrier_p (expr))
1217 disqualify_base_of_expr (expr, "storage order barrier.");
1218 return NULL;
1221 /* We need to dive through V_C_Es in order to get the size of its parameter
1222 and not the result type. Ada produces such statements. We are also
1223 capable of handling the topmost V_C_E but not any of those buried in other
1224 handled components. */
1225 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
1226 expr = TREE_OPERAND (expr, 0);
1228 if (contains_view_convert_expr_p (expr))
1230 disqualify_base_of_expr (expr, "V_C_E under a different handled "
1231 "component.");
1232 return NULL;
1234 if (TREE_THIS_VOLATILE (expr))
1236 disqualify_base_of_expr (expr, "part of a volatile reference.");
1237 return NULL;
1240 switch (TREE_CODE (expr))
1242 case MEM_REF:
1243 if (TREE_CODE (TREE_OPERAND (expr, 0)) != ADDR_EXPR
1244 && sra_mode != SRA_MODE_EARLY_IPA)
1245 return NULL;
1246 /* fall through */
1247 case VAR_DECL:
1248 case PARM_DECL:
1249 case RESULT_DECL:
1250 case COMPONENT_REF:
1251 case ARRAY_REF:
1252 case ARRAY_RANGE_REF:
1253 ret = create_access (expr, stmt, write);
1254 break;
1256 default:
1257 break;
1260 if (write && partial_ref && ret)
1261 ret->grp_partial_lhs = 1;
1263 return ret;
1266 /* Scan expression EXPR and create access structures for all accesses to
1267 candidates for scalarization. Return true if any access has been inserted.
1268 STMT must be the statement from which the expression is taken, WRITE must be
1269 true if the expression is a store and false otherwise. */
1271 static bool
1272 build_access_from_expr (tree expr, gimple *stmt, bool write)
1274 struct access *access;
1276 access = build_access_from_expr_1 (expr, stmt, write);
1277 if (access)
1279 /* This means the aggregate is accesses as a whole in a way other than an
1280 assign statement and thus cannot be removed even if we had a scalar
1281 replacement for everything. */
1282 if (cannot_scalarize_away_bitmap)
1283 bitmap_set_bit (cannot_scalarize_away_bitmap, DECL_UID (access->base));
1284 return true;
1286 return false;
1289 /* Return the single non-EH successor edge of BB or NULL if there is none or
1290 more than one. */
1292 static edge
1293 single_non_eh_succ (basic_block bb)
1295 edge e, res = NULL;
1296 edge_iterator ei;
1298 FOR_EACH_EDGE (e, ei, bb->succs)
1299 if (!(e->flags & EDGE_EH))
1301 if (res)
1302 return NULL;
1303 res = e;
1306 return res;
1309 /* Disqualify LHS and RHS for scalarization if STMT has to terminate its BB and
1310 there is no alternative spot where to put statements SRA might need to
1311 generate after it. The spot we are looking for is an edge leading to a
1312 single non-EH successor, if it exists and is indeed single. RHS may be
1313 NULL, in that case ignore it. */
1315 static bool
1316 disqualify_if_bad_bb_terminating_stmt (gimple *stmt, tree lhs, tree rhs)
1318 if ((sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
1319 && stmt_ends_bb_p (stmt))
1321 if (single_non_eh_succ (gimple_bb (stmt)))
1322 return false;
1324 disqualify_base_of_expr (lhs, "LHS of a throwing stmt.");
1325 if (rhs)
1326 disqualify_base_of_expr (rhs, "RHS of a throwing stmt.");
1327 return true;
1329 return false;
1332 /* Return true if the nature of BASE is such that it contains data even if
1333 there is no write to it in the function. */
1335 static bool
1336 comes_initialized_p (tree base)
1338 return TREE_CODE (base) == PARM_DECL || constant_decl_p (base);
1341 /* Scan expressions occurring in STMT, create access structures for all accesses
1342 to candidates for scalarization and remove those candidates which occur in
1343 statements or expressions that prevent them from being split apart. Return
1344 true if any access has been inserted. */
1346 static bool
1347 build_accesses_from_assign (gimple *stmt)
1349 tree lhs, rhs;
1350 struct access *lacc, *racc;
1352 if (!gimple_assign_single_p (stmt)
1353 /* Scope clobbers don't influence scalarization. */
1354 || gimple_clobber_p (stmt))
1355 return false;
1357 lhs = gimple_assign_lhs (stmt);
1358 rhs = gimple_assign_rhs1 (stmt);
1360 if (disqualify_if_bad_bb_terminating_stmt (stmt, lhs, rhs))
1361 return false;
1363 racc = build_access_from_expr_1 (rhs, stmt, false);
1364 lacc = build_access_from_expr_1 (lhs, stmt, true);
1366 if (lacc)
1368 lacc->grp_assignment_write = 1;
1369 if (storage_order_barrier_p (rhs))
1370 lacc->grp_unscalarizable_region = 1;
1373 if (racc)
1375 racc->grp_assignment_read = 1;
1376 if (should_scalarize_away_bitmap && !gimple_has_volatile_ops (stmt)
1377 && !is_gimple_reg_type (racc->type))
1379 if (contains_vce_or_bfcref_p (rhs))
1380 bitmap_set_bit (cannot_scalarize_away_bitmap,
1381 DECL_UID (racc->base));
1382 else
1383 bitmap_set_bit (should_scalarize_away_bitmap,
1384 DECL_UID (racc->base));
1386 if (storage_order_barrier_p (lhs))
1387 racc->grp_unscalarizable_region = 1;
1390 if (lacc && racc
1391 && (sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
1392 && !lacc->grp_unscalarizable_region
1393 && !racc->grp_unscalarizable_region
1394 && AGGREGATE_TYPE_P (TREE_TYPE (lhs))
1395 && lacc->size == racc->size
1396 && useless_type_conversion_p (lacc->type, racc->type))
1398 struct assign_link *link;
1400 link = assign_link_pool.allocate ();
1401 memset (link, 0, sizeof (struct assign_link));
1403 link->lacc = lacc;
1404 link->racc = racc;
1405 add_link_to_rhs (racc, link);
1406 add_access_to_work_queue (racc);
1408 /* Let's delay marking the areas as written until propagation of accesses
1409 across link, unless the nature of rhs tells us that its data comes
1410 from elsewhere. */
1411 if (!comes_initialized_p (racc->base))
1412 lacc->write = false;
1415 return lacc || racc;
1418 /* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine
1419 GIMPLE_ASM operands with memory constrains which cannot be scalarized. */
1421 static bool
1422 asm_visit_addr (gimple *, tree op, tree, void *)
1424 op = get_base_address (op);
1425 if (op
1426 && DECL_P (op))
1427 disqualify_candidate (op, "Non-scalarizable GIMPLE_ASM operand.");
1429 return false;
1432 /* Return true iff callsite CALL has at least as many actual arguments as there
1433 are formal parameters of the function currently processed by IPA-SRA and
1434 that their types match. */
1436 static inline bool
1437 callsite_arguments_match_p (gimple *call)
1439 if (gimple_call_num_args (call) < (unsigned) func_param_count)
1440 return false;
1442 tree parm;
1443 int i;
1444 for (parm = DECL_ARGUMENTS (current_function_decl), i = 0;
1445 parm;
1446 parm = DECL_CHAIN (parm), i++)
1448 tree arg = gimple_call_arg (call, i);
1449 if (!useless_type_conversion_p (TREE_TYPE (parm), TREE_TYPE (arg)))
1450 return false;
1452 return true;
1455 /* Scan function and look for interesting expressions and create access
1456 structures for them. Return true iff any access is created. */
1458 static bool
1459 scan_function (void)
1461 basic_block bb;
1462 bool ret = false;
1464 FOR_EACH_BB_FN (bb, cfun)
1466 gimple_stmt_iterator gsi;
1467 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1469 gimple *stmt = gsi_stmt (gsi);
1470 tree t;
1471 unsigned i;
1473 if (final_bbs && stmt_can_throw_external (stmt))
1474 bitmap_set_bit (final_bbs, bb->index);
1475 switch (gimple_code (stmt))
1477 case GIMPLE_RETURN:
1478 t = gimple_return_retval (as_a <greturn *> (stmt));
1479 if (t != NULL_TREE)
1480 ret |= build_access_from_expr (t, stmt, false);
1481 if (final_bbs)
1482 bitmap_set_bit (final_bbs, bb->index);
1483 break;
1485 case GIMPLE_ASSIGN:
1486 ret |= build_accesses_from_assign (stmt);
1487 break;
1489 case GIMPLE_CALL:
1490 for (i = 0; i < gimple_call_num_args (stmt); i++)
1491 ret |= build_access_from_expr (gimple_call_arg (stmt, i),
1492 stmt, false);
1494 if (sra_mode == SRA_MODE_EARLY_IPA)
1496 tree dest = gimple_call_fndecl (stmt);
1497 int flags = gimple_call_flags (stmt);
1499 if (dest)
1501 if (DECL_BUILT_IN_CLASS (dest) == BUILT_IN_NORMAL
1502 && DECL_FUNCTION_CODE (dest) == BUILT_IN_APPLY_ARGS)
1503 encountered_apply_args = true;
1504 if (recursive_call_p (current_function_decl, dest))
1506 encountered_recursive_call = true;
1507 if (!callsite_arguments_match_p (stmt))
1508 encountered_unchangable_recursive_call = true;
1512 if (final_bbs
1513 && (flags & (ECF_CONST | ECF_PURE)) == 0)
1514 bitmap_set_bit (final_bbs, bb->index);
1517 t = gimple_call_lhs (stmt);
1518 if (t && !disqualify_if_bad_bb_terminating_stmt (stmt, t, NULL))
1519 ret |= build_access_from_expr (t, stmt, true);
1520 break;
1522 case GIMPLE_ASM:
1524 gasm *asm_stmt = as_a <gasm *> (stmt);
1525 walk_stmt_load_store_addr_ops (asm_stmt, NULL, NULL, NULL,
1526 asm_visit_addr);
1527 if (final_bbs)
1528 bitmap_set_bit (final_bbs, bb->index);
1530 for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
1532 t = TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
1533 ret |= build_access_from_expr (t, asm_stmt, false);
1535 for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
1537 t = TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
1538 ret |= build_access_from_expr (t, asm_stmt, true);
1541 break;
1543 default:
1544 break;
1549 return ret;
1552 /* Helper of QSORT function. There are pointers to accesses in the array. An
1553 access is considered smaller than another if it has smaller offset or if the
1554 offsets are the same but is size is bigger. */
1556 static int
1557 compare_access_positions (const void *a, const void *b)
1559 const access_p *fp1 = (const access_p *) a;
1560 const access_p *fp2 = (const access_p *) b;
1561 const access_p f1 = *fp1;
1562 const access_p f2 = *fp2;
1564 if (f1->offset != f2->offset)
1565 return f1->offset < f2->offset ? -1 : 1;
1567 if (f1->size == f2->size)
1569 if (f1->type == f2->type)
1570 return 0;
1571 /* Put any non-aggregate type before any aggregate type. */
1572 else if (!is_gimple_reg_type (f1->type)
1573 && is_gimple_reg_type (f2->type))
1574 return 1;
1575 else if (is_gimple_reg_type (f1->type)
1576 && !is_gimple_reg_type (f2->type))
1577 return -1;
1578 /* Put any complex or vector type before any other scalar type. */
1579 else if (TREE_CODE (f1->type) != COMPLEX_TYPE
1580 && TREE_CODE (f1->type) != VECTOR_TYPE
1581 && (TREE_CODE (f2->type) == COMPLEX_TYPE
1582 || TREE_CODE (f2->type) == VECTOR_TYPE))
1583 return 1;
1584 else if ((TREE_CODE (f1->type) == COMPLEX_TYPE
1585 || TREE_CODE (f1->type) == VECTOR_TYPE)
1586 && TREE_CODE (f2->type) != COMPLEX_TYPE
1587 && TREE_CODE (f2->type) != VECTOR_TYPE)
1588 return -1;
1589 /* Put any integral type before any non-integral type. When splicing, we
1590 make sure that those with insufficient precision and occupying the
1591 same space are not scalarized. */
1592 else if (INTEGRAL_TYPE_P (f1->type)
1593 && !INTEGRAL_TYPE_P (f2->type))
1594 return -1;
1595 else if (!INTEGRAL_TYPE_P (f1->type)
1596 && INTEGRAL_TYPE_P (f2->type))
1597 return 1;
1598 /* Put the integral type with the bigger precision first. */
1599 else if (INTEGRAL_TYPE_P (f1->type)
1600 && INTEGRAL_TYPE_P (f2->type)
1601 && (TYPE_PRECISION (f2->type) != TYPE_PRECISION (f1->type)))
1602 return TYPE_PRECISION (f2->type) - TYPE_PRECISION (f1->type);
1603 /* Stabilize the sort. */
1604 return TYPE_UID (f1->type) - TYPE_UID (f2->type);
1607 /* We want the bigger accesses first, thus the opposite operator in the next
1608 line: */
1609 return f1->size > f2->size ? -1 : 1;
1613 /* Append a name of the declaration to the name obstack. A helper function for
1614 make_fancy_name. */
1616 static void
1617 make_fancy_decl_name (tree decl)
1619 char buffer[32];
1621 tree name = DECL_NAME (decl);
1622 if (name)
1623 obstack_grow (&name_obstack, IDENTIFIER_POINTER (name),
1624 IDENTIFIER_LENGTH (name));
1625 else
1627 sprintf (buffer, "D%u", DECL_UID (decl));
1628 obstack_grow (&name_obstack, buffer, strlen (buffer));
1632 /* Helper for make_fancy_name. */
1634 static void
1635 make_fancy_name_1 (tree expr)
1637 char buffer[32];
1638 tree index;
1640 if (DECL_P (expr))
1642 make_fancy_decl_name (expr);
1643 return;
1646 switch (TREE_CODE (expr))
1648 case COMPONENT_REF:
1649 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1650 obstack_1grow (&name_obstack, '$');
1651 make_fancy_decl_name (TREE_OPERAND (expr, 1));
1652 break;
1654 case ARRAY_REF:
1655 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1656 obstack_1grow (&name_obstack, '$');
1657 /* Arrays with only one element may not have a constant as their
1658 index. */
1659 index = TREE_OPERAND (expr, 1);
1660 if (TREE_CODE (index) != INTEGER_CST)
1661 break;
1662 sprintf (buffer, HOST_WIDE_INT_PRINT_DEC, TREE_INT_CST_LOW (index));
1663 obstack_grow (&name_obstack, buffer, strlen (buffer));
1664 break;
1666 case ADDR_EXPR:
1667 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1668 break;
1670 case MEM_REF:
1671 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1672 if (!integer_zerop (TREE_OPERAND (expr, 1)))
1674 obstack_1grow (&name_obstack, '$');
1675 sprintf (buffer, HOST_WIDE_INT_PRINT_DEC,
1676 TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)));
1677 obstack_grow (&name_obstack, buffer, strlen (buffer));
1679 break;
1681 case BIT_FIELD_REF:
1682 case REALPART_EXPR:
1683 case IMAGPART_EXPR:
1684 gcc_unreachable (); /* we treat these as scalars. */
1685 break;
1686 default:
1687 break;
1691 /* Create a human readable name for replacement variable of ACCESS. */
1693 static char *
1694 make_fancy_name (tree expr)
1696 make_fancy_name_1 (expr);
1697 obstack_1grow (&name_obstack, '\0');
1698 return XOBFINISH (&name_obstack, char *);
1701 /* Construct a MEM_REF that would reference a part of aggregate BASE of type
1702 EXP_TYPE at the given OFFSET and with storage order REVERSE. If BASE is
1703 something for which get_addr_base_and_unit_offset returns NULL, gsi must
1704 be non-NULL and is used to insert new statements either before or below
1705 the current one as specified by INSERT_AFTER. This function is not capable
1706 of handling bitfields. */
1708 tree
1709 build_ref_for_offset (location_t loc, tree base, poly_int64 offset,
1710 bool reverse, tree exp_type, gimple_stmt_iterator *gsi,
1711 bool insert_after)
1713 tree prev_base = base;
1714 tree off;
1715 tree mem_ref;
1716 poly_int64 base_offset;
1717 unsigned HOST_WIDE_INT misalign;
1718 unsigned int align;
1720 /* Preserve address-space information. */
1721 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (base));
1722 if (as != TYPE_ADDR_SPACE (exp_type))
1723 exp_type = build_qualified_type (exp_type,
1724 TYPE_QUALS (exp_type)
1725 | ENCODE_QUAL_ADDR_SPACE (as));
1727 poly_int64 byte_offset = exact_div (offset, BITS_PER_UNIT);
1728 get_object_alignment_1 (base, &align, &misalign);
1729 base = get_addr_base_and_unit_offset (base, &base_offset);
1731 /* get_addr_base_and_unit_offset returns NULL for references with a variable
1732 offset such as array[var_index]. */
1733 if (!base)
1735 gassign *stmt;
1736 tree tmp, addr;
1738 gcc_checking_assert (gsi);
1739 tmp = make_ssa_name (build_pointer_type (TREE_TYPE (prev_base)));
1740 addr = build_fold_addr_expr (unshare_expr (prev_base));
1741 STRIP_USELESS_TYPE_CONVERSION (addr);
1742 stmt = gimple_build_assign (tmp, addr);
1743 gimple_set_location (stmt, loc);
1744 if (insert_after)
1745 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
1746 else
1747 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
1749 off = build_int_cst (reference_alias_ptr_type (prev_base), byte_offset);
1750 base = tmp;
1752 else if (TREE_CODE (base) == MEM_REF)
1754 off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
1755 base_offset + byte_offset);
1756 off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
1757 base = unshare_expr (TREE_OPERAND (base, 0));
1759 else
1761 off = build_int_cst (reference_alias_ptr_type (prev_base),
1762 base_offset + byte_offset);
1763 base = build_fold_addr_expr (unshare_expr (base));
1766 unsigned int align_bound = known_alignment (misalign + offset);
1767 if (align_bound != 0)
1768 align = MIN (align, align_bound);
1769 if (align != TYPE_ALIGN (exp_type))
1770 exp_type = build_aligned_type (exp_type, align);
1772 mem_ref = fold_build2_loc (loc, MEM_REF, exp_type, base, off);
1773 REF_REVERSE_STORAGE_ORDER (mem_ref) = reverse;
1774 if (TREE_THIS_VOLATILE (prev_base))
1775 TREE_THIS_VOLATILE (mem_ref) = 1;
1776 if (TREE_SIDE_EFFECTS (prev_base))
1777 TREE_SIDE_EFFECTS (mem_ref) = 1;
1778 return mem_ref;
1781 /* Construct a memory reference to a part of an aggregate BASE at the given
1782 OFFSET and of the same type as MODEL. In case this is a reference to a
1783 bit-field, the function will replicate the last component_ref of model's
1784 expr to access it. GSI and INSERT_AFTER have the same meaning as in
1785 build_ref_for_offset. */
1787 static tree
1788 build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
1789 struct access *model, gimple_stmt_iterator *gsi,
1790 bool insert_after)
1792 if (TREE_CODE (model->expr) == COMPONENT_REF
1793 && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
1795 /* This access represents a bit-field. */
1796 tree t, exp_type, fld = TREE_OPERAND (model->expr, 1);
1798 offset -= int_bit_position (fld);
1799 exp_type = TREE_TYPE (TREE_OPERAND (model->expr, 0));
1800 t = build_ref_for_offset (loc, base, offset, model->reverse, exp_type,
1801 gsi, insert_after);
1802 /* The flag will be set on the record type. */
1803 REF_REVERSE_STORAGE_ORDER (t) = 0;
1804 return fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (fld), t, fld,
1805 NULL_TREE);
1807 else
1808 return
1809 build_ref_for_offset (loc, base, offset, model->reverse, model->type,
1810 gsi, insert_after);
1813 /* Attempt to build a memory reference that we could but into a gimple
1814 debug_bind statement. Similar to build_ref_for_model but punts if it has to
1815 create statements and return s NULL instead. This function also ignores
1816 alignment issues and so its results should never end up in non-debug
1817 statements. */
1819 static tree
1820 build_debug_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
1821 struct access *model)
1823 poly_int64 base_offset;
1824 tree off;
1826 if (TREE_CODE (model->expr) == COMPONENT_REF
1827 && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
1828 return NULL_TREE;
1830 base = get_addr_base_and_unit_offset (base, &base_offset);
1831 if (!base)
1832 return NULL_TREE;
1833 if (TREE_CODE (base) == MEM_REF)
1835 off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
1836 base_offset + offset / BITS_PER_UNIT);
1837 off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
1838 base = unshare_expr (TREE_OPERAND (base, 0));
1840 else
1842 off = build_int_cst (reference_alias_ptr_type (base),
1843 base_offset + offset / BITS_PER_UNIT);
1844 base = build_fold_addr_expr (unshare_expr (base));
1847 return fold_build2_loc (loc, MEM_REF, model->type, base, off);
1850 /* Construct a memory reference consisting of component_refs and array_refs to
1851 a part of an aggregate *RES (which is of type TYPE). The requested part
1852 should have type EXP_TYPE at be the given OFFSET. This function might not
1853 succeed, it returns true when it does and only then *RES points to something
1854 meaningful. This function should be used only to build expressions that we
1855 might need to present to user (e.g. in warnings). In all other situations,
1856 build_ref_for_model or build_ref_for_offset should be used instead. */
1858 static bool
1859 build_user_friendly_ref_for_offset (tree *res, tree type, HOST_WIDE_INT offset,
1860 tree exp_type)
1862 while (1)
1864 tree fld;
1865 tree tr_size, index, minidx;
1866 HOST_WIDE_INT el_size;
1868 if (offset == 0 && exp_type
1869 && types_compatible_p (exp_type, type))
1870 return true;
1872 switch (TREE_CODE (type))
1874 case UNION_TYPE:
1875 case QUAL_UNION_TYPE:
1876 case RECORD_TYPE:
1877 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
1879 HOST_WIDE_INT pos, size;
1880 tree tr_pos, expr, *expr_ptr;
1882 if (TREE_CODE (fld) != FIELD_DECL)
1883 continue;
1885 tr_pos = bit_position (fld);
1886 if (!tr_pos || !tree_fits_uhwi_p (tr_pos))
1887 continue;
1888 pos = tree_to_uhwi (tr_pos);
1889 gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0);
1890 tr_size = DECL_SIZE (fld);
1891 if (!tr_size || !tree_fits_uhwi_p (tr_size))
1892 continue;
1893 size = tree_to_uhwi (tr_size);
1894 if (size == 0)
1896 if (pos != offset)
1897 continue;
1899 else if (pos > offset || (pos + size) <= offset)
1900 continue;
1902 expr = build3 (COMPONENT_REF, TREE_TYPE (fld), *res, fld,
1903 NULL_TREE);
1904 expr_ptr = &expr;
1905 if (build_user_friendly_ref_for_offset (expr_ptr, TREE_TYPE (fld),
1906 offset - pos, exp_type))
1908 *res = expr;
1909 return true;
1912 return false;
1914 case ARRAY_TYPE:
1915 tr_size = TYPE_SIZE (TREE_TYPE (type));
1916 if (!tr_size || !tree_fits_uhwi_p (tr_size))
1917 return false;
1918 el_size = tree_to_uhwi (tr_size);
1920 minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
1921 if (TREE_CODE (minidx) != INTEGER_CST || el_size == 0)
1922 return false;
1923 index = build_int_cst (TYPE_DOMAIN (type), offset / el_size);
1924 if (!integer_zerop (minidx))
1925 index = int_const_binop (PLUS_EXPR, index, minidx);
1926 *res = build4 (ARRAY_REF, TREE_TYPE (type), *res, index,
1927 NULL_TREE, NULL_TREE);
1928 offset = offset % el_size;
1929 type = TREE_TYPE (type);
1930 break;
1932 default:
1933 if (offset != 0)
1934 return false;
1936 if (exp_type)
1937 return false;
1938 else
1939 return true;
1944 /* Return true iff TYPE is stdarg va_list type. */
1946 static inline bool
1947 is_va_list_type (tree type)
1949 return TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (va_list_type_node);
1952 /* Print message to dump file why a variable was rejected. */
1954 static void
1955 reject (tree var, const char *msg)
1957 if (dump_file && (dump_flags & TDF_DETAILS))
1959 fprintf (dump_file, "Rejected (%d): %s: ", DECL_UID (var), msg);
1960 print_generic_expr (dump_file, var);
1961 fprintf (dump_file, "\n");
1965 /* Return true if VAR is a candidate for SRA. */
1967 static bool
1968 maybe_add_sra_candidate (tree var)
1970 tree type = TREE_TYPE (var);
1971 const char *msg;
1972 tree_node **slot;
1974 if (!AGGREGATE_TYPE_P (type))
1976 reject (var, "not aggregate");
1977 return false;
1979 /* Allow constant-pool entries (that "need to live in memory")
1980 unless we are doing IPA SRA. */
1981 if (needs_to_live_in_memory (var)
1982 && (sra_mode == SRA_MODE_EARLY_IPA || !constant_decl_p (var)))
1984 reject (var, "needs to live in memory");
1985 return false;
1987 if (TREE_THIS_VOLATILE (var))
1989 reject (var, "is volatile");
1990 return false;
1992 if (!COMPLETE_TYPE_P (type))
1994 reject (var, "has incomplete type");
1995 return false;
1997 if (!tree_fits_uhwi_p (TYPE_SIZE (type)))
1999 reject (var, "type size not fixed");
2000 return false;
2002 if (tree_to_uhwi (TYPE_SIZE (type)) == 0)
2004 reject (var, "type size is zero");
2005 return false;
2007 if (type_internals_preclude_sra_p (type, &msg))
2009 reject (var, msg);
2010 return false;
2012 if (/* Fix for PR 41089. tree-stdarg.c needs to have va_lists intact but
2013 we also want to schedule it rather late. Thus we ignore it in
2014 the early pass. */
2015 (sra_mode == SRA_MODE_EARLY_INTRA
2016 && is_va_list_type (type)))
2018 reject (var, "is va_list");
2019 return false;
2022 bitmap_set_bit (candidate_bitmap, DECL_UID (var));
2023 slot = candidates->find_slot_with_hash (var, DECL_UID (var), INSERT);
2024 *slot = var;
2026 if (dump_file && (dump_flags & TDF_DETAILS))
2028 fprintf (dump_file, "Candidate (%d): ", DECL_UID (var));
2029 print_generic_expr (dump_file, var);
2030 fprintf (dump_file, "\n");
2033 return true;
2036 /* The very first phase of intraprocedural SRA. It marks in candidate_bitmap
2037 those with type which is suitable for scalarization. */
2039 static bool
2040 find_var_candidates (void)
2042 tree var, parm;
2043 unsigned int i;
2044 bool ret = false;
2046 for (parm = DECL_ARGUMENTS (current_function_decl);
2047 parm;
2048 parm = DECL_CHAIN (parm))
2049 ret |= maybe_add_sra_candidate (parm);
2051 FOR_EACH_LOCAL_DECL (cfun, i, var)
2053 if (!VAR_P (var))
2054 continue;
2056 ret |= maybe_add_sra_candidate (var);
2059 return ret;
2062 /* Sort all accesses for the given variable, check for partial overlaps and
2063 return NULL if there are any. If there are none, pick a representative for
2064 each combination of offset and size and create a linked list out of them.
2065 Return the pointer to the first representative and make sure it is the first
2066 one in the vector of accesses. */
2068 static struct access *
2069 sort_and_splice_var_accesses (tree var)
2071 int i, j, access_count;
2072 struct access *res, **prev_acc_ptr = &res;
2073 vec<access_p> *access_vec;
2074 bool first = true;
2075 HOST_WIDE_INT low = -1, high = 0;
2077 access_vec = get_base_access_vector (var);
2078 if (!access_vec)
2079 return NULL;
2080 access_count = access_vec->length ();
2082 /* Sort by <OFFSET, SIZE>. */
2083 access_vec->qsort (compare_access_positions);
2085 i = 0;
2086 while (i < access_count)
2088 struct access *access = (*access_vec)[i];
2089 bool grp_write = access->write;
2090 bool grp_read = !access->write;
2091 bool grp_scalar_write = access->write
2092 && is_gimple_reg_type (access->type);
2093 bool grp_scalar_read = !access->write
2094 && is_gimple_reg_type (access->type);
2095 bool grp_assignment_read = access->grp_assignment_read;
2096 bool grp_assignment_write = access->grp_assignment_write;
2097 bool multiple_scalar_reads = false;
2098 bool total_scalarization = access->grp_total_scalarization;
2099 bool grp_partial_lhs = access->grp_partial_lhs;
2100 bool first_scalar = is_gimple_reg_type (access->type);
2101 bool unscalarizable_region = access->grp_unscalarizable_region;
2102 bool bf_non_full_precision
2103 = (INTEGRAL_TYPE_P (access->type)
2104 && TYPE_PRECISION (access->type) != access->size
2105 && TREE_CODE (access->expr) == COMPONENT_REF
2106 && DECL_BIT_FIELD (TREE_OPERAND (access->expr, 1)));
2108 if (first || access->offset >= high)
2110 first = false;
2111 low = access->offset;
2112 high = access->offset + access->size;
2114 else if (access->offset > low && access->offset + access->size > high)
2115 return NULL;
2116 else
2117 gcc_assert (access->offset >= low
2118 && access->offset + access->size <= high);
2120 j = i + 1;
2121 while (j < access_count)
2123 struct access *ac2 = (*access_vec)[j];
2124 if (ac2->offset != access->offset || ac2->size != access->size)
2125 break;
2126 if (ac2->write)
2128 grp_write = true;
2129 grp_scalar_write = (grp_scalar_write
2130 || is_gimple_reg_type (ac2->type));
2132 else
2134 grp_read = true;
2135 if (is_gimple_reg_type (ac2->type))
2137 if (grp_scalar_read)
2138 multiple_scalar_reads = true;
2139 else
2140 grp_scalar_read = true;
2143 grp_assignment_read |= ac2->grp_assignment_read;
2144 grp_assignment_write |= ac2->grp_assignment_write;
2145 grp_partial_lhs |= ac2->grp_partial_lhs;
2146 unscalarizable_region |= ac2->grp_unscalarizable_region;
2147 total_scalarization |= ac2->grp_total_scalarization;
2148 relink_to_new_repr (access, ac2);
2150 /* If there are both aggregate-type and scalar-type accesses with
2151 this combination of size and offset, the comparison function
2152 should have put the scalars first. */
2153 gcc_assert (first_scalar || !is_gimple_reg_type (ac2->type));
2154 /* It also prefers integral types to non-integral. However, when the
2155 precision of the selected type does not span the entire area and
2156 should also be used for a non-integer (i.e. float), we must not
2157 let that happen. Normally analyze_access_subtree expands the type
2158 to cover the entire area but for bit-fields it doesn't. */
2159 if (bf_non_full_precision && !INTEGRAL_TYPE_P (ac2->type))
2161 if (dump_file && (dump_flags & TDF_DETAILS))
2163 fprintf (dump_file, "Cannot scalarize the following access "
2164 "because insufficient precision integer type was "
2165 "selected.\n ");
2166 dump_access (dump_file, access, false);
2168 unscalarizable_region = true;
2170 ac2->group_representative = access;
2171 j++;
2174 i = j;
2176 access->group_representative = access;
2177 access->grp_write = grp_write;
2178 access->grp_read = grp_read;
2179 access->grp_scalar_read = grp_scalar_read;
2180 access->grp_scalar_write = grp_scalar_write;
2181 access->grp_assignment_read = grp_assignment_read;
2182 access->grp_assignment_write = grp_assignment_write;
2183 access->grp_hint = total_scalarization
2184 || (multiple_scalar_reads && !constant_decl_p (var));
2185 access->grp_total_scalarization = total_scalarization;
2186 access->grp_partial_lhs = grp_partial_lhs;
2187 access->grp_unscalarizable_region = unscalarizable_region;
2189 *prev_acc_ptr = access;
2190 prev_acc_ptr = &access->next_grp;
2193 gcc_assert (res == (*access_vec)[0]);
2194 return res;
2197 /* Create a variable for the given ACCESS which determines the type, name and a
2198 few other properties. Return the variable declaration and store it also to
2199 ACCESS->replacement. */
2201 static tree
2202 create_access_replacement (struct access *access)
2204 tree repl;
2206 if (access->grp_to_be_debug_replaced)
2208 repl = create_tmp_var_raw (access->type);
2209 DECL_CONTEXT (repl) = current_function_decl;
2211 else
2212 /* Drop any special alignment on the type if it's not on the main
2213 variant. This avoids issues with weirdo ABIs like AAPCS. */
2214 repl = create_tmp_var (build_qualified_type
2215 (TYPE_MAIN_VARIANT (access->type),
2216 TYPE_QUALS (access->type)), "SR");
2217 if (TREE_CODE (access->type) == COMPLEX_TYPE
2218 || TREE_CODE (access->type) == VECTOR_TYPE)
2220 if (!access->grp_partial_lhs)
2221 DECL_GIMPLE_REG_P (repl) = 1;
2223 else if (access->grp_partial_lhs
2224 && is_gimple_reg_type (access->type))
2225 TREE_ADDRESSABLE (repl) = 1;
2227 DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base);
2228 DECL_ARTIFICIAL (repl) = 1;
2229 DECL_IGNORED_P (repl) = DECL_IGNORED_P (access->base);
2231 if (DECL_NAME (access->base)
2232 && !DECL_IGNORED_P (access->base)
2233 && !DECL_ARTIFICIAL (access->base))
2235 char *pretty_name = make_fancy_name (access->expr);
2236 tree debug_expr = unshare_expr_without_location (access->expr), d;
2237 bool fail = false;
2239 DECL_NAME (repl) = get_identifier (pretty_name);
2240 DECL_NAMELESS (repl) = 1;
2241 obstack_free (&name_obstack, pretty_name);
2243 /* Get rid of any SSA_NAMEs embedded in debug_expr,
2244 as DECL_DEBUG_EXPR isn't considered when looking for still
2245 used SSA_NAMEs and thus they could be freed. All debug info
2246 generation cares is whether something is constant or variable
2247 and that get_ref_base_and_extent works properly on the
2248 expression. It cannot handle accesses at a non-constant offset
2249 though, so just give up in those cases. */
2250 for (d = debug_expr;
2251 !fail && (handled_component_p (d) || TREE_CODE (d) == MEM_REF);
2252 d = TREE_OPERAND (d, 0))
2253 switch (TREE_CODE (d))
2255 case ARRAY_REF:
2256 case ARRAY_RANGE_REF:
2257 if (TREE_OPERAND (d, 1)
2258 && TREE_CODE (TREE_OPERAND (d, 1)) != INTEGER_CST)
2259 fail = true;
2260 if (TREE_OPERAND (d, 3)
2261 && TREE_CODE (TREE_OPERAND (d, 3)) != INTEGER_CST)
2262 fail = true;
2263 /* FALLTHRU */
2264 case COMPONENT_REF:
2265 if (TREE_OPERAND (d, 2)
2266 && TREE_CODE (TREE_OPERAND (d, 2)) != INTEGER_CST)
2267 fail = true;
2268 break;
2269 case MEM_REF:
2270 if (TREE_CODE (TREE_OPERAND (d, 0)) != ADDR_EXPR)
2271 fail = true;
2272 else
2273 d = TREE_OPERAND (d, 0);
2274 break;
2275 default:
2276 break;
2278 if (!fail)
2280 SET_DECL_DEBUG_EXPR (repl, debug_expr);
2281 DECL_HAS_DEBUG_EXPR_P (repl) = 1;
2283 if (access->grp_no_warning)
2284 TREE_NO_WARNING (repl) = 1;
2285 else
2286 TREE_NO_WARNING (repl) = TREE_NO_WARNING (access->base);
2288 else
2289 TREE_NO_WARNING (repl) = 1;
2291 if (dump_file)
2293 if (access->grp_to_be_debug_replaced)
2295 fprintf (dump_file, "Created a debug-only replacement for ");
2296 print_generic_expr (dump_file, access->base);
2297 fprintf (dump_file, " offset: %u, size: %u\n",
2298 (unsigned) access->offset, (unsigned) access->size);
2300 else
2302 fprintf (dump_file, "Created a replacement for ");
2303 print_generic_expr (dump_file, access->base);
2304 fprintf (dump_file, " offset: %u, size: %u: ",
2305 (unsigned) access->offset, (unsigned) access->size);
2306 print_generic_expr (dump_file, repl);
2307 fprintf (dump_file, "\n");
2310 sra_stats.replacements++;
2312 return repl;
2315 /* Return ACCESS scalar replacement, which must exist. */
2317 static inline tree
2318 get_access_replacement (struct access *access)
2320 gcc_checking_assert (access->replacement_decl);
2321 return access->replacement_decl;
2325 /* Build a subtree of accesses rooted in *ACCESS, and move the pointer in the
2326 linked list along the way. Stop when *ACCESS is NULL or the access pointed
2327 to it is not "within" the root. Return false iff some accesses partially
2328 overlap. */
2330 static bool
2331 build_access_subtree (struct access **access)
2333 struct access *root = *access, *last_child = NULL;
2334 HOST_WIDE_INT limit = root->offset + root->size;
2336 *access = (*access)->next_grp;
2337 while (*access && (*access)->offset + (*access)->size <= limit)
2339 if (!last_child)
2340 root->first_child = *access;
2341 else
2342 last_child->next_sibling = *access;
2343 last_child = *access;
2344 (*access)->parent = root;
2345 (*access)->grp_write |= root->grp_write;
2347 if (!build_access_subtree (access))
2348 return false;
2351 if (*access && (*access)->offset < limit)
2352 return false;
2354 return true;
2357 /* Build a tree of access representatives, ACCESS is the pointer to the first
2358 one, others are linked in a list by the next_grp field. Return false iff
2359 some accesses partially overlap. */
2361 static bool
2362 build_access_trees (struct access *access)
2364 while (access)
2366 struct access *root = access;
2368 if (!build_access_subtree (&access))
2369 return false;
2370 root->next_grp = access;
2372 return true;
2375 /* Return true if expr contains some ARRAY_REFs into a variable bounded
2376 array. */
2378 static bool
2379 expr_with_var_bounded_array_refs_p (tree expr)
2381 while (handled_component_p (expr))
2383 if (TREE_CODE (expr) == ARRAY_REF
2384 && !tree_fits_shwi_p (array_ref_low_bound (expr)))
2385 return true;
2386 expr = TREE_OPERAND (expr, 0);
2388 return false;
2391 /* Analyze the subtree of accesses rooted in ROOT, scheduling replacements when
2392 both seeming beneficial and when ALLOW_REPLACEMENTS allows it. Also set all
2393 sorts of access flags appropriately along the way, notably always set
2394 grp_read and grp_assign_read according to MARK_READ and grp_write when
2395 MARK_WRITE is true.
2397 Creating a replacement for a scalar access is considered beneficial if its
2398 grp_hint is set (this means we are either attempting total scalarization or
2399 there is more than one direct read access) or according to the following
2400 table:
2402 Access written to through a scalar type (once or more times)
2404 | Written to in an assignment statement
2406 | | Access read as scalar _once_
2407 | | |
2408 | | | Read in an assignment statement
2409 | | | |
2410 | | | | Scalarize Comment
2411 -----------------------------------------------------------------------------
2412 0 0 0 0 No access for the scalar
2413 0 0 0 1 No access for the scalar
2414 0 0 1 0 No Single read - won't help
2415 0 0 1 1 No The same case
2416 0 1 0 0 No access for the scalar
2417 0 1 0 1 No access for the scalar
2418 0 1 1 0 Yes s = *g; return s.i;
2419 0 1 1 1 Yes The same case as above
2420 1 0 0 0 No Won't help
2421 1 0 0 1 Yes s.i = 1; *g = s;
2422 1 0 1 0 Yes s.i = 5; g = s.i;
2423 1 0 1 1 Yes The same case as above
2424 1 1 0 0 No Won't help.
2425 1 1 0 1 Yes s.i = 1; *g = s;
2426 1 1 1 0 Yes s = *g; return s.i;
2427 1 1 1 1 Yes Any of the above yeses */
2429 static bool
2430 analyze_access_subtree (struct access *root, struct access *parent,
2431 bool allow_replacements)
2433 struct access *child;
2434 HOST_WIDE_INT limit = root->offset + root->size;
2435 HOST_WIDE_INT covered_to = root->offset;
2436 bool scalar = is_gimple_reg_type (root->type);
2437 bool hole = false, sth_created = false;
2439 if (parent)
2441 if (parent->grp_read)
2442 root->grp_read = 1;
2443 if (parent->grp_assignment_read)
2444 root->grp_assignment_read = 1;
2445 if (parent->grp_write)
2446 root->grp_write = 1;
2447 if (parent->grp_assignment_write)
2448 root->grp_assignment_write = 1;
2449 if (parent->grp_total_scalarization)
2450 root->grp_total_scalarization = 1;
2453 if (root->grp_unscalarizable_region)
2454 allow_replacements = false;
2456 if (allow_replacements && expr_with_var_bounded_array_refs_p (root->expr))
2457 allow_replacements = false;
2459 for (child = root->first_child; child; child = child->next_sibling)
2461 hole |= covered_to < child->offset;
2462 sth_created |= analyze_access_subtree (child, root,
2463 allow_replacements && !scalar);
2465 root->grp_unscalarized_data |= child->grp_unscalarized_data;
2466 root->grp_total_scalarization &= child->grp_total_scalarization;
2467 if (child->grp_covered)
2468 covered_to += child->size;
2469 else
2470 hole = true;
2473 if (allow_replacements && scalar && !root->first_child
2474 && (root->grp_hint
2475 || ((root->grp_scalar_read || root->grp_assignment_read)
2476 && (root->grp_scalar_write || root->grp_assignment_write))))
2478 /* Always create access replacements that cover the whole access.
2479 For integral types this means the precision has to match.
2480 Avoid assumptions based on the integral type kind, too. */
2481 if (INTEGRAL_TYPE_P (root->type)
2482 && (TREE_CODE (root->type) != INTEGER_TYPE
2483 || TYPE_PRECISION (root->type) != root->size)
2484 /* But leave bitfield accesses alone. */
2485 && (TREE_CODE (root->expr) != COMPONENT_REF
2486 || !DECL_BIT_FIELD (TREE_OPERAND (root->expr, 1))))
2488 tree rt = root->type;
2489 gcc_assert ((root->offset % BITS_PER_UNIT) == 0
2490 && (root->size % BITS_PER_UNIT) == 0);
2491 root->type = build_nonstandard_integer_type (root->size,
2492 TYPE_UNSIGNED (rt));
2493 root->expr = build_ref_for_offset (UNKNOWN_LOCATION, root->base,
2494 root->offset, root->reverse,
2495 root->type, NULL, false);
2497 if (dump_file && (dump_flags & TDF_DETAILS))
2499 fprintf (dump_file, "Changing the type of a replacement for ");
2500 print_generic_expr (dump_file, root->base);
2501 fprintf (dump_file, " offset: %u, size: %u ",
2502 (unsigned) root->offset, (unsigned) root->size);
2503 fprintf (dump_file, " to an integer.\n");
2507 root->grp_to_be_replaced = 1;
2508 root->replacement_decl = create_access_replacement (root);
2509 sth_created = true;
2510 hole = false;
2512 else
2514 if (allow_replacements
2515 && scalar && !root->first_child
2516 && (root->grp_scalar_write || root->grp_assignment_write)
2517 && !bitmap_bit_p (cannot_scalarize_away_bitmap,
2518 DECL_UID (root->base)))
2520 gcc_checking_assert (!root->grp_scalar_read
2521 && !root->grp_assignment_read);
2522 sth_created = true;
2523 if (MAY_HAVE_DEBUG_BIND_STMTS)
2525 root->grp_to_be_debug_replaced = 1;
2526 root->replacement_decl = create_access_replacement (root);
2530 if (covered_to < limit)
2531 hole = true;
2532 if (scalar || !allow_replacements)
2533 root->grp_total_scalarization = 0;
2536 if (!hole || root->grp_total_scalarization)
2537 root->grp_covered = 1;
2538 else if (root->grp_write || comes_initialized_p (root->base))
2539 root->grp_unscalarized_data = 1; /* not covered and written to */
2540 return sth_created;
2543 /* Analyze all access trees linked by next_grp by the means of
2544 analyze_access_subtree. */
2545 static bool
2546 analyze_access_trees (struct access *access)
2548 bool ret = false;
2550 while (access)
2552 if (analyze_access_subtree (access, NULL, true))
2553 ret = true;
2554 access = access->next_grp;
2557 return ret;
2560 /* Return true iff a potential new child of LACC at offset OFFSET and with size
2561 SIZE would conflict with an already existing one. If exactly such a child
2562 already exists in LACC, store a pointer to it in EXACT_MATCH. */
2564 static bool
2565 child_would_conflict_in_lacc (struct access *lacc, HOST_WIDE_INT norm_offset,
2566 HOST_WIDE_INT size, struct access **exact_match)
2568 struct access *child;
2570 for (child = lacc->first_child; child; child = child->next_sibling)
2572 if (child->offset == norm_offset && child->size == size)
2574 *exact_match = child;
2575 return true;
2578 if (child->offset < norm_offset + size
2579 && child->offset + child->size > norm_offset)
2580 return true;
2583 return false;
2586 /* Create a new child access of PARENT, with all properties just like MODEL
2587 except for its offset and with its grp_write false and grp_read true.
2588 Return the new access or NULL if it cannot be created. Note that this
2589 access is created long after all splicing and sorting, it's not located in
2590 any access vector and is automatically a representative of its group. Set
2591 the gpr_write flag of the new accesss if SET_GRP_WRITE is true. */
2593 static struct access *
2594 create_artificial_child_access (struct access *parent, struct access *model,
2595 HOST_WIDE_INT new_offset,
2596 bool set_grp_write)
2598 struct access **child;
2599 tree expr = parent->base;
2601 gcc_assert (!model->grp_unscalarizable_region);
2603 struct access *access = access_pool.allocate ();
2604 memset (access, 0, sizeof (struct access));
2605 if (!build_user_friendly_ref_for_offset (&expr, TREE_TYPE (expr), new_offset,
2606 model->type))
2608 access->grp_no_warning = true;
2609 expr = build_ref_for_model (EXPR_LOCATION (parent->base), parent->base,
2610 new_offset, model, NULL, false);
2613 access->base = parent->base;
2614 access->expr = expr;
2615 access->offset = new_offset;
2616 access->size = model->size;
2617 access->type = model->type;
2618 access->grp_write = set_grp_write;
2619 access->grp_read = false;
2620 access->reverse = model->reverse;
2622 child = &parent->first_child;
2623 while (*child && (*child)->offset < new_offset)
2624 child = &(*child)->next_sibling;
2626 access->next_sibling = *child;
2627 *child = access;
2629 return access;
2633 /* Beginning with ACCESS, traverse its whole access subtree and mark all
2634 sub-trees as written to. If any of them has not been marked so previously
2635 and has assignment links leading from it, re-enqueue it. */
2637 static void
2638 subtree_mark_written_and_enqueue (struct access *access)
2640 if (access->grp_write)
2641 return;
2642 access->grp_write = true;
2643 add_access_to_work_queue (access);
2645 struct access *child;
2646 for (child = access->first_child; child; child = child->next_sibling)
2647 subtree_mark_written_and_enqueue (child);
2650 /* Propagate subaccesses and grp_write flags of RACC across an assignment link
2651 to LACC. Enqueue sub-accesses as necessary so that the write flag is
2652 propagated transitively. Return true if anything changed. Additionally, if
2653 RACC is a scalar access but LACC is not, change the type of the latter, if
2654 possible. */
2656 static bool
2657 propagate_subaccesses_across_link (struct access *lacc, struct access *racc)
2659 struct access *rchild;
2660 HOST_WIDE_INT norm_delta = lacc->offset - racc->offset;
2661 bool ret = false;
2663 /* IF the LHS is still not marked as being written to, we only need to do so
2664 if the RHS at this level actually was. */
2665 if (!lacc->grp_write)
2667 gcc_checking_assert (!comes_initialized_p (racc->base));
2668 if (racc->grp_write)
2670 subtree_mark_written_and_enqueue (lacc);
2671 ret = true;
2675 if (is_gimple_reg_type (lacc->type)
2676 || lacc->grp_unscalarizable_region
2677 || racc->grp_unscalarizable_region)
2679 if (!lacc->grp_write)
2681 ret = true;
2682 subtree_mark_written_and_enqueue (lacc);
2684 return ret;
2687 if (is_gimple_reg_type (racc->type))
2689 if (!lacc->grp_write)
2691 ret = true;
2692 subtree_mark_written_and_enqueue (lacc);
2694 if (!lacc->first_child && !racc->first_child)
2696 tree t = lacc->base;
2698 lacc->type = racc->type;
2699 if (build_user_friendly_ref_for_offset (&t, TREE_TYPE (t),
2700 lacc->offset, racc->type))
2701 lacc->expr = t;
2702 else
2704 lacc->expr = build_ref_for_model (EXPR_LOCATION (lacc->base),
2705 lacc->base, lacc->offset,
2706 racc, NULL, false);
2707 lacc->grp_no_warning = true;
2710 return ret;
2713 for (rchild = racc->first_child; rchild; rchild = rchild->next_sibling)
2715 struct access *new_acc = NULL;
2716 HOST_WIDE_INT norm_offset = rchild->offset + norm_delta;
2718 if (child_would_conflict_in_lacc (lacc, norm_offset, rchild->size,
2719 &new_acc))
2721 if (new_acc)
2723 if (!new_acc->grp_write && rchild->grp_write)
2725 gcc_assert (!lacc->grp_write);
2726 subtree_mark_written_and_enqueue (new_acc);
2727 ret = true;
2730 rchild->grp_hint = 1;
2731 new_acc->grp_hint |= new_acc->grp_read;
2732 if (rchild->first_child)
2733 ret |= propagate_subaccesses_across_link (new_acc, rchild);
2735 else
2737 if (!lacc->grp_write)
2739 ret = true;
2740 subtree_mark_written_and_enqueue (lacc);
2743 continue;
2746 if (rchild->grp_unscalarizable_region)
2748 if (rchild->grp_write && !lacc->grp_write)
2750 ret = true;
2751 subtree_mark_written_and_enqueue (lacc);
2753 continue;
2756 rchild->grp_hint = 1;
2757 new_acc = create_artificial_child_access (lacc, rchild, norm_offset,
2758 lacc->grp_write
2759 || rchild->grp_write);
2760 gcc_checking_assert (new_acc);
2761 if (racc->first_child)
2762 propagate_subaccesses_across_link (new_acc, rchild);
2764 add_access_to_work_queue (lacc);
2765 ret = true;
2768 return ret;
2771 /* Propagate all subaccesses across assignment links. */
2773 static void
2774 propagate_all_subaccesses (void)
2776 while (work_queue_head)
2778 struct access *racc = pop_access_from_work_queue ();
2779 struct assign_link *link;
2781 if (racc->group_representative)
2782 racc= racc->group_representative;
2783 gcc_assert (racc->first_link);
2785 for (link = racc->first_link; link; link = link->next)
2787 struct access *lacc = link->lacc;
2789 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
2790 continue;
2791 lacc = lacc->group_representative;
2793 bool reque_parents = false;
2794 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (racc->base)))
2796 if (!lacc->grp_write)
2798 subtree_mark_written_and_enqueue (lacc);
2799 reque_parents = true;
2802 else if (propagate_subaccesses_across_link (lacc, racc))
2803 reque_parents = true;
2805 if (reque_parents)
2808 add_access_to_work_queue (lacc);
2809 lacc = lacc->parent;
2811 while (lacc);
2816 /* Go through all accesses collected throughout the (intraprocedural) analysis
2817 stage, exclude overlapping ones, identify representatives and build trees
2818 out of them, making decisions about scalarization on the way. Return true
2819 iff there are any to-be-scalarized variables after this stage. */
2821 static bool
2822 analyze_all_variable_accesses (void)
2824 int res = 0;
2825 bitmap tmp = BITMAP_ALLOC (NULL);
2826 bitmap_iterator bi;
2827 unsigned i;
2828 bool optimize_speed_p = !optimize_function_for_size_p (cfun);
2830 enum compiler_param param = optimize_speed_p
2831 ? PARAM_SRA_MAX_SCALARIZATION_SIZE_SPEED
2832 : PARAM_SRA_MAX_SCALARIZATION_SIZE_SIZE;
2834 /* If the user didn't set PARAM_SRA_MAX_SCALARIZATION_SIZE_<...>,
2835 fall back to a target default. */
2836 unsigned HOST_WIDE_INT max_scalarization_size
2837 = global_options_set.x_param_values[param]
2838 ? PARAM_VALUE (param)
2839 : get_move_ratio (optimize_speed_p) * UNITS_PER_WORD;
2841 max_scalarization_size *= BITS_PER_UNIT;
2843 EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
2844 if (bitmap_bit_p (should_scalarize_away_bitmap, i)
2845 && !bitmap_bit_p (cannot_scalarize_away_bitmap, i))
2847 tree var = candidate (i);
2849 if (VAR_P (var) && scalarizable_type_p (TREE_TYPE (var),
2850 constant_decl_p (var)))
2852 if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (var)))
2853 <= max_scalarization_size)
2855 create_total_scalarization_access (var);
2856 completely_scalarize (var, TREE_TYPE (var), 0, var);
2857 statistics_counter_event (cfun,
2858 "Totally-scalarized aggregates", 1);
2859 if (dump_file && (dump_flags & TDF_DETAILS))
2861 fprintf (dump_file, "Will attempt to totally scalarize ");
2862 print_generic_expr (dump_file, var);
2863 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
2866 else if (dump_file && (dump_flags & TDF_DETAILS))
2868 fprintf (dump_file, "Too big to totally scalarize: ");
2869 print_generic_expr (dump_file, var);
2870 fprintf (dump_file, " (UID: %u)\n", DECL_UID (var));
2875 bitmap_copy (tmp, candidate_bitmap);
2876 EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
2878 tree var = candidate (i);
2879 struct access *access;
2881 access = sort_and_splice_var_accesses (var);
2882 if (!access || !build_access_trees (access))
2883 disqualify_candidate (var,
2884 "No or inhibitingly overlapping accesses.");
2887 propagate_all_subaccesses ();
2889 bitmap_copy (tmp, candidate_bitmap);
2890 EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
2892 tree var = candidate (i);
2893 struct access *access = get_first_repr_for_decl (var);
2895 if (analyze_access_trees (access))
2897 res++;
2898 if (dump_file && (dump_flags & TDF_DETAILS))
2900 fprintf (dump_file, "\nAccess trees for ");
2901 print_generic_expr (dump_file, var);
2902 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
2903 dump_access_tree (dump_file, access);
2904 fprintf (dump_file, "\n");
2907 else
2908 disqualify_candidate (var, "No scalar replacements to be created.");
2911 BITMAP_FREE (tmp);
2913 if (res)
2915 statistics_counter_event (cfun, "Scalarized aggregates", res);
2916 return true;
2918 else
2919 return false;
2922 /* Generate statements copying scalar replacements of accesses within a subtree
2923 into or out of AGG. ACCESS, all its children, siblings and their children
2924 are to be processed. AGG is an aggregate type expression (can be a
2925 declaration but does not have to be, it can for example also be a mem_ref or
2926 a series of handled components). TOP_OFFSET is the offset of the processed
2927 subtree which has to be subtracted from offsets of individual accesses to
2928 get corresponding offsets for AGG. If CHUNK_SIZE is non-null, copy only
2929 replacements in the interval <start_offset, start_offset + chunk_size>,
2930 otherwise copy all. GSI is a statement iterator used to place the new
2931 statements. WRITE should be true when the statements should write from AGG
2932 to the replacement and false if vice versa. if INSERT_AFTER is true, new
2933 statements will be added after the current statement in GSI, they will be
2934 added before the statement otherwise. */
2936 static void
2937 generate_subtree_copies (struct access *access, tree agg,
2938 HOST_WIDE_INT top_offset,
2939 HOST_WIDE_INT start_offset, HOST_WIDE_INT chunk_size,
2940 gimple_stmt_iterator *gsi, bool write,
2941 bool insert_after, location_t loc)
2943 /* Never write anything into constant pool decls. See PR70602. */
2944 if (!write && constant_decl_p (agg))
2945 return;
2948 if (chunk_size && access->offset >= start_offset + chunk_size)
2949 return;
2951 if (access->grp_to_be_replaced
2952 && (chunk_size == 0
2953 || access->offset + access->size > start_offset))
2955 tree expr, repl = get_access_replacement (access);
2956 gassign *stmt;
2958 expr = build_ref_for_model (loc, agg, access->offset - top_offset,
2959 access, gsi, insert_after);
2961 if (write)
2963 if (access->grp_partial_lhs)
2964 expr = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
2965 !insert_after,
2966 insert_after ? GSI_NEW_STMT
2967 : GSI_SAME_STMT);
2968 stmt = gimple_build_assign (repl, expr);
2970 else
2972 TREE_NO_WARNING (repl) = 1;
2973 if (access->grp_partial_lhs)
2974 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
2975 !insert_after,
2976 insert_after ? GSI_NEW_STMT
2977 : GSI_SAME_STMT);
2978 stmt = gimple_build_assign (expr, repl);
2980 gimple_set_location (stmt, loc);
2982 if (insert_after)
2983 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2984 else
2985 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2986 update_stmt (stmt);
2987 sra_stats.subtree_copies++;
2989 else if (write
2990 && access->grp_to_be_debug_replaced
2991 && (chunk_size == 0
2992 || access->offset + access->size > start_offset))
2994 gdebug *ds;
2995 tree drhs = build_debug_ref_for_model (loc, agg,
2996 access->offset - top_offset,
2997 access);
2998 ds = gimple_build_debug_bind (get_access_replacement (access),
2999 drhs, gsi_stmt (*gsi));
3000 if (insert_after)
3001 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
3002 else
3003 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
3006 if (access->first_child)
3007 generate_subtree_copies (access->first_child, agg, top_offset,
3008 start_offset, chunk_size, gsi,
3009 write, insert_after, loc);
3011 access = access->next_sibling;
3013 while (access);
3016 /* Assign zero to all scalar replacements in an access subtree. ACCESS is the
3017 root of the subtree to be processed. GSI is the statement iterator used
3018 for inserting statements which are added after the current statement if
3019 INSERT_AFTER is true or before it otherwise. */
3021 static void
3022 init_subtree_with_zero (struct access *access, gimple_stmt_iterator *gsi,
3023 bool insert_after, location_t loc)
3026 struct access *child;
3028 if (access->grp_to_be_replaced)
3030 gassign *stmt;
3032 stmt = gimple_build_assign (get_access_replacement (access),
3033 build_zero_cst (access->type));
3034 if (insert_after)
3035 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
3036 else
3037 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3038 update_stmt (stmt);
3039 gimple_set_location (stmt, loc);
3041 else if (access->grp_to_be_debug_replaced)
3043 gdebug *ds
3044 = gimple_build_debug_bind (get_access_replacement (access),
3045 build_zero_cst (access->type),
3046 gsi_stmt (*gsi));
3047 if (insert_after)
3048 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
3049 else
3050 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
3053 for (child = access->first_child; child; child = child->next_sibling)
3054 init_subtree_with_zero (child, gsi, insert_after, loc);
3057 /* Clobber all scalar replacements in an access subtree. ACCESS is the
3058 root of the subtree to be processed. GSI is the statement iterator used
3059 for inserting statements which are added after the current statement if
3060 INSERT_AFTER is true or before it otherwise. */
3062 static void
3063 clobber_subtree (struct access *access, gimple_stmt_iterator *gsi,
3064 bool insert_after, location_t loc)
3067 struct access *child;
3069 if (access->grp_to_be_replaced)
3071 tree rep = get_access_replacement (access);
3072 tree clobber = build_constructor (access->type, NULL);
3073 TREE_THIS_VOLATILE (clobber) = 1;
3074 gimple *stmt = gimple_build_assign (rep, clobber);
3076 if (insert_after)
3077 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
3078 else
3079 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3080 update_stmt (stmt);
3081 gimple_set_location (stmt, loc);
3084 for (child = access->first_child; child; child = child->next_sibling)
3085 clobber_subtree (child, gsi, insert_after, loc);
3088 /* Search for an access representative for the given expression EXPR and
3089 return it or NULL if it cannot be found. */
3091 static struct access *
3092 get_access_for_expr (tree expr)
3094 poly_int64 poffset, psize, pmax_size;
3095 HOST_WIDE_INT offset, max_size;
3096 tree base;
3097 bool reverse;
3099 /* FIXME: This should not be necessary but Ada produces V_C_Es with a type of
3100 a different size than the size of its argument and we need the latter
3101 one. */
3102 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
3103 expr = TREE_OPERAND (expr, 0);
3105 base = get_ref_base_and_extent (expr, &poffset, &psize, &pmax_size,
3106 &reverse);
3107 if (!known_size_p (pmax_size)
3108 || !pmax_size.is_constant (&max_size)
3109 || !poffset.is_constant (&offset)
3110 || !DECL_P (base))
3111 return NULL;
3113 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
3114 return NULL;
3116 return get_var_base_offset_size_access (base, offset, max_size);
3119 /* Replace the expression EXPR with a scalar replacement if there is one and
3120 generate other statements to do type conversion or subtree copying if
3121 necessary. GSI is used to place newly created statements, WRITE is true if
3122 the expression is being written to (it is on a LHS of a statement or output
3123 in an assembly statement). */
3125 static bool
3126 sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
3128 location_t loc;
3129 struct access *access;
3130 tree type, bfr, orig_expr;
3132 if (TREE_CODE (*expr) == BIT_FIELD_REF)
3134 bfr = *expr;
3135 expr = &TREE_OPERAND (*expr, 0);
3137 else
3138 bfr = NULL_TREE;
3140 if (TREE_CODE (*expr) == REALPART_EXPR || TREE_CODE (*expr) == IMAGPART_EXPR)
3141 expr = &TREE_OPERAND (*expr, 0);
3142 access = get_access_for_expr (*expr);
3143 if (!access)
3144 return false;
3145 type = TREE_TYPE (*expr);
3146 orig_expr = *expr;
3148 loc = gimple_location (gsi_stmt (*gsi));
3149 gimple_stmt_iterator alt_gsi = gsi_none ();
3150 if (write && stmt_ends_bb_p (gsi_stmt (*gsi)))
3152 alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi)));
3153 gsi = &alt_gsi;
3156 if (access->grp_to_be_replaced)
3158 tree repl = get_access_replacement (access);
3159 /* If we replace a non-register typed access simply use the original
3160 access expression to extract the scalar component afterwards.
3161 This happens if scalarizing a function return value or parameter
3162 like in gcc.c-torture/execute/20041124-1.c, 20050316-1.c and
3163 gcc.c-torture/compile/20011217-1.c.
3165 We also want to use this when accessing a complex or vector which can
3166 be accessed as a different type too, potentially creating a need for
3167 type conversion (see PR42196) and when scalarized unions are involved
3168 in assembler statements (see PR42398). */
3169 if (!useless_type_conversion_p (type, access->type))
3171 tree ref;
3173 ref = build_ref_for_model (loc, orig_expr, 0, access, gsi, false);
3175 if (write)
3177 gassign *stmt;
3179 if (access->grp_partial_lhs)
3180 ref = force_gimple_operand_gsi (gsi, ref, true, NULL_TREE,
3181 false, GSI_NEW_STMT);
3182 stmt = gimple_build_assign (repl, ref);
3183 gimple_set_location (stmt, loc);
3184 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
3186 else
3188 gassign *stmt;
3190 if (access->grp_partial_lhs)
3191 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
3192 true, GSI_SAME_STMT);
3193 stmt = gimple_build_assign (ref, repl);
3194 gimple_set_location (stmt, loc);
3195 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
3198 else
3199 *expr = repl;
3200 sra_stats.exprs++;
3202 else if (write && access->grp_to_be_debug_replaced)
3204 gdebug *ds = gimple_build_debug_bind (get_access_replacement (access),
3205 NULL_TREE,
3206 gsi_stmt (*gsi));
3207 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
3210 if (access->first_child)
3212 HOST_WIDE_INT start_offset, chunk_size;
3213 if (bfr
3214 && tree_fits_uhwi_p (TREE_OPERAND (bfr, 1))
3215 && tree_fits_uhwi_p (TREE_OPERAND (bfr, 2)))
3217 chunk_size = tree_to_uhwi (TREE_OPERAND (bfr, 1));
3218 start_offset = access->offset
3219 + tree_to_uhwi (TREE_OPERAND (bfr, 2));
3221 else
3222 start_offset = chunk_size = 0;
3224 generate_subtree_copies (access->first_child, orig_expr, access->offset,
3225 start_offset, chunk_size, gsi, write, write,
3226 loc);
3228 return true;
3231 /* Where scalar replacements of the RHS have been written to when a replacement
3232 of a LHS of an assigments cannot be direclty loaded from a replacement of
3233 the RHS. */
3234 enum unscalarized_data_handling { SRA_UDH_NONE, /* Nothing done so far. */
3235 SRA_UDH_RIGHT, /* Data flushed to the RHS. */
3236 SRA_UDH_LEFT }; /* Data flushed to the LHS. */
3238 struct subreplacement_assignment_data
3240 /* Offset of the access representing the lhs of the assignment. */
3241 HOST_WIDE_INT left_offset;
3243 /* LHS and RHS of the original assignment. */
3244 tree assignment_lhs, assignment_rhs;
3246 /* Access representing the rhs of the whole assignment. */
3247 struct access *top_racc;
3249 /* Stmt iterator used for statement insertions after the original assignment.
3250 It points to the main GSI used to traverse a BB during function body
3251 modification. */
3252 gimple_stmt_iterator *new_gsi;
3254 /* Stmt iterator used for statement insertions before the original
3255 assignment. Keeps on pointing to the original statement. */
3256 gimple_stmt_iterator old_gsi;
3258 /* Location of the assignment. */
3259 location_t loc;
3261 /* Keeps the information whether we have needed to refresh replacements of
3262 the LHS and from which side of the assignments this takes place. */
3263 enum unscalarized_data_handling refreshed;
3266 /* Store all replacements in the access tree rooted in TOP_RACC either to their
3267 base aggregate if there are unscalarized data or directly to LHS of the
3268 statement that is pointed to by GSI otherwise. */
3270 static void
3271 handle_unscalarized_data_in_subtree (struct subreplacement_assignment_data *sad)
3273 tree src;
3274 if (sad->top_racc->grp_unscalarized_data)
3276 src = sad->assignment_rhs;
3277 sad->refreshed = SRA_UDH_RIGHT;
3279 else
3281 src = sad->assignment_lhs;
3282 sad->refreshed = SRA_UDH_LEFT;
3284 generate_subtree_copies (sad->top_racc->first_child, src,
3285 sad->top_racc->offset, 0, 0,
3286 &sad->old_gsi, false, false, sad->loc);
3289 /* Try to generate statements to load all sub-replacements in an access subtree
3290 formed by children of LACC from scalar replacements in the SAD->top_racc
3291 subtree. If that is not possible, refresh the SAD->top_racc base aggregate
3292 and load the accesses from it. */
3294 static void
3295 load_assign_lhs_subreplacements (struct access *lacc,
3296 struct subreplacement_assignment_data *sad)
3298 for (lacc = lacc->first_child; lacc; lacc = lacc->next_sibling)
3300 HOST_WIDE_INT offset;
3301 offset = lacc->offset - sad->left_offset + sad->top_racc->offset;
3303 if (lacc->grp_to_be_replaced)
3305 struct access *racc;
3306 gassign *stmt;
3307 tree rhs;
3309 racc = find_access_in_subtree (sad->top_racc, offset, lacc->size);
3310 if (racc && racc->grp_to_be_replaced)
3312 rhs = get_access_replacement (racc);
3313 if (!useless_type_conversion_p (lacc->type, racc->type))
3314 rhs = fold_build1_loc (sad->loc, VIEW_CONVERT_EXPR,
3315 lacc->type, rhs);
3317 if (racc->grp_partial_lhs && lacc->grp_partial_lhs)
3318 rhs = force_gimple_operand_gsi (&sad->old_gsi, rhs, true,
3319 NULL_TREE, true, GSI_SAME_STMT);
3321 else
3323 /* No suitable access on the right hand side, need to load from
3324 the aggregate. See if we have to update it first... */
3325 if (sad->refreshed == SRA_UDH_NONE)
3326 handle_unscalarized_data_in_subtree (sad);
3328 if (sad->refreshed == SRA_UDH_LEFT)
3329 rhs = build_ref_for_model (sad->loc, sad->assignment_lhs,
3330 lacc->offset - sad->left_offset,
3331 lacc, sad->new_gsi, true);
3332 else
3333 rhs = build_ref_for_model (sad->loc, sad->assignment_rhs,
3334 lacc->offset - sad->left_offset,
3335 lacc, sad->new_gsi, true);
3336 if (lacc->grp_partial_lhs)
3337 rhs = force_gimple_operand_gsi (sad->new_gsi,
3338 rhs, true, NULL_TREE,
3339 false, GSI_NEW_STMT);
3342 stmt = gimple_build_assign (get_access_replacement (lacc), rhs);
3343 gsi_insert_after (sad->new_gsi, stmt, GSI_NEW_STMT);
3344 gimple_set_location (stmt, sad->loc);
3345 update_stmt (stmt);
3346 sra_stats.subreplacements++;
3348 else
3350 if (sad->refreshed == SRA_UDH_NONE
3351 && lacc->grp_read && !lacc->grp_covered)
3352 handle_unscalarized_data_in_subtree (sad);
3354 if (lacc && lacc->grp_to_be_debug_replaced)
3356 gdebug *ds;
3357 tree drhs;
3358 struct access *racc = find_access_in_subtree (sad->top_racc,
3359 offset,
3360 lacc->size);
3362 if (racc && racc->grp_to_be_replaced)
3364 if (racc->grp_write || constant_decl_p (racc->base))
3365 drhs = get_access_replacement (racc);
3366 else
3367 drhs = NULL;
3369 else if (sad->refreshed == SRA_UDH_LEFT)
3370 drhs = build_debug_ref_for_model (sad->loc, lacc->base,
3371 lacc->offset, lacc);
3372 else if (sad->refreshed == SRA_UDH_RIGHT)
3373 drhs = build_debug_ref_for_model (sad->loc, sad->top_racc->base,
3374 offset, lacc);
3375 else
3376 drhs = NULL_TREE;
3377 if (drhs
3378 && !useless_type_conversion_p (lacc->type, TREE_TYPE (drhs)))
3379 drhs = fold_build1_loc (sad->loc, VIEW_CONVERT_EXPR,
3380 lacc->type, drhs);
3381 ds = gimple_build_debug_bind (get_access_replacement (lacc),
3382 drhs, gsi_stmt (sad->old_gsi));
3383 gsi_insert_after (sad->new_gsi, ds, GSI_NEW_STMT);
3387 if (lacc->first_child)
3388 load_assign_lhs_subreplacements (lacc, sad);
3392 /* Result code for SRA assignment modification. */
3393 enum assignment_mod_result { SRA_AM_NONE, /* nothing done for the stmt */
3394 SRA_AM_MODIFIED, /* stmt changed but not
3395 removed */
3396 SRA_AM_REMOVED }; /* stmt eliminated */
3398 /* Modify assignments with a CONSTRUCTOR on their RHS. STMT contains a pointer
3399 to the assignment and GSI is the statement iterator pointing at it. Returns
3400 the same values as sra_modify_assign. */
3402 static enum assignment_mod_result
3403 sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
3405 tree lhs = gimple_assign_lhs (stmt);
3406 struct access *acc = get_access_for_expr (lhs);
3407 if (!acc)
3408 return SRA_AM_NONE;
3409 location_t loc = gimple_location (stmt);
3411 if (gimple_clobber_p (stmt))
3413 /* Clobber the replacement variable. */
3414 clobber_subtree (acc, gsi, !acc->grp_covered, loc);
3415 /* Remove clobbers of fully scalarized variables, they are dead. */
3416 if (acc->grp_covered)
3418 unlink_stmt_vdef (stmt);
3419 gsi_remove (gsi, true);
3420 release_defs (stmt);
3421 return SRA_AM_REMOVED;
3423 else
3424 return SRA_AM_MODIFIED;
3427 if (CONSTRUCTOR_NELTS (gimple_assign_rhs1 (stmt)) > 0)
3429 /* I have never seen this code path trigger but if it can happen the
3430 following should handle it gracefully. */
3431 if (access_has_children_p (acc))
3432 generate_subtree_copies (acc->first_child, lhs, acc->offset, 0, 0, gsi,
3433 true, true, loc);
3434 return SRA_AM_MODIFIED;
3437 if (acc->grp_covered)
3439 init_subtree_with_zero (acc, gsi, false, loc);
3440 unlink_stmt_vdef (stmt);
3441 gsi_remove (gsi, true);
3442 release_defs (stmt);
3443 return SRA_AM_REMOVED;
3445 else
3447 init_subtree_with_zero (acc, gsi, true, loc);
3448 return SRA_AM_MODIFIED;
3452 /* Create and return a new suitable default definition SSA_NAME for RACC which
3453 is an access describing an uninitialized part of an aggregate that is being
3454 loaded. */
3456 static tree
3457 get_repl_default_def_ssa_name (struct access *racc)
3459 gcc_checking_assert (!racc->grp_to_be_replaced
3460 && !racc->grp_to_be_debug_replaced);
3461 if (!racc->replacement_decl)
3462 racc->replacement_decl = create_access_replacement (racc);
3463 return get_or_create_ssa_default_def (cfun, racc->replacement_decl);
3466 /* Examine both sides of the assignment statement pointed to by STMT, replace
3467 them with a scalare replacement if there is one and generate copying of
3468 replacements if scalarized aggregates have been used in the assignment. GSI
3469 is used to hold generated statements for type conversions and subtree
3470 copying. */
3472 static enum assignment_mod_result
3473 sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi)
3475 struct access *lacc, *racc;
3476 tree lhs, rhs;
3477 bool modify_this_stmt = false;
3478 bool force_gimple_rhs = false;
3479 location_t loc;
3480 gimple_stmt_iterator orig_gsi = *gsi;
3482 if (!gimple_assign_single_p (stmt))
3483 return SRA_AM_NONE;
3484 lhs = gimple_assign_lhs (stmt);
3485 rhs = gimple_assign_rhs1 (stmt);
3487 if (TREE_CODE (rhs) == CONSTRUCTOR)
3488 return sra_modify_constructor_assign (stmt, gsi);
3490 if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (lhs) == REALPART_EXPR
3491 || TREE_CODE (rhs) == IMAGPART_EXPR || TREE_CODE (lhs) == IMAGPART_EXPR
3492 || TREE_CODE (rhs) == BIT_FIELD_REF || TREE_CODE (lhs) == BIT_FIELD_REF)
3494 modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (stmt),
3495 gsi, false);
3496 modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (stmt),
3497 gsi, true);
3498 return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
3501 lacc = get_access_for_expr (lhs);
3502 racc = get_access_for_expr (rhs);
3503 if (!lacc && !racc)
3504 return SRA_AM_NONE;
3505 /* Avoid modifying initializations of constant-pool replacements. */
3506 if (racc && (racc->replacement_decl == lhs))
3507 return SRA_AM_NONE;
3509 loc = gimple_location (stmt);
3510 if (lacc && lacc->grp_to_be_replaced)
3512 lhs = get_access_replacement (lacc);
3513 gimple_assign_set_lhs (stmt, lhs);
3514 modify_this_stmt = true;
3515 if (lacc->grp_partial_lhs)
3516 force_gimple_rhs = true;
3517 sra_stats.exprs++;
3520 if (racc && racc->grp_to_be_replaced)
3522 rhs = get_access_replacement (racc);
3523 modify_this_stmt = true;
3524 if (racc->grp_partial_lhs)
3525 force_gimple_rhs = true;
3526 sra_stats.exprs++;
3528 else if (racc
3529 && !racc->grp_unscalarized_data
3530 && !racc->grp_unscalarizable_region
3531 && TREE_CODE (lhs) == SSA_NAME
3532 && !access_has_replacements_p (racc))
3534 rhs = get_repl_default_def_ssa_name (racc);
3535 modify_this_stmt = true;
3536 sra_stats.exprs++;
3539 if (modify_this_stmt)
3541 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
3543 /* If we can avoid creating a VIEW_CONVERT_EXPR do so.
3544 ??? This should move to fold_stmt which we simply should
3545 call after building a VIEW_CONVERT_EXPR here. */
3546 if (AGGREGATE_TYPE_P (TREE_TYPE (lhs))
3547 && !contains_bitfld_component_ref_p (lhs))
3549 lhs = build_ref_for_model (loc, lhs, 0, racc, gsi, false);
3550 gimple_assign_set_lhs (stmt, lhs);
3552 else if (AGGREGATE_TYPE_P (TREE_TYPE (rhs))
3553 && !contains_vce_or_bfcref_p (rhs))
3554 rhs = build_ref_for_model (loc, rhs, 0, lacc, gsi, false);
3556 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
3558 rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
3559 rhs);
3560 if (is_gimple_reg_type (TREE_TYPE (lhs))
3561 && TREE_CODE (lhs) != SSA_NAME)
3562 force_gimple_rhs = true;
3567 if (lacc && lacc->grp_to_be_debug_replaced)
3569 tree dlhs = get_access_replacement (lacc);
3570 tree drhs = unshare_expr (rhs);
3571 if (!useless_type_conversion_p (TREE_TYPE (dlhs), TREE_TYPE (drhs)))
3573 if (AGGREGATE_TYPE_P (TREE_TYPE (drhs))
3574 && !contains_vce_or_bfcref_p (drhs))
3575 drhs = build_debug_ref_for_model (loc, drhs, 0, lacc);
3576 if (drhs
3577 && !useless_type_conversion_p (TREE_TYPE (dlhs),
3578 TREE_TYPE (drhs)))
3579 drhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
3580 TREE_TYPE (dlhs), drhs);
3582 gdebug *ds = gimple_build_debug_bind (dlhs, drhs, stmt);
3583 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
3586 /* From this point on, the function deals with assignments in between
3587 aggregates when at least one has scalar reductions of some of its
3588 components. There are three possible scenarios: Both the LHS and RHS have
3589 to-be-scalarized components, 2) only the RHS has or 3) only the LHS has.
3591 In the first case, we would like to load the LHS components from RHS
3592 components whenever possible. If that is not possible, we would like to
3593 read it directly from the RHS (after updating it by storing in it its own
3594 components). If there are some necessary unscalarized data in the LHS,
3595 those will be loaded by the original assignment too. If neither of these
3596 cases happen, the original statement can be removed. Most of this is done
3597 by load_assign_lhs_subreplacements.
3599 In the second case, we would like to store all RHS scalarized components
3600 directly into LHS and if they cover the aggregate completely, remove the
3601 statement too. In the third case, we want the LHS components to be loaded
3602 directly from the RHS (DSE will remove the original statement if it
3603 becomes redundant).
3605 This is a bit complex but manageable when types match and when unions do
3606 not cause confusion in a way that we cannot really load a component of LHS
3607 from the RHS or vice versa (the access representing this level can have
3608 subaccesses that are accessible only through a different union field at a
3609 higher level - different from the one used in the examined expression).
3610 Unions are fun.
3612 Therefore, I specially handle a fourth case, happening when there is a
3613 specific type cast or it is impossible to locate a scalarized subaccess on
3614 the other side of the expression. If that happens, I simply "refresh" the
3615 RHS by storing in it is scalarized components leave the original statement
3616 there to do the copying and then load the scalar replacements of the LHS.
3617 This is what the first branch does. */
3619 if (modify_this_stmt
3620 || gimple_has_volatile_ops (stmt)
3621 || contains_vce_or_bfcref_p (rhs)
3622 || contains_vce_or_bfcref_p (lhs)
3623 || stmt_ends_bb_p (stmt))
3625 /* No need to copy into a constant-pool, it comes pre-initialized. */
3626 if (access_has_children_p (racc) && !constant_decl_p (racc->base))
3627 generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0,
3628 gsi, false, false, loc);
3629 if (access_has_children_p (lacc))
3631 gimple_stmt_iterator alt_gsi = gsi_none ();
3632 if (stmt_ends_bb_p (stmt))
3634 alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi)));
3635 gsi = &alt_gsi;
3637 generate_subtree_copies (lacc->first_child, lhs, lacc->offset, 0, 0,
3638 gsi, true, true, loc);
3640 sra_stats.separate_lhs_rhs_handling++;
3642 /* This gimplification must be done after generate_subtree_copies,
3643 lest we insert the subtree copies in the middle of the gimplified
3644 sequence. */
3645 if (force_gimple_rhs)
3646 rhs = force_gimple_operand_gsi (&orig_gsi, rhs, true, NULL_TREE,
3647 true, GSI_SAME_STMT);
3648 if (gimple_assign_rhs1 (stmt) != rhs)
3650 modify_this_stmt = true;
3651 gimple_assign_set_rhs_from_tree (&orig_gsi, rhs);
3652 gcc_assert (stmt == gsi_stmt (orig_gsi));
3655 return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
3657 else
3659 if (access_has_children_p (lacc)
3660 && access_has_children_p (racc)
3661 /* When an access represents an unscalarizable region, it usually
3662 represents accesses with variable offset and thus must not be used
3663 to generate new memory accesses. */
3664 && !lacc->grp_unscalarizable_region
3665 && !racc->grp_unscalarizable_region)
3667 struct subreplacement_assignment_data sad;
3669 sad.left_offset = lacc->offset;
3670 sad.assignment_lhs = lhs;
3671 sad.assignment_rhs = rhs;
3672 sad.top_racc = racc;
3673 sad.old_gsi = *gsi;
3674 sad.new_gsi = gsi;
3675 sad.loc = gimple_location (stmt);
3676 sad.refreshed = SRA_UDH_NONE;
3678 if (lacc->grp_read && !lacc->grp_covered)
3679 handle_unscalarized_data_in_subtree (&sad);
3681 load_assign_lhs_subreplacements (lacc, &sad);
3682 if (sad.refreshed != SRA_UDH_RIGHT)
3684 gsi_next (gsi);
3685 unlink_stmt_vdef (stmt);
3686 gsi_remove (&sad.old_gsi, true);
3687 release_defs (stmt);
3688 sra_stats.deleted++;
3689 return SRA_AM_REMOVED;
3692 else
3694 if (access_has_children_p (racc)
3695 && !racc->grp_unscalarized_data
3696 && TREE_CODE (lhs) != SSA_NAME)
3698 if (dump_file)
3700 fprintf (dump_file, "Removing load: ");
3701 print_gimple_stmt (dump_file, stmt, 0);
3703 generate_subtree_copies (racc->first_child, lhs,
3704 racc->offset, 0, 0, gsi,
3705 false, false, loc);
3706 gcc_assert (stmt == gsi_stmt (*gsi));
3707 unlink_stmt_vdef (stmt);
3708 gsi_remove (gsi, true);
3709 release_defs (stmt);
3710 sra_stats.deleted++;
3711 return SRA_AM_REMOVED;
3713 /* Restore the aggregate RHS from its components so the
3714 prevailing aggregate copy does the right thing. */
3715 if (access_has_children_p (racc))
3716 generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0,
3717 gsi, false, false, loc);
3718 /* Re-load the components of the aggregate copy destination.
3719 But use the RHS aggregate to load from to expose more
3720 optimization opportunities. */
3721 if (access_has_children_p (lacc))
3722 generate_subtree_copies (lacc->first_child, rhs, lacc->offset,
3723 0, 0, gsi, true, true, loc);
3726 return SRA_AM_NONE;
3730 /* Set any scalar replacements of values in the constant pool to the initial
3731 value of the constant. (Constant-pool decls like *.LC0 have effectively
3732 been initialized before the program starts, we must do the same for their
3733 replacements.) Thus, we output statements like 'SR.1 = *.LC0[0];' into
3734 the function's entry block. */
3736 static void
3737 initialize_constant_pool_replacements (void)
3739 gimple_seq seq = NULL;
3740 gimple_stmt_iterator gsi = gsi_start (seq);
3741 bitmap_iterator bi;
3742 unsigned i;
3744 EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
3746 tree var = candidate (i);
3747 if (!constant_decl_p (var))
3748 continue;
3749 vec<access_p> *access_vec = get_base_access_vector (var);
3750 if (!access_vec)
3751 continue;
3752 for (unsigned i = 0; i < access_vec->length (); i++)
3754 struct access *access = (*access_vec)[i];
3755 if (!access->replacement_decl)
3756 continue;
3757 gassign *stmt
3758 = gimple_build_assign (get_access_replacement (access),
3759 unshare_expr (access->expr));
3760 if (dump_file && (dump_flags & TDF_DETAILS))
3762 fprintf (dump_file, "Generating constant initializer: ");
3763 print_gimple_stmt (dump_file, stmt, 0);
3764 fprintf (dump_file, "\n");
3766 gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
3767 update_stmt (stmt);
3771 seq = gsi_seq (gsi);
3772 if (seq)
3773 gsi_insert_seq_on_edge_immediate (
3774 single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
3777 /* Traverse the function body and all modifications as decided in
3778 analyze_all_variable_accesses. Return true iff the CFG has been
3779 changed. */
3781 static bool
3782 sra_modify_function_body (void)
3784 bool cfg_changed = false;
3785 basic_block bb;
3787 initialize_constant_pool_replacements ();
3789 FOR_EACH_BB_FN (bb, cfun)
3791 gimple_stmt_iterator gsi = gsi_start_bb (bb);
3792 while (!gsi_end_p (gsi))
3794 gimple *stmt = gsi_stmt (gsi);
3795 enum assignment_mod_result assign_result;
3796 bool modified = false, deleted = false;
3797 tree *t;
3798 unsigned i;
3800 switch (gimple_code (stmt))
3802 case GIMPLE_RETURN:
3803 t = gimple_return_retval_ptr (as_a <greturn *> (stmt));
3804 if (*t != NULL_TREE)
3805 modified |= sra_modify_expr (t, &gsi, false);
3806 break;
3808 case GIMPLE_ASSIGN:
3809 assign_result = sra_modify_assign (stmt, &gsi);
3810 modified |= assign_result == SRA_AM_MODIFIED;
3811 deleted = assign_result == SRA_AM_REMOVED;
3812 break;
3814 case GIMPLE_CALL:
3815 /* Operands must be processed before the lhs. */
3816 for (i = 0; i < gimple_call_num_args (stmt); i++)
3818 t = gimple_call_arg_ptr (stmt, i);
3819 modified |= sra_modify_expr (t, &gsi, false);
3822 if (gimple_call_lhs (stmt))
3824 t = gimple_call_lhs_ptr (stmt);
3825 modified |= sra_modify_expr (t, &gsi, true);
3827 break;
3829 case GIMPLE_ASM:
3831 gasm *asm_stmt = as_a <gasm *> (stmt);
3832 for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
3834 t = &TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
3835 modified |= sra_modify_expr (t, &gsi, false);
3837 for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
3839 t = &TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
3840 modified |= sra_modify_expr (t, &gsi, true);
3843 break;
3845 default:
3846 break;
3849 if (modified)
3851 update_stmt (stmt);
3852 if (maybe_clean_eh_stmt (stmt)
3853 && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
3854 cfg_changed = true;
3856 if (!deleted)
3857 gsi_next (&gsi);
3861 gsi_commit_edge_inserts ();
3862 return cfg_changed;
3865 /* Generate statements initializing scalar replacements of parts of function
3866 parameters. */
3868 static void
3869 initialize_parameter_reductions (void)
3871 gimple_stmt_iterator gsi;
3872 gimple_seq seq = NULL;
3873 tree parm;
3875 gsi = gsi_start (seq);
3876 for (parm = DECL_ARGUMENTS (current_function_decl);
3877 parm;
3878 parm = DECL_CHAIN (parm))
3880 vec<access_p> *access_vec;
3881 struct access *access;
3883 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
3884 continue;
3885 access_vec = get_base_access_vector (parm);
3886 if (!access_vec)
3887 continue;
3889 for (access = (*access_vec)[0];
3890 access;
3891 access = access->next_grp)
3892 generate_subtree_copies (access, parm, 0, 0, 0, &gsi, true, true,
3893 EXPR_LOCATION (parm));
3896 seq = gsi_seq (gsi);
3897 if (seq)
3898 gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
3901 /* The "main" function of intraprocedural SRA passes. Runs the analysis and if
3902 it reveals there are components of some aggregates to be scalarized, it runs
3903 the required transformations. */
3904 static unsigned int
3905 perform_intra_sra (void)
3907 int ret = 0;
3908 sra_initialize ();
3910 if (!find_var_candidates ())
3911 goto out;
3913 if (!scan_function ())
3914 goto out;
3916 if (!analyze_all_variable_accesses ())
3917 goto out;
3919 if (sra_modify_function_body ())
3920 ret = TODO_update_ssa | TODO_cleanup_cfg;
3921 else
3922 ret = TODO_update_ssa;
3923 initialize_parameter_reductions ();
3925 statistics_counter_event (cfun, "Scalar replacements created",
3926 sra_stats.replacements);
3927 statistics_counter_event (cfun, "Modified expressions", sra_stats.exprs);
3928 statistics_counter_event (cfun, "Subtree copy stmts",
3929 sra_stats.subtree_copies);
3930 statistics_counter_event (cfun, "Subreplacement stmts",
3931 sra_stats.subreplacements);
3932 statistics_counter_event (cfun, "Deleted stmts", sra_stats.deleted);
3933 statistics_counter_event (cfun, "Separate LHS and RHS handling",
3934 sra_stats.separate_lhs_rhs_handling);
3936 out:
3937 sra_deinitialize ();
3938 return ret;
3941 /* Perform early intraprocedural SRA. */
3942 static unsigned int
3943 early_intra_sra (void)
3945 sra_mode = SRA_MODE_EARLY_INTRA;
3946 return perform_intra_sra ();
3949 /* Perform "late" intraprocedural SRA. */
3950 static unsigned int
3951 late_intra_sra (void)
3953 sra_mode = SRA_MODE_INTRA;
3954 return perform_intra_sra ();
3958 static bool
3959 gate_intra_sra (void)
3961 return flag_tree_sra != 0 && dbg_cnt (tree_sra);
3965 namespace {
3967 const pass_data pass_data_sra_early =
3969 GIMPLE_PASS, /* type */
3970 "esra", /* name */
3971 OPTGROUP_NONE, /* optinfo_flags */
3972 TV_TREE_SRA, /* tv_id */
3973 ( PROP_cfg | PROP_ssa ), /* properties_required */
3974 0, /* properties_provided */
3975 0, /* properties_destroyed */
3976 0, /* todo_flags_start */
3977 TODO_update_ssa, /* todo_flags_finish */
3980 class pass_sra_early : public gimple_opt_pass
3982 public:
3983 pass_sra_early (gcc::context *ctxt)
3984 : gimple_opt_pass (pass_data_sra_early, ctxt)
3987 /* opt_pass methods: */
3988 virtual bool gate (function *) { return gate_intra_sra (); }
3989 virtual unsigned int execute (function *) { return early_intra_sra (); }
3991 }; // class pass_sra_early
3993 } // anon namespace
3995 gimple_opt_pass *
3996 make_pass_sra_early (gcc::context *ctxt)
3998 return new pass_sra_early (ctxt);
4001 namespace {
4003 const pass_data pass_data_sra =
4005 GIMPLE_PASS, /* type */
4006 "sra", /* name */
4007 OPTGROUP_NONE, /* optinfo_flags */
4008 TV_TREE_SRA, /* tv_id */
4009 ( PROP_cfg | PROP_ssa ), /* properties_required */
4010 0, /* properties_provided */
4011 0, /* properties_destroyed */
4012 TODO_update_address_taken, /* todo_flags_start */
4013 TODO_update_ssa, /* todo_flags_finish */
4016 class pass_sra : public gimple_opt_pass
4018 public:
4019 pass_sra (gcc::context *ctxt)
4020 : gimple_opt_pass (pass_data_sra, ctxt)
4023 /* opt_pass methods: */
4024 virtual bool gate (function *) { return gate_intra_sra (); }
4025 virtual unsigned int execute (function *) { return late_intra_sra (); }
4027 }; // class pass_sra
4029 } // anon namespace
4031 gimple_opt_pass *
4032 make_pass_sra (gcc::context *ctxt)
4034 return new pass_sra (ctxt);
4038 /* Return true iff PARM (which must be a parm_decl) is an unused scalar
4039 parameter. */
4041 static bool
4042 is_unused_scalar_param (tree parm)
4044 tree name;
4045 return (is_gimple_reg (parm)
4046 && (!(name = ssa_default_def (cfun, parm))
4047 || has_zero_uses (name)));
4050 /* Scan immediate uses of a default definition SSA name of a parameter PARM and
4051 examine whether there are any direct or otherwise infeasible ones. If so,
4052 return true, otherwise return false. PARM must be a gimple register with a
4053 non-NULL default definition. */
4055 static bool
4056 ptr_parm_has_direct_uses (tree parm)
4058 imm_use_iterator ui;
4059 gimple *stmt;
4060 tree name = ssa_default_def (cfun, parm);
4061 bool ret = false;
4063 FOR_EACH_IMM_USE_STMT (stmt, ui, name)
4065 int uses_ok = 0;
4066 use_operand_p use_p;
4068 if (is_gimple_debug (stmt))
4069 continue;
4071 /* Valid uses include dereferences on the lhs and the rhs. */
4072 if (gimple_has_lhs (stmt))
4074 tree lhs = gimple_get_lhs (stmt);
4075 while (handled_component_p (lhs))
4076 lhs = TREE_OPERAND (lhs, 0);
4077 if (TREE_CODE (lhs) == MEM_REF
4078 && TREE_OPERAND (lhs, 0) == name
4079 && integer_zerop (TREE_OPERAND (lhs, 1))
4080 && types_compatible_p (TREE_TYPE (lhs),
4081 TREE_TYPE (TREE_TYPE (name)))
4082 && !TREE_THIS_VOLATILE (lhs))
4083 uses_ok++;
4085 if (gimple_assign_single_p (stmt))
4087 tree rhs = gimple_assign_rhs1 (stmt);
4088 while (handled_component_p (rhs))
4089 rhs = TREE_OPERAND (rhs, 0);
4090 if (TREE_CODE (rhs) == MEM_REF
4091 && TREE_OPERAND (rhs, 0) == name
4092 && integer_zerop (TREE_OPERAND (rhs, 1))
4093 && types_compatible_p (TREE_TYPE (rhs),
4094 TREE_TYPE (TREE_TYPE (name)))
4095 && !TREE_THIS_VOLATILE (rhs))
4096 uses_ok++;
4098 else if (is_gimple_call (stmt))
4100 unsigned i;
4101 for (i = 0; i < gimple_call_num_args (stmt); ++i)
4103 tree arg = gimple_call_arg (stmt, i);
4104 while (handled_component_p (arg))
4105 arg = TREE_OPERAND (arg, 0);
4106 if (TREE_CODE (arg) == MEM_REF
4107 && TREE_OPERAND (arg, 0) == name
4108 && integer_zerop (TREE_OPERAND (arg, 1))
4109 && types_compatible_p (TREE_TYPE (arg),
4110 TREE_TYPE (TREE_TYPE (name)))
4111 && !TREE_THIS_VOLATILE (arg))
4112 uses_ok++;
4116 /* If the number of valid uses does not match the number of
4117 uses in this stmt there is an unhandled use. */
4118 FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
4119 --uses_ok;
4121 if (uses_ok != 0)
4122 ret = true;
4124 if (ret)
4125 BREAK_FROM_IMM_USE_STMT (ui);
4128 return ret;
4131 /* Identify candidates for reduction for IPA-SRA based on their type and mark
4132 them in candidate_bitmap. Note that these do not necessarily include
4133 parameter which are unused and thus can be removed. Return true iff any
4134 such candidate has been found. */
4136 static bool
4137 find_param_candidates (void)
4139 tree parm;
4140 int count = 0;
4141 bool ret = false;
4142 const char *msg;
4144 for (parm = DECL_ARGUMENTS (current_function_decl);
4145 parm;
4146 parm = DECL_CHAIN (parm))
4148 tree type = TREE_TYPE (parm);
4149 tree_node **slot;
4151 count++;
4153 if (TREE_THIS_VOLATILE (parm)
4154 || TREE_ADDRESSABLE (parm)
4155 || (!is_gimple_reg_type (type) && is_va_list_type (type)))
4156 continue;
4158 if (is_unused_scalar_param (parm))
4160 ret = true;
4161 continue;
4164 if (POINTER_TYPE_P (type))
4166 type = TREE_TYPE (type);
4168 if (TREE_CODE (type) == FUNCTION_TYPE
4169 || TYPE_VOLATILE (type)
4170 || (TREE_CODE (type) == ARRAY_TYPE
4171 && TYPE_NONALIASED_COMPONENT (type))
4172 || !is_gimple_reg (parm)
4173 || is_va_list_type (type)
4174 || ptr_parm_has_direct_uses (parm))
4175 continue;
4177 else if (!AGGREGATE_TYPE_P (type))
4178 continue;
4180 if (!COMPLETE_TYPE_P (type)
4181 || !tree_fits_uhwi_p (TYPE_SIZE (type))
4182 || tree_to_uhwi (TYPE_SIZE (type)) == 0
4183 || (AGGREGATE_TYPE_P (type)
4184 && type_internals_preclude_sra_p (type, &msg)))
4185 continue;
4187 bitmap_set_bit (candidate_bitmap, DECL_UID (parm));
4188 slot = candidates->find_slot_with_hash (parm, DECL_UID (parm), INSERT);
4189 *slot = parm;
4191 ret = true;
4192 if (dump_file && (dump_flags & TDF_DETAILS))
4194 fprintf (dump_file, "Candidate (%d): ", DECL_UID (parm));
4195 print_generic_expr (dump_file, parm);
4196 fprintf (dump_file, "\n");
4200 func_param_count = count;
4201 return ret;
4204 /* Callback of walk_aliased_vdefs, marks the access passed as DATA as
4205 maybe_modified. */
4207 static bool
4208 mark_maybe_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
4209 void *data)
4211 struct access *repr = (struct access *) data;
4213 repr->grp_maybe_modified = 1;
4214 return true;
4217 /* Analyze what representatives (in linked lists accessible from
4218 REPRESENTATIVES) can be modified by side effects of statements in the
4219 current function. */
4221 static void
4222 analyze_modified_params (vec<access_p> representatives)
4224 int i;
4226 for (i = 0; i < func_param_count; i++)
4228 struct access *repr;
4230 for (repr = representatives[i];
4231 repr;
4232 repr = repr->next_grp)
4234 struct access *access;
4235 bitmap visited;
4236 ao_ref ar;
4238 if (no_accesses_p (repr))
4239 continue;
4240 if (!POINTER_TYPE_P (TREE_TYPE (repr->base))
4241 || repr->grp_maybe_modified)
4242 continue;
4244 ao_ref_init (&ar, repr->expr);
4245 visited = BITMAP_ALLOC (NULL);
4246 for (access = repr; access; access = access->next_sibling)
4248 /* All accesses are read ones, otherwise grp_maybe_modified would
4249 be trivially set. */
4250 walk_aliased_vdefs (&ar, gimple_vuse (access->stmt),
4251 mark_maybe_modified, repr, &visited);
4252 if (repr->grp_maybe_modified)
4253 break;
4255 BITMAP_FREE (visited);
4260 /* Propagate distances in bb_dereferences in the opposite direction than the
4261 control flow edges, in each step storing the maximum of the current value
4262 and the minimum of all successors. These steps are repeated until the table
4263 stabilizes. Note that BBs which might terminate the functions (according to
4264 final_bbs bitmap) never updated in this way. */
4266 static void
4267 propagate_dereference_distances (void)
4269 basic_block bb;
4271 auto_vec<basic_block> queue (last_basic_block_for_fn (cfun));
4272 queue.quick_push (ENTRY_BLOCK_PTR_FOR_FN (cfun));
4273 FOR_EACH_BB_FN (bb, cfun)
4275 queue.quick_push (bb);
4276 bb->aux = bb;
4279 while (!queue.is_empty ())
4281 edge_iterator ei;
4282 edge e;
4283 bool change = false;
4284 int i;
4286 bb = queue.pop ();
4287 bb->aux = NULL;
4289 if (bitmap_bit_p (final_bbs, bb->index))
4290 continue;
4292 for (i = 0; i < func_param_count; i++)
4294 int idx = bb->index * func_param_count + i;
4295 bool first = true;
4296 HOST_WIDE_INT inh = 0;
4298 FOR_EACH_EDGE (e, ei, bb->succs)
4300 int succ_idx = e->dest->index * func_param_count + i;
4302 if (e->src == EXIT_BLOCK_PTR_FOR_FN (cfun))
4303 continue;
4305 if (first)
4307 first = false;
4308 inh = bb_dereferences [succ_idx];
4310 else if (bb_dereferences [succ_idx] < inh)
4311 inh = bb_dereferences [succ_idx];
4314 if (!first && bb_dereferences[idx] < inh)
4316 bb_dereferences[idx] = inh;
4317 change = true;
4321 if (change && !bitmap_bit_p (final_bbs, bb->index))
4322 FOR_EACH_EDGE (e, ei, bb->preds)
4324 if (e->src->aux)
4325 continue;
4327 e->src->aux = e->src;
4328 queue.quick_push (e->src);
4333 /* Dump a dereferences TABLE with heading STR to file F. */
4335 static void
4336 dump_dereferences_table (FILE *f, const char *str, HOST_WIDE_INT *table)
4338 basic_block bb;
4340 fprintf (dump_file, "%s", str);
4341 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun),
4342 EXIT_BLOCK_PTR_FOR_FN (cfun), next_bb)
4344 fprintf (f, "%4i %i ", bb->index, bitmap_bit_p (final_bbs, bb->index));
4345 if (bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
4347 int i;
4348 for (i = 0; i < func_param_count; i++)
4350 int idx = bb->index * func_param_count + i;
4351 fprintf (f, " %4" HOST_WIDE_INT_PRINT "d", table[idx]);
4354 fprintf (f, "\n");
4356 fprintf (dump_file, "\n");
4359 /* Determine what (parts of) parameters passed by reference that are not
4360 assigned to are not certainly dereferenced in this function and thus the
4361 dereferencing cannot be safely moved to the caller without potentially
4362 introducing a segfault. Mark such REPRESENTATIVES as
4363 grp_not_necessarilly_dereferenced.
4365 The dereferenced maximum "distance," i.e. the offset + size of the accessed
4366 part is calculated rather than simple booleans are calculated for each
4367 pointer parameter to handle cases when only a fraction of the whole
4368 aggregate is allocated (see testsuite/gcc.c-torture/execute/ipa-sra-2.c for
4369 an example).
4371 The maximum dereference distances for each pointer parameter and BB are
4372 already stored in bb_dereference. This routine simply propagates these
4373 values upwards by propagate_dereference_distances and then compares the
4374 distances of individual parameters in the ENTRY BB to the equivalent
4375 distances of each representative of a (fraction of a) parameter. */
4377 static void
4378 analyze_caller_dereference_legality (vec<access_p> representatives)
4380 int i;
4382 if (dump_file && (dump_flags & TDF_DETAILS))
4383 dump_dereferences_table (dump_file,
4384 "Dereference table before propagation:\n",
4385 bb_dereferences);
4387 propagate_dereference_distances ();
4389 if (dump_file && (dump_flags & TDF_DETAILS))
4390 dump_dereferences_table (dump_file,
4391 "Dereference table after propagation:\n",
4392 bb_dereferences);
4394 for (i = 0; i < func_param_count; i++)
4396 struct access *repr = representatives[i];
4397 int idx = ENTRY_BLOCK_PTR_FOR_FN (cfun)->index * func_param_count + i;
4399 if (!repr || no_accesses_p (repr))
4400 continue;
4404 if ((repr->offset + repr->size) > bb_dereferences[idx])
4405 repr->grp_not_necessarilly_dereferenced = 1;
4406 repr = repr->next_grp;
4408 while (repr);
4412 /* Return the representative access for the parameter declaration PARM if it is
4413 a scalar passed by reference which is not written to and the pointer value
4414 is not used directly. Thus, if it is legal to dereference it in the caller
4415 and we can rule out modifications through aliases, such parameter should be
4416 turned into one passed by value. Return NULL otherwise. */
4418 static struct access *
4419 unmodified_by_ref_scalar_representative (tree parm)
4421 int i, access_count;
4422 struct access *repr;
4423 vec<access_p> *access_vec;
4425 access_vec = get_base_access_vector (parm);
4426 gcc_assert (access_vec);
4427 repr = (*access_vec)[0];
4428 if (repr->write)
4429 return NULL;
4430 repr->group_representative = repr;
4432 access_count = access_vec->length ();
4433 for (i = 1; i < access_count; i++)
4435 struct access *access = (*access_vec)[i];
4436 if (access->write)
4437 return NULL;
4438 access->group_representative = repr;
4439 access->next_sibling = repr->next_sibling;
4440 repr->next_sibling = access;
4443 repr->grp_read = 1;
4444 repr->grp_scalar_ptr = 1;
4445 return repr;
4448 /* Return true iff this ACCESS precludes IPA-SRA of the parameter it is
4449 associated with. REQ_ALIGN is the minimum required alignment. */
4451 static bool
4452 access_precludes_ipa_sra_p (struct access *access, unsigned int req_align)
4454 unsigned int exp_align;
4455 /* Avoid issues such as the second simple testcase in PR 42025. The problem
4456 is incompatible assign in a call statement (and possibly even in asm
4457 statements). This can be relaxed by using a new temporary but only for
4458 non-TREE_ADDRESSABLE types and is probably not worth the complexity. (In
4459 intraprocedural SRA we deal with this by keeping the old aggregate around,
4460 something we cannot do in IPA-SRA.) */
4461 if (access->write
4462 && (is_gimple_call (access->stmt)
4463 || gimple_code (access->stmt) == GIMPLE_ASM))
4464 return true;
4466 exp_align = get_object_alignment (access->expr);
4467 if (exp_align < req_align)
4468 return true;
4470 return false;
4474 /* Sort collected accesses for parameter PARM, identify representatives for
4475 each accessed region and link them together. Return NULL if there are
4476 different but overlapping accesses, return the special ptr value meaning
4477 there are no accesses for this parameter if that is the case and return the
4478 first representative otherwise. Set *RO_GRP if there is a group of accesses
4479 with only read (i.e. no write) accesses. */
4481 static struct access *
4482 splice_param_accesses (tree parm, bool *ro_grp)
4484 int i, j, access_count, group_count;
4485 int total_size = 0;
4486 struct access *access, *res, **prev_acc_ptr = &res;
4487 vec<access_p> *access_vec;
4489 access_vec = get_base_access_vector (parm);
4490 if (!access_vec)
4491 return &no_accesses_representant;
4492 access_count = access_vec->length ();
4494 access_vec->qsort (compare_access_positions);
4496 i = 0;
4497 total_size = 0;
4498 group_count = 0;
4499 while (i < access_count)
4501 bool modification;
4502 tree a1_alias_type;
4503 access = (*access_vec)[i];
4504 modification = access->write;
4505 if (access_precludes_ipa_sra_p (access, TYPE_ALIGN (access->type)))
4506 return NULL;
4507 a1_alias_type = reference_alias_ptr_type (access->expr);
4509 /* Access is about to become group representative unless we find some
4510 nasty overlap which would preclude us from breaking this parameter
4511 apart. */
4513 j = i + 1;
4514 while (j < access_count)
4516 struct access *ac2 = (*access_vec)[j];
4517 if (ac2->offset != access->offset)
4519 /* All or nothing law for parameters. */
4520 if (access->offset + access->size > ac2->offset)
4521 return NULL;
4522 else
4523 break;
4525 else if (ac2->size != access->size)
4526 return NULL;
4528 if (access_precludes_ipa_sra_p (ac2, TYPE_ALIGN (access->type))
4529 || (ac2->type != access->type
4530 && (TREE_ADDRESSABLE (ac2->type)
4531 || TREE_ADDRESSABLE (access->type)))
4532 || (reference_alias_ptr_type (ac2->expr) != a1_alias_type))
4533 return NULL;
4535 modification |= ac2->write;
4536 ac2->group_representative = access;
4537 ac2->next_sibling = access->next_sibling;
4538 access->next_sibling = ac2;
4539 j++;
4542 group_count++;
4543 access->grp_maybe_modified = modification;
4544 if (!modification)
4545 *ro_grp = true;
4546 *prev_acc_ptr = access;
4547 prev_acc_ptr = &access->next_grp;
4548 total_size += access->size;
4549 i = j;
4552 gcc_assert (group_count > 0);
4553 return res;
4556 /* Decide whether parameters with representative accesses given by REPR should
4557 be reduced into components. */
4559 static int
4560 decide_one_param_reduction (struct access *repr)
4562 HOST_WIDE_INT total_size, cur_parm_size;
4563 bool by_ref;
4564 tree parm;
4566 parm = repr->base;
4567 cur_parm_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (parm)));
4568 gcc_assert (cur_parm_size > 0);
4570 if (POINTER_TYPE_P (TREE_TYPE (parm)))
4571 by_ref = true;
4572 else
4573 by_ref = false;
4575 if (dump_file)
4577 struct access *acc;
4578 fprintf (dump_file, "Evaluating PARAM group sizes for ");
4579 print_generic_expr (dump_file, parm);
4580 fprintf (dump_file, " (UID: %u): \n", DECL_UID (parm));
4581 for (acc = repr; acc; acc = acc->next_grp)
4582 dump_access (dump_file, acc, true);
4585 total_size = 0;
4586 int new_param_count = 0;
4588 for (; repr; repr = repr->next_grp)
4590 gcc_assert (parm == repr->base);
4592 /* Taking the address of a non-addressable field is verboten. */
4593 if (by_ref && repr->non_addressable)
4594 return 0;
4596 /* Do not decompose a non-BLKmode param in a way that would
4597 create BLKmode params. Especially for by-reference passing
4598 (thus, pointer-type param) this is hardly worthwhile. */
4599 if (DECL_MODE (parm) != BLKmode
4600 && TYPE_MODE (repr->type) == BLKmode)
4601 return 0;
4603 if (!by_ref || (!repr->grp_maybe_modified
4604 && !repr->grp_not_necessarilly_dereferenced))
4605 total_size += repr->size;
4606 else
4607 total_size += cur_parm_size;
4609 new_param_count++;
4612 gcc_assert (new_param_count > 0);
4614 if (!by_ref)
4616 if (total_size >= cur_parm_size)
4617 return 0;
4619 else
4621 int parm_num_limit;
4622 if (optimize_function_for_size_p (cfun))
4623 parm_num_limit = 1;
4624 else
4625 parm_num_limit = PARAM_VALUE (PARAM_IPA_SRA_PTR_GROWTH_FACTOR);
4627 if (new_param_count > parm_num_limit
4628 || total_size > (parm_num_limit * cur_parm_size))
4629 return 0;
4632 if (dump_file)
4633 fprintf (dump_file, " ....will be split into %i components\n",
4634 new_param_count);
4635 return new_param_count;
4638 /* The order of the following enums is important, we need to do extra work for
4639 UNUSED_PARAMS, BY_VAL_ACCESSES and UNMODIF_BY_REF_ACCESSES. */
4640 enum ipa_splicing_result { NO_GOOD_ACCESS, UNUSED_PARAMS, BY_VAL_ACCESSES,
4641 MODIF_BY_REF_ACCESSES, UNMODIF_BY_REF_ACCESSES };
4643 /* Identify representatives of all accesses to all candidate parameters for
4644 IPA-SRA. Return result based on what representatives have been found. */
4646 static enum ipa_splicing_result
4647 splice_all_param_accesses (vec<access_p> &representatives)
4649 enum ipa_splicing_result result = NO_GOOD_ACCESS;
4650 tree parm;
4651 struct access *repr;
4653 representatives.create (func_param_count);
4655 for (parm = DECL_ARGUMENTS (current_function_decl);
4656 parm;
4657 parm = DECL_CHAIN (parm))
4659 if (is_unused_scalar_param (parm))
4661 representatives.quick_push (&no_accesses_representant);
4662 if (result == NO_GOOD_ACCESS)
4663 result = UNUSED_PARAMS;
4665 else if (POINTER_TYPE_P (TREE_TYPE (parm))
4666 && is_gimple_reg_type (TREE_TYPE (TREE_TYPE (parm)))
4667 && bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
4669 repr = unmodified_by_ref_scalar_representative (parm);
4670 representatives.quick_push (repr);
4671 if (repr)
4672 result = UNMODIF_BY_REF_ACCESSES;
4674 else if (bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
4676 bool ro_grp = false;
4677 repr = splice_param_accesses (parm, &ro_grp);
4678 representatives.quick_push (repr);
4680 if (repr && !no_accesses_p (repr))
4682 if (POINTER_TYPE_P (TREE_TYPE (parm)))
4684 if (ro_grp)
4685 result = UNMODIF_BY_REF_ACCESSES;
4686 else if (result < MODIF_BY_REF_ACCESSES)
4687 result = MODIF_BY_REF_ACCESSES;
4689 else if (result < BY_VAL_ACCESSES)
4690 result = BY_VAL_ACCESSES;
4692 else if (no_accesses_p (repr) && (result == NO_GOOD_ACCESS))
4693 result = UNUSED_PARAMS;
4695 else
4696 representatives.quick_push (NULL);
4699 if (result == NO_GOOD_ACCESS)
4701 representatives.release ();
4702 return NO_GOOD_ACCESS;
4705 return result;
4708 /* Return the index of BASE in PARMS. Abort if it is not found. */
4710 static inline int
4711 get_param_index (tree base, vec<tree> parms)
4713 int i, len;
4715 len = parms.length ();
4716 for (i = 0; i < len; i++)
4717 if (parms[i] == base)
4718 return i;
4719 gcc_unreachable ();
4722 /* Convert the decisions made at the representative level into compact
4723 parameter adjustments. REPRESENTATIVES are pointers to first
4724 representatives of each param accesses, ADJUSTMENTS_COUNT is the expected
4725 final number of adjustments. */
4727 static ipa_parm_adjustment_vec
4728 turn_representatives_into_adjustments (vec<access_p> representatives,
4729 int adjustments_count)
4731 vec<tree> parms;
4732 ipa_parm_adjustment_vec adjustments;
4733 tree parm;
4734 int i;
4736 gcc_assert (adjustments_count > 0);
4737 parms = ipa_get_vector_of_formal_parms (current_function_decl);
4738 adjustments.create (adjustments_count);
4739 parm = DECL_ARGUMENTS (current_function_decl);
4740 for (i = 0; i < func_param_count; i++, parm = DECL_CHAIN (parm))
4742 struct access *repr = representatives[i];
4744 if (!repr || no_accesses_p (repr))
4746 struct ipa_parm_adjustment adj;
4748 memset (&adj, 0, sizeof (adj));
4749 adj.base_index = get_param_index (parm, parms);
4750 adj.base = parm;
4751 if (!repr)
4752 adj.op = IPA_PARM_OP_COPY;
4753 else
4754 adj.op = IPA_PARM_OP_REMOVE;
4755 adj.arg_prefix = "ISRA";
4756 adjustments.quick_push (adj);
4758 else
4760 struct ipa_parm_adjustment adj;
4761 int index = get_param_index (parm, parms);
4763 for (; repr; repr = repr->next_grp)
4765 memset (&adj, 0, sizeof (adj));
4766 gcc_assert (repr->base == parm);
4767 adj.base_index = index;
4768 adj.base = repr->base;
4769 adj.type = repr->type;
4770 adj.alias_ptr_type = reference_alias_ptr_type (repr->expr);
4771 adj.offset = repr->offset;
4772 adj.reverse = repr->reverse;
4773 adj.by_ref = (POINTER_TYPE_P (TREE_TYPE (repr->base))
4774 && (repr->grp_maybe_modified
4775 || repr->grp_not_necessarilly_dereferenced));
4776 adj.arg_prefix = "ISRA";
4777 adjustments.quick_push (adj);
4781 parms.release ();
4782 return adjustments;
4785 /* Analyze the collected accesses and produce a plan what to do with the
4786 parameters in the form of adjustments, NULL meaning nothing. */
4788 static ipa_parm_adjustment_vec
4789 analyze_all_param_acesses (void)
4791 enum ipa_splicing_result repr_state;
4792 bool proceed = false;
4793 int i, adjustments_count = 0;
4794 vec<access_p> representatives;
4795 ipa_parm_adjustment_vec adjustments;
4797 repr_state = splice_all_param_accesses (representatives);
4798 if (repr_state == NO_GOOD_ACCESS)
4799 return ipa_parm_adjustment_vec ();
4801 /* If there are any parameters passed by reference which are not modified
4802 directly, we need to check whether they can be modified indirectly. */
4803 if (repr_state == UNMODIF_BY_REF_ACCESSES)
4805 analyze_caller_dereference_legality (representatives);
4806 analyze_modified_params (representatives);
4809 for (i = 0; i < func_param_count; i++)
4811 struct access *repr = representatives[i];
4813 if (repr && !no_accesses_p (repr))
4815 if (repr->grp_scalar_ptr)
4817 adjustments_count++;
4818 if (repr->grp_not_necessarilly_dereferenced
4819 || repr->grp_maybe_modified)
4820 representatives[i] = NULL;
4821 else
4823 proceed = true;
4824 sra_stats.scalar_by_ref_to_by_val++;
4827 else
4829 int new_components = decide_one_param_reduction (repr);
4831 if (new_components == 0)
4833 representatives[i] = NULL;
4834 adjustments_count++;
4836 else
4838 adjustments_count += new_components;
4839 sra_stats.aggregate_params_reduced++;
4840 sra_stats.param_reductions_created += new_components;
4841 proceed = true;
4845 else
4847 if (no_accesses_p (repr))
4849 proceed = true;
4850 sra_stats.deleted_unused_parameters++;
4852 adjustments_count++;
4856 if (!proceed && dump_file)
4857 fprintf (dump_file, "NOT proceeding to change params.\n");
4859 if (proceed)
4860 adjustments = turn_representatives_into_adjustments (representatives,
4861 adjustments_count);
4862 else
4863 adjustments = ipa_parm_adjustment_vec ();
4865 representatives.release ();
4866 return adjustments;
4869 /* If a parameter replacement identified by ADJ does not yet exist in the form
4870 of declaration, create it and record it, otherwise return the previously
4871 created one. */
4873 static tree
4874 get_replaced_param_substitute (struct ipa_parm_adjustment *adj)
4876 tree repl;
4877 if (!adj->new_ssa_base)
4879 char *pretty_name = make_fancy_name (adj->base);
4881 repl = create_tmp_reg (TREE_TYPE (adj->base), "ISR");
4882 DECL_NAME (repl) = get_identifier (pretty_name);
4883 DECL_NAMELESS (repl) = 1;
4884 obstack_free (&name_obstack, pretty_name);
4886 adj->new_ssa_base = repl;
4888 else
4889 repl = adj->new_ssa_base;
4890 return repl;
4893 /* Find the first adjustment for a particular parameter BASE in a vector of
4894 ADJUSTMENTS which is not a copy_param. Return NULL if there is no such
4895 adjustment. */
4897 static struct ipa_parm_adjustment *
4898 get_adjustment_for_base (ipa_parm_adjustment_vec adjustments, tree base)
4900 int i, len;
4902 len = adjustments.length ();
4903 for (i = 0; i < len; i++)
4905 struct ipa_parm_adjustment *adj;
4907 adj = &adjustments[i];
4908 if (adj->op != IPA_PARM_OP_COPY && adj->base == base)
4909 return adj;
4912 return NULL;
4915 /* If OLD_NAME, which is being defined by statement STMT, is an SSA_NAME of a
4916 parameter which is to be removed because its value is not used, create a new
4917 SSA_NAME relating to a replacement VAR_DECL, replace all uses of the
4918 original with it and return it. If there is no need to re-map, return NULL.
4919 ADJUSTMENTS is a pointer to a vector of IPA-SRA adjustments. */
4921 static tree
4922 replace_removed_params_ssa_names (tree old_name, gimple *stmt,
4923 ipa_parm_adjustment_vec adjustments)
4925 struct ipa_parm_adjustment *adj;
4926 tree decl, repl, new_name;
4928 if (TREE_CODE (old_name) != SSA_NAME)
4929 return NULL;
4931 decl = SSA_NAME_VAR (old_name);
4932 if (decl == NULL_TREE
4933 || TREE_CODE (decl) != PARM_DECL)
4934 return NULL;
4936 adj = get_adjustment_for_base (adjustments, decl);
4937 if (!adj)
4938 return NULL;
4940 repl = get_replaced_param_substitute (adj);
4941 new_name = make_ssa_name (repl, stmt);
4942 SSA_NAME_OCCURS_IN_ABNORMAL_PHI (new_name)
4943 = SSA_NAME_OCCURS_IN_ABNORMAL_PHI (old_name);
4945 if (dump_file)
4947 fprintf (dump_file, "replacing an SSA name of a removed param ");
4948 print_generic_expr (dump_file, old_name);
4949 fprintf (dump_file, " with ");
4950 print_generic_expr (dump_file, new_name);
4951 fprintf (dump_file, "\n");
4954 replace_uses_by (old_name, new_name);
4955 return new_name;
4958 /* If the statement STMT contains any expressions that need to replaced with a
4959 different one as noted by ADJUSTMENTS, do so. Handle any potential type
4960 incompatibilities (GSI is used to accommodate conversion statements and must
4961 point to the statement). Return true iff the statement was modified. */
4963 static bool
4964 sra_ipa_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi,
4965 ipa_parm_adjustment_vec adjustments)
4967 tree *lhs_p, *rhs_p;
4968 bool any;
4970 if (!gimple_assign_single_p (stmt))
4971 return false;
4973 rhs_p = gimple_assign_rhs1_ptr (stmt);
4974 lhs_p = gimple_assign_lhs_ptr (stmt);
4976 any = ipa_modify_expr (rhs_p, false, adjustments);
4977 any |= ipa_modify_expr (lhs_p, false, adjustments);
4978 if (any)
4980 tree new_rhs = NULL_TREE;
4982 if (!useless_type_conversion_p (TREE_TYPE (*lhs_p), TREE_TYPE (*rhs_p)))
4984 if (TREE_CODE (*rhs_p) == CONSTRUCTOR)
4986 /* V_C_Es of constructors can cause trouble (PR 42714). */
4987 if (is_gimple_reg_type (TREE_TYPE (*lhs_p)))
4988 *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
4989 else
4990 *rhs_p = build_constructor (TREE_TYPE (*lhs_p),
4991 NULL);
4993 else
4994 new_rhs = fold_build1_loc (gimple_location (stmt),
4995 VIEW_CONVERT_EXPR, TREE_TYPE (*lhs_p),
4996 *rhs_p);
4998 else if (REFERENCE_CLASS_P (*rhs_p)
4999 && is_gimple_reg_type (TREE_TYPE (*lhs_p))
5000 && !is_gimple_reg (*lhs_p))
5001 /* This can happen when an assignment in between two single field
5002 structures is turned into an assignment in between two pointers to
5003 scalars (PR 42237). */
5004 new_rhs = *rhs_p;
5006 if (new_rhs)
5008 tree tmp = force_gimple_operand_gsi (gsi, new_rhs, true, NULL_TREE,
5009 true, GSI_SAME_STMT);
5011 gimple_assign_set_rhs_from_tree (gsi, tmp);
5014 return true;
5017 return false;
5020 /* Traverse the function body and all modifications as described in
5021 ADJUSTMENTS. Return true iff the CFG has been changed. */
5023 bool
5024 ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments)
5026 bool cfg_changed = false;
5027 basic_block bb;
5029 FOR_EACH_BB_FN (bb, cfun)
5031 gimple_stmt_iterator gsi;
5033 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5035 gphi *phi = as_a <gphi *> (gsi_stmt (gsi));
5036 tree new_lhs, old_lhs = gimple_phi_result (phi);
5037 new_lhs = replace_removed_params_ssa_names (old_lhs, phi, adjustments);
5038 if (new_lhs)
5040 gimple_phi_set_result (phi, new_lhs);
5041 release_ssa_name (old_lhs);
5045 gsi = gsi_start_bb (bb);
5046 while (!gsi_end_p (gsi))
5048 gimple *stmt = gsi_stmt (gsi);
5049 bool modified = false;
5050 tree *t;
5051 unsigned i;
5053 switch (gimple_code (stmt))
5055 case GIMPLE_RETURN:
5056 t = gimple_return_retval_ptr (as_a <greturn *> (stmt));
5057 if (*t != NULL_TREE)
5058 modified |= ipa_modify_expr (t, true, adjustments);
5059 break;
5061 case GIMPLE_ASSIGN:
5062 modified |= sra_ipa_modify_assign (stmt, &gsi, adjustments);
5063 break;
5065 case GIMPLE_CALL:
5066 /* Operands must be processed before the lhs. */
5067 for (i = 0; i < gimple_call_num_args (stmt); i++)
5069 t = gimple_call_arg_ptr (stmt, i);
5070 modified |= ipa_modify_expr (t, true, adjustments);
5073 if (gimple_call_lhs (stmt))
5075 t = gimple_call_lhs_ptr (stmt);
5076 modified |= ipa_modify_expr (t, false, adjustments);
5078 break;
5080 case GIMPLE_ASM:
5082 gasm *asm_stmt = as_a <gasm *> (stmt);
5083 for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
5085 t = &TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
5086 modified |= ipa_modify_expr (t, true, adjustments);
5088 for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
5090 t = &TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
5091 modified |= ipa_modify_expr (t, false, adjustments);
5094 break;
5096 default:
5097 break;
5100 def_operand_p defp;
5101 ssa_op_iter iter;
5102 FOR_EACH_SSA_DEF_OPERAND (defp, stmt, iter, SSA_OP_DEF)
5104 tree old_def = DEF_FROM_PTR (defp);
5105 if (tree new_def = replace_removed_params_ssa_names (old_def, stmt,
5106 adjustments))
5108 SET_DEF (defp, new_def);
5109 release_ssa_name (old_def);
5110 modified = true;
5114 if (modified)
5116 update_stmt (stmt);
5117 if (maybe_clean_eh_stmt (stmt)
5118 && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
5119 cfg_changed = true;
5121 gsi_next (&gsi);
5125 return cfg_changed;
5128 /* Call gimple_debug_bind_reset_value on all debug statements describing
5129 gimple register parameters that are being removed or replaced. */
5131 static void
5132 sra_ipa_reset_debug_stmts (ipa_parm_adjustment_vec adjustments)
5134 int i, len;
5135 gimple_stmt_iterator *gsip = NULL, gsi;
5137 if (MAY_HAVE_DEBUG_STMTS && single_succ_p (ENTRY_BLOCK_PTR_FOR_FN (cfun)))
5139 gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
5140 gsip = &gsi;
5142 len = adjustments.length ();
5143 for (i = 0; i < len; i++)
5145 struct ipa_parm_adjustment *adj;
5146 imm_use_iterator ui;
5147 gimple *stmt;
5148 gdebug *def_temp;
5149 tree name, vexpr, copy = NULL_TREE;
5150 use_operand_p use_p;
5152 adj = &adjustments[i];
5153 if (adj->op == IPA_PARM_OP_COPY || !is_gimple_reg (adj->base))
5154 continue;
5155 name = ssa_default_def (cfun, adj->base);
5156 vexpr = NULL;
5157 if (name)
5158 FOR_EACH_IMM_USE_STMT (stmt, ui, name)
5160 if (gimple_clobber_p (stmt))
5162 gimple_stmt_iterator cgsi = gsi_for_stmt (stmt);
5163 unlink_stmt_vdef (stmt);
5164 gsi_remove (&cgsi, true);
5165 release_defs (stmt);
5166 continue;
5168 /* All other users must have been removed by
5169 ipa_sra_modify_function_body. */
5170 gcc_assert (is_gimple_debug (stmt));
5171 if (vexpr == NULL && gsip != NULL)
5173 gcc_assert (TREE_CODE (adj->base) == PARM_DECL);
5174 vexpr = make_node (DEBUG_EXPR_DECL);
5175 def_temp = gimple_build_debug_source_bind (vexpr, adj->base,
5176 NULL);
5177 DECL_ARTIFICIAL (vexpr) = 1;
5178 TREE_TYPE (vexpr) = TREE_TYPE (name);
5179 SET_DECL_MODE (vexpr, DECL_MODE (adj->base));
5180 gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
5182 if (vexpr)
5184 FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
5185 SET_USE (use_p, vexpr);
5187 else
5188 gimple_debug_bind_reset_value (stmt);
5189 update_stmt (stmt);
5191 /* Create a VAR_DECL for debug info purposes. */
5192 if (!DECL_IGNORED_P (adj->base))
5194 copy = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
5195 VAR_DECL, DECL_NAME (adj->base),
5196 TREE_TYPE (adj->base));
5197 if (DECL_PT_UID_SET_P (adj->base))
5198 SET_DECL_PT_UID (copy, DECL_PT_UID (adj->base));
5199 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (adj->base);
5200 TREE_READONLY (copy) = TREE_READONLY (adj->base);
5201 TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (adj->base);
5202 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (adj->base);
5203 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (adj->base);
5204 DECL_IGNORED_P (copy) = DECL_IGNORED_P (adj->base);
5205 DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (adj->base);
5206 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
5207 SET_DECL_RTL (copy, 0);
5208 TREE_USED (copy) = 1;
5209 DECL_CONTEXT (copy) = current_function_decl;
5210 add_local_decl (cfun, copy);
5211 DECL_CHAIN (copy) =
5212 BLOCK_VARS (DECL_INITIAL (current_function_decl));
5213 BLOCK_VARS (DECL_INITIAL (current_function_decl)) = copy;
5215 if (gsip != NULL && copy && target_for_debug_bind (adj->base))
5217 gcc_assert (TREE_CODE (adj->base) == PARM_DECL);
5218 if (vexpr)
5219 def_temp = gimple_build_debug_bind (copy, vexpr, NULL);
5220 else
5221 def_temp = gimple_build_debug_source_bind (copy, adj->base,
5222 NULL);
5223 gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
5228 /* Return false if all callers have at least as many actual arguments as there
5229 are formal parameters in the current function and that their types
5230 match. */
5232 static bool
5233 some_callers_have_mismatched_arguments_p (struct cgraph_node *node,
5234 void *data ATTRIBUTE_UNUSED)
5236 struct cgraph_edge *cs;
5237 for (cs = node->callers; cs; cs = cs->next_caller)
5238 if (!cs->call_stmt || !callsite_arguments_match_p (cs->call_stmt))
5239 return true;
5241 return false;
5244 /* Return false if all callers have vuse attached to a call statement. */
5246 static bool
5247 some_callers_have_no_vuse_p (struct cgraph_node *node,
5248 void *data ATTRIBUTE_UNUSED)
5250 struct cgraph_edge *cs;
5251 for (cs = node->callers; cs; cs = cs->next_caller)
5252 if (!cs->call_stmt || !gimple_vuse (cs->call_stmt))
5253 return true;
5255 return false;
5258 /* Convert all callers of NODE. */
5260 static bool
5261 convert_callers_for_node (struct cgraph_node *node,
5262 void *data)
5264 ipa_parm_adjustment_vec *adjustments = (ipa_parm_adjustment_vec *) data;
5265 bitmap recomputed_callers = BITMAP_ALLOC (NULL);
5266 struct cgraph_edge *cs;
5268 for (cs = node->callers; cs; cs = cs->next_caller)
5270 push_cfun (DECL_STRUCT_FUNCTION (cs->caller->decl));
5272 if (dump_file)
5273 fprintf (dump_file, "Adjusting call %s -> %s\n",
5274 cs->caller->dump_name (), cs->callee->dump_name ());
5276 ipa_modify_call_arguments (cs, cs->call_stmt, *adjustments);
5278 pop_cfun ();
5281 for (cs = node->callers; cs; cs = cs->next_caller)
5282 if (bitmap_set_bit (recomputed_callers, cs->caller->uid)
5283 && gimple_in_ssa_p (DECL_STRUCT_FUNCTION (cs->caller->decl)))
5284 compute_fn_summary (cs->caller, true);
5285 BITMAP_FREE (recomputed_callers);
5287 return true;
5290 /* Convert all callers of NODE to pass parameters as given in ADJUSTMENTS. */
5292 static void
5293 convert_callers (struct cgraph_node *node, tree old_decl,
5294 ipa_parm_adjustment_vec adjustments)
5296 basic_block this_block;
5298 node->call_for_symbol_and_aliases (convert_callers_for_node,
5299 &adjustments, false);
5301 if (!encountered_recursive_call)
5302 return;
5304 FOR_EACH_BB_FN (this_block, cfun)
5306 gimple_stmt_iterator gsi;
5308 for (gsi = gsi_start_bb (this_block); !gsi_end_p (gsi); gsi_next (&gsi))
5310 gcall *stmt;
5311 tree call_fndecl;
5312 stmt = dyn_cast <gcall *> (gsi_stmt (gsi));
5313 if (!stmt)
5314 continue;
5315 call_fndecl = gimple_call_fndecl (stmt);
5316 if (call_fndecl == old_decl)
5318 if (dump_file)
5319 fprintf (dump_file, "Adjusting recursive call");
5320 gimple_call_set_fndecl (stmt, node->decl);
5321 ipa_modify_call_arguments (NULL, stmt, adjustments);
5326 return;
5329 /* Perform all the modification required in IPA-SRA for NODE to have parameters
5330 as given in ADJUSTMENTS. Return true iff the CFG has been changed. */
5332 static bool
5333 modify_function (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments)
5335 struct cgraph_node *new_node;
5336 bool cfg_changed;
5338 cgraph_edge::rebuild_edges ();
5339 free_dominance_info (CDI_DOMINATORS);
5340 pop_cfun ();
5342 /* This must be done after rebuilding cgraph edges for node above.
5343 Otherwise any recursive calls to node that are recorded in
5344 redirect_callers will be corrupted. */
5345 vec<cgraph_edge *> redirect_callers = node->collect_callers ();
5346 new_node = node->create_version_clone_with_body (redirect_callers, NULL,
5347 NULL, false, NULL, NULL,
5348 "isra");
5349 redirect_callers.release ();
5351 push_cfun (DECL_STRUCT_FUNCTION (new_node->decl));
5352 ipa_modify_formal_parameters (current_function_decl, adjustments);
5353 cfg_changed = ipa_sra_modify_function_body (adjustments);
5354 sra_ipa_reset_debug_stmts (adjustments);
5355 convert_callers (new_node, node->decl, adjustments);
5356 new_node->make_local ();
5357 return cfg_changed;
5360 /* Means of communication between ipa_sra_check_caller and
5361 ipa_sra_preliminary_function_checks. */
5363 struct ipa_sra_check_caller_data
5365 bool has_callers;
5366 bool bad_arg_alignment;
5367 bool has_thunk;
5370 /* If NODE has a caller, mark that fact in DATA which is pointer to
5371 ipa_sra_check_caller_data. Also check all aggregate arguments in all known
5372 calls if they are unit aligned and if not, set the appropriate flag in DATA
5373 too. */
5375 static bool
5376 ipa_sra_check_caller (struct cgraph_node *node, void *data)
5378 if (!node->callers)
5379 return false;
5381 struct ipa_sra_check_caller_data *iscc;
5382 iscc = (struct ipa_sra_check_caller_data *) data;
5383 iscc->has_callers = true;
5385 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
5387 if (cs->caller->thunk.thunk_p)
5389 iscc->has_thunk = true;
5390 return true;
5392 gimple *call_stmt = cs->call_stmt;
5393 unsigned count = gimple_call_num_args (call_stmt);
5394 for (unsigned i = 0; i < count; i++)
5396 tree arg = gimple_call_arg (call_stmt, i);
5397 if (is_gimple_reg (arg))
5398 continue;
5400 tree offset;
5401 poly_int64 bitsize, bitpos;
5402 machine_mode mode;
5403 int unsignedp, reversep, volatilep = 0;
5404 get_inner_reference (arg, &bitsize, &bitpos, &offset, &mode,
5405 &unsignedp, &reversep, &volatilep);
5406 if (!multiple_p (bitpos, BITS_PER_UNIT))
5408 iscc->bad_arg_alignment = true;
5409 return true;
5414 return false;
5417 /* Return false the function is apparently unsuitable for IPA-SRA based on it's
5418 attributes, return true otherwise. NODE is the cgraph node of the current
5419 function. */
5421 static bool
5422 ipa_sra_preliminary_function_checks (struct cgraph_node *node)
5424 if (!node->can_be_local_p ())
5426 if (dump_file)
5427 fprintf (dump_file, "Function not local to this compilation unit.\n");
5428 return false;
5431 if (!node->local.can_change_signature)
5433 if (dump_file)
5434 fprintf (dump_file, "Function can not change signature.\n");
5435 return false;
5438 if (!tree_versionable_function_p (node->decl))
5440 if (dump_file)
5441 fprintf (dump_file, "Function is not versionable.\n");
5442 return false;
5445 if (!opt_for_fn (node->decl, optimize)
5446 || !opt_for_fn (node->decl, flag_ipa_sra))
5448 if (dump_file)
5449 fprintf (dump_file, "Function not optimized.\n");
5450 return false;
5453 if (DECL_VIRTUAL_P (current_function_decl))
5455 if (dump_file)
5456 fprintf (dump_file, "Function is a virtual method.\n");
5457 return false;
5460 if ((DECL_ONE_ONLY (node->decl) || DECL_EXTERNAL (node->decl))
5461 && ipa_fn_summaries->get (node)->size >= MAX_INLINE_INSNS_AUTO)
5463 if (dump_file)
5464 fprintf (dump_file, "Function too big to be made truly local.\n");
5465 return false;
5468 if (cfun->stdarg)
5470 if (dump_file)
5471 fprintf (dump_file, "Function uses stdarg. \n");
5472 return false;
5475 if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl)))
5476 return false;
5478 if (DECL_DISREGARD_INLINE_LIMITS (node->decl))
5480 if (dump_file)
5481 fprintf (dump_file, "Always inline function will be inlined "
5482 "anyway. \n");
5483 return false;
5486 struct ipa_sra_check_caller_data iscc;
5487 memset (&iscc, 0, sizeof(iscc));
5488 node->call_for_symbol_and_aliases (ipa_sra_check_caller, &iscc, true);
5489 if (!iscc.has_callers)
5491 if (dump_file)
5492 fprintf (dump_file,
5493 "Function has no callers in this compilation unit.\n");
5494 return false;
5497 if (iscc.bad_arg_alignment)
5499 if (dump_file)
5500 fprintf (dump_file,
5501 "A function call has an argument with non-unit alignment.\n");
5502 return false;
5505 if (iscc.has_thunk)
5507 if (dump_file)
5508 fprintf (dump_file,
5509 "A has thunk.\n");
5510 return false;
5513 return true;
5516 /* Perform early interprocedural SRA. */
5518 static unsigned int
5519 ipa_early_sra (void)
5521 struct cgraph_node *node = cgraph_node::get (current_function_decl);
5522 ipa_parm_adjustment_vec adjustments;
5523 int ret = 0;
5525 if (!ipa_sra_preliminary_function_checks (node))
5526 return 0;
5528 sra_initialize ();
5529 sra_mode = SRA_MODE_EARLY_IPA;
5531 if (!find_param_candidates ())
5533 if (dump_file)
5534 fprintf (dump_file, "Function has no IPA-SRA candidates.\n");
5535 goto simple_out;
5538 if (node->call_for_symbol_and_aliases
5539 (some_callers_have_mismatched_arguments_p, NULL, true))
5541 if (dump_file)
5542 fprintf (dump_file, "There are callers with insufficient number of "
5543 "arguments or arguments with type mismatches.\n");
5544 goto simple_out;
5547 if (node->call_for_symbol_and_aliases
5548 (some_callers_have_no_vuse_p, NULL, true))
5550 if (dump_file)
5551 fprintf (dump_file, "There are callers with no VUSE attached "
5552 "to a call stmt.\n");
5553 goto simple_out;
5556 bb_dereferences = XCNEWVEC (HOST_WIDE_INT,
5557 func_param_count
5558 * last_basic_block_for_fn (cfun));
5559 final_bbs = BITMAP_ALLOC (NULL);
5561 scan_function ();
5562 if (encountered_apply_args)
5564 if (dump_file)
5565 fprintf (dump_file, "Function calls __builtin_apply_args().\n");
5566 goto out;
5569 if (encountered_unchangable_recursive_call)
5571 if (dump_file)
5572 fprintf (dump_file, "Function calls itself with insufficient "
5573 "number of arguments.\n");
5574 goto out;
5577 adjustments = analyze_all_param_acesses ();
5578 if (!adjustments.exists ())
5579 goto out;
5580 if (dump_file)
5581 ipa_dump_param_adjustments (dump_file, adjustments, current_function_decl);
5583 if (modify_function (node, adjustments))
5584 ret = TODO_update_ssa | TODO_cleanup_cfg;
5585 else
5586 ret = TODO_update_ssa;
5587 adjustments.release ();
5589 statistics_counter_event (cfun, "Unused parameters deleted",
5590 sra_stats.deleted_unused_parameters);
5591 statistics_counter_event (cfun, "Scalar parameters converted to by-value",
5592 sra_stats.scalar_by_ref_to_by_val);
5593 statistics_counter_event (cfun, "Aggregate parameters broken up",
5594 sra_stats.aggregate_params_reduced);
5595 statistics_counter_event (cfun, "Aggregate parameter components created",
5596 sra_stats.param_reductions_created);
5598 out:
5599 BITMAP_FREE (final_bbs);
5600 free (bb_dereferences);
5601 simple_out:
5602 sra_deinitialize ();
5603 return ret;
5606 namespace {
5608 const pass_data pass_data_early_ipa_sra =
5610 GIMPLE_PASS, /* type */
5611 "eipa_sra", /* name */
5612 OPTGROUP_NONE, /* optinfo_flags */
5613 TV_IPA_SRA, /* tv_id */
5614 0, /* properties_required */
5615 0, /* properties_provided */
5616 0, /* properties_destroyed */
5617 0, /* todo_flags_start */
5618 TODO_dump_symtab, /* todo_flags_finish */
5621 class pass_early_ipa_sra : public gimple_opt_pass
5623 public:
5624 pass_early_ipa_sra (gcc::context *ctxt)
5625 : gimple_opt_pass (pass_data_early_ipa_sra, ctxt)
5628 /* opt_pass methods: */
5629 virtual bool gate (function *) { return flag_ipa_sra && dbg_cnt (eipa_sra); }
5630 virtual unsigned int execute (function *) { return ipa_early_sra (); }
5632 }; // class pass_early_ipa_sra
5634 } // anon namespace
5636 gimple_opt_pass *
5637 make_pass_early_ipa_sra (gcc::context *ctxt)
5639 return new pass_early_ipa_sra (ctxt);