1 /* Scalar Replacement of Aggregates (SRA) converts some structure
2 references into scalar references, exposing them to the scalar
4 Copyright (C) 2008-2014 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
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
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
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
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. */
76 #include "coretypes.h"
78 #include "hash-table.h"
79 #include "alloc-pool.h"
87 #include "hard-reg-set.h"
90 #include "dominance.h"
92 #include "basic-block.h"
93 #include "tree-ssa-alias.h"
94 #include "internal-fn.h"
96 #include "gimple-expr.h"
99 #include "stor-layout.h"
100 #include "gimplify.h"
101 #include "gimple-iterator.h"
102 #include "gimplify-me.h"
103 #include "gimple-walk.h"
105 #include "gimple-ssa.h"
106 #include "tree-cfg.h"
107 #include "tree-phinodes.h"
108 #include "ssa-iterators.h"
109 #include "stringpool.h"
110 #include "tree-ssanames.h"
112 #include "tree-dfa.h"
113 #include "tree-ssa.h"
114 #include "tree-pass.h"
115 #include "plugin-api.h"
118 #include "symbol-summary.h"
119 #include "ipa-prop.h"
120 #include "statistics.h"
125 #include "tree-inline.h"
126 #include "gimple-pretty-print.h"
127 #include "ipa-inline.h"
128 #include "ipa-utils.h"
129 #include "builtins.h"
131 /* Enumeration of all aggregate reductions we can do. */
132 enum sra_mode
{ SRA_MODE_EARLY_IPA
, /* early call regularization */
133 SRA_MODE_EARLY_INTRA
, /* early intraprocedural SRA */
134 SRA_MODE_INTRA
}; /* late intraprocedural SRA */
136 /* Global variable describing which aggregate reduction we are performing at
138 static enum sra_mode sra_mode
;
142 /* ACCESS represents each access to an aggregate variable (as a whole or a
143 part). It can also represent a group of accesses that refer to exactly the
144 same fragment of an aggregate (i.e. those that have exactly the same offset
145 and size). Such representatives for a single aggregate, once determined,
146 are linked in a linked list and have the group fields set.
148 Moreover, when doing intraprocedural SRA, a tree is built from those
149 representatives (by the means of first_child and next_sibling pointers), in
150 which all items in a subtree are "within" the root, i.e. their offset is
151 greater or equal to offset of the root and offset+size is smaller or equal
152 to offset+size of the root. Children of an access are sorted by offset.
154 Note that accesses to parts of vector and complex number types always
155 represented by an access to the whole complex number or a vector. It is a
156 duty of the modifying functions to replace them appropriately. */
160 /* Values returned by `get_ref_base_and_extent' for each component reference
161 If EXPR isn't a component reference just set `BASE = EXPR', `OFFSET = 0',
162 `SIZE = TREE_SIZE (TREE_TYPE (expr))'. */
163 HOST_WIDE_INT offset
;
167 /* Expression. It is context dependent so do not use it to create new
168 expressions to access the original aggregate. See PR 42154 for a
174 /* The statement this access belongs to. */
177 /* Next group representative for this aggregate. */
178 struct access
*next_grp
;
180 /* Pointer to the group representative. Pointer to itself if the struct is
181 the representative. */
182 struct access
*group_representative
;
184 /* If this access has any children (in terms of the definition above), this
185 points to the first one. */
186 struct access
*first_child
;
188 /* In intraprocedural SRA, pointer to the next sibling in the access tree as
189 described above. In IPA-SRA this is a pointer to the next access
190 belonging to the same group (having the same representative). */
191 struct access
*next_sibling
;
193 /* Pointers to the first and last element in the linked list of assign
195 struct assign_link
*first_link
, *last_link
;
197 /* Pointer to the next access in the work queue. */
198 struct access
*next_queued
;
200 /* Replacement variable for this access "region." Never to be accessed
201 directly, always only by the means of get_access_replacement() and only
202 when grp_to_be_replaced flag is set. */
203 tree replacement_decl
;
205 /* Is this particular access write access? */
208 /* Is this access an access to a non-addressable field? */
209 unsigned non_addressable
: 1;
211 /* Is this access currently in the work queue? */
212 unsigned grp_queued
: 1;
214 /* Does this group contain a write access? This flag is propagated down the
216 unsigned grp_write
: 1;
218 /* Does this group contain a read access? This flag is propagated down the
220 unsigned grp_read
: 1;
222 /* Does this group contain a read access that comes from an assignment
223 statement? This flag is propagated down the access tree. */
224 unsigned grp_assignment_read
: 1;
226 /* Does this group contain a write access that comes from an assignment
227 statement? This flag is propagated down the access tree. */
228 unsigned grp_assignment_write
: 1;
230 /* Does this group contain a read access through a scalar type? This flag is
231 not propagated in the access tree in any direction. */
232 unsigned grp_scalar_read
: 1;
234 /* Does this group contain a write access through a scalar type? This flag
235 is not propagated in the access tree in any direction. */
236 unsigned grp_scalar_write
: 1;
238 /* Is this access an artificial one created to scalarize some record
240 unsigned grp_total_scalarization
: 1;
242 /* Other passes of the analysis use this bit to make function
243 analyze_access_subtree create scalar replacements for this group if
245 unsigned grp_hint
: 1;
247 /* Is the subtree rooted in this access fully covered by scalar
249 unsigned grp_covered
: 1;
251 /* If set to true, this access and all below it in an access tree must not be
253 unsigned grp_unscalarizable_region
: 1;
255 /* Whether data have been written to parts of the aggregate covered by this
256 access which is not to be scalarized. This flag is propagated up in the
258 unsigned grp_unscalarized_data
: 1;
260 /* Does this access and/or group contain a write access through a
262 unsigned grp_partial_lhs
: 1;
264 /* Set when a scalar replacement should be created for this variable. */
265 unsigned grp_to_be_replaced
: 1;
267 /* Set when we want a replacement for the sole purpose of having it in
268 generated debug statements. */
269 unsigned grp_to_be_debug_replaced
: 1;
271 /* Should TREE_NO_WARNING of a replacement be set? */
272 unsigned grp_no_warning
: 1;
274 /* Is it possible that the group refers to data which might be (directly or
275 otherwise) modified? */
276 unsigned grp_maybe_modified
: 1;
278 /* Set when this is a representative of a pointer to scalar (i.e. by
279 reference) parameter which we consider for turning into a plain scalar
280 (i.e. a by value parameter). */
281 unsigned grp_scalar_ptr
: 1;
283 /* Set when we discover that this pointer is not safe to dereference in the
285 unsigned grp_not_necessarilly_dereferenced
: 1;
288 typedef struct access
*access_p
;
291 /* Alloc pool for allocating access structures. */
292 static alloc_pool access_pool
;
294 /* A structure linking lhs and rhs accesses from an aggregate assignment. They
295 are used to propagate subaccesses from rhs to lhs as long as they don't
296 conflict with what is already there. */
299 struct access
*lacc
, *racc
;
300 struct assign_link
*next
;
303 /* Alloc pool for allocating assign link structures. */
304 static alloc_pool link_pool
;
306 /* Base (tree) -> Vector (vec<access_p> *) map. */
307 static hash_map
<tree
, auto_vec
<access_p
> > *base_access_vec
;
309 /* Candidate hash table helpers. */
311 struct uid_decl_hasher
: typed_noop_remove
<tree_node
>
313 typedef tree_node value_type
;
314 typedef tree_node compare_type
;
315 static inline hashval_t
hash (const value_type
*);
316 static inline bool equal (const value_type
*, const compare_type
*);
319 /* Hash a tree in a uid_decl_map. */
322 uid_decl_hasher::hash (const value_type
*item
)
324 return item
->decl_minimal
.uid
;
327 /* Return true if the DECL_UID in both trees are equal. */
330 uid_decl_hasher::equal (const value_type
*a
, const compare_type
*b
)
332 return (a
->decl_minimal
.uid
== b
->decl_minimal
.uid
);
335 /* Set of candidates. */
336 static bitmap candidate_bitmap
;
337 static hash_table
<uid_decl_hasher
> *candidates
;
339 /* For a candidate UID return the candidates decl. */
342 candidate (unsigned uid
)
345 t
.decl_minimal
.uid
= uid
;
346 return candidates
->find_with_hash (&t
, static_cast <hashval_t
> (uid
));
349 /* Bitmap of candidates which we should try to entirely scalarize away and
350 those which cannot be (because they are and need be used as a whole). */
351 static bitmap should_scalarize_away_bitmap
, cannot_scalarize_away_bitmap
;
353 /* Obstack for creation of fancy names. */
354 static struct obstack name_obstack
;
356 /* Head of a linked list of accesses that need to have its subaccesses
357 propagated to their assignment counterparts. */
358 static struct access
*work_queue_head
;
360 /* Number of parameters of the analyzed function when doing early ipa SRA. */
361 static int func_param_count
;
363 /* scan_function sets the following to true if it encounters a call to
364 __builtin_apply_args. */
365 static bool encountered_apply_args
;
367 /* Set by scan_function when it finds a recursive call. */
368 static bool encountered_recursive_call
;
370 /* Set by scan_function when it finds a recursive call with less actual
371 arguments than formal parameters.. */
372 static bool encountered_unchangable_recursive_call
;
374 /* This is a table in which for each basic block and parameter there is a
375 distance (offset + size) in that parameter which is dereferenced and
376 accessed in that BB. */
377 static HOST_WIDE_INT
*bb_dereferences
;
378 /* Bitmap of BBs that can cause the function to "stop" progressing by
379 returning, throwing externally, looping infinitely or calling a function
380 which might abort etc.. */
381 static bitmap final_bbs
;
383 /* Representative of no accesses at all. */
384 static struct access no_accesses_representant
;
386 /* Predicate to test the special value. */
389 no_accesses_p (struct access
*access
)
391 return access
== &no_accesses_representant
;
394 /* Dump contents of ACCESS to file F in a human friendly way. If GRP is true,
395 representative fields are dumped, otherwise those which only describe the
396 individual access are. */
400 /* Number of processed aggregates is readily available in
401 analyze_all_variable_accesses and so is not stored here. */
403 /* Number of created scalar replacements. */
406 /* Number of times sra_modify_expr or sra_modify_assign themselves changed an
410 /* Number of statements created by generate_subtree_copies. */
413 /* Number of statements created by load_assign_lhs_subreplacements. */
416 /* Number of times sra_modify_assign has deleted a statement. */
419 /* Number of times sra_modify_assign has to deal with subaccesses of LHS and
420 RHS reparately due to type conversions or nonexistent matching
422 int separate_lhs_rhs_handling
;
424 /* Number of parameters that were removed because they were unused. */
425 int deleted_unused_parameters
;
427 /* Number of scalars passed as parameters by reference that have been
428 converted to be passed by value. */
429 int scalar_by_ref_to_by_val
;
431 /* Number of aggregate parameters that were replaced by one or more of their
433 int aggregate_params_reduced
;
435 /* Numbber of components created when splitting aggregate parameters. */
436 int param_reductions_created
;
440 dump_access (FILE *f
, struct access
*access
, bool grp
)
442 fprintf (f
, "access { ");
443 fprintf (f
, "base = (%d)'", DECL_UID (access
->base
));
444 print_generic_expr (f
, access
->base
, 0);
445 fprintf (f
, "', offset = " HOST_WIDE_INT_PRINT_DEC
, access
->offset
);
446 fprintf (f
, ", size = " HOST_WIDE_INT_PRINT_DEC
, access
->size
);
447 fprintf (f
, ", expr = ");
448 print_generic_expr (f
, access
->expr
, 0);
449 fprintf (f
, ", type = ");
450 print_generic_expr (f
, access
->type
, 0);
452 fprintf (f
, ", grp_read = %d, grp_write = %d, grp_assignment_read = %d, "
453 "grp_assignment_write = %d, grp_scalar_read = %d, "
454 "grp_scalar_write = %d, grp_total_scalarization = %d, "
455 "grp_hint = %d, grp_covered = %d, "
456 "grp_unscalarizable_region = %d, grp_unscalarized_data = %d, "
457 "grp_partial_lhs = %d, grp_to_be_replaced = %d, "
458 "grp_to_be_debug_replaced = %d, grp_maybe_modified = %d, "
459 "grp_not_necessarilly_dereferenced = %d\n",
460 access
->grp_read
, access
->grp_write
, access
->grp_assignment_read
,
461 access
->grp_assignment_write
, access
->grp_scalar_read
,
462 access
->grp_scalar_write
, access
->grp_total_scalarization
,
463 access
->grp_hint
, access
->grp_covered
,
464 access
->grp_unscalarizable_region
, access
->grp_unscalarized_data
,
465 access
->grp_partial_lhs
, access
->grp_to_be_replaced
,
466 access
->grp_to_be_debug_replaced
, access
->grp_maybe_modified
,
467 access
->grp_not_necessarilly_dereferenced
);
469 fprintf (f
, ", write = %d, grp_total_scalarization = %d, "
470 "grp_partial_lhs = %d\n",
471 access
->write
, access
->grp_total_scalarization
,
472 access
->grp_partial_lhs
);
475 /* Dump a subtree rooted in ACCESS to file F, indent by LEVEL. */
478 dump_access_tree_1 (FILE *f
, struct access
*access
, int level
)
484 for (i
= 0; i
< level
; i
++)
485 fputs ("* ", dump_file
);
487 dump_access (f
, access
, true);
489 if (access
->first_child
)
490 dump_access_tree_1 (f
, access
->first_child
, level
+ 1);
492 access
= access
->next_sibling
;
497 /* Dump all access trees for a variable, given the pointer to the first root in
501 dump_access_tree (FILE *f
, struct access
*access
)
503 for (; access
; access
= access
->next_grp
)
504 dump_access_tree_1 (f
, access
, 0);
507 /* Return true iff ACC is non-NULL and has subaccesses. */
510 access_has_children_p (struct access
*acc
)
512 return acc
&& acc
->first_child
;
515 /* Return true iff ACC is (partly) covered by at least one replacement. */
518 access_has_replacements_p (struct access
*acc
)
520 struct access
*child
;
521 if (acc
->grp_to_be_replaced
)
523 for (child
= acc
->first_child
; child
; child
= child
->next_sibling
)
524 if (access_has_replacements_p (child
))
529 /* Return a vector of pointers to accesses for the variable given in BASE or
530 NULL if there is none. */
532 static vec
<access_p
> *
533 get_base_access_vector (tree base
)
535 return base_access_vec
->get (base
);
538 /* Find an access with required OFFSET and SIZE in a subtree of accesses rooted
539 in ACCESS. Return NULL if it cannot be found. */
541 static struct access
*
542 find_access_in_subtree (struct access
*access
, HOST_WIDE_INT offset
,
545 while (access
&& (access
->offset
!= offset
|| access
->size
!= size
))
547 struct access
*child
= access
->first_child
;
549 while (child
&& (child
->offset
+ child
->size
<= offset
))
550 child
= child
->next_sibling
;
557 /* Return the first group representative for DECL or NULL if none exists. */
559 static struct access
*
560 get_first_repr_for_decl (tree base
)
562 vec
<access_p
> *access_vec
;
564 access_vec
= get_base_access_vector (base
);
568 return (*access_vec
)[0];
571 /* Find an access representative for the variable BASE and given OFFSET and
572 SIZE. Requires that access trees have already been built. Return NULL if
573 it cannot be found. */
575 static struct access
*
576 get_var_base_offset_size_access (tree base
, HOST_WIDE_INT offset
,
579 struct access
*access
;
581 access
= get_first_repr_for_decl (base
);
582 while (access
&& (access
->offset
+ access
->size
<= offset
))
583 access
= access
->next_grp
;
587 return find_access_in_subtree (access
, offset
, size
);
590 /* Add LINK to the linked list of assign links of RACC. */
592 add_link_to_rhs (struct access
*racc
, struct assign_link
*link
)
594 gcc_assert (link
->racc
== racc
);
596 if (!racc
->first_link
)
598 gcc_assert (!racc
->last_link
);
599 racc
->first_link
= link
;
602 racc
->last_link
->next
= link
;
604 racc
->last_link
= link
;
608 /* Move all link structures in their linked list in OLD_RACC to the linked list
611 relink_to_new_repr (struct access
*new_racc
, struct access
*old_racc
)
613 if (!old_racc
->first_link
)
615 gcc_assert (!old_racc
->last_link
);
619 if (new_racc
->first_link
)
621 gcc_assert (!new_racc
->last_link
->next
);
622 gcc_assert (!old_racc
->last_link
|| !old_racc
->last_link
->next
);
624 new_racc
->last_link
->next
= old_racc
->first_link
;
625 new_racc
->last_link
= old_racc
->last_link
;
629 gcc_assert (!new_racc
->last_link
);
631 new_racc
->first_link
= old_racc
->first_link
;
632 new_racc
->last_link
= old_racc
->last_link
;
634 old_racc
->first_link
= old_racc
->last_link
= NULL
;
637 /* Add ACCESS to the work queue (which is actually a stack). */
640 add_access_to_work_queue (struct access
*access
)
642 if (!access
->grp_queued
)
644 gcc_assert (!access
->next_queued
);
645 access
->next_queued
= work_queue_head
;
646 access
->grp_queued
= 1;
647 work_queue_head
= access
;
651 /* Pop an access from the work queue, and return it, assuming there is one. */
653 static struct access
*
654 pop_access_from_work_queue (void)
656 struct access
*access
= work_queue_head
;
658 work_queue_head
= access
->next_queued
;
659 access
->next_queued
= NULL
;
660 access
->grp_queued
= 0;
665 /* Allocate necessary structures. */
668 sra_initialize (void)
670 candidate_bitmap
= BITMAP_ALLOC (NULL
);
671 candidates
= new hash_table
<uid_decl_hasher
>
672 (vec_safe_length (cfun
->local_decls
) / 2);
673 should_scalarize_away_bitmap
= BITMAP_ALLOC (NULL
);
674 cannot_scalarize_away_bitmap
= BITMAP_ALLOC (NULL
);
675 gcc_obstack_init (&name_obstack
);
676 access_pool
= create_alloc_pool ("SRA accesses", sizeof (struct access
), 16);
677 link_pool
= create_alloc_pool ("SRA links", sizeof (struct assign_link
), 16);
678 base_access_vec
= new hash_map
<tree
, auto_vec
<access_p
> >;
679 memset (&sra_stats
, 0, sizeof (sra_stats
));
680 encountered_apply_args
= false;
681 encountered_recursive_call
= false;
682 encountered_unchangable_recursive_call
= false;
685 /* Deallocate all general structures. */
688 sra_deinitialize (void)
690 BITMAP_FREE (candidate_bitmap
);
693 BITMAP_FREE (should_scalarize_away_bitmap
);
694 BITMAP_FREE (cannot_scalarize_away_bitmap
);
695 free_alloc_pool (access_pool
);
696 free_alloc_pool (link_pool
);
697 obstack_free (&name_obstack
, NULL
);
699 delete base_access_vec
;
702 /* Remove DECL from candidates for SRA and write REASON to the dump file if
705 disqualify_candidate (tree decl
, const char *reason
)
707 if (bitmap_clear_bit (candidate_bitmap
, DECL_UID (decl
)))
708 candidates
->remove_elt_with_hash (decl
, DECL_UID (decl
));
710 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
712 fprintf (dump_file
, "! Disqualifying ");
713 print_generic_expr (dump_file
, decl
, 0);
714 fprintf (dump_file
, " - %s\n", reason
);
718 /* Return true iff the type contains a field or an element which does not allow
722 type_internals_preclude_sra_p (tree type
, const char **msg
)
727 switch (TREE_CODE (type
))
731 case QUAL_UNION_TYPE
:
732 for (fld
= TYPE_FIELDS (type
); fld
; fld
= DECL_CHAIN (fld
))
733 if (TREE_CODE (fld
) == FIELD_DECL
)
735 tree ft
= TREE_TYPE (fld
);
737 if (TREE_THIS_VOLATILE (fld
))
739 *msg
= "volatile structure field";
742 if (!DECL_FIELD_OFFSET (fld
))
744 *msg
= "no structure field offset";
747 if (!DECL_SIZE (fld
))
749 *msg
= "zero structure field size";
752 if (!tree_fits_uhwi_p (DECL_FIELD_OFFSET (fld
)))
754 *msg
= "structure field offset not fixed";
757 if (!tree_fits_uhwi_p (DECL_SIZE (fld
)))
759 *msg
= "structure field size not fixed";
762 if (!tree_fits_shwi_p (bit_position (fld
)))
764 *msg
= "structure field size too big";
767 if (AGGREGATE_TYPE_P (ft
)
768 && int_bit_position (fld
) % BITS_PER_UNIT
!= 0)
770 *msg
= "structure field is bit field";
774 if (AGGREGATE_TYPE_P (ft
) && type_internals_preclude_sra_p (ft
, msg
))
781 et
= TREE_TYPE (type
);
783 if (TYPE_VOLATILE (et
))
785 *msg
= "element type is volatile";
789 if (AGGREGATE_TYPE_P (et
) && type_internals_preclude_sra_p (et
, msg
))
799 /* If T is an SSA_NAME, return NULL if it is not a default def or return its
800 base variable if it is. Return T if it is not an SSA_NAME. */
803 get_ssa_base_param (tree t
)
805 if (TREE_CODE (t
) == SSA_NAME
)
807 if (SSA_NAME_IS_DEFAULT_DEF (t
))
808 return SSA_NAME_VAR (t
);
815 /* Mark a dereference of BASE of distance DIST in a basic block tht STMT
816 belongs to, unless the BB has already been marked as a potentially
820 mark_parm_dereference (tree base
, HOST_WIDE_INT dist
, gimple stmt
)
822 basic_block bb
= gimple_bb (stmt
);
823 int idx
, parm_index
= 0;
826 if (bitmap_bit_p (final_bbs
, bb
->index
))
829 for (parm
= DECL_ARGUMENTS (current_function_decl
);
830 parm
&& parm
!= base
;
831 parm
= DECL_CHAIN (parm
))
834 gcc_assert (parm_index
< func_param_count
);
836 idx
= bb
->index
* func_param_count
+ parm_index
;
837 if (bb_dereferences
[idx
] < dist
)
838 bb_dereferences
[idx
] = dist
;
841 /* Allocate an access structure for BASE, OFFSET and SIZE, clear it, fill in
842 the three fields. Also add it to the vector of accesses corresponding to
843 the base. Finally, return the new access. */
845 static struct access
*
846 create_access_1 (tree base
, HOST_WIDE_INT offset
, HOST_WIDE_INT size
)
848 struct access
*access
;
850 access
= (struct access
*) pool_alloc (access_pool
);
851 memset (access
, 0, sizeof (struct access
));
853 access
->offset
= offset
;
856 base_access_vec
->get_or_insert (base
).safe_push (access
);
861 /* Create and insert access for EXPR. Return created access, or NULL if it is
864 static struct access
*
865 create_access (tree expr
, gimple stmt
, bool write
)
867 struct access
*access
;
868 HOST_WIDE_INT offset
, size
, max_size
;
870 bool ptr
, unscalarizable_region
= false;
872 base
= get_ref_base_and_extent (expr
, &offset
, &size
, &max_size
);
874 if (sra_mode
== SRA_MODE_EARLY_IPA
875 && TREE_CODE (base
) == MEM_REF
)
877 base
= get_ssa_base_param (TREE_OPERAND (base
, 0));
885 if (!DECL_P (base
) || !bitmap_bit_p (candidate_bitmap
, DECL_UID (base
)))
888 if (sra_mode
== SRA_MODE_EARLY_IPA
)
890 if (size
< 0 || size
!= max_size
)
892 disqualify_candidate (base
, "Encountered a variable sized access.");
895 if (TREE_CODE (expr
) == COMPONENT_REF
896 && DECL_BIT_FIELD (TREE_OPERAND (expr
, 1)))
898 disqualify_candidate (base
, "Encountered a bit-field access.");
901 gcc_checking_assert ((offset
% BITS_PER_UNIT
) == 0);
904 mark_parm_dereference (base
, offset
+ size
, stmt
);
908 if (size
!= max_size
)
911 unscalarizable_region
= true;
915 disqualify_candidate (base
, "Encountered an unconstrained access.");
920 access
= create_access_1 (base
, offset
, size
);
922 access
->type
= TREE_TYPE (expr
);
923 access
->write
= write
;
924 access
->grp_unscalarizable_region
= unscalarizable_region
;
927 if (TREE_CODE (expr
) == COMPONENT_REF
928 && DECL_NONADDRESSABLE_P (TREE_OPERAND (expr
, 1)))
929 access
->non_addressable
= 1;
935 /* Return true iff TYPE is a RECORD_TYPE with fields that are either of gimple
936 register types or (recursively) records with only these two kinds of fields.
937 It also returns false if any of these records contains a bit-field. */
940 type_consists_of_records_p (tree type
)
944 if (TREE_CODE (type
) != RECORD_TYPE
)
947 for (fld
= TYPE_FIELDS (type
); fld
; fld
= DECL_CHAIN (fld
))
948 if (TREE_CODE (fld
) == FIELD_DECL
)
950 tree ft
= TREE_TYPE (fld
);
952 if (DECL_BIT_FIELD (fld
))
955 if (!is_gimple_reg_type (ft
)
956 && !type_consists_of_records_p (ft
))
963 /* Create total_scalarization accesses for all scalar type fields in DECL that
964 must be of a RECORD_TYPE conforming to type_consists_of_records_p. BASE
965 must be the top-most VAR_DECL representing the variable, OFFSET must be the
966 offset of DECL within BASE. REF must be the memory reference expression for
970 completely_scalarize_record (tree base
, tree decl
, HOST_WIDE_INT offset
,
973 tree fld
, decl_type
= TREE_TYPE (decl
);
975 for (fld
= TYPE_FIELDS (decl_type
); fld
; fld
= DECL_CHAIN (fld
))
976 if (TREE_CODE (fld
) == FIELD_DECL
)
978 HOST_WIDE_INT pos
= offset
+ int_bit_position (fld
);
979 tree ft
= TREE_TYPE (fld
);
980 tree nref
= build3 (COMPONENT_REF
, TREE_TYPE (fld
), ref
, fld
,
983 if (is_gimple_reg_type (ft
))
985 struct access
*access
;
988 size
= tree_to_uhwi (DECL_SIZE (fld
));
989 access
= create_access_1 (base
, pos
, size
);
992 access
->grp_total_scalarization
= 1;
993 /* Accesses for intraprocedural SRA can have their stmt NULL. */
996 completely_scalarize_record (base
, fld
, pos
, nref
);
1000 /* Create total_scalarization accesses for all scalar type fields in VAR and
1001 for VAR a a whole. VAR must be of a RECORD_TYPE conforming to
1002 type_consists_of_records_p. */
1005 completely_scalarize_var (tree var
)
1007 HOST_WIDE_INT size
= tree_to_uhwi (DECL_SIZE (var
));
1008 struct access
*access
;
1010 access
= create_access_1 (var
, 0, size
);
1012 access
->type
= TREE_TYPE (var
);
1013 access
->grp_total_scalarization
= 1;
1015 completely_scalarize_record (var
, var
, 0, var
);
1018 /* Return true if REF has an VIEW_CONVERT_EXPR somewhere in it. */
1021 contains_view_convert_expr_p (const_tree ref
)
1023 while (handled_component_p (ref
))
1025 if (TREE_CODE (ref
) == VIEW_CONVERT_EXPR
)
1027 ref
= TREE_OPERAND (ref
, 0);
1033 /* Search the given tree for a declaration by skipping handled components and
1034 exclude it from the candidates. */
1037 disqualify_base_of_expr (tree t
, const char *reason
)
1039 t
= get_base_address (t
);
1040 if (sra_mode
== SRA_MODE_EARLY_IPA
1041 && TREE_CODE (t
) == MEM_REF
)
1042 t
= get_ssa_base_param (TREE_OPERAND (t
, 0));
1044 if (t
&& DECL_P (t
))
1045 disqualify_candidate (t
, reason
);
1048 /* Scan expression EXPR and create access structures for all accesses to
1049 candidates for scalarization. Return the created access or NULL if none is
1052 static struct access
*
1053 build_access_from_expr_1 (tree expr
, gimple stmt
, bool write
)
1055 struct access
*ret
= NULL
;
1058 if (TREE_CODE (expr
) == BIT_FIELD_REF
1059 || TREE_CODE (expr
) == IMAGPART_EXPR
1060 || TREE_CODE (expr
) == REALPART_EXPR
)
1062 expr
= TREE_OPERAND (expr
, 0);
1066 partial_ref
= false;
1068 /* We need to dive through V_C_Es in order to get the size of its parameter
1069 and not the result type. Ada produces such statements. We are also
1070 capable of handling the topmost V_C_E but not any of those buried in other
1071 handled components. */
1072 if (TREE_CODE (expr
) == VIEW_CONVERT_EXPR
)
1073 expr
= TREE_OPERAND (expr
, 0);
1075 if (contains_view_convert_expr_p (expr
))
1077 disqualify_base_of_expr (expr
, "V_C_E under a different handled "
1081 if (TREE_THIS_VOLATILE (expr
))
1083 disqualify_base_of_expr (expr
, "part of a volatile reference.");
1087 switch (TREE_CODE (expr
))
1090 if (TREE_CODE (TREE_OPERAND (expr
, 0)) != ADDR_EXPR
1091 && sra_mode
!= SRA_MODE_EARLY_IPA
)
1099 case ARRAY_RANGE_REF
:
1100 ret
= create_access (expr
, stmt
, write
);
1107 if (write
&& partial_ref
&& ret
)
1108 ret
->grp_partial_lhs
= 1;
1113 /* Scan expression EXPR and create access structures for all accesses to
1114 candidates for scalarization. Return true if any access has been inserted.
1115 STMT must be the statement from which the expression is taken, WRITE must be
1116 true if the expression is a store and false otherwise. */
1119 build_access_from_expr (tree expr
, gimple stmt
, bool write
)
1121 struct access
*access
;
1123 access
= build_access_from_expr_1 (expr
, stmt
, write
);
1126 /* This means the aggregate is accesses as a whole in a way other than an
1127 assign statement and thus cannot be removed even if we had a scalar
1128 replacement for everything. */
1129 if (cannot_scalarize_away_bitmap
)
1130 bitmap_set_bit (cannot_scalarize_away_bitmap
, DECL_UID (access
->base
));
1136 /* Return the single non-EH successor edge of BB or NULL if there is none or
1140 single_non_eh_succ (basic_block bb
)
1145 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1146 if (!(e
->flags
& EDGE_EH
))
1156 /* Disqualify LHS and RHS for scalarization if STMT has to terminate its BB and
1157 there is no alternative spot where to put statements SRA might need to
1158 generate after it. The spot we are looking for is an edge leading to a
1159 single non-EH successor, if it exists and is indeed single. RHS may be
1160 NULL, in that case ignore it. */
1163 disqualify_if_bad_bb_terminating_stmt (gimple stmt
, tree lhs
, tree rhs
)
1165 if ((sra_mode
== SRA_MODE_EARLY_INTRA
|| sra_mode
== SRA_MODE_INTRA
)
1166 && stmt_ends_bb_p (stmt
))
1168 if (single_non_eh_succ (gimple_bb (stmt
)))
1171 disqualify_base_of_expr (lhs
, "LHS of a throwing stmt.");
1173 disqualify_base_of_expr (rhs
, "RHS of a throwing stmt.");
1179 /* Scan expressions occurring in STMT, create access structures for all accesses
1180 to candidates for scalarization and remove those candidates which occur in
1181 statements or expressions that prevent them from being split apart. Return
1182 true if any access has been inserted. */
1185 build_accesses_from_assign (gimple stmt
)
1188 struct access
*lacc
, *racc
;
1190 if (!gimple_assign_single_p (stmt
)
1191 /* Scope clobbers don't influence scalarization. */
1192 || gimple_clobber_p (stmt
))
1195 lhs
= gimple_assign_lhs (stmt
);
1196 rhs
= gimple_assign_rhs1 (stmt
);
1198 if (disqualify_if_bad_bb_terminating_stmt (stmt
, lhs
, rhs
))
1201 racc
= build_access_from_expr_1 (rhs
, stmt
, false);
1202 lacc
= build_access_from_expr_1 (lhs
, stmt
, true);
1205 lacc
->grp_assignment_write
= 1;
1209 racc
->grp_assignment_read
= 1;
1210 if (should_scalarize_away_bitmap
&& !gimple_has_volatile_ops (stmt
)
1211 && !is_gimple_reg_type (racc
->type
))
1212 bitmap_set_bit (should_scalarize_away_bitmap
, DECL_UID (racc
->base
));
1216 && (sra_mode
== SRA_MODE_EARLY_INTRA
|| sra_mode
== SRA_MODE_INTRA
)
1217 && !lacc
->grp_unscalarizable_region
1218 && !racc
->grp_unscalarizable_region
1219 && AGGREGATE_TYPE_P (TREE_TYPE (lhs
))
1220 && lacc
->size
== racc
->size
1221 && useless_type_conversion_p (lacc
->type
, racc
->type
))
1223 struct assign_link
*link
;
1225 link
= (struct assign_link
*) pool_alloc (link_pool
);
1226 memset (link
, 0, sizeof (struct assign_link
));
1231 add_link_to_rhs (racc
, link
);
1234 return lacc
|| racc
;
1237 /* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine
1238 GIMPLE_ASM operands with memory constrains which cannot be scalarized. */
1241 asm_visit_addr (gimple
, tree op
, tree
, void *)
1243 op
= get_base_address (op
);
1246 disqualify_candidate (op
, "Non-scalarizable GIMPLE_ASM operand.");
1251 /* Return true iff callsite CALL has at least as many actual arguments as there
1252 are formal parameters of the function currently processed by IPA-SRA and
1253 that their types match. */
1256 callsite_arguments_match_p (gimple call
)
1258 if (gimple_call_num_args (call
) < (unsigned) func_param_count
)
1263 for (parm
= DECL_ARGUMENTS (current_function_decl
), i
= 0;
1265 parm
= DECL_CHAIN (parm
), i
++)
1267 tree arg
= gimple_call_arg (call
, i
);
1268 if (!useless_type_conversion_p (TREE_TYPE (parm
), TREE_TYPE (arg
)))
1274 /* Scan function and look for interesting expressions and create access
1275 structures for them. Return true iff any access is created. */
1278 scan_function (void)
1283 FOR_EACH_BB_FN (bb
, cfun
)
1285 gimple_stmt_iterator gsi
;
1286 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
1288 gimple stmt
= gsi_stmt (gsi
);
1292 if (final_bbs
&& stmt_can_throw_external (stmt
))
1293 bitmap_set_bit (final_bbs
, bb
->index
);
1294 switch (gimple_code (stmt
))
1297 t
= gimple_return_retval (as_a
<greturn
*> (stmt
));
1299 ret
|= build_access_from_expr (t
, stmt
, false);
1301 bitmap_set_bit (final_bbs
, bb
->index
);
1305 ret
|= build_accesses_from_assign (stmt
);
1309 for (i
= 0; i
< gimple_call_num_args (stmt
); i
++)
1310 ret
|= build_access_from_expr (gimple_call_arg (stmt
, i
),
1313 if (sra_mode
== SRA_MODE_EARLY_IPA
)
1315 tree dest
= gimple_call_fndecl (stmt
);
1316 int flags
= gimple_call_flags (stmt
);
1320 if (DECL_BUILT_IN_CLASS (dest
) == BUILT_IN_NORMAL
1321 && DECL_FUNCTION_CODE (dest
) == BUILT_IN_APPLY_ARGS
)
1322 encountered_apply_args
= true;
1323 if (recursive_call_p (current_function_decl
, dest
))
1325 encountered_recursive_call
= true;
1326 if (!callsite_arguments_match_p (stmt
))
1327 encountered_unchangable_recursive_call
= true;
1332 && (flags
& (ECF_CONST
| ECF_PURE
)) == 0)
1333 bitmap_set_bit (final_bbs
, bb
->index
);
1336 t
= gimple_call_lhs (stmt
);
1337 if (t
&& !disqualify_if_bad_bb_terminating_stmt (stmt
, t
, NULL
))
1338 ret
|= build_access_from_expr (t
, stmt
, true);
1343 gasm
*asm_stmt
= as_a
<gasm
*> (stmt
);
1344 walk_stmt_load_store_addr_ops (asm_stmt
, NULL
, NULL
, NULL
,
1347 bitmap_set_bit (final_bbs
, bb
->index
);
1349 for (i
= 0; i
< gimple_asm_ninputs (asm_stmt
); i
++)
1351 t
= TREE_VALUE (gimple_asm_input_op (asm_stmt
, i
));
1352 ret
|= build_access_from_expr (t
, asm_stmt
, false);
1354 for (i
= 0; i
< gimple_asm_noutputs (asm_stmt
); i
++)
1356 t
= TREE_VALUE (gimple_asm_output_op (asm_stmt
, i
));
1357 ret
|= build_access_from_expr (t
, asm_stmt
, true);
1371 /* Helper of QSORT function. There are pointers to accesses in the array. An
1372 access is considered smaller than another if it has smaller offset or if the
1373 offsets are the same but is size is bigger. */
1376 compare_access_positions (const void *a
, const void *b
)
1378 const access_p
*fp1
= (const access_p
*) a
;
1379 const access_p
*fp2
= (const access_p
*) b
;
1380 const access_p f1
= *fp1
;
1381 const access_p f2
= *fp2
;
1383 if (f1
->offset
!= f2
->offset
)
1384 return f1
->offset
< f2
->offset
? -1 : 1;
1386 if (f1
->size
== f2
->size
)
1388 if (f1
->type
== f2
->type
)
1390 /* Put any non-aggregate type before any aggregate type. */
1391 else if (!is_gimple_reg_type (f1
->type
)
1392 && is_gimple_reg_type (f2
->type
))
1394 else if (is_gimple_reg_type (f1
->type
)
1395 && !is_gimple_reg_type (f2
->type
))
1397 /* Put any complex or vector type before any other scalar type. */
1398 else if (TREE_CODE (f1
->type
) != COMPLEX_TYPE
1399 && TREE_CODE (f1
->type
) != VECTOR_TYPE
1400 && (TREE_CODE (f2
->type
) == COMPLEX_TYPE
1401 || TREE_CODE (f2
->type
) == VECTOR_TYPE
))
1403 else if ((TREE_CODE (f1
->type
) == COMPLEX_TYPE
1404 || TREE_CODE (f1
->type
) == VECTOR_TYPE
)
1405 && TREE_CODE (f2
->type
) != COMPLEX_TYPE
1406 && TREE_CODE (f2
->type
) != VECTOR_TYPE
)
1408 /* Put the integral type with the bigger precision first. */
1409 else if (INTEGRAL_TYPE_P (f1
->type
)
1410 && INTEGRAL_TYPE_P (f2
->type
))
1411 return TYPE_PRECISION (f2
->type
) - TYPE_PRECISION (f1
->type
);
1412 /* Put any integral type with non-full precision last. */
1413 else if (INTEGRAL_TYPE_P (f1
->type
)
1414 && (TREE_INT_CST_LOW (TYPE_SIZE (f1
->type
))
1415 != TYPE_PRECISION (f1
->type
)))
1417 else if (INTEGRAL_TYPE_P (f2
->type
)
1418 && (TREE_INT_CST_LOW (TYPE_SIZE (f2
->type
))
1419 != TYPE_PRECISION (f2
->type
)))
1421 /* Stabilize the sort. */
1422 return TYPE_UID (f1
->type
) - TYPE_UID (f2
->type
);
1425 /* We want the bigger accesses first, thus the opposite operator in the next
1427 return f1
->size
> f2
->size
? -1 : 1;
1431 /* Append a name of the declaration to the name obstack. A helper function for
1435 make_fancy_decl_name (tree decl
)
1439 tree name
= DECL_NAME (decl
);
1441 obstack_grow (&name_obstack
, IDENTIFIER_POINTER (name
),
1442 IDENTIFIER_LENGTH (name
));
1445 sprintf (buffer
, "D%u", DECL_UID (decl
));
1446 obstack_grow (&name_obstack
, buffer
, strlen (buffer
));
1450 /* Helper for make_fancy_name. */
1453 make_fancy_name_1 (tree expr
)
1460 make_fancy_decl_name (expr
);
1464 switch (TREE_CODE (expr
))
1467 make_fancy_name_1 (TREE_OPERAND (expr
, 0));
1468 obstack_1grow (&name_obstack
, '$');
1469 make_fancy_decl_name (TREE_OPERAND (expr
, 1));
1473 make_fancy_name_1 (TREE_OPERAND (expr
, 0));
1474 obstack_1grow (&name_obstack
, '$');
1475 /* Arrays with only one element may not have a constant as their
1477 index
= TREE_OPERAND (expr
, 1);
1478 if (TREE_CODE (index
) != INTEGER_CST
)
1480 sprintf (buffer
, HOST_WIDE_INT_PRINT_DEC
, TREE_INT_CST_LOW (index
));
1481 obstack_grow (&name_obstack
, buffer
, strlen (buffer
));
1485 make_fancy_name_1 (TREE_OPERAND (expr
, 0));
1489 make_fancy_name_1 (TREE_OPERAND (expr
, 0));
1490 if (!integer_zerop (TREE_OPERAND (expr
, 1)))
1492 obstack_1grow (&name_obstack
, '$');
1493 sprintf (buffer
, HOST_WIDE_INT_PRINT_DEC
,
1494 TREE_INT_CST_LOW (TREE_OPERAND (expr
, 1)));
1495 obstack_grow (&name_obstack
, buffer
, strlen (buffer
));
1502 gcc_unreachable (); /* we treat these as scalars. */
1509 /* Create a human readable name for replacement variable of ACCESS. */
1512 make_fancy_name (tree expr
)
1514 make_fancy_name_1 (expr
);
1515 obstack_1grow (&name_obstack
, '\0');
1516 return XOBFINISH (&name_obstack
, char *);
1519 /* Construct a MEM_REF that would reference a part of aggregate BASE of type
1520 EXP_TYPE at the given OFFSET. If BASE is something for which
1521 get_addr_base_and_unit_offset returns NULL, gsi must be non-NULL and is used
1522 to insert new statements either before or below the current one as specified
1523 by INSERT_AFTER. This function is not capable of handling bitfields.
1525 BASE must be either a declaration or a memory reference that has correct
1526 alignment ifformation embeded in it (e.g. a pre-existing one in SRA). */
1529 build_ref_for_offset (location_t loc
, tree base
, HOST_WIDE_INT offset
,
1530 tree exp_type
, gimple_stmt_iterator
*gsi
,
1533 tree prev_base
= base
;
1536 HOST_WIDE_INT base_offset
;
1537 unsigned HOST_WIDE_INT misalign
;
1540 gcc_checking_assert (offset
% BITS_PER_UNIT
== 0);
1541 get_object_alignment_1 (base
, &align
, &misalign
);
1542 base
= get_addr_base_and_unit_offset (base
, &base_offset
);
1544 /* get_addr_base_and_unit_offset returns NULL for references with a variable
1545 offset such as array[var_index]. */
1551 gcc_checking_assert (gsi
);
1552 tmp
= make_ssa_name (build_pointer_type (TREE_TYPE (prev_base
)));
1553 addr
= build_fold_addr_expr (unshare_expr (prev_base
));
1554 STRIP_USELESS_TYPE_CONVERSION (addr
);
1555 stmt
= gimple_build_assign (tmp
, addr
);
1556 gimple_set_location (stmt
, loc
);
1558 gsi_insert_after (gsi
, stmt
, GSI_NEW_STMT
);
1560 gsi_insert_before (gsi
, stmt
, GSI_SAME_STMT
);
1562 off
= build_int_cst (reference_alias_ptr_type (prev_base
),
1563 offset
/ BITS_PER_UNIT
);
1566 else if (TREE_CODE (base
) == MEM_REF
)
1568 off
= build_int_cst (TREE_TYPE (TREE_OPERAND (base
, 1)),
1569 base_offset
+ offset
/ BITS_PER_UNIT
);
1570 off
= int_const_binop (PLUS_EXPR
, TREE_OPERAND (base
, 1), off
);
1571 base
= unshare_expr (TREE_OPERAND (base
, 0));
1575 off
= build_int_cst (reference_alias_ptr_type (base
),
1576 base_offset
+ offset
/ BITS_PER_UNIT
);
1577 base
= build_fold_addr_expr (unshare_expr (base
));
1580 misalign
= (misalign
+ offset
) & (align
- 1);
1582 align
= (misalign
& -misalign
);
1583 if (align
< TYPE_ALIGN (exp_type
))
1584 exp_type
= build_aligned_type (exp_type
, align
);
1586 mem_ref
= fold_build2_loc (loc
, MEM_REF
, exp_type
, base
, off
);
1587 if (TREE_THIS_VOLATILE (prev_base
))
1588 TREE_THIS_VOLATILE (mem_ref
) = 1;
1589 if (TREE_SIDE_EFFECTS (prev_base
))
1590 TREE_SIDE_EFFECTS (mem_ref
) = 1;
1594 /* Construct a memory reference to a part of an aggregate BASE at the given
1595 OFFSET and of the same type as MODEL. In case this is a reference to a
1596 bit-field, the function will replicate the last component_ref of model's
1597 expr to access it. GSI and INSERT_AFTER have the same meaning as in
1598 build_ref_for_offset. */
1601 build_ref_for_model (location_t loc
, tree base
, HOST_WIDE_INT offset
,
1602 struct access
*model
, gimple_stmt_iterator
*gsi
,
1605 if (TREE_CODE (model
->expr
) == COMPONENT_REF
1606 && DECL_BIT_FIELD (TREE_OPERAND (model
->expr
, 1)))
1608 /* This access represents a bit-field. */
1609 tree t
, exp_type
, fld
= TREE_OPERAND (model
->expr
, 1);
1611 offset
-= int_bit_position (fld
);
1612 exp_type
= TREE_TYPE (TREE_OPERAND (model
->expr
, 0));
1613 t
= build_ref_for_offset (loc
, base
, offset
, exp_type
, gsi
, insert_after
);
1614 return fold_build3_loc (loc
, COMPONENT_REF
, TREE_TYPE (fld
), t
, fld
,
1618 return build_ref_for_offset (loc
, base
, offset
, model
->type
,
1622 /* Attempt to build a memory reference that we could but into a gimple
1623 debug_bind statement. Similar to build_ref_for_model but punts if it has to
1624 create statements and return s NULL instead. This function also ignores
1625 alignment issues and so its results should never end up in non-debug
1629 build_debug_ref_for_model (location_t loc
, tree base
, HOST_WIDE_INT offset
,
1630 struct access
*model
)
1632 HOST_WIDE_INT base_offset
;
1635 if (TREE_CODE (model
->expr
) == COMPONENT_REF
1636 && DECL_BIT_FIELD (TREE_OPERAND (model
->expr
, 1)))
1639 base
= get_addr_base_and_unit_offset (base
, &base_offset
);
1642 if (TREE_CODE (base
) == MEM_REF
)
1644 off
= build_int_cst (TREE_TYPE (TREE_OPERAND (base
, 1)),
1645 base_offset
+ offset
/ BITS_PER_UNIT
);
1646 off
= int_const_binop (PLUS_EXPR
, TREE_OPERAND (base
, 1), off
);
1647 base
= unshare_expr (TREE_OPERAND (base
, 0));
1651 off
= build_int_cst (reference_alias_ptr_type (base
),
1652 base_offset
+ offset
/ BITS_PER_UNIT
);
1653 base
= build_fold_addr_expr (unshare_expr (base
));
1656 return fold_build2_loc (loc
, MEM_REF
, model
->type
, base
, off
);
1659 /* Construct a memory reference consisting of component_refs and array_refs to
1660 a part of an aggregate *RES (which is of type TYPE). The requested part
1661 should have type EXP_TYPE at be the given OFFSET. This function might not
1662 succeed, it returns true when it does and only then *RES points to something
1663 meaningful. This function should be used only to build expressions that we
1664 might need to present to user (e.g. in warnings). In all other situations,
1665 build_ref_for_model or build_ref_for_offset should be used instead. */
1668 build_user_friendly_ref_for_offset (tree
*res
, tree type
, HOST_WIDE_INT offset
,
1674 tree tr_size
, index
, minidx
;
1675 HOST_WIDE_INT el_size
;
1677 if (offset
== 0 && exp_type
1678 && types_compatible_p (exp_type
, type
))
1681 switch (TREE_CODE (type
))
1684 case QUAL_UNION_TYPE
:
1686 for (fld
= TYPE_FIELDS (type
); fld
; fld
= DECL_CHAIN (fld
))
1688 HOST_WIDE_INT pos
, size
;
1689 tree tr_pos
, expr
, *expr_ptr
;
1691 if (TREE_CODE (fld
) != FIELD_DECL
)
1694 tr_pos
= bit_position (fld
);
1695 if (!tr_pos
|| !tree_fits_uhwi_p (tr_pos
))
1697 pos
= tree_to_uhwi (tr_pos
);
1698 gcc_assert (TREE_CODE (type
) == RECORD_TYPE
|| pos
== 0);
1699 tr_size
= DECL_SIZE (fld
);
1700 if (!tr_size
|| !tree_fits_uhwi_p (tr_size
))
1702 size
= tree_to_uhwi (tr_size
);
1708 else if (pos
> offset
|| (pos
+ size
) <= offset
)
1711 expr
= build3 (COMPONENT_REF
, TREE_TYPE (fld
), *res
, fld
,
1714 if (build_user_friendly_ref_for_offset (expr_ptr
, TREE_TYPE (fld
),
1715 offset
- pos
, exp_type
))
1724 tr_size
= TYPE_SIZE (TREE_TYPE (type
));
1725 if (!tr_size
|| !tree_fits_uhwi_p (tr_size
))
1727 el_size
= tree_to_uhwi (tr_size
);
1729 minidx
= TYPE_MIN_VALUE (TYPE_DOMAIN (type
));
1730 if (TREE_CODE (minidx
) != INTEGER_CST
|| el_size
== 0)
1732 index
= build_int_cst (TYPE_DOMAIN (type
), offset
/ el_size
);
1733 if (!integer_zerop (minidx
))
1734 index
= int_const_binop (PLUS_EXPR
, index
, minidx
);
1735 *res
= build4 (ARRAY_REF
, TREE_TYPE (type
), *res
, index
,
1736 NULL_TREE
, NULL_TREE
);
1737 offset
= offset
% el_size
;
1738 type
= TREE_TYPE (type
);
1753 /* Return true iff TYPE is stdarg va_list type. */
1756 is_va_list_type (tree type
)
1758 return TYPE_MAIN_VARIANT (type
) == TYPE_MAIN_VARIANT (va_list_type_node
);
1761 /* Print message to dump file why a variable was rejected. */
1764 reject (tree var
, const char *msg
)
1766 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1768 fprintf (dump_file
, "Rejected (%d): %s: ", DECL_UID (var
), msg
);
1769 print_generic_expr (dump_file
, var
, 0);
1770 fprintf (dump_file
, "\n");
1774 /* Return true if VAR is a candidate for SRA. */
1777 maybe_add_sra_candidate (tree var
)
1779 tree type
= TREE_TYPE (var
);
1783 if (!AGGREGATE_TYPE_P (type
))
1785 reject (var
, "not aggregate");
1788 if (needs_to_live_in_memory (var
))
1790 reject (var
, "needs to live in memory");
1793 if (TREE_THIS_VOLATILE (var
))
1795 reject (var
, "is volatile");
1798 if (!COMPLETE_TYPE_P (type
))
1800 reject (var
, "has incomplete type");
1803 if (!tree_fits_uhwi_p (TYPE_SIZE (type
)))
1805 reject (var
, "type size not fixed");
1808 if (tree_to_uhwi (TYPE_SIZE (type
)) == 0)
1810 reject (var
, "type size is zero");
1813 if (type_internals_preclude_sra_p (type
, &msg
))
1818 if (/* Fix for PR 41089. tree-stdarg.c needs to have va_lists intact but
1819 we also want to schedule it rather late. Thus we ignore it in
1821 (sra_mode
== SRA_MODE_EARLY_INTRA
1822 && is_va_list_type (type
)))
1824 reject (var
, "is va_list");
1828 bitmap_set_bit (candidate_bitmap
, DECL_UID (var
));
1829 slot
= candidates
->find_slot_with_hash (var
, DECL_UID (var
), INSERT
);
1832 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1834 fprintf (dump_file
, "Candidate (%d): ", DECL_UID (var
));
1835 print_generic_expr (dump_file
, var
, 0);
1836 fprintf (dump_file
, "\n");
1842 /* The very first phase of intraprocedural SRA. It marks in candidate_bitmap
1843 those with type which is suitable for scalarization. */
1846 find_var_candidates (void)
1852 for (parm
= DECL_ARGUMENTS (current_function_decl
);
1854 parm
= DECL_CHAIN (parm
))
1855 ret
|= maybe_add_sra_candidate (parm
);
1857 FOR_EACH_LOCAL_DECL (cfun
, i
, var
)
1859 if (TREE_CODE (var
) != VAR_DECL
)
1862 ret
|= maybe_add_sra_candidate (var
);
1868 /* Sort all accesses for the given variable, check for partial overlaps and
1869 return NULL if there are any. If there are none, pick a representative for
1870 each combination of offset and size and create a linked list out of them.
1871 Return the pointer to the first representative and make sure it is the first
1872 one in the vector of accesses. */
1874 static struct access
*
1875 sort_and_splice_var_accesses (tree var
)
1877 int i
, j
, access_count
;
1878 struct access
*res
, **prev_acc_ptr
= &res
;
1879 vec
<access_p
> *access_vec
;
1881 HOST_WIDE_INT low
= -1, high
= 0;
1883 access_vec
= get_base_access_vector (var
);
1886 access_count
= access_vec
->length ();
1888 /* Sort by <OFFSET, SIZE>. */
1889 access_vec
->qsort (compare_access_positions
);
1892 while (i
< access_count
)
1894 struct access
*access
= (*access_vec
)[i
];
1895 bool grp_write
= access
->write
;
1896 bool grp_read
= !access
->write
;
1897 bool grp_scalar_write
= access
->write
1898 && is_gimple_reg_type (access
->type
);
1899 bool grp_scalar_read
= !access
->write
1900 && is_gimple_reg_type (access
->type
);
1901 bool grp_assignment_read
= access
->grp_assignment_read
;
1902 bool grp_assignment_write
= access
->grp_assignment_write
;
1903 bool multiple_scalar_reads
= false;
1904 bool total_scalarization
= access
->grp_total_scalarization
;
1905 bool grp_partial_lhs
= access
->grp_partial_lhs
;
1906 bool first_scalar
= is_gimple_reg_type (access
->type
);
1907 bool unscalarizable_region
= access
->grp_unscalarizable_region
;
1909 if (first
|| access
->offset
>= high
)
1912 low
= access
->offset
;
1913 high
= access
->offset
+ access
->size
;
1915 else if (access
->offset
> low
&& access
->offset
+ access
->size
> high
)
1918 gcc_assert (access
->offset
>= low
1919 && access
->offset
+ access
->size
<= high
);
1922 while (j
< access_count
)
1924 struct access
*ac2
= (*access_vec
)[j
];
1925 if (ac2
->offset
!= access
->offset
|| ac2
->size
!= access
->size
)
1930 grp_scalar_write
= (grp_scalar_write
1931 || is_gimple_reg_type (ac2
->type
));
1936 if (is_gimple_reg_type (ac2
->type
))
1938 if (grp_scalar_read
)
1939 multiple_scalar_reads
= true;
1941 grp_scalar_read
= true;
1944 grp_assignment_read
|= ac2
->grp_assignment_read
;
1945 grp_assignment_write
|= ac2
->grp_assignment_write
;
1946 grp_partial_lhs
|= ac2
->grp_partial_lhs
;
1947 unscalarizable_region
|= ac2
->grp_unscalarizable_region
;
1948 total_scalarization
|= ac2
->grp_total_scalarization
;
1949 relink_to_new_repr (access
, ac2
);
1951 /* If there are both aggregate-type and scalar-type accesses with
1952 this combination of size and offset, the comparison function
1953 should have put the scalars first. */
1954 gcc_assert (first_scalar
|| !is_gimple_reg_type (ac2
->type
));
1955 ac2
->group_representative
= access
;
1961 access
->group_representative
= access
;
1962 access
->grp_write
= grp_write
;
1963 access
->grp_read
= grp_read
;
1964 access
->grp_scalar_read
= grp_scalar_read
;
1965 access
->grp_scalar_write
= grp_scalar_write
;
1966 access
->grp_assignment_read
= grp_assignment_read
;
1967 access
->grp_assignment_write
= grp_assignment_write
;
1968 access
->grp_hint
= multiple_scalar_reads
|| total_scalarization
;
1969 access
->grp_total_scalarization
= total_scalarization
;
1970 access
->grp_partial_lhs
= grp_partial_lhs
;
1971 access
->grp_unscalarizable_region
= unscalarizable_region
;
1972 if (access
->first_link
)
1973 add_access_to_work_queue (access
);
1975 *prev_acc_ptr
= access
;
1976 prev_acc_ptr
= &access
->next_grp
;
1979 gcc_assert (res
== (*access_vec
)[0]);
1983 /* Create a variable for the given ACCESS which determines the type, name and a
1984 few other properties. Return the variable declaration and store it also to
1985 ACCESS->replacement. */
1988 create_access_replacement (struct access
*access
)
1992 if (access
->grp_to_be_debug_replaced
)
1994 repl
= create_tmp_var_raw (access
->type
);
1995 DECL_CONTEXT (repl
) = current_function_decl
;
1998 repl
= create_tmp_var (access
->type
, "SR");
1999 if (TREE_CODE (access
->type
) == COMPLEX_TYPE
2000 || TREE_CODE (access
->type
) == VECTOR_TYPE
)
2002 if (!access
->grp_partial_lhs
)
2003 DECL_GIMPLE_REG_P (repl
) = 1;
2005 else if (access
->grp_partial_lhs
2006 && is_gimple_reg_type (access
->type
))
2007 TREE_ADDRESSABLE (repl
) = 1;
2009 DECL_SOURCE_LOCATION (repl
) = DECL_SOURCE_LOCATION (access
->base
);
2010 DECL_ARTIFICIAL (repl
) = 1;
2011 DECL_IGNORED_P (repl
) = DECL_IGNORED_P (access
->base
);
2013 if (DECL_NAME (access
->base
)
2014 && !DECL_IGNORED_P (access
->base
)
2015 && !DECL_ARTIFICIAL (access
->base
))
2017 char *pretty_name
= make_fancy_name (access
->expr
);
2018 tree debug_expr
= unshare_expr_without_location (access
->expr
), d
;
2021 DECL_NAME (repl
) = get_identifier (pretty_name
);
2022 obstack_free (&name_obstack
, pretty_name
);
2024 /* Get rid of any SSA_NAMEs embedded in debug_expr,
2025 as DECL_DEBUG_EXPR isn't considered when looking for still
2026 used SSA_NAMEs and thus they could be freed. All debug info
2027 generation cares is whether something is constant or variable
2028 and that get_ref_base_and_extent works properly on the
2029 expression. It cannot handle accesses at a non-constant offset
2030 though, so just give up in those cases. */
2031 for (d
= debug_expr
;
2032 !fail
&& (handled_component_p (d
) || TREE_CODE (d
) == MEM_REF
);
2033 d
= TREE_OPERAND (d
, 0))
2034 switch (TREE_CODE (d
))
2037 case ARRAY_RANGE_REF
:
2038 if (TREE_OPERAND (d
, 1)
2039 && TREE_CODE (TREE_OPERAND (d
, 1)) != INTEGER_CST
)
2041 if (TREE_OPERAND (d
, 3)
2042 && TREE_CODE (TREE_OPERAND (d
, 3)) != INTEGER_CST
)
2046 if (TREE_OPERAND (d
, 2)
2047 && TREE_CODE (TREE_OPERAND (d
, 2)) != INTEGER_CST
)
2051 if (TREE_CODE (TREE_OPERAND (d
, 0)) != ADDR_EXPR
)
2054 d
= TREE_OPERAND (d
, 0);
2061 SET_DECL_DEBUG_EXPR (repl
, debug_expr
);
2062 DECL_HAS_DEBUG_EXPR_P (repl
) = 1;
2064 if (access
->grp_no_warning
)
2065 TREE_NO_WARNING (repl
) = 1;
2067 TREE_NO_WARNING (repl
) = TREE_NO_WARNING (access
->base
);
2070 TREE_NO_WARNING (repl
) = 1;
2074 if (access
->grp_to_be_debug_replaced
)
2076 fprintf (dump_file
, "Created a debug-only replacement for ");
2077 print_generic_expr (dump_file
, access
->base
, 0);
2078 fprintf (dump_file
, " offset: %u, size: %u\n",
2079 (unsigned) access
->offset
, (unsigned) access
->size
);
2083 fprintf (dump_file
, "Created a replacement for ");
2084 print_generic_expr (dump_file
, access
->base
, 0);
2085 fprintf (dump_file
, " offset: %u, size: %u: ",
2086 (unsigned) access
->offset
, (unsigned) access
->size
);
2087 print_generic_expr (dump_file
, repl
, 0);
2088 fprintf (dump_file
, "\n");
2091 sra_stats
.replacements
++;
2096 /* Return ACCESS scalar replacement, create it if it does not exist yet. */
2099 get_access_replacement (struct access
*access
)
2101 gcc_checking_assert (access
->replacement_decl
);
2102 return access
->replacement_decl
;
2106 /* Build a subtree of accesses rooted in *ACCESS, and move the pointer in the
2107 linked list along the way. Stop when *ACCESS is NULL or the access pointed
2108 to it is not "within" the root. Return false iff some accesses partially
2112 build_access_subtree (struct access
**access
)
2114 struct access
*root
= *access
, *last_child
= NULL
;
2115 HOST_WIDE_INT limit
= root
->offset
+ root
->size
;
2117 *access
= (*access
)->next_grp
;
2118 while (*access
&& (*access
)->offset
+ (*access
)->size
<= limit
)
2121 root
->first_child
= *access
;
2123 last_child
->next_sibling
= *access
;
2124 last_child
= *access
;
2126 if (!build_access_subtree (access
))
2130 if (*access
&& (*access
)->offset
< limit
)
2136 /* Build a tree of access representatives, ACCESS is the pointer to the first
2137 one, others are linked in a list by the next_grp field. Return false iff
2138 some accesses partially overlap. */
2141 build_access_trees (struct access
*access
)
2145 struct access
*root
= access
;
2147 if (!build_access_subtree (&access
))
2149 root
->next_grp
= access
;
2154 /* Return true if expr contains some ARRAY_REFs into a variable bounded
2158 expr_with_var_bounded_array_refs_p (tree expr
)
2160 while (handled_component_p (expr
))
2162 if (TREE_CODE (expr
) == ARRAY_REF
2163 && !tree_fits_shwi_p (array_ref_low_bound (expr
)))
2165 expr
= TREE_OPERAND (expr
, 0);
2170 /* Analyze the subtree of accesses rooted in ROOT, scheduling replacements when
2171 both seeming beneficial and when ALLOW_REPLACEMENTS allows it. Also set all
2172 sorts of access flags appropriately along the way, notably always set
2173 grp_read and grp_assign_read according to MARK_READ and grp_write when
2176 Creating a replacement for a scalar access is considered beneficial if its
2177 grp_hint is set (this means we are either attempting total scalarization or
2178 there is more than one direct read access) or according to the following
2181 Access written to through a scalar type (once or more times)
2183 | Written to in an assignment statement
2185 | | Access read as scalar _once_
2187 | | | Read in an assignment statement
2189 | | | | Scalarize Comment
2190 -----------------------------------------------------------------------------
2191 0 0 0 0 No access for the scalar
2192 0 0 0 1 No access for the scalar
2193 0 0 1 0 No Single read - won't help
2194 0 0 1 1 No The same case
2195 0 1 0 0 No access for the scalar
2196 0 1 0 1 No access for the scalar
2197 0 1 1 0 Yes s = *g; return s.i;
2198 0 1 1 1 Yes The same case as above
2199 1 0 0 0 No Won't help
2200 1 0 0 1 Yes s.i = 1; *g = s;
2201 1 0 1 0 Yes s.i = 5; g = s.i;
2202 1 0 1 1 Yes The same case as above
2203 1 1 0 0 No Won't help.
2204 1 1 0 1 Yes s.i = 1; *g = s;
2205 1 1 1 0 Yes s = *g; return s.i;
2206 1 1 1 1 Yes Any of the above yeses */
2209 analyze_access_subtree (struct access
*root
, struct access
*parent
,
2210 bool allow_replacements
)
2212 struct access
*child
;
2213 HOST_WIDE_INT limit
= root
->offset
+ root
->size
;
2214 HOST_WIDE_INT covered_to
= root
->offset
;
2215 bool scalar
= is_gimple_reg_type (root
->type
);
2216 bool hole
= false, sth_created
= false;
2220 if (parent
->grp_read
)
2222 if (parent
->grp_assignment_read
)
2223 root
->grp_assignment_read
= 1;
2224 if (parent
->grp_write
)
2225 root
->grp_write
= 1;
2226 if (parent
->grp_assignment_write
)
2227 root
->grp_assignment_write
= 1;
2228 if (parent
->grp_total_scalarization
)
2229 root
->grp_total_scalarization
= 1;
2232 if (root
->grp_unscalarizable_region
)
2233 allow_replacements
= false;
2235 if (allow_replacements
&& expr_with_var_bounded_array_refs_p (root
->expr
))
2236 allow_replacements
= false;
2238 for (child
= root
->first_child
; child
; child
= child
->next_sibling
)
2240 hole
|= covered_to
< child
->offset
;
2241 sth_created
|= analyze_access_subtree (child
, root
,
2242 allow_replacements
&& !scalar
);
2244 root
->grp_unscalarized_data
|= child
->grp_unscalarized_data
;
2245 root
->grp_total_scalarization
&= child
->grp_total_scalarization
;
2246 if (child
->grp_covered
)
2247 covered_to
+= child
->size
;
2252 if (allow_replacements
&& scalar
&& !root
->first_child
2254 || ((root
->grp_scalar_read
|| root
->grp_assignment_read
)
2255 && (root
->grp_scalar_write
|| root
->grp_assignment_write
))))
2257 /* Always create access replacements that cover the whole access.
2258 For integral types this means the precision has to match.
2259 Avoid assumptions based on the integral type kind, too. */
2260 if (INTEGRAL_TYPE_P (root
->type
)
2261 && (TREE_CODE (root
->type
) != INTEGER_TYPE
2262 || TYPE_PRECISION (root
->type
) != root
->size
)
2263 /* But leave bitfield accesses alone. */
2264 && (TREE_CODE (root
->expr
) != COMPONENT_REF
2265 || !DECL_BIT_FIELD (TREE_OPERAND (root
->expr
, 1))))
2267 tree rt
= root
->type
;
2268 gcc_assert ((root
->offset
% BITS_PER_UNIT
) == 0
2269 && (root
->size
% BITS_PER_UNIT
) == 0);
2270 root
->type
= build_nonstandard_integer_type (root
->size
,
2271 TYPE_UNSIGNED (rt
));
2272 root
->expr
= build_ref_for_offset (UNKNOWN_LOCATION
,
2273 root
->base
, root
->offset
,
2274 root
->type
, NULL
, false);
2276 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2278 fprintf (dump_file
, "Changing the type of a replacement for ");
2279 print_generic_expr (dump_file
, root
->base
, 0);
2280 fprintf (dump_file
, " offset: %u, size: %u ",
2281 (unsigned) root
->offset
, (unsigned) root
->size
);
2282 fprintf (dump_file
, " to an integer.\n");
2286 root
->grp_to_be_replaced
= 1;
2287 root
->replacement_decl
= create_access_replacement (root
);
2293 if (allow_replacements
2294 && scalar
&& !root
->first_child
2295 && (root
->grp_scalar_write
|| root
->grp_assignment_write
)
2296 && !bitmap_bit_p (cannot_scalarize_away_bitmap
,
2297 DECL_UID (root
->base
)))
2299 gcc_checking_assert (!root
->grp_scalar_read
2300 && !root
->grp_assignment_read
);
2302 if (MAY_HAVE_DEBUG_STMTS
)
2304 root
->grp_to_be_debug_replaced
= 1;
2305 root
->replacement_decl
= create_access_replacement (root
);
2309 if (covered_to
< limit
)
2312 root
->grp_total_scalarization
= 0;
2315 if (!hole
|| root
->grp_total_scalarization
)
2316 root
->grp_covered
= 1;
2317 else if (root
->grp_write
|| TREE_CODE (root
->base
) == PARM_DECL
)
2318 root
->grp_unscalarized_data
= 1; /* not covered and written to */
2322 /* Analyze all access trees linked by next_grp by the means of
2323 analyze_access_subtree. */
2325 analyze_access_trees (struct access
*access
)
2331 if (analyze_access_subtree (access
, NULL
, true))
2333 access
= access
->next_grp
;
2339 /* Return true iff a potential new child of LACC at offset OFFSET and with size
2340 SIZE would conflict with an already existing one. If exactly such a child
2341 already exists in LACC, store a pointer to it in EXACT_MATCH. */
2344 child_would_conflict_in_lacc (struct access
*lacc
, HOST_WIDE_INT norm_offset
,
2345 HOST_WIDE_INT size
, struct access
**exact_match
)
2347 struct access
*child
;
2349 for (child
= lacc
->first_child
; child
; child
= child
->next_sibling
)
2351 if (child
->offset
== norm_offset
&& child
->size
== size
)
2353 *exact_match
= child
;
2357 if (child
->offset
< norm_offset
+ size
2358 && child
->offset
+ child
->size
> norm_offset
)
2365 /* Create a new child access of PARENT, with all properties just like MODEL
2366 except for its offset and with its grp_write false and grp_read true.
2367 Return the new access or NULL if it cannot be created. Note that this access
2368 is created long after all splicing and sorting, it's not located in any
2369 access vector and is automatically a representative of its group. */
2371 static struct access
*
2372 create_artificial_child_access (struct access
*parent
, struct access
*model
,
2373 HOST_WIDE_INT new_offset
)
2375 struct access
*access
;
2376 struct access
**child
;
2377 tree expr
= parent
->base
;
2379 gcc_assert (!model
->grp_unscalarizable_region
);
2381 access
= (struct access
*) pool_alloc (access_pool
);
2382 memset (access
, 0, sizeof (struct access
));
2383 if (!build_user_friendly_ref_for_offset (&expr
, TREE_TYPE (expr
), new_offset
,
2386 access
->grp_no_warning
= true;
2387 expr
= build_ref_for_model (EXPR_LOCATION (parent
->base
), parent
->base
,
2388 new_offset
, model
, NULL
, false);
2391 access
->base
= parent
->base
;
2392 access
->expr
= expr
;
2393 access
->offset
= new_offset
;
2394 access
->size
= model
->size
;
2395 access
->type
= model
->type
;
2396 access
->grp_write
= true;
2397 access
->grp_read
= false;
2399 child
= &parent
->first_child
;
2400 while (*child
&& (*child
)->offset
< new_offset
)
2401 child
= &(*child
)->next_sibling
;
2403 access
->next_sibling
= *child
;
2410 /* Propagate all subaccesses of RACC across an assignment link to LACC. Return
2411 true if any new subaccess was created. Additionally, if RACC is a scalar
2412 access but LACC is not, change the type of the latter, if possible. */
2415 propagate_subaccesses_across_link (struct access
*lacc
, struct access
*racc
)
2417 struct access
*rchild
;
2418 HOST_WIDE_INT norm_delta
= lacc
->offset
- racc
->offset
;
2421 if (is_gimple_reg_type (lacc
->type
)
2422 || lacc
->grp_unscalarizable_region
2423 || racc
->grp_unscalarizable_region
)
2426 if (is_gimple_reg_type (racc
->type
))
2428 if (!lacc
->first_child
&& !racc
->first_child
)
2430 tree t
= lacc
->base
;
2432 lacc
->type
= racc
->type
;
2433 if (build_user_friendly_ref_for_offset (&t
, TREE_TYPE (t
),
2434 lacc
->offset
, racc
->type
))
2438 lacc
->expr
= build_ref_for_model (EXPR_LOCATION (lacc
->base
),
2439 lacc
->base
, lacc
->offset
,
2441 lacc
->grp_no_warning
= true;
2447 for (rchild
= racc
->first_child
; rchild
; rchild
= rchild
->next_sibling
)
2449 struct access
*new_acc
= NULL
;
2450 HOST_WIDE_INT norm_offset
= rchild
->offset
+ norm_delta
;
2452 if (rchild
->grp_unscalarizable_region
)
2455 if (child_would_conflict_in_lacc (lacc
, norm_offset
, rchild
->size
,
2460 rchild
->grp_hint
= 1;
2461 new_acc
->grp_hint
|= new_acc
->grp_read
;
2462 if (rchild
->first_child
)
2463 ret
|= propagate_subaccesses_across_link (new_acc
, rchild
);
2468 rchild
->grp_hint
= 1;
2469 new_acc
= create_artificial_child_access (lacc
, rchild
, norm_offset
);
2473 if (racc
->first_child
)
2474 propagate_subaccesses_across_link (new_acc
, rchild
);
2481 /* Propagate all subaccesses across assignment links. */
2484 propagate_all_subaccesses (void)
2486 while (work_queue_head
)
2488 struct access
*racc
= pop_access_from_work_queue ();
2489 struct assign_link
*link
;
2491 gcc_assert (racc
->first_link
);
2493 for (link
= racc
->first_link
; link
; link
= link
->next
)
2495 struct access
*lacc
= link
->lacc
;
2497 if (!bitmap_bit_p (candidate_bitmap
, DECL_UID (lacc
->base
)))
2499 lacc
= lacc
->group_representative
;
2500 if (propagate_subaccesses_across_link (lacc
, racc
)
2501 && lacc
->first_link
)
2502 add_access_to_work_queue (lacc
);
2507 /* Go through all accesses collected throughout the (intraprocedural) analysis
2508 stage, exclude overlapping ones, identify representatives and build trees
2509 out of them, making decisions about scalarization on the way. Return true
2510 iff there are any to-be-scalarized variables after this stage. */
2513 analyze_all_variable_accesses (void)
2516 bitmap tmp
= BITMAP_ALLOC (NULL
);
2519 unsigned max_scalarization_size
2520 = (optimize_function_for_size_p (cfun
)
2521 ? PARAM_VALUE (PARAM_SRA_MAX_SCALARIZATION_SIZE_SIZE
)
2522 : PARAM_VALUE (PARAM_SRA_MAX_SCALARIZATION_SIZE_SPEED
))
2525 EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap
, 0, i
, bi
)
2526 if (bitmap_bit_p (should_scalarize_away_bitmap
, i
)
2527 && !bitmap_bit_p (cannot_scalarize_away_bitmap
, i
))
2529 tree var
= candidate (i
);
2531 if (TREE_CODE (var
) == VAR_DECL
2532 && type_consists_of_records_p (TREE_TYPE (var
)))
2534 if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (var
)))
2535 <= max_scalarization_size
)
2537 completely_scalarize_var (var
);
2538 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2540 fprintf (dump_file
, "Will attempt to totally scalarize ");
2541 print_generic_expr (dump_file
, var
, 0);
2542 fprintf (dump_file
, " (UID: %u): \n", DECL_UID (var
));
2545 else if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2547 fprintf (dump_file
, "Too big to totally scalarize: ");
2548 print_generic_expr (dump_file
, var
, 0);
2549 fprintf (dump_file
, " (UID: %u)\n", DECL_UID (var
));
2554 bitmap_copy (tmp
, candidate_bitmap
);
2555 EXECUTE_IF_SET_IN_BITMAP (tmp
, 0, i
, bi
)
2557 tree var
= candidate (i
);
2558 struct access
*access
;
2560 access
= sort_and_splice_var_accesses (var
);
2561 if (!access
|| !build_access_trees (access
))
2562 disqualify_candidate (var
,
2563 "No or inhibitingly overlapping accesses.");
2566 propagate_all_subaccesses ();
2568 bitmap_copy (tmp
, candidate_bitmap
);
2569 EXECUTE_IF_SET_IN_BITMAP (tmp
, 0, i
, bi
)
2571 tree var
= candidate (i
);
2572 struct access
*access
= get_first_repr_for_decl (var
);
2574 if (analyze_access_trees (access
))
2577 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2579 fprintf (dump_file
, "\nAccess trees for ");
2580 print_generic_expr (dump_file
, var
, 0);
2581 fprintf (dump_file
, " (UID: %u): \n", DECL_UID (var
));
2582 dump_access_tree (dump_file
, access
);
2583 fprintf (dump_file
, "\n");
2587 disqualify_candidate (var
, "No scalar replacements to be created.");
2594 statistics_counter_event (cfun
, "Scalarized aggregates", res
);
2601 /* Generate statements copying scalar replacements of accesses within a subtree
2602 into or out of AGG. ACCESS, all its children, siblings and their children
2603 are to be processed. AGG is an aggregate type expression (can be a
2604 declaration but does not have to be, it can for example also be a mem_ref or
2605 a series of handled components). TOP_OFFSET is the offset of the processed
2606 subtree which has to be subtracted from offsets of individual accesses to
2607 get corresponding offsets for AGG. If CHUNK_SIZE is non-null, copy only
2608 replacements in the interval <start_offset, start_offset + chunk_size>,
2609 otherwise copy all. GSI is a statement iterator used to place the new
2610 statements. WRITE should be true when the statements should write from AGG
2611 to the replacement and false if vice versa. if INSERT_AFTER is true, new
2612 statements will be added after the current statement in GSI, they will be
2613 added before the statement otherwise. */
2616 generate_subtree_copies (struct access
*access
, tree agg
,
2617 HOST_WIDE_INT top_offset
,
2618 HOST_WIDE_INT start_offset
, HOST_WIDE_INT chunk_size
,
2619 gimple_stmt_iterator
*gsi
, bool write
,
2620 bool insert_after
, location_t loc
)
2624 if (chunk_size
&& access
->offset
>= start_offset
+ chunk_size
)
2627 if (access
->grp_to_be_replaced
2629 || access
->offset
+ access
->size
> start_offset
))
2631 tree expr
, repl
= get_access_replacement (access
);
2634 expr
= build_ref_for_model (loc
, agg
, access
->offset
- top_offset
,
2635 access
, gsi
, insert_after
);
2639 if (access
->grp_partial_lhs
)
2640 expr
= force_gimple_operand_gsi (gsi
, expr
, true, NULL_TREE
,
2642 insert_after
? GSI_NEW_STMT
2644 stmt
= gimple_build_assign (repl
, expr
);
2648 TREE_NO_WARNING (repl
) = 1;
2649 if (access
->grp_partial_lhs
)
2650 repl
= force_gimple_operand_gsi (gsi
, repl
, true, NULL_TREE
,
2652 insert_after
? GSI_NEW_STMT
2654 stmt
= gimple_build_assign (expr
, repl
);
2656 gimple_set_location (stmt
, loc
);
2659 gsi_insert_after (gsi
, stmt
, GSI_NEW_STMT
);
2661 gsi_insert_before (gsi
, stmt
, GSI_SAME_STMT
);
2663 sra_stats
.subtree_copies
++;
2666 && access
->grp_to_be_debug_replaced
2668 || access
->offset
+ access
->size
> start_offset
))
2671 tree drhs
= build_debug_ref_for_model (loc
, agg
,
2672 access
->offset
- top_offset
,
2674 ds
= gimple_build_debug_bind (get_access_replacement (access
),
2675 drhs
, gsi_stmt (*gsi
));
2677 gsi_insert_after (gsi
, ds
, GSI_NEW_STMT
);
2679 gsi_insert_before (gsi
, ds
, GSI_SAME_STMT
);
2682 if (access
->first_child
)
2683 generate_subtree_copies (access
->first_child
, agg
, top_offset
,
2684 start_offset
, chunk_size
, gsi
,
2685 write
, insert_after
, loc
);
2687 access
= access
->next_sibling
;
2692 /* Assign zero to all scalar replacements in an access subtree. ACCESS is the
2693 the root of the subtree to be processed. GSI is the statement iterator used
2694 for inserting statements which are added after the current statement if
2695 INSERT_AFTER is true or before it otherwise. */
2698 init_subtree_with_zero (struct access
*access
, gimple_stmt_iterator
*gsi
,
2699 bool insert_after
, location_t loc
)
2702 struct access
*child
;
2704 if (access
->grp_to_be_replaced
)
2708 stmt
= gimple_build_assign (get_access_replacement (access
),
2709 build_zero_cst (access
->type
));
2711 gsi_insert_after (gsi
, stmt
, GSI_NEW_STMT
);
2713 gsi_insert_before (gsi
, stmt
, GSI_SAME_STMT
);
2715 gimple_set_location (stmt
, loc
);
2717 else if (access
->grp_to_be_debug_replaced
)
2720 = gimple_build_debug_bind (get_access_replacement (access
),
2721 build_zero_cst (access
->type
),
2724 gsi_insert_after (gsi
, ds
, GSI_NEW_STMT
);
2726 gsi_insert_before (gsi
, ds
, GSI_SAME_STMT
);
2729 for (child
= access
->first_child
; child
; child
= child
->next_sibling
)
2730 init_subtree_with_zero (child
, gsi
, insert_after
, loc
);
2733 /* Clobber all scalar replacements in an access subtree. ACCESS is the the
2734 root of the subtree to be processed. GSI is the statement iterator used
2735 for inserting statements which are added after the current statement if
2736 INSERT_AFTER is true or before it otherwise. */
2739 clobber_subtree (struct access
*access
, gimple_stmt_iterator
*gsi
,
2740 bool insert_after
, location_t loc
)
2743 struct access
*child
;
2745 if (access
->grp_to_be_replaced
)
2747 tree rep
= get_access_replacement (access
);
2748 tree clobber
= build_constructor (access
->type
, NULL
);
2749 TREE_THIS_VOLATILE (clobber
) = 1;
2750 gimple stmt
= gimple_build_assign (rep
, clobber
);
2753 gsi_insert_after (gsi
, stmt
, GSI_NEW_STMT
);
2755 gsi_insert_before (gsi
, stmt
, GSI_SAME_STMT
);
2757 gimple_set_location (stmt
, loc
);
2760 for (child
= access
->first_child
; child
; child
= child
->next_sibling
)
2761 clobber_subtree (child
, gsi
, insert_after
, loc
);
2764 /* Search for an access representative for the given expression EXPR and
2765 return it or NULL if it cannot be found. */
2767 static struct access
*
2768 get_access_for_expr (tree expr
)
2770 HOST_WIDE_INT offset
, size
, max_size
;
2773 /* FIXME: This should not be necessary but Ada produces V_C_Es with a type of
2774 a different size than the size of its argument and we need the latter
2776 if (TREE_CODE (expr
) == VIEW_CONVERT_EXPR
)
2777 expr
= TREE_OPERAND (expr
, 0);
2779 base
= get_ref_base_and_extent (expr
, &offset
, &size
, &max_size
);
2780 if (max_size
== -1 || !DECL_P (base
))
2783 if (!bitmap_bit_p (candidate_bitmap
, DECL_UID (base
)))
2786 return get_var_base_offset_size_access (base
, offset
, max_size
);
2789 /* Replace the expression EXPR with a scalar replacement if there is one and
2790 generate other statements to do type conversion or subtree copying if
2791 necessary. GSI is used to place newly created statements, WRITE is true if
2792 the expression is being written to (it is on a LHS of a statement or output
2793 in an assembly statement). */
2796 sra_modify_expr (tree
*expr
, gimple_stmt_iterator
*gsi
, bool write
)
2799 struct access
*access
;
2800 tree type
, bfr
, orig_expr
;
2802 if (TREE_CODE (*expr
) == BIT_FIELD_REF
)
2805 expr
= &TREE_OPERAND (*expr
, 0);
2810 if (TREE_CODE (*expr
) == REALPART_EXPR
|| TREE_CODE (*expr
) == IMAGPART_EXPR
)
2811 expr
= &TREE_OPERAND (*expr
, 0);
2812 access
= get_access_for_expr (*expr
);
2815 type
= TREE_TYPE (*expr
);
2818 loc
= gimple_location (gsi_stmt (*gsi
));
2819 gimple_stmt_iterator alt_gsi
= gsi_none ();
2820 if (write
&& stmt_ends_bb_p (gsi_stmt (*gsi
)))
2822 alt_gsi
= gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi
)));
2826 if (access
->grp_to_be_replaced
)
2828 tree repl
= get_access_replacement (access
);
2829 /* If we replace a non-register typed access simply use the original
2830 access expression to extract the scalar component afterwards.
2831 This happens if scalarizing a function return value or parameter
2832 like in gcc.c-torture/execute/20041124-1.c, 20050316-1.c and
2833 gcc.c-torture/compile/20011217-1.c.
2835 We also want to use this when accessing a complex or vector which can
2836 be accessed as a different type too, potentially creating a need for
2837 type conversion (see PR42196) and when scalarized unions are involved
2838 in assembler statements (see PR42398). */
2839 if (!useless_type_conversion_p (type
, access
->type
))
2843 ref
= build_ref_for_model (loc
, orig_expr
, 0, access
, gsi
, false);
2849 if (access
->grp_partial_lhs
)
2850 ref
= force_gimple_operand_gsi (gsi
, ref
, true, NULL_TREE
,
2851 false, GSI_NEW_STMT
);
2852 stmt
= gimple_build_assign (repl
, ref
);
2853 gimple_set_location (stmt
, loc
);
2854 gsi_insert_after (gsi
, stmt
, GSI_NEW_STMT
);
2860 if (access
->grp_partial_lhs
)
2861 repl
= force_gimple_operand_gsi (gsi
, repl
, true, NULL_TREE
,
2862 true, GSI_SAME_STMT
);
2863 stmt
= gimple_build_assign (ref
, repl
);
2864 gimple_set_location (stmt
, loc
);
2865 gsi_insert_before (gsi
, stmt
, GSI_SAME_STMT
);
2872 else if (write
&& access
->grp_to_be_debug_replaced
)
2874 gdebug
*ds
= gimple_build_debug_bind (get_access_replacement (access
),
2877 gsi_insert_after (gsi
, ds
, GSI_NEW_STMT
);
2880 if (access
->first_child
)
2882 HOST_WIDE_INT start_offset
, chunk_size
;
2884 && tree_fits_uhwi_p (TREE_OPERAND (bfr
, 1))
2885 && tree_fits_uhwi_p (TREE_OPERAND (bfr
, 2)))
2887 chunk_size
= tree_to_uhwi (TREE_OPERAND (bfr
, 1));
2888 start_offset
= access
->offset
2889 + tree_to_uhwi (TREE_OPERAND (bfr
, 2));
2892 start_offset
= chunk_size
= 0;
2894 generate_subtree_copies (access
->first_child
, orig_expr
, access
->offset
,
2895 start_offset
, chunk_size
, gsi
, write
, write
,
2901 /* Where scalar replacements of the RHS have been written to when a replacement
2902 of a LHS of an assigments cannot be direclty loaded from a replacement of
2904 enum unscalarized_data_handling
{ SRA_UDH_NONE
, /* Nothing done so far. */
2905 SRA_UDH_RIGHT
, /* Data flushed to the RHS. */
2906 SRA_UDH_LEFT
}; /* Data flushed to the LHS. */
2908 struct subreplacement_assignment_data
2910 /* Offset of the access representing the lhs of the assignment. */
2911 HOST_WIDE_INT left_offset
;
2913 /* LHS and RHS of the original assignment. */
2914 tree assignment_lhs
, assignment_rhs
;
2916 /* Access representing the rhs of the whole assignment. */
2917 struct access
*top_racc
;
2919 /* Stmt iterator used for statement insertions after the original assignment.
2920 It points to the main GSI used to traverse a BB during function body
2922 gimple_stmt_iterator
*new_gsi
;
2924 /* Stmt iterator used for statement insertions before the original
2925 assignment. Keeps on pointing to the original statement. */
2926 gimple_stmt_iterator old_gsi
;
2928 /* Location of the assignment. */
2931 /* Keeps the information whether we have needed to refresh replacements of
2932 the LHS and from which side of the assignments this takes place. */
2933 enum unscalarized_data_handling refreshed
;
2936 /* Store all replacements in the access tree rooted in TOP_RACC either to their
2937 base aggregate if there are unscalarized data or directly to LHS of the
2938 statement that is pointed to by GSI otherwise. */
2941 handle_unscalarized_data_in_subtree (struct subreplacement_assignment_data
*sad
)
2944 if (sad
->top_racc
->grp_unscalarized_data
)
2946 src
= sad
->assignment_rhs
;
2947 sad
->refreshed
= SRA_UDH_RIGHT
;
2951 src
= sad
->assignment_lhs
;
2952 sad
->refreshed
= SRA_UDH_LEFT
;
2954 generate_subtree_copies (sad
->top_racc
->first_child
, src
,
2955 sad
->top_racc
->offset
, 0, 0,
2956 &sad
->old_gsi
, false, false, sad
->loc
);
2959 /* Try to generate statements to load all sub-replacements in an access subtree
2960 formed by children of LACC from scalar replacements in the SAD->top_racc
2961 subtree. If that is not possible, refresh the SAD->top_racc base aggregate
2962 and load the accesses from it. */
2965 load_assign_lhs_subreplacements (struct access
*lacc
,
2966 struct subreplacement_assignment_data
*sad
)
2968 for (lacc
= lacc
->first_child
; lacc
; lacc
= lacc
->next_sibling
)
2970 HOST_WIDE_INT offset
;
2971 offset
= lacc
->offset
- sad
->left_offset
+ sad
->top_racc
->offset
;
2973 if (lacc
->grp_to_be_replaced
)
2975 struct access
*racc
;
2979 racc
= find_access_in_subtree (sad
->top_racc
, offset
, lacc
->size
);
2980 if (racc
&& racc
->grp_to_be_replaced
)
2982 rhs
= get_access_replacement (racc
);
2983 if (!useless_type_conversion_p (lacc
->type
, racc
->type
))
2984 rhs
= fold_build1_loc (sad
->loc
, VIEW_CONVERT_EXPR
,
2987 if (racc
->grp_partial_lhs
&& lacc
->grp_partial_lhs
)
2988 rhs
= force_gimple_operand_gsi (&sad
->old_gsi
, rhs
, true,
2989 NULL_TREE
, true, GSI_SAME_STMT
);
2993 /* No suitable access on the right hand side, need to load from
2994 the aggregate. See if we have to update it first... */
2995 if (sad
->refreshed
== SRA_UDH_NONE
)
2996 handle_unscalarized_data_in_subtree (sad
);
2998 if (sad
->refreshed
== SRA_UDH_LEFT
)
2999 rhs
= build_ref_for_model (sad
->loc
, sad
->assignment_lhs
,
3000 lacc
->offset
- sad
->left_offset
,
3001 lacc
, sad
->new_gsi
, true);
3003 rhs
= build_ref_for_model (sad
->loc
, sad
->assignment_rhs
,
3004 lacc
->offset
- sad
->left_offset
,
3005 lacc
, sad
->new_gsi
, true);
3006 if (lacc
->grp_partial_lhs
)
3007 rhs
= force_gimple_operand_gsi (sad
->new_gsi
,
3008 rhs
, true, NULL_TREE
,
3009 false, GSI_NEW_STMT
);
3012 stmt
= gimple_build_assign (get_access_replacement (lacc
), rhs
);
3013 gsi_insert_after (sad
->new_gsi
, stmt
, GSI_NEW_STMT
);
3014 gimple_set_location (stmt
, sad
->loc
);
3016 sra_stats
.subreplacements
++;
3020 if (sad
->refreshed
== SRA_UDH_NONE
3021 && lacc
->grp_read
&& !lacc
->grp_covered
)
3022 handle_unscalarized_data_in_subtree (sad
);
3024 if (lacc
&& lacc
->grp_to_be_debug_replaced
)
3028 struct access
*racc
= find_access_in_subtree (sad
->top_racc
,
3032 if (racc
&& racc
->grp_to_be_replaced
)
3034 if (racc
->grp_write
)
3035 drhs
= get_access_replacement (racc
);
3039 else if (sad
->refreshed
== SRA_UDH_LEFT
)
3040 drhs
= build_debug_ref_for_model (sad
->loc
, lacc
->base
,
3041 lacc
->offset
, lacc
);
3042 else if (sad
->refreshed
== SRA_UDH_RIGHT
)
3043 drhs
= build_debug_ref_for_model (sad
->loc
, sad
->top_racc
->base
,
3048 && !useless_type_conversion_p (lacc
->type
, TREE_TYPE (drhs
)))
3049 drhs
= fold_build1_loc (sad
->loc
, VIEW_CONVERT_EXPR
,
3051 ds
= gimple_build_debug_bind (get_access_replacement (lacc
),
3052 drhs
, gsi_stmt (sad
->old_gsi
));
3053 gsi_insert_after (sad
->new_gsi
, ds
, GSI_NEW_STMT
);
3057 if (lacc
->first_child
)
3058 load_assign_lhs_subreplacements (lacc
, sad
);
3062 /* Result code for SRA assignment modification. */
3063 enum assignment_mod_result
{ SRA_AM_NONE
, /* nothing done for the stmt */
3064 SRA_AM_MODIFIED
, /* stmt changed but not
3066 SRA_AM_REMOVED
}; /* stmt eliminated */
3068 /* Modify assignments with a CONSTRUCTOR on their RHS. STMT contains a pointer
3069 to the assignment and GSI is the statement iterator pointing at it. Returns
3070 the same values as sra_modify_assign. */
3072 static enum assignment_mod_result
3073 sra_modify_constructor_assign (gimple stmt
, gimple_stmt_iterator
*gsi
)
3075 tree lhs
= gimple_assign_lhs (stmt
);
3076 struct access
*acc
= get_access_for_expr (lhs
);
3079 location_t loc
= gimple_location (stmt
);
3081 if (gimple_clobber_p (stmt
))
3083 /* Clobber the replacement variable. */
3084 clobber_subtree (acc
, gsi
, !acc
->grp_covered
, loc
);
3085 /* Remove clobbers of fully scalarized variables, they are dead. */
3086 if (acc
->grp_covered
)
3088 unlink_stmt_vdef (stmt
);
3089 gsi_remove (gsi
, true);
3090 release_defs (stmt
);
3091 return SRA_AM_REMOVED
;
3094 return SRA_AM_MODIFIED
;
3097 if (vec_safe_length (CONSTRUCTOR_ELTS (gimple_assign_rhs1 (stmt
))) > 0)
3099 /* I have never seen this code path trigger but if it can happen the
3100 following should handle it gracefully. */
3101 if (access_has_children_p (acc
))
3102 generate_subtree_copies (acc
->first_child
, lhs
, acc
->offset
, 0, 0, gsi
,
3104 return SRA_AM_MODIFIED
;
3107 if (acc
->grp_covered
)
3109 init_subtree_with_zero (acc
, gsi
, false, loc
);
3110 unlink_stmt_vdef (stmt
);
3111 gsi_remove (gsi
, true);
3112 release_defs (stmt
);
3113 return SRA_AM_REMOVED
;
3117 init_subtree_with_zero (acc
, gsi
, true, loc
);
3118 return SRA_AM_MODIFIED
;
3122 /* Create and return a new suitable default definition SSA_NAME for RACC which
3123 is an access describing an uninitialized part of an aggregate that is being
3127 get_repl_default_def_ssa_name (struct access
*racc
)
3129 gcc_checking_assert (!racc
->grp_to_be_replaced
3130 && !racc
->grp_to_be_debug_replaced
);
3131 if (!racc
->replacement_decl
)
3132 racc
->replacement_decl
= create_access_replacement (racc
);
3133 return get_or_create_ssa_default_def (cfun
, racc
->replacement_decl
);
3136 /* Return true if REF has an VIEW_CONVERT_EXPR or a COMPONENT_REF with a
3137 bit-field field declaration somewhere in it. */
3140 contains_vce_or_bfcref_p (const_tree ref
)
3142 while (handled_component_p (ref
))
3144 if (TREE_CODE (ref
) == VIEW_CONVERT_EXPR
3145 || (TREE_CODE (ref
) == COMPONENT_REF
3146 && DECL_BIT_FIELD (TREE_OPERAND (ref
, 1))))
3148 ref
= TREE_OPERAND (ref
, 0);
3154 /* Examine both sides of the assignment statement pointed to by STMT, replace
3155 them with a scalare replacement if there is one and generate copying of
3156 replacements if scalarized aggregates have been used in the assignment. GSI
3157 is used to hold generated statements for type conversions and subtree
3160 static enum assignment_mod_result
3161 sra_modify_assign (gimple stmt
, gimple_stmt_iterator
*gsi
)
3163 struct access
*lacc
, *racc
;
3165 bool modify_this_stmt
= false;
3166 bool force_gimple_rhs
= false;
3168 gimple_stmt_iterator orig_gsi
= *gsi
;
3170 if (!gimple_assign_single_p (stmt
))
3172 lhs
= gimple_assign_lhs (stmt
);
3173 rhs
= gimple_assign_rhs1 (stmt
);
3175 if (TREE_CODE (rhs
) == CONSTRUCTOR
)
3176 return sra_modify_constructor_assign (stmt
, gsi
);
3178 if (TREE_CODE (rhs
) == REALPART_EXPR
|| TREE_CODE (lhs
) == REALPART_EXPR
3179 || TREE_CODE (rhs
) == IMAGPART_EXPR
|| TREE_CODE (lhs
) == IMAGPART_EXPR
3180 || TREE_CODE (rhs
) == BIT_FIELD_REF
|| TREE_CODE (lhs
) == BIT_FIELD_REF
)
3182 modify_this_stmt
= sra_modify_expr (gimple_assign_rhs1_ptr (stmt
),
3184 modify_this_stmt
|= sra_modify_expr (gimple_assign_lhs_ptr (stmt
),
3186 return modify_this_stmt
? SRA_AM_MODIFIED
: SRA_AM_NONE
;
3189 lacc
= get_access_for_expr (lhs
);
3190 racc
= get_access_for_expr (rhs
);
3194 loc
= gimple_location (stmt
);
3195 if (lacc
&& lacc
->grp_to_be_replaced
)
3197 lhs
= get_access_replacement (lacc
);
3198 gimple_assign_set_lhs (stmt
, lhs
);
3199 modify_this_stmt
= true;
3200 if (lacc
->grp_partial_lhs
)
3201 force_gimple_rhs
= true;
3205 if (racc
&& racc
->grp_to_be_replaced
)
3207 rhs
= get_access_replacement (racc
);
3208 modify_this_stmt
= true;
3209 if (racc
->grp_partial_lhs
)
3210 force_gimple_rhs
= true;
3214 && !racc
->grp_unscalarized_data
3215 && TREE_CODE (lhs
) == SSA_NAME
3216 && !access_has_replacements_p (racc
))
3218 rhs
= get_repl_default_def_ssa_name (racc
);
3219 modify_this_stmt
= true;
3223 if (modify_this_stmt
)
3225 if (!useless_type_conversion_p (TREE_TYPE (lhs
), TREE_TYPE (rhs
)))
3227 /* If we can avoid creating a VIEW_CONVERT_EXPR do so.
3228 ??? This should move to fold_stmt which we simply should
3229 call after building a VIEW_CONVERT_EXPR here. */
3230 if (AGGREGATE_TYPE_P (TREE_TYPE (lhs
))
3231 && !contains_bitfld_component_ref_p (lhs
))
3233 lhs
= build_ref_for_model (loc
, lhs
, 0, racc
, gsi
, false);
3234 gimple_assign_set_lhs (stmt
, lhs
);
3236 else if (AGGREGATE_TYPE_P (TREE_TYPE (rhs
))
3237 && !contains_vce_or_bfcref_p (rhs
))
3238 rhs
= build_ref_for_model (loc
, rhs
, 0, lacc
, gsi
, false);
3240 if (!useless_type_conversion_p (TREE_TYPE (lhs
), TREE_TYPE (rhs
)))
3242 rhs
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, TREE_TYPE (lhs
),
3244 if (is_gimple_reg_type (TREE_TYPE (lhs
))
3245 && TREE_CODE (lhs
) != SSA_NAME
)
3246 force_gimple_rhs
= true;
3251 if (lacc
&& lacc
->grp_to_be_debug_replaced
)
3253 tree dlhs
= get_access_replacement (lacc
);
3254 tree drhs
= unshare_expr (rhs
);
3255 if (!useless_type_conversion_p (TREE_TYPE (dlhs
), TREE_TYPE (drhs
)))
3257 if (AGGREGATE_TYPE_P (TREE_TYPE (drhs
))
3258 && !contains_vce_or_bfcref_p (drhs
))
3259 drhs
= build_debug_ref_for_model (loc
, drhs
, 0, lacc
);
3261 && !useless_type_conversion_p (TREE_TYPE (dlhs
),
3263 drhs
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
,
3264 TREE_TYPE (dlhs
), drhs
);
3266 gdebug
*ds
= gimple_build_debug_bind (dlhs
, drhs
, stmt
);
3267 gsi_insert_before (gsi
, ds
, GSI_SAME_STMT
);
3270 /* From this point on, the function deals with assignments in between
3271 aggregates when at least one has scalar reductions of some of its
3272 components. There are three possible scenarios: Both the LHS and RHS have
3273 to-be-scalarized components, 2) only the RHS has or 3) only the LHS has.
3275 In the first case, we would like to load the LHS components from RHS
3276 components whenever possible. If that is not possible, we would like to
3277 read it directly from the RHS (after updating it by storing in it its own
3278 components). If there are some necessary unscalarized data in the LHS,
3279 those will be loaded by the original assignment too. If neither of these
3280 cases happen, the original statement can be removed. Most of this is done
3281 by load_assign_lhs_subreplacements.
3283 In the second case, we would like to store all RHS scalarized components
3284 directly into LHS and if they cover the aggregate completely, remove the
3285 statement too. In the third case, we want the LHS components to be loaded
3286 directly from the RHS (DSE will remove the original statement if it
3289 This is a bit complex but manageable when types match and when unions do
3290 not cause confusion in a way that we cannot really load a component of LHS
3291 from the RHS or vice versa (the access representing this level can have
3292 subaccesses that are accessible only through a different union field at a
3293 higher level - different from the one used in the examined expression).
3296 Therefore, I specially handle a fourth case, happening when there is a
3297 specific type cast or it is impossible to locate a scalarized subaccess on
3298 the other side of the expression. If that happens, I simply "refresh" the
3299 RHS by storing in it is scalarized components leave the original statement
3300 there to do the copying and then load the scalar replacements of the LHS.
3301 This is what the first branch does. */
3303 if (modify_this_stmt
3304 || gimple_has_volatile_ops (stmt
)
3305 || contains_vce_or_bfcref_p (rhs
)
3306 || contains_vce_or_bfcref_p (lhs
)
3307 || stmt_ends_bb_p (stmt
))
3309 if (access_has_children_p (racc
))
3310 generate_subtree_copies (racc
->first_child
, rhs
, racc
->offset
, 0, 0,
3311 gsi
, false, false, loc
);
3312 if (access_has_children_p (lacc
))
3314 gimple_stmt_iterator alt_gsi
= gsi_none ();
3315 if (stmt_ends_bb_p (stmt
))
3317 alt_gsi
= gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi
)));
3320 generate_subtree_copies (lacc
->first_child
, lhs
, lacc
->offset
, 0, 0,
3321 gsi
, true, true, loc
);
3323 sra_stats
.separate_lhs_rhs_handling
++;
3325 /* This gimplification must be done after generate_subtree_copies,
3326 lest we insert the subtree copies in the middle of the gimplified
3328 if (force_gimple_rhs
)
3329 rhs
= force_gimple_operand_gsi (&orig_gsi
, rhs
, true, NULL_TREE
,
3330 true, GSI_SAME_STMT
);
3331 if (gimple_assign_rhs1 (stmt
) != rhs
)
3333 modify_this_stmt
= true;
3334 gimple_assign_set_rhs_from_tree (&orig_gsi
, rhs
);
3335 gcc_assert (stmt
== gsi_stmt (orig_gsi
));
3338 return modify_this_stmt
? SRA_AM_MODIFIED
: SRA_AM_NONE
;
3342 if (access_has_children_p (lacc
)
3343 && access_has_children_p (racc
)
3344 /* When an access represents an unscalarizable region, it usually
3345 represents accesses with variable offset and thus must not be used
3346 to generate new memory accesses. */
3347 && !lacc
->grp_unscalarizable_region
3348 && !racc
->grp_unscalarizable_region
)
3350 struct subreplacement_assignment_data sad
;
3352 sad
.left_offset
= lacc
->offset
;
3353 sad
.assignment_lhs
= lhs
;
3354 sad
.assignment_rhs
= rhs
;
3355 sad
.top_racc
= racc
;
3358 sad
.loc
= gimple_location (stmt
);
3359 sad
.refreshed
= SRA_UDH_NONE
;
3361 if (lacc
->grp_read
&& !lacc
->grp_covered
)
3362 handle_unscalarized_data_in_subtree (&sad
);
3364 load_assign_lhs_subreplacements (lacc
, &sad
);
3365 if (sad
.refreshed
!= SRA_UDH_RIGHT
)
3368 unlink_stmt_vdef (stmt
);
3369 gsi_remove (&sad
.old_gsi
, true);
3370 release_defs (stmt
);
3371 sra_stats
.deleted
++;
3372 return SRA_AM_REMOVED
;
3377 if (access_has_children_p (racc
)
3378 && !racc
->grp_unscalarized_data
)
3382 fprintf (dump_file
, "Removing load: ");
3383 print_gimple_stmt (dump_file
, stmt
, 0, 0);
3385 generate_subtree_copies (racc
->first_child
, lhs
,
3386 racc
->offset
, 0, 0, gsi
,
3388 gcc_assert (stmt
== gsi_stmt (*gsi
));
3389 unlink_stmt_vdef (stmt
);
3390 gsi_remove (gsi
, true);
3391 release_defs (stmt
);
3392 sra_stats
.deleted
++;
3393 return SRA_AM_REMOVED
;
3395 /* Restore the aggregate RHS from its components so the
3396 prevailing aggregate copy does the right thing. */
3397 if (access_has_children_p (racc
))
3398 generate_subtree_copies (racc
->first_child
, rhs
, racc
->offset
, 0, 0,
3399 gsi
, false, false, loc
);
3400 /* Re-load the components of the aggregate copy destination.
3401 But use the RHS aggregate to load from to expose more
3402 optimization opportunities. */
3403 if (access_has_children_p (lacc
))
3404 generate_subtree_copies (lacc
->first_child
, rhs
, lacc
->offset
,
3405 0, 0, gsi
, true, true, loc
);
3412 /* Traverse the function body and all modifications as decided in
3413 analyze_all_variable_accesses. Return true iff the CFG has been
3417 sra_modify_function_body (void)
3419 bool cfg_changed
= false;
3422 FOR_EACH_BB_FN (bb
, cfun
)
3424 gimple_stmt_iterator gsi
= gsi_start_bb (bb
);
3425 while (!gsi_end_p (gsi
))
3427 gimple stmt
= gsi_stmt (gsi
);
3428 enum assignment_mod_result assign_result
;
3429 bool modified
= false, deleted
= false;
3433 switch (gimple_code (stmt
))
3436 t
= gimple_return_retval_ptr (as_a
<greturn
*> (stmt
));
3437 if (*t
!= NULL_TREE
)
3438 modified
|= sra_modify_expr (t
, &gsi
, false);
3442 assign_result
= sra_modify_assign (stmt
, &gsi
);
3443 modified
|= assign_result
== SRA_AM_MODIFIED
;
3444 deleted
= assign_result
== SRA_AM_REMOVED
;
3448 /* Operands must be processed before the lhs. */
3449 for (i
= 0; i
< gimple_call_num_args (stmt
); i
++)
3451 t
= gimple_call_arg_ptr (stmt
, i
);
3452 modified
|= sra_modify_expr (t
, &gsi
, false);
3455 if (gimple_call_lhs (stmt
))
3457 t
= gimple_call_lhs_ptr (stmt
);
3458 modified
|= sra_modify_expr (t
, &gsi
, true);
3464 gasm
*asm_stmt
= as_a
<gasm
*> (stmt
);
3465 for (i
= 0; i
< gimple_asm_ninputs (asm_stmt
); i
++)
3467 t
= &TREE_VALUE (gimple_asm_input_op (asm_stmt
, i
));
3468 modified
|= sra_modify_expr (t
, &gsi
, false);
3470 for (i
= 0; i
< gimple_asm_noutputs (asm_stmt
); i
++)
3472 t
= &TREE_VALUE (gimple_asm_output_op (asm_stmt
, i
));
3473 modified
|= sra_modify_expr (t
, &gsi
, true);
3485 if (maybe_clean_eh_stmt (stmt
)
3486 && gimple_purge_dead_eh_edges (gimple_bb (stmt
)))
3494 gsi_commit_edge_inserts ();
3498 /* Generate statements initializing scalar replacements of parts of function
3502 initialize_parameter_reductions (void)
3504 gimple_stmt_iterator gsi
;
3505 gimple_seq seq
= NULL
;
3508 gsi
= gsi_start (seq
);
3509 for (parm
= DECL_ARGUMENTS (current_function_decl
);
3511 parm
= DECL_CHAIN (parm
))
3513 vec
<access_p
> *access_vec
;
3514 struct access
*access
;
3516 if (!bitmap_bit_p (candidate_bitmap
, DECL_UID (parm
)))
3518 access_vec
= get_base_access_vector (parm
);
3522 for (access
= (*access_vec
)[0];
3524 access
= access
->next_grp
)
3525 generate_subtree_copies (access
, parm
, 0, 0, 0, &gsi
, true, true,
3526 EXPR_LOCATION (parm
));
3529 seq
= gsi_seq (gsi
);
3531 gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun
)), seq
);
3534 /* The "main" function of intraprocedural SRA passes. Runs the analysis and if
3535 it reveals there are components of some aggregates to be scalarized, it runs
3536 the required transformations. */
3538 perform_intra_sra (void)
3543 if (!find_var_candidates ())
3546 if (!scan_function ())
3549 if (!analyze_all_variable_accesses ())
3552 if (sra_modify_function_body ())
3553 ret
= TODO_update_ssa
| TODO_cleanup_cfg
;
3555 ret
= TODO_update_ssa
;
3556 initialize_parameter_reductions ();
3558 statistics_counter_event (cfun
, "Scalar replacements created",
3559 sra_stats
.replacements
);
3560 statistics_counter_event (cfun
, "Modified expressions", sra_stats
.exprs
);
3561 statistics_counter_event (cfun
, "Subtree copy stmts",
3562 sra_stats
.subtree_copies
);
3563 statistics_counter_event (cfun
, "Subreplacement stmts",
3564 sra_stats
.subreplacements
);
3565 statistics_counter_event (cfun
, "Deleted stmts", sra_stats
.deleted
);
3566 statistics_counter_event (cfun
, "Separate LHS and RHS handling",
3567 sra_stats
.separate_lhs_rhs_handling
);
3570 sra_deinitialize ();
3574 /* Perform early intraprocedural SRA. */
3576 early_intra_sra (void)
3578 sra_mode
= SRA_MODE_EARLY_INTRA
;
3579 return perform_intra_sra ();
3582 /* Perform "late" intraprocedural SRA. */
3584 late_intra_sra (void)
3586 sra_mode
= SRA_MODE_INTRA
;
3587 return perform_intra_sra ();
3592 gate_intra_sra (void)
3594 return flag_tree_sra
!= 0 && dbg_cnt (tree_sra
);
3600 const pass_data pass_data_sra_early
=
3602 GIMPLE_PASS
, /* type */
3604 OPTGROUP_NONE
, /* optinfo_flags */
3605 TV_TREE_SRA
, /* tv_id */
3606 ( PROP_cfg
| PROP_ssa
), /* properties_required */
3607 0, /* properties_provided */
3608 0, /* properties_destroyed */
3609 0, /* todo_flags_start */
3610 TODO_update_ssa
, /* todo_flags_finish */
3613 class pass_sra_early
: public gimple_opt_pass
3616 pass_sra_early (gcc::context
*ctxt
)
3617 : gimple_opt_pass (pass_data_sra_early
, ctxt
)
3620 /* opt_pass methods: */
3621 virtual bool gate (function
*) { return gate_intra_sra (); }
3622 virtual unsigned int execute (function
*) { return early_intra_sra (); }
3624 }; // class pass_sra_early
3629 make_pass_sra_early (gcc::context
*ctxt
)
3631 return new pass_sra_early (ctxt
);
3636 const pass_data pass_data_sra
=
3638 GIMPLE_PASS
, /* type */
3640 OPTGROUP_NONE
, /* optinfo_flags */
3641 TV_TREE_SRA
, /* tv_id */
3642 ( PROP_cfg
| PROP_ssa
), /* properties_required */
3643 0, /* properties_provided */
3644 0, /* properties_destroyed */
3645 TODO_update_address_taken
, /* todo_flags_start */
3646 TODO_update_ssa
, /* todo_flags_finish */
3649 class pass_sra
: public gimple_opt_pass
3652 pass_sra (gcc::context
*ctxt
)
3653 : gimple_opt_pass (pass_data_sra
, ctxt
)
3656 /* opt_pass methods: */
3657 virtual bool gate (function
*) { return gate_intra_sra (); }
3658 virtual unsigned int execute (function
*) { return late_intra_sra (); }
3660 }; // class pass_sra
3665 make_pass_sra (gcc::context
*ctxt
)
3667 return new pass_sra (ctxt
);
3671 /* Return true iff PARM (which must be a parm_decl) is an unused scalar
3675 is_unused_scalar_param (tree parm
)
3678 return (is_gimple_reg (parm
)
3679 && (!(name
= ssa_default_def (cfun
, parm
))
3680 || has_zero_uses (name
)));
3683 /* Scan immediate uses of a default definition SSA name of a parameter PARM and
3684 examine whether there are any direct or otherwise infeasible ones. If so,
3685 return true, otherwise return false. PARM must be a gimple register with a
3686 non-NULL default definition. */
3689 ptr_parm_has_direct_uses (tree parm
)
3691 imm_use_iterator ui
;
3693 tree name
= ssa_default_def (cfun
, parm
);
3696 FOR_EACH_IMM_USE_STMT (stmt
, ui
, name
)
3699 use_operand_p use_p
;
3701 if (is_gimple_debug (stmt
))
3704 /* Valid uses include dereferences on the lhs and the rhs. */
3705 if (gimple_has_lhs (stmt
))
3707 tree lhs
= gimple_get_lhs (stmt
);
3708 while (handled_component_p (lhs
))
3709 lhs
= TREE_OPERAND (lhs
, 0);
3710 if (TREE_CODE (lhs
) == MEM_REF
3711 && TREE_OPERAND (lhs
, 0) == name
3712 && integer_zerop (TREE_OPERAND (lhs
, 1))
3713 && types_compatible_p (TREE_TYPE (lhs
),
3714 TREE_TYPE (TREE_TYPE (name
)))
3715 && !TREE_THIS_VOLATILE (lhs
))
3718 if (gimple_assign_single_p (stmt
))
3720 tree rhs
= gimple_assign_rhs1 (stmt
);
3721 while (handled_component_p (rhs
))
3722 rhs
= TREE_OPERAND (rhs
, 0);
3723 if (TREE_CODE (rhs
) == MEM_REF
3724 && TREE_OPERAND (rhs
, 0) == name
3725 && integer_zerop (TREE_OPERAND (rhs
, 1))
3726 && types_compatible_p (TREE_TYPE (rhs
),
3727 TREE_TYPE (TREE_TYPE (name
)))
3728 && !TREE_THIS_VOLATILE (rhs
))
3731 else if (is_gimple_call (stmt
))
3734 for (i
= 0; i
< gimple_call_num_args (stmt
); ++i
)
3736 tree arg
= gimple_call_arg (stmt
, i
);
3737 while (handled_component_p (arg
))
3738 arg
= TREE_OPERAND (arg
, 0);
3739 if (TREE_CODE (arg
) == MEM_REF
3740 && TREE_OPERAND (arg
, 0) == name
3741 && integer_zerop (TREE_OPERAND (arg
, 1))
3742 && types_compatible_p (TREE_TYPE (arg
),
3743 TREE_TYPE (TREE_TYPE (name
)))
3744 && !TREE_THIS_VOLATILE (arg
))
3749 /* If the number of valid uses does not match the number of
3750 uses in this stmt there is an unhandled use. */
3751 FOR_EACH_IMM_USE_ON_STMT (use_p
, ui
)
3758 BREAK_FROM_IMM_USE_STMT (ui
);
3764 /* Identify candidates for reduction for IPA-SRA based on their type and mark
3765 them in candidate_bitmap. Note that these do not necessarily include
3766 parameter which are unused and thus can be removed. Return true iff any
3767 such candidate has been found. */
3770 find_param_candidates (void)
3777 for (parm
= DECL_ARGUMENTS (current_function_decl
);
3779 parm
= DECL_CHAIN (parm
))
3781 tree type
= TREE_TYPE (parm
);
3786 if (TREE_THIS_VOLATILE (parm
)
3787 || TREE_ADDRESSABLE (parm
)
3788 || (!is_gimple_reg_type (type
) && is_va_list_type (type
)))
3791 if (is_unused_scalar_param (parm
))
3797 if (POINTER_TYPE_P (type
))
3799 type
= TREE_TYPE (type
);
3801 if (TREE_CODE (type
) == FUNCTION_TYPE
3802 || TYPE_VOLATILE (type
)
3803 || (TREE_CODE (type
) == ARRAY_TYPE
3804 && TYPE_NONALIASED_COMPONENT (type
))
3805 || !is_gimple_reg (parm
)
3806 || is_va_list_type (type
)
3807 || ptr_parm_has_direct_uses (parm
))
3810 else if (!AGGREGATE_TYPE_P (type
))
3813 if (!COMPLETE_TYPE_P (type
)
3814 || !tree_fits_uhwi_p (TYPE_SIZE (type
))
3815 || tree_to_uhwi (TYPE_SIZE (type
)) == 0
3816 || (AGGREGATE_TYPE_P (type
)
3817 && type_internals_preclude_sra_p (type
, &msg
)))
3820 bitmap_set_bit (candidate_bitmap
, DECL_UID (parm
));
3821 slot
= candidates
->find_slot_with_hash (parm
, DECL_UID (parm
), INSERT
);
3825 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
3827 fprintf (dump_file
, "Candidate (%d): ", DECL_UID (parm
));
3828 print_generic_expr (dump_file
, parm
, 0);
3829 fprintf (dump_file
, "\n");
3833 func_param_count
= count
;
3837 /* Callback of walk_aliased_vdefs, marks the access passed as DATA as
3841 mark_maybe_modified (ao_ref
*ao ATTRIBUTE_UNUSED
, tree vdef ATTRIBUTE_UNUSED
,
3844 struct access
*repr
= (struct access
*) data
;
3846 repr
->grp_maybe_modified
= 1;
3850 /* Analyze what representatives (in linked lists accessible from
3851 REPRESENTATIVES) can be modified by side effects of statements in the
3852 current function. */
3855 analyze_modified_params (vec
<access_p
> representatives
)
3859 for (i
= 0; i
< func_param_count
; i
++)
3861 struct access
*repr
;
3863 for (repr
= representatives
[i
];
3865 repr
= repr
->next_grp
)
3867 struct access
*access
;
3871 if (no_accesses_p (repr
))
3873 if (!POINTER_TYPE_P (TREE_TYPE (repr
->base
))
3874 || repr
->grp_maybe_modified
)
3877 ao_ref_init (&ar
, repr
->expr
);
3878 visited
= BITMAP_ALLOC (NULL
);
3879 for (access
= repr
; access
; access
= access
->next_sibling
)
3881 /* All accesses are read ones, otherwise grp_maybe_modified would
3882 be trivially set. */
3883 walk_aliased_vdefs (&ar
, gimple_vuse (access
->stmt
),
3884 mark_maybe_modified
, repr
, &visited
);
3885 if (repr
->grp_maybe_modified
)
3888 BITMAP_FREE (visited
);
3893 /* Propagate distances in bb_dereferences in the opposite direction than the
3894 control flow edges, in each step storing the maximum of the current value
3895 and the minimum of all successors. These steps are repeated until the table
3896 stabilizes. Note that BBs which might terminate the functions (according to
3897 final_bbs bitmap) never updated in this way. */
3900 propagate_dereference_distances (void)
3904 auto_vec
<basic_block
> queue (last_basic_block_for_fn (cfun
));
3905 queue
.quick_push (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
3906 FOR_EACH_BB_FN (bb
, cfun
)
3908 queue
.quick_push (bb
);
3912 while (!queue
.is_empty ())
3916 bool change
= false;
3922 if (bitmap_bit_p (final_bbs
, bb
->index
))
3925 for (i
= 0; i
< func_param_count
; i
++)
3927 int idx
= bb
->index
* func_param_count
+ i
;
3929 HOST_WIDE_INT inh
= 0;
3931 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
3933 int succ_idx
= e
->dest
->index
* func_param_count
+ i
;
3935 if (e
->src
== EXIT_BLOCK_PTR_FOR_FN (cfun
))
3941 inh
= bb_dereferences
[succ_idx
];
3943 else if (bb_dereferences
[succ_idx
] < inh
)
3944 inh
= bb_dereferences
[succ_idx
];
3947 if (!first
&& bb_dereferences
[idx
] < inh
)
3949 bb_dereferences
[idx
] = inh
;
3954 if (change
&& !bitmap_bit_p (final_bbs
, bb
->index
))
3955 FOR_EACH_EDGE (e
, ei
, bb
->preds
)
3960 e
->src
->aux
= e
->src
;
3961 queue
.quick_push (e
->src
);
3966 /* Dump a dereferences TABLE with heading STR to file F. */
3969 dump_dereferences_table (FILE *f
, const char *str
, HOST_WIDE_INT
*table
)
3973 fprintf (dump_file
, str
);
3974 FOR_BB_BETWEEN (bb
, ENTRY_BLOCK_PTR_FOR_FN (cfun
),
3975 EXIT_BLOCK_PTR_FOR_FN (cfun
), next_bb
)
3977 fprintf (f
, "%4i %i ", bb
->index
, bitmap_bit_p (final_bbs
, bb
->index
));
3978 if (bb
!= EXIT_BLOCK_PTR_FOR_FN (cfun
))
3981 for (i
= 0; i
< func_param_count
; i
++)
3983 int idx
= bb
->index
* func_param_count
+ i
;
3984 fprintf (f
, " %4" HOST_WIDE_INT_PRINT
"d", table
[idx
]);
3989 fprintf (dump_file
, "\n");
3992 /* Determine what (parts of) parameters passed by reference that are not
3993 assigned to are not certainly dereferenced in this function and thus the
3994 dereferencing cannot be safely moved to the caller without potentially
3995 introducing a segfault. Mark such REPRESENTATIVES as
3996 grp_not_necessarilly_dereferenced.
3998 The dereferenced maximum "distance," i.e. the offset + size of the accessed
3999 part is calculated rather than simple booleans are calculated for each
4000 pointer parameter to handle cases when only a fraction of the whole
4001 aggregate is allocated (see testsuite/gcc.c-torture/execute/ipa-sra-2.c for
4004 The maximum dereference distances for each pointer parameter and BB are
4005 already stored in bb_dereference. This routine simply propagates these
4006 values upwards by propagate_dereference_distances and then compares the
4007 distances of individual parameters in the ENTRY BB to the equivalent
4008 distances of each representative of a (fraction of a) parameter. */
4011 analyze_caller_dereference_legality (vec
<access_p
> representatives
)
4015 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
4016 dump_dereferences_table (dump_file
,
4017 "Dereference table before propagation:\n",
4020 propagate_dereference_distances ();
4022 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
4023 dump_dereferences_table (dump_file
,
4024 "Dereference table after propagation:\n",
4027 for (i
= 0; i
< func_param_count
; i
++)
4029 struct access
*repr
= representatives
[i
];
4030 int idx
= ENTRY_BLOCK_PTR_FOR_FN (cfun
)->index
* func_param_count
+ i
;
4032 if (!repr
|| no_accesses_p (repr
))
4037 if ((repr
->offset
+ repr
->size
) > bb_dereferences
[idx
])
4038 repr
->grp_not_necessarilly_dereferenced
= 1;
4039 repr
= repr
->next_grp
;
4045 /* Return the representative access for the parameter declaration PARM if it is
4046 a scalar passed by reference which is not written to and the pointer value
4047 is not used directly. Thus, if it is legal to dereference it in the caller
4048 and we can rule out modifications through aliases, such parameter should be
4049 turned into one passed by value. Return NULL otherwise. */
4051 static struct access
*
4052 unmodified_by_ref_scalar_representative (tree parm
)
4054 int i
, access_count
;
4055 struct access
*repr
;
4056 vec
<access_p
> *access_vec
;
4058 access_vec
= get_base_access_vector (parm
);
4059 gcc_assert (access_vec
);
4060 repr
= (*access_vec
)[0];
4063 repr
->group_representative
= repr
;
4065 access_count
= access_vec
->length ();
4066 for (i
= 1; i
< access_count
; i
++)
4068 struct access
*access
= (*access_vec
)[i
];
4071 access
->group_representative
= repr
;
4072 access
->next_sibling
= repr
->next_sibling
;
4073 repr
->next_sibling
= access
;
4077 repr
->grp_scalar_ptr
= 1;
4081 /* Return true iff this ACCESS precludes IPA-SRA of the parameter it is
4082 associated with. REQ_ALIGN is the minimum required alignment. */
4085 access_precludes_ipa_sra_p (struct access
*access
, unsigned int req_align
)
4087 unsigned int exp_align
;
4088 /* Avoid issues such as the second simple testcase in PR 42025. The problem
4089 is incompatible assign in a call statement (and possibly even in asm
4090 statements). This can be relaxed by using a new temporary but only for
4091 non-TREE_ADDRESSABLE types and is probably not worth the complexity. (In
4092 intraprocedural SRA we deal with this by keeping the old aggregate around,
4093 something we cannot do in IPA-SRA.) */
4095 && (is_gimple_call (access
->stmt
)
4096 || gimple_code (access
->stmt
) == GIMPLE_ASM
))
4099 exp_align
= get_object_alignment (access
->expr
);
4100 if (exp_align
< req_align
)
4107 /* Sort collected accesses for parameter PARM, identify representatives for
4108 each accessed region and link them together. Return NULL if there are
4109 different but overlapping accesses, return the special ptr value meaning
4110 there are no accesses for this parameter if that is the case and return the
4111 first representative otherwise. Set *RO_GRP if there is a group of accesses
4112 with only read (i.e. no write) accesses. */
4114 static struct access
*
4115 splice_param_accesses (tree parm
, bool *ro_grp
)
4117 int i
, j
, access_count
, group_count
;
4118 int agg_size
, total_size
= 0;
4119 struct access
*access
, *res
, **prev_acc_ptr
= &res
;
4120 vec
<access_p
> *access_vec
;
4122 access_vec
= get_base_access_vector (parm
);
4124 return &no_accesses_representant
;
4125 access_count
= access_vec
->length ();
4127 access_vec
->qsort (compare_access_positions
);
4132 while (i
< access_count
)
4136 access
= (*access_vec
)[i
];
4137 modification
= access
->write
;
4138 if (access_precludes_ipa_sra_p (access
, TYPE_ALIGN (access
->type
)))
4140 a1_alias_type
= reference_alias_ptr_type (access
->expr
);
4142 /* Access is about to become group representative unless we find some
4143 nasty overlap which would preclude us from breaking this parameter
4147 while (j
< access_count
)
4149 struct access
*ac2
= (*access_vec
)[j
];
4150 if (ac2
->offset
!= access
->offset
)
4152 /* All or nothing law for parameters. */
4153 if (access
->offset
+ access
->size
> ac2
->offset
)
4158 else if (ac2
->size
!= access
->size
)
4161 if (access_precludes_ipa_sra_p (ac2
, TYPE_ALIGN (access
->type
))
4162 || (ac2
->type
!= access
->type
4163 && (TREE_ADDRESSABLE (ac2
->type
)
4164 || TREE_ADDRESSABLE (access
->type
)))
4165 || (reference_alias_ptr_type (ac2
->expr
) != a1_alias_type
))
4168 modification
|= ac2
->write
;
4169 ac2
->group_representative
= access
;
4170 ac2
->next_sibling
= access
->next_sibling
;
4171 access
->next_sibling
= ac2
;
4176 access
->grp_maybe_modified
= modification
;
4179 *prev_acc_ptr
= access
;
4180 prev_acc_ptr
= &access
->next_grp
;
4181 total_size
+= access
->size
;
4185 if (POINTER_TYPE_P (TREE_TYPE (parm
)))
4186 agg_size
= tree_to_uhwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm
))));
4188 agg_size
= tree_to_uhwi (TYPE_SIZE (TREE_TYPE (parm
)));
4189 if (total_size
>= agg_size
)
4192 gcc_assert (group_count
> 0);
4196 /* Decide whether parameters with representative accesses given by REPR should
4197 be reduced into components. */
4200 decide_one_param_reduction (struct access
*repr
)
4202 int total_size
, cur_parm_size
, agg_size
, new_param_count
, parm_size_limit
;
4207 cur_parm_size
= tree_to_uhwi (TYPE_SIZE (TREE_TYPE (parm
)));
4208 gcc_assert (cur_parm_size
> 0);
4210 if (POINTER_TYPE_P (TREE_TYPE (parm
)))
4213 agg_size
= tree_to_uhwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm
))));
4218 agg_size
= cur_parm_size
;
4224 fprintf (dump_file
, "Evaluating PARAM group sizes for ");
4225 print_generic_expr (dump_file
, parm
, 0);
4226 fprintf (dump_file
, " (UID: %u): \n", DECL_UID (parm
));
4227 for (acc
= repr
; acc
; acc
= acc
->next_grp
)
4228 dump_access (dump_file
, acc
, true);
4232 new_param_count
= 0;
4234 for (; repr
; repr
= repr
->next_grp
)
4236 gcc_assert (parm
== repr
->base
);
4238 /* Taking the address of a non-addressable field is verboten. */
4239 if (by_ref
&& repr
->non_addressable
)
4242 /* Do not decompose a non-BLKmode param in a way that would
4243 create BLKmode params. Especially for by-reference passing
4244 (thus, pointer-type param) this is hardly worthwhile. */
4245 if (DECL_MODE (parm
) != BLKmode
4246 && TYPE_MODE (repr
->type
) == BLKmode
)
4249 if (!by_ref
|| (!repr
->grp_maybe_modified
4250 && !repr
->grp_not_necessarilly_dereferenced
))
4251 total_size
+= repr
->size
;
4253 total_size
+= cur_parm_size
;
4258 gcc_assert (new_param_count
> 0);
4260 if (optimize_function_for_size_p (cfun
))
4261 parm_size_limit
= cur_parm_size
;
4263 parm_size_limit
= (PARAM_VALUE (PARAM_IPA_SRA_PTR_GROWTH_FACTOR
)
4266 if (total_size
< agg_size
4267 && total_size
<= parm_size_limit
)
4270 fprintf (dump_file
, " ....will be split into %i components\n",
4272 return new_param_count
;
4278 /* The order of the following enums is important, we need to do extra work for
4279 UNUSED_PARAMS, BY_VAL_ACCESSES and UNMODIF_BY_REF_ACCESSES. */
4280 enum ipa_splicing_result
{ NO_GOOD_ACCESS
, UNUSED_PARAMS
, BY_VAL_ACCESSES
,
4281 MODIF_BY_REF_ACCESSES
, UNMODIF_BY_REF_ACCESSES
};
4283 /* Identify representatives of all accesses to all candidate parameters for
4284 IPA-SRA. Return result based on what representatives have been found. */
4286 static enum ipa_splicing_result
4287 splice_all_param_accesses (vec
<access_p
> &representatives
)
4289 enum ipa_splicing_result result
= NO_GOOD_ACCESS
;
4291 struct access
*repr
;
4293 representatives
.create (func_param_count
);
4295 for (parm
= DECL_ARGUMENTS (current_function_decl
);
4297 parm
= DECL_CHAIN (parm
))
4299 if (is_unused_scalar_param (parm
))
4301 representatives
.quick_push (&no_accesses_representant
);
4302 if (result
== NO_GOOD_ACCESS
)
4303 result
= UNUSED_PARAMS
;
4305 else if (POINTER_TYPE_P (TREE_TYPE (parm
))
4306 && is_gimple_reg_type (TREE_TYPE (TREE_TYPE (parm
)))
4307 && bitmap_bit_p (candidate_bitmap
, DECL_UID (parm
)))
4309 repr
= unmodified_by_ref_scalar_representative (parm
);
4310 representatives
.quick_push (repr
);
4312 result
= UNMODIF_BY_REF_ACCESSES
;
4314 else if (bitmap_bit_p (candidate_bitmap
, DECL_UID (parm
)))
4316 bool ro_grp
= false;
4317 repr
= splice_param_accesses (parm
, &ro_grp
);
4318 representatives
.quick_push (repr
);
4320 if (repr
&& !no_accesses_p (repr
))
4322 if (POINTER_TYPE_P (TREE_TYPE (parm
)))
4325 result
= UNMODIF_BY_REF_ACCESSES
;
4326 else if (result
< MODIF_BY_REF_ACCESSES
)
4327 result
= MODIF_BY_REF_ACCESSES
;
4329 else if (result
< BY_VAL_ACCESSES
)
4330 result
= BY_VAL_ACCESSES
;
4332 else if (no_accesses_p (repr
) && (result
== NO_GOOD_ACCESS
))
4333 result
= UNUSED_PARAMS
;
4336 representatives
.quick_push (NULL
);
4339 if (result
== NO_GOOD_ACCESS
)
4341 representatives
.release ();
4342 return NO_GOOD_ACCESS
;
4348 /* Return the index of BASE in PARMS. Abort if it is not found. */
4351 get_param_index (tree base
, vec
<tree
> parms
)
4355 len
= parms
.length ();
4356 for (i
= 0; i
< len
; i
++)
4357 if (parms
[i
] == base
)
4362 /* Convert the decisions made at the representative level into compact
4363 parameter adjustments. REPRESENTATIVES are pointers to first
4364 representatives of each param accesses, ADJUSTMENTS_COUNT is the expected
4365 final number of adjustments. */
4367 static ipa_parm_adjustment_vec
4368 turn_representatives_into_adjustments (vec
<access_p
> representatives
,
4369 int adjustments_count
)
4372 ipa_parm_adjustment_vec adjustments
;
4376 gcc_assert (adjustments_count
> 0);
4377 parms
= ipa_get_vector_of_formal_parms (current_function_decl
);
4378 adjustments
.create (adjustments_count
);
4379 parm
= DECL_ARGUMENTS (current_function_decl
);
4380 for (i
= 0; i
< func_param_count
; i
++, parm
= DECL_CHAIN (parm
))
4382 struct access
*repr
= representatives
[i
];
4384 if (!repr
|| no_accesses_p (repr
))
4386 struct ipa_parm_adjustment adj
;
4388 memset (&adj
, 0, sizeof (adj
));
4389 adj
.base_index
= get_param_index (parm
, parms
);
4392 adj
.op
= IPA_PARM_OP_COPY
;
4394 adj
.op
= IPA_PARM_OP_REMOVE
;
4395 adj
.arg_prefix
= "ISRA";
4396 adjustments
.quick_push (adj
);
4400 struct ipa_parm_adjustment adj
;
4401 int index
= get_param_index (parm
, parms
);
4403 for (; repr
; repr
= repr
->next_grp
)
4405 memset (&adj
, 0, sizeof (adj
));
4406 gcc_assert (repr
->base
== parm
);
4407 adj
.base_index
= index
;
4408 adj
.base
= repr
->base
;
4409 adj
.type
= repr
->type
;
4410 adj
.alias_ptr_type
= reference_alias_ptr_type (repr
->expr
);
4411 adj
.offset
= repr
->offset
;
4412 adj
.by_ref
= (POINTER_TYPE_P (TREE_TYPE (repr
->base
))
4413 && (repr
->grp_maybe_modified
4414 || repr
->grp_not_necessarilly_dereferenced
));
4415 adj
.arg_prefix
= "ISRA";
4416 adjustments
.quick_push (adj
);
4424 /* Analyze the collected accesses and produce a plan what to do with the
4425 parameters in the form of adjustments, NULL meaning nothing. */
4427 static ipa_parm_adjustment_vec
4428 analyze_all_param_acesses (void)
4430 enum ipa_splicing_result repr_state
;
4431 bool proceed
= false;
4432 int i
, adjustments_count
= 0;
4433 vec
<access_p
> representatives
;
4434 ipa_parm_adjustment_vec adjustments
;
4436 repr_state
= splice_all_param_accesses (representatives
);
4437 if (repr_state
== NO_GOOD_ACCESS
)
4438 return ipa_parm_adjustment_vec ();
4440 /* If there are any parameters passed by reference which are not modified
4441 directly, we need to check whether they can be modified indirectly. */
4442 if (repr_state
== UNMODIF_BY_REF_ACCESSES
)
4444 analyze_caller_dereference_legality (representatives
);
4445 analyze_modified_params (representatives
);
4448 for (i
= 0; i
< func_param_count
; i
++)
4450 struct access
*repr
= representatives
[i
];
4452 if (repr
&& !no_accesses_p (repr
))
4454 if (repr
->grp_scalar_ptr
)
4456 adjustments_count
++;
4457 if (repr
->grp_not_necessarilly_dereferenced
4458 || repr
->grp_maybe_modified
)
4459 representatives
[i
] = NULL
;
4463 sra_stats
.scalar_by_ref_to_by_val
++;
4468 int new_components
= decide_one_param_reduction (repr
);
4470 if (new_components
== 0)
4472 representatives
[i
] = NULL
;
4473 adjustments_count
++;
4477 adjustments_count
+= new_components
;
4478 sra_stats
.aggregate_params_reduced
++;
4479 sra_stats
.param_reductions_created
+= new_components
;
4486 if (no_accesses_p (repr
))
4489 sra_stats
.deleted_unused_parameters
++;
4491 adjustments_count
++;
4495 if (!proceed
&& dump_file
)
4496 fprintf (dump_file
, "NOT proceeding to change params.\n");
4499 adjustments
= turn_representatives_into_adjustments (representatives
,
4502 adjustments
= ipa_parm_adjustment_vec ();
4504 representatives
.release ();
4508 /* If a parameter replacement identified by ADJ does not yet exist in the form
4509 of declaration, create it and record it, otherwise return the previously
4513 get_replaced_param_substitute (struct ipa_parm_adjustment
*adj
)
4516 if (!adj
->new_ssa_base
)
4518 char *pretty_name
= make_fancy_name (adj
->base
);
4520 repl
= create_tmp_reg (TREE_TYPE (adj
->base
), "ISR");
4521 DECL_NAME (repl
) = get_identifier (pretty_name
);
4522 obstack_free (&name_obstack
, pretty_name
);
4524 adj
->new_ssa_base
= repl
;
4527 repl
= adj
->new_ssa_base
;
4531 /* Find the first adjustment for a particular parameter BASE in a vector of
4532 ADJUSTMENTS which is not a copy_param. Return NULL if there is no such
4535 static struct ipa_parm_adjustment
*
4536 get_adjustment_for_base (ipa_parm_adjustment_vec adjustments
, tree base
)
4540 len
= adjustments
.length ();
4541 for (i
= 0; i
< len
; i
++)
4543 struct ipa_parm_adjustment
*adj
;
4545 adj
= &adjustments
[i
];
4546 if (adj
->op
!= IPA_PARM_OP_COPY
&& adj
->base
== base
)
4553 /* If the statement STMT defines an SSA_NAME of a parameter which is to be
4554 removed because its value is not used, replace the SSA_NAME with a one
4555 relating to a created VAR_DECL together all of its uses and return true.
4556 ADJUSTMENTS is a pointer to an adjustments vector. */
4559 replace_removed_params_ssa_names (gimple stmt
,
4560 ipa_parm_adjustment_vec adjustments
)
4562 struct ipa_parm_adjustment
*adj
;
4563 tree lhs
, decl
, repl
, name
;
4565 if (gimple_code (stmt
) == GIMPLE_PHI
)
4566 lhs
= gimple_phi_result (stmt
);
4567 else if (is_gimple_assign (stmt
))
4568 lhs
= gimple_assign_lhs (stmt
);
4569 else if (is_gimple_call (stmt
))
4570 lhs
= gimple_call_lhs (stmt
);
4574 if (TREE_CODE (lhs
) != SSA_NAME
)
4577 decl
= SSA_NAME_VAR (lhs
);
4578 if (decl
== NULL_TREE
4579 || TREE_CODE (decl
) != PARM_DECL
)
4582 adj
= get_adjustment_for_base (adjustments
, decl
);
4586 repl
= get_replaced_param_substitute (adj
);
4587 name
= make_ssa_name (repl
, stmt
);
4591 fprintf (dump_file
, "replacing an SSA name of a removed param ");
4592 print_generic_expr (dump_file
, lhs
, 0);
4593 fprintf (dump_file
, " with ");
4594 print_generic_expr (dump_file
, name
, 0);
4595 fprintf (dump_file
, "\n");
4598 if (is_gimple_assign (stmt
))
4599 gimple_assign_set_lhs (stmt
, name
);
4600 else if (is_gimple_call (stmt
))
4601 gimple_call_set_lhs (stmt
, name
);
4603 gimple_phi_set_result (as_a
<gphi
*> (stmt
), name
);
4605 replace_uses_by (lhs
, name
);
4606 release_ssa_name (lhs
);
4610 /* If the statement STMT contains any expressions that need to replaced with a
4611 different one as noted by ADJUSTMENTS, do so. Handle any potential type
4612 incompatibilities (GSI is used to accommodate conversion statements and must
4613 point to the statement). Return true iff the statement was modified. */
4616 sra_ipa_modify_assign (gimple stmt
, gimple_stmt_iterator
*gsi
,
4617 ipa_parm_adjustment_vec adjustments
)
4619 tree
*lhs_p
, *rhs_p
;
4622 if (!gimple_assign_single_p (stmt
))
4625 rhs_p
= gimple_assign_rhs1_ptr (stmt
);
4626 lhs_p
= gimple_assign_lhs_ptr (stmt
);
4628 any
= ipa_modify_expr (rhs_p
, false, adjustments
);
4629 any
|= ipa_modify_expr (lhs_p
, false, adjustments
);
4632 tree new_rhs
= NULL_TREE
;
4634 if (!useless_type_conversion_p (TREE_TYPE (*lhs_p
), TREE_TYPE (*rhs_p
)))
4636 if (TREE_CODE (*rhs_p
) == CONSTRUCTOR
)
4638 /* V_C_Es of constructors can cause trouble (PR 42714). */
4639 if (is_gimple_reg_type (TREE_TYPE (*lhs_p
)))
4640 *rhs_p
= build_zero_cst (TREE_TYPE (*lhs_p
));
4642 *rhs_p
= build_constructor (TREE_TYPE (*lhs_p
),
4646 new_rhs
= fold_build1_loc (gimple_location (stmt
),
4647 VIEW_CONVERT_EXPR
, TREE_TYPE (*lhs_p
),
4650 else if (REFERENCE_CLASS_P (*rhs_p
)
4651 && is_gimple_reg_type (TREE_TYPE (*lhs_p
))
4652 && !is_gimple_reg (*lhs_p
))
4653 /* This can happen when an assignment in between two single field
4654 structures is turned into an assignment in between two pointers to
4655 scalars (PR 42237). */
4660 tree tmp
= force_gimple_operand_gsi (gsi
, new_rhs
, true, NULL_TREE
,
4661 true, GSI_SAME_STMT
);
4663 gimple_assign_set_rhs_from_tree (gsi
, tmp
);
4672 /* Traverse the function body and all modifications as described in
4673 ADJUSTMENTS. Return true iff the CFG has been changed. */
4676 ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments
)
4678 bool cfg_changed
= false;
4681 FOR_EACH_BB_FN (bb
, cfun
)
4683 gimple_stmt_iterator gsi
;
4685 for (gsi
= gsi_start_phis (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
4686 replace_removed_params_ssa_names (gsi_stmt (gsi
), adjustments
);
4688 gsi
= gsi_start_bb (bb
);
4689 while (!gsi_end_p (gsi
))
4691 gimple stmt
= gsi_stmt (gsi
);
4692 bool modified
= false;
4696 switch (gimple_code (stmt
))
4699 t
= gimple_return_retval_ptr (as_a
<greturn
*> (stmt
));
4700 if (*t
!= NULL_TREE
)
4701 modified
|= ipa_modify_expr (t
, true, adjustments
);
4705 modified
|= sra_ipa_modify_assign (stmt
, &gsi
, adjustments
);
4706 modified
|= replace_removed_params_ssa_names (stmt
, adjustments
);
4710 /* Operands must be processed before the lhs. */
4711 for (i
= 0; i
< gimple_call_num_args (stmt
); i
++)
4713 t
= gimple_call_arg_ptr (stmt
, i
);
4714 modified
|= ipa_modify_expr (t
, true, adjustments
);
4717 if (gimple_call_lhs (stmt
))
4719 t
= gimple_call_lhs_ptr (stmt
);
4720 modified
|= ipa_modify_expr (t
, false, adjustments
);
4721 modified
|= replace_removed_params_ssa_names (stmt
,
4728 gasm
*asm_stmt
= as_a
<gasm
*> (stmt
);
4729 for (i
= 0; i
< gimple_asm_ninputs (asm_stmt
); i
++)
4731 t
= &TREE_VALUE (gimple_asm_input_op (asm_stmt
, i
));
4732 modified
|= ipa_modify_expr (t
, true, adjustments
);
4734 for (i
= 0; i
< gimple_asm_noutputs (asm_stmt
); i
++)
4736 t
= &TREE_VALUE (gimple_asm_output_op (asm_stmt
, i
));
4737 modified
|= ipa_modify_expr (t
, false, adjustments
);
4749 if (maybe_clean_eh_stmt (stmt
)
4750 && gimple_purge_dead_eh_edges (gimple_bb (stmt
)))
4760 /* Call gimple_debug_bind_reset_value on all debug statements describing
4761 gimple register parameters that are being removed or replaced. */
4764 sra_ipa_reset_debug_stmts (ipa_parm_adjustment_vec adjustments
)
4767 gimple_stmt_iterator
*gsip
= NULL
, gsi
;
4769 if (MAY_HAVE_DEBUG_STMTS
&& single_succ_p (ENTRY_BLOCK_PTR_FOR_FN (cfun
)))
4771 gsi
= gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
)));
4774 len
= adjustments
.length ();
4775 for (i
= 0; i
< len
; i
++)
4777 struct ipa_parm_adjustment
*adj
;
4778 imm_use_iterator ui
;
4781 tree name
, vexpr
, copy
= NULL_TREE
;
4782 use_operand_p use_p
;
4784 adj
= &adjustments
[i
];
4785 if (adj
->op
== IPA_PARM_OP_COPY
|| !is_gimple_reg (adj
->base
))
4787 name
= ssa_default_def (cfun
, adj
->base
);
4790 FOR_EACH_IMM_USE_STMT (stmt
, ui
, name
)
4792 if (gimple_clobber_p (stmt
))
4794 gimple_stmt_iterator cgsi
= gsi_for_stmt (stmt
);
4795 unlink_stmt_vdef (stmt
);
4796 gsi_remove (&cgsi
, true);
4797 release_defs (stmt
);
4800 /* All other users must have been removed by
4801 ipa_sra_modify_function_body. */
4802 gcc_assert (is_gimple_debug (stmt
));
4803 if (vexpr
== NULL
&& gsip
!= NULL
)
4805 gcc_assert (TREE_CODE (adj
->base
) == PARM_DECL
);
4806 vexpr
= make_node (DEBUG_EXPR_DECL
);
4807 def_temp
= gimple_build_debug_source_bind (vexpr
, adj
->base
,
4809 DECL_ARTIFICIAL (vexpr
) = 1;
4810 TREE_TYPE (vexpr
) = TREE_TYPE (name
);
4811 DECL_MODE (vexpr
) = DECL_MODE (adj
->base
);
4812 gsi_insert_before (gsip
, def_temp
, GSI_SAME_STMT
);
4816 FOR_EACH_IMM_USE_ON_STMT (use_p
, ui
)
4817 SET_USE (use_p
, vexpr
);
4820 gimple_debug_bind_reset_value (stmt
);
4823 /* Create a VAR_DECL for debug info purposes. */
4824 if (!DECL_IGNORED_P (adj
->base
))
4826 copy
= build_decl (DECL_SOURCE_LOCATION (current_function_decl
),
4827 VAR_DECL
, DECL_NAME (adj
->base
),
4828 TREE_TYPE (adj
->base
));
4829 if (DECL_PT_UID_SET_P (adj
->base
))
4830 SET_DECL_PT_UID (copy
, DECL_PT_UID (adj
->base
));
4831 TREE_ADDRESSABLE (copy
) = TREE_ADDRESSABLE (adj
->base
);
4832 TREE_READONLY (copy
) = TREE_READONLY (adj
->base
);
4833 TREE_THIS_VOLATILE (copy
) = TREE_THIS_VOLATILE (adj
->base
);
4834 DECL_GIMPLE_REG_P (copy
) = DECL_GIMPLE_REG_P (adj
->base
);
4835 DECL_ARTIFICIAL (copy
) = DECL_ARTIFICIAL (adj
->base
);
4836 DECL_IGNORED_P (copy
) = DECL_IGNORED_P (adj
->base
);
4837 DECL_ABSTRACT_ORIGIN (copy
) = DECL_ORIGIN (adj
->base
);
4838 DECL_SEEN_IN_BIND_EXPR_P (copy
) = 1;
4839 SET_DECL_RTL (copy
, 0);
4840 TREE_USED (copy
) = 1;
4841 DECL_CONTEXT (copy
) = current_function_decl
;
4842 add_local_decl (cfun
, copy
);
4844 BLOCK_VARS (DECL_INITIAL (current_function_decl
));
4845 BLOCK_VARS (DECL_INITIAL (current_function_decl
)) = copy
;
4847 if (gsip
!= NULL
&& copy
&& target_for_debug_bind (adj
->base
))
4849 gcc_assert (TREE_CODE (adj
->base
) == PARM_DECL
);
4851 def_temp
= gimple_build_debug_bind (copy
, vexpr
, NULL
);
4853 def_temp
= gimple_build_debug_source_bind (copy
, adj
->base
,
4855 gsi_insert_before (gsip
, def_temp
, GSI_SAME_STMT
);
4860 /* Return false if all callers have at least as many actual arguments as there
4861 are formal parameters in the current function and that their types
4865 some_callers_have_mismatched_arguments_p (struct cgraph_node
*node
,
4866 void *data ATTRIBUTE_UNUSED
)
4868 struct cgraph_edge
*cs
;
4869 for (cs
= node
->callers
; cs
; cs
= cs
->next_caller
)
4870 if (!callsite_arguments_match_p (cs
->call_stmt
))
4876 /* Convert all callers of NODE. */
4879 convert_callers_for_node (struct cgraph_node
*node
,
4882 ipa_parm_adjustment_vec
*adjustments
= (ipa_parm_adjustment_vec
*) data
;
4883 bitmap recomputed_callers
= BITMAP_ALLOC (NULL
);
4884 struct cgraph_edge
*cs
;
4886 for (cs
= node
->callers
; cs
; cs
= cs
->next_caller
)
4888 push_cfun (DECL_STRUCT_FUNCTION (cs
->caller
->decl
));
4891 fprintf (dump_file
, "Adjusting call %s/%i -> %s/%i\n",
4892 xstrdup (cs
->caller
->name ()),
4894 xstrdup (cs
->callee
->name ()),
4897 ipa_modify_call_arguments (cs
, cs
->call_stmt
, *adjustments
);
4902 for (cs
= node
->callers
; cs
; cs
= cs
->next_caller
)
4903 if (bitmap_set_bit (recomputed_callers
, cs
->caller
->uid
)
4904 && gimple_in_ssa_p (DECL_STRUCT_FUNCTION (cs
->caller
->decl
)))
4905 compute_inline_parameters (cs
->caller
, true);
4906 BITMAP_FREE (recomputed_callers
);
4911 /* Convert all callers of NODE to pass parameters as given in ADJUSTMENTS. */
4914 convert_callers (struct cgraph_node
*node
, tree old_decl
,
4915 ipa_parm_adjustment_vec adjustments
)
4917 basic_block this_block
;
4919 node
->call_for_symbol_thunks_and_aliases (convert_callers_for_node
,
4920 &adjustments
, false);
4922 if (!encountered_recursive_call
)
4925 FOR_EACH_BB_FN (this_block
, cfun
)
4927 gimple_stmt_iterator gsi
;
4929 for (gsi
= gsi_start_bb (this_block
); !gsi_end_p (gsi
); gsi_next (&gsi
))
4933 stmt
= dyn_cast
<gcall
*> (gsi_stmt (gsi
));
4936 call_fndecl
= gimple_call_fndecl (stmt
);
4937 if (call_fndecl
== old_decl
)
4940 fprintf (dump_file
, "Adjusting recursive call");
4941 gimple_call_set_fndecl (stmt
, node
->decl
);
4942 ipa_modify_call_arguments (NULL
, stmt
, adjustments
);
4950 /* Perform all the modification required in IPA-SRA for NODE to have parameters
4951 as given in ADJUSTMENTS. Return true iff the CFG has been changed. */
4954 modify_function (struct cgraph_node
*node
, ipa_parm_adjustment_vec adjustments
)
4956 struct cgraph_node
*new_node
;
4959 cgraph_edge::rebuild_edges ();
4960 free_dominance_info (CDI_DOMINATORS
);
4963 /* This must be done after rebuilding cgraph edges for node above.
4964 Otherwise any recursive calls to node that are recorded in
4965 redirect_callers will be corrupted. */
4966 vec
<cgraph_edge
*> redirect_callers
= node
->collect_callers ();
4967 new_node
= node
->create_version_clone_with_body (redirect_callers
, NULL
,
4968 NULL
, false, NULL
, NULL
,
4970 redirect_callers
.release ();
4972 push_cfun (DECL_STRUCT_FUNCTION (new_node
->decl
));
4973 ipa_modify_formal_parameters (current_function_decl
, adjustments
);
4974 cfg_changed
= ipa_sra_modify_function_body (adjustments
);
4975 sra_ipa_reset_debug_stmts (adjustments
);
4976 convert_callers (new_node
, node
->decl
, adjustments
);
4977 new_node
->make_local ();
4981 /* If NODE has a caller, return true. */
4984 has_caller_p (struct cgraph_node
*node
, void *data ATTRIBUTE_UNUSED
)
4991 /* Return false the function is apparently unsuitable for IPA-SRA based on it's
4992 attributes, return true otherwise. NODE is the cgraph node of the current
4996 ipa_sra_preliminary_function_checks (struct cgraph_node
*node
)
4998 if (!node
->can_be_local_p ())
5001 fprintf (dump_file
, "Function not local to this compilation unit.\n");
5005 if (!node
->local
.can_change_signature
)
5008 fprintf (dump_file
, "Function can not change signature.\n");
5012 if (!tree_versionable_function_p (node
->decl
))
5015 fprintf (dump_file
, "Function is not versionable.\n");
5019 if (!opt_for_fn (node
->decl
, optimize
)
5020 || !opt_for_fn (node
->decl
, flag_ipa_sra
))
5023 fprintf (dump_file
, "Function not optimized.\n");
5027 if (DECL_VIRTUAL_P (current_function_decl
))
5030 fprintf (dump_file
, "Function is a virtual method.\n");
5034 if ((DECL_COMDAT (node
->decl
) || DECL_EXTERNAL (node
->decl
))
5035 && inline_summary (node
)->size
>= MAX_INLINE_INSNS_AUTO
)
5038 fprintf (dump_file
, "Function too big to be made truly local.\n");
5042 if (!node
->call_for_symbol_thunks_and_aliases (has_caller_p
, NULL
, true))
5046 "Function has no callers in this compilation unit.\n");
5053 fprintf (dump_file
, "Function uses stdarg. \n");
5057 if (TYPE_ATTRIBUTES (TREE_TYPE (node
->decl
)))
5060 if (DECL_DISREGARD_INLINE_LIMITS (node
->decl
))
5063 fprintf (dump_file
, "Always inline function will be inlined "
5071 /* Perform early interprocedural SRA. */
5074 ipa_early_sra (void)
5076 struct cgraph_node
*node
= cgraph_node::get (current_function_decl
);
5077 ipa_parm_adjustment_vec adjustments
;
5080 if (!ipa_sra_preliminary_function_checks (node
))
5084 sra_mode
= SRA_MODE_EARLY_IPA
;
5086 if (!find_param_candidates ())
5089 fprintf (dump_file
, "Function has no IPA-SRA candidates.\n");
5093 if (node
->call_for_symbol_thunks_and_aliases
5094 (some_callers_have_mismatched_arguments_p
, NULL
, true))
5097 fprintf (dump_file
, "There are callers with insufficient number of "
5098 "arguments or arguments with type mismatches.\n");
5102 bb_dereferences
= XCNEWVEC (HOST_WIDE_INT
,
5104 * last_basic_block_for_fn (cfun
));
5105 final_bbs
= BITMAP_ALLOC (NULL
);
5108 if (encountered_apply_args
)
5111 fprintf (dump_file
, "Function calls __builtin_apply_args().\n");
5115 if (encountered_unchangable_recursive_call
)
5118 fprintf (dump_file
, "Function calls itself with insufficient "
5119 "number of arguments.\n");
5123 adjustments
= analyze_all_param_acesses ();
5124 if (!adjustments
.exists ())
5127 ipa_dump_param_adjustments (dump_file
, adjustments
, current_function_decl
);
5129 if (modify_function (node
, adjustments
))
5130 ret
= TODO_update_ssa
| TODO_cleanup_cfg
;
5132 ret
= TODO_update_ssa
;
5133 adjustments
.release ();
5135 statistics_counter_event (cfun
, "Unused parameters deleted",
5136 sra_stats
.deleted_unused_parameters
);
5137 statistics_counter_event (cfun
, "Scalar parameters converted to by-value",
5138 sra_stats
.scalar_by_ref_to_by_val
);
5139 statistics_counter_event (cfun
, "Aggregate parameters broken up",
5140 sra_stats
.aggregate_params_reduced
);
5141 statistics_counter_event (cfun
, "Aggregate parameter components created",
5142 sra_stats
.param_reductions_created
);
5145 BITMAP_FREE (final_bbs
);
5146 free (bb_dereferences
);
5148 sra_deinitialize ();
5154 const pass_data pass_data_early_ipa_sra
=
5156 GIMPLE_PASS
, /* type */
5157 "eipa_sra", /* name */
5158 OPTGROUP_NONE
, /* optinfo_flags */
5159 TV_IPA_SRA
, /* tv_id */
5160 0, /* properties_required */
5161 0, /* properties_provided */
5162 0, /* properties_destroyed */
5163 0, /* todo_flags_start */
5164 TODO_dump_symtab
, /* todo_flags_finish */
5167 class pass_early_ipa_sra
: public gimple_opt_pass
5170 pass_early_ipa_sra (gcc::context
*ctxt
)
5171 : gimple_opt_pass (pass_data_early_ipa_sra
, ctxt
)
5174 /* opt_pass methods: */
5175 virtual bool gate (function
*) { return flag_ipa_sra
&& dbg_cnt (eipa_sra
); }
5176 virtual unsigned int execute (function
*) { return ipa_early_sra (); }
5178 }; // class pass_early_ipa_sra
5183 make_pass_early_ipa_sra (gcc::context
*ctxt
)
5185 return new pass_early_ipa_sra (ctxt
);