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