]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/tree-sra.c
Factor unrelated declarations out of tree.h.
[thirdparty/gcc.git] / gcc / tree-sra.c
CommitLineData
6de9cd9a
DN
1/* Scalar Replacement of Aggregates (SRA) converts some structure
2 references into scalar references, exposing them to the scalar
3 optimizers.
d1e082c2 4 Copyright (C) 2008-2013 Free Software Foundation, Inc.
0674b9d0 5 Contributed by Martin Jambor <mjambor@suse.cz>
6de9cd9a
DN
6
7This file is part of GCC.
19114537 8
0674b9d0
MJ
9GCC is free software; you can redistribute it and/or modify it under
10the terms of the GNU General Public License as published by the Free
11Software Foundation; either version 3, or (at your option) any later
12version.
19114537 13
0674b9d0
MJ
14GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15WARRANTY; without even the implied warranty of MERCHANTABILITY or
6de9cd9a
DN
16FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17for more details.
19114537 18
6de9cd9a 19You should have received a copy of the GNU General Public License
9dcd6f09
NC
20along with GCC; see the file COPYING3. If not see
21<http://www.gnu.org/licenses/>. */
6de9cd9a 22
0674b9d0
MJ
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.
27
28 The two passes are nearly identical, the only difference is that early SRA
29 does not scalarize unions which are used as the result in a GIMPLE_RETURN
30 statement because together with inlining this can lead to weird type
31 conversions.
32
33 Both passes operate in four stages:
34
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.
38
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.
46
47 On a related note, assign_link structures are created for every assign
48 statement between candidate aggregates and attached to the related
49 accesses.
50
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.
55
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).
60
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.
64
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.
67
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. */
73
6de9cd9a
DN
74#include "config.h"
75#include "system.h"
76#include "coretypes.h"
4a8fb1a1 77#include "hash-table.h"
0674b9d0 78#include "alloc-pool.h"
6de9cd9a 79#include "tm.h"
6de9cd9a 80#include "tree.h"
18f429e2 81#include "gimple.h"
d8a2d370 82#include "stor-layout.h"
45b0be94 83#include "gimplify.h"
5be5c238 84#include "gimple-iterator.h"
18f429e2 85#include "gimplify-me.h"
5be5c238 86#include "gimple-walk.h"
442b4905
AM
87#include "bitmap.h"
88#include "gimple-ssa.h"
89#include "tree-cfg.h"
90#include "tree-phinodes.h"
91#include "ssa-iterators.h"
d8a2d370 92#include "stringpool.h"
442b4905 93#include "tree-ssanames.h"
d8a2d370 94#include "expr.h"
442b4905 95#include "tree-dfa.h"
7a300452 96#include "tree-ssa.h"
7ee2468b 97#include "tree-pass.h"
3f84bf08 98#include "ipa-prop.h"
2a45675f 99#include "statistics.h"
61b58001 100#include "params.h"
0674b9d0
MJ
101#include "target.h"
102#include "flags.h"
567a4beb 103#include "dbgcnt.h"
29be3835 104#include "tree-inline.h"
56a42add 105#include "gimple-pretty-print.h"
e7f23018 106#include "ipa-inline.h"
9e401b63 107#include "ipa-utils.h"
6de9cd9a 108
0674b9d0 109/* Enumeration of all aggregate reductions we can do. */
07ffa034
MJ
110enum sra_mode { SRA_MODE_EARLY_IPA, /* early call regularization */
111 SRA_MODE_EARLY_INTRA, /* early intraprocedural SRA */
112 SRA_MODE_INTRA }; /* late intraprocedural SRA */
6de9cd9a 113
0674b9d0
MJ
114/* Global variable describing which aggregate reduction we are performing at
115 the moment. */
116static enum sra_mode sra_mode;
97e73bd2 117
0674b9d0 118struct assign_link;
97e73bd2 119
0674b9d0
MJ
120/* ACCESS represents each access to an aggregate variable (as a whole or a
121 part). It can also represent a group of accesses that refer to exactly the
122 same fragment of an aggregate (i.e. those that have exactly the same offset
123 and size). Such representatives for a single aggregate, once determined,
124 are linked in a linked list and have the group fields set.
97e73bd2 125
0674b9d0
MJ
126 Moreover, when doing intraprocedural SRA, a tree is built from those
127 representatives (by the means of first_child and next_sibling pointers), in
128 which all items in a subtree are "within" the root, i.e. their offset is
129 greater or equal to offset of the root and offset+size is smaller or equal
130 to offset+size of the root. Children of an access are sorted by offset.
97e73bd2 131
0674b9d0
MJ
132 Note that accesses to parts of vector and complex number types always
133 represented by an access to the whole complex number or a vector. It is a
134 duty of the modifying functions to replace them appropriately. */
97e73bd2 135
0674b9d0
MJ
136struct access
137{
138 /* Values returned by `get_ref_base_and_extent' for each component reference
139 If EXPR isn't a component reference just set `BASE = EXPR', `OFFSET = 0',
140 `SIZE = TREE_SIZE (TREE_TYPE (expr))'. */
141 HOST_WIDE_INT offset;
142 HOST_WIDE_INT size;
143 tree base;
6de9cd9a 144
09f0dc45
MJ
145 /* Expression. It is context dependent so do not use it to create new
146 expressions to access the original aggregate. See PR 42154 for a
147 testcase. */
0674b9d0
MJ
148 tree expr;
149 /* Type. */
150 tree type;
6de9cd9a 151
07ffa034
MJ
152 /* The statement this access belongs to. */
153 gimple stmt;
154
0674b9d0
MJ
155 /* Next group representative for this aggregate. */
156 struct access *next_grp;
157
158 /* Pointer to the group representative. Pointer to itself if the struct is
159 the representative. */
160 struct access *group_representative;
161
162 /* If this access has any children (in terms of the definition above), this
163 points to the first one. */
164 struct access *first_child;
165
30a20e97
MJ
166 /* In intraprocedural SRA, pointer to the next sibling in the access tree as
167 described above. In IPA-SRA this is a pointer to the next access
168 belonging to the same group (having the same representative). */
0674b9d0
MJ
169 struct access *next_sibling;
170
171 /* Pointers to the first and last element in the linked list of assign
172 links. */
173 struct assign_link *first_link, *last_link;
174
175 /* Pointer to the next access in the work queue. */
176 struct access *next_queued;
177
178 /* Replacement variable for this access "region." Never to be accessed
179 directly, always only by the means of get_access_replacement() and only
180 when grp_to_be_replaced flag is set. */
181 tree replacement_decl;
182
183 /* Is this particular access write access? */
184 unsigned write : 1;
185
5e9fba51
EB
186 /* Is this access an access to a non-addressable field? */
187 unsigned non_addressable : 1;
188
0674b9d0
MJ
189 /* Is this access currently in the work queue? */
190 unsigned grp_queued : 1;
07ffa034 191
0674b9d0
MJ
192 /* Does this group contain a write access? This flag is propagated down the
193 access tree. */
194 unsigned grp_write : 1;
07ffa034 195
0674b9d0
MJ
196 /* Does this group contain a read access? This flag is propagated down the
197 access tree. */
198 unsigned grp_read : 1;
07ffa034 199
77620011
MJ
200 /* Does this group contain a read access that comes from an assignment
201 statement? This flag is propagated down the access tree. */
202 unsigned grp_assignment_read : 1;
203
fc37536b
MJ
204 /* Does this group contain a write access that comes from an assignment
205 statement? This flag is propagated down the access tree. */
206 unsigned grp_assignment_write : 1;
207
4fd73214
MJ
208 /* Does this group contain a read access through a scalar type? This flag is
209 not propagated in the access tree in any direction. */
210 unsigned grp_scalar_read : 1;
211
212 /* Does this group contain a write access through a scalar type? This flag
213 is not propagated in the access tree in any direction. */
214 unsigned grp_scalar_write : 1;
215
1ac93f10
MJ
216 /* Is this access an artificial one created to scalarize some record
217 entirely? */
218 unsigned grp_total_scalarization : 1;
219
fef94f76
MJ
220 /* Other passes of the analysis use this bit to make function
221 analyze_access_subtree create scalar replacements for this group if
222 possible. */
223 unsigned grp_hint : 1;
07ffa034 224
0674b9d0
MJ
225 /* Is the subtree rooted in this access fully covered by scalar
226 replacements? */
227 unsigned grp_covered : 1;
07ffa034 228
0674b9d0
MJ
229 /* If set to true, this access and all below it in an access tree must not be
230 scalarized. */
231 unsigned grp_unscalarizable_region : 1;
07ffa034 232
0674b9d0
MJ
233 /* Whether data have been written to parts of the aggregate covered by this
234 access which is not to be scalarized. This flag is propagated up in the
235 access tree. */
236 unsigned grp_unscalarized_data : 1;
07ffa034 237
0674b9d0
MJ
238 /* Does this access and/or group contain a write access through a
239 BIT_FIELD_REF? */
240 unsigned grp_partial_lhs : 1;
241
d94b820b 242 /* Set when a scalar replacement should be created for this variable. */
0674b9d0 243 unsigned grp_to_be_replaced : 1;
07ffa034 244
be384c10
MJ
245 /* Set when we want a replacement for the sole purpose of having it in
246 generated debug statements. */
247 unsigned grp_to_be_debug_replaced : 1;
248
9271a43c
MJ
249 /* Should TREE_NO_WARNING of a replacement be set? */
250 unsigned grp_no_warning : 1;
251
07ffa034
MJ
252 /* Is it possible that the group refers to data which might be (directly or
253 otherwise) modified? */
254 unsigned grp_maybe_modified : 1;
255
256 /* Set when this is a representative of a pointer to scalar (i.e. by
257 reference) parameter which we consider for turning into a plain scalar
258 (i.e. a by value parameter). */
259 unsigned grp_scalar_ptr : 1;
260
261 /* Set when we discover that this pointer is not safe to dereference in the
262 caller. */
263 unsigned grp_not_necessarilly_dereferenced : 1;
0674b9d0 264};
029f45bd 265
0674b9d0 266typedef struct access *access_p;
6de9cd9a 267
6de9cd9a 268
0674b9d0
MJ
269/* Alloc pool for allocating access structures. */
270static alloc_pool access_pool;
97e73bd2 271
0674b9d0
MJ
272/* A structure linking lhs and rhs accesses from an aggregate assignment. They
273 are used to propagate subaccesses from rhs to lhs as long as they don't
274 conflict with what is already there. */
275struct assign_link
6de9cd9a 276{
0674b9d0
MJ
277 struct access *lacc, *racc;
278 struct assign_link *next;
279};
6de9cd9a 280
0674b9d0
MJ
281/* Alloc pool for allocating assign link structures. */
282static alloc_pool link_pool;
6de9cd9a 283
9771b263 284/* Base (tree) -> Vector (vec<access_p> *) map. */
0674b9d0 285static struct pointer_map_t *base_access_vec;
6de9cd9a 286
4a8fb1a1
LC
287/* Candidate hash table helpers. */
288
289struct uid_decl_hasher : typed_noop_remove <tree_node>
290{
291 typedef tree_node value_type;
292 typedef tree_node compare_type;
293 static inline hashval_t hash (const value_type *);
294 static inline bool equal (const value_type *, const compare_type *);
295};
296
297/* Hash a tree in a uid_decl_map. */
298
299inline hashval_t
300uid_decl_hasher::hash (const value_type *item)
301{
302 return item->decl_minimal.uid;
303}
304
305/* Return true if the DECL_UID in both trees are equal. */
306
307inline bool
308uid_decl_hasher::equal (const value_type *a, const compare_type *b)
309{
310 return (a->decl_minimal.uid == b->decl_minimal.uid);
311}
312
d94b820b 313/* Set of candidates. */
0674b9d0 314static bitmap candidate_bitmap;
4a8fb1a1 315static hash_table <uid_decl_hasher> candidates;
d94b820b
RG
316
317/* For a candidate UID return the candidates decl. */
318
319static inline tree
320candidate (unsigned uid)
321{
4a8fb1a1
LC
322 tree_node t;
323 t.decl_minimal.uid = uid;
324 return candidates.find_with_hash (&t, static_cast <hashval_t> (uid));
d94b820b 325}
07ffa034 326
7744b697
MJ
327/* Bitmap of candidates which we should try to entirely scalarize away and
328 those which cannot be (because they are and need be used as a whole). */
329static bitmap should_scalarize_away_bitmap, cannot_scalarize_away_bitmap;
330
0674b9d0
MJ
331/* Obstack for creation of fancy names. */
332static struct obstack name_obstack;
6de9cd9a 333
0674b9d0
MJ
334/* Head of a linked list of accesses that need to have its subaccesses
335 propagated to their assignment counterparts. */
336static struct access *work_queue_head;
6de9cd9a 337
07ffa034
MJ
338/* Number of parameters of the analyzed function when doing early ipa SRA. */
339static int func_param_count;
340
341/* scan_function sets the following to true if it encounters a call to
342 __builtin_apply_args. */
343static bool encountered_apply_args;
344
2f3cdcf5
MJ
345/* Set by scan_function when it finds a recursive call. */
346static bool encountered_recursive_call;
347
348/* Set by scan_function when it finds a recursive call with less actual
349 arguments than formal parameters.. */
350static bool encountered_unchangable_recursive_call;
351
07ffa034
MJ
352/* This is a table in which for each basic block and parameter there is a
353 distance (offset + size) in that parameter which is dereferenced and
354 accessed in that BB. */
355static HOST_WIDE_INT *bb_dereferences;
356/* Bitmap of BBs that can cause the function to "stop" progressing by
357 returning, throwing externally, looping infinitely or calling a function
358 which might abort etc.. */
359static bitmap final_bbs;
360
361/* Representative of no accesses at all. */
362static struct access no_accesses_representant;
363
364/* Predicate to test the special value. */
365
366static inline bool
367no_accesses_p (struct access *access)
368{
369 return access == &no_accesses_representant;
370}
371
0674b9d0
MJ
372/* Dump contents of ACCESS to file F in a human friendly way. If GRP is true,
373 representative fields are dumped, otherwise those which only describe the
374 individual access are. */
11fc4275 375
2a45675f
MJ
376static struct
377{
07ffa034
MJ
378 /* Number of processed aggregates is readily available in
379 analyze_all_variable_accesses and so is not stored here. */
380
2a45675f
MJ
381 /* Number of created scalar replacements. */
382 int replacements;
383
384 /* Number of times sra_modify_expr or sra_modify_assign themselves changed an
385 expression. */
386 int exprs;
387
388 /* Number of statements created by generate_subtree_copies. */
389 int subtree_copies;
390
391 /* Number of statements created by load_assign_lhs_subreplacements. */
392 int subreplacements;
393
394 /* Number of times sra_modify_assign has deleted a statement. */
395 int deleted;
396
397 /* Number of times sra_modify_assign has to deal with subaccesses of LHS and
398 RHS reparately due to type conversions or nonexistent matching
399 references. */
400 int separate_lhs_rhs_handling;
401
07ffa034
MJ
402 /* Number of parameters that were removed because they were unused. */
403 int deleted_unused_parameters;
404
405 /* Number of scalars passed as parameters by reference that have been
406 converted to be passed by value. */
407 int scalar_by_ref_to_by_val;
408
409 /* Number of aggregate parameters that were replaced by one or more of their
410 components. */
411 int aggregate_params_reduced;
412
413 /* Numbber of components created when splitting aggregate parameters. */
414 int param_reductions_created;
2a45675f
MJ
415} sra_stats;
416
0674b9d0
MJ
417static void
418dump_access (FILE *f, struct access *access, bool grp)
419{
420 fprintf (f, "access { ");
421 fprintf (f, "base = (%d)'", DECL_UID (access->base));
422 print_generic_expr (f, access->base, 0);
423 fprintf (f, "', offset = " HOST_WIDE_INT_PRINT_DEC, access->offset);
424 fprintf (f, ", size = " HOST_WIDE_INT_PRINT_DEC, access->size);
425 fprintf (f, ", expr = ");
426 print_generic_expr (f, access->expr, 0);
427 fprintf (f, ", type = ");
428 print_generic_expr (f, access->type, 0);
429 if (grp)
1ac93f10
MJ
430 fprintf (f, ", grp_read = %d, grp_write = %d, grp_assignment_read = %d, "
431 "grp_assignment_write = %d, grp_scalar_read = %d, "
432 "grp_scalar_write = %d, grp_total_scalarization = %d, "
4fd73214 433 "grp_hint = %d, grp_covered = %d, "
fc37536b
MJ
434 "grp_unscalarizable_region = %d, grp_unscalarized_data = %d, "
435 "grp_partial_lhs = %d, grp_to_be_replaced = %d, "
be384c10 436 "grp_to_be_debug_replaced = %d, grp_maybe_modified = %d, "
07ffa034 437 "grp_not_necessarilly_dereferenced = %d\n",
1ac93f10
MJ
438 access->grp_read, access->grp_write, access->grp_assignment_read,
439 access->grp_assignment_write, access->grp_scalar_read,
440 access->grp_scalar_write, access->grp_total_scalarization,
4fd73214 441 access->grp_hint, access->grp_covered,
fc37536b
MJ
442 access->grp_unscalarizable_region, access->grp_unscalarized_data,
443 access->grp_partial_lhs, access->grp_to_be_replaced,
be384c10 444 access->grp_to_be_debug_replaced, access->grp_maybe_modified,
07ffa034 445 access->grp_not_necessarilly_dereferenced);
0674b9d0 446 else
1ac93f10 447 fprintf (f, ", write = %d, grp_total_scalarization = %d, "
7744b697 448 "grp_partial_lhs = %d\n",
1ac93f10 449 access->write, access->grp_total_scalarization,
0674b9d0
MJ
450 access->grp_partial_lhs);
451}
6de9cd9a 452
0674b9d0 453/* Dump a subtree rooted in ACCESS to file F, indent by LEVEL. */
a32b97a2 454
0674b9d0
MJ
455static void
456dump_access_tree_1 (FILE *f, struct access *access, int level)
457{
458 do
459 {
460 int i;
d116ffa6 461
0674b9d0
MJ
462 for (i = 0; i < level; i++)
463 fputs ("* ", dump_file);
0890b981 464
0674b9d0 465 dump_access (f, access, true);
510335c8 466
0674b9d0
MJ
467 if (access->first_child)
468 dump_access_tree_1 (f, access->first_child, level + 1);
a32b97a2 469
0674b9d0
MJ
470 access = access->next_sibling;
471 }
472 while (access);
473}
11fc4275 474
0674b9d0
MJ
475/* Dump all access trees for a variable, given the pointer to the first root in
476 ACCESS. */
11fc4275 477
0674b9d0
MJ
478static void
479dump_access_tree (FILE *f, struct access *access)
11fc4275 480{
0674b9d0
MJ
481 for (; access; access = access->next_grp)
482 dump_access_tree_1 (f, access, 0);
483}
11fc4275 484
0674b9d0 485/* Return true iff ACC is non-NULL and has subaccesses. */
11fc4275 486
0674b9d0
MJ
487static inline bool
488access_has_children_p (struct access *acc)
489{
490 return acc && acc->first_child;
491}
11fc4275 492
973a39ae
RG
493/* Return true iff ACC is (partly) covered by at least one replacement. */
494
495static bool
496access_has_replacements_p (struct access *acc)
497{
498 struct access *child;
499 if (acc->grp_to_be_replaced)
500 return true;
501 for (child = acc->first_child; child; child = child->next_sibling)
502 if (access_has_replacements_p (child))
503 return true;
504 return false;
505}
506
0674b9d0
MJ
507/* Return a vector of pointers to accesses for the variable given in BASE or
508 NULL if there is none. */
11fc4275 509
9771b263 510static vec<access_p> *
0674b9d0
MJ
511get_base_access_vector (tree base)
512{
513 void **slot;
514
515 slot = pointer_map_contains (base_access_vec, base);
516 if (!slot)
517 return NULL;
518 else
9771b263 519 return *(vec<access_p> **) slot;
11fc4275
EB
520}
521
0674b9d0
MJ
522/* Find an access with required OFFSET and SIZE in a subtree of accesses rooted
523 in ACCESS. Return NULL if it cannot be found. */
a32b97a2 524
0674b9d0
MJ
525static struct access *
526find_access_in_subtree (struct access *access, HOST_WIDE_INT offset,
527 HOST_WIDE_INT size)
528{
529 while (access && (access->offset != offset || access->size != size))
530 {
531 struct access *child = access->first_child;
a32b97a2 532
0674b9d0
MJ
533 while (child && (child->offset + child->size <= offset))
534 child = child->next_sibling;
535 access = child;
536 }
6de9cd9a 537
0674b9d0
MJ
538 return access;
539}
510335c8 540
0674b9d0 541/* Return the first group representative for DECL or NULL if none exists. */
6de9cd9a 542
0674b9d0
MJ
543static struct access *
544get_first_repr_for_decl (tree base)
6de9cd9a 545{
9771b263 546 vec<access_p> *access_vec;
0674b9d0
MJ
547
548 access_vec = get_base_access_vector (base);
549 if (!access_vec)
550 return NULL;
551
9771b263 552 return (*access_vec)[0];
6de9cd9a
DN
553}
554
0674b9d0
MJ
555/* Find an access representative for the variable BASE and given OFFSET and
556 SIZE. Requires that access trees have already been built. Return NULL if
557 it cannot be found. */
6de9cd9a 558
0674b9d0
MJ
559static struct access *
560get_var_base_offset_size_access (tree base, HOST_WIDE_INT offset,
561 HOST_WIDE_INT size)
6de9cd9a 562{
0674b9d0 563 struct access *access;
6de9cd9a 564
0674b9d0
MJ
565 access = get_first_repr_for_decl (base);
566 while (access && (access->offset + access->size <= offset))
567 access = access->next_grp;
568 if (!access)
569 return NULL;
97e73bd2 570
0674b9d0
MJ
571 return find_access_in_subtree (access, offset, size);
572}
03797ac5 573
0674b9d0
MJ
574/* Add LINK to the linked list of assign links of RACC. */
575static void
576add_link_to_rhs (struct access *racc, struct assign_link *link)
03797ac5 577{
0674b9d0 578 gcc_assert (link->racc == racc);
03797ac5 579
0674b9d0
MJ
580 if (!racc->first_link)
581 {
582 gcc_assert (!racc->last_link);
583 racc->first_link = link;
584 }
585 else
586 racc->last_link->next = link;
6de9cd9a 587
0674b9d0
MJ
588 racc->last_link = link;
589 link->next = NULL;
590}
6de9cd9a 591
0674b9d0
MJ
592/* Move all link structures in their linked list in OLD_RACC to the linked list
593 in NEW_RACC. */
594static void
595relink_to_new_repr (struct access *new_racc, struct access *old_racc)
596{
597 if (!old_racc->first_link)
6de9cd9a 598 {
0674b9d0
MJ
599 gcc_assert (!old_racc->last_link);
600 return;
601 }
6de9cd9a 602
0674b9d0
MJ
603 if (new_racc->first_link)
604 {
605 gcc_assert (!new_racc->last_link->next);
606 gcc_assert (!old_racc->last_link || !old_racc->last_link->next);
6de9cd9a 607
0674b9d0
MJ
608 new_racc->last_link->next = old_racc->first_link;
609 new_racc->last_link = old_racc->last_link;
610 }
611 else
612 {
613 gcc_assert (!new_racc->last_link);
6de9cd9a 614
0674b9d0
MJ
615 new_racc->first_link = old_racc->first_link;
616 new_racc->last_link = old_racc->last_link;
617 }
618 old_racc->first_link = old_racc->last_link = NULL;
619}
6de9cd9a 620
0674b9d0 621/* Add ACCESS to the work queue (which is actually a stack). */
6de9cd9a 622
0674b9d0
MJ
623static void
624add_access_to_work_queue (struct access *access)
625{
626 if (!access->grp_queued)
627 {
628 gcc_assert (!access->next_queued);
629 access->next_queued = work_queue_head;
630 access->grp_queued = 1;
631 work_queue_head = access;
97e73bd2 632 }
0674b9d0 633}
6de9cd9a 634
0674b9d0 635/* Pop an access from the work queue, and return it, assuming there is one. */
6de9cd9a 636
0674b9d0
MJ
637static struct access *
638pop_access_from_work_queue (void)
639{
640 struct access *access = work_queue_head;
641
642 work_queue_head = access->next_queued;
643 access->next_queued = NULL;
644 access->grp_queued = 0;
645 return access;
646}
647
648
649/* Allocate necessary structures. */
650
651static void
652sra_initialize (void)
653{
654 candidate_bitmap = BITMAP_ALLOC (NULL);
4a8fb1a1 655 candidates.create (vec_safe_length (cfun->local_decls) / 2);
7744b697
MJ
656 should_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
657 cannot_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
0674b9d0
MJ
658 gcc_obstack_init (&name_obstack);
659 access_pool = create_alloc_pool ("SRA accesses", sizeof (struct access), 16);
660 link_pool = create_alloc_pool ("SRA links", sizeof (struct assign_link), 16);
661 base_access_vec = pointer_map_create ();
2a45675f 662 memset (&sra_stats, 0, sizeof (sra_stats));
07ffa034 663 encountered_apply_args = false;
2f3cdcf5
MJ
664 encountered_recursive_call = false;
665 encountered_unchangable_recursive_call = false;
6de9cd9a
DN
666}
667
0674b9d0 668/* Hook fed to pointer_map_traverse, deallocate stored vectors. */
35cbb299
KT
669
670static bool
0674b9d0
MJ
671delete_base_accesses (const void *key ATTRIBUTE_UNUSED, void **value,
672 void *data ATTRIBUTE_UNUSED)
35cbb299 673{
9771b263
DN
674 vec<access_p> *access_vec = (vec<access_p> *) *value;
675 vec_free (access_vec);
0674b9d0 676 return true;
35cbb299
KT
677}
678
0674b9d0 679/* Deallocate all general structures. */
6de9cd9a 680
0674b9d0
MJ
681static void
682sra_deinitialize (void)
6de9cd9a 683{
0674b9d0 684 BITMAP_FREE (candidate_bitmap);
4a8fb1a1 685 candidates.dispose ();
7744b697
MJ
686 BITMAP_FREE (should_scalarize_away_bitmap);
687 BITMAP_FREE (cannot_scalarize_away_bitmap);
0674b9d0
MJ
688 free_alloc_pool (access_pool);
689 free_alloc_pool (link_pool);
690 obstack_free (&name_obstack, NULL);
6de9cd9a 691
0674b9d0
MJ
692 pointer_map_traverse (base_access_vec, delete_base_accesses, NULL);
693 pointer_map_destroy (base_access_vec);
694}
6de9cd9a 695
0674b9d0
MJ
696/* Remove DECL from candidates for SRA and write REASON to the dump file if
697 there is one. */
698static void
699disqualify_candidate (tree decl, const char *reason)
700{
d94b820b 701 if (bitmap_clear_bit (candidate_bitmap, DECL_UID (decl)))
4a8fb1a1
LC
702 candidates.clear_slot (candidates.find_slot_with_hash (decl,
703 DECL_UID (decl),
704 NO_INSERT));
6de9cd9a 705
0674b9d0 706 if (dump_file && (dump_flags & TDF_DETAILS))
97e73bd2 707 {
0674b9d0
MJ
708 fprintf (dump_file, "! Disqualifying ");
709 print_generic_expr (dump_file, decl, 0);
710 fprintf (dump_file, " - %s\n", reason);
97e73bd2 711 }
97e73bd2
RH
712}
713
0674b9d0
MJ
714/* Return true iff the type contains a field or an element which does not allow
715 scalarization. */
97e73bd2
RH
716
717static bool
949cfd0a 718type_internals_preclude_sra_p (tree type, const char **msg)
97e73bd2 719{
0674b9d0
MJ
720 tree fld;
721 tree et;
6de9cd9a 722
97e73bd2 723 switch (TREE_CODE (type))
6de9cd9a 724 {
97e73bd2 725 case RECORD_TYPE:
0674b9d0
MJ
726 case UNION_TYPE:
727 case QUAL_UNION_TYPE:
910ad8de 728 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
0674b9d0
MJ
729 if (TREE_CODE (fld) == FIELD_DECL)
730 {
731 tree ft = TREE_TYPE (fld);
6de9cd9a 732
949cfd0a
AK
733 if (TREE_THIS_VOLATILE (fld))
734 {
735 *msg = "volatile structure field";
736 return true;
737 }
738 if (!DECL_FIELD_OFFSET (fld))
739 {
740 *msg = "no structure field offset";
741 return true;
742 }
743 if (!DECL_SIZE (fld))
744 {
745 *msg = "zero structure field size";
746 return true;
747 }
cc269bb6 748 if (!tree_fits_uhwi_p (DECL_FIELD_OFFSET (fld)))
949cfd0a
AK
749 {
750 *msg = "structure field offset not fixed";
751 return true;
752 }
cc269bb6 753 if (!tree_fits_uhwi_p (DECL_SIZE (fld)))
949cfd0a
AK
754 {
755 *msg = "structure field size not fixed";
756 return true;
28afe3fc 757 }
9541ffee 758 if (!tree_fits_shwi_p (bit_position (fld)))
28afe3fc
MJ
759 {
760 *msg = "structure field size too big";
761 return true;
762 }
949cfd0a
AK
763 if (AGGREGATE_TYPE_P (ft)
764 && int_bit_position (fld) % BITS_PER_UNIT != 0)
765 {
766 *msg = "structure field is bit field";
767 return true;
768 }
6de9cd9a 769
949cfd0a 770 if (AGGREGATE_TYPE_P (ft) && type_internals_preclude_sra_p (ft, msg))
0674b9d0
MJ
771 return true;
772 }
6de9cd9a 773
0674b9d0 774 return false;
6de9cd9a 775
97e73bd2 776 case ARRAY_TYPE:
0674b9d0 777 et = TREE_TYPE (type);
6de9cd9a 778
c020c92b 779 if (TYPE_VOLATILE (et))
949cfd0a
AK
780 {
781 *msg = "element type is volatile";
782 return true;
783 }
c020c92b 784
949cfd0a 785 if (AGGREGATE_TYPE_P (et) && type_internals_preclude_sra_p (et, msg))
c020c92b
EB
786 return true;
787
788 return false;
6de9cd9a 789
97e73bd2 790 default:
0674b9d0 791 return false;
97e73bd2
RH
792 }
793}
6de9cd9a 794
07ffa034
MJ
795/* If T is an SSA_NAME, return NULL if it is not a default def or return its
796 base variable if it is. Return T if it is not an SSA_NAME. */
797
798static tree
799get_ssa_base_param (tree t)
800{
801 if (TREE_CODE (t) == SSA_NAME)
802 {
803 if (SSA_NAME_IS_DEFAULT_DEF (t))
804 return SSA_NAME_VAR (t);
805 else
806 return NULL_TREE;
807 }
808 return t;
809}
810
811/* Mark a dereference of BASE of distance DIST in a basic block tht STMT
812 belongs to, unless the BB has already been marked as a potentially
813 final. */
814
815static void
816mark_parm_dereference (tree base, HOST_WIDE_INT dist, gimple stmt)
817{
818 basic_block bb = gimple_bb (stmt);
819 int idx, parm_index = 0;
820 tree parm;
821
822 if (bitmap_bit_p (final_bbs, bb->index))
823 return;
824
825 for (parm = DECL_ARGUMENTS (current_function_decl);
826 parm && parm != base;
910ad8de 827 parm = DECL_CHAIN (parm))
07ffa034
MJ
828 parm_index++;
829
830 gcc_assert (parm_index < func_param_count);
831
832 idx = bb->index * func_param_count + parm_index;
833 if (bb_dereferences[idx] < dist)
834 bb_dereferences[idx] = dist;
835}
836
7744b697
MJ
837/* Allocate an access structure for BASE, OFFSET and SIZE, clear it, fill in
838 the three fields. Also add it to the vector of accesses corresponding to
839 the base. Finally, return the new access. */
840
841static struct access *
842create_access_1 (tree base, HOST_WIDE_INT offset, HOST_WIDE_INT size)
843{
9771b263 844 vec<access_p> *v;
7744b697
MJ
845 struct access *access;
846 void **slot;
847
848 access = (struct access *) pool_alloc (access_pool);
849 memset (access, 0, sizeof (struct access));
850 access->base = base;
851 access->offset = offset;
852 access->size = size;
853
854 slot = pointer_map_contains (base_access_vec, base);
855 if (slot)
9771b263 856 v = (vec<access_p> *) *slot;
7744b697 857 else
9771b263 858 vec_alloc (v, 32);
7744b697 859
9771b263 860 v->safe_push (access);
7744b697 861
9771b263
DN
862 *((vec<access_p> **)
863 pointer_map_insert (base_access_vec, base)) = v;
7744b697
MJ
864
865 return access;
866}
867
0674b9d0
MJ
868/* Create and insert access for EXPR. Return created access, or NULL if it is
869 not possible. */
6de9cd9a 870
0674b9d0 871static struct access *
07ffa034 872create_access (tree expr, gimple stmt, bool write)
6de9cd9a 873{
0674b9d0 874 struct access *access;
0674b9d0
MJ
875 HOST_WIDE_INT offset, size, max_size;
876 tree base = expr;
07ffa034 877 bool ptr, unscalarizable_region = false;
97e73bd2 878
0674b9d0 879 base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
6de9cd9a 880
70f34814
RG
881 if (sra_mode == SRA_MODE_EARLY_IPA
882 && TREE_CODE (base) == MEM_REF)
07ffa034
MJ
883 {
884 base = get_ssa_base_param (TREE_OPERAND (base, 0));
885 if (!base)
886 return NULL;
887 ptr = true;
888 }
889 else
890 ptr = false;
891
0674b9d0
MJ
892 if (!DECL_P (base) || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
893 return NULL;
6de9cd9a 894
07ffa034 895 if (sra_mode == SRA_MODE_EARLY_IPA)
0674b9d0 896 {
07ffa034
MJ
897 if (size < 0 || size != max_size)
898 {
899 disqualify_candidate (base, "Encountered a variable sized access.");
900 return NULL;
901 }
1faab08d
MJ
902 if (TREE_CODE (expr) == COMPONENT_REF
903 && DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
07ffa034 904 {
1faab08d 905 disqualify_candidate (base, "Encountered a bit-field access.");
07ffa034
MJ
906 return NULL;
907 }
1faab08d 908 gcc_checking_assert ((offset % BITS_PER_UNIT) == 0);
fa27426e 909
07ffa034
MJ
910 if (ptr)
911 mark_parm_dereference (base, offset + size, stmt);
912 }
913 else
6de9cd9a 914 {
07ffa034
MJ
915 if (size != max_size)
916 {
917 size = max_size;
918 unscalarizable_region = true;
919 }
920 if (size < 0)
921 {
922 disqualify_candidate (base, "Encountered an unconstrained access.");
923 return NULL;
924 }
0674b9d0 925 }
fa27426e 926
7744b697 927 access = create_access_1 (base, offset, size);
0674b9d0
MJ
928 access->expr = expr;
929 access->type = TREE_TYPE (expr);
930 access->write = write;
931 access->grp_unscalarizable_region = unscalarizable_region;
07ffa034 932 access->stmt = stmt;
11fc4275 933
5e9fba51
EB
934 if (TREE_CODE (expr) == COMPONENT_REF
935 && DECL_NONADDRESSABLE_P (TREE_OPERAND (expr, 1)))
936 access->non_addressable = 1;
937
7744b697
MJ
938 return access;
939}
fa27426e 940
510335c8 941
7744b697 942/* Return true iff TYPE is a RECORD_TYPE with fields that are either of gimple
76f76cd0 943 register types or (recursively) records with only these two kinds of fields.
37ccfc46 944 It also returns false if any of these records contains a bit-field. */
fa27426e 945
7744b697
MJ
946static bool
947type_consists_of_records_p (tree type)
948{
949 tree fld;
950
951 if (TREE_CODE (type) != RECORD_TYPE)
952 return false;
953
910ad8de 954 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
7744b697
MJ
955 if (TREE_CODE (fld) == FIELD_DECL)
956 {
957 tree ft = TREE_TYPE (fld);
958
36b86f4a
JZ
959 if (DECL_BIT_FIELD (fld))
960 return false;
961
7744b697
MJ
962 if (!is_gimple_reg_type (ft)
963 && !type_consists_of_records_p (ft))
964 return false;
965 }
76f76cd0 966
7744b697
MJ
967 return true;
968}
969
970/* Create total_scalarization accesses for all scalar type fields in DECL that
971 must be of a RECORD_TYPE conforming to type_consists_of_records_p. BASE
972 must be the top-most VAR_DECL representing the variable, OFFSET must be the
fc734382
MJ
973 offset of DECL within BASE. REF must be the memory reference expression for
974 the given decl. */
7744b697
MJ
975
976static void
fc734382
MJ
977completely_scalarize_record (tree base, tree decl, HOST_WIDE_INT offset,
978 tree ref)
7744b697
MJ
979{
980 tree fld, decl_type = TREE_TYPE (decl);
981
910ad8de 982 for (fld = TYPE_FIELDS (decl_type); fld; fld = DECL_CHAIN (fld))
7744b697
MJ
983 if (TREE_CODE (fld) == FIELD_DECL)
984 {
985 HOST_WIDE_INT pos = offset + int_bit_position (fld);
986 tree ft = TREE_TYPE (fld);
fc734382
MJ
987 tree nref = build3 (COMPONENT_REF, TREE_TYPE (fld), ref, fld,
988 NULL_TREE);
7744b697
MJ
989
990 if (is_gimple_reg_type (ft))
991 {
992 struct access *access;
993 HOST_WIDE_INT size;
7744b697 994
ae7e9ddd 995 size = tree_to_uhwi (DECL_SIZE (fld));
7744b697 996 access = create_access_1 (base, pos, size);
fc734382 997 access->expr = nref;
7744b697 998 access->type = ft;
1ac93f10 999 access->grp_total_scalarization = 1;
7744b697
MJ
1000 /* Accesses for intraprocedural SRA can have their stmt NULL. */
1001 }
1002 else
fc734382 1003 completely_scalarize_record (base, fld, pos, nref);
7744b697 1004 }
6de9cd9a
DN
1005}
1006
1ac93f10
MJ
1007/* Create total_scalarization accesses for all scalar type fields in VAR and
1008 for VAR a a whole. VAR must be of a RECORD_TYPE conforming to
1009 type_consists_of_records_p. */
1010
1011static void
1012completely_scalarize_var (tree var)
1013{
ae7e9ddd 1014 HOST_WIDE_INT size = tree_to_uhwi (DECL_SIZE (var));
1ac93f10
MJ
1015 struct access *access;
1016
1017 access = create_access_1 (var, 0, size);
1018 access->expr = var;
1019 access->type = TREE_TYPE (var);
1020 access->grp_total_scalarization = 1;
1021
1022 completely_scalarize_record (var, var, 0, var);
1023}
6de9cd9a 1024
cc524fc7
AM
1025/* Return true if REF has an VIEW_CONVERT_EXPR somewhere in it. */
1026
1027static inline bool
1028contains_view_convert_expr_p (const_tree ref)
1029{
1030 while (handled_component_p (ref))
1031 {
1032 if (TREE_CODE (ref) == VIEW_CONVERT_EXPR)
1033 return true;
1034 ref = TREE_OPERAND (ref, 0);
1035 }
1036
1037 return false;
1038}
1039
0674b9d0
MJ
1040/* Search the given tree for a declaration by skipping handled components and
1041 exclude it from the candidates. */
1042
1043static void
1044disqualify_base_of_expr (tree t, const char *reason)
6de9cd9a 1045{
70f34814
RG
1046 t = get_base_address (t);
1047 if (sra_mode == SRA_MODE_EARLY_IPA
1048 && TREE_CODE (t) == MEM_REF)
1049 t = get_ssa_base_param (TREE_OPERAND (t, 0));
07ffa034
MJ
1050
1051 if (t && DECL_P (t))
0674b9d0 1052 disqualify_candidate (t, reason);
97e73bd2 1053}
19114537 1054
0674b9d0
MJ
1055/* Scan expression EXPR and create access structures for all accesses to
1056 candidates for scalarization. Return the created access or NULL if none is
1057 created. */
6de9cd9a 1058
0674b9d0 1059static struct access *
6cbd3b6a 1060build_access_from_expr_1 (tree expr, gimple stmt, bool write)
97e73bd2 1061{
0674b9d0 1062 struct access *ret = NULL;
0674b9d0 1063 bool partial_ref;
6de9cd9a 1064
0674b9d0
MJ
1065 if (TREE_CODE (expr) == BIT_FIELD_REF
1066 || TREE_CODE (expr) == IMAGPART_EXPR
1067 || TREE_CODE (expr) == REALPART_EXPR)
1068 {
1069 expr = TREE_OPERAND (expr, 0);
1070 partial_ref = true;
1071 }
1072 else
1073 partial_ref = false;
6de9cd9a 1074
0674b9d0
MJ
1075 /* We need to dive through V_C_Es in order to get the size of its parameter
1076 and not the result type. Ada produces such statements. We are also
1077 capable of handling the topmost V_C_E but not any of those buried in other
1078 handled components. */
1079 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
1080 expr = TREE_OPERAND (expr, 0);
1081
1082 if (contains_view_convert_expr_p (expr))
1083 {
1084 disqualify_base_of_expr (expr, "V_C_E under a different handled "
1085 "component.");
1086 return NULL;
1087 }
fa27426e 1088
0674b9d0 1089 switch (TREE_CODE (expr))
fa27426e 1090 {
70f34814
RG
1091 case MEM_REF:
1092 if (TREE_CODE (TREE_OPERAND (expr, 0)) != ADDR_EXPR
1093 && sra_mode != SRA_MODE_EARLY_IPA)
07ffa034
MJ
1094 return NULL;
1095 /* fall through */
fa27426e
RH
1096 case VAR_DECL:
1097 case PARM_DECL:
1098 case RESULT_DECL:
0674b9d0
MJ
1099 case COMPONENT_REF:
1100 case ARRAY_REF:
1101 case ARRAY_RANGE_REF:
07ffa034 1102 ret = create_access (expr, stmt, write);
0674b9d0 1103 break;
fa27426e 1104
0674b9d0
MJ
1105 default:
1106 break;
1107 }
fa27426e 1108
0674b9d0
MJ
1109 if (write && partial_ref && ret)
1110 ret->grp_partial_lhs = 1;
11fc4275 1111
0674b9d0
MJ
1112 return ret;
1113}
fa27426e 1114
6cbd3b6a
MJ
1115/* Scan expression EXPR and create access structures for all accesses to
1116 candidates for scalarization. Return true if any access has been inserted.
1117 STMT must be the statement from which the expression is taken, WRITE must be
1118 true if the expression is a store and false otherwise. */
510335c8 1119
0674b9d0 1120static bool
6cbd3b6a 1121build_access_from_expr (tree expr, gimple stmt, bool write)
0674b9d0 1122{
7744b697
MJ
1123 struct access *access;
1124
6cbd3b6a 1125 access = build_access_from_expr_1 (expr, stmt, write);
7744b697
MJ
1126 if (access)
1127 {
1128 /* This means the aggregate is accesses as a whole in a way other than an
1129 assign statement and thus cannot be removed even if we had a scalar
1130 replacement for everything. */
1131 if (cannot_scalarize_away_bitmap)
1132 bitmap_set_bit (cannot_scalarize_away_bitmap, DECL_UID (access->base));
1133 return true;
1134 }
1135 return false;
6de9cd9a
DN
1136}
1137
0674b9d0
MJ
1138/* Disqualify LHS and RHS for scalarization if STMT must end its basic block in
1139 modes in which it matters, return true iff they have been disqualified. RHS
1140 may be NULL, in that case ignore it. If we scalarize an aggregate in
1141 intra-SRA we may need to add statements after each statement. This is not
1142 possible if a statement unconditionally has to end the basic block. */
1143static bool
1144disqualify_ops_if_throwing_stmt (gimple stmt, tree lhs, tree rhs)
6de9cd9a 1145{
07ffa034
MJ
1146 if ((sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
1147 && (stmt_can_throw_internal (stmt) || stmt_ends_bb_p (stmt)))
0674b9d0
MJ
1148 {
1149 disqualify_base_of_expr (lhs, "LHS of a throwing stmt.");
1150 if (rhs)
1151 disqualify_base_of_expr (rhs, "RHS of a throwing stmt.");
1152 return true;
1153 }
1154 return false;
1155}
6de9cd9a 1156
073a8998 1157/* Scan expressions occurring in STMT, create access structures for all accesses
6cbd3b6a 1158 to candidates for scalarization and remove those candidates which occur in
0674b9d0
MJ
1159 statements or expressions that prevent them from being split apart. Return
1160 true if any access has been inserted. */
97e73bd2 1161
6cbd3b6a
MJ
1162static bool
1163build_accesses_from_assign (gimple stmt)
0674b9d0 1164{
6cbd3b6a 1165 tree lhs, rhs;
0674b9d0 1166 struct access *lacc, *racc;
6de9cd9a 1167
47598145
MM
1168 if (!gimple_assign_single_p (stmt)
1169 /* Scope clobbers don't influence scalarization. */
1170 || gimple_clobber_p (stmt))
6cbd3b6a 1171 return false;
6de9cd9a 1172
6cbd3b6a
MJ
1173 lhs = gimple_assign_lhs (stmt);
1174 rhs = gimple_assign_rhs1 (stmt);
6de9cd9a 1175
6cbd3b6a
MJ
1176 if (disqualify_ops_if_throwing_stmt (stmt, lhs, rhs))
1177 return false;
97e73bd2 1178
6cbd3b6a
MJ
1179 racc = build_access_from_expr_1 (rhs, stmt, false);
1180 lacc = build_access_from_expr_1 (lhs, stmt, true);
97e73bd2 1181
fc37536b 1182 if (lacc)
3515a00b 1183 lacc->grp_assignment_write = 1;
fc37536b 1184
77620011
MJ
1185 if (racc)
1186 {
1187 racc->grp_assignment_read = 1;
1188 if (should_scalarize_away_bitmap && !gimple_has_volatile_ops (stmt)
1189 && !is_gimple_reg_type (racc->type))
1190 bitmap_set_bit (should_scalarize_away_bitmap, DECL_UID (racc->base));
1191 }
7744b697 1192
0674b9d0 1193 if (lacc && racc
07ffa034 1194 && (sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
0674b9d0
MJ
1195 && !lacc->grp_unscalarizable_region
1196 && !racc->grp_unscalarizable_region
6cbd3b6a 1197 && AGGREGATE_TYPE_P (TREE_TYPE (lhs))
0674b9d0
MJ
1198 && lacc->size == racc->size
1199 && useless_type_conversion_p (lacc->type, racc->type))
97e73bd2 1200 {
0674b9d0 1201 struct assign_link *link;
11fc4275 1202
0674b9d0
MJ
1203 link = (struct assign_link *) pool_alloc (link_pool);
1204 memset (link, 0, sizeof (struct assign_link));
97e73bd2 1205
0674b9d0
MJ
1206 link->lacc = lacc;
1207 link->racc = racc;
97e73bd2 1208
0674b9d0 1209 add_link_to_rhs (racc, link);
97e73bd2
RH
1210 }
1211
6cbd3b6a 1212 return lacc || racc;
97e73bd2
RH
1213}
1214
0674b9d0
MJ
1215/* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine
1216 GIMPLE_ASM operands with memory constrains which cannot be scalarized. */
97e73bd2 1217
0674b9d0
MJ
1218static bool
1219asm_visit_addr (gimple stmt ATTRIBUTE_UNUSED, tree op,
1220 void *data ATTRIBUTE_UNUSED)
97e73bd2 1221{
2ea9dc64
RG
1222 op = get_base_address (op);
1223 if (op
1224 && DECL_P (op))
0674b9d0 1225 disqualify_candidate (op, "Non-scalarizable GIMPLE_ASM operand.");
97e73bd2 1226
0674b9d0 1227 return false;
97e73bd2
RH
1228}
1229
2f3cdcf5
MJ
1230/* Return true iff callsite CALL has at least as many actual arguments as there
1231 are formal parameters of the function currently processed by IPA-SRA. */
1232
1233static inline bool
1234callsite_has_enough_arguments_p (gimple call)
1235{
1236 return gimple_call_num_args (call) >= (unsigned) func_param_count;
1237}
97e73bd2 1238
6cbd3b6a
MJ
1239/* Scan function and look for interesting expressions and create access
1240 structures for them. Return true iff any access is created. */
d4d3aad9 1241
0674b9d0 1242static bool
6cbd3b6a 1243scan_function (void)
97e73bd2
RH
1244{
1245 basic_block bb;
0674b9d0 1246 bool ret = false;
97e73bd2
RH
1247
1248 FOR_EACH_BB (bb)
97e73bd2 1249 {
6cbd3b6a
MJ
1250 gimple_stmt_iterator gsi;
1251 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
97e73bd2 1252 {
0674b9d0 1253 gimple stmt = gsi_stmt (gsi);
6cbd3b6a
MJ
1254 tree t;
1255 unsigned i;
7ec49257 1256
6cbd3b6a 1257 if (final_bbs && stmt_can_throw_external (stmt))
07ffa034 1258 bitmap_set_bit (final_bbs, bb->index);
0674b9d0 1259 switch (gimple_code (stmt))
510335c8 1260 {
0674b9d0 1261 case GIMPLE_RETURN:
6cbd3b6a
MJ
1262 t = gimple_return_retval (stmt);
1263 if (t != NULL_TREE)
1264 ret |= build_access_from_expr (t, stmt, false);
1265 if (final_bbs)
07ffa034 1266 bitmap_set_bit (final_bbs, bb->index);
0674b9d0 1267 break;
510335c8 1268
0674b9d0 1269 case GIMPLE_ASSIGN:
6cbd3b6a 1270 ret |= build_accesses_from_assign (stmt);
0674b9d0 1271 break;
510335c8 1272
0674b9d0 1273 case GIMPLE_CALL:
0674b9d0 1274 for (i = 0; i < gimple_call_num_args (stmt); i++)
6cbd3b6a
MJ
1275 ret |= build_access_from_expr (gimple_call_arg (stmt, i),
1276 stmt, false);
510335c8 1277
6cbd3b6a 1278 if (sra_mode == SRA_MODE_EARLY_IPA)
07ffa034
MJ
1279 {
1280 tree dest = gimple_call_fndecl (stmt);
1281 int flags = gimple_call_flags (stmt);
1282
2f3cdcf5
MJ
1283 if (dest)
1284 {
1285 if (DECL_BUILT_IN_CLASS (dest) == BUILT_IN_NORMAL
1286 && DECL_FUNCTION_CODE (dest) == BUILT_IN_APPLY_ARGS)
1287 encountered_apply_args = true;
9e401b63 1288 if (recursive_call_p (current_function_decl, dest))
2f3cdcf5
MJ
1289 {
1290 encountered_recursive_call = true;
1291 if (!callsite_has_enough_arguments_p (stmt))
1292 encountered_unchangable_recursive_call = true;
1293 }
1294 }
07ffa034
MJ
1295
1296 if (final_bbs
1297 && (flags & (ECF_CONST | ECF_PURE)) == 0)
1298 bitmap_set_bit (final_bbs, bb->index);
1299 }
1300
6cbd3b6a
MJ
1301 t = gimple_call_lhs (stmt);
1302 if (t && !disqualify_ops_if_throwing_stmt (stmt, t, NULL))
1303 ret |= build_access_from_expr (t, stmt, true);
0674b9d0 1304 break;
510335c8 1305
0674b9d0 1306 case GIMPLE_ASM:
6cbd3b6a
MJ
1307 walk_stmt_load_store_addr_ops (stmt, NULL, NULL, NULL,
1308 asm_visit_addr);
1309 if (final_bbs)
1310 bitmap_set_bit (final_bbs, bb->index);
1311
0674b9d0
MJ
1312 for (i = 0; i < gimple_asm_ninputs (stmt); i++)
1313 {
6cbd3b6a
MJ
1314 t = TREE_VALUE (gimple_asm_input_op (stmt, i));
1315 ret |= build_access_from_expr (t, stmt, false);
0674b9d0
MJ
1316 }
1317 for (i = 0; i < gimple_asm_noutputs (stmt); i++)
1318 {
6cbd3b6a
MJ
1319 t = TREE_VALUE (gimple_asm_output_op (stmt, i));
1320 ret |= build_access_from_expr (t, stmt, true);
0674b9d0 1321 }
07ffa034 1322 break;
97e73bd2 1323
0674b9d0
MJ
1324 default:
1325 break;
1326 }
97e73bd2 1327 }
87c476a2 1328 }
97e73bd2 1329
0674b9d0 1330 return ret;
97e73bd2
RH
1331}
1332
0674b9d0
MJ
1333/* Helper of QSORT function. There are pointers to accesses in the array. An
1334 access is considered smaller than another if it has smaller offset or if the
1335 offsets are the same but is size is bigger. */
97e73bd2 1336
0674b9d0
MJ
1337static int
1338compare_access_positions (const void *a, const void *b)
1339{
1340 const access_p *fp1 = (const access_p *) a;
1341 const access_p *fp2 = (const access_p *) b;
1342 const access_p f1 = *fp1;
1343 const access_p f2 = *fp2;
1344
1345 if (f1->offset != f2->offset)
1346 return f1->offset < f2->offset ? -1 : 1;
1347
1348 if (f1->size == f2->size)
1349 {
d05fe940
MJ
1350 if (f1->type == f2->type)
1351 return 0;
0674b9d0 1352 /* Put any non-aggregate type before any aggregate type. */
d05fe940 1353 else if (!is_gimple_reg_type (f1->type)
9fda11a2 1354 && is_gimple_reg_type (f2->type))
0674b9d0
MJ
1355 return 1;
1356 else if (is_gimple_reg_type (f1->type)
1357 && !is_gimple_reg_type (f2->type))
1358 return -1;
9fda11a2
MJ
1359 /* Put any complex or vector type before any other scalar type. */
1360 else if (TREE_CODE (f1->type) != COMPLEX_TYPE
1361 && TREE_CODE (f1->type) != VECTOR_TYPE
1362 && (TREE_CODE (f2->type) == COMPLEX_TYPE
1363 || TREE_CODE (f2->type) == VECTOR_TYPE))
1364 return 1;
1365 else if ((TREE_CODE (f1->type) == COMPLEX_TYPE
1366 || TREE_CODE (f1->type) == VECTOR_TYPE)
1367 && TREE_CODE (f2->type) != COMPLEX_TYPE
1368 && TREE_CODE (f2->type) != VECTOR_TYPE)
1369 return -1;
0674b9d0
MJ
1370 /* Put the integral type with the bigger precision first. */
1371 else if (INTEGRAL_TYPE_P (f1->type)
9fda11a2 1372 && INTEGRAL_TYPE_P (f2->type))
d05fe940 1373 return TYPE_PRECISION (f2->type) - TYPE_PRECISION (f1->type);
0674b9d0
MJ
1374 /* Put any integral type with non-full precision last. */
1375 else if (INTEGRAL_TYPE_P (f1->type)
1376 && (TREE_INT_CST_LOW (TYPE_SIZE (f1->type))
1377 != TYPE_PRECISION (f1->type)))
1378 return 1;
1379 else if (INTEGRAL_TYPE_P (f2->type)
1380 && (TREE_INT_CST_LOW (TYPE_SIZE (f2->type))
1381 != TYPE_PRECISION (f2->type)))
1382 return -1;
1383 /* Stabilize the sort. */
1384 return TYPE_UID (f1->type) - TYPE_UID (f2->type);
1385 }
1386
1387 /* We want the bigger accesses first, thus the opposite operator in the next
1388 line: */
1389 return f1->size > f2->size ? -1 : 1;
1390}
1391
1392
1393/* Append a name of the declaration to the name obstack. A helper function for
1394 make_fancy_name. */
0bca51f0
DN
1395
1396static void
0674b9d0 1397make_fancy_decl_name (tree decl)
0bca51f0 1398{
0674b9d0 1399 char buffer[32];
6de9cd9a 1400
0674b9d0
MJ
1401 tree name = DECL_NAME (decl);
1402 if (name)
1403 obstack_grow (&name_obstack, IDENTIFIER_POINTER (name),
1404 IDENTIFIER_LENGTH (name));
1405 else
1406 {
1407 sprintf (buffer, "D%u", DECL_UID (decl));
1408 obstack_grow (&name_obstack, buffer, strlen (buffer));
1409 }
726a989a 1410}
38635499 1411
0674b9d0 1412/* Helper for make_fancy_name. */
d116ffa6
RH
1413
1414static void
0674b9d0 1415make_fancy_name_1 (tree expr)
d116ffa6 1416{
0674b9d0
MJ
1417 char buffer[32];
1418 tree index;
1419
1420 if (DECL_P (expr))
d116ffa6 1421 {
0674b9d0
MJ
1422 make_fancy_decl_name (expr);
1423 return;
d116ffa6 1424 }
6de9cd9a 1425
0674b9d0 1426 switch (TREE_CODE (expr))
6de9cd9a 1427 {
0674b9d0
MJ
1428 case COMPONENT_REF:
1429 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1430 obstack_1grow (&name_obstack, '$');
1431 make_fancy_decl_name (TREE_OPERAND (expr, 1));
1432 break;
6de9cd9a 1433
0674b9d0
MJ
1434 case ARRAY_REF:
1435 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1436 obstack_1grow (&name_obstack, '$');
1437 /* Arrays with only one element may not have a constant as their
1438 index. */
1439 index = TREE_OPERAND (expr, 1);
1440 if (TREE_CODE (index) != INTEGER_CST)
1441 break;
1442 sprintf (buffer, HOST_WIDE_INT_PRINT_DEC, TREE_INT_CST_LOW (index));
1443 obstack_grow (&name_obstack, buffer, strlen (buffer));
70f34814 1444 break;
6de9cd9a 1445
70f34814
RG
1446 case ADDR_EXPR:
1447 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1448 break;
1449
1450 case MEM_REF:
1451 make_fancy_name_1 (TREE_OPERAND (expr, 0));
1452 if (!integer_zerop (TREE_OPERAND (expr, 1)))
1453 {
1454 obstack_1grow (&name_obstack, '$');
1455 sprintf (buffer, HOST_WIDE_INT_PRINT_DEC,
1456 TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)));
1457 obstack_grow (&name_obstack, buffer, strlen (buffer));
1458 }
0674b9d0 1459 break;
6de9cd9a 1460
0674b9d0
MJ
1461 case BIT_FIELD_REF:
1462 case REALPART_EXPR:
1463 case IMAGPART_EXPR:
1464 gcc_unreachable (); /* we treat these as scalars. */
1465 break;
97e73bd2 1466 default:
0674b9d0 1467 break;
97e73bd2 1468 }
6de9cd9a
DN
1469}
1470
0674b9d0 1471/* Create a human readable name for replacement variable of ACCESS. */
6de9cd9a 1472
0674b9d0
MJ
1473static char *
1474make_fancy_name (tree expr)
97e73bd2 1475{
0674b9d0
MJ
1476 make_fancy_name_1 (expr);
1477 obstack_1grow (&name_obstack, '\0');
1478 return XOBFINISH (&name_obstack, char *);
97e73bd2
RH
1479}
1480
d242d063
MJ
1481/* Construct a MEM_REF that would reference a part of aggregate BASE of type
1482 EXP_TYPE at the given OFFSET. If BASE is something for which
1483 get_addr_base_and_unit_offset returns NULL, gsi must be non-NULL and is used
1484 to insert new statements either before or below the current one as specified
4bd7b70b
MJ
1485 by INSERT_AFTER. This function is not capable of handling bitfields.
1486
1487 BASE must be either a declaration or a memory reference that has correct
1488 alignment ifformation embeded in it (e.g. a pre-existing one in SRA). */
70f34814 1489
d242d063 1490tree
e4b5cace 1491build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset,
d242d063
MJ
1492 tree exp_type, gimple_stmt_iterator *gsi,
1493 bool insert_after)
1494{
1495 tree prev_base = base;
1496 tree off;
4ca890e2 1497 tree mem_ref;
d242d063 1498 HOST_WIDE_INT base_offset;
aff86594
RG
1499 unsigned HOST_WIDE_INT misalign;
1500 unsigned int align;
d242d063
MJ
1501
1502 gcc_checking_assert (offset % BITS_PER_UNIT == 0);
4bd7b70b 1503 get_object_alignment_1 (base, &align, &misalign);
d242d063
MJ
1504 base = get_addr_base_and_unit_offset (base, &base_offset);
1505
1506 /* get_addr_base_and_unit_offset returns NULL for references with a variable
1507 offset such as array[var_index]. */
1508 if (!base)
1509 {
1510 gimple stmt;
1511 tree tmp, addr;
1512
1513 gcc_checking_assert (gsi);
83d5977e 1514 tmp = make_ssa_name (build_pointer_type (TREE_TYPE (prev_base)), NULL);
d242d063 1515 addr = build_fold_addr_expr (unshare_expr (prev_base));
1d60cc55 1516 STRIP_USELESS_TYPE_CONVERSION (addr);
d242d063 1517 stmt = gimple_build_assign (tmp, addr);
e4b5cace 1518 gimple_set_location (stmt, loc);
d242d063
MJ
1519 if (insert_after)
1520 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
1521 else
1522 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
d242d063
MJ
1523
1524 off = build_int_cst (reference_alias_ptr_type (prev_base),
1525 offset / BITS_PER_UNIT);
1526 base = tmp;
1527 }
1528 else if (TREE_CODE (base) == MEM_REF)
1529 {
1530 off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
1531 base_offset + offset / BITS_PER_UNIT);
d35936ab 1532 off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
d242d063
MJ
1533 base = unshare_expr (TREE_OPERAND (base, 0));
1534 }
1535 else
1536 {
1537 off = build_int_cst (reference_alias_ptr_type (base),
1538 base_offset + offset / BITS_PER_UNIT);
1539 base = build_fold_addr_expr (unshare_expr (base));
1540 }
1541
4bd7b70b 1542 misalign = (misalign + offset) & (align - 1);
aff86594
RG
1543 if (misalign != 0)
1544 align = (misalign & -misalign);
1545 if (align < TYPE_ALIGN (exp_type))
1546 exp_type = build_aligned_type (exp_type, align);
1547
4ca890e2
JJ
1548 mem_ref = fold_build2_loc (loc, MEM_REF, exp_type, base, off);
1549 if (TREE_THIS_VOLATILE (prev_base))
1550 TREE_THIS_VOLATILE (mem_ref) = 1;
1551 if (TREE_SIDE_EFFECTS (prev_base))
1552 TREE_SIDE_EFFECTS (mem_ref) = 1;
1553 return mem_ref;
d242d063
MJ
1554}
1555
1556/* Construct a memory reference to a part of an aggregate BASE at the given
36e57e16
MJ
1557 OFFSET and of the same type as MODEL. In case this is a reference to a
1558 bit-field, the function will replicate the last component_ref of model's
1559 expr to access it. GSI and INSERT_AFTER have the same meaning as in
1560 build_ref_for_offset. */
d242d063
MJ
1561
1562static tree
e4b5cace 1563build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
d242d063
MJ
1564 struct access *model, gimple_stmt_iterator *gsi,
1565 bool insert_after)
1566{
36e57e16
MJ
1567 if (TREE_CODE (model->expr) == COMPONENT_REF
1568 && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
d242d063 1569 {
36e57e16
MJ
1570 /* This access represents a bit-field. */
1571 tree t, exp_type, fld = TREE_OPERAND (model->expr, 1);
1572
1573 offset -= int_bit_position (fld);
1574 exp_type = TREE_TYPE (TREE_OPERAND (model->expr, 0));
1575 t = build_ref_for_offset (loc, base, offset, exp_type, gsi, insert_after);
1576 return fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (fld), t, fld,
1577 NULL_TREE);
d242d063 1578 }
36e57e16
MJ
1579 else
1580 return build_ref_for_offset (loc, base, offset, model->type,
1581 gsi, insert_after);
d242d063
MJ
1582}
1583
be384c10
MJ
1584/* Attempt to build a memory reference that we could but into a gimple
1585 debug_bind statement. Similar to build_ref_for_model but punts if it has to
1586 create statements and return s NULL instead. This function also ignores
1587 alignment issues and so its results should never end up in non-debug
1588 statements. */
1589
1590static tree
1591build_debug_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
1592 struct access *model)
1593{
1594 HOST_WIDE_INT base_offset;
1595 tree off;
1596
1597 if (TREE_CODE (model->expr) == COMPONENT_REF
1598 && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
1599 return NULL_TREE;
1600
1601 base = get_addr_base_and_unit_offset (base, &base_offset);
1602 if (!base)
1603 return NULL_TREE;
1604 if (TREE_CODE (base) == MEM_REF)
1605 {
1606 off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
1607 base_offset + offset / BITS_PER_UNIT);
1608 off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
1609 base = unshare_expr (TREE_OPERAND (base, 0));
1610 }
1611 else
1612 {
1613 off = build_int_cst (reference_alias_ptr_type (base),
1614 base_offset + offset / BITS_PER_UNIT);
1615 base = build_fold_addr_expr (unshare_expr (base));
1616 }
1617
1618 return fold_build2_loc (loc, MEM_REF, model->type, base, off);
1619}
1620
d242d063
MJ
1621/* Construct a memory reference consisting of component_refs and array_refs to
1622 a part of an aggregate *RES (which is of type TYPE). The requested part
1623 should have type EXP_TYPE at be the given OFFSET. This function might not
1624 succeed, it returns true when it does and only then *RES points to something
1625 meaningful. This function should be used only to build expressions that we
1626 might need to present to user (e.g. in warnings). In all other situations,
1627 build_ref_for_model or build_ref_for_offset should be used instead. */
510335c8
AO
1628
1629static bool
d242d063
MJ
1630build_user_friendly_ref_for_offset (tree *res, tree type, HOST_WIDE_INT offset,
1631 tree exp_type)
45f94ec7 1632{
0674b9d0 1633 while (1)
510335c8 1634 {
0674b9d0 1635 tree fld;
22fc64b4 1636 tree tr_size, index, minidx;
0674b9d0 1637 HOST_WIDE_INT el_size;
510335c8 1638
0674b9d0 1639 if (offset == 0 && exp_type
71d4d3eb 1640 && types_compatible_p (exp_type, type))
0674b9d0 1641 return true;
510335c8 1642
0674b9d0 1643 switch (TREE_CODE (type))
510335c8 1644 {
0674b9d0
MJ
1645 case UNION_TYPE:
1646 case QUAL_UNION_TYPE:
1647 case RECORD_TYPE:
910ad8de 1648 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
0674b9d0
MJ
1649 {
1650 HOST_WIDE_INT pos, size;
ca8d9092 1651 tree tr_pos, expr, *expr_ptr;
510335c8 1652
0674b9d0
MJ
1653 if (TREE_CODE (fld) != FIELD_DECL)
1654 continue;
4c44c315 1655
ca8d9092 1656 tr_pos = bit_position (fld);
cc269bb6 1657 if (!tr_pos || !tree_fits_uhwi_p (tr_pos))
ca8d9092
EB
1658 continue;
1659 pos = TREE_INT_CST_LOW (tr_pos);
0674b9d0 1660 gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0);
a1aa1701 1661 tr_size = DECL_SIZE (fld);
cc269bb6 1662 if (!tr_size || !tree_fits_uhwi_p (tr_size))
a1aa1701 1663 continue;
ca8d9092 1664 size = TREE_INT_CST_LOW (tr_size);
fff08961
MJ
1665 if (size == 0)
1666 {
1667 if (pos != offset)
1668 continue;
1669 }
1670 else if (pos > offset || (pos + size) <= offset)
0674b9d0 1671 continue;
2fb5f2af 1672
d242d063
MJ
1673 expr = build3 (COMPONENT_REF, TREE_TYPE (fld), *res, fld,
1674 NULL_TREE);
1675 expr_ptr = &expr;
1676 if (build_user_friendly_ref_for_offset (expr_ptr, TREE_TYPE (fld),
1677 offset - pos, exp_type))
0674b9d0 1678 {
d242d063 1679 *res = expr;
0674b9d0
MJ
1680 return true;
1681 }
1682 }
1683 return false;
ff1fe457 1684
0674b9d0
MJ
1685 case ARRAY_TYPE:
1686 tr_size = TYPE_SIZE (TREE_TYPE (type));
cc269bb6 1687 if (!tr_size || !tree_fits_uhwi_p (tr_size))
0674b9d0 1688 return false;
ae7e9ddd 1689 el_size = tree_to_uhwi (tr_size);
ff1fe457 1690
22fc64b4 1691 minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
746e119f 1692 if (TREE_CODE (minidx) != INTEGER_CST || el_size == 0)
22fc64b4 1693 return false;
d242d063
MJ
1694 index = build_int_cst (TYPE_DOMAIN (type), offset / el_size);
1695 if (!integer_zerop (minidx))
d35936ab 1696 index = int_const_binop (PLUS_EXPR, index, minidx);
d242d063
MJ
1697 *res = build4 (ARRAY_REF, TREE_TYPE (type), *res, index,
1698 NULL_TREE, NULL_TREE);
0674b9d0
MJ
1699 offset = offset % el_size;
1700 type = TREE_TYPE (type);
1701 break;
510335c8 1702
0674b9d0
MJ
1703 default:
1704 if (offset != 0)
1705 return false;
510335c8 1706
0674b9d0
MJ
1707 if (exp_type)
1708 return false;
1709 else
1710 return true;
1711 }
d573123d 1712 }
45f94ec7
AO
1713}
1714
1e9fb3de
MJ
1715/* Return true iff TYPE is stdarg va_list type. */
1716
1717static inline bool
1718is_va_list_type (tree type)
1719{
1720 return TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (va_list_type_node);
1721}
1722
949cfd0a
AK
1723/* Print message to dump file why a variable was rejected. */
1724
1725static void
1726reject (tree var, const char *msg)
1727{
1728 if (dump_file && (dump_flags & TDF_DETAILS))
1729 {
1730 fprintf (dump_file, "Rejected (%d): %s: ", DECL_UID (var), msg);
1731 print_generic_expr (dump_file, var, 0);
1732 fprintf (dump_file, "\n");
1733 }
1734}
1735
d94b820b
RG
1736/* Return true if VAR is a candidate for SRA. */
1737
1738static bool
1739maybe_add_sra_candidate (tree var)
1740{
1741 tree type = TREE_TYPE (var);
1742 const char *msg;
4a8fb1a1 1743 tree_node **slot;
d94b820b
RG
1744
1745 if (!AGGREGATE_TYPE_P (type))
1746 {
1747 reject (var, "not aggregate");
1748 return false;
1749 }
1750 if (needs_to_live_in_memory (var))
1751 {
1752 reject (var, "needs to live in memory");
1753 return false;
1754 }
1755 if (TREE_THIS_VOLATILE (var))
1756 {
1757 reject (var, "is volatile");
1758 return false;
1759 }
1760 if (!COMPLETE_TYPE_P (type))
1761 {
1762 reject (var, "has incomplete type");
1763 return false;
1764 }
cc269bb6 1765 if (!tree_fits_uhwi_p (TYPE_SIZE (type)))
d94b820b
RG
1766 {
1767 reject (var, "type size not fixed");
1768 return false;
1769 }
ae7e9ddd 1770 if (tree_to_uhwi (TYPE_SIZE (type)) == 0)
d94b820b
RG
1771 {
1772 reject (var, "type size is zero");
1773 return false;
1774 }
1775 if (type_internals_preclude_sra_p (type, &msg))
1776 {
1777 reject (var, msg);
1778 return false;
1779 }
1780 if (/* Fix for PR 41089. tree-stdarg.c needs to have va_lists intact but
1781 we also want to schedule it rather late. Thus we ignore it in
1782 the early pass. */
1783 (sra_mode == SRA_MODE_EARLY_INTRA
1784 && is_va_list_type (type)))
1785 {
1786 reject (var, "is va_list");
1787 return false;
1788 }
1789
1790 bitmap_set_bit (candidate_bitmap, DECL_UID (var));
4a8fb1a1
LC
1791 slot = candidates.find_slot_with_hash (var, DECL_UID (var), INSERT);
1792 *slot = var;
d94b820b
RG
1793
1794 if (dump_file && (dump_flags & TDF_DETAILS))
1795 {
1796 fprintf (dump_file, "Candidate (%d): ", DECL_UID (var));
1797 print_generic_expr (dump_file, var, 0);
1798 fprintf (dump_file, "\n");
1799 }
1800
1801 return true;
1802}
1803
0674b9d0
MJ
1804/* The very first phase of intraprocedural SRA. It marks in candidate_bitmap
1805 those with type which is suitable for scalarization. */
aee91ff0 1806
0674b9d0
MJ
1807static bool
1808find_var_candidates (void)
1809{
d94b820b
RG
1810 tree var, parm;
1811 unsigned int i;
0674b9d0 1812 bool ret = false;
510335c8 1813
d94b820b
RG
1814 for (parm = DECL_ARGUMENTS (current_function_decl);
1815 parm;
1816 parm = DECL_CHAIN (parm))
1817 ret |= maybe_add_sra_candidate (parm);
1818
1819 FOR_EACH_LOCAL_DECL (cfun, i, var)
510335c8 1820 {
d94b820b 1821 if (TREE_CODE (var) != VAR_DECL)
0674b9d0 1822 continue;
0674b9d0 1823
d94b820b 1824 ret |= maybe_add_sra_candidate (var);
510335c8
AO
1825 }
1826
0674b9d0
MJ
1827 return ret;
1828}
510335c8 1829
0674b9d0
MJ
1830/* Sort all accesses for the given variable, check for partial overlaps and
1831 return NULL if there are any. If there are none, pick a representative for
1832 each combination of offset and size and create a linked list out of them.
1833 Return the pointer to the first representative and make sure it is the first
1834 one in the vector of accesses. */
510335c8 1835
0674b9d0
MJ
1836static struct access *
1837sort_and_splice_var_accesses (tree var)
1838{
1839 int i, j, access_count;
1840 struct access *res, **prev_acc_ptr = &res;
9771b263 1841 vec<access_p> *access_vec;
0674b9d0
MJ
1842 bool first = true;
1843 HOST_WIDE_INT low = -1, high = 0;
510335c8 1844
0674b9d0
MJ
1845 access_vec = get_base_access_vector (var);
1846 if (!access_vec)
1847 return NULL;
9771b263 1848 access_count = access_vec->length ();
510335c8 1849
0674b9d0 1850 /* Sort by <OFFSET, SIZE>. */
9771b263 1851 access_vec->qsort (compare_access_positions);
510335c8 1852
0674b9d0
MJ
1853 i = 0;
1854 while (i < access_count)
510335c8 1855 {
9771b263 1856 struct access *access = (*access_vec)[i];
fef94f76 1857 bool grp_write = access->write;
0674b9d0 1858 bool grp_read = !access->write;
4fd73214
MJ
1859 bool grp_scalar_write = access->write
1860 && is_gimple_reg_type (access->type);
1861 bool grp_scalar_read = !access->write
1862 && is_gimple_reg_type (access->type);
77620011 1863 bool grp_assignment_read = access->grp_assignment_read;
fc37536b 1864 bool grp_assignment_write = access->grp_assignment_write;
4fd73214 1865 bool multiple_scalar_reads = false;
1ac93f10 1866 bool total_scalarization = access->grp_total_scalarization;
0674b9d0
MJ
1867 bool grp_partial_lhs = access->grp_partial_lhs;
1868 bool first_scalar = is_gimple_reg_type (access->type);
1869 bool unscalarizable_region = access->grp_unscalarizable_region;
510335c8 1870
0674b9d0 1871 if (first || access->offset >= high)
510335c8 1872 {
0674b9d0
MJ
1873 first = false;
1874 low = access->offset;
1875 high = access->offset + access->size;
510335c8 1876 }
0674b9d0
MJ
1877 else if (access->offset > low && access->offset + access->size > high)
1878 return NULL;
510335c8 1879 else
0674b9d0
MJ
1880 gcc_assert (access->offset >= low
1881 && access->offset + access->size <= high);
1882
1883 j = i + 1;
1884 while (j < access_count)
510335c8 1885 {
9771b263 1886 struct access *ac2 = (*access_vec)[j];
0674b9d0
MJ
1887 if (ac2->offset != access->offset || ac2->size != access->size)
1888 break;
fef94f76 1889 if (ac2->write)
4fd73214
MJ
1890 {
1891 grp_write = true;
1892 grp_scalar_write = (grp_scalar_write
1893 || is_gimple_reg_type (ac2->type));
1894 }
fef94f76
MJ
1895 else
1896 {
4fd73214
MJ
1897 grp_read = true;
1898 if (is_gimple_reg_type (ac2->type))
1899 {
1900 if (grp_scalar_read)
1901 multiple_scalar_reads = true;
1902 else
1903 grp_scalar_read = true;
1904 }
fef94f76 1905 }
77620011 1906 grp_assignment_read |= ac2->grp_assignment_read;
fc37536b 1907 grp_assignment_write |= ac2->grp_assignment_write;
0674b9d0
MJ
1908 grp_partial_lhs |= ac2->grp_partial_lhs;
1909 unscalarizable_region |= ac2->grp_unscalarizable_region;
1ac93f10 1910 total_scalarization |= ac2->grp_total_scalarization;
0674b9d0
MJ
1911 relink_to_new_repr (access, ac2);
1912
1913 /* If there are both aggregate-type and scalar-type accesses with
1914 this combination of size and offset, the comparison function
1915 should have put the scalars first. */
1916 gcc_assert (first_scalar || !is_gimple_reg_type (ac2->type));
1917 ac2->group_representative = access;
1918 j++;
510335c8
AO
1919 }
1920
0674b9d0
MJ
1921 i = j;
1922
1923 access->group_representative = access;
fef94f76 1924 access->grp_write = grp_write;
0674b9d0 1925 access->grp_read = grp_read;
4fd73214
MJ
1926 access->grp_scalar_read = grp_scalar_read;
1927 access->grp_scalar_write = grp_scalar_write;
77620011 1928 access->grp_assignment_read = grp_assignment_read;
fc37536b 1929 access->grp_assignment_write = grp_assignment_write;
4fd73214 1930 access->grp_hint = multiple_scalar_reads || total_scalarization;
1ac93f10 1931 access->grp_total_scalarization = total_scalarization;
0674b9d0
MJ
1932 access->grp_partial_lhs = grp_partial_lhs;
1933 access->grp_unscalarizable_region = unscalarizable_region;
1934 if (access->first_link)
1935 add_access_to_work_queue (access);
1936
1937 *prev_acc_ptr = access;
1938 prev_acc_ptr = &access->next_grp;
510335c8
AO
1939 }
1940
9771b263 1941 gcc_assert (res == (*access_vec)[0]);
0674b9d0 1942 return res;
510335c8
AO
1943}
1944
0674b9d0
MJ
1945/* Create a variable for the given ACCESS which determines the type, name and a
1946 few other properties. Return the variable declaration and store it also to
1947 ACCESS->replacement. */
97e73bd2 1948
0674b9d0 1949static tree
13714310 1950create_access_replacement (struct access *access)
6de9cd9a 1951{
0674b9d0 1952 tree repl;
97e73bd2 1953
be384c10
MJ
1954 if (access->grp_to_be_debug_replaced)
1955 {
1956 repl = create_tmp_var_raw (access->type, NULL);
1957 DECL_CONTEXT (repl) = current_function_decl;
1958 }
1959 else
1960 repl = create_tmp_var (access->type, "SR");
3f5f6592
RG
1961 if (TREE_CODE (access->type) == COMPLEX_TYPE
1962 || TREE_CODE (access->type) == VECTOR_TYPE)
1963 {
1964 if (!access->grp_partial_lhs)
1965 DECL_GIMPLE_REG_P (repl) = 1;
1966 }
1967 else if (access->grp_partial_lhs
1968 && is_gimple_reg_type (access->type))
1969 TREE_ADDRESSABLE (repl) = 1;
0563fe8b 1970
0674b9d0
MJ
1971 DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base);
1972 DECL_ARTIFICIAL (repl) = 1;
ec24771f 1973 DECL_IGNORED_P (repl) = DECL_IGNORED_P (access->base);
0674b9d0
MJ
1974
1975 if (DECL_NAME (access->base)
1976 && !DECL_IGNORED_P (access->base)
1977 && !DECL_ARTIFICIAL (access->base))
6de9cd9a 1978 {
0674b9d0 1979 char *pretty_name = make_fancy_name (access->expr);
64366d35 1980 tree debug_expr = unshare_expr_without_location (access->expr), d;
70b5e7dc 1981 bool fail = false;
0674b9d0
MJ
1982
1983 DECL_NAME (repl) = get_identifier (pretty_name);
1984 obstack_free (&name_obstack, pretty_name);
1985
823e9473
JJ
1986 /* Get rid of any SSA_NAMEs embedded in debug_expr,
1987 as DECL_DEBUG_EXPR isn't considered when looking for still
1988 used SSA_NAMEs and thus they could be freed. All debug info
1989 generation cares is whether something is constant or variable
1990 and that get_ref_base_and_extent works properly on the
70b5e7dc
RG
1991 expression. It cannot handle accesses at a non-constant offset
1992 though, so just give up in those cases. */
9430b7ba
JJ
1993 for (d = debug_expr;
1994 !fail && (handled_component_p (d) || TREE_CODE (d) == MEM_REF);
70b5e7dc 1995 d = TREE_OPERAND (d, 0))
823e9473
JJ
1996 switch (TREE_CODE (d))
1997 {
1998 case ARRAY_REF:
1999 case ARRAY_RANGE_REF:
2000 if (TREE_OPERAND (d, 1)
70b5e7dc
RG
2001 && TREE_CODE (TREE_OPERAND (d, 1)) != INTEGER_CST)
2002 fail = true;
823e9473 2003 if (TREE_OPERAND (d, 3)
70b5e7dc
RG
2004 && TREE_CODE (TREE_OPERAND (d, 3)) != INTEGER_CST)
2005 fail = true;
823e9473
JJ
2006 /* FALLTHRU */
2007 case COMPONENT_REF:
2008 if (TREE_OPERAND (d, 2)
70b5e7dc
RG
2009 && TREE_CODE (TREE_OPERAND (d, 2)) != INTEGER_CST)
2010 fail = true;
823e9473 2011 break;
9430b7ba
JJ
2012 case MEM_REF:
2013 if (TREE_CODE (TREE_OPERAND (d, 0)) != ADDR_EXPR)
2014 fail = true;
2015 else
2016 d = TREE_OPERAND (d, 0);
2017 break;
823e9473
JJ
2018 default:
2019 break;
2020 }
70b5e7dc
RG
2021 if (!fail)
2022 {
2023 SET_DECL_DEBUG_EXPR (repl, debug_expr);
839b422f 2024 DECL_HAS_DEBUG_EXPR_P (repl) = 1;
70b5e7dc 2025 }
9271a43c
MJ
2026 if (access->grp_no_warning)
2027 TREE_NO_WARNING (repl) = 1;
2028 else
2029 TREE_NO_WARNING (repl) = TREE_NO_WARNING (access->base);
97e73bd2 2030 }
ec24771f
MJ
2031 else
2032 TREE_NO_WARNING (repl) = 1;
0674b9d0
MJ
2033
2034 if (dump_file)
97e73bd2 2035 {
be384c10
MJ
2036 if (access->grp_to_be_debug_replaced)
2037 {
2038 fprintf (dump_file, "Created a debug-only replacement for ");
2039 print_generic_expr (dump_file, access->base, 0);
2040 fprintf (dump_file, " offset: %u, size: %u\n",
2041 (unsigned) access->offset, (unsigned) access->size);
2042 }
2043 else
2044 {
2045 fprintf (dump_file, "Created a replacement for ");
2046 print_generic_expr (dump_file, access->base, 0);
2047 fprintf (dump_file, " offset: %u, size: %u: ",
2048 (unsigned) access->offset, (unsigned) access->size);
2049 print_generic_expr (dump_file, repl, 0);
2050 fprintf (dump_file, "\n");
2051 }
97e73bd2 2052 }
2a45675f 2053 sra_stats.replacements++;
0674b9d0
MJ
2054
2055 return repl;
97e73bd2 2056}
6de9cd9a 2057
0674b9d0 2058/* Return ACCESS scalar replacement, create it if it does not exist yet. */
6de9cd9a 2059
0674b9d0
MJ
2060static inline tree
2061get_access_replacement (struct access *access)
97e73bd2 2062{
b48b3fc4 2063 gcc_checking_assert (access->replacement_decl);
5feb49f0
MJ
2064 return access->replacement_decl;
2065}
2066
2067
0674b9d0
MJ
2068/* Build a subtree of accesses rooted in *ACCESS, and move the pointer in the
2069 linked list along the way. Stop when *ACCESS is NULL or the access pointed
591d4f4a
MJ
2070 to it is not "within" the root. Return false iff some accesses partially
2071 overlap. */
e4521d11 2072
591d4f4a 2073static bool
0674b9d0
MJ
2074build_access_subtree (struct access **access)
2075{
2076 struct access *root = *access, *last_child = NULL;
2077 HOST_WIDE_INT limit = root->offset + root->size;
6de9cd9a 2078
0674b9d0
MJ
2079 *access = (*access)->next_grp;
2080 while (*access && (*access)->offset + (*access)->size <= limit)
97e73bd2 2081 {
0674b9d0
MJ
2082 if (!last_child)
2083 root->first_child = *access;
2084 else
2085 last_child->next_sibling = *access;
2086 last_child = *access;
6de9cd9a 2087
591d4f4a
MJ
2088 if (!build_access_subtree (access))
2089 return false;
97e73bd2 2090 }
591d4f4a
MJ
2091
2092 if (*access && (*access)->offset < limit)
2093 return false;
2094
2095 return true;
97e73bd2 2096}
6de9cd9a 2097
0674b9d0 2098/* Build a tree of access representatives, ACCESS is the pointer to the first
591d4f4a
MJ
2099 one, others are linked in a list by the next_grp field. Return false iff
2100 some accesses partially overlap. */
6de9cd9a 2101
591d4f4a 2102static bool
0674b9d0 2103build_access_trees (struct access *access)
6de9cd9a 2104{
0674b9d0 2105 while (access)
bfeebecf 2106 {
0674b9d0 2107 struct access *root = access;
6de9cd9a 2108
591d4f4a
MJ
2109 if (!build_access_subtree (&access))
2110 return false;
0674b9d0 2111 root->next_grp = access;
6de9cd9a 2112 }
591d4f4a 2113 return true;
97e73bd2 2114}
6de9cd9a 2115
22fc64b4
MJ
2116/* Return true if expr contains some ARRAY_REFs into a variable bounded
2117 array. */
2118
2119static bool
2120expr_with_var_bounded_array_refs_p (tree expr)
2121{
2122 while (handled_component_p (expr))
2123 {
2124 if (TREE_CODE (expr) == ARRAY_REF
9541ffee 2125 && !tree_fits_shwi_p (array_ref_low_bound (expr)))
22fc64b4
MJ
2126 return true;
2127 expr = TREE_OPERAND (expr, 0);
2128 }
2129 return false;
2130}
2131
0674b9d0 2132/* Analyze the subtree of accesses rooted in ROOT, scheduling replacements when
77620011
MJ
2133 both seeming beneficial and when ALLOW_REPLACEMENTS allows it. Also set all
2134 sorts of access flags appropriately along the way, notably always set
2135 grp_read and grp_assign_read according to MARK_READ and grp_write when
fc37536b
MJ
2136 MARK_WRITE is true.
2137
2138 Creating a replacement for a scalar access is considered beneficial if its
2139 grp_hint is set (this means we are either attempting total scalarization or
2140 there is more than one direct read access) or according to the following
2141 table:
2142
4fd73214 2143 Access written to through a scalar type (once or more times)
fc37536b 2144 |
4fd73214 2145 | Written to in an assignment statement
fc37536b 2146 | |
4fd73214 2147 | | Access read as scalar _once_
fc37536b 2148 | | |
4fd73214 2149 | | | Read in an assignment statement
fc37536b
MJ
2150 | | | |
2151 | | | | Scalarize Comment
2152-----------------------------------------------------------------------------
2153 0 0 0 0 No access for the scalar
2154 0 0 0 1 No access for the scalar
2155 0 0 1 0 No Single read - won't help
2156 0 0 1 1 No The same case
2157 0 1 0 0 No access for the scalar
2158 0 1 0 1 No access for the scalar
2159 0 1 1 0 Yes s = *g; return s.i;
2160 0 1 1 1 Yes The same case as above
2161 1 0 0 0 No Won't help
2162 1 0 0 1 Yes s.i = 1; *g = s;
2163 1 0 1 0 Yes s.i = 5; g = s.i;
2164 1 0 1 1 Yes The same case as above
2165 1 1 0 0 No Won't help.
2166 1 1 0 1 Yes s.i = 1; *g = s;
2167 1 1 1 0 Yes s = *g; return s.i;
2168 1 1 1 1 Yes Any of the above yeses */
71956db3 2169
0674b9d0 2170static bool
d9c77712
MJ
2171analyze_access_subtree (struct access *root, struct access *parent,
2172 bool allow_replacements)
71956db3 2173{
0674b9d0
MJ
2174 struct access *child;
2175 HOST_WIDE_INT limit = root->offset + root->size;
2176 HOST_WIDE_INT covered_to = root->offset;
2177 bool scalar = is_gimple_reg_type (root->type);
2178 bool hole = false, sth_created = false;
71956db3 2179
d9c77712 2180 if (parent)
fc37536b 2181 {
d9c77712
MJ
2182 if (parent->grp_read)
2183 root->grp_read = 1;
2184 if (parent->grp_assignment_read)
2185 root->grp_assignment_read = 1;
2186 if (parent->grp_write)
2187 root->grp_write = 1;
2188 if (parent->grp_assignment_write)
2189 root->grp_assignment_write = 1;
1ac93f10
MJ
2190 if (parent->grp_total_scalarization)
2191 root->grp_total_scalarization = 1;
fc37536b 2192 }
0674b9d0
MJ
2193
2194 if (root->grp_unscalarizable_region)
2195 allow_replacements = false;
2196
22fc64b4
MJ
2197 if (allow_replacements && expr_with_var_bounded_array_refs_p (root->expr))
2198 allow_replacements = false;
2199
0674b9d0 2200 for (child = root->first_child; child; child = child->next_sibling)
97e73bd2 2201 {
1ac93f10 2202 hole |= covered_to < child->offset;
d9c77712
MJ
2203 sth_created |= analyze_access_subtree (child, root,
2204 allow_replacements && !scalar);
0674b9d0
MJ
2205
2206 root->grp_unscalarized_data |= child->grp_unscalarized_data;
1ac93f10
MJ
2207 root->grp_total_scalarization &= child->grp_total_scalarization;
2208 if (child->grp_covered)
2209 covered_to += child->size;
2210 else
2211 hole = true;
97e73bd2 2212 }
6de9cd9a 2213
fef94f76
MJ
2214 if (allow_replacements && scalar && !root->first_child
2215 && (root->grp_hint
4fd73214
MJ
2216 || ((root->grp_scalar_read || root->grp_assignment_read)
2217 && (root->grp_scalar_write || root->grp_assignment_write))))
97e73bd2 2218 {
8085c586
RG
2219 /* Always create access replacements that cover the whole access.
2220 For integral types this means the precision has to match.
2221 Avoid assumptions based on the integral type kind, too. */
2222 if (INTEGRAL_TYPE_P (root->type)
2223 && (TREE_CODE (root->type) != INTEGER_TYPE
2224 || TYPE_PRECISION (root->type) != root->size)
2225 /* But leave bitfield accesses alone. */
e8257960
RG
2226 && (TREE_CODE (root->expr) != COMPONENT_REF
2227 || !DECL_BIT_FIELD (TREE_OPERAND (root->expr, 1))))
da990dc0
MJ
2228 {
2229 tree rt = root->type;
e8257960
RG
2230 gcc_assert ((root->offset % BITS_PER_UNIT) == 0
2231 && (root->size % BITS_PER_UNIT) == 0);
8085c586 2232 root->type = build_nonstandard_integer_type (root->size,
da990dc0 2233 TYPE_UNSIGNED (rt));
8085c586
RG
2234 root->expr = build_ref_for_offset (UNKNOWN_LOCATION,
2235 root->base, root->offset,
2236 root->type, NULL, false);
da990dc0 2237
b48b3fc4
MJ
2238 if (dump_file && (dump_flags & TDF_DETAILS))
2239 {
2240 fprintf (dump_file, "Changing the type of a replacement for ");
2241 print_generic_expr (dump_file, root->base, 0);
2242 fprintf (dump_file, " offset: %u, size: %u ",
2243 (unsigned) root->offset, (unsigned) root->size);
2244 fprintf (dump_file, " to an integer.\n");
2245 }
97e73bd2 2246 }
6de9cd9a 2247
0674b9d0 2248 root->grp_to_be_replaced = 1;
b48b3fc4 2249 root->replacement_decl = create_access_replacement (root);
0674b9d0
MJ
2250 sth_created = true;
2251 hole = false;
97e73bd2 2252 }
1ac93f10
MJ
2253 else
2254 {
4267a4a6 2255 if (allow_replacements
be384c10 2256 && scalar && !root->first_child
207b5956
MJ
2257 && (root->grp_scalar_write || root->grp_assignment_write)
2258 && !bitmap_bit_p (cannot_scalarize_away_bitmap,
2259 DECL_UID (root->base)))
be384c10
MJ
2260 {
2261 gcc_checking_assert (!root->grp_scalar_read
2262 && !root->grp_assignment_read);
4267a4a6
MJ
2263 sth_created = true;
2264 if (MAY_HAVE_DEBUG_STMTS)
be384c10 2265 {
4267a4a6 2266 root->grp_to_be_debug_replaced = 1;
b48b3fc4 2267 root->replacement_decl = create_access_replacement (root);
be384c10
MJ
2268 }
2269 }
2270
1ac93f10
MJ
2271 if (covered_to < limit)
2272 hole = true;
2273 if (scalar)
2274 root->grp_total_scalarization = 0;
2275 }
402a3dec 2276
4267a4a6
MJ
2277 if (!hole || root->grp_total_scalarization)
2278 root->grp_covered = 1;
2279 else if (root->grp_write || TREE_CODE (root->base) == PARM_DECL)
0674b9d0 2280 root->grp_unscalarized_data = 1; /* not covered and written to */
4267a4a6 2281 return sth_created;
97e73bd2 2282}
6de9cd9a 2283
0674b9d0
MJ
2284/* Analyze all access trees linked by next_grp by the means of
2285 analyze_access_subtree. */
fa588429 2286static bool
0674b9d0 2287analyze_access_trees (struct access *access)
fa588429 2288{
0674b9d0 2289 bool ret = false;
fa588429 2290
0674b9d0 2291 while (access)
fa588429 2292 {
d9c77712 2293 if (analyze_access_subtree (access, NULL, true))
0674b9d0
MJ
2294 ret = true;
2295 access = access->next_grp;
fa588429
RH
2296 }
2297
2298 return ret;
2299}
2300
0674b9d0
MJ
2301/* Return true iff a potential new child of LACC at offset OFFSET and with size
2302 SIZE would conflict with an already existing one. If exactly such a child
2303 already exists in LACC, store a pointer to it in EXACT_MATCH. */
6de9cd9a 2304
0674b9d0
MJ
2305static bool
2306child_would_conflict_in_lacc (struct access *lacc, HOST_WIDE_INT norm_offset,
2307 HOST_WIDE_INT size, struct access **exact_match)
6de9cd9a 2308{
0674b9d0
MJ
2309 struct access *child;
2310
2311 for (child = lacc->first_child; child; child = child->next_sibling)
2312 {
2313 if (child->offset == norm_offset && child->size == size)
2314 {
2315 *exact_match = child;
2316 return true;
2317 }
6de9cd9a 2318
0674b9d0
MJ
2319 if (child->offset < norm_offset + size
2320 && child->offset + child->size > norm_offset)
2321 return true;
2322 }
2323
2324 return false;
6de9cd9a
DN
2325}
2326
0674b9d0
MJ
2327/* Create a new child access of PARENT, with all properties just like MODEL
2328 except for its offset and with its grp_write false and grp_read true.
4a50e99c
MJ
2329 Return the new access or NULL if it cannot be created. Note that this access
2330 is created long after all splicing and sorting, it's not located in any
2331 access vector and is automatically a representative of its group. */
0674b9d0
MJ
2332
2333static struct access *
2334create_artificial_child_access (struct access *parent, struct access *model,
2335 HOST_WIDE_INT new_offset)
6de9cd9a 2336{
0674b9d0
MJ
2337 struct access *access;
2338 struct access **child;
d242d063 2339 tree expr = parent->base;
6de9cd9a 2340
0674b9d0 2341 gcc_assert (!model->grp_unscalarizable_region);
4a50e99c 2342
0674b9d0
MJ
2343 access = (struct access *) pool_alloc (access_pool);
2344 memset (access, 0, sizeof (struct access));
9271a43c
MJ
2345 if (!build_user_friendly_ref_for_offset (&expr, TREE_TYPE (expr), new_offset,
2346 model->type))
2347 {
2348 access->grp_no_warning = true;
2349 expr = build_ref_for_model (EXPR_LOCATION (parent->base), parent->base,
2350 new_offset, model, NULL, false);
2351 }
2352
0674b9d0 2353 access->base = parent->base;
4a50e99c 2354 access->expr = expr;
0674b9d0
MJ
2355 access->offset = new_offset;
2356 access->size = model->size;
0674b9d0
MJ
2357 access->type = model->type;
2358 access->grp_write = true;
2359 access->grp_read = false;
510335c8 2360
0674b9d0
MJ
2361 child = &parent->first_child;
2362 while (*child && (*child)->offset < new_offset)
2363 child = &(*child)->next_sibling;
510335c8 2364
0674b9d0
MJ
2365 access->next_sibling = *child;
2366 *child = access;
510335c8 2367
0674b9d0
MJ
2368 return access;
2369}
510335c8 2370
0674b9d0
MJ
2371
2372/* Propagate all subaccesses of RACC across an assignment link to LACC. Return
2373 true if any new subaccess was created. Additionally, if RACC is a scalar
4a50e99c 2374 access but LACC is not, change the type of the latter, if possible. */
510335c8
AO
2375
2376static bool
8a1326b3 2377propagate_subaccesses_across_link (struct access *lacc, struct access *racc)
510335c8 2378{
0674b9d0
MJ
2379 struct access *rchild;
2380 HOST_WIDE_INT norm_delta = lacc->offset - racc->offset;
0674b9d0 2381 bool ret = false;
510335c8 2382
0674b9d0
MJ
2383 if (is_gimple_reg_type (lacc->type)
2384 || lacc->grp_unscalarizable_region
2385 || racc->grp_unscalarizable_region)
2386 return false;
510335c8 2387
d3705186 2388 if (is_gimple_reg_type (racc->type))
510335c8 2389 {
d3705186 2390 if (!lacc->first_child && !racc->first_child)
4a50e99c 2391 {
d3705186
MJ
2392 tree t = lacc->base;
2393
2394 lacc->type = racc->type;
2395 if (build_user_friendly_ref_for_offset (&t, TREE_TYPE (t),
2396 lacc->offset, racc->type))
2397 lacc->expr = t;
2398 else
2399 {
2400 lacc->expr = build_ref_for_model (EXPR_LOCATION (lacc->base),
2401 lacc->base, lacc->offset,
2402 racc, NULL, false);
2403 lacc->grp_no_warning = true;
2404 }
4a50e99c 2405 }
0674b9d0
MJ
2406 return false;
2407 }
510335c8 2408
0674b9d0
MJ
2409 for (rchild = racc->first_child; rchild; rchild = rchild->next_sibling)
2410 {
2411 struct access *new_acc = NULL;
2412 HOST_WIDE_INT norm_offset = rchild->offset + norm_delta;
510335c8 2413
0674b9d0
MJ
2414 if (rchild->grp_unscalarizable_region)
2415 continue;
510335c8 2416
0674b9d0
MJ
2417 if (child_would_conflict_in_lacc (lacc, norm_offset, rchild->size,
2418 &new_acc))
510335c8 2419 {
fef94f76
MJ
2420 if (new_acc)
2421 {
2422 rchild->grp_hint = 1;
2423 new_acc->grp_hint |= new_acc->grp_read;
2424 if (rchild->first_child)
8a1326b3 2425 ret |= propagate_subaccesses_across_link (new_acc, rchild);
fef94f76 2426 }
0674b9d0 2427 continue;
510335c8 2428 }
0674b9d0 2429
fef94f76 2430 rchild->grp_hint = 1;
0674b9d0 2431 new_acc = create_artificial_child_access (lacc, rchild, norm_offset);
4a50e99c
MJ
2432 if (new_acc)
2433 {
2434 ret = true;
2435 if (racc->first_child)
8a1326b3 2436 propagate_subaccesses_across_link (new_acc, rchild);
4a50e99c 2437 }
510335c8
AO
2438 }
2439
2440 return ret;
2441}
2442
0674b9d0 2443/* Propagate all subaccesses across assignment links. */
510335c8
AO
2444
2445static void
0674b9d0 2446propagate_all_subaccesses (void)
510335c8 2447{
0674b9d0 2448 while (work_queue_head)
510335c8 2449 {
0674b9d0
MJ
2450 struct access *racc = pop_access_from_work_queue ();
2451 struct assign_link *link;
510335c8 2452
0674b9d0 2453 gcc_assert (racc->first_link);
510335c8 2454
0674b9d0 2455 for (link = racc->first_link; link; link = link->next)
510335c8 2456 {
0674b9d0 2457 struct access *lacc = link->lacc;
510335c8 2458
0674b9d0
MJ
2459 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
2460 continue;
2461 lacc = lacc->group_representative;
8a1326b3 2462 if (propagate_subaccesses_across_link (lacc, racc)
0674b9d0
MJ
2463 && lacc->first_link)
2464 add_access_to_work_queue (lacc);
2465 }
2466 }
2467}
510335c8 2468
0674b9d0
MJ
2469/* Go through all accesses collected throughout the (intraprocedural) analysis
2470 stage, exclude overlapping ones, identify representatives and build trees
2471 out of them, making decisions about scalarization on the way. Return true
2472 iff there are any to-be-scalarized variables after this stage. */
088371ac 2473
0674b9d0
MJ
2474static bool
2475analyze_all_variable_accesses (void)
2476{
2a45675f 2477 int res = 0;
aecd4d81
RG
2478 bitmap tmp = BITMAP_ALLOC (NULL);
2479 bitmap_iterator bi;
7744b697
MJ
2480 unsigned i, max_total_scalarization_size;
2481
2482 max_total_scalarization_size = UNITS_PER_WORD * BITS_PER_UNIT
2483 * MOVE_RATIO (optimize_function_for_speed_p (cfun));
2484
2485 EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
2486 if (bitmap_bit_p (should_scalarize_away_bitmap, i)
2487 && !bitmap_bit_p (cannot_scalarize_away_bitmap, i))
2488 {
d94b820b 2489 tree var = candidate (i);
7744b697
MJ
2490
2491 if (TREE_CODE (var) == VAR_DECL
7744b697
MJ
2492 && type_consists_of_records_p (TREE_TYPE (var)))
2493 {
7d362f6c 2494 if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (var)))
e923ef41
MJ
2495 <= max_total_scalarization_size)
2496 {
2497 completely_scalarize_var (var);
2498 if (dump_file && (dump_flags & TDF_DETAILS))
2499 {
2500 fprintf (dump_file, "Will attempt to totally scalarize ");
2501 print_generic_expr (dump_file, var, 0);
2502 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
2503 }
2504 }
2505 else if (dump_file && (dump_flags & TDF_DETAILS))
7744b697 2506 {
e923ef41 2507 fprintf (dump_file, "Too big to totally scalarize: ");
7744b697 2508 print_generic_expr (dump_file, var, 0);
e923ef41 2509 fprintf (dump_file, " (UID: %u)\n", DECL_UID (var));
7744b697
MJ
2510 }
2511 }
2512 }
510335c8 2513
aecd4d81
RG
2514 bitmap_copy (tmp, candidate_bitmap);
2515 EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
2516 {
d94b820b 2517 tree var = candidate (i);
aecd4d81
RG
2518 struct access *access;
2519
2520 access = sort_and_splice_var_accesses (var);
591d4f4a 2521 if (!access || !build_access_trees (access))
aecd4d81
RG
2522 disqualify_candidate (var,
2523 "No or inhibitingly overlapping accesses.");
2524 }
510335c8 2525
0674b9d0 2526 propagate_all_subaccesses ();
510335c8 2527
aecd4d81
RG
2528 bitmap_copy (tmp, candidate_bitmap);
2529 EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
2530 {
d94b820b 2531 tree var = candidate (i);
aecd4d81 2532 struct access *access = get_first_repr_for_decl (var);
510335c8 2533
aecd4d81
RG
2534 if (analyze_access_trees (access))
2535 {
2536 res++;
2537 if (dump_file && (dump_flags & TDF_DETAILS))
2538 {
2539 fprintf (dump_file, "\nAccess trees for ");
2540 print_generic_expr (dump_file, var, 0);
2541 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
2542 dump_access_tree (dump_file, access);
2543 fprintf (dump_file, "\n");
2544 }
2545 }
2546 else
2547 disqualify_candidate (var, "No scalar replacements to be created.");
2548 }
2549
2550 BITMAP_FREE (tmp);
510335c8 2551
2a45675f
MJ
2552 if (res)
2553 {
2554 statistics_counter_event (cfun, "Scalarized aggregates", res);
2555 return true;
2556 }
2557 else
2558 return false;
510335c8
AO
2559}
2560
0674b9d0 2561/* Generate statements copying scalar replacements of accesses within a subtree
ea395a11
MJ
2562 into or out of AGG. ACCESS, all its children, siblings and their children
2563 are to be processed. AGG is an aggregate type expression (can be a
2564 declaration but does not have to be, it can for example also be a mem_ref or
2565 a series of handled components). TOP_OFFSET is the offset of the processed
2566 subtree which has to be subtracted from offsets of individual accesses to
2567 get corresponding offsets for AGG. If CHUNK_SIZE is non-null, copy only
d242d063
MJ
2568 replacements in the interval <start_offset, start_offset + chunk_size>,
2569 otherwise copy all. GSI is a statement iterator used to place the new
2570 statements. WRITE should be true when the statements should write from AGG
2571 to the replacement and false if vice versa. if INSERT_AFTER is true, new
2572 statements will be added after the current statement in GSI, they will be
2573 added before the statement otherwise. */
6de9cd9a
DN
2574
2575static void
0674b9d0
MJ
2576generate_subtree_copies (struct access *access, tree agg,
2577 HOST_WIDE_INT top_offset,
2578 HOST_WIDE_INT start_offset, HOST_WIDE_INT chunk_size,
2579 gimple_stmt_iterator *gsi, bool write,
e4b5cace 2580 bool insert_after, location_t loc)
6de9cd9a 2581{
0674b9d0 2582 do
6de9cd9a 2583 {
0674b9d0
MJ
2584 if (chunk_size && access->offset >= start_offset + chunk_size)
2585 return;
510335c8 2586
0674b9d0
MJ
2587 if (access->grp_to_be_replaced
2588 && (chunk_size == 0
2589 || access->offset + access->size > start_offset))
510335c8 2590 {
d242d063 2591 tree expr, repl = get_access_replacement (access);
0674b9d0 2592 gimple stmt;
510335c8 2593
e4b5cace 2594 expr = build_ref_for_model (loc, agg, access->offset - top_offset,
d242d063 2595 access, gsi, insert_after);
510335c8 2596
0674b9d0 2597 if (write)
510335c8 2598 {
0674b9d0
MJ
2599 if (access->grp_partial_lhs)
2600 expr = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
2601 !insert_after,
2602 insert_after ? GSI_NEW_STMT
2603 : GSI_SAME_STMT);
2604 stmt = gimple_build_assign (repl, expr);
2605 }
2606 else
2607 {
2608 TREE_NO_WARNING (repl) = 1;
2609 if (access->grp_partial_lhs)
2610 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
2611 !insert_after,
2612 insert_after ? GSI_NEW_STMT
2613 : GSI_SAME_STMT);
2614 stmt = gimple_build_assign (expr, repl);
510335c8 2615 }
e4b5cace 2616 gimple_set_location (stmt, loc);
510335c8 2617
0674b9d0
MJ
2618 if (insert_after)
2619 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
b5dcec1e 2620 else
0674b9d0
MJ
2621 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2622 update_stmt (stmt);
71d4d3eb 2623 sra_stats.subtree_copies++;
510335c8 2624 }
be384c10
MJ
2625 else if (write
2626 && access->grp_to_be_debug_replaced
2627 && (chunk_size == 0
2628 || access->offset + access->size > start_offset))
2629 {
2630 gimple ds;
2631 tree drhs = build_debug_ref_for_model (loc, agg,
2632 access->offset - top_offset,
2633 access);
2634 ds = gimple_build_debug_bind (get_access_replacement (access),
2635 drhs, gsi_stmt (*gsi));
2636 if (insert_after)
2637 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
2638 else
2639 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
2640 }
510335c8 2641
0674b9d0
MJ
2642 if (access->first_child)
2643 generate_subtree_copies (access->first_child, agg, top_offset,
2644 start_offset, chunk_size, gsi,
e4b5cace 2645 write, insert_after, loc);
510335c8 2646
0674b9d0 2647 access = access->next_sibling;
510335c8 2648 }
0674b9d0
MJ
2649 while (access);
2650}
2651
2652/* Assign zero to all scalar replacements in an access subtree. ACCESS is the
2653 the root of the subtree to be processed. GSI is the statement iterator used
2654 for inserting statements which are added after the current statement if
2655 INSERT_AFTER is true or before it otherwise. */
2656
2657static void
2658init_subtree_with_zero (struct access *access, gimple_stmt_iterator *gsi,
e4b5cace 2659 bool insert_after, location_t loc)
0674b9d0
MJ
2660
2661{
2662 struct access *child;
2663
2664 if (access->grp_to_be_replaced)
510335c8 2665 {
0674b9d0 2666 gimple stmt;
510335c8 2667
0674b9d0 2668 stmt = gimple_build_assign (get_access_replacement (access),
e8160c9a 2669 build_zero_cst (access->type));
0674b9d0
MJ
2670 if (insert_after)
2671 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2672 else
2673 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2674 update_stmt (stmt);
e4b5cace 2675 gimple_set_location (stmt, loc);
0674b9d0 2676 }
be384c10
MJ
2677 else if (access->grp_to_be_debug_replaced)
2678 {
2679 gimple ds = gimple_build_debug_bind (get_access_replacement (access),
2680 build_zero_cst (access->type),
2681 gsi_stmt (*gsi));
2682 if (insert_after)
2683 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
2684 else
2685 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
2686 }
510335c8 2687
0674b9d0 2688 for (child = access->first_child; child; child = child->next_sibling)
e4b5cace 2689 init_subtree_with_zero (child, gsi, insert_after, loc);
0674b9d0 2690}
510335c8 2691
0674b9d0
MJ
2692/* Search for an access representative for the given expression EXPR and
2693 return it or NULL if it cannot be found. */
510335c8 2694
0674b9d0
MJ
2695static struct access *
2696get_access_for_expr (tree expr)
2697{
2698 HOST_WIDE_INT offset, size, max_size;
2699 tree base;
510335c8 2700
0674b9d0
MJ
2701 /* FIXME: This should not be necessary but Ada produces V_C_Es with a type of
2702 a different size than the size of its argument and we need the latter
2703 one. */
2704 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
2705 expr = TREE_OPERAND (expr, 0);
510335c8 2706
0674b9d0
MJ
2707 base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
2708 if (max_size == -1 || !DECL_P (base))
2709 return NULL;
510335c8 2710
0674b9d0
MJ
2711 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
2712 return NULL;
2713
2714 return get_var_base_offset_size_access (base, offset, max_size);
2715}
2716
6cbd3b6a
MJ
2717/* Replace the expression EXPR with a scalar replacement if there is one and
2718 generate other statements to do type conversion or subtree copying if
2719 necessary. GSI is used to place newly created statements, WRITE is true if
2720 the expression is being written to (it is on a LHS of a statement or output
2721 in an assembly statement). */
0674b9d0
MJ
2722
2723static bool
6cbd3b6a 2724sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
0674b9d0 2725{
e4b5cace 2726 location_t loc;
0674b9d0
MJ
2727 struct access *access;
2728 tree type, bfr;
510335c8 2729
0674b9d0
MJ
2730 if (TREE_CODE (*expr) == BIT_FIELD_REF)
2731 {
2732 bfr = *expr;
2733 expr = &TREE_OPERAND (*expr, 0);
510335c8 2734 }
97e73bd2 2735 else
0674b9d0
MJ
2736 bfr = NULL_TREE;
2737
2738 if (TREE_CODE (*expr) == REALPART_EXPR || TREE_CODE (*expr) == IMAGPART_EXPR)
2739 expr = &TREE_OPERAND (*expr, 0);
2740 access = get_access_for_expr (*expr);
2741 if (!access)
2742 return false;
2743 type = TREE_TYPE (*expr);
2744
e4b5cace 2745 loc = gimple_location (gsi_stmt (*gsi));
0674b9d0 2746 if (access->grp_to_be_replaced)
6de9cd9a 2747 {
0674b9d0
MJ
2748 tree repl = get_access_replacement (access);
2749 /* If we replace a non-register typed access simply use the original
2750 access expression to extract the scalar component afterwards.
2751 This happens if scalarizing a function return value or parameter
2752 like in gcc.c-torture/execute/20041124-1.c, 20050316-1.c and
9fda11a2
MJ
2753 gcc.c-torture/compile/20011217-1.c.
2754
2755 We also want to use this when accessing a complex or vector which can
2756 be accessed as a different type too, potentially creating a need for
caee6ca1
MJ
2757 type conversion (see PR42196) and when scalarized unions are involved
2758 in assembler statements (see PR42398). */
2759 if (!useless_type_conversion_p (type, access->type))
0674b9d0 2760 {
d242d063 2761 tree ref;
09f0dc45 2762
e4b5cace 2763 ref = build_ref_for_model (loc, access->base, access->offset, access,
d242d063 2764 NULL, false);
09f0dc45 2765
0674b9d0
MJ
2766 if (write)
2767 {
09f0dc45
MJ
2768 gimple stmt;
2769
0674b9d0
MJ
2770 if (access->grp_partial_lhs)
2771 ref = force_gimple_operand_gsi (gsi, ref, true, NULL_TREE,
2772 false, GSI_NEW_STMT);
2773 stmt = gimple_build_assign (repl, ref);
e4b5cace 2774 gimple_set_location (stmt, loc);
0674b9d0
MJ
2775 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
2776 }
2777 else
2778 {
09f0dc45
MJ
2779 gimple stmt;
2780
0674b9d0
MJ
2781 if (access->grp_partial_lhs)
2782 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
2783 true, GSI_SAME_STMT);
09f0dc45 2784 stmt = gimple_build_assign (ref, repl);
e4b5cace 2785 gimple_set_location (stmt, loc);
0674b9d0
MJ
2786 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
2787 }
2788 }
143569a8 2789 else
caee6ca1 2790 *expr = repl;
2a45675f 2791 sra_stats.exprs++;
0674b9d0 2792 }
be384c10
MJ
2793 else if (write && access->grp_to_be_debug_replaced)
2794 {
2795 gimple ds = gimple_build_debug_bind (get_access_replacement (access),
2796 NULL_TREE,
2797 gsi_stmt (*gsi));
2798 gsi_insert_after (gsi, ds, GSI_NEW_STMT);
2799 }
0674b9d0
MJ
2800
2801 if (access->first_child)
2802 {
2803 HOST_WIDE_INT start_offset, chunk_size;
2804 if (bfr
cc269bb6
RS
2805 && tree_fits_uhwi_p (TREE_OPERAND (bfr, 1))
2806 && tree_fits_uhwi_p (TREE_OPERAND (bfr, 2)))
0674b9d0 2807 {
ae7e9ddd 2808 chunk_size = tree_to_uhwi (TREE_OPERAND (bfr, 1));
f57017cd 2809 start_offset = access->offset
ae7e9ddd 2810 + tree_to_uhwi (TREE_OPERAND (bfr, 2));
d116ffa6 2811 }
0674b9d0
MJ
2812 else
2813 start_offset = chunk_size = 0;
2814
2815 generate_subtree_copies (access->first_child, access->base, 0,
e4b5cace
MJ
2816 start_offset, chunk_size, gsi, write, write,
2817 loc);
6de9cd9a 2818 }
0674b9d0 2819 return true;
6de9cd9a
DN
2820}
2821
fac52fdd
MJ
2822/* Where scalar replacements of the RHS have been written to when a replacement
2823 of a LHS of an assigments cannot be direclty loaded from a replacement of
2824 the RHS. */
2825enum unscalarized_data_handling { SRA_UDH_NONE, /* Nothing done so far. */
2826 SRA_UDH_RIGHT, /* Data flushed to the RHS. */
2827 SRA_UDH_LEFT }; /* Data flushed to the LHS. */
2828
0674b9d0 2829/* Store all replacements in the access tree rooted in TOP_RACC either to their
ea395a11
MJ
2830 base aggregate if there are unscalarized data or directly to LHS of the
2831 statement that is pointed to by GSI otherwise. */
6de9cd9a 2832
fac52fdd 2833static enum unscalarized_data_handling
ea395a11 2834handle_unscalarized_data_in_subtree (struct access *top_racc,
0674b9d0 2835 gimple_stmt_iterator *gsi)
6de9cd9a 2836{
0674b9d0 2837 if (top_racc->grp_unscalarized_data)
fac52fdd
MJ
2838 {
2839 generate_subtree_copies (top_racc->first_child, top_racc->base, 0, 0, 0,
e4b5cace
MJ
2840 gsi, false, false,
2841 gimple_location (gsi_stmt (*gsi)));
fac52fdd
MJ
2842 return SRA_UDH_RIGHT;
2843 }
0674b9d0 2844 else
fac52fdd 2845 {
ea395a11 2846 tree lhs = gimple_assign_lhs (gsi_stmt (*gsi));
fac52fdd 2847 generate_subtree_copies (top_racc->first_child, lhs, top_racc->offset,
e4b5cace
MJ
2848 0, 0, gsi, false, false,
2849 gimple_location (gsi_stmt (*gsi)));
fac52fdd
MJ
2850 return SRA_UDH_LEFT;
2851 }
0674b9d0 2852}
6de9cd9a 2853
97e73bd2 2854
ea395a11
MJ
2855/* Try to generate statements to load all sub-replacements in an access subtree
2856 formed by children of LACC from scalar replacements in the TOP_RACC subtree.
2857 If that is not possible, refresh the TOP_RACC base aggregate and load the
2858 accesses from it. LEFT_OFFSET is the offset of the left whole subtree being
2859 copied. NEW_GSI is stmt iterator used for statement insertions after the
2860 original assignment, OLD_GSI is used to insert statements before the
2861 assignment. *REFRESHED keeps the information whether we have needed to
2862 refresh replacements of the LHS and from which side of the assignments this
2863 takes place. */
726a989a 2864
0674b9d0
MJ
2865static void
2866load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc,
2867 HOST_WIDE_INT left_offset,
0674b9d0
MJ
2868 gimple_stmt_iterator *old_gsi,
2869 gimple_stmt_iterator *new_gsi,
ea395a11 2870 enum unscalarized_data_handling *refreshed)
0674b9d0 2871{
e4b5cace 2872 location_t loc = gimple_location (gsi_stmt (*old_gsi));
ea395a11 2873 for (lacc = lacc->first_child; lacc; lacc = lacc->next_sibling)
97e73bd2 2874 {
be384c10
MJ
2875 HOST_WIDE_INT offset = lacc->offset - left_offset + top_racc->offset;
2876
0674b9d0 2877 if (lacc->grp_to_be_replaced)
6de9cd9a 2878 {
0674b9d0 2879 struct access *racc;
0674b9d0
MJ
2880 gimple stmt;
2881 tree rhs;
2882
2883 racc = find_access_in_subtree (top_racc, offset, lacc->size);
2884 if (racc && racc->grp_to_be_replaced)
2885 {
2886 rhs = get_access_replacement (racc);
2887 if (!useless_type_conversion_p (lacc->type, racc->type))
db3927fb 2888 rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, lacc->type, rhs);
3e44f600
MJ
2889
2890 if (racc->grp_partial_lhs && lacc->grp_partial_lhs)
2891 rhs = force_gimple_operand_gsi (old_gsi, rhs, true, NULL_TREE,
2892 true, GSI_SAME_STMT);
0674b9d0
MJ
2893 }
2894 else
2895 {
0674b9d0
MJ
2896 /* No suitable access on the right hand side, need to load from
2897 the aggregate. See if we have to update it first... */
fac52fdd 2898 if (*refreshed == SRA_UDH_NONE)
ea395a11 2899 *refreshed = handle_unscalarized_data_in_subtree (top_racc,
e4b5cace 2900 old_gsi);
fac52fdd
MJ
2901
2902 if (*refreshed == SRA_UDH_LEFT)
e4b5cace 2903 rhs = build_ref_for_model (loc, lacc->base, lacc->offset, lacc,
d242d063 2904 new_gsi, true);
fac52fdd 2905 else
e4b5cace 2906 rhs = build_ref_for_model (loc, top_racc->base, offset, lacc,
d242d063 2907 new_gsi, true);
6a9ceb17
MJ
2908 if (lacc->grp_partial_lhs)
2909 rhs = force_gimple_operand_gsi (new_gsi, rhs, true, NULL_TREE,
2910 false, GSI_NEW_STMT);
0674b9d0 2911 }
97e73bd2 2912
0674b9d0
MJ
2913 stmt = gimple_build_assign (get_access_replacement (lacc), rhs);
2914 gsi_insert_after (new_gsi, stmt, GSI_NEW_STMT);
e4b5cace 2915 gimple_set_location (stmt, loc);
0674b9d0 2916 update_stmt (stmt);
2a45675f 2917 sra_stats.subreplacements++;
0674b9d0 2918 }
be384c10
MJ
2919 else
2920 {
2921 if (*refreshed == SRA_UDH_NONE
2922 && lacc->grp_read && !lacc->grp_covered)
2923 *refreshed = handle_unscalarized_data_in_subtree (top_racc,
2924 old_gsi);
2925 if (lacc && lacc->grp_to_be_debug_replaced)
2926 {
2927 gimple ds;
2928 tree drhs;
2929 struct access *racc = find_access_in_subtree (top_racc, offset,
2930 lacc->size);
2931
2932 if (racc && racc->grp_to_be_replaced)
f8f42513
MJ
2933 {
2934 if (racc->grp_write)
2935 drhs = get_access_replacement (racc);
2936 else
2937 drhs = NULL;
2938 }
be384c10
MJ
2939 else if (*refreshed == SRA_UDH_LEFT)
2940 drhs = build_debug_ref_for_model (loc, lacc->base, lacc->offset,
2941 lacc);
2942 else if (*refreshed == SRA_UDH_RIGHT)
2943 drhs = build_debug_ref_for_model (loc, top_racc->base, offset,
2944 lacc);
2945 else
2946 drhs = NULL_TREE;
2947 ds = gimple_build_debug_bind (get_access_replacement (lacc),
2948 drhs, gsi_stmt (*old_gsi));
2949 gsi_insert_after (new_gsi, ds, GSI_NEW_STMT);
2950 }
2951 }
0674b9d0
MJ
2952
2953 if (lacc->first_child)
ea395a11
MJ
2954 load_assign_lhs_subreplacements (lacc, top_racc, left_offset,
2955 old_gsi, new_gsi, refreshed);
6de9cd9a 2956 }
97e73bd2 2957}
6de9cd9a 2958
6cbd3b6a
MJ
2959/* Result code for SRA assignment modification. */
2960enum assignment_mod_result { SRA_AM_NONE, /* nothing done for the stmt */
2961 SRA_AM_MODIFIED, /* stmt changed but not
2962 removed */
2963 SRA_AM_REMOVED }; /* stmt eliminated */
2964
0674b9d0
MJ
2965/* Modify assignments with a CONSTRUCTOR on their RHS. STMT contains a pointer
2966 to the assignment and GSI is the statement iterator pointing at it. Returns
2967 the same values as sra_modify_assign. */
6de9cd9a 2968
6cbd3b6a 2969static enum assignment_mod_result
0674b9d0 2970sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
6de9cd9a 2971{
0674b9d0
MJ
2972 tree lhs = gimple_assign_lhs (*stmt);
2973 struct access *acc;
e4b5cace 2974 location_t loc;
6de9cd9a 2975
0674b9d0
MJ
2976 acc = get_access_for_expr (lhs);
2977 if (!acc)
6cbd3b6a 2978 return SRA_AM_NONE;
6de9cd9a 2979
13604927
RG
2980 if (gimple_clobber_p (*stmt))
2981 {
2982 /* Remove clobbers of fully scalarized variables, otherwise
2983 do nothing. */
2984 if (acc->grp_covered)
2985 {
2986 unlink_stmt_vdef (*stmt);
2987 gsi_remove (gsi, true);
3d3f2249 2988 release_defs (*stmt);
13604927
RG
2989 return SRA_AM_REMOVED;
2990 }
2991 else
2992 return SRA_AM_NONE;
2993 }
2994
e4b5cace 2995 loc = gimple_location (*stmt);
9771b263 2996 if (vec_safe_length (CONSTRUCTOR_ELTS (gimple_assign_rhs1 (*stmt))) > 0)
400196f1 2997 {
0674b9d0
MJ
2998 /* I have never seen this code path trigger but if it can happen the
2999 following should handle it gracefully. */
3000 if (access_has_children_p (acc))
3001 generate_subtree_copies (acc->first_child, acc->base, 0, 0, 0, gsi,
e4b5cace 3002 true, true, loc);
6cbd3b6a 3003 return SRA_AM_MODIFIED;
400196f1 3004 }
6de9cd9a 3005
0674b9d0 3006 if (acc->grp_covered)
97e73bd2 3007 {
e4b5cace 3008 init_subtree_with_zero (acc, gsi, false, loc);
0674b9d0
MJ
3009 unlink_stmt_vdef (*stmt);
3010 gsi_remove (gsi, true);
3d3f2249 3011 release_defs (*stmt);
6cbd3b6a 3012 return SRA_AM_REMOVED;
97e73bd2
RH
3013 }
3014 else
3015 {
e4b5cace 3016 init_subtree_with_zero (acc, gsi, true, loc);
6cbd3b6a 3017 return SRA_AM_MODIFIED;
6de9cd9a
DN
3018 }
3019}
3020
56a42add
MJ
3021/* Create and return a new suitable default definition SSA_NAME for RACC which
3022 is an access describing an uninitialized part of an aggregate that is being
3023 loaded. */
0f2ffb9a 3024
56a42add
MJ
3025static tree
3026get_repl_default_def_ssa_name (struct access *racc)
0f2ffb9a 3027{
5d751b0c
JJ
3028 gcc_checking_assert (!racc->grp_to_be_replaced
3029 && !racc->grp_to_be_debug_replaced);
b48b3fc4
MJ
3030 if (!racc->replacement_decl)
3031 racc->replacement_decl = create_access_replacement (racc);
3032 return get_or_create_ssa_default_def (cfun, racc->replacement_decl);
0f2ffb9a 3033}
6de9cd9a 3034
4cc13d9d
MJ
3035/* Return true if REF has an VIEW_CONVERT_EXPR or a COMPONENT_REF with a
3036 bit-field field declaration somewhere in it. */
3037
3038static inline bool
3039contains_vce_or_bfcref_p (const_tree ref)
3040{
3041 while (handled_component_p (ref))
3042 {
3043 if (TREE_CODE (ref) == VIEW_CONVERT_EXPR
3044 || (TREE_CODE (ref) == COMPONENT_REF
3045 && DECL_BIT_FIELD (TREE_OPERAND (ref, 1))))
3046 return true;
3047 ref = TREE_OPERAND (ref, 0);
3048 }
3049
3050 return false;
3051}
3052
6cbd3b6a
MJ
3053/* Examine both sides of the assignment statement pointed to by STMT, replace
3054 them with a scalare replacement if there is one and generate copying of
3055 replacements if scalarized aggregates have been used in the assignment. GSI
3056 is used to hold generated statements for type conversions and subtree
0674b9d0
MJ
3057 copying. */
3058
6cbd3b6a
MJ
3059static enum assignment_mod_result
3060sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi)
6de9cd9a 3061{
0674b9d0
MJ
3062 struct access *lacc, *racc;
3063 tree lhs, rhs;
3064 bool modify_this_stmt = false;
3065 bool force_gimple_rhs = false;
e4b5cace 3066 location_t loc;
002cda0a 3067 gimple_stmt_iterator orig_gsi = *gsi;
6de9cd9a 3068
0674b9d0 3069 if (!gimple_assign_single_p (*stmt))
6cbd3b6a 3070 return SRA_AM_NONE;
0674b9d0
MJ
3071 lhs = gimple_assign_lhs (*stmt);
3072 rhs = gimple_assign_rhs1 (*stmt);
6de9cd9a 3073
0674b9d0
MJ
3074 if (TREE_CODE (rhs) == CONSTRUCTOR)
3075 return sra_modify_constructor_assign (stmt, gsi);
6de9cd9a 3076
0674b9d0
MJ
3077 if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (lhs) == REALPART_EXPR
3078 || TREE_CODE (rhs) == IMAGPART_EXPR || TREE_CODE (lhs) == IMAGPART_EXPR
3079 || TREE_CODE (rhs) == BIT_FIELD_REF || TREE_CODE (lhs) == BIT_FIELD_REF)
3080 {
3081 modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (*stmt),
6cbd3b6a 3082 gsi, false);
0674b9d0 3083 modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (*stmt),
6cbd3b6a
MJ
3084 gsi, true);
3085 return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
0674b9d0 3086 }
6de9cd9a 3087
0674b9d0
MJ
3088 lacc = get_access_for_expr (lhs);
3089 racc = get_access_for_expr (rhs);
3090 if (!lacc && !racc)
6cbd3b6a 3091 return SRA_AM_NONE;
6de9cd9a 3092
e4b5cace 3093 loc = gimple_location (*stmt);
0674b9d0 3094 if (lacc && lacc->grp_to_be_replaced)
97e73bd2 3095 {
0674b9d0
MJ
3096 lhs = get_access_replacement (lacc);
3097 gimple_assign_set_lhs (*stmt, lhs);
3098 modify_this_stmt = true;
3099 if (lacc->grp_partial_lhs)
3100 force_gimple_rhs = true;
2a45675f 3101 sra_stats.exprs++;
97e73bd2 3102 }
6de9cd9a 3103
0674b9d0
MJ
3104 if (racc && racc->grp_to_be_replaced)
3105 {
3106 rhs = get_access_replacement (racc);
3107 modify_this_stmt = true;
3108 if (racc->grp_partial_lhs)
3109 force_gimple_rhs = true;
2a45675f 3110 sra_stats.exprs++;
0674b9d0 3111 }
fdad69c1 3112 else if (racc
fdad69c1 3113 && !racc->grp_unscalarized_data
973a39ae
RG
3114 && TREE_CODE (lhs) == SSA_NAME
3115 && !access_has_replacements_p (racc))
fdad69c1
RG
3116 {
3117 rhs = get_repl_default_def_ssa_name (racc);
3118 modify_this_stmt = true;
3119 sra_stats.exprs++;
3120 }
6de9cd9a 3121
0674b9d0
MJ
3122 if (modify_this_stmt)
3123 {
3124 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
6de9cd9a 3125 {
0674b9d0
MJ
3126 /* If we can avoid creating a VIEW_CONVERT_EXPR do so.
3127 ??? This should move to fold_stmt which we simply should
3128 call after building a VIEW_CONVERT_EXPR here. */
3129 if (AGGREGATE_TYPE_P (TREE_TYPE (lhs))
7d2fb524 3130 && !contains_bitfld_component_ref_p (lhs))
0674b9d0 3131 {
e80b21ed 3132 lhs = build_ref_for_model (loc, lhs, 0, racc, gsi, false);
d242d063 3133 gimple_assign_set_lhs (*stmt, lhs);
0674b9d0
MJ
3134 }
3135 else if (AGGREGATE_TYPE_P (TREE_TYPE (rhs))
87eab554 3136 && !contains_vce_or_bfcref_p (rhs))
e80b21ed 3137 rhs = build_ref_for_model (loc, rhs, 0, lacc, gsi, false);
d242d063 3138
0674b9d0 3139 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
0ec19b8c 3140 {
d242d063
MJ
3141 rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
3142 rhs);
1bea3098
RG
3143 if (is_gimple_reg_type (TREE_TYPE (lhs))
3144 && TREE_CODE (lhs) != SSA_NAME)
0ec19b8c
MJ
3145 force_gimple_rhs = true;
3146 }
0674b9d0 3147 }
0674b9d0 3148 }
97e73bd2 3149
be384c10
MJ
3150 if (lacc && lacc->grp_to_be_debug_replaced)
3151 {
a7818b54
JJ
3152 tree dlhs = get_access_replacement (lacc);
3153 tree drhs = unshare_expr (rhs);
3154 if (!useless_type_conversion_p (TREE_TYPE (dlhs), TREE_TYPE (drhs)))
3155 {
3156 if (AGGREGATE_TYPE_P (TREE_TYPE (drhs))
3157 && !contains_vce_or_bfcref_p (drhs))
3158 drhs = build_debug_ref_for_model (loc, drhs, 0, lacc);
3159 if (drhs
3160 && !useless_type_conversion_p (TREE_TYPE (dlhs),
3161 TREE_TYPE (drhs)))
3162 drhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
3163 TREE_TYPE (dlhs), drhs);
3164 }
3165 gimple ds = gimple_build_debug_bind (dlhs, drhs, *stmt);
be384c10
MJ
3166 gsi_insert_before (gsi, ds, GSI_SAME_STMT);
3167 }
3168
0674b9d0
MJ
3169 /* From this point on, the function deals with assignments in between
3170 aggregates when at least one has scalar reductions of some of its
3171 components. There are three possible scenarios: Both the LHS and RHS have
3172 to-be-scalarized components, 2) only the RHS has or 3) only the LHS has.
3173
3174 In the first case, we would like to load the LHS components from RHS
3175 components whenever possible. If that is not possible, we would like to
3176 read it directly from the RHS (after updating it by storing in it its own
3177 components). If there are some necessary unscalarized data in the LHS,
3178 those will be loaded by the original assignment too. If neither of these
3179 cases happen, the original statement can be removed. Most of this is done
3180 by load_assign_lhs_subreplacements.
3181
3182 In the second case, we would like to store all RHS scalarized components
3183 directly into LHS and if they cover the aggregate completely, remove the
3184 statement too. In the third case, we want the LHS components to be loaded
3185 directly from the RHS (DSE will remove the original statement if it
3186 becomes redundant).
3187
3188 This is a bit complex but manageable when types match and when unions do
3189 not cause confusion in a way that we cannot really load a component of LHS
3190 from the RHS or vice versa (the access representing this level can have
3191 subaccesses that are accessible only through a different union field at a
3192 higher level - different from the one used in the examined expression).
3193 Unions are fun.
3194
3195 Therefore, I specially handle a fourth case, happening when there is a
3196 specific type cast or it is impossible to locate a scalarized subaccess on
3197 the other side of the expression. If that happens, I simply "refresh" the
3198 RHS by storing in it is scalarized components leave the original statement
3199 there to do the copying and then load the scalar replacements of the LHS.
3200 This is what the first branch does. */
3201
b807e627
MJ
3202 if (modify_this_stmt
3203 || gimple_has_volatile_ops (*stmt)
4cc13d9d
MJ
3204 || contains_vce_or_bfcref_p (rhs)
3205 || contains_vce_or_bfcref_p (lhs))
0674b9d0
MJ
3206 {
3207 if (access_has_children_p (racc))
3208 generate_subtree_copies (racc->first_child, racc->base, 0, 0, 0,
e4b5cace 3209 gsi, false, false, loc);
0674b9d0
MJ
3210 if (access_has_children_p (lacc))
3211 generate_subtree_copies (lacc->first_child, lacc->base, 0, 0, 0,
e4b5cace 3212 gsi, true, true, loc);
2a45675f 3213 sra_stats.separate_lhs_rhs_handling++;
fdad69c1
RG
3214
3215 /* This gimplification must be done after generate_subtree_copies,
3216 lest we insert the subtree copies in the middle of the gimplified
3217 sequence. */
3218 if (force_gimple_rhs)
3219 rhs = force_gimple_operand_gsi (&orig_gsi, rhs, true, NULL_TREE,
3220 true, GSI_SAME_STMT);
3221 if (gimple_assign_rhs1 (*stmt) != rhs)
3222 {
3223 modify_this_stmt = true;
3224 gimple_assign_set_rhs_from_tree (&orig_gsi, rhs);
3225 gcc_assert (*stmt == gsi_stmt (orig_gsi));
3226 }
3227
3228 return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
0674b9d0
MJ
3229 }
3230 else
3231 {
429576ac
MJ
3232 if (access_has_children_p (lacc)
3233 && access_has_children_p (racc)
3234 /* When an access represents an unscalarizable region, it usually
3235 represents accesses with variable offset and thus must not be used
3236 to generate new memory accesses. */
3237 && !lacc->grp_unscalarizable_region
3238 && !racc->grp_unscalarizable_region)
0674b9d0
MJ
3239 {
3240 gimple_stmt_iterator orig_gsi = *gsi;
fac52fdd 3241 enum unscalarized_data_handling refreshed;
510335c8 3242
0674b9d0 3243 if (lacc->grp_read && !lacc->grp_covered)
ea395a11 3244 refreshed = handle_unscalarized_data_in_subtree (racc, gsi);
0674b9d0 3245 else
fac52fdd 3246 refreshed = SRA_UDH_NONE;
19114537 3247
ea395a11
MJ
3248 load_assign_lhs_subreplacements (lacc, racc, lacc->offset,
3249 &orig_gsi, gsi, &refreshed);
fac52fdd 3250 if (refreshed != SRA_UDH_RIGHT)
97e73bd2 3251 {
75a75e91 3252 gsi_next (gsi);
0674b9d0
MJ
3253 unlink_stmt_vdef (*stmt);
3254 gsi_remove (&orig_gsi, true);
3d3f2249 3255 release_defs (*stmt);
2a45675f 3256 sra_stats.deleted++;
6cbd3b6a 3257 return SRA_AM_REMOVED;
97e73bd2 3258 }
6de9cd9a 3259 }
97e73bd2 3260 else
0674b9d0 3261 {
fdad69c1
RG
3262 if (access_has_children_p (racc)
3263 && !racc->grp_unscalarized_data)
0674b9d0 3264 {
fdad69c1 3265 if (dump_file)
0674b9d0 3266 {
fdad69c1
RG
3267 fprintf (dump_file, "Removing load: ");
3268 print_gimple_stmt (dump_file, *stmt, 0, 0);
0674b9d0 3269 }
fdad69c1
RG
3270 generate_subtree_copies (racc->first_child, lhs,
3271 racc->offset, 0, 0, gsi,
3272 false, false, loc);
3273 gcc_assert (*stmt == gsi_stmt (*gsi));
3274 unlink_stmt_vdef (*stmt);
3275 gsi_remove (gsi, true);
3d3f2249 3276 release_defs (*stmt);
fdad69c1
RG
3277 sra_stats.deleted++;
3278 return SRA_AM_REMOVED;
0674b9d0 3279 }
63d7ceaa
RG
3280 /* Restore the aggregate RHS from its components so the
3281 prevailing aggregate copy does the right thing. */
fdad69c1 3282 if (access_has_children_p (racc))
63d7ceaa
RG
3283 generate_subtree_copies (racc->first_child, racc->base, 0, 0, 0,
3284 gsi, false, false, loc);
3285 /* Re-load the components of the aggregate copy destination.
3286 But use the RHS aggregate to load from to expose more
3287 optimization opportunities. */
0f2ffb9a 3288 if (access_has_children_p (lacc))
0674b9d0 3289 generate_subtree_copies (lacc->first_child, rhs, lacc->offset,
e4b5cace 3290 0, 0, gsi, true, true, loc);
0674b9d0 3291 }
002cda0a 3292
fdad69c1 3293 return SRA_AM_NONE;
002cda0a 3294 }
6cbd3b6a
MJ
3295}
3296
3297/* Traverse the function body and all modifications as decided in
8cbeddcc
MJ
3298 analyze_all_variable_accesses. Return true iff the CFG has been
3299 changed. */
6cbd3b6a 3300
8cbeddcc 3301static bool
6cbd3b6a
MJ
3302sra_modify_function_body (void)
3303{
8cbeddcc 3304 bool cfg_changed = false;
6cbd3b6a
MJ
3305 basic_block bb;
3306
3307 FOR_EACH_BB (bb)
3308 {
3309 gimple_stmt_iterator gsi = gsi_start_bb (bb);
3310 while (!gsi_end_p (gsi))
3311 {
3312 gimple stmt = gsi_stmt (gsi);
3313 enum assignment_mod_result assign_result;
3314 bool modified = false, deleted = false;
3315 tree *t;
3316 unsigned i;
3317
3318 switch (gimple_code (stmt))
3319 {
3320 case GIMPLE_RETURN:
3321 t = gimple_return_retval_ptr (stmt);
3322 if (*t != NULL_TREE)
3323 modified |= sra_modify_expr (t, &gsi, false);
3324 break;
3325
3326 case GIMPLE_ASSIGN:
3327 assign_result = sra_modify_assign (&stmt, &gsi);
3328 modified |= assign_result == SRA_AM_MODIFIED;
3329 deleted = assign_result == SRA_AM_REMOVED;
3330 break;
3331
3332 case GIMPLE_CALL:
3333 /* Operands must be processed before the lhs. */
3334 for (i = 0; i < gimple_call_num_args (stmt); i++)
3335 {
3336 t = gimple_call_arg_ptr (stmt, i);
3337 modified |= sra_modify_expr (t, &gsi, false);
3338 }
3339
3340 if (gimple_call_lhs (stmt))
3341 {
3342 t = gimple_call_lhs_ptr (stmt);
3343 modified |= sra_modify_expr (t, &gsi, true);
3344 }
3345 break;
3346
3347 case GIMPLE_ASM:
3348 for (i = 0; i < gimple_asm_ninputs (stmt); i++)
3349 {
3350 t = &TREE_VALUE (gimple_asm_input_op (stmt, i));
3351 modified |= sra_modify_expr (t, &gsi, false);
3352 }
3353 for (i = 0; i < gimple_asm_noutputs (stmt); i++)
3354 {
3355 t = &TREE_VALUE (gimple_asm_output_op (stmt, i));
3356 modified |= sra_modify_expr (t, &gsi, true);
3357 }
3358 break;
3359
3360 default:
3361 break;
3362 }
3363
3364 if (modified)
3365 {
3366 update_stmt (stmt);
8cbeddcc
MJ
3367 if (maybe_clean_eh_stmt (stmt)
3368 && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
3369 cfg_changed = true;
6cbd3b6a
MJ
3370 }
3371 if (!deleted)
3372 gsi_next (&gsi);
3373 }
3374 }
8cbeddcc
MJ
3375
3376 return cfg_changed;
6de9cd9a
DN
3377}
3378
0674b9d0
MJ
3379/* Generate statements initializing scalar replacements of parts of function
3380 parameters. */
6de9cd9a 3381
97e73bd2 3382static void
0674b9d0 3383initialize_parameter_reductions (void)
6de9cd9a 3384{
0674b9d0 3385 gimple_stmt_iterator gsi;
726a989a 3386 gimple_seq seq = NULL;
0674b9d0 3387 tree parm;
6de9cd9a 3388
355a7673 3389 gsi = gsi_start (seq);
0674b9d0
MJ
3390 for (parm = DECL_ARGUMENTS (current_function_decl);
3391 parm;
910ad8de 3392 parm = DECL_CHAIN (parm))
0bca51f0 3393 {
9771b263 3394 vec<access_p> *access_vec;
0674b9d0 3395 struct access *access;
97e73bd2 3396
0674b9d0
MJ
3397 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
3398 continue;
3399 access_vec = get_base_access_vector (parm);
3400 if (!access_vec)
3401 continue;
6de9cd9a 3402
9771b263 3403 for (access = (*access_vec)[0];
0674b9d0
MJ
3404 access;
3405 access = access->next_grp)
e4b5cace
MJ
3406 generate_subtree_copies (access, parm, 0, 0, 0, &gsi, true, true,
3407 EXPR_LOCATION (parm));
0674b9d0 3408 }
97e73bd2 3409
355a7673 3410 seq = gsi_seq (gsi);
0674b9d0
MJ
3411 if (seq)
3412 gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR), seq);
97e73bd2 3413}
6de9cd9a 3414
0674b9d0
MJ
3415/* The "main" function of intraprocedural SRA passes. Runs the analysis and if
3416 it reveals there are components of some aggregates to be scalarized, it runs
3417 the required transformations. */
3418static unsigned int
3419perform_intra_sra (void)
ea900239 3420{
0674b9d0
MJ
3421 int ret = 0;
3422 sra_initialize ();
ea900239 3423
0674b9d0
MJ
3424 if (!find_var_candidates ())
3425 goto out;
ea900239 3426
6cbd3b6a 3427 if (!scan_function ())
0674b9d0 3428 goto out;
726a989a 3429
0674b9d0
MJ
3430 if (!analyze_all_variable_accesses ())
3431 goto out;
6de9cd9a 3432
8cbeddcc
MJ
3433 if (sra_modify_function_body ())
3434 ret = TODO_update_ssa | TODO_cleanup_cfg;
3435 else
3436 ret = TODO_update_ssa;
0674b9d0 3437 initialize_parameter_reductions ();
2a45675f
MJ
3438
3439 statistics_counter_event (cfun, "Scalar replacements created",
3440 sra_stats.replacements);
3441 statistics_counter_event (cfun, "Modified expressions", sra_stats.exprs);
3442 statistics_counter_event (cfun, "Subtree copy stmts",
3443 sra_stats.subtree_copies);
3444 statistics_counter_event (cfun, "Subreplacement stmts",
3445 sra_stats.subreplacements);
3446 statistics_counter_event (cfun, "Deleted stmts", sra_stats.deleted);
3447 statistics_counter_event (cfun, "Separate LHS and RHS handling",
3448 sra_stats.separate_lhs_rhs_handling);
3449
0674b9d0
MJ
3450 out:
3451 sra_deinitialize ();
3452 return ret;
6de9cd9a
DN
3453}
3454
0674b9d0 3455/* Perform early intraprocedural SRA. */
029f45bd 3456static unsigned int
0674b9d0 3457early_intra_sra (void)
029f45bd 3458{
0674b9d0
MJ
3459 sra_mode = SRA_MODE_EARLY_INTRA;
3460 return perform_intra_sra ();
3461}
029f45bd 3462
0674b9d0
MJ
3463/* Perform "late" intraprocedural SRA. */
3464static unsigned int
3465late_intra_sra (void)
3466{
3467 sra_mode = SRA_MODE_INTRA;
3468 return perform_intra_sra ();
029f45bd
RH
3469}
3470
0674b9d0 3471
6de9cd9a 3472static bool
0674b9d0 3473gate_intra_sra (void)
6de9cd9a 3474{
567a4beb 3475 return flag_tree_sra != 0 && dbg_cnt (tree_sra);
6de9cd9a
DN
3476}
3477
0674b9d0 3478
27a4cd48
DM
3479namespace {
3480
3481const pass_data pass_data_sra_early =
029f45bd 3482{
27a4cd48
DM
3483 GIMPLE_PASS, /* type */
3484 "esra", /* name */
3485 OPTGROUP_NONE, /* optinfo_flags */
3486 true, /* has_gate */
3487 true, /* has_execute */
3488 TV_TREE_SRA, /* tv_id */
3489 ( PROP_cfg | PROP_ssa ), /* properties_required */
3490 0, /* properties_provided */
3491 0, /* properties_destroyed */
3492 0, /* todo_flags_start */
3493 ( TODO_update_ssa | TODO_verify_ssa ), /* todo_flags_finish */
029f45bd
RH
3494};
3495
27a4cd48
DM
3496class pass_sra_early : public gimple_opt_pass
3497{
3498public:
c3284718
RS
3499 pass_sra_early (gcc::context *ctxt)
3500 : gimple_opt_pass (pass_data_sra_early, ctxt)
27a4cd48
DM
3501 {}
3502
3503 /* opt_pass methods: */
3504 bool gate () { return gate_intra_sra (); }
3505 unsigned int execute () { return early_intra_sra (); }
3506
3507}; // class pass_sra_early
3508
3509} // anon namespace
3510
3511gimple_opt_pass *
3512make_pass_sra_early (gcc::context *ctxt)
3513{
3514 return new pass_sra_early (ctxt);
3515}
3516
3517namespace {
3518
3519const pass_data pass_data_sra =
6de9cd9a 3520{
27a4cd48
DM
3521 GIMPLE_PASS, /* type */
3522 "sra", /* name */
3523 OPTGROUP_NONE, /* optinfo_flags */
3524 true, /* has_gate */
3525 true, /* has_execute */
3526 TV_TREE_SRA, /* tv_id */
3527 ( PROP_cfg | PROP_ssa ), /* properties_required */
3528 0, /* properties_provided */
3529 0, /* properties_destroyed */
3530 TODO_update_address_taken, /* todo_flags_start */
3531 ( TODO_update_ssa | TODO_verify_ssa ), /* todo_flags_finish */
6de9cd9a 3532};
07ffa034 3533
27a4cd48
DM
3534class pass_sra : public gimple_opt_pass
3535{
3536public:
c3284718
RS
3537 pass_sra (gcc::context *ctxt)
3538 : gimple_opt_pass (pass_data_sra, ctxt)
27a4cd48
DM
3539 {}
3540
3541 /* opt_pass methods: */
3542 bool gate () { return gate_intra_sra (); }
3543 unsigned int execute () { return late_intra_sra (); }
3544
3545}; // class pass_sra
3546
3547} // anon namespace
3548
3549gimple_opt_pass *
3550make_pass_sra (gcc::context *ctxt)
3551{
3552 return new pass_sra (ctxt);
3553}
3554
07ffa034
MJ
3555
3556/* Return true iff PARM (which must be a parm_decl) is an unused scalar
3557 parameter. */
3558
3559static bool
3560is_unused_scalar_param (tree parm)
3561{
3562 tree name;
3563 return (is_gimple_reg (parm)
32244553 3564 && (!(name = ssa_default_def (cfun, parm))
07ffa034
MJ
3565 || has_zero_uses (name)));
3566}
3567
3568/* Scan immediate uses of a default definition SSA name of a parameter PARM and
3569 examine whether there are any direct or otherwise infeasible ones. If so,
3570 return true, otherwise return false. PARM must be a gimple register with a
3571 non-NULL default definition. */
3572
3573static bool
3574ptr_parm_has_direct_uses (tree parm)
3575{
3576 imm_use_iterator ui;
3577 gimple stmt;
32244553 3578 tree name = ssa_default_def (cfun, parm);
07ffa034
MJ
3579 bool ret = false;
3580
3581 FOR_EACH_IMM_USE_STMT (stmt, ui, name)
3582 {
44f89620
RG
3583 int uses_ok = 0;
3584 use_operand_p use_p;
3585
3586 if (is_gimple_debug (stmt))
3587 continue;
3588
3589 /* Valid uses include dereferences on the lhs and the rhs. */
3590 if (gimple_has_lhs (stmt))
07ffa034 3591 {
44f89620
RG
3592 tree lhs = gimple_get_lhs (stmt);
3593 while (handled_component_p (lhs))
3594 lhs = TREE_OPERAND (lhs, 0);
70f34814
RG
3595 if (TREE_CODE (lhs) == MEM_REF
3596 && TREE_OPERAND (lhs, 0) == name
3597 && integer_zerop (TREE_OPERAND (lhs, 1))
3598 && types_compatible_p (TREE_TYPE (lhs),
0de204de
AP
3599 TREE_TYPE (TREE_TYPE (name)))
3600 && !TREE_THIS_VOLATILE (lhs))
44f89620 3601 uses_ok++;
07ffa034 3602 }
44f89620 3603 if (gimple_assign_single_p (stmt))
07ffa034 3604 {
44f89620
RG
3605 tree rhs = gimple_assign_rhs1 (stmt);
3606 while (handled_component_p (rhs))
3607 rhs = TREE_OPERAND (rhs, 0);
70f34814
RG
3608 if (TREE_CODE (rhs) == MEM_REF
3609 && TREE_OPERAND (rhs, 0) == name
3610 && integer_zerop (TREE_OPERAND (rhs, 1))
3611 && types_compatible_p (TREE_TYPE (rhs),
0de204de
AP
3612 TREE_TYPE (TREE_TYPE (name)))
3613 && !TREE_THIS_VOLATILE (rhs))
44f89620 3614 uses_ok++;
07ffa034
MJ
3615 }
3616 else if (is_gimple_call (stmt))
3617 {
3618 unsigned i;
44f89620 3619 for (i = 0; i < gimple_call_num_args (stmt); ++i)
07ffa034
MJ
3620 {
3621 tree arg = gimple_call_arg (stmt, i);
44f89620
RG
3622 while (handled_component_p (arg))
3623 arg = TREE_OPERAND (arg, 0);
70f34814
RG
3624 if (TREE_CODE (arg) == MEM_REF
3625 && TREE_OPERAND (arg, 0) == name
3626 && integer_zerop (TREE_OPERAND (arg, 1))
3627 && types_compatible_p (TREE_TYPE (arg),
0de204de
AP
3628 TREE_TYPE (TREE_TYPE (name)))
3629 && !TREE_THIS_VOLATILE (arg))
44f89620 3630 uses_ok++;
07ffa034
MJ
3631 }
3632 }
44f89620
RG
3633
3634 /* If the number of valid uses does not match the number of
3635 uses in this stmt there is an unhandled use. */
3636 FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
3637 --uses_ok;
3638
3639 if (uses_ok != 0)
07ffa034
MJ
3640 ret = true;
3641
3642 if (ret)
3643 BREAK_FROM_IMM_USE_STMT (ui);
3644 }
3645
3646 return ret;
3647}
3648
3649/* Identify candidates for reduction for IPA-SRA based on their type and mark
3650 them in candidate_bitmap. Note that these do not necessarily include
3651 parameter which are unused and thus can be removed. Return true iff any
3652 such candidate has been found. */
3653
3654static bool
3655find_param_candidates (void)
3656{
3657 tree parm;
3658 int count = 0;
3659 bool ret = false;
949cfd0a 3660 const char *msg;
07ffa034
MJ
3661
3662 for (parm = DECL_ARGUMENTS (current_function_decl);
3663 parm;
910ad8de 3664 parm = DECL_CHAIN (parm))
07ffa034 3665 {
1e9fb3de 3666 tree type = TREE_TYPE (parm);
4a8fb1a1 3667 tree_node **slot;
07ffa034
MJ
3668
3669 count++;
1e9fb3de 3670
07ffa034 3671 if (TREE_THIS_VOLATILE (parm)
1e9fb3de 3672 || TREE_ADDRESSABLE (parm)
a7752396 3673 || (!is_gimple_reg_type (type) && is_va_list_type (type)))
07ffa034
MJ
3674 continue;
3675
3676 if (is_unused_scalar_param (parm))
3677 {
3678 ret = true;
3679 continue;
3680 }
3681
07ffa034
MJ
3682 if (POINTER_TYPE_P (type))
3683 {
3684 type = TREE_TYPE (type);
3685
3686 if (TREE_CODE (type) == FUNCTION_TYPE
3687 || TYPE_VOLATILE (type)
c2cf2f4a
EB
3688 || (TREE_CODE (type) == ARRAY_TYPE
3689 && TYPE_NONALIASED_COMPONENT (type))
07ffa034 3690 || !is_gimple_reg (parm)
1e9fb3de 3691 || is_va_list_type (type)
07ffa034
MJ
3692 || ptr_parm_has_direct_uses (parm))
3693 continue;
3694 }
3695 else if (!AGGREGATE_TYPE_P (type))
3696 continue;
3697
3698 if (!COMPLETE_TYPE_P (type)
cc269bb6 3699 || !tree_fits_uhwi_p (TYPE_SIZE (type))
ae7e9ddd 3700 || tree_to_uhwi (TYPE_SIZE (type)) == 0
07ffa034 3701 || (AGGREGATE_TYPE_P (type)
949cfd0a 3702 && type_internals_preclude_sra_p (type, &msg)))
07ffa034
MJ
3703 continue;
3704
3705 bitmap_set_bit (candidate_bitmap, DECL_UID (parm));
4a8fb1a1
LC
3706 slot = candidates.find_slot_with_hash (parm, DECL_UID (parm), INSERT);
3707 *slot = parm;
d94b820b 3708
07ffa034
MJ
3709 ret = true;
3710 if (dump_file && (dump_flags & TDF_DETAILS))
3711 {
3712 fprintf (dump_file, "Candidate (%d): ", DECL_UID (parm));
3713 print_generic_expr (dump_file, parm, 0);
3714 fprintf (dump_file, "\n");
3715 }
3716 }
3717
3718 func_param_count = count;
3719 return ret;
3720}
3721
3722/* Callback of walk_aliased_vdefs, marks the access passed as DATA as
3723 maybe_modified. */
3724
3725static bool
3726mark_maybe_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
3727 void *data)
3728{
3729 struct access *repr = (struct access *) data;
3730
3731 repr->grp_maybe_modified = 1;
3732 return true;
3733}
3734
3735/* Analyze what representatives (in linked lists accessible from
3736 REPRESENTATIVES) can be modified by side effects of statements in the
3737 current function. */
3738
3739static void
9771b263 3740analyze_modified_params (vec<access_p> representatives)
07ffa034
MJ
3741{
3742 int i;
3743
3744 for (i = 0; i < func_param_count; i++)
3745 {
2b93f88d 3746 struct access *repr;
07ffa034 3747
9771b263 3748 for (repr = representatives[i];
2b93f88d
MJ
3749 repr;
3750 repr = repr->next_grp)
07ffa034 3751 {
30a20e97
MJ
3752 struct access *access;
3753 bitmap visited;
3754 ao_ref ar;
2b93f88d
MJ
3755
3756 if (no_accesses_p (repr))
3757 continue;
30a20e97 3758 if (!POINTER_TYPE_P (TREE_TYPE (repr->base))
2b93f88d
MJ
3759 || repr->grp_maybe_modified)
3760 continue;
3761
30a20e97
MJ
3762 ao_ref_init (&ar, repr->expr);
3763 visited = BITMAP_ALLOC (NULL);
3764 for (access = repr; access; access = access->next_sibling)
2b93f88d 3765 {
2b93f88d
MJ
3766 /* All accesses are read ones, otherwise grp_maybe_modified would
3767 be trivially set. */
2b93f88d 3768 walk_aliased_vdefs (&ar, gimple_vuse (access->stmt),
30a20e97 3769 mark_maybe_modified, repr, &visited);
2b93f88d
MJ
3770 if (repr->grp_maybe_modified)
3771 break;
3772 }
30a20e97 3773 BITMAP_FREE (visited);
07ffa034
MJ
3774 }
3775 }
3776}
3777
3778/* Propagate distances in bb_dereferences in the opposite direction than the
3779 control flow edges, in each step storing the maximum of the current value
3780 and the minimum of all successors. These steps are repeated until the table
3781 stabilizes. Note that BBs which might terminate the functions (according to
3782 final_bbs bitmap) never updated in this way. */
3783
3784static void
3785propagate_dereference_distances (void)
3786{
9771b263 3787 vec<basic_block> queue;
07ffa034
MJ
3788 basic_block bb;
3789
9771b263
DN
3790 queue.create (last_basic_block_for_function (cfun));
3791 queue.quick_push (ENTRY_BLOCK_PTR);
07ffa034
MJ
3792 FOR_EACH_BB (bb)
3793 {
9771b263 3794 queue.quick_push (bb);
07ffa034
MJ
3795 bb->aux = bb;
3796 }
3797
9771b263 3798 while (!queue.is_empty ())
07ffa034
MJ
3799 {
3800 edge_iterator ei;
3801 edge e;
3802 bool change = false;
3803 int i;
3804
9771b263 3805 bb = queue.pop ();
07ffa034
MJ
3806 bb->aux = NULL;
3807
3808 if (bitmap_bit_p (final_bbs, bb->index))
3809 continue;
3810
3811 for (i = 0; i < func_param_count; i++)
3812 {
3813 int idx = bb->index * func_param_count + i;
3814 bool first = true;
3815 HOST_WIDE_INT inh = 0;
3816
3817 FOR_EACH_EDGE (e, ei, bb->succs)
3818 {
3819 int succ_idx = e->dest->index * func_param_count + i;
3820
3821 if (e->src == EXIT_BLOCK_PTR)
3822 continue;
3823
3824 if (first)
3825 {
3826 first = false;
3827 inh = bb_dereferences [succ_idx];
3828 }
3829 else if (bb_dereferences [succ_idx] < inh)
3830 inh = bb_dereferences [succ_idx];
3831 }
3832
3833 if (!first && bb_dereferences[idx] < inh)
3834 {
3835 bb_dereferences[idx] = inh;
3836 change = true;
3837 }
3838 }
3839
3840 if (change && !bitmap_bit_p (final_bbs, bb->index))
3841 FOR_EACH_EDGE (e, ei, bb->preds)
3842 {
3843 if (e->src->aux)
3844 continue;
3845
3846 e->src->aux = e->src;
9771b263 3847 queue.quick_push (e->src);
07ffa034
MJ
3848 }
3849 }
3850
9771b263 3851 queue.release ();
07ffa034
MJ
3852}
3853
3854/* Dump a dereferences TABLE with heading STR to file F. */
3855
3856static void
3857dump_dereferences_table (FILE *f, const char *str, HOST_WIDE_INT *table)
3858{
3859 basic_block bb;
3860
3861 fprintf (dump_file, str);
3862 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
3863 {
3864 fprintf (f, "%4i %i ", bb->index, bitmap_bit_p (final_bbs, bb->index));
3865 if (bb != EXIT_BLOCK_PTR)
3866 {
3867 int i;
3868 for (i = 0; i < func_param_count; i++)
3869 {
3870 int idx = bb->index * func_param_count + i;
3871 fprintf (f, " %4" HOST_WIDE_INT_PRINT "d", table[idx]);
3872 }
3873 }
3874 fprintf (f, "\n");
3875 }
3876 fprintf (dump_file, "\n");
3877}
3878
3879/* Determine what (parts of) parameters passed by reference that are not
3880 assigned to are not certainly dereferenced in this function and thus the
3881 dereferencing cannot be safely moved to the caller without potentially
3882 introducing a segfault. Mark such REPRESENTATIVES as
3883 grp_not_necessarilly_dereferenced.
3884
3885 The dereferenced maximum "distance," i.e. the offset + size of the accessed
3886 part is calculated rather than simple booleans are calculated for each
3887 pointer parameter to handle cases when only a fraction of the whole
3888 aggregate is allocated (see testsuite/gcc.c-torture/execute/ipa-sra-2.c for
3889 an example).
3890
3891 The maximum dereference distances for each pointer parameter and BB are
3892 already stored in bb_dereference. This routine simply propagates these
3893 values upwards by propagate_dereference_distances and then compares the
3894 distances of individual parameters in the ENTRY BB to the equivalent
3895 distances of each representative of a (fraction of a) parameter. */
3896
3897static void
9771b263 3898analyze_caller_dereference_legality (vec<access_p> representatives)
07ffa034
MJ
3899{
3900 int i;
3901
3902 if (dump_file && (dump_flags & TDF_DETAILS))
3903 dump_dereferences_table (dump_file,
3904 "Dereference table before propagation:\n",
3905 bb_dereferences);
3906
3907 propagate_dereference_distances ();
3908
3909 if (dump_file && (dump_flags & TDF_DETAILS))
3910 dump_dereferences_table (dump_file,
3911 "Dereference table after propagation:\n",
3912 bb_dereferences);
3913
3914 for (i = 0; i < func_param_count; i++)
3915 {
9771b263 3916 struct access *repr = representatives[i];
07ffa034
MJ
3917 int idx = ENTRY_BLOCK_PTR->index * func_param_count + i;
3918
3919 if (!repr || no_accesses_p (repr))
3920 continue;
3921
3922 do
3923 {
3924 if ((repr->offset + repr->size) > bb_dereferences[idx])
3925 repr->grp_not_necessarilly_dereferenced = 1;
3926 repr = repr->next_grp;
3927 }
3928 while (repr);
3929 }
3930}
3931
3932/* Return the representative access for the parameter declaration PARM if it is
3933 a scalar passed by reference which is not written to and the pointer value
3934 is not used directly. Thus, if it is legal to dereference it in the caller
3935 and we can rule out modifications through aliases, such parameter should be
3936 turned into one passed by value. Return NULL otherwise. */
3937
3938static struct access *
3939unmodified_by_ref_scalar_representative (tree parm)
3940{
3941 int i, access_count;
30a20e97 3942 struct access *repr;
9771b263 3943 vec<access_p> *access_vec;
07ffa034
MJ
3944
3945 access_vec = get_base_access_vector (parm);
3946 gcc_assert (access_vec);
9771b263 3947 repr = (*access_vec)[0];
30a20e97
MJ
3948 if (repr->write)
3949 return NULL;
3950 repr->group_representative = repr;
07ffa034 3951
9771b263 3952 access_count = access_vec->length ();
30a20e97 3953 for (i = 1; i < access_count; i++)
07ffa034 3954 {
9771b263 3955 struct access *access = (*access_vec)[i];
07ffa034
MJ
3956 if (access->write)
3957 return NULL;
30a20e97
MJ
3958 access->group_representative = repr;
3959 access->next_sibling = repr->next_sibling;
3960 repr->next_sibling = access;
07ffa034
MJ
3961 }
3962
30a20e97
MJ
3963 repr->grp_read = 1;
3964 repr->grp_scalar_ptr = 1;
3965 return repr;
07ffa034
MJ
3966}
3967
c1ed6a01
MJ
3968/* Return true iff this ACCESS precludes IPA-SRA of the parameter it is
3969 associated with. REQ_ALIGN is the minimum required alignment. */
c6a2c25d
MJ
3970
3971static bool
c1ed6a01 3972access_precludes_ipa_sra_p (struct access *access, unsigned int req_align)
c6a2c25d 3973{
c1ed6a01 3974 unsigned int exp_align;
c6a2c25d
MJ
3975 /* Avoid issues such as the second simple testcase in PR 42025. The problem
3976 is incompatible assign in a call statement (and possibly even in asm
3977 statements). This can be relaxed by using a new temporary but only for
3978 non-TREE_ADDRESSABLE types and is probably not worth the complexity. (In
3979 intraprocedural SRA we deal with this by keeping the old aggregate around,
3980 something we cannot do in IPA-SRA.) */
3981 if (access->write
3982 && (is_gimple_call (access->stmt)
3983 || gimple_code (access->stmt) == GIMPLE_ASM))
3984 return true;
3985
c1ed6a01
MJ
3986 exp_align = get_object_alignment (access->expr);
3987 if (exp_align < req_align)
3988 return true;
3989
c6a2c25d
MJ
3990 return false;
3991}
3992
3993
07ffa034
MJ
3994/* Sort collected accesses for parameter PARM, identify representatives for
3995 each accessed region and link them together. Return NULL if there are
3996 different but overlapping accesses, return the special ptr value meaning
3997 there are no accesses for this parameter if that is the case and return the
3998 first representative otherwise. Set *RO_GRP if there is a group of accesses
3999 with only read (i.e. no write) accesses. */
4000
4001static struct access *
4002splice_param_accesses (tree parm, bool *ro_grp)
4003{
4004 int i, j, access_count, group_count;
4005 int agg_size, total_size = 0;
4006 struct access *access, *res, **prev_acc_ptr = &res;
9771b263 4007 vec<access_p> *access_vec;
07ffa034
MJ
4008
4009 access_vec = get_base_access_vector (parm);
4010 if (!access_vec)
4011 return &no_accesses_representant;
9771b263 4012 access_count = access_vec->length ();
07ffa034 4013
9771b263 4014 access_vec->qsort (compare_access_positions);
07ffa034
MJ
4015
4016 i = 0;
4017 total_size = 0;
4018 group_count = 0;
4019 while (i < access_count)
4020 {
4021 bool modification;
82d49829 4022 tree a1_alias_type;
9771b263 4023 access = (*access_vec)[i];
07ffa034 4024 modification = access->write;
c1ed6a01 4025 if (access_precludes_ipa_sra_p (access, TYPE_ALIGN (access->type)))
c6a2c25d 4026 return NULL;
82d49829 4027 a1_alias_type = reference_alias_ptr_type (access->expr);
07ffa034
MJ
4028
4029 /* Access is about to become group representative unless we find some
4030 nasty overlap which would preclude us from breaking this parameter
4031 apart. */
4032
4033 j = i + 1;
4034 while (j < access_count)
4035 {
9771b263 4036 struct access *ac2 = (*access_vec)[j];
07ffa034
MJ
4037 if (ac2->offset != access->offset)
4038 {
4039 /* All or nothing law for parameters. */
4040 if (access->offset + access->size > ac2->offset)
4041 return NULL;
4042 else
4043 break;
4044 }
4045 else if (ac2->size != access->size)
4046 return NULL;
4047
c1ed6a01 4048 if (access_precludes_ipa_sra_p (ac2, TYPE_ALIGN (access->type))
363e01cc
MJ
4049 || (ac2->type != access->type
4050 && (TREE_ADDRESSABLE (ac2->type)
82d49829
MJ
4051 || TREE_ADDRESSABLE (access->type)))
4052 || (reference_alias_ptr_type (ac2->expr) != a1_alias_type))
c6a2c25d
MJ
4053 return NULL;
4054
07ffa034 4055 modification |= ac2->write;
30a20e97
MJ
4056 ac2->group_representative = access;
4057 ac2->next_sibling = access->next_sibling;
4058 access->next_sibling = ac2;
07ffa034
MJ
4059 j++;
4060 }
4061
4062 group_count++;
4063 access->grp_maybe_modified = modification;
4064 if (!modification)
4065 *ro_grp = true;
4066 *prev_acc_ptr = access;
4067 prev_acc_ptr = &access->next_grp;
4068 total_size += access->size;
4069 i = j;
4070 }
4071
4072 if (POINTER_TYPE_P (TREE_TYPE (parm)))
ae7e9ddd 4073 agg_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))));
07ffa034 4074 else
ae7e9ddd 4075 agg_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (parm)));
07ffa034
MJ
4076 if (total_size >= agg_size)
4077 return NULL;
4078
4079 gcc_assert (group_count > 0);
4080 return res;
4081}
4082
4083/* Decide whether parameters with representative accesses given by REPR should
4084 be reduced into components. */
4085
4086static int
4087decide_one_param_reduction (struct access *repr)
4088{
4089 int total_size, cur_parm_size, agg_size, new_param_count, parm_size_limit;
4090 bool by_ref;
4091 tree parm;
4092
4093 parm = repr->base;
ae7e9ddd 4094 cur_parm_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (parm)));
07ffa034
MJ
4095 gcc_assert (cur_parm_size > 0);
4096
4097 if (POINTER_TYPE_P (TREE_TYPE (parm)))
4098 {
4099 by_ref = true;
ae7e9ddd 4100 agg_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))));
07ffa034
MJ
4101 }
4102 else
4103 {
4104 by_ref = false;
4105 agg_size = cur_parm_size;
4106 }
4107
4108 if (dump_file)
4109 {
4110 struct access *acc;
4111 fprintf (dump_file, "Evaluating PARAM group sizes for ");
4112 print_generic_expr (dump_file, parm, 0);
4113 fprintf (dump_file, " (UID: %u): \n", DECL_UID (parm));
4114 for (acc = repr; acc; acc = acc->next_grp)
4115 dump_access (dump_file, acc, true);
4116 }
4117
4118 total_size = 0;
4119 new_param_count = 0;
4120
4121 for (; repr; repr = repr->next_grp)
4122 {
4123 gcc_assert (parm == repr->base);
5e9fba51
EB
4124
4125 /* Taking the address of a non-addressable field is verboten. */
4126 if (by_ref && repr->non_addressable)
4127 return 0;
07ffa034 4128
191879f9
RG
4129 /* Do not decompose a non-BLKmode param in a way that would
4130 create BLKmode params. Especially for by-reference passing
4131 (thus, pointer-type param) this is hardly worthwhile. */
4132 if (DECL_MODE (parm) != BLKmode
4133 && TYPE_MODE (repr->type) == BLKmode)
4134 return 0;
4135
07ffa034
MJ
4136 if (!by_ref || (!repr->grp_maybe_modified
4137 && !repr->grp_not_necessarilly_dereferenced))
4138 total_size += repr->size;
4139 else
4140 total_size += cur_parm_size;
5e9fba51
EB
4141
4142 new_param_count++;
07ffa034
MJ
4143 }
4144
4145 gcc_assert (new_param_count > 0);
4146
4147 if (optimize_function_for_size_p (cfun))
4148 parm_size_limit = cur_parm_size;
4149 else
4150 parm_size_limit = (PARAM_VALUE (PARAM_IPA_SRA_PTR_GROWTH_FACTOR)
4151 * cur_parm_size);
4152
4153 if (total_size < agg_size
4154 && total_size <= parm_size_limit)
4155 {
4156 if (dump_file)
4157 fprintf (dump_file, " ....will be split into %i components\n",
4158 new_param_count);
4159 return new_param_count;
4160 }
4161 else
4162 return 0;
4163}
4164
4165/* The order of the following enums is important, we need to do extra work for
4166 UNUSED_PARAMS, BY_VAL_ACCESSES and UNMODIF_BY_REF_ACCESSES. */
4167enum ipa_splicing_result { NO_GOOD_ACCESS, UNUSED_PARAMS, BY_VAL_ACCESSES,
4168 MODIF_BY_REF_ACCESSES, UNMODIF_BY_REF_ACCESSES };
4169
4170/* Identify representatives of all accesses to all candidate parameters for
4171 IPA-SRA. Return result based on what representatives have been found. */
4172
4173static enum ipa_splicing_result
9771b263 4174splice_all_param_accesses (vec<access_p> &representatives)
07ffa034
MJ
4175{
4176 enum ipa_splicing_result result = NO_GOOD_ACCESS;
4177 tree parm;
4178 struct access *repr;
4179
9771b263 4180 representatives.create (func_param_count);
07ffa034
MJ
4181
4182 for (parm = DECL_ARGUMENTS (current_function_decl);
4183 parm;
910ad8de 4184 parm = DECL_CHAIN (parm))
07ffa034
MJ
4185 {
4186 if (is_unused_scalar_param (parm))
4187 {
9771b263 4188 representatives.quick_push (&no_accesses_representant);
07ffa034
MJ
4189 if (result == NO_GOOD_ACCESS)
4190 result = UNUSED_PARAMS;
4191 }
4192 else if (POINTER_TYPE_P (TREE_TYPE (parm))
4193 && is_gimple_reg_type (TREE_TYPE (TREE_TYPE (parm)))
4194 && bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
4195 {
4196 repr = unmodified_by_ref_scalar_representative (parm);
9771b263 4197 representatives.quick_push (repr);
07ffa034
MJ
4198 if (repr)
4199 result = UNMODIF_BY_REF_ACCESSES;
4200 }
4201 else if (bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
4202 {
4203 bool ro_grp = false;
4204 repr = splice_param_accesses (parm, &ro_grp);
9771b263 4205 representatives.quick_push (repr);
07ffa034
MJ
4206
4207 if (repr && !no_accesses_p (repr))
4208 {
4209 if (POINTER_TYPE_P (TREE_TYPE (parm)))
4210 {
4211 if (ro_grp)
4212 result = UNMODIF_BY_REF_ACCESSES;
4213 else if (result < MODIF_BY_REF_ACCESSES)
4214 result = MODIF_BY_REF_ACCESSES;
4215 }
4216 else if (result < BY_VAL_ACCESSES)
4217 result = BY_VAL_ACCESSES;
4218 }
4219 else if (no_accesses_p (repr) && (result == NO_GOOD_ACCESS))
4220 result = UNUSED_PARAMS;
4221 }
4222 else
9771b263 4223 representatives.quick_push (NULL);
07ffa034
MJ
4224 }
4225
4226 if (result == NO_GOOD_ACCESS)
4227 {
9771b263 4228 representatives.release ();
07ffa034
MJ
4229 return NO_GOOD_ACCESS;
4230 }
4231
4232 return result;
4233}
4234
4235/* Return the index of BASE in PARMS. Abort if it is not found. */
4236
4237static inline int
9771b263 4238get_param_index (tree base, vec<tree> parms)
07ffa034
MJ
4239{
4240 int i, len;
4241
9771b263 4242 len = parms.length ();
07ffa034 4243 for (i = 0; i < len; i++)
9771b263 4244 if (parms[i] == base)
07ffa034
MJ
4245 return i;
4246 gcc_unreachable ();
4247}
4248
4249/* Convert the decisions made at the representative level into compact
4250 parameter adjustments. REPRESENTATIVES are pointers to first
4251 representatives of each param accesses, ADJUSTMENTS_COUNT is the expected
4252 final number of adjustments. */
4253
4254static ipa_parm_adjustment_vec
9771b263 4255turn_representatives_into_adjustments (vec<access_p> representatives,
07ffa034
MJ
4256 int adjustments_count)
4257{
9771b263 4258 vec<tree> parms;
07ffa034
MJ
4259 ipa_parm_adjustment_vec adjustments;
4260 tree parm;
4261 int i;
4262
4263 gcc_assert (adjustments_count > 0);
4264 parms = ipa_get_vector_of_formal_parms (current_function_decl);
9771b263 4265 adjustments.create (adjustments_count);
07ffa034 4266 parm = DECL_ARGUMENTS (current_function_decl);
910ad8de 4267 for (i = 0; i < func_param_count; i++, parm = DECL_CHAIN (parm))
07ffa034 4268 {
9771b263 4269 struct access *repr = representatives[i];
07ffa034
MJ
4270
4271 if (!repr || no_accesses_p (repr))
4272 {
f32682ca 4273 struct ipa_parm_adjustment adj;
07ffa034 4274
f32682ca
DN
4275 memset (&adj, 0, sizeof (adj));
4276 adj.base_index = get_param_index (parm, parms);
4277 adj.base = parm;
07ffa034 4278 if (!repr)
f32682ca 4279 adj.copy_param = 1;
07ffa034 4280 else
f32682ca 4281 adj.remove_param = 1;
9771b263 4282 adjustments.quick_push (adj);
07ffa034
MJ
4283 }
4284 else
4285 {
f32682ca 4286 struct ipa_parm_adjustment adj;
07ffa034
MJ
4287 int index = get_param_index (parm, parms);
4288
4289 for (; repr; repr = repr->next_grp)
4290 {
f32682ca 4291 memset (&adj, 0, sizeof (adj));
07ffa034 4292 gcc_assert (repr->base == parm);
f32682ca
DN
4293 adj.base_index = index;
4294 adj.base = repr->base;
4295 adj.type = repr->type;
4296 adj.alias_ptr_type = reference_alias_ptr_type (repr->expr);
4297 adj.offset = repr->offset;
4298 adj.by_ref = (POINTER_TYPE_P (TREE_TYPE (repr->base))
4299 && (repr->grp_maybe_modified
4300 || repr->grp_not_necessarilly_dereferenced));
9771b263 4301 adjustments.quick_push (adj);
07ffa034
MJ
4302 }
4303 }
4304 }
9771b263 4305 parms.release ();
07ffa034
MJ
4306 return adjustments;
4307}
4308
4309/* Analyze the collected accesses and produce a plan what to do with the
4310 parameters in the form of adjustments, NULL meaning nothing. */
4311
4312static ipa_parm_adjustment_vec
4313analyze_all_param_acesses (void)
4314{
4315 enum ipa_splicing_result repr_state;
4316 bool proceed = false;
4317 int i, adjustments_count = 0;
9771b263 4318 vec<access_p> representatives;
07ffa034
MJ
4319 ipa_parm_adjustment_vec adjustments;
4320
9771b263 4321 repr_state = splice_all_param_accesses (representatives);
07ffa034 4322 if (repr_state == NO_GOOD_ACCESS)
c3284718 4323 return ipa_parm_adjustment_vec ();
07ffa034
MJ
4324
4325 /* If there are any parameters passed by reference which are not modified
4326 directly, we need to check whether they can be modified indirectly. */
4327 if (repr_state == UNMODIF_BY_REF_ACCESSES)
4328 {
4329 analyze_caller_dereference_legality (representatives);
4330 analyze_modified_params (representatives);
4331 }
4332
4333 for (i = 0; i < func_param_count; i++)
4334 {
9771b263 4335 struct access *repr = representatives[i];
07ffa034
MJ
4336
4337 if (repr && !no_accesses_p (repr))
4338 {
4339 if (repr->grp_scalar_ptr)
4340 {
4341 adjustments_count++;
4342 if (repr->grp_not_necessarilly_dereferenced
4343 || repr->grp_maybe_modified)
9771b263 4344 representatives[i] = NULL;
07ffa034
MJ
4345 else
4346 {
4347 proceed = true;
4348 sra_stats.scalar_by_ref_to_by_val++;
4349 }
4350 }
4351 else
4352 {
4353 int new_components = decide_one_param_reduction (repr);
4354
4355 if (new_components == 0)
4356 {
9771b263 4357 representatives[i] = NULL;
07ffa034
MJ
4358 adjustments_count++;
4359 }
4360 else
4361 {
4362 adjustments_count += new_components;
4363 sra_stats.aggregate_params_reduced++;
4364 sra_stats.param_reductions_created += new_components;
4365 proceed = true;
4366 }
4367 }
4368 }
4369 else
4370 {
4371 if (no_accesses_p (repr))
4372 {
4373 proceed = true;
4374 sra_stats.deleted_unused_parameters++;
4375 }
4376 adjustments_count++;
4377 }
4378 }
4379
4380 if (!proceed && dump_file)
4381 fprintf (dump_file, "NOT proceeding to change params.\n");
4382
4383 if (proceed)
4384 adjustments = turn_representatives_into_adjustments (representatives,
4385 adjustments_count);
4386 else
c3284718 4387 adjustments = ipa_parm_adjustment_vec ();
07ffa034 4388
9771b263 4389 representatives.release ();
07ffa034
MJ
4390 return adjustments;
4391}
4392
4393/* If a parameter replacement identified by ADJ does not yet exist in the form
4394 of declaration, create it and record it, otherwise return the previously
4395 created one. */
4396
4397static tree
4398get_replaced_param_substitute (struct ipa_parm_adjustment *adj)
4399{
4400 tree repl;
4401 if (!adj->new_ssa_base)
4402 {
4403 char *pretty_name = make_fancy_name (adj->base);
4404
acd63801 4405 repl = create_tmp_reg (TREE_TYPE (adj->base), "ISR");
07ffa034
MJ
4406 DECL_NAME (repl) = get_identifier (pretty_name);
4407 obstack_free (&name_obstack, pretty_name);
4408
07ffa034
MJ
4409 adj->new_ssa_base = repl;
4410 }
4411 else
4412 repl = adj->new_ssa_base;
4413 return repl;
4414}
4415
4416/* Find the first adjustment for a particular parameter BASE in a vector of
4417 ADJUSTMENTS which is not a copy_param. Return NULL if there is no such
4418 adjustment. */
4419
4420static struct ipa_parm_adjustment *
4421get_adjustment_for_base (ipa_parm_adjustment_vec adjustments, tree base)
4422{
4423 int i, len;
4424
9771b263 4425 len = adjustments.length ();
07ffa034
MJ
4426 for (i = 0; i < len; i++)
4427 {
4428 struct ipa_parm_adjustment *adj;
4429
9771b263 4430 adj = &adjustments[i];
07ffa034
MJ
4431 if (!adj->copy_param && adj->base == base)
4432 return adj;
4433 }
4434
4435 return NULL;
4436}
4437
6cbd3b6a
MJ
4438/* If the statement STMT defines an SSA_NAME of a parameter which is to be
4439 removed because its value is not used, replace the SSA_NAME with a one
4440 relating to a created VAR_DECL together all of its uses and return true.
4441 ADJUSTMENTS is a pointer to an adjustments vector. */
07ffa034
MJ
4442
4443static bool
6cbd3b6a
MJ
4444replace_removed_params_ssa_names (gimple stmt,
4445 ipa_parm_adjustment_vec adjustments)
07ffa034 4446{
07ffa034
MJ
4447 struct ipa_parm_adjustment *adj;
4448 tree lhs, decl, repl, name;
4449
07ffa034
MJ
4450 if (gimple_code (stmt) == GIMPLE_PHI)
4451 lhs = gimple_phi_result (stmt);
4452 else if (is_gimple_assign (stmt))
4453 lhs = gimple_assign_lhs (stmt);
4454 else if (is_gimple_call (stmt))
4455 lhs = gimple_call_lhs (stmt);
4456 else
4457 gcc_unreachable ();
4458
4459 if (TREE_CODE (lhs) != SSA_NAME)
4460 return false;
70b5e7dc 4461
07ffa034 4462 decl = SSA_NAME_VAR (lhs);
70b5e7dc
RG
4463 if (decl == NULL_TREE
4464 || TREE_CODE (decl) != PARM_DECL)
07ffa034
MJ
4465 return false;
4466
4467 adj = get_adjustment_for_base (adjustments, decl);
4468 if (!adj)
4469 return false;
4470
4471 repl = get_replaced_param_substitute (adj);
4472 name = make_ssa_name (repl, stmt);
4473
4474 if (dump_file)
4475 {
4476 fprintf (dump_file, "replacing an SSA name of a removed param ");
4477 print_generic_expr (dump_file, lhs, 0);
4478 fprintf (dump_file, " with ");
4479 print_generic_expr (dump_file, name, 0);
4480 fprintf (dump_file, "\n");
4481 }
4482
4483 if (is_gimple_assign (stmt))
4484 gimple_assign_set_lhs (stmt, name);
4485 else if (is_gimple_call (stmt))
4486 gimple_call_set_lhs (stmt, name);
4487 else
4488 gimple_phi_set_result (stmt, name);
4489
4490 replace_uses_by (lhs, name);
eed5f58a 4491 release_ssa_name (lhs);
07ffa034
MJ
4492 return true;
4493}
4494
6cbd3b6a
MJ
4495/* If the expression *EXPR should be replaced by a reduction of a parameter, do
4496 so. ADJUSTMENTS is a pointer to a vector of adjustments. CONVERT
4497 specifies whether the function should care about type incompatibility the
4498 current and new expressions. If it is false, the function will leave
4499 incompatibility issues to the caller. Return true iff the expression
4500 was modified. */
07ffa034
MJ
4501
4502static bool
6cbd3b6a
MJ
4503sra_ipa_modify_expr (tree *expr, bool convert,
4504 ipa_parm_adjustment_vec adjustments)
07ffa034 4505{
07ffa034
MJ
4506 int i, len;
4507 struct ipa_parm_adjustment *adj, *cand = NULL;
4508 HOST_WIDE_INT offset, size, max_size;
4509 tree base, src;
4510
9771b263 4511 len = adjustments.length ();
07ffa034
MJ
4512
4513 if (TREE_CODE (*expr) == BIT_FIELD_REF
4514 || TREE_CODE (*expr) == IMAGPART_EXPR
4515 || TREE_CODE (*expr) == REALPART_EXPR)
c6a2c25d
MJ
4516 {
4517 expr = &TREE_OPERAND (*expr, 0);
6cbd3b6a 4518 convert = true;
c6a2c25d 4519 }
07ffa034
MJ
4520
4521 base = get_ref_base_and_extent (*expr, &offset, &size, &max_size);
4522 if (!base || size == -1 || max_size == -1)
4523 return false;
4524
70f34814
RG
4525 if (TREE_CODE (base) == MEM_REF)
4526 {
4527 offset += mem_ref_offset (base).low * BITS_PER_UNIT;
4528 base = TREE_OPERAND (base, 0);
4529 }
07ffa034
MJ
4530
4531 base = get_ssa_base_param (base);
4532 if (!base || TREE_CODE (base) != PARM_DECL)
4533 return false;
4534
4535 for (i = 0; i < len; i++)
4536 {
9771b263 4537 adj = &adjustments[i];
07ffa034 4538
5d751b0c
JJ
4539 if (adj->base == base
4540 && (adj->offset == offset || adj->remove_param))
07ffa034
MJ
4541 {
4542 cand = adj;
4543 break;
4544 }
4545 }
4546 if (!cand || cand->copy_param || cand->remove_param)
4547 return false;
4548
4549 if (cand->by_ref)
70f34814 4550 src = build_simple_mem_ref (cand->reduction);
07ffa034
MJ
4551 else
4552 src = cand->reduction;
4553
4554 if (dump_file && (dump_flags & TDF_DETAILS))
4555 {
4556 fprintf (dump_file, "About to replace expr ");
4557 print_generic_expr (dump_file, *expr, 0);
4558 fprintf (dump_file, " with ");
4559 print_generic_expr (dump_file, src, 0);
4560 fprintf (dump_file, "\n");
4561 }
4562
6cbd3b6a 4563 if (convert && !useless_type_conversion_p (TREE_TYPE (*expr), cand->type))
07ffa034
MJ
4564 {
4565 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*expr), src);
4566 *expr = vce;
4567 }
c6a2c25d
MJ
4568 else
4569 *expr = src;
07ffa034
MJ
4570 return true;
4571}
4572
6cbd3b6a
MJ
4573/* If the statement pointed to by STMT_PTR contains any expressions that need
4574 to replaced with a different one as noted by ADJUSTMENTS, do so. Handle any
4575 potential type incompatibilities (GSI is used to accommodate conversion
4576 statements and must point to the statement). Return true iff the statement
4577 was modified. */
07ffa034 4578
6cbd3b6a
MJ
4579static bool
4580sra_ipa_modify_assign (gimple *stmt_ptr, gimple_stmt_iterator *gsi,
4581 ipa_parm_adjustment_vec adjustments)
07ffa034
MJ
4582{
4583 gimple stmt = *stmt_ptr;
c6a2c25d
MJ
4584 tree *lhs_p, *rhs_p;
4585 bool any;
07ffa034
MJ
4586
4587 if (!gimple_assign_single_p (stmt))
6cbd3b6a 4588 return false;
07ffa034 4589
c6a2c25d
MJ
4590 rhs_p = gimple_assign_rhs1_ptr (stmt);
4591 lhs_p = gimple_assign_lhs_ptr (stmt);
4592
6cbd3b6a
MJ
4593 any = sra_ipa_modify_expr (rhs_p, false, adjustments);
4594 any |= sra_ipa_modify_expr (lhs_p, false, adjustments);
c6a2c25d
MJ
4595 if (any)
4596 {
d557591d
MJ
4597 tree new_rhs = NULL_TREE;
4598
c6a2c25d 4599 if (!useless_type_conversion_p (TREE_TYPE (*lhs_p), TREE_TYPE (*rhs_p)))
92e97cdd
MJ
4600 {
4601 if (TREE_CODE (*rhs_p) == CONSTRUCTOR)
4602 {
4603 /* V_C_Es of constructors can cause trouble (PR 42714). */
4604 if (is_gimple_reg_type (TREE_TYPE (*lhs_p)))
e8160c9a 4605 *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
92e97cdd 4606 else
9771b263
DN
4607 *rhs_p = build_constructor (TREE_TYPE (*lhs_p),
4608 NULL);
92e97cdd
MJ
4609 }
4610 else
4611 new_rhs = fold_build1_loc (gimple_location (stmt),
4612 VIEW_CONVERT_EXPR, TREE_TYPE (*lhs_p),
4613 *rhs_p);
4614 }
d557591d
MJ
4615 else if (REFERENCE_CLASS_P (*rhs_p)
4616 && is_gimple_reg_type (TREE_TYPE (*lhs_p))
4617 && !is_gimple_reg (*lhs_p))
4618 /* This can happen when an assignment in between two single field
4619 structures is turned into an assignment in between two pointers to
4620 scalars (PR 42237). */
4621 new_rhs = *rhs_p;
4622
4623 if (new_rhs)
c6a2c25d 4624 {
d557591d 4625 tree tmp = force_gimple_operand_gsi (gsi, new_rhs, true, NULL_TREE,
c6a2c25d
MJ
4626 true, GSI_SAME_STMT);
4627
4628 gimple_assign_set_rhs_from_tree (gsi, tmp);
4629 }
4630
6cbd3b6a 4631 return true;
c6a2c25d 4632 }
07ffa034 4633
6cbd3b6a
MJ
4634 return false;
4635}
4636
4637/* Traverse the function body and all modifications as described in
8cbeddcc 4638 ADJUSTMENTS. Return true iff the CFG has been changed. */
6cbd3b6a 4639
8cbeddcc 4640static bool
6cbd3b6a
MJ
4641ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments)
4642{
8cbeddcc 4643 bool cfg_changed = false;
6cbd3b6a
MJ
4644 basic_block bb;
4645
4646 FOR_EACH_BB (bb)
4647 {
4648 gimple_stmt_iterator gsi;
6cbd3b6a
MJ
4649
4650 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4651 replace_removed_params_ssa_names (gsi_stmt (gsi), adjustments);
4652
4653 gsi = gsi_start_bb (bb);
4654 while (!gsi_end_p (gsi))
4655 {
4656 gimple stmt = gsi_stmt (gsi);
4657 bool modified = false;
4658 tree *t;
4659 unsigned i;
4660
4661 switch (gimple_code (stmt))
4662 {
4663 case GIMPLE_RETURN:
4664 t = gimple_return_retval_ptr (stmt);
4665 if (*t != NULL_TREE)
4666 modified |= sra_ipa_modify_expr (t, true, adjustments);
4667 break;
4668
4669 case GIMPLE_ASSIGN:
4670 modified |= sra_ipa_modify_assign (&stmt, &gsi, adjustments);
4671 modified |= replace_removed_params_ssa_names (stmt, adjustments);
4672 break;
4673
4674 case GIMPLE_CALL:
4675 /* Operands must be processed before the lhs. */
4676 for (i = 0; i < gimple_call_num_args (stmt); i++)
4677 {
4678 t = gimple_call_arg_ptr (stmt, i);
4679 modified |= sra_ipa_modify_expr (t, true, adjustments);
4680 }
4681
4682 if (gimple_call_lhs (stmt))
4683 {
4684 t = gimple_call_lhs_ptr (stmt);
4685 modified |= sra_ipa_modify_expr (t, false, adjustments);
4686 modified |= replace_removed_params_ssa_names (stmt,
4687 adjustments);
4688 }
4689 break;
4690
4691 case GIMPLE_ASM:
4692 for (i = 0; i < gimple_asm_ninputs (stmt); i++)
4693 {
4694 t = &TREE_VALUE (gimple_asm_input_op (stmt, i));
4695 modified |= sra_ipa_modify_expr (t, true, adjustments);
4696 }
4697 for (i = 0; i < gimple_asm_noutputs (stmt); i++)
4698 {
4699 t = &TREE_VALUE (gimple_asm_output_op (stmt, i));
4700 modified |= sra_ipa_modify_expr (t, false, adjustments);
4701 }
4702 break;
4703
4704 default:
4705 break;
4706 }
4707
4708 if (modified)
4709 {
6cbd3b6a 4710 update_stmt (stmt);
8cbeddcc
MJ
4711 if (maybe_clean_eh_stmt (stmt)
4712 && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
4713 cfg_changed = true;
6cbd3b6a
MJ
4714 }
4715 gsi_next (&gsi);
4716 }
6cbd3b6a 4717 }
8cbeddcc
MJ
4718
4719 return cfg_changed;
07ffa034
MJ
4720}
4721
4722/* Call gimple_debug_bind_reset_value on all debug statements describing
4723 gimple register parameters that are being removed or replaced. */
4724
4725static void
4726sra_ipa_reset_debug_stmts (ipa_parm_adjustment_vec adjustments)
4727{
4728 int i, len;
ddb555ed 4729 gimple_stmt_iterator *gsip = NULL, gsi;
07ffa034 4730
ddb555ed
JJ
4731 if (MAY_HAVE_DEBUG_STMTS && single_succ_p (ENTRY_BLOCK_PTR))
4732 {
4733 gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
4734 gsip = &gsi;
4735 }
9771b263 4736 len = adjustments.length ();
07ffa034
MJ
4737 for (i = 0; i < len; i++)
4738 {
4739 struct ipa_parm_adjustment *adj;
4740 imm_use_iterator ui;
ddb555ed
JJ
4741 gimple stmt, def_temp;
4742 tree name, vexpr, copy = NULL_TREE;
4743 use_operand_p use_p;
07ffa034 4744
9771b263 4745 adj = &adjustments[i];
07ffa034
MJ
4746 if (adj->copy_param || !is_gimple_reg (adj->base))
4747 continue;
32244553 4748 name = ssa_default_def (cfun, adj->base);
ddb555ed
JJ
4749 vexpr = NULL;
4750 if (name)
4751 FOR_EACH_IMM_USE_STMT (stmt, ui, name)
4752 {
5d751b0c
JJ
4753 if (gimple_clobber_p (stmt))
4754 {
4755 gimple_stmt_iterator cgsi = gsi_for_stmt (stmt);
4756 unlink_stmt_vdef (stmt);
4757 gsi_remove (&cgsi, true);
4758 release_defs (stmt);
4759 continue;
4760 }
ddb555ed
JJ
4761 /* All other users must have been removed by
4762 ipa_sra_modify_function_body. */
4763 gcc_assert (is_gimple_debug (stmt));
4764 if (vexpr == NULL && gsip != NULL)
4765 {
4766 gcc_assert (TREE_CODE (adj->base) == PARM_DECL);
4767 vexpr = make_node (DEBUG_EXPR_DECL);
4768 def_temp = gimple_build_debug_source_bind (vexpr, adj->base,
4769 NULL);
4770 DECL_ARTIFICIAL (vexpr) = 1;
4771 TREE_TYPE (vexpr) = TREE_TYPE (name);
4772 DECL_MODE (vexpr) = DECL_MODE (adj->base);
4773 gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
4774 }
4775 if (vexpr)
4776 {
4777 FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
4778 SET_USE (use_p, vexpr);
4779 }
4780 else
4781 gimple_debug_bind_reset_value (stmt);
4782 update_stmt (stmt);
4783 }
4784 /* Create a VAR_DECL for debug info purposes. */
4785 if (!DECL_IGNORED_P (adj->base))
07ffa034 4786 {
ddb555ed
JJ
4787 copy = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
4788 VAR_DECL, DECL_NAME (adj->base),
4789 TREE_TYPE (adj->base));
4790 if (DECL_PT_UID_SET_P (adj->base))
4791 SET_DECL_PT_UID (copy, DECL_PT_UID (adj->base));
4792 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (adj->base);
4793 TREE_READONLY (copy) = TREE_READONLY (adj->base);
4794 TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (adj->base);
4795 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (adj->base);
4796 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (adj->base);
4797 DECL_IGNORED_P (copy) = DECL_IGNORED_P (adj->base);
4798 DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (adj->base);
4799 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
4800 SET_DECL_RTL (copy, 0);
4801 TREE_USED (copy) = 1;
4802 DECL_CONTEXT (copy) = current_function_decl;
ddb555ed
JJ
4803 add_local_decl (cfun, copy);
4804 DECL_CHAIN (copy) =
4805 BLOCK_VARS (DECL_INITIAL (current_function_decl));
4806 BLOCK_VARS (DECL_INITIAL (current_function_decl)) = copy;
4807 }
4808 if (gsip != NULL && copy && target_for_debug_bind (adj->base))
4809 {
4810 gcc_assert (TREE_CODE (adj->base) == PARM_DECL);
4811 if (vexpr)
4812 def_temp = gimple_build_debug_bind (copy, vexpr, NULL);
4813 else
4814 def_temp = gimple_build_debug_source_bind (copy, adj->base,
4815 NULL);
4816 gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
07ffa034
MJ
4817 }
4818 }
4819}
4820
a6f834c5 4821/* Return false iff all callers have at least as many actual arguments as there
2f3cdcf5
MJ
4822 are formal parameters in the current function. */
4823
4824static bool
a6f834c5
JH
4825not_all_callers_have_enough_arguments_p (struct cgraph_node *node,
4826 void *data ATTRIBUTE_UNUSED)
2f3cdcf5
MJ
4827{
4828 struct cgraph_edge *cs;
4829 for (cs = node->callers; cs; cs = cs->next_caller)
4830 if (!callsite_has_enough_arguments_p (cs->call_stmt))
a6f834c5 4831 return true;
2f3cdcf5 4832
a6f834c5 4833 return false;
2f3cdcf5
MJ
4834}
4835
a6f834c5 4836/* Convert all callers of NODE. */
2f3cdcf5 4837
a6f834c5
JH
4838static bool
4839convert_callers_for_node (struct cgraph_node *node,
4840 void *data)
07ffa034 4841{
9771b263 4842 ipa_parm_adjustment_vec *adjustments = (ipa_parm_adjustment_vec *) data;
6096017e 4843 bitmap recomputed_callers = BITMAP_ALLOC (NULL);
a6f834c5 4844 struct cgraph_edge *cs;
07ffa034
MJ
4845
4846 for (cs = node->callers; cs; cs = cs->next_caller)
4847 {
67348ccc 4848 push_cfun (DECL_STRUCT_FUNCTION (cs->caller->decl));
07ffa034
MJ
4849
4850 if (dump_file)
9de04252 4851 fprintf (dump_file, "Adjusting call %s/%i -> %s/%i\n",
fec39fa6 4852 xstrdup (cs->caller->name ()),
67348ccc 4853 cs->caller->order,
fec39fa6 4854 xstrdup (cs->callee->name ()),
67348ccc 4855 cs->callee->order);
07ffa034 4856
9771b263 4857 ipa_modify_call_arguments (cs, cs->call_stmt, *adjustments);
07ffa034
MJ
4858
4859 pop_cfun ();
4860 }
6096017e
MJ
4861
4862 for (cs = node->callers; cs; cs = cs->next_caller)
bb7e6d55 4863 if (bitmap_set_bit (recomputed_callers, cs->caller->uid)
67348ccc 4864 && gimple_in_ssa_p (DECL_STRUCT_FUNCTION (cs->caller->decl)))
632b4f8e 4865 compute_inline_parameters (cs->caller, true);
6096017e
MJ
4866 BITMAP_FREE (recomputed_callers);
4867
a6f834c5
JH
4868 return true;
4869}
4870
4871/* Convert all callers of NODE to pass parameters as given in ADJUSTMENTS. */
4872
4873static void
4874convert_callers (struct cgraph_node *node, tree old_decl,
4875 ipa_parm_adjustment_vec adjustments)
4876{
a6f834c5
JH
4877 basic_block this_block;
4878
4879 cgraph_for_node_and_aliases (node, convert_callers_for_node,
9771b263 4880 &adjustments, false);
a6f834c5 4881
2f3cdcf5
MJ
4882 if (!encountered_recursive_call)
4883 return;
4884
07ffa034
MJ
4885 FOR_EACH_BB (this_block)
4886 {
4887 gimple_stmt_iterator gsi;
4888
4889 for (gsi = gsi_start_bb (this_block); !gsi_end_p (gsi); gsi_next (&gsi))
4890 {
4891 gimple stmt = gsi_stmt (gsi);
566f27e4
JJ
4892 tree call_fndecl;
4893 if (gimple_code (stmt) != GIMPLE_CALL)
4894 continue;
4895 call_fndecl = gimple_call_fndecl (stmt);
bb8e5dca 4896 if (call_fndecl == old_decl)
07ffa034
MJ
4897 {
4898 if (dump_file)
4899 fprintf (dump_file, "Adjusting recursive call");
67348ccc 4900 gimple_call_set_fndecl (stmt, node->decl);
07ffa034
MJ
4901 ipa_modify_call_arguments (NULL, stmt, adjustments);
4902 }
4903 }
4904 }
4905
4906 return;
4907}
4908
4909/* Perform all the modification required in IPA-SRA for NODE to have parameters
8cbeddcc 4910 as given in ADJUSTMENTS. Return true iff the CFG has been changed. */
07ffa034 4911
8cbeddcc 4912static bool
07ffa034
MJ
4913modify_function (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments)
4914{
29be3835 4915 struct cgraph_node *new_node;
8cbeddcc 4916 bool cfg_changed;
9771b263 4917 vec<cgraph_edge_p> redirect_callers = collect_callers_of_node (node);
29be3835
MJ
4918
4919 rebuild_cgraph_edges ();
467a8db0 4920 free_dominance_info (CDI_DOMINATORS);
29be3835 4921 pop_cfun ();
29be3835 4922
9771b263
DN
4923 new_node = cgraph_function_versioning (node, redirect_callers,
4924 NULL,
4925 NULL, false, NULL, NULL, "isra");
4926 redirect_callers.release ();
c7e62a26 4927
67348ccc 4928 push_cfun (DECL_STRUCT_FUNCTION (new_node->decl));
07ffa034 4929 ipa_modify_formal_parameters (current_function_decl, adjustments, "ISRA");
8cbeddcc 4930 cfg_changed = ipa_sra_modify_function_body (adjustments);
07ffa034 4931 sra_ipa_reset_debug_stmts (adjustments);
67348ccc 4932 convert_callers (new_node, node->decl, adjustments);
29be3835 4933 cgraph_make_node_local (new_node);
8cbeddcc 4934 return cfg_changed;
07ffa034
MJ
4935}
4936
9e401b63
JH
4937/* If NODE has a caller, return true. */
4938
4939static bool
4940has_caller_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
4941{
4942 if (node->callers)
4943 return true;
4944 return false;
4945}
4946
07ffa034
MJ
4947/* Return false the function is apparently unsuitable for IPA-SRA based on it's
4948 attributes, return true otherwise. NODE is the cgraph node of the current
4949 function. */
4950
4951static bool
4952ipa_sra_preliminary_function_checks (struct cgraph_node *node)
4953{
4954 if (!cgraph_node_can_be_local_p (node))
4955 {
4956 if (dump_file)
4957 fprintf (dump_file, "Function not local to this compilation unit.\n");
4958 return false;
4959 }
4960
61e03ffc
JH
4961 if (!node->local.can_change_signature)
4962 {
4963 if (dump_file)
4964 fprintf (dump_file, "Function can not change signature.\n");
4965 return false;
4966 }
4967
67348ccc 4968 if (!tree_versionable_function_p (node->decl))
29be3835
MJ
4969 {
4970 if (dump_file)
a23c4464 4971 fprintf (dump_file, "Function is not versionable.\n");
29be3835
MJ
4972 return false;
4973 }
4974
07ffa034
MJ
4975 if (DECL_VIRTUAL_P (current_function_decl))
4976 {
4977 if (dump_file)
4978 fprintf (dump_file, "Function is a virtual method.\n");
4979 return false;
4980 }
4981
67348ccc 4982 if ((DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl))
c3284718 4983 && inline_summary (node)->size >= MAX_INLINE_INSNS_AUTO)
07ffa034
MJ
4984 {
4985 if (dump_file)
4986 fprintf (dump_file, "Function too big to be made truly local.\n");
4987 return false;
4988 }
4989
9e401b63 4990 if (!cgraph_for_node_and_aliases (node, has_caller_p, NULL, true))
07ffa034
MJ
4991 {
4992 if (dump_file)
4993 fprintf (dump_file,
4994 "Function has no callers in this compilation unit.\n");
4995 return false;
4996 }
4997
4998 if (cfun->stdarg)
4999 {
5000 if (dump_file)
5001 fprintf (dump_file, "Function uses stdarg. \n");
5002 return false;
5003 }
5004
67348ccc 5005 if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl)))
5c20baf1
MJ
5006 return false;
5007
07ffa034
MJ
5008 return true;
5009}
5010
5011/* Perform early interprocedural SRA. */
5012
5013static unsigned int
5014ipa_early_sra (void)
5015{
581985d7 5016 struct cgraph_node *node = cgraph_get_node (current_function_decl);
07ffa034
MJ
5017 ipa_parm_adjustment_vec adjustments;
5018 int ret = 0;
5019
5020 if (!ipa_sra_preliminary_function_checks (node))
5021 return 0;
5022
5023 sra_initialize ();
5024 sra_mode = SRA_MODE_EARLY_IPA;
5025
5026 if (!find_param_candidates ())
5027 {
5028 if (dump_file)
5029 fprintf (dump_file, "Function has no IPA-SRA candidates.\n");
5030 goto simple_out;
5031 }
5032
a6f834c5
JH
5033 if (cgraph_for_node_and_aliases (node, not_all_callers_have_enough_arguments_p,
5034 NULL, true))
2f3cdcf5
MJ
5035 {
5036 if (dump_file)
5037 fprintf (dump_file, "There are callers with insufficient number of "
5038 "arguments.\n");
5039 goto simple_out;
5040 }
5041
07ffa034
MJ
5042 bb_dereferences = XCNEWVEC (HOST_WIDE_INT,
5043 func_param_count
5044 * last_basic_block_for_function (cfun));
5045 final_bbs = BITMAP_ALLOC (NULL);
5046
6cbd3b6a 5047 scan_function ();
07ffa034
MJ
5048 if (encountered_apply_args)
5049 {
5050 if (dump_file)
5051 fprintf (dump_file, "Function calls __builtin_apply_args().\n");
5052 goto out;
5053 }
5054
2f3cdcf5
MJ
5055 if (encountered_unchangable_recursive_call)
5056 {
5057 if (dump_file)
5058 fprintf (dump_file, "Function calls itself with insufficient "
5059 "number of arguments.\n");
5060 goto out;
5061 }
5062
07ffa034 5063 adjustments = analyze_all_param_acesses ();
9771b263 5064 if (!adjustments.exists ())
07ffa034
MJ
5065 goto out;
5066 if (dump_file)
5067 ipa_dump_param_adjustments (dump_file, adjustments, current_function_decl);
5068
8cbeddcc
MJ
5069 if (modify_function (node, adjustments))
5070 ret = TODO_update_ssa | TODO_cleanup_cfg;
5071 else
5072 ret = TODO_update_ssa;
9771b263 5073 adjustments.release ();
07ffa034
MJ
5074
5075 statistics_counter_event (cfun, "Unused parameters deleted",
5076 sra_stats.deleted_unused_parameters);
5077 statistics_counter_event (cfun, "Scalar parameters converted to by-value",
5078 sra_stats.scalar_by_ref_to_by_val);
5079 statistics_counter_event (cfun, "Aggregate parameters broken up",
5080 sra_stats.aggregate_params_reduced);
5081 statistics_counter_event (cfun, "Aggregate parameter components created",
5082 sra_stats.param_reductions_created);
5083
5084 out:
5085 BITMAP_FREE (final_bbs);
5086 free (bb_dereferences);
5087 simple_out:
5088 sra_deinitialize ();
5089 return ret;
5090}
5091
5092/* Return if early ipa sra shall be performed. */
5093static bool
5094ipa_early_sra_gate (void)
5095{
a1a6c2df 5096 return flag_ipa_sra && dbg_cnt (eipa_sra);
07ffa034
MJ
5097}
5098
27a4cd48
DM
5099namespace {
5100
5101const pass_data pass_data_early_ipa_sra =
07ffa034 5102{
27a4cd48
DM
5103 GIMPLE_PASS, /* type */
5104 "eipa_sra", /* name */
5105 OPTGROUP_NONE, /* optinfo_flags */
5106 true, /* has_gate */
5107 true, /* has_execute */
5108 TV_IPA_SRA, /* tv_id */
5109 0, /* properties_required */
5110 0, /* properties_provided */
5111 0, /* properties_destroyed */
5112 0, /* todo_flags_start */
5113 TODO_dump_symtab, /* todo_flags_finish */
07ffa034 5114};
27a4cd48
DM
5115
5116class pass_early_ipa_sra : public gimple_opt_pass
5117{
5118public:
c3284718
RS
5119 pass_early_ipa_sra (gcc::context *ctxt)
5120 : gimple_opt_pass (pass_data_early_ipa_sra, ctxt)
27a4cd48
DM
5121 {}
5122
5123 /* opt_pass methods: */
5124 bool gate () { return ipa_early_sra_gate (); }
5125 unsigned int execute () { return ipa_early_sra (); }
5126
5127}; // class pass_early_ipa_sra
5128
5129} // anon namespace
5130
5131gimple_opt_pass *
5132make_pass_early_ipa_sra (gcc::context *ctxt)
5133{
5134 return new pass_early_ipa_sra (ctxt);
5135}