re PR tree-optimization/40582 (ice for non-trivial conversion at assignment with...
[gcc.git] / gcc / tree-sra.c
1 /* Scalar Replacement of Aggregates (SRA) converts some structure
2 references into scalar references, exposing them to the scalar
3 optimizers.
4 Copyright (C) 2008, 2009 Free Software Foundation, Inc.
5 Contributed by Martin Jambor <mjambor@suse.cz>
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
13
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
22
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
74 #include "config.h"
75 #include "system.h"
76 #include "coretypes.h"
77 #include "alloc-pool.h"
78 #include "tm.h"
79 #include "tree.h"
80 #include "gimple.h"
81 #include "tree-flow.h"
82 #include "diagnostic.h"
83 #include "statistics.h"
84 #include "tree-dump.h"
85 #include "timevar.h"
86 #include "params.h"
87 #include "target.h"
88 #include "flags.h"
89
90 /* Enumeration of all aggregate reductions we can do. */
91 enum sra_mode { SRA_MODE_EARLY_INTRA, /* early intraprocedural SRA */
92 SRA_MODE_INTRA }; /* late intraprocedural SRA */
93
94 /* Global variable describing which aggregate reduction we are performing at
95 the moment. */
96 static enum sra_mode sra_mode;
97
98 struct assign_link;
99
100 /* ACCESS represents each access to an aggregate variable (as a whole or a
101 part). It can also represent a group of accesses that refer to exactly the
102 same fragment of an aggregate (i.e. those that have exactly the same offset
103 and size). Such representatives for a single aggregate, once determined,
104 are linked in a linked list and have the group fields set.
105
106 Moreover, when doing intraprocedural SRA, a tree is built from those
107 representatives (by the means of first_child and next_sibling pointers), in
108 which all items in a subtree are "within" the root, i.e. their offset is
109 greater or equal to offset of the root and offset+size is smaller or equal
110 to offset+size of the root. Children of an access are sorted by offset.
111
112 Note that accesses to parts of vector and complex number types always
113 represented by an access to the whole complex number or a vector. It is a
114 duty of the modifying functions to replace them appropriately. */
115
116 struct access
117 {
118 /* Values returned by `get_ref_base_and_extent' for each component reference
119 If EXPR isn't a component reference just set `BASE = EXPR', `OFFSET = 0',
120 `SIZE = TREE_SIZE (TREE_TYPE (expr))'. */
121 HOST_WIDE_INT offset;
122 HOST_WIDE_INT size;
123 tree base;
124
125 /* Expression. */
126 tree expr;
127 /* Type. */
128 tree type;
129
130 /* Next group representative for this aggregate. */
131 struct access *next_grp;
132
133 /* Pointer to the group representative. Pointer to itself if the struct is
134 the representative. */
135 struct access *group_representative;
136
137 /* If this access has any children (in terms of the definition above), this
138 points to the first one. */
139 struct access *first_child;
140
141 /* Pointer to the next sibling in the access tree as described above. */
142 struct access *next_sibling;
143
144 /* Pointers to the first and last element in the linked list of assign
145 links. */
146 struct assign_link *first_link, *last_link;
147
148 /* Pointer to the next access in the work queue. */
149 struct access *next_queued;
150
151 /* Replacement variable for this access "region." Never to be accessed
152 directly, always only by the means of get_access_replacement() and only
153 when grp_to_be_replaced flag is set. */
154 tree replacement_decl;
155
156 /* Is this particular access write access? */
157 unsigned write : 1;
158
159 /* Is this access currently in the work queue? */
160 unsigned grp_queued : 1;
161 /* Does this group contain a write access? This flag is propagated down the
162 access tree. */
163 unsigned grp_write : 1;
164 /* Does this group contain a read access? This flag is propagated down the
165 access tree. */
166 unsigned grp_read : 1;
167 /* Is the subtree rooted in this access fully covered by scalar
168 replacements? */
169 unsigned grp_covered : 1;
170 /* If set to true, this access and all below it in an access tree must not be
171 scalarized. */
172 unsigned grp_unscalarizable_region : 1;
173 /* Whether data have been written to parts of the aggregate covered by this
174 access which is not to be scalarized. This flag is propagated up in the
175 access tree. */
176 unsigned grp_unscalarized_data : 1;
177 /* Does this access and/or group contain a write access through a
178 BIT_FIELD_REF? */
179 unsigned grp_partial_lhs : 1;
180
181 /* Set when a scalar replacement should be created for this variable. We do
182 the decision and creation at different places because create_tmp_var
183 cannot be called from within FOR_EACH_REFERENCED_VAR. */
184 unsigned grp_to_be_replaced : 1;
185 };
186
187 typedef struct access *access_p;
188
189 DEF_VEC_P (access_p);
190 DEF_VEC_ALLOC_P (access_p, heap);
191
192 /* Alloc pool for allocating access structures. */
193 static alloc_pool access_pool;
194
195 /* A structure linking lhs and rhs accesses from an aggregate assignment. They
196 are used to propagate subaccesses from rhs to lhs as long as they don't
197 conflict with what is already there. */
198 struct assign_link
199 {
200 struct access *lacc, *racc;
201 struct assign_link *next;
202 };
203
204 /* Alloc pool for allocating assign link structures. */
205 static alloc_pool link_pool;
206
207 /* Base (tree) -> Vector (VEC(access_p,heap) *) map. */
208 static struct pointer_map_t *base_access_vec;
209
210 /* Bitmap of bases (candidates). */
211 static bitmap candidate_bitmap;
212 /* Obstack for creation of fancy names. */
213 static struct obstack name_obstack;
214
215 /* Head of a linked list of accesses that need to have its subaccesses
216 propagated to their assignment counterparts. */
217 static struct access *work_queue_head;
218
219 /* Dump contents of ACCESS to file F in a human friendly way. If GRP is true,
220 representative fields are dumped, otherwise those which only describe the
221 individual access are. */
222
223 static struct
224 {
225 /* Number of created scalar replacements. */
226 int replacements;
227
228 /* Number of times sra_modify_expr or sra_modify_assign themselves changed an
229 expression. */
230 int exprs;
231
232 /* Number of statements created by generate_subtree_copies. */
233 int subtree_copies;
234
235 /* Number of statements created by load_assign_lhs_subreplacements. */
236 int subreplacements;
237
238 /* Number of times sra_modify_assign has deleted a statement. */
239 int deleted;
240
241 /* Number of times sra_modify_assign has to deal with subaccesses of LHS and
242 RHS reparately due to type conversions or nonexistent matching
243 references. */
244 int separate_lhs_rhs_handling;
245
246 /* Number of processed aggregates is readily available in
247 analyze_all_variable_accesses and so is not stored here. */
248 } sra_stats;
249
250 static void
251 dump_access (FILE *f, struct access *access, bool grp)
252 {
253 fprintf (f, "access { ");
254 fprintf (f, "base = (%d)'", DECL_UID (access->base));
255 print_generic_expr (f, access->base, 0);
256 fprintf (f, "', offset = " HOST_WIDE_INT_PRINT_DEC, access->offset);
257 fprintf (f, ", size = " HOST_WIDE_INT_PRINT_DEC, access->size);
258 fprintf (f, ", expr = ");
259 print_generic_expr (f, access->expr, 0);
260 fprintf (f, ", type = ");
261 print_generic_expr (f, access->type, 0);
262 if (grp)
263 fprintf (f, ", grp_write = %d, grp_read = %d, grp_covered = %d, "
264 "grp_unscalarizable_region = %d, grp_unscalarized_data = %d, "
265 "grp_partial_lhs = %d, grp_to_be_replaced = %d\n",
266 access->grp_write, access->grp_read, access->grp_covered,
267 access->grp_unscalarizable_region, access->grp_unscalarized_data,
268 access->grp_partial_lhs, access->grp_to_be_replaced);
269 else
270 fprintf (f, ", write = %d, grp_partial_lhs = %d\n", access->write,
271 access->grp_partial_lhs);
272 }
273
274 /* Dump a subtree rooted in ACCESS to file F, indent by LEVEL. */
275
276 static void
277 dump_access_tree_1 (FILE *f, struct access *access, int level)
278 {
279 do
280 {
281 int i;
282
283 for (i = 0; i < level; i++)
284 fputs ("* ", dump_file);
285
286 dump_access (f, access, true);
287
288 if (access->first_child)
289 dump_access_tree_1 (f, access->first_child, level + 1);
290
291 access = access->next_sibling;
292 }
293 while (access);
294 }
295
296 /* Dump all access trees for a variable, given the pointer to the first root in
297 ACCESS. */
298
299 static void
300 dump_access_tree (FILE *f, struct access *access)
301 {
302 for (; access; access = access->next_grp)
303 dump_access_tree_1 (f, access, 0);
304 }
305
306 /* Return true iff ACC is non-NULL and has subaccesses. */
307
308 static inline bool
309 access_has_children_p (struct access *acc)
310 {
311 return acc && acc->first_child;
312 }
313
314 /* Return a vector of pointers to accesses for the variable given in BASE or
315 NULL if there is none. */
316
317 static VEC (access_p, heap) *
318 get_base_access_vector (tree base)
319 {
320 void **slot;
321
322 slot = pointer_map_contains (base_access_vec, base);
323 if (!slot)
324 return NULL;
325 else
326 return *(VEC (access_p, heap) **) slot;
327 }
328
329 /* Find an access with required OFFSET and SIZE in a subtree of accesses rooted
330 in ACCESS. Return NULL if it cannot be found. */
331
332 static struct access *
333 find_access_in_subtree (struct access *access, HOST_WIDE_INT offset,
334 HOST_WIDE_INT size)
335 {
336 while (access && (access->offset != offset || access->size != size))
337 {
338 struct access *child = access->first_child;
339
340 while (child && (child->offset + child->size <= offset))
341 child = child->next_sibling;
342 access = child;
343 }
344
345 return access;
346 }
347
348 /* Return the first group representative for DECL or NULL if none exists. */
349
350 static struct access *
351 get_first_repr_for_decl (tree base)
352 {
353 VEC (access_p, heap) *access_vec;
354
355 access_vec = get_base_access_vector (base);
356 if (!access_vec)
357 return NULL;
358
359 return VEC_index (access_p, access_vec, 0);
360 }
361
362 /* Find an access representative for the variable BASE and given OFFSET and
363 SIZE. Requires that access trees have already been built. Return NULL if
364 it cannot be found. */
365
366 static struct access *
367 get_var_base_offset_size_access (tree base, HOST_WIDE_INT offset,
368 HOST_WIDE_INT size)
369 {
370 struct access *access;
371
372 access = get_first_repr_for_decl (base);
373 while (access && (access->offset + access->size <= offset))
374 access = access->next_grp;
375 if (!access)
376 return NULL;
377
378 return find_access_in_subtree (access, offset, size);
379 }
380
381 /* Add LINK to the linked list of assign links of RACC. */
382 static void
383 add_link_to_rhs (struct access *racc, struct assign_link *link)
384 {
385 gcc_assert (link->racc == racc);
386
387 if (!racc->first_link)
388 {
389 gcc_assert (!racc->last_link);
390 racc->first_link = link;
391 }
392 else
393 racc->last_link->next = link;
394
395 racc->last_link = link;
396 link->next = NULL;
397 }
398
399 /* Move all link structures in their linked list in OLD_RACC to the linked list
400 in NEW_RACC. */
401 static void
402 relink_to_new_repr (struct access *new_racc, struct access *old_racc)
403 {
404 if (!old_racc->first_link)
405 {
406 gcc_assert (!old_racc->last_link);
407 return;
408 }
409
410 if (new_racc->first_link)
411 {
412 gcc_assert (!new_racc->last_link->next);
413 gcc_assert (!old_racc->last_link || !old_racc->last_link->next);
414
415 new_racc->last_link->next = old_racc->first_link;
416 new_racc->last_link = old_racc->last_link;
417 }
418 else
419 {
420 gcc_assert (!new_racc->last_link);
421
422 new_racc->first_link = old_racc->first_link;
423 new_racc->last_link = old_racc->last_link;
424 }
425 old_racc->first_link = old_racc->last_link = NULL;
426 }
427
428 /* Add ACCESS to the work queue (which is actually a stack). */
429
430 static void
431 add_access_to_work_queue (struct access *access)
432 {
433 if (!access->grp_queued)
434 {
435 gcc_assert (!access->next_queued);
436 access->next_queued = work_queue_head;
437 access->grp_queued = 1;
438 work_queue_head = access;
439 }
440 }
441
442 /* Pop an access from the work queue, and return it, assuming there is one. */
443
444 static struct access *
445 pop_access_from_work_queue (void)
446 {
447 struct access *access = work_queue_head;
448
449 work_queue_head = access->next_queued;
450 access->next_queued = NULL;
451 access->grp_queued = 0;
452 return access;
453 }
454
455
456 /* Allocate necessary structures. */
457
458 static void
459 sra_initialize (void)
460 {
461 candidate_bitmap = BITMAP_ALLOC (NULL);
462 gcc_obstack_init (&name_obstack);
463 access_pool = create_alloc_pool ("SRA accesses", sizeof (struct access), 16);
464 link_pool = create_alloc_pool ("SRA links", sizeof (struct assign_link), 16);
465 base_access_vec = pointer_map_create ();
466 memset (&sra_stats, 0, sizeof (sra_stats));
467 }
468
469 /* Hook fed to pointer_map_traverse, deallocate stored vectors. */
470
471 static bool
472 delete_base_accesses (const void *key ATTRIBUTE_UNUSED, void **value,
473 void *data ATTRIBUTE_UNUSED)
474 {
475 VEC (access_p, heap) *access_vec;
476 access_vec = (VEC (access_p, heap) *) *value;
477 VEC_free (access_p, heap, access_vec);
478
479 return true;
480 }
481
482 /* Deallocate all general structures. */
483
484 static void
485 sra_deinitialize (void)
486 {
487 BITMAP_FREE (candidate_bitmap);
488 free_alloc_pool (access_pool);
489 free_alloc_pool (link_pool);
490 obstack_free (&name_obstack, NULL);
491
492 pointer_map_traverse (base_access_vec, delete_base_accesses, NULL);
493 pointer_map_destroy (base_access_vec);
494 }
495
496 /* Remove DECL from candidates for SRA and write REASON to the dump file if
497 there is one. */
498 static void
499 disqualify_candidate (tree decl, const char *reason)
500 {
501 bitmap_clear_bit (candidate_bitmap, DECL_UID (decl));
502
503 if (dump_file && (dump_flags & TDF_DETAILS))
504 {
505 fprintf (dump_file, "! Disqualifying ");
506 print_generic_expr (dump_file, decl, 0);
507 fprintf (dump_file, " - %s\n", reason);
508 }
509 }
510
511 /* Return true iff the type contains a field or an element which does not allow
512 scalarization. */
513
514 static bool
515 type_internals_preclude_sra_p (tree type)
516 {
517 tree fld;
518 tree et;
519
520 switch (TREE_CODE (type))
521 {
522 case RECORD_TYPE:
523 case UNION_TYPE:
524 case QUAL_UNION_TYPE:
525 for (fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
526 if (TREE_CODE (fld) == FIELD_DECL)
527 {
528 tree ft = TREE_TYPE (fld);
529
530 if (TREE_THIS_VOLATILE (fld)
531 || !DECL_FIELD_OFFSET (fld) || !DECL_SIZE (fld)
532 || !host_integerp (DECL_FIELD_OFFSET (fld), 1)
533 || !host_integerp (DECL_SIZE (fld), 1))
534 return true;
535
536 if (AGGREGATE_TYPE_P (ft)
537 && type_internals_preclude_sra_p (ft))
538 return true;
539 }
540
541 return false;
542
543 case ARRAY_TYPE:
544 et = TREE_TYPE (type);
545
546 if (AGGREGATE_TYPE_P (et))
547 return type_internals_preclude_sra_p (et);
548 else
549 return false;
550
551 default:
552 return false;
553 }
554 }
555
556 /* Create and insert access for EXPR. Return created access, or NULL if it is
557 not possible. */
558
559 static struct access *
560 create_access (tree expr, bool write)
561 {
562 struct access *access;
563 void **slot;
564 VEC (access_p,heap) *vec;
565 HOST_WIDE_INT offset, size, max_size;
566 tree base = expr;
567 bool unscalarizable_region = false;
568
569 base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
570
571 if (!DECL_P (base) || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
572 return NULL;
573
574 if (size != max_size)
575 {
576 size = max_size;
577 unscalarizable_region = true;
578 }
579
580 if (size < 0)
581 {
582 disqualify_candidate (base, "Encountered an unconstrained access.");
583 return NULL;
584 }
585
586 access = (struct access *) pool_alloc (access_pool);
587 memset (access, 0, sizeof (struct access));
588
589 access->base = base;
590 access->offset = offset;
591 access->size = size;
592 access->expr = expr;
593 access->type = TREE_TYPE (expr);
594 access->write = write;
595 access->grp_unscalarizable_region = unscalarizable_region;
596
597 slot = pointer_map_contains (base_access_vec, base);
598 if (slot)
599 vec = (VEC (access_p, heap) *) *slot;
600 else
601 vec = VEC_alloc (access_p, heap, 32);
602
603 VEC_safe_push (access_p, heap, vec, access);
604
605 *((struct VEC (access_p,heap) **)
606 pointer_map_insert (base_access_vec, base)) = vec;
607
608 return access;
609 }
610
611
612 /* Search the given tree for a declaration by skipping handled components and
613 exclude it from the candidates. */
614
615 static void
616 disqualify_base_of_expr (tree t, const char *reason)
617 {
618 while (handled_component_p (t))
619 t = TREE_OPERAND (t, 0);
620
621 if (DECL_P (t))
622 disqualify_candidate (t, reason);
623 }
624
625 /* Scan expression EXPR and create access structures for all accesses to
626 candidates for scalarization. Return the created access or NULL if none is
627 created. */
628
629 static struct access *
630 build_access_from_expr_1 (tree *expr_ptr, bool write)
631 {
632 struct access *ret = NULL;
633 tree expr = *expr_ptr;
634 bool partial_ref;
635
636 if (TREE_CODE (expr) == BIT_FIELD_REF
637 || TREE_CODE (expr) == IMAGPART_EXPR
638 || TREE_CODE (expr) == REALPART_EXPR)
639 {
640 expr = TREE_OPERAND (expr, 0);
641 partial_ref = true;
642 }
643 else
644 partial_ref = false;
645
646 /* We need to dive through V_C_Es in order to get the size of its parameter
647 and not the result type. Ada produces such statements. We are also
648 capable of handling the topmost V_C_E but not any of those buried in other
649 handled components. */
650 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
651 expr = TREE_OPERAND (expr, 0);
652
653 if (contains_view_convert_expr_p (expr))
654 {
655 disqualify_base_of_expr (expr, "V_C_E under a different handled "
656 "component.");
657 return NULL;
658 }
659
660 switch (TREE_CODE (expr))
661 {
662 case VAR_DECL:
663 case PARM_DECL:
664 case RESULT_DECL:
665 case COMPONENT_REF:
666 case ARRAY_REF:
667 case ARRAY_RANGE_REF:
668 ret = create_access (expr, write);
669 break;
670
671 default:
672 break;
673 }
674
675 if (write && partial_ref && ret)
676 ret->grp_partial_lhs = 1;
677
678 return ret;
679 }
680
681 /* Callback of scan_function. Scan expression EXPR and create access
682 structures for all accesses to candidates for scalarization. Return true if
683 any access has been inserted. */
684
685 static bool
686 build_access_from_expr (tree *expr_ptr,
687 gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED, bool write,
688 void *data ATTRIBUTE_UNUSED)
689 {
690 return build_access_from_expr_1 (expr_ptr, write) != NULL;
691 }
692
693 /* Disqualify LHS and RHS for scalarization if STMT must end its basic block in
694 modes in which it matters, return true iff they have been disqualified. RHS
695 may be NULL, in that case ignore it. If we scalarize an aggregate in
696 intra-SRA we may need to add statements after each statement. This is not
697 possible if a statement unconditionally has to end the basic block. */
698 static bool
699 disqualify_ops_if_throwing_stmt (gimple stmt, tree lhs, tree rhs)
700 {
701 if (stmt_can_throw_internal (stmt) || stmt_ends_bb_p (stmt))
702 {
703 disqualify_base_of_expr (lhs, "LHS of a throwing stmt.");
704 if (rhs)
705 disqualify_base_of_expr (rhs, "RHS of a throwing stmt.");
706 return true;
707 }
708 return false;
709 }
710
711
712 /* Result code for scan_assign callback for scan_function. */
713 enum scan_assign_result { SRA_SA_NONE, /* nothing done for the stmt */
714 SRA_SA_PROCESSED, /* stmt analyzed/changed */
715 SRA_SA_REMOVED }; /* stmt redundant and eliminated */
716
717
718 /* Callback of scan_function. Scan expressions occuring in the statement
719 pointed to by STMT_EXPR, create access structures for all accesses to
720 candidates for scalarization and remove those candidates which occur in
721 statements or expressions that prevent them from being split apart. Return
722 true if any access has been inserted. */
723
724 static enum scan_assign_result
725 build_accesses_from_assign (gimple *stmt_ptr,
726 gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED,
727 void *data ATTRIBUTE_UNUSED)
728 {
729 gimple stmt = *stmt_ptr;
730 tree *lhs_ptr, *rhs_ptr;
731 struct access *lacc, *racc;
732
733 if (!gimple_assign_single_p (stmt))
734 return SRA_SA_NONE;
735
736 lhs_ptr = gimple_assign_lhs_ptr (stmt);
737 rhs_ptr = gimple_assign_rhs1_ptr (stmt);
738
739 if (disqualify_ops_if_throwing_stmt (stmt, *lhs_ptr, *rhs_ptr))
740 return SRA_SA_NONE;
741
742 racc = build_access_from_expr_1 (rhs_ptr, false);
743 lacc = build_access_from_expr_1 (lhs_ptr, true);
744
745 if (lacc && racc
746 && !lacc->grp_unscalarizable_region
747 && !racc->grp_unscalarizable_region
748 && AGGREGATE_TYPE_P (TREE_TYPE (*lhs_ptr))
749 /* FIXME: Turn the following line into an assert after PR 40058 is
750 fixed. */
751 && lacc->size == racc->size
752 && useless_type_conversion_p (lacc->type, racc->type))
753 {
754 struct assign_link *link;
755
756 link = (struct assign_link *) pool_alloc (link_pool);
757 memset (link, 0, sizeof (struct assign_link));
758
759 link->lacc = lacc;
760 link->racc = racc;
761
762 add_link_to_rhs (racc, link);
763 }
764
765 return (lacc || racc) ? SRA_SA_PROCESSED : SRA_SA_NONE;
766 }
767
768 /* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine
769 GIMPLE_ASM operands with memory constrains which cannot be scalarized. */
770
771 static bool
772 asm_visit_addr (gimple stmt ATTRIBUTE_UNUSED, tree op,
773 void *data ATTRIBUTE_UNUSED)
774 {
775 if (DECL_P (op))
776 disqualify_candidate (op, "Non-scalarizable GIMPLE_ASM operand.");
777
778 return false;
779 }
780
781
782 /* Scan function and look for interesting statements. Return true if any has
783 been found or processed, as indicated by callbacks. SCAN_EXPR is a callback
784 called on all expressions within statements except assign statements and
785 those deemed entirely unsuitable for some reason (all operands in such
786 statements and expression are removed from candidate_bitmap). SCAN_ASSIGN
787 is a callback called on all assign statements, HANDLE_SSA_DEFS is a callback
788 called on assign statements and those call statements which have a lhs and
789 it is the only callback which can be NULL. ANALYSIS_STAGE is true when
790 running in the analysis stage of a pass and thus no statement is being
791 modified. DATA is a pointer passed to all callbacks. If any single
792 callback returns true, this function also returns true, otherwise it returns
793 false. */
794
795 static bool
796 scan_function (bool (*scan_expr) (tree *, gimple_stmt_iterator *, bool, void *),
797 enum scan_assign_result (*scan_assign) (gimple *,
798 gimple_stmt_iterator *,
799 void *),
800 bool (*handle_ssa_defs)(gimple, void *),
801 bool analysis_stage, void *data)
802 {
803 gimple_stmt_iterator gsi;
804 basic_block bb;
805 unsigned i;
806 tree *t;
807 bool ret = false;
808
809 FOR_EACH_BB (bb)
810 {
811 bool bb_changed = false;
812
813 gsi = gsi_start_bb (bb);
814 while (!gsi_end_p (gsi))
815 {
816 gimple stmt = gsi_stmt (gsi);
817 enum scan_assign_result assign_result;
818 bool any = false, deleted = false;
819
820 switch (gimple_code (stmt))
821 {
822 case GIMPLE_RETURN:
823 t = gimple_return_retval_ptr (stmt);
824 if (*t != NULL_TREE)
825 any |= scan_expr (t, &gsi, false, data);
826 break;
827
828 case GIMPLE_ASSIGN:
829 assign_result = scan_assign (&stmt, &gsi, data);
830 any |= assign_result == SRA_SA_PROCESSED;
831 deleted = assign_result == SRA_SA_REMOVED;
832 if (handle_ssa_defs && assign_result != SRA_SA_REMOVED)
833 any |= handle_ssa_defs (stmt, data);
834 break;
835
836 case GIMPLE_CALL:
837 /* Operands must be processed before the lhs. */
838 for (i = 0; i < gimple_call_num_args (stmt); i++)
839 {
840 tree *argp = gimple_call_arg_ptr (stmt, i);
841 any |= scan_expr (argp, &gsi, false, data);
842 }
843
844 if (gimple_call_lhs (stmt))
845 {
846 tree *lhs_ptr = gimple_call_lhs_ptr (stmt);
847 if (!analysis_stage
848 || !disqualify_ops_if_throwing_stmt (stmt,
849 *lhs_ptr, NULL))
850 {
851 any |= scan_expr (lhs_ptr, &gsi, true, data);
852 if (handle_ssa_defs)
853 any |= handle_ssa_defs (stmt, data);
854 }
855 }
856 break;
857
858 case GIMPLE_ASM:
859
860 if (analysis_stage)
861 walk_stmt_load_store_addr_ops (stmt, NULL, NULL, NULL,
862 asm_visit_addr);
863 for (i = 0; i < gimple_asm_ninputs (stmt); i++)
864 {
865 tree *op = &TREE_VALUE (gimple_asm_input_op (stmt, i));
866 any |= scan_expr (op, &gsi, false, data);
867 }
868 for (i = 0; i < gimple_asm_noutputs (stmt); i++)
869 {
870 tree *op = &TREE_VALUE (gimple_asm_output_op (stmt, i));
871 any |= scan_expr (op, &gsi, true, data);
872 }
873
874 default:
875 break;
876 }
877
878 if (any)
879 {
880 ret = true;
881 bb_changed = true;
882
883 if (!analysis_stage)
884 {
885 update_stmt (stmt);
886 if (!stmt_could_throw_p (stmt))
887 remove_stmt_from_eh_region (stmt);
888 }
889 }
890 if (deleted)
891 bb_changed = true;
892 else
893 {
894 gsi_next (&gsi);
895 ret = true;
896 }
897 }
898 if (!analysis_stage && bb_changed)
899 gimple_purge_dead_eh_edges (bb);
900 }
901
902 return ret;
903 }
904
905 /* Helper of QSORT function. There are pointers to accesses in the array. An
906 access is considered smaller than another if it has smaller offset or if the
907 offsets are the same but is size is bigger. */
908
909 static int
910 compare_access_positions (const void *a, const void *b)
911 {
912 const access_p *fp1 = (const access_p *) a;
913 const access_p *fp2 = (const access_p *) b;
914 const access_p f1 = *fp1;
915 const access_p f2 = *fp2;
916
917 if (f1->offset != f2->offset)
918 return f1->offset < f2->offset ? -1 : 1;
919
920 if (f1->size == f2->size)
921 {
922 /* Put any non-aggregate type before any aggregate type. */
923 if (!is_gimple_reg_type (f1->type)
924 && is_gimple_reg_type (f2->type))
925 return 1;
926 else if (is_gimple_reg_type (f1->type)
927 && !is_gimple_reg_type (f2->type))
928 return -1;
929 /* Put the integral type with the bigger precision first. */
930 else if (INTEGRAL_TYPE_P (f1->type)
931 && INTEGRAL_TYPE_P (f2->type))
932 return TYPE_PRECISION (f1->type) > TYPE_PRECISION (f2->type) ? -1 : 1;
933 /* Put any integral type with non-full precision last. */
934 else if (INTEGRAL_TYPE_P (f1->type)
935 && (TREE_INT_CST_LOW (TYPE_SIZE (f1->type))
936 != TYPE_PRECISION (f1->type)))
937 return 1;
938 else if (INTEGRAL_TYPE_P (f2->type)
939 && (TREE_INT_CST_LOW (TYPE_SIZE (f2->type))
940 != TYPE_PRECISION (f2->type)))
941 return -1;
942 /* Stabilize the sort. */
943 return TYPE_UID (f1->type) - TYPE_UID (f2->type);
944 }
945
946 /* We want the bigger accesses first, thus the opposite operator in the next
947 line: */
948 return f1->size > f2->size ? -1 : 1;
949 }
950
951
952 /* Append a name of the declaration to the name obstack. A helper function for
953 make_fancy_name. */
954
955 static void
956 make_fancy_decl_name (tree decl)
957 {
958 char buffer[32];
959
960 tree name = DECL_NAME (decl);
961 if (name)
962 obstack_grow (&name_obstack, IDENTIFIER_POINTER (name),
963 IDENTIFIER_LENGTH (name));
964 else
965 {
966 sprintf (buffer, "D%u", DECL_UID (decl));
967 obstack_grow (&name_obstack, buffer, strlen (buffer));
968 }
969 }
970
971 /* Helper for make_fancy_name. */
972
973 static void
974 make_fancy_name_1 (tree expr)
975 {
976 char buffer[32];
977 tree index;
978
979 if (DECL_P (expr))
980 {
981 make_fancy_decl_name (expr);
982 return;
983 }
984
985 switch (TREE_CODE (expr))
986 {
987 case COMPONENT_REF:
988 make_fancy_name_1 (TREE_OPERAND (expr, 0));
989 obstack_1grow (&name_obstack, '$');
990 make_fancy_decl_name (TREE_OPERAND (expr, 1));
991 break;
992
993 case ARRAY_REF:
994 make_fancy_name_1 (TREE_OPERAND (expr, 0));
995 obstack_1grow (&name_obstack, '$');
996 /* Arrays with only one element may not have a constant as their
997 index. */
998 index = TREE_OPERAND (expr, 1);
999 if (TREE_CODE (index) != INTEGER_CST)
1000 break;
1001 sprintf (buffer, HOST_WIDE_INT_PRINT_DEC, TREE_INT_CST_LOW (index));
1002 obstack_grow (&name_obstack, buffer, strlen (buffer));
1003
1004 break;
1005
1006 case BIT_FIELD_REF:
1007 case REALPART_EXPR:
1008 case IMAGPART_EXPR:
1009 gcc_unreachable (); /* we treat these as scalars. */
1010 break;
1011 default:
1012 break;
1013 }
1014 }
1015
1016 /* Create a human readable name for replacement variable of ACCESS. */
1017
1018 static char *
1019 make_fancy_name (tree expr)
1020 {
1021 make_fancy_name_1 (expr);
1022 obstack_1grow (&name_obstack, '\0');
1023 return XOBFINISH (&name_obstack, char *);
1024 }
1025
1026 /* Helper function for build_ref_for_offset. */
1027
1028 static bool
1029 build_ref_for_offset_1 (tree *res, tree type, HOST_WIDE_INT offset,
1030 tree exp_type)
1031 {
1032 while (1)
1033 {
1034 tree fld;
1035 tree tr_size, index;
1036 HOST_WIDE_INT el_size;
1037
1038 if (offset == 0 && exp_type
1039 && types_compatible_p (exp_type, type))
1040 return true;
1041
1042 switch (TREE_CODE (type))
1043 {
1044 case UNION_TYPE:
1045 case QUAL_UNION_TYPE:
1046 case RECORD_TYPE:
1047 /* Some ADA records are half-unions, treat all of them the same. */
1048 for (fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
1049 {
1050 HOST_WIDE_INT pos, size;
1051 tree expr, *expr_ptr;
1052
1053 if (TREE_CODE (fld) != FIELD_DECL)
1054 continue;
1055
1056 pos = int_bit_position (fld);
1057 gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0);
1058 size = tree_low_cst (DECL_SIZE (fld), 1);
1059 if (pos > offset || (pos + size) <= offset)
1060 continue;
1061
1062 if (res)
1063 {
1064 expr = build3 (COMPONENT_REF, TREE_TYPE (fld), *res, fld,
1065 NULL_TREE);
1066 expr_ptr = &expr;
1067 }
1068 else
1069 expr_ptr = NULL;
1070 if (build_ref_for_offset_1 (expr_ptr, TREE_TYPE (fld),
1071 offset - pos, exp_type))
1072 {
1073 if (res)
1074 *res = expr;
1075 return true;
1076 }
1077 }
1078 return false;
1079
1080 case ARRAY_TYPE:
1081 tr_size = TYPE_SIZE (TREE_TYPE (type));
1082 if (!tr_size || !host_integerp (tr_size, 1))
1083 return false;
1084 el_size = tree_low_cst (tr_size, 1);
1085
1086 if (res)
1087 {
1088 index = build_int_cst (TYPE_DOMAIN (type), offset / el_size);
1089 if (!integer_zerop (TYPE_MIN_VALUE (TYPE_DOMAIN (type))))
1090 index = int_const_binop (PLUS_EXPR, index,
1091 TYPE_MIN_VALUE (TYPE_DOMAIN (type)),
1092 0);
1093 *res = build4 (ARRAY_REF, TREE_TYPE (type), *res, index,
1094 NULL_TREE, NULL_TREE);
1095 }
1096 offset = offset % el_size;
1097 type = TREE_TYPE (type);
1098 break;
1099
1100 default:
1101 if (offset != 0)
1102 return false;
1103
1104 if (exp_type)
1105 return false;
1106 else
1107 return true;
1108 }
1109 }
1110 }
1111
1112 /* Construct an expression that would reference a part of aggregate *EXPR of
1113 type TYPE at the given OFFSET of the type EXP_TYPE. If EXPR is NULL, the
1114 function only determines whether it can build such a reference without
1115 actually doing it.
1116
1117 FIXME: Eventually this should be replaced with
1118 maybe_fold_offset_to_reference() from tree-ssa-ccp.c but that requires a
1119 minor rewrite of fold_stmt.
1120 */
1121
1122 static bool
1123 build_ref_for_offset (tree *expr, tree type, HOST_WIDE_INT offset,
1124 tree exp_type, bool allow_ptr)
1125 {
1126 if (allow_ptr && POINTER_TYPE_P (type))
1127 {
1128 type = TREE_TYPE (type);
1129 if (expr)
1130 *expr = fold_build1 (INDIRECT_REF, type, *expr);
1131 }
1132
1133 return build_ref_for_offset_1 (expr, type, offset, exp_type);
1134 }
1135
1136 /* The very first phase of intraprocedural SRA. It marks in candidate_bitmap
1137 those with type which is suitable for scalarization. */
1138
1139 static bool
1140 find_var_candidates (void)
1141 {
1142 tree var, type;
1143 referenced_var_iterator rvi;
1144 bool ret = false;
1145
1146 FOR_EACH_REFERENCED_VAR (var, rvi)
1147 {
1148 if (TREE_CODE (var) != VAR_DECL && TREE_CODE (var) != PARM_DECL)
1149 continue;
1150 type = TREE_TYPE (var);
1151
1152 if (!AGGREGATE_TYPE_P (type)
1153 || needs_to_live_in_memory (var)
1154 || TREE_THIS_VOLATILE (var)
1155 || !COMPLETE_TYPE_P (type)
1156 || !host_integerp (TYPE_SIZE (type), 1)
1157 || tree_low_cst (TYPE_SIZE (type), 1) == 0
1158 || type_internals_preclude_sra_p (type))
1159 continue;
1160
1161 bitmap_set_bit (candidate_bitmap, DECL_UID (var));
1162
1163 if (dump_file && (dump_flags & TDF_DETAILS))
1164 {
1165 fprintf (dump_file, "Candidate (%d): ", DECL_UID (var));
1166 print_generic_expr (dump_file, var, 0);
1167 fprintf (dump_file, "\n");
1168 }
1169 ret = true;
1170 }
1171
1172 return ret;
1173 }
1174
1175 /* Sort all accesses for the given variable, check for partial overlaps and
1176 return NULL if there are any. If there are none, pick a representative for
1177 each combination of offset and size and create a linked list out of them.
1178 Return the pointer to the first representative and make sure it is the first
1179 one in the vector of accesses. */
1180
1181 static struct access *
1182 sort_and_splice_var_accesses (tree var)
1183 {
1184 int i, j, access_count;
1185 struct access *res, **prev_acc_ptr = &res;
1186 VEC (access_p, heap) *access_vec;
1187 bool first = true;
1188 HOST_WIDE_INT low = -1, high = 0;
1189
1190 access_vec = get_base_access_vector (var);
1191 if (!access_vec)
1192 return NULL;
1193 access_count = VEC_length (access_p, access_vec);
1194
1195 /* Sort by <OFFSET, SIZE>. */
1196 qsort (VEC_address (access_p, access_vec), access_count, sizeof (access_p),
1197 compare_access_positions);
1198
1199 i = 0;
1200 while (i < access_count)
1201 {
1202 struct access *access = VEC_index (access_p, access_vec, i);
1203 bool modification = access->write;
1204 bool grp_read = !access->write;
1205 bool grp_partial_lhs = access->grp_partial_lhs;
1206 bool first_scalar = is_gimple_reg_type (access->type);
1207 bool unscalarizable_region = access->grp_unscalarizable_region;
1208
1209 if (first || access->offset >= high)
1210 {
1211 first = false;
1212 low = access->offset;
1213 high = access->offset + access->size;
1214 }
1215 else if (access->offset > low && access->offset + access->size > high)
1216 return NULL;
1217 else
1218 gcc_assert (access->offset >= low
1219 && access->offset + access->size <= high);
1220
1221 j = i + 1;
1222 while (j < access_count)
1223 {
1224 struct access *ac2 = VEC_index (access_p, access_vec, j);
1225 if (ac2->offset != access->offset || ac2->size != access->size)
1226 break;
1227 modification |= ac2->write;
1228 grp_read |= !ac2->write;
1229 grp_partial_lhs |= ac2->grp_partial_lhs;
1230 unscalarizable_region |= ac2->grp_unscalarizable_region;
1231 relink_to_new_repr (access, ac2);
1232
1233 /* If there are both aggregate-type and scalar-type accesses with
1234 this combination of size and offset, the comparison function
1235 should have put the scalars first. */
1236 gcc_assert (first_scalar || !is_gimple_reg_type (ac2->type));
1237 ac2->group_representative = access;
1238 j++;
1239 }
1240
1241 i = j;
1242
1243 access->group_representative = access;
1244 access->grp_write = modification;
1245 access->grp_read = grp_read;
1246 access->grp_partial_lhs = grp_partial_lhs;
1247 access->grp_unscalarizable_region = unscalarizable_region;
1248 if (access->first_link)
1249 add_access_to_work_queue (access);
1250
1251 *prev_acc_ptr = access;
1252 prev_acc_ptr = &access->next_grp;
1253 }
1254
1255 gcc_assert (res == VEC_index (access_p, access_vec, 0));
1256 return res;
1257 }
1258
1259 /* Create a variable for the given ACCESS which determines the type, name and a
1260 few other properties. Return the variable declaration and store it also to
1261 ACCESS->replacement. */
1262
1263 static tree
1264 create_access_replacement (struct access *access)
1265 {
1266 tree repl;
1267
1268 repl = create_tmp_var (access->type, "SR");
1269 get_var_ann (repl);
1270 add_referenced_var (repl);
1271 mark_sym_for_renaming (repl);
1272
1273 if (!access->grp_partial_lhs
1274 && (TREE_CODE (access->type) == COMPLEX_TYPE
1275 || TREE_CODE (access->type) == VECTOR_TYPE))
1276 DECL_GIMPLE_REG_P (repl) = 1;
1277
1278 DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base);
1279 DECL_ARTIFICIAL (repl) = 1;
1280
1281 if (DECL_NAME (access->base)
1282 && !DECL_IGNORED_P (access->base)
1283 && !DECL_ARTIFICIAL (access->base))
1284 {
1285 char *pretty_name = make_fancy_name (access->expr);
1286
1287 DECL_NAME (repl) = get_identifier (pretty_name);
1288 obstack_free (&name_obstack, pretty_name);
1289
1290 SET_DECL_DEBUG_EXPR (repl, access->expr);
1291 DECL_DEBUG_EXPR_IS_FROM (repl) = 1;
1292 DECL_IGNORED_P (repl) = 0;
1293 }
1294
1295 DECL_IGNORED_P (repl) = DECL_IGNORED_P (access->base);
1296 TREE_NO_WARNING (repl) = TREE_NO_WARNING (access->base);
1297
1298 if (dump_file)
1299 {
1300 fprintf (dump_file, "Created a replacement for ");
1301 print_generic_expr (dump_file, access->base, 0);
1302 fprintf (dump_file, " offset: %u, size: %u: ",
1303 (unsigned) access->offset, (unsigned) access->size);
1304 print_generic_expr (dump_file, repl, 0);
1305 fprintf (dump_file, "\n");
1306 }
1307 sra_stats.replacements++;
1308
1309 return repl;
1310 }
1311
1312 /* Return ACCESS scalar replacement, create it if it does not exist yet. */
1313
1314 static inline tree
1315 get_access_replacement (struct access *access)
1316 {
1317 gcc_assert (access->grp_to_be_replaced);
1318
1319 if (!access->replacement_decl)
1320 access->replacement_decl = create_access_replacement (access);
1321 return access->replacement_decl;
1322 }
1323
1324 /* Build a subtree of accesses rooted in *ACCESS, and move the pointer in the
1325 linked list along the way. Stop when *ACCESS is NULL or the access pointed
1326 to it is not "within" the root. */
1327
1328 static void
1329 build_access_subtree (struct access **access)
1330 {
1331 struct access *root = *access, *last_child = NULL;
1332 HOST_WIDE_INT limit = root->offset + root->size;
1333
1334 *access = (*access)->next_grp;
1335 while (*access && (*access)->offset + (*access)->size <= limit)
1336 {
1337 if (!last_child)
1338 root->first_child = *access;
1339 else
1340 last_child->next_sibling = *access;
1341 last_child = *access;
1342
1343 build_access_subtree (access);
1344 }
1345 }
1346
1347 /* Build a tree of access representatives, ACCESS is the pointer to the first
1348 one, others are linked in a list by the next_grp field. Decide about scalar
1349 replacements on the way, return true iff any are to be created. */
1350
1351 static void
1352 build_access_trees (struct access *access)
1353 {
1354 while (access)
1355 {
1356 struct access *root = access;
1357
1358 build_access_subtree (&access);
1359 root->next_grp = access;
1360 }
1361 }
1362
1363 /* Analyze the subtree of accesses rooted in ROOT, scheduling replacements when
1364 both seeming beneficial and when ALLOW_REPLACEMENTS allows it. Also set
1365 all sorts of access flags appropriately along the way, notably always ser
1366 grp_read when MARK_READ is true and grp_write when MARK_WRITE is true. */
1367
1368 static bool
1369 analyze_access_subtree (struct access *root, bool allow_replacements,
1370 bool mark_read, bool mark_write)
1371 {
1372 struct access *child;
1373 HOST_WIDE_INT limit = root->offset + root->size;
1374 HOST_WIDE_INT covered_to = root->offset;
1375 bool scalar = is_gimple_reg_type (root->type);
1376 bool hole = false, sth_created = false;
1377
1378 if (mark_read)
1379 root->grp_read = true;
1380 else if (root->grp_read)
1381 mark_read = true;
1382
1383 if (mark_write)
1384 root->grp_write = true;
1385 else if (root->grp_write)
1386 mark_write = true;
1387
1388 if (root->grp_unscalarizable_region)
1389 allow_replacements = false;
1390
1391 for (child = root->first_child; child; child = child->next_sibling)
1392 {
1393 if (!hole && child->offset < covered_to)
1394 hole = true;
1395 else
1396 covered_to += child->size;
1397
1398 sth_created |= analyze_access_subtree (child, allow_replacements,
1399 mark_read, mark_write);
1400
1401 root->grp_unscalarized_data |= child->grp_unscalarized_data;
1402 hole |= !child->grp_covered;
1403 }
1404
1405 if (allow_replacements && scalar && !root->first_child)
1406 {
1407 if (dump_file && (dump_flags & TDF_DETAILS))
1408 {
1409 fprintf (dump_file, "Marking ");
1410 print_generic_expr (dump_file, root->base, 0);
1411 fprintf (dump_file, " offset: %u, size: %u: ",
1412 (unsigned) root->offset, (unsigned) root->size);
1413 fprintf (dump_file, " to be replaced.\n");
1414 }
1415
1416 root->grp_to_be_replaced = 1;
1417 sth_created = true;
1418 hole = false;
1419 }
1420 else if (covered_to < limit)
1421 hole = true;
1422
1423 if (sth_created && !hole)
1424 {
1425 root->grp_covered = 1;
1426 return true;
1427 }
1428 if (root->grp_write || TREE_CODE (root->base) == PARM_DECL)
1429 root->grp_unscalarized_data = 1; /* not covered and written to */
1430 if (sth_created)
1431 return true;
1432 return false;
1433 }
1434
1435 /* Analyze all access trees linked by next_grp by the means of
1436 analyze_access_subtree. */
1437 static bool
1438 analyze_access_trees (struct access *access)
1439 {
1440 bool ret = false;
1441
1442 while (access)
1443 {
1444 if (analyze_access_subtree (access, true, false, false))
1445 ret = true;
1446 access = access->next_grp;
1447 }
1448
1449 return ret;
1450 }
1451
1452 /* Return true iff a potential new child of LACC at offset OFFSET and with size
1453 SIZE would conflict with an already existing one. If exactly such a child
1454 already exists in LACC, store a pointer to it in EXACT_MATCH. */
1455
1456 static bool
1457 child_would_conflict_in_lacc (struct access *lacc, HOST_WIDE_INT norm_offset,
1458 HOST_WIDE_INT size, struct access **exact_match)
1459 {
1460 struct access *child;
1461
1462 for (child = lacc->first_child; child; child = child->next_sibling)
1463 {
1464 if (child->offset == norm_offset && child->size == size)
1465 {
1466 *exact_match = child;
1467 return true;
1468 }
1469
1470 if (child->offset < norm_offset + size
1471 && child->offset + child->size > norm_offset)
1472 return true;
1473 }
1474
1475 return false;
1476 }
1477
1478 /* Set the expr of TARGET to one just like MODEL but with is own base at the
1479 bottom of the handled components. */
1480
1481 static void
1482 duplicate_expr_for_different_base (struct access *target,
1483 struct access *model)
1484 {
1485 tree t, expr = unshare_expr (model->expr);
1486
1487 gcc_assert (handled_component_p (expr));
1488 t = expr;
1489 while (handled_component_p (TREE_OPERAND (t, 0)))
1490 t = TREE_OPERAND (t, 0);
1491 gcc_assert (TREE_OPERAND (t, 0) == model->base);
1492 TREE_OPERAND (t, 0) = target->base;
1493
1494 target->expr = expr;
1495 }
1496
1497
1498 /* Create a new child access of PARENT, with all properties just like MODEL
1499 except for its offset and with its grp_write false and grp_read true.
1500 Return the new access. Note that this access is created long after all
1501 splicing and sorting, it's not located in any access vector and is
1502 automatically a representative of its group. */
1503
1504 static struct access *
1505 create_artificial_child_access (struct access *parent, struct access *model,
1506 HOST_WIDE_INT new_offset)
1507 {
1508 struct access *access;
1509 struct access **child;
1510
1511 gcc_assert (!model->grp_unscalarizable_region);
1512
1513 access = (struct access *) pool_alloc (access_pool);
1514 memset (access, 0, sizeof (struct access));
1515 access->base = parent->base;
1516 access->offset = new_offset;
1517 access->size = model->size;
1518 duplicate_expr_for_different_base (access, model);
1519 access->type = model->type;
1520 access->grp_write = true;
1521 access->grp_read = false;
1522
1523 child = &parent->first_child;
1524 while (*child && (*child)->offset < new_offset)
1525 child = &(*child)->next_sibling;
1526
1527 access->next_sibling = *child;
1528 *child = access;
1529
1530 return access;
1531 }
1532
1533
1534 /* Propagate all subaccesses of RACC across an assignment link to LACC. Return
1535 true if any new subaccess was created. Additionally, if RACC is a scalar
1536 access but LACC is not, change the type of the latter. */
1537
1538 static bool
1539 propagate_subacesses_accross_link (struct access *lacc, struct access *racc)
1540 {
1541 struct access *rchild;
1542 HOST_WIDE_INT norm_delta = lacc->offset - racc->offset;
1543
1544 bool ret = false;
1545
1546 if (is_gimple_reg_type (lacc->type)
1547 || lacc->grp_unscalarizable_region
1548 || racc->grp_unscalarizable_region)
1549 return false;
1550
1551 if (!lacc->first_child && !racc->first_child
1552 && is_gimple_reg_type (racc->type))
1553 {
1554 duplicate_expr_for_different_base (lacc, racc);
1555 lacc->type = racc->type;
1556 return false;
1557 }
1558
1559 for (rchild = racc->first_child; rchild; rchild = rchild->next_sibling)
1560 {
1561 struct access *new_acc = NULL;
1562 HOST_WIDE_INT norm_offset = rchild->offset + norm_delta;
1563
1564 if (rchild->grp_unscalarizable_region)
1565 continue;
1566
1567 if (child_would_conflict_in_lacc (lacc, norm_offset, rchild->size,
1568 &new_acc))
1569 {
1570 if (new_acc && rchild->first_child)
1571 ret |= propagate_subacesses_accross_link (new_acc, rchild);
1572 continue;
1573 }
1574
1575 /* If a (part of) a union field is on the RHS of an assignment, it can
1576 have sub-accesses which do not make sense on the LHS (PR 40351).
1577 Check that this is not the case. */
1578 if (!build_ref_for_offset (NULL, TREE_TYPE (lacc->base), norm_offset,
1579 rchild->type, false))
1580 continue;
1581
1582 new_acc = create_artificial_child_access (lacc, rchild, norm_offset);
1583 if (racc->first_child)
1584 propagate_subacesses_accross_link (new_acc, rchild);
1585
1586 ret = true;
1587 }
1588
1589 return ret;
1590 }
1591
1592 /* Propagate all subaccesses across assignment links. */
1593
1594 static void
1595 propagate_all_subaccesses (void)
1596 {
1597 while (work_queue_head)
1598 {
1599 struct access *racc = pop_access_from_work_queue ();
1600 struct assign_link *link;
1601
1602 gcc_assert (racc->first_link);
1603
1604 for (link = racc->first_link; link; link = link->next)
1605 {
1606 struct access *lacc = link->lacc;
1607
1608 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
1609 continue;
1610 lacc = lacc->group_representative;
1611 if (propagate_subacesses_accross_link (lacc, racc)
1612 && lacc->first_link)
1613 add_access_to_work_queue (lacc);
1614 }
1615 }
1616 }
1617
1618 /* Go through all accesses collected throughout the (intraprocedural) analysis
1619 stage, exclude overlapping ones, identify representatives and build trees
1620 out of them, making decisions about scalarization on the way. Return true
1621 iff there are any to-be-scalarized variables after this stage. */
1622
1623 static bool
1624 analyze_all_variable_accesses (void)
1625 {
1626 tree var;
1627 referenced_var_iterator rvi;
1628 int res = 0;
1629
1630 FOR_EACH_REFERENCED_VAR (var, rvi)
1631 if (bitmap_bit_p (candidate_bitmap, DECL_UID (var)))
1632 {
1633 struct access *access;
1634
1635 access = sort_and_splice_var_accesses (var);
1636 if (access)
1637 build_access_trees (access);
1638 else
1639 disqualify_candidate (var,
1640 "No or inhibitingly overlapping accesses.");
1641 }
1642
1643 propagate_all_subaccesses ();
1644
1645 FOR_EACH_REFERENCED_VAR (var, rvi)
1646 if (bitmap_bit_p (candidate_bitmap, DECL_UID (var)))
1647 {
1648 struct access *access = get_first_repr_for_decl (var);
1649
1650 if (analyze_access_trees (access))
1651 {
1652 res++;
1653 if (dump_file && (dump_flags & TDF_DETAILS))
1654 {
1655 fprintf (dump_file, "\nAccess trees for ");
1656 print_generic_expr (dump_file, var, 0);
1657 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
1658 dump_access_tree (dump_file, access);
1659 fprintf (dump_file, "\n");
1660 }
1661 }
1662 else
1663 disqualify_candidate (var, "No scalar replacements to be created.");
1664 }
1665
1666 if (res)
1667 {
1668 statistics_counter_event (cfun, "Scalarized aggregates", res);
1669 return true;
1670 }
1671 else
1672 return false;
1673 }
1674
1675 /* Return true iff a reference statement into aggregate AGG can be built for
1676 every single to-be-replaced accesses that is a child of ACCESS, its sibling
1677 or a child of its sibling. TOP_OFFSET is the offset from the processed
1678 access subtree that has to be subtracted from offset of each access. */
1679
1680 static bool
1681 ref_expr_for_all_replacements_p (struct access *access, tree agg,
1682 HOST_WIDE_INT top_offset)
1683 {
1684 do
1685 {
1686 if (access->grp_to_be_replaced
1687 && !build_ref_for_offset (NULL, TREE_TYPE (agg),
1688 access->offset - top_offset,
1689 access->type, false))
1690 return false;
1691
1692 if (access->first_child
1693 && !ref_expr_for_all_replacements_p (access->first_child, agg,
1694 top_offset))
1695 return false;
1696
1697 access = access->next_sibling;
1698 }
1699 while (access);
1700
1701 return true;
1702 }
1703
1704 /* Generate statements copying scalar replacements of accesses within a subtree
1705 into or out of AGG. ACCESS is the first child of the root of the subtree to
1706 be processed. AGG is an aggregate type expression (can be a declaration but
1707 does not have to be, it can for example also be an indirect_ref).
1708 TOP_OFFSET is the offset of the processed subtree which has to be subtracted
1709 from offsets of individual accesses to get corresponding offsets for AGG.
1710 If CHUNK_SIZE is non-null, copy only replacements in the interval
1711 <start_offset, start_offset + chunk_size>, otherwise copy all. GSI is a
1712 statement iterator used to place the new statements. WRITE should be true
1713 when the statements should write from AGG to the replacement and false if
1714 vice versa. if INSERT_AFTER is true, new statements will be added after the
1715 current statement in GSI, they will be added before the statement
1716 otherwise. */
1717
1718 static void
1719 generate_subtree_copies (struct access *access, tree agg,
1720 HOST_WIDE_INT top_offset,
1721 HOST_WIDE_INT start_offset, HOST_WIDE_INT chunk_size,
1722 gimple_stmt_iterator *gsi, bool write,
1723 bool insert_after)
1724 {
1725 do
1726 {
1727 tree expr = unshare_expr (agg);
1728
1729 if (chunk_size && access->offset >= start_offset + chunk_size)
1730 return;
1731
1732 if (access->grp_to_be_replaced
1733 && (chunk_size == 0
1734 || access->offset + access->size > start_offset))
1735 {
1736 tree repl = get_access_replacement (access);
1737 bool ref_found;
1738 gimple stmt;
1739
1740 ref_found = build_ref_for_offset (&expr, TREE_TYPE (agg),
1741 access->offset - top_offset,
1742 access->type, false);
1743 gcc_assert (ref_found);
1744
1745 if (write)
1746 {
1747 if (access->grp_partial_lhs)
1748 expr = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
1749 !insert_after,
1750 insert_after ? GSI_NEW_STMT
1751 : GSI_SAME_STMT);
1752 stmt = gimple_build_assign (repl, expr);
1753 }
1754 else
1755 {
1756 TREE_NO_WARNING (repl) = 1;
1757 if (access->grp_partial_lhs)
1758 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
1759 !insert_after,
1760 insert_after ? GSI_NEW_STMT
1761 : GSI_SAME_STMT);
1762 stmt = gimple_build_assign (expr, repl);
1763 }
1764
1765 if (insert_after)
1766 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
1767 else
1768 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
1769 update_stmt (stmt);
1770 sra_stats.subtree_copies++;
1771 }
1772
1773 if (access->first_child)
1774 generate_subtree_copies (access->first_child, agg, top_offset,
1775 start_offset, chunk_size, gsi,
1776 write, insert_after);
1777
1778 access = access->next_sibling;
1779 }
1780 while (access);
1781 }
1782
1783 /* Assign zero to all scalar replacements in an access subtree. ACCESS is the
1784 the root of the subtree to be processed. GSI is the statement iterator used
1785 for inserting statements which are added after the current statement if
1786 INSERT_AFTER is true or before it otherwise. */
1787
1788 static void
1789 init_subtree_with_zero (struct access *access, gimple_stmt_iterator *gsi,
1790 bool insert_after)
1791
1792 {
1793 struct access *child;
1794
1795 if (access->grp_to_be_replaced)
1796 {
1797 gimple stmt;
1798
1799 stmt = gimple_build_assign (get_access_replacement (access),
1800 fold_convert (access->type,
1801 integer_zero_node));
1802 if (insert_after)
1803 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
1804 else
1805 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
1806 update_stmt (stmt);
1807 }
1808
1809 for (child = access->first_child; child; child = child->next_sibling)
1810 init_subtree_with_zero (child, gsi, insert_after);
1811 }
1812
1813 /* Search for an access representative for the given expression EXPR and
1814 return it or NULL if it cannot be found. */
1815
1816 static struct access *
1817 get_access_for_expr (tree expr)
1818 {
1819 HOST_WIDE_INT offset, size, max_size;
1820 tree base;
1821
1822 /* FIXME: This should not be necessary but Ada produces V_C_Es with a type of
1823 a different size than the size of its argument and we need the latter
1824 one. */
1825 if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
1826 expr = TREE_OPERAND (expr, 0);
1827
1828 base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
1829 if (max_size == -1 || !DECL_P (base))
1830 return NULL;
1831
1832 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
1833 return NULL;
1834
1835 return get_var_base_offset_size_access (base, offset, max_size);
1836 }
1837
1838 /* Callback for scan_function. Replace the expression EXPR with a scalar
1839 replacement if there is one and generate other statements to do type
1840 conversion or subtree copying if necessary. GSI is used to place newly
1841 created statements, WRITE is true if the expression is being written to (it
1842 is on a LHS of a statement or output in an assembly statement). */
1843
1844 static bool
1845 sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write,
1846 void *data ATTRIBUTE_UNUSED)
1847 {
1848 struct access *access;
1849 tree type, bfr;
1850
1851 if (TREE_CODE (*expr) == BIT_FIELD_REF)
1852 {
1853 bfr = *expr;
1854 expr = &TREE_OPERAND (*expr, 0);
1855 }
1856 else
1857 bfr = NULL_TREE;
1858
1859 if (TREE_CODE (*expr) == REALPART_EXPR || TREE_CODE (*expr) == IMAGPART_EXPR)
1860 expr = &TREE_OPERAND (*expr, 0);
1861 access = get_access_for_expr (*expr);
1862 if (!access)
1863 return false;
1864 type = TREE_TYPE (*expr);
1865
1866 if (access->grp_to_be_replaced)
1867 {
1868 tree repl = get_access_replacement (access);
1869 /* If we replace a non-register typed access simply use the original
1870 access expression to extract the scalar component afterwards.
1871 This happens if scalarizing a function return value or parameter
1872 like in gcc.c-torture/execute/20041124-1.c, 20050316-1.c and
1873 gcc.c-torture/compile/20011217-1.c. */
1874 if (!is_gimple_reg_type (type))
1875 {
1876 gimple stmt;
1877 if (write)
1878 {
1879 tree ref = unshare_expr (access->expr);
1880 if (access->grp_partial_lhs)
1881 ref = force_gimple_operand_gsi (gsi, ref, true, NULL_TREE,
1882 false, GSI_NEW_STMT);
1883 stmt = gimple_build_assign (repl, ref);
1884 gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
1885 }
1886 else
1887 {
1888 if (access->grp_partial_lhs)
1889 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
1890 true, GSI_SAME_STMT);
1891 stmt = gimple_build_assign (unshare_expr (access->expr), repl);
1892 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
1893 }
1894 }
1895 else
1896 {
1897 gcc_assert (useless_type_conversion_p (type, access->type));
1898 *expr = repl;
1899 }
1900 sra_stats.exprs++;
1901 }
1902
1903 if (access->first_child)
1904 {
1905 HOST_WIDE_INT start_offset, chunk_size;
1906 if (bfr
1907 && host_integerp (TREE_OPERAND (bfr, 1), 1)
1908 && host_integerp (TREE_OPERAND (bfr, 2), 1))
1909 {
1910 chunk_size = tree_low_cst (TREE_OPERAND (bfr, 1), 1);
1911 start_offset = access->offset
1912 + tree_low_cst (TREE_OPERAND (bfr, 2), 1);
1913 }
1914 else
1915 start_offset = chunk_size = 0;
1916
1917 generate_subtree_copies (access->first_child, access->base, 0,
1918 start_offset, chunk_size, gsi, write, write);
1919 }
1920 return true;
1921 }
1922
1923 /* Where scalar replacements of the RHS have been written to when a replacement
1924 of a LHS of an assigments cannot be direclty loaded from a replacement of
1925 the RHS. */
1926 enum unscalarized_data_handling { SRA_UDH_NONE, /* Nothing done so far. */
1927 SRA_UDH_RIGHT, /* Data flushed to the RHS. */
1928 SRA_UDH_LEFT }; /* Data flushed to the LHS. */
1929
1930 /* Store all replacements in the access tree rooted in TOP_RACC either to their
1931 base aggregate if there are unscalarized data or directly to LHS
1932 otherwise. */
1933
1934 static enum unscalarized_data_handling
1935 handle_unscalarized_data_in_subtree (struct access *top_racc, tree lhs,
1936 gimple_stmt_iterator *gsi)
1937 {
1938 if (top_racc->grp_unscalarized_data)
1939 {
1940 generate_subtree_copies (top_racc->first_child, top_racc->base, 0, 0, 0,
1941 gsi, false, false);
1942 return SRA_UDH_RIGHT;
1943 }
1944 else
1945 {
1946 generate_subtree_copies (top_racc->first_child, lhs, top_racc->offset,
1947 0, 0, gsi, false, false);
1948 return SRA_UDH_LEFT;
1949 }
1950 }
1951
1952
1953 /* Try to generate statements to load all sub-replacements in an access
1954 (sub)tree (LACC is the first child) from scalar replacements in the TOP_RACC
1955 (sub)tree. If that is not possible, refresh the TOP_RACC base aggregate and
1956 load the accesses from it. LEFT_OFFSET is the offset of the left whole
1957 subtree being copied, RIGHT_OFFSET is the same thing for the right subtree.
1958 GSI is stmt iterator used for statement insertions. *REFRESHED is true iff
1959 the rhs top aggregate has already been refreshed by contents of its scalar
1960 reductions and is set to true if this function has to do it. */
1961
1962 static void
1963 load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc,
1964 HOST_WIDE_INT left_offset,
1965 HOST_WIDE_INT right_offset,
1966 gimple_stmt_iterator *old_gsi,
1967 gimple_stmt_iterator *new_gsi,
1968 enum unscalarized_data_handling *refreshed,
1969 tree lhs)
1970 {
1971 do
1972 {
1973 if (lacc->grp_to_be_replaced)
1974 {
1975 struct access *racc;
1976 HOST_WIDE_INT offset = lacc->offset - left_offset + right_offset;
1977 gimple stmt;
1978 tree rhs;
1979
1980 racc = find_access_in_subtree (top_racc, offset, lacc->size);
1981 if (racc && racc->grp_to_be_replaced)
1982 {
1983 rhs = get_access_replacement (racc);
1984 if (!useless_type_conversion_p (lacc->type, racc->type))
1985 rhs = fold_build1 (VIEW_CONVERT_EXPR, lacc->type, rhs);
1986 }
1987 else
1988 {
1989 bool repl_found;
1990
1991 /* No suitable access on the right hand side, need to load from
1992 the aggregate. See if we have to update it first... */
1993 if (*refreshed == SRA_UDH_NONE)
1994 *refreshed = handle_unscalarized_data_in_subtree (top_racc,
1995 lhs, old_gsi);
1996
1997 if (*refreshed == SRA_UDH_LEFT)
1998 rhs = unshare_expr (lacc->expr);
1999 else
2000 {
2001 rhs = unshare_expr (top_racc->base);
2002 repl_found = build_ref_for_offset (&rhs,
2003 TREE_TYPE (top_racc->base),
2004 offset, lacc->type, false);
2005 gcc_assert (repl_found);
2006 }
2007 }
2008
2009 stmt = gimple_build_assign (get_access_replacement (lacc), rhs);
2010 gsi_insert_after (new_gsi, stmt, GSI_NEW_STMT);
2011 update_stmt (stmt);
2012 sra_stats.subreplacements++;
2013 }
2014 else if (*refreshed == SRA_UDH_NONE
2015 && lacc->grp_read && !lacc->grp_covered)
2016 *refreshed = handle_unscalarized_data_in_subtree (top_racc, lhs,
2017 old_gsi);
2018
2019 if (lacc->first_child)
2020 load_assign_lhs_subreplacements (lacc->first_child, top_racc,
2021 left_offset, right_offset,
2022 old_gsi, new_gsi, refreshed, lhs);
2023 lacc = lacc->next_sibling;
2024 }
2025 while (lacc);
2026 }
2027
2028 /* Modify assignments with a CONSTRUCTOR on their RHS. STMT contains a pointer
2029 to the assignment and GSI is the statement iterator pointing at it. Returns
2030 the same values as sra_modify_assign. */
2031
2032 static enum scan_assign_result
2033 sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
2034 {
2035 tree lhs = gimple_assign_lhs (*stmt);
2036 struct access *acc;
2037
2038 acc = get_access_for_expr (lhs);
2039 if (!acc)
2040 return SRA_SA_NONE;
2041
2042 if (VEC_length (constructor_elt,
2043 CONSTRUCTOR_ELTS (gimple_assign_rhs1 (*stmt))) > 0)
2044 {
2045 /* I have never seen this code path trigger but if it can happen the
2046 following should handle it gracefully. */
2047 if (access_has_children_p (acc))
2048 generate_subtree_copies (acc->first_child, acc->base, 0, 0, 0, gsi,
2049 true, true);
2050 return SRA_SA_PROCESSED;
2051 }
2052
2053 if (acc->grp_covered)
2054 {
2055 init_subtree_with_zero (acc, gsi, false);
2056 unlink_stmt_vdef (*stmt);
2057 gsi_remove (gsi, true);
2058 return SRA_SA_REMOVED;
2059 }
2060 else
2061 {
2062 init_subtree_with_zero (acc, gsi, true);
2063 return SRA_SA_PROCESSED;
2064 }
2065 }
2066
2067
2068 /* Callback of scan_function to process assign statements. It examines both
2069 sides of the statement, replaces them with a scalare replacement if there is
2070 one and generating copying of replacements if scalarized aggregates have been
2071 used in the assignment. STMT is a pointer to the assign statement, GSI is
2072 used to hold generated statements for type conversions and subtree
2073 copying. */
2074
2075 static enum scan_assign_result
2076 sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi,
2077 void *data ATTRIBUTE_UNUSED)
2078 {
2079 struct access *lacc, *racc;
2080 tree lhs, rhs;
2081 bool modify_this_stmt = false;
2082 bool force_gimple_rhs = false;
2083
2084 if (!gimple_assign_single_p (*stmt))
2085 return SRA_SA_NONE;
2086 lhs = gimple_assign_lhs (*stmt);
2087 rhs = gimple_assign_rhs1 (*stmt);
2088
2089 if (TREE_CODE (rhs) == CONSTRUCTOR)
2090 return sra_modify_constructor_assign (stmt, gsi);
2091
2092 if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (lhs) == REALPART_EXPR
2093 || TREE_CODE (rhs) == IMAGPART_EXPR || TREE_CODE (lhs) == IMAGPART_EXPR
2094 || TREE_CODE (rhs) == BIT_FIELD_REF || TREE_CODE (lhs) == BIT_FIELD_REF)
2095 {
2096 modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (*stmt),
2097 gsi, false, data);
2098 modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (*stmt),
2099 gsi, true, data);
2100 return modify_this_stmt ? SRA_SA_PROCESSED : SRA_SA_NONE;
2101 }
2102
2103 lacc = get_access_for_expr (lhs);
2104 racc = get_access_for_expr (rhs);
2105 if (!lacc && !racc)
2106 return SRA_SA_NONE;
2107
2108 if (lacc && lacc->grp_to_be_replaced)
2109 {
2110 lhs = get_access_replacement (lacc);
2111 gimple_assign_set_lhs (*stmt, lhs);
2112 modify_this_stmt = true;
2113 if (lacc->grp_partial_lhs)
2114 force_gimple_rhs = true;
2115 sra_stats.exprs++;
2116 }
2117
2118 if (racc && racc->grp_to_be_replaced)
2119 {
2120 rhs = get_access_replacement (racc);
2121 modify_this_stmt = true;
2122 if (racc->grp_partial_lhs)
2123 force_gimple_rhs = true;
2124 sra_stats.exprs++;
2125 }
2126
2127 if (modify_this_stmt)
2128 {
2129 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
2130 {
2131 /* If we can avoid creating a VIEW_CONVERT_EXPR do so.
2132 ??? This should move to fold_stmt which we simply should
2133 call after building a VIEW_CONVERT_EXPR here. */
2134 if (AGGREGATE_TYPE_P (TREE_TYPE (lhs))
2135 && !access_has_children_p (lacc))
2136 {
2137 tree expr = unshare_expr (lhs);
2138 if (build_ref_for_offset (&expr, TREE_TYPE (lhs), 0,
2139 TREE_TYPE (rhs), false))
2140 {
2141 lhs = expr;
2142 gimple_assign_set_lhs (*stmt, expr);
2143 }
2144 }
2145 else if (AGGREGATE_TYPE_P (TREE_TYPE (rhs))
2146 && !access_has_children_p (racc))
2147 {
2148 tree expr = unshare_expr (rhs);
2149 if (build_ref_for_offset (&expr, TREE_TYPE (rhs), 0,
2150 TREE_TYPE (lhs), false))
2151 rhs = expr;
2152 }
2153 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
2154 {
2155 rhs = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lhs), rhs);
2156 if (!is_gimple_reg (lhs))
2157 force_gimple_rhs = true;
2158 }
2159 }
2160
2161 if (force_gimple_rhs)
2162 rhs = force_gimple_operand_gsi (gsi, rhs, true, NULL_TREE,
2163 true, GSI_SAME_STMT);
2164 if (gimple_assign_rhs1 (*stmt) != rhs)
2165 {
2166 gimple_assign_set_rhs_from_tree (gsi, rhs);
2167 gcc_assert (*stmt == gsi_stmt (*gsi));
2168 }
2169 }
2170
2171 /* From this point on, the function deals with assignments in between
2172 aggregates when at least one has scalar reductions of some of its
2173 components. There are three possible scenarios: Both the LHS and RHS have
2174 to-be-scalarized components, 2) only the RHS has or 3) only the LHS has.
2175
2176 In the first case, we would like to load the LHS components from RHS
2177 components whenever possible. If that is not possible, we would like to
2178 read it directly from the RHS (after updating it by storing in it its own
2179 components). If there are some necessary unscalarized data in the LHS,
2180 those will be loaded by the original assignment too. If neither of these
2181 cases happen, the original statement can be removed. Most of this is done
2182 by load_assign_lhs_subreplacements.
2183
2184 In the second case, we would like to store all RHS scalarized components
2185 directly into LHS and if they cover the aggregate completely, remove the
2186 statement too. In the third case, we want the LHS components to be loaded
2187 directly from the RHS (DSE will remove the original statement if it
2188 becomes redundant).
2189
2190 This is a bit complex but manageable when types match and when unions do
2191 not cause confusion in a way that we cannot really load a component of LHS
2192 from the RHS or vice versa (the access representing this level can have
2193 subaccesses that are accessible only through a different union field at a
2194 higher level - different from the one used in the examined expression).
2195 Unions are fun.
2196
2197 Therefore, I specially handle a fourth case, happening when there is a
2198 specific type cast or it is impossible to locate a scalarized subaccess on
2199 the other side of the expression. If that happens, I simply "refresh" the
2200 RHS by storing in it is scalarized components leave the original statement
2201 there to do the copying and then load the scalar replacements of the LHS.
2202 This is what the first branch does. */
2203
2204 if (contains_view_convert_expr_p (rhs) || contains_view_convert_expr_p (lhs)
2205 || (access_has_children_p (racc)
2206 && !ref_expr_for_all_replacements_p (racc, lhs, racc->offset))
2207 || (access_has_children_p (lacc)
2208 && !ref_expr_for_all_replacements_p (lacc, rhs, lacc->offset)))
2209 {
2210 if (access_has_children_p (racc))
2211 generate_subtree_copies (racc->first_child, racc->base, 0, 0, 0,
2212 gsi, false, false);
2213 if (access_has_children_p (lacc))
2214 generate_subtree_copies (lacc->first_child, lacc->base, 0, 0, 0,
2215 gsi, true, true);
2216 sra_stats.separate_lhs_rhs_handling++;
2217 }
2218 else
2219 {
2220 if (access_has_children_p (lacc) && access_has_children_p (racc))
2221 {
2222 gimple_stmt_iterator orig_gsi = *gsi;
2223 enum unscalarized_data_handling refreshed;
2224
2225 if (lacc->grp_read && !lacc->grp_covered)
2226 refreshed = handle_unscalarized_data_in_subtree (racc, lhs, gsi);
2227 else
2228 refreshed = SRA_UDH_NONE;
2229
2230 load_assign_lhs_subreplacements (lacc->first_child, racc,
2231 lacc->offset, racc->offset,
2232 &orig_gsi, gsi, &refreshed, lhs);
2233 if (refreshed != SRA_UDH_RIGHT)
2234 {
2235 if (*stmt == gsi_stmt (*gsi))
2236 gsi_next (gsi);
2237
2238 unlink_stmt_vdef (*stmt);
2239 gsi_remove (&orig_gsi, true);
2240 sra_stats.deleted++;
2241 return SRA_SA_REMOVED;
2242 }
2243 }
2244 else
2245 {
2246 if (access_has_children_p (racc))
2247 {
2248 if (!racc->grp_unscalarized_data)
2249 {
2250 generate_subtree_copies (racc->first_child, lhs,
2251 racc->offset, 0, 0, gsi,
2252 false, false);
2253 gcc_assert (*stmt == gsi_stmt (*gsi));
2254 unlink_stmt_vdef (*stmt);
2255 gsi_remove (gsi, true);
2256 sra_stats.deleted++;
2257 return SRA_SA_REMOVED;
2258 }
2259 else
2260 generate_subtree_copies (racc->first_child, lhs,
2261 racc->offset, 0, 0, gsi, false, true);
2262 }
2263 else if (access_has_children_p (lacc))
2264 generate_subtree_copies (lacc->first_child, rhs, lacc->offset,
2265 0, 0, gsi, true, true);
2266 }
2267 }
2268 return modify_this_stmt ? SRA_SA_PROCESSED : SRA_SA_NONE;
2269 }
2270
2271 /* Generate statements initializing scalar replacements of parts of function
2272 parameters. */
2273
2274 static void
2275 initialize_parameter_reductions (void)
2276 {
2277 gimple_stmt_iterator gsi;
2278 gimple_seq seq = NULL;
2279 tree parm;
2280
2281 for (parm = DECL_ARGUMENTS (current_function_decl);
2282 parm;
2283 parm = TREE_CHAIN (parm))
2284 {
2285 VEC (access_p, heap) *access_vec;
2286 struct access *access;
2287
2288 if (!bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
2289 continue;
2290 access_vec = get_base_access_vector (parm);
2291 if (!access_vec)
2292 continue;
2293
2294 if (!seq)
2295 {
2296 seq = gimple_seq_alloc ();
2297 gsi = gsi_start (seq);
2298 }
2299
2300 for (access = VEC_index (access_p, access_vec, 0);
2301 access;
2302 access = access->next_grp)
2303 generate_subtree_copies (access, parm, 0, 0, 0, &gsi, true, true);
2304 }
2305
2306 if (seq)
2307 gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR), seq);
2308 }
2309
2310 /* The "main" function of intraprocedural SRA passes. Runs the analysis and if
2311 it reveals there are components of some aggregates to be scalarized, it runs
2312 the required transformations. */
2313 static unsigned int
2314 perform_intra_sra (void)
2315 {
2316 int ret = 0;
2317 sra_initialize ();
2318
2319 if (!find_var_candidates ())
2320 goto out;
2321
2322 if (!scan_function (build_access_from_expr, build_accesses_from_assign, NULL,
2323 true, NULL))
2324 goto out;
2325
2326 if (!analyze_all_variable_accesses ())
2327 goto out;
2328
2329 scan_function (sra_modify_expr, sra_modify_assign, NULL,
2330 false, NULL);
2331 initialize_parameter_reductions ();
2332
2333 statistics_counter_event (cfun, "Scalar replacements created",
2334 sra_stats.replacements);
2335 statistics_counter_event (cfun, "Modified expressions", sra_stats.exprs);
2336 statistics_counter_event (cfun, "Subtree copy stmts",
2337 sra_stats.subtree_copies);
2338 statistics_counter_event (cfun, "Subreplacement stmts",
2339 sra_stats.subreplacements);
2340 statistics_counter_event (cfun, "Deleted stmts", sra_stats.deleted);
2341 statistics_counter_event (cfun, "Separate LHS and RHS handling",
2342 sra_stats.separate_lhs_rhs_handling);
2343
2344 ret = TODO_update_ssa;
2345
2346 out:
2347 sra_deinitialize ();
2348 return ret;
2349 }
2350
2351 /* Perform early intraprocedural SRA. */
2352 static unsigned int
2353 early_intra_sra (void)
2354 {
2355 sra_mode = SRA_MODE_EARLY_INTRA;
2356 return perform_intra_sra ();
2357 }
2358
2359 /* Perform "late" intraprocedural SRA. */
2360 static unsigned int
2361 late_intra_sra (void)
2362 {
2363 sra_mode = SRA_MODE_INTRA;
2364 return perform_intra_sra ();
2365 }
2366
2367
2368 static bool
2369 gate_intra_sra (void)
2370 {
2371 return flag_tree_sra != 0;
2372 }
2373
2374
2375 struct gimple_opt_pass pass_sra_early =
2376 {
2377 {
2378 GIMPLE_PASS,
2379 "esra", /* name */
2380 gate_intra_sra, /* gate */
2381 early_intra_sra, /* execute */
2382 NULL, /* sub */
2383 NULL, /* next */
2384 0, /* static_pass_number */
2385 TV_TREE_SRA, /* tv_id */
2386 PROP_cfg | PROP_ssa, /* properties_required */
2387 0, /* properties_provided */
2388 0, /* properties_destroyed */
2389 0, /* todo_flags_start */
2390 TODO_dump_func
2391 | TODO_update_ssa
2392 | TODO_ggc_collect
2393 | TODO_verify_ssa /* todo_flags_finish */
2394 }
2395 };
2396
2397
2398 struct gimple_opt_pass pass_sra =
2399 {
2400 {
2401 GIMPLE_PASS,
2402 "sra", /* name */
2403 gate_intra_sra, /* gate */
2404 late_intra_sra, /* execute */
2405 NULL, /* sub */
2406 NULL, /* next */
2407 0, /* static_pass_number */
2408 TV_TREE_SRA, /* tv_id */
2409 PROP_cfg | PROP_ssa, /* properties_required */
2410 0, /* properties_provided */
2411 0, /* properties_destroyed */
2412 TODO_update_address_taken, /* todo_flags_start */
2413 TODO_dump_func
2414 | TODO_update_ssa
2415 | TODO_ggc_collect
2416 | TODO_verify_ssa /* todo_flags_finish */
2417 }
2418 };