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