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