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