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