OSDN Git Service

./:
[pf3gnuchains/gcc-fork.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           && useless_type_conversion_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               sra_stats.subtree_copies++;
1764             }
1765
1766           if (insert_after)
1767             gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
1768           else
1769             gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
1770           update_stmt (stmt);
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           start_offset = tree_low_cst (TREE_OPERAND (bfr, 1), 1);
1911           chunk_size = tree_low_cst (TREE_OPERAND (bfr, 2), 1);
1912         }
1913       else
1914         start_offset = chunk_size = 0;
1915
1916       generate_subtree_copies (access->first_child, access->base, 0,
1917                                start_offset, chunk_size, gsi, write, write);
1918     }
1919   return true;
1920 }
1921
1922 /* Store all replacements in the access tree rooted in TOP_RACC either to their
1923    base aggregate if there are unscalarized data or directly to LHS
1924    otherwise.  */
1925
1926 static void
1927 handle_unscalarized_data_in_subtree (struct access *top_racc, tree lhs,
1928                                      gimple_stmt_iterator *gsi)
1929 {
1930   if (top_racc->grp_unscalarized_data)
1931     generate_subtree_copies (top_racc->first_child, top_racc->base, 0, 0, 0,
1932                              gsi, false, false);
1933   else
1934     generate_subtree_copies (top_racc->first_child, lhs, top_racc->offset,
1935                              0, 0, gsi, false, false);
1936 }
1937
1938
1939 /* Try to generate statements to load all sub-replacements in an access
1940    (sub)tree (LACC is the first child) from scalar replacements in the TOP_RACC
1941    (sub)tree.  If that is not possible, refresh the TOP_RACC base aggregate and
1942    load the accesses from it.  LEFT_OFFSET is the offset of the left whole
1943    subtree being copied, RIGHT_OFFSET is the same thing for the right subtree.
1944    GSI is stmt iterator used for statement insertions.  *REFRESHED is true iff
1945    the rhs top aggregate has already been refreshed by contents of its scalar
1946    reductions and is set to true if this function has to do it.  */
1947
1948 static void
1949 load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc,
1950                                  HOST_WIDE_INT left_offset,
1951                                  HOST_WIDE_INT right_offset,
1952                                  gimple_stmt_iterator *old_gsi,
1953                                  gimple_stmt_iterator *new_gsi,
1954                                  bool *refreshed, tree lhs)
1955 {
1956   do
1957     {
1958       if (lacc->grp_to_be_replaced)
1959         {
1960           struct access *racc;
1961           HOST_WIDE_INT offset = lacc->offset - left_offset + right_offset;
1962           gimple stmt;
1963           tree rhs;
1964
1965           racc = find_access_in_subtree (top_racc, offset, lacc->size);
1966           if (racc && racc->grp_to_be_replaced)
1967             {
1968               rhs = get_access_replacement (racc);
1969               if (!useless_type_conversion_p (lacc->type, racc->type))
1970                 rhs = fold_build1 (VIEW_CONVERT_EXPR, lacc->type, rhs);
1971             }
1972           else
1973             {
1974               bool repl_found;
1975
1976               /* No suitable access on the right hand side, need to load from
1977                  the aggregate.  See if we have to update it first... */
1978               if (!*refreshed)
1979                 {
1980                   gcc_assert (top_racc->first_child);
1981                   handle_unscalarized_data_in_subtree (top_racc, lhs, old_gsi);
1982                   *refreshed = true;
1983                 }
1984
1985               rhs = unshare_expr (top_racc->base);
1986               repl_found = build_ref_for_offset (&rhs,
1987                                                  TREE_TYPE (top_racc->base),
1988                                                  offset, lacc->type, false);
1989               gcc_assert (repl_found);
1990             }
1991
1992           stmt = gimple_build_assign (get_access_replacement (lacc), rhs);
1993           gsi_insert_after (new_gsi, stmt, GSI_NEW_STMT);
1994           update_stmt (stmt);
1995           sra_stats.subreplacements++;
1996         }
1997       else if (lacc->grp_read && !lacc->grp_covered && !*refreshed)
1998         {
1999           handle_unscalarized_data_in_subtree (top_racc, lhs, old_gsi);
2000           *refreshed = true;
2001         }
2002
2003       if (lacc->first_child)
2004         load_assign_lhs_subreplacements (lacc->first_child, top_racc,
2005                                          left_offset, right_offset,
2006                                          old_gsi, new_gsi, refreshed, lhs);
2007       lacc = lacc->next_sibling;
2008     }
2009   while (lacc);
2010 }
2011
2012 /* Modify assignments with a CONSTRUCTOR on their RHS.  STMT contains a pointer
2013    to the assignment and GSI is the statement iterator pointing at it.  Returns
2014    the same values as sra_modify_assign.  */
2015
2016 static enum scan_assign_result
2017 sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
2018 {
2019   tree lhs = gimple_assign_lhs (*stmt);
2020   struct access *acc;
2021
2022   acc = get_access_for_expr (lhs);
2023   if (!acc)
2024     return SRA_SA_NONE;
2025
2026   if (VEC_length (constructor_elt,
2027                   CONSTRUCTOR_ELTS (gimple_assign_rhs1 (*stmt))) > 0)
2028     {
2029       /* I have never seen this code path trigger but if it can happen the
2030          following should handle it gracefully.  */
2031       if (access_has_children_p (acc))
2032         generate_subtree_copies (acc->first_child, acc->base, 0, 0, 0, gsi,
2033                                  true, true);
2034       return SRA_SA_PROCESSED;
2035     }
2036
2037   if (acc->grp_covered)
2038     {
2039       init_subtree_with_zero (acc, gsi, false);
2040       unlink_stmt_vdef (*stmt);
2041       gsi_remove (gsi, true);
2042       return SRA_SA_REMOVED;
2043     }
2044   else
2045     {
2046       init_subtree_with_zero (acc, gsi, true);
2047       return SRA_SA_PROCESSED;
2048     }
2049 }
2050
2051
2052 /* Callback of scan_function to process assign statements.  It examines both
2053    sides of the statement, replaces them with a scalare replacement if there is
2054    one and generating copying of replacements if scalarized aggregates have been
2055    used in the assignment.  STMT is a pointer to the assign statement, GSI is
2056    used to hold generated statements for type conversions and subtree
2057    copying.  */
2058
2059 static enum scan_assign_result
2060 sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi,
2061                    void *data ATTRIBUTE_UNUSED)
2062 {
2063   struct access *lacc, *racc;
2064   tree lhs, rhs;
2065   bool modify_this_stmt = false;
2066   bool force_gimple_rhs = false;
2067
2068   if (!gimple_assign_single_p (*stmt))
2069     return SRA_SA_NONE;
2070   lhs = gimple_assign_lhs (*stmt);
2071   rhs = gimple_assign_rhs1 (*stmt);
2072
2073   if (TREE_CODE (rhs) == CONSTRUCTOR)
2074     return sra_modify_constructor_assign (stmt, gsi);
2075
2076   if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (lhs) == REALPART_EXPR
2077       || TREE_CODE (rhs) == IMAGPART_EXPR || TREE_CODE (lhs) == IMAGPART_EXPR
2078       || TREE_CODE (rhs) == BIT_FIELD_REF || TREE_CODE (lhs) == BIT_FIELD_REF)
2079     {
2080       modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (*stmt),
2081                                           gsi, false, data);
2082       modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (*stmt),
2083                                            gsi, true, data);
2084       return modify_this_stmt ? SRA_SA_PROCESSED : SRA_SA_NONE;
2085     }
2086
2087   lacc = get_access_for_expr (lhs);
2088   racc = get_access_for_expr (rhs);
2089   if (!lacc && !racc)
2090     return SRA_SA_NONE;
2091
2092   if (lacc && lacc->grp_to_be_replaced)
2093     {
2094       lhs = get_access_replacement (lacc);
2095       gimple_assign_set_lhs (*stmt, lhs);
2096       modify_this_stmt = true;
2097       if (lacc->grp_partial_lhs)
2098         force_gimple_rhs = true;
2099       sra_stats.exprs++;
2100     }
2101
2102   if (racc && racc->grp_to_be_replaced)
2103     {
2104       rhs = get_access_replacement (racc);
2105       modify_this_stmt = true;
2106       if (racc->grp_partial_lhs)
2107         force_gimple_rhs = true;
2108       sra_stats.exprs++;
2109     }
2110
2111   if (modify_this_stmt)
2112     {
2113       if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
2114         {
2115           /* If we can avoid creating a VIEW_CONVERT_EXPR do so.
2116              ???  This should move to fold_stmt which we simply should
2117              call after building a VIEW_CONVERT_EXPR here.  */
2118           if (AGGREGATE_TYPE_P (TREE_TYPE (lhs))
2119               && !access_has_children_p (lacc))
2120             {
2121               tree expr = unshare_expr (lhs);
2122               if (build_ref_for_offset (&expr, TREE_TYPE (lhs), 0,
2123                                         TREE_TYPE (rhs), false))
2124                 {
2125                   lhs = expr;
2126                   gimple_assign_set_lhs (*stmt, expr);
2127                 }
2128             }
2129           else if (AGGREGATE_TYPE_P (TREE_TYPE (rhs))
2130                    && !access_has_children_p (racc))
2131             {
2132               tree expr = unshare_expr (rhs);
2133               if (build_ref_for_offset (&expr, TREE_TYPE (rhs), 0,
2134                                         TREE_TYPE (lhs), false))
2135                 rhs = expr;
2136             }
2137           if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
2138             {
2139               rhs = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lhs), rhs);
2140               if (!is_gimple_reg (lhs))
2141                 force_gimple_rhs = true;
2142             }
2143         }
2144
2145       if (force_gimple_rhs)
2146         rhs = force_gimple_operand_gsi (gsi, rhs, true, NULL_TREE,
2147                                         true, GSI_SAME_STMT);
2148       if (gimple_assign_rhs1 (*stmt) != rhs)
2149         {
2150           gimple_assign_set_rhs_from_tree (gsi, rhs);
2151           gcc_assert (*stmt == gsi_stmt (*gsi));
2152         }
2153     }
2154
2155   /* From this point on, the function deals with assignments in between
2156      aggregates when at least one has scalar reductions of some of its
2157      components.  There are three possible scenarios: Both the LHS and RHS have
2158      to-be-scalarized components, 2) only the RHS has or 3) only the LHS has.
2159
2160      In the first case, we would like to load the LHS components from RHS
2161      components whenever possible.  If that is not possible, we would like to
2162      read it directly from the RHS (after updating it by storing in it its own
2163      components).  If there are some necessary unscalarized data in the LHS,
2164      those will be loaded by the original assignment too.  If neither of these
2165      cases happen, the original statement can be removed.  Most of this is done
2166      by load_assign_lhs_subreplacements.
2167
2168      In the second case, we would like to store all RHS scalarized components
2169      directly into LHS and if they cover the aggregate completely, remove the
2170      statement too.  In the third case, we want the LHS components to be loaded
2171      directly from the RHS (DSE will remove the original statement if it
2172      becomes redundant).
2173
2174      This is a bit complex but manageable when types match and when unions do
2175      not cause confusion in a way that we cannot really load a component of LHS
2176      from the RHS or vice versa (the access representing this level can have
2177      subaccesses that are accessible only through a different union field at a
2178      higher level - different from the one used in the examined expression).
2179      Unions are fun.
2180
2181      Therefore, I specially handle a fourth case, happening when there is a
2182      specific type cast or it is impossible to locate a scalarized subaccess on
2183      the other side of the expression.  If that happens, I simply "refresh" the
2184      RHS by storing in it is scalarized components leave the original statement
2185      there to do the copying and then load the scalar replacements of the LHS.
2186      This is what the first branch does.  */
2187
2188   if (contains_view_convert_expr_p (rhs) || contains_view_convert_expr_p (lhs)
2189       || (access_has_children_p (racc)
2190           && !ref_expr_for_all_replacements_p (racc, lhs, racc->offset))
2191       || (access_has_children_p (lacc)
2192           && !ref_expr_for_all_replacements_p (lacc, rhs, lacc->offset)))
2193     {
2194       if (access_has_children_p (racc))
2195         generate_subtree_copies (racc->first_child, racc->base, 0, 0, 0,
2196                                  gsi, false, false);
2197       if (access_has_children_p (lacc))
2198         generate_subtree_copies (lacc->first_child, lacc->base, 0, 0, 0,
2199                                  gsi, true, true);
2200       sra_stats.separate_lhs_rhs_handling++;
2201     }
2202   else
2203     {
2204       if (access_has_children_p (lacc) && access_has_children_p (racc))
2205         {
2206           gimple_stmt_iterator orig_gsi = *gsi;
2207           bool refreshed;
2208
2209           if (lacc->grp_read && !lacc->grp_covered)
2210             {
2211               handle_unscalarized_data_in_subtree (racc, lhs, gsi);
2212               refreshed = true;
2213             }
2214           else
2215             refreshed = false;
2216
2217           load_assign_lhs_subreplacements (lacc->first_child, racc,
2218                                            lacc->offset, racc->offset,
2219                                            &orig_gsi, gsi, &refreshed, lhs);
2220           if (!refreshed || !racc->grp_unscalarized_data)
2221             {
2222               if (*stmt == gsi_stmt (*gsi))
2223                 gsi_next (gsi);
2224
2225               unlink_stmt_vdef (*stmt);
2226               gsi_remove (&orig_gsi, true);
2227               sra_stats.deleted++;
2228               return SRA_SA_REMOVED;
2229             }
2230         }
2231       else
2232         {
2233           if (access_has_children_p (racc))
2234             {
2235               if (!racc->grp_unscalarized_data)
2236                 {
2237                   generate_subtree_copies (racc->first_child, lhs,
2238                                            racc->offset, 0, 0, gsi,
2239                                            false, false);
2240                   gcc_assert (*stmt == gsi_stmt (*gsi));
2241                   unlink_stmt_vdef (*stmt);
2242                   gsi_remove (gsi, true);
2243                   sra_stats.deleted++;
2244                   return SRA_SA_REMOVED;
2245                 }
2246               else
2247                 generate_subtree_copies (racc->first_child, lhs,
2248                                          racc->offset, 0, 0, gsi, false, true);
2249             }
2250           else if (access_has_children_p (lacc))
2251             generate_subtree_copies (lacc->first_child, rhs, lacc->offset,
2252                                      0, 0, gsi, true, true);
2253         }
2254     }
2255   return modify_this_stmt ? SRA_SA_PROCESSED : SRA_SA_NONE;
2256 }
2257
2258 /* Generate statements initializing scalar replacements of parts of function
2259    parameters.  */
2260
2261 static void
2262 initialize_parameter_reductions (void)
2263 {
2264   gimple_stmt_iterator gsi;
2265   gimple_seq seq = NULL;
2266   tree parm;
2267
2268   for (parm = DECL_ARGUMENTS (current_function_decl);
2269        parm;
2270        parm = TREE_CHAIN (parm))
2271     {
2272       VEC (access_p, heap) *access_vec;
2273       struct access *access;
2274
2275       if (!bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
2276         continue;
2277       access_vec = get_base_access_vector (parm);
2278       if (!access_vec)
2279         continue;
2280
2281       if (!seq)
2282         {
2283           seq = gimple_seq_alloc ();
2284           gsi = gsi_start (seq);
2285         }
2286
2287       for (access = VEC_index (access_p, access_vec, 0);
2288            access;
2289            access = access->next_grp)
2290         generate_subtree_copies (access, parm, 0, 0, 0, &gsi, true, true);
2291     }
2292
2293   if (seq)
2294     gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR), seq);
2295 }
2296
2297 /* The "main" function of intraprocedural SRA passes.  Runs the analysis and if
2298    it reveals there are components of some aggregates to be scalarized, it runs
2299    the required transformations.  */
2300 static unsigned int
2301 perform_intra_sra (void)
2302 {
2303   int ret = 0;
2304   sra_initialize ();
2305
2306   if (!find_var_candidates ())
2307     goto out;
2308
2309   if (!scan_function (build_access_from_expr, build_accesses_from_assign, NULL,
2310                       true, NULL))
2311     goto out;
2312
2313   if (!analyze_all_variable_accesses ())
2314     goto out;
2315
2316   scan_function (sra_modify_expr, sra_modify_assign, NULL,
2317                  false, NULL);
2318   initialize_parameter_reductions ();
2319
2320   statistics_counter_event (cfun, "Scalar replacements created",
2321                             sra_stats.replacements);
2322   statistics_counter_event (cfun, "Modified expressions", sra_stats.exprs);
2323   statistics_counter_event (cfun, "Subtree copy stmts",
2324                             sra_stats.subtree_copies);
2325   statistics_counter_event (cfun, "Subreplacement stmts",
2326                             sra_stats.subreplacements);
2327   statistics_counter_event (cfun, "Deleted stmts", sra_stats.deleted);
2328   statistics_counter_event (cfun, "Separate LHS and RHS handling",
2329                             sra_stats.separate_lhs_rhs_handling);
2330
2331   ret = TODO_update_ssa;
2332
2333  out:
2334   sra_deinitialize ();
2335   return ret;
2336 }
2337
2338 /* Perform early intraprocedural SRA.  */
2339 static unsigned int
2340 early_intra_sra (void)
2341 {
2342   sra_mode = SRA_MODE_EARLY_INTRA;
2343   return perform_intra_sra ();
2344 }
2345
2346 /* Perform "late" intraprocedural SRA.  */
2347 static unsigned int
2348 late_intra_sra (void)
2349 {
2350   sra_mode = SRA_MODE_INTRA;
2351   return perform_intra_sra ();
2352 }
2353
2354
2355 static bool
2356 gate_intra_sra (void)
2357 {
2358   return flag_tree_sra != 0;
2359 }
2360
2361
2362 struct gimple_opt_pass pass_sra_early =
2363 {
2364  {
2365   GIMPLE_PASS,
2366   "esra",                               /* name */
2367   gate_intra_sra,                       /* gate */
2368   early_intra_sra,                      /* execute */
2369   NULL,                                 /* sub */
2370   NULL,                                 /* next */
2371   0,                                    /* static_pass_number */
2372   TV_TREE_SRA,                          /* tv_id */
2373   PROP_cfg | PROP_ssa,                  /* properties_required */
2374   0,                                    /* properties_provided */
2375   0,                                    /* properties_destroyed */
2376   0,                                    /* todo_flags_start */
2377   TODO_dump_func
2378   | TODO_update_ssa
2379   | TODO_ggc_collect
2380   | TODO_verify_ssa                     /* todo_flags_finish */
2381  }
2382 };
2383
2384
2385 struct gimple_opt_pass pass_sra =
2386 {
2387  {
2388   GIMPLE_PASS,
2389   "sra",                                /* name */
2390   gate_intra_sra,                       /* gate */
2391   late_intra_sra,                       /* execute */
2392   NULL,                                 /* sub */
2393   NULL,                                 /* next */
2394   0,                                    /* static_pass_number */
2395   TV_TREE_SRA,                          /* tv_id */
2396   PROP_cfg | PROP_ssa,                  /* properties_required */
2397   0,                                    /* properties_provided */
2398   0,                                    /* properties_destroyed */
2399   TODO_update_address_taken,            /* todo_flags_start */
2400   TODO_dump_func
2401   | TODO_update_ssa
2402   | TODO_ggc_collect
2403   | TODO_verify_ssa                     /* todo_flags_finish */
2404  }
2405 };