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