OSDN Git Service

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