OSDN Git Service

2009-09-02 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 /* Set the expr of TARGET to one just like MODEL but with is own base at the
1500    bottom of the handled components.  */
1501
1502 static void
1503 duplicate_expr_for_different_base (struct access *target,
1504                                    struct access *model)
1505 {
1506   tree t, expr = unshare_expr (model->expr);
1507
1508   gcc_assert (handled_component_p (expr));
1509   t = expr;
1510   while (handled_component_p (TREE_OPERAND (t, 0)))
1511     t = TREE_OPERAND (t, 0);
1512   gcc_assert (TREE_OPERAND (t, 0) == model->base);
1513   TREE_OPERAND (t, 0) = target->base;
1514
1515   target->expr = expr;
1516 }
1517
1518
1519 /* Create a new child access of PARENT, with all properties just like MODEL
1520    except for its offset and with its grp_write false and grp_read true.
1521    Return the new access. Note that this access is created long after all
1522    splicing and sorting, it's not located in any access vector and is
1523    automatically a representative of its group.  */
1524
1525 static struct access *
1526 create_artificial_child_access (struct access *parent, struct access *model,
1527                                 HOST_WIDE_INT new_offset)
1528 {
1529   struct access *access;
1530   struct access **child;
1531
1532   gcc_assert (!model->grp_unscalarizable_region);
1533
1534   access = (struct access *) pool_alloc (access_pool);
1535   memset (access, 0, sizeof (struct access));
1536   access->base = parent->base;
1537   access->offset = new_offset;
1538   access->size = model->size;
1539   duplicate_expr_for_different_base (access, model);
1540   access->type = model->type;
1541   access->grp_write = true;
1542   access->grp_read = false;
1543
1544   child = &parent->first_child;
1545   while (*child && (*child)->offset < new_offset)
1546     child = &(*child)->next_sibling;
1547
1548   access->next_sibling = *child;
1549   *child = access;
1550
1551   return access;
1552 }
1553
1554
1555 /* Propagate all subaccesses of RACC across an assignment link to LACC. Return
1556    true if any new subaccess was created.  Additionally, if RACC is a scalar
1557    access but LACC is not, change the type of the latter.  */
1558
1559 static bool
1560 propagate_subacesses_accross_link (struct access *lacc, struct access *racc)
1561 {
1562   struct access *rchild;
1563   HOST_WIDE_INT norm_delta = lacc->offset - racc->offset;
1564   bool ret = false;
1565
1566   if (is_gimple_reg_type (lacc->type)
1567       || lacc->grp_unscalarizable_region
1568       || racc->grp_unscalarizable_region)
1569     return false;
1570
1571   if (!lacc->first_child && !racc->first_child
1572       && is_gimple_reg_type (racc->type))
1573     {
1574       duplicate_expr_for_different_base (lacc, racc);
1575       lacc->type = racc->type;
1576       return false;
1577     }
1578
1579   for (rchild = racc->first_child; rchild; rchild = rchild->next_sibling)
1580     {
1581       struct access *new_acc = NULL;
1582       HOST_WIDE_INT norm_offset = rchild->offset + norm_delta;
1583
1584       if (rchild->grp_unscalarizable_region)
1585         continue;
1586
1587       if (child_would_conflict_in_lacc (lacc, norm_offset, rchild->size,
1588                                         &new_acc))
1589         {
1590           if (new_acc)
1591             {
1592               rchild->grp_hint = 1;
1593               new_acc->grp_hint |= new_acc->grp_read;
1594               if (rchild->first_child)
1595                 ret |= propagate_subacesses_accross_link (new_acc, rchild);
1596             }
1597           continue;
1598         }
1599
1600       /* If a (part of) a union field is on the RHS of an assignment, it can
1601          have sub-accesses which do not make sense on the LHS (PR 40351).
1602          Check that this is not the case.  */
1603       if (!build_ref_for_offset (NULL, TREE_TYPE (lacc->base), norm_offset,
1604                                  rchild->type, false))
1605         continue;
1606
1607       rchild->grp_hint = 1;
1608       new_acc = create_artificial_child_access (lacc, rchild, norm_offset);
1609       if (racc->first_child)
1610         propagate_subacesses_accross_link (new_acc, rchild);
1611
1612       ret = true;
1613     }
1614
1615   return ret;
1616 }
1617
1618 /* Propagate all subaccesses across assignment links.  */
1619
1620 static void
1621 propagate_all_subaccesses (void)
1622 {
1623   while (work_queue_head)
1624     {
1625       struct access *racc = pop_access_from_work_queue ();
1626       struct assign_link *link;
1627
1628       gcc_assert (racc->first_link);
1629
1630       for (link = racc->first_link; link; link = link->next)
1631         {
1632           struct access *lacc = link->lacc;
1633
1634           if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
1635             continue;
1636           lacc = lacc->group_representative;
1637           if (propagate_subacesses_accross_link (lacc, racc)
1638               && lacc->first_link)
1639             add_access_to_work_queue (lacc);
1640         }
1641     }
1642 }
1643
1644 /* Go through all accesses collected throughout the (intraprocedural) analysis
1645    stage, exclude overlapping ones, identify representatives and build trees
1646    out of them, making decisions about scalarization on the way.  Return true
1647    iff there are any to-be-scalarized variables after this stage. */
1648
1649 static bool
1650 analyze_all_variable_accesses (void)
1651 {
1652   tree var;
1653   referenced_var_iterator rvi;
1654   int res = 0;
1655
1656   FOR_EACH_REFERENCED_VAR (var, rvi)
1657     if (bitmap_bit_p (candidate_bitmap, DECL_UID (var)))
1658       {
1659         struct access *access;
1660
1661         access = sort_and_splice_var_accesses (var);
1662         if (access)
1663           build_access_trees (access);
1664         else
1665           disqualify_candidate (var,
1666                                 "No or inhibitingly overlapping accesses.");
1667       }
1668
1669   propagate_all_subaccesses ();
1670
1671   FOR_EACH_REFERENCED_VAR (var, rvi)
1672     if (bitmap_bit_p (candidate_bitmap, DECL_UID (var)))
1673       {
1674         struct access *access = get_first_repr_for_decl (var);
1675
1676         if (analyze_access_trees (access))
1677           {
1678             res++;
1679             if (dump_file && (dump_flags & TDF_DETAILS))
1680               {
1681                 fprintf (dump_file, "\nAccess trees for ");
1682                 print_generic_expr (dump_file, var, 0);
1683                 fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
1684                 dump_access_tree (dump_file, access);
1685                 fprintf (dump_file, "\n");
1686               }
1687           }
1688         else
1689           disqualify_candidate (var, "No scalar replacements to be created.");
1690       }
1691
1692   if (res)
1693     {
1694       statistics_counter_event (cfun, "Scalarized aggregates", res);
1695       return true;
1696     }
1697   else
1698     return false;
1699 }
1700
1701 /* Return true iff a reference statement into aggregate AGG can be built for
1702    every single to-be-replaced accesses that is a child of ACCESS, its sibling
1703    or a child of its sibling. TOP_OFFSET is the offset from the processed
1704    access subtree that has to be subtracted from offset of each access.  */
1705
1706 static bool
1707 ref_expr_for_all_replacements_p (struct access *access, tree agg,
1708                                  HOST_WIDE_INT top_offset)
1709 {
1710   do
1711     {
1712       if (access->grp_to_be_replaced
1713           && !build_ref_for_offset (NULL, TREE_TYPE (agg),
1714                                     access->offset - top_offset,
1715                                     access->type, false))
1716         return false;
1717
1718       if (access->first_child
1719           && !ref_expr_for_all_replacements_p (access->first_child, agg,
1720                                                top_offset))
1721         return false;
1722
1723       access = access->next_sibling;
1724     }
1725   while (access);
1726
1727   return true;
1728 }
1729
1730 /* Generate statements copying scalar replacements of accesses within a subtree
1731    into or out of AGG.  ACCESS is the first child of the root of the subtree to
1732    be processed.  AGG is an aggregate type expression (can be a declaration but
1733    does not have to be, it can for example also be an indirect_ref).
1734    TOP_OFFSET is the offset of the processed subtree which has to be subtracted
1735    from offsets of individual accesses to get corresponding offsets for AGG.
1736    If CHUNK_SIZE is non-null, copy only replacements in the interval
1737    <start_offset, start_offset + chunk_size>, otherwise copy all.  GSI is a
1738    statement iterator used to place the new statements.  WRITE should be true
1739    when the statements should write from AGG to the replacement and false if
1740    vice versa.  if INSERT_AFTER is true, new statements will be added after the
1741    current statement in GSI, they will be added before the statement
1742    otherwise.  */
1743
1744 static void
1745 generate_subtree_copies (struct access *access, tree agg,
1746                          HOST_WIDE_INT top_offset,
1747                          HOST_WIDE_INT start_offset, HOST_WIDE_INT chunk_size,
1748                          gimple_stmt_iterator *gsi, bool write,
1749                          bool insert_after)
1750 {
1751   do
1752     {
1753       tree expr = unshare_expr (agg);
1754
1755       if (chunk_size && access->offset >= start_offset + chunk_size)
1756         return;
1757
1758       if (access->grp_to_be_replaced
1759           && (chunk_size == 0
1760               || access->offset + access->size > start_offset))
1761         {
1762           tree repl = get_access_replacement (access);
1763           bool ref_found;
1764           gimple stmt;
1765
1766           ref_found = build_ref_for_offset (&expr, TREE_TYPE (agg),
1767                                              access->offset - top_offset,
1768                                              access->type, false);
1769           gcc_assert (ref_found);
1770
1771           if (write)
1772             {
1773               if (access->grp_partial_lhs)
1774                 expr = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
1775                                                  !insert_after,
1776                                                  insert_after ? GSI_NEW_STMT
1777                                                  : GSI_SAME_STMT);
1778               stmt = gimple_build_assign (repl, expr);
1779             }
1780           else
1781             {
1782               TREE_NO_WARNING (repl) = 1;
1783               if (access->grp_partial_lhs)
1784                 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
1785                                                  !insert_after,
1786                                                  insert_after ? GSI_NEW_STMT
1787                                                  : GSI_SAME_STMT);
1788               stmt = gimple_build_assign (expr, repl);
1789             }
1790
1791           if (insert_after)
1792             gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
1793           else
1794             gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
1795           update_stmt (stmt);
1796           sra_stats.subtree_copies++;
1797         }
1798
1799       if (access->first_child)
1800         generate_subtree_copies (access->first_child, agg, top_offset,
1801                                  start_offset, chunk_size, gsi,
1802                                  write, insert_after);
1803
1804       access = access->next_sibling;
1805     }
1806   while (access);
1807 }
1808
1809 /* Assign zero to all scalar replacements in an access subtree.  ACCESS is the
1810    the root of the subtree to be processed.  GSI is the statement iterator used
1811    for inserting statements which are added after the current statement if
1812    INSERT_AFTER is true or before it otherwise.  */
1813
1814 static void
1815 init_subtree_with_zero (struct access *access, gimple_stmt_iterator *gsi,
1816                         bool insert_after)
1817
1818 {
1819   struct access *child;
1820
1821   if (access->grp_to_be_replaced)
1822     {
1823       gimple stmt;
1824
1825       stmt = gimple_build_assign (get_access_replacement (access),
1826                                   fold_convert (access->type,
1827                                                 integer_zero_node));
1828       if (insert_after)
1829         gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
1830       else
1831         gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
1832       update_stmt (stmt);
1833     }
1834
1835   for (child = access->first_child; child; child = child->next_sibling)
1836     init_subtree_with_zero (child, gsi, insert_after);
1837 }
1838
1839 /* Search for an access representative for the given expression EXPR and
1840    return it or NULL if it cannot be found.  */
1841
1842 static struct access *
1843 get_access_for_expr (tree expr)
1844 {
1845   HOST_WIDE_INT offset, size, max_size;
1846   tree base;
1847
1848   /* FIXME: This should not be necessary but Ada produces V_C_Es with a type of
1849      a different size than the size of its argument and we need the latter
1850      one.  */
1851   if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
1852     expr = TREE_OPERAND (expr, 0);
1853
1854   base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
1855   if (max_size == -1 || !DECL_P (base))
1856     return NULL;
1857
1858   if (!bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
1859     return NULL;
1860
1861   return get_var_base_offset_size_access (base, offset, max_size);
1862 }
1863
1864 /* Callback for scan_function.  Replace the expression EXPR with a scalar
1865    replacement if there is one and generate other statements to do type
1866    conversion or subtree copying if necessary.  GSI is used to place newly
1867    created statements, WRITE is true if the expression is being written to (it
1868    is on a LHS of a statement or output in an assembly statement).  */
1869
1870 static bool
1871 sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write,
1872                  void *data ATTRIBUTE_UNUSED)
1873 {
1874   struct access *access;
1875   tree type, bfr;
1876
1877   if (TREE_CODE (*expr) == BIT_FIELD_REF)
1878     {
1879       bfr = *expr;
1880       expr = &TREE_OPERAND (*expr, 0);
1881     }
1882   else
1883     bfr = NULL_TREE;
1884
1885   if (TREE_CODE (*expr) == REALPART_EXPR || TREE_CODE (*expr) == IMAGPART_EXPR)
1886     expr = &TREE_OPERAND (*expr, 0);
1887   access = get_access_for_expr (*expr);
1888   if (!access)
1889     return false;
1890   type = TREE_TYPE (*expr);
1891
1892   if (access->grp_to_be_replaced)
1893     {
1894       tree repl = get_access_replacement (access);
1895       /* If we replace a non-register typed access simply use the original
1896          access expression to extract the scalar component afterwards.
1897          This happens if scalarizing a function return value or parameter
1898          like in gcc.c-torture/execute/20041124-1.c, 20050316-1.c and
1899          gcc.c-torture/compile/20011217-1.c.  */
1900       if (!is_gimple_reg_type (type))
1901         {
1902           gimple stmt;
1903           if (write)
1904             {
1905               tree ref = unshare_expr (access->expr);
1906               if (access->grp_partial_lhs)
1907                 ref = force_gimple_operand_gsi (gsi, ref, true, NULL_TREE,
1908                                                  false, GSI_NEW_STMT);
1909               stmt = gimple_build_assign (repl, ref);
1910               gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
1911             }
1912           else
1913             {
1914               if (access->grp_partial_lhs)
1915                 repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
1916                                                  true, GSI_SAME_STMT);
1917               stmt = gimple_build_assign (unshare_expr (access->expr), repl);
1918               gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
1919             }
1920         }
1921       else
1922         {
1923           gcc_assert (useless_type_conversion_p (type, access->type));
1924           *expr = repl;
1925         }
1926       sra_stats.exprs++;
1927     }
1928
1929   if (access->first_child)
1930     {
1931       HOST_WIDE_INT start_offset, chunk_size;
1932       if (bfr
1933           && host_integerp (TREE_OPERAND (bfr, 1), 1)
1934           && host_integerp (TREE_OPERAND (bfr, 2), 1))
1935         {
1936           chunk_size = tree_low_cst (TREE_OPERAND (bfr, 1), 1);
1937           start_offset = access->offset
1938             + tree_low_cst (TREE_OPERAND (bfr, 2), 1);
1939         }
1940       else
1941         start_offset = chunk_size = 0;
1942
1943       generate_subtree_copies (access->first_child, access->base, 0,
1944                                start_offset, chunk_size, gsi, write, write);
1945     }
1946   return true;
1947 }
1948
1949 /* Where scalar replacements of the RHS have been written to when a replacement
1950    of a LHS of an assigments cannot be direclty loaded from a replacement of
1951    the RHS. */
1952 enum unscalarized_data_handling { SRA_UDH_NONE,  /* Nothing done so far. */
1953                                   SRA_UDH_RIGHT, /* Data flushed to the RHS. */
1954                                   SRA_UDH_LEFT }; /* Data flushed to the LHS. */
1955
1956 /* Store all replacements in the access tree rooted in TOP_RACC either to their
1957    base aggregate if there are unscalarized data or directly to LHS
1958    otherwise.  */
1959
1960 static enum unscalarized_data_handling
1961 handle_unscalarized_data_in_subtree (struct access *top_racc, tree lhs,
1962                                      gimple_stmt_iterator *gsi)
1963 {
1964   if (top_racc->grp_unscalarized_data)
1965     {
1966       generate_subtree_copies (top_racc->first_child, top_racc->base, 0, 0, 0,
1967                                gsi, false, false);
1968       return SRA_UDH_RIGHT;
1969     }
1970   else
1971     {
1972       generate_subtree_copies (top_racc->first_child, lhs, top_racc->offset,
1973                                0, 0, gsi, false, false);
1974       return SRA_UDH_LEFT;
1975     }
1976 }
1977
1978
1979 /* Try to generate statements to load all sub-replacements in an access
1980    (sub)tree (LACC is the first child) from scalar replacements in the TOP_RACC
1981    (sub)tree.  If that is not possible, refresh the TOP_RACC base aggregate and
1982    load the accesses from it.  LEFT_OFFSET is the offset of the left whole
1983    subtree being copied, RIGHT_OFFSET is the same thing for the right subtree.
1984    GSI is stmt iterator used for statement insertions.  *REFRESHED is true iff
1985    the rhs top aggregate has already been refreshed by contents of its scalar
1986    reductions and is set to true if this function has to do it.  */
1987
1988 static void
1989 load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc,
1990                                  HOST_WIDE_INT left_offset,
1991                                  HOST_WIDE_INT right_offset,
1992                                  gimple_stmt_iterator *old_gsi,
1993                                  gimple_stmt_iterator *new_gsi,
1994                                  enum unscalarized_data_handling *refreshed,
1995                                  tree lhs)
1996 {
1997   location_t loc = EXPR_LOCATION (lacc->expr);
1998   do
1999     {
2000       if (lacc->grp_to_be_replaced)
2001         {
2002           struct access *racc;
2003           HOST_WIDE_INT offset = lacc->offset - left_offset + right_offset;
2004           gimple stmt;
2005           tree rhs;
2006
2007           racc = find_access_in_subtree (top_racc, offset, lacc->size);
2008           if (racc && racc->grp_to_be_replaced)
2009             {
2010               rhs = get_access_replacement (racc);
2011               if (!useless_type_conversion_p (lacc->type, racc->type))
2012                 rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, lacc->type, rhs);
2013             }
2014           else
2015             {
2016               bool repl_found;
2017
2018               /* No suitable access on the right hand side, need to load from
2019                  the aggregate.  See if we have to update it first... */
2020               if (*refreshed == SRA_UDH_NONE)
2021                 *refreshed = handle_unscalarized_data_in_subtree (top_racc,
2022                                                                   lhs, old_gsi);
2023
2024               if (*refreshed == SRA_UDH_LEFT)
2025                 rhs = unshare_expr (lacc->expr);
2026               else
2027                 {
2028                   rhs = unshare_expr (top_racc->base);
2029                   repl_found = build_ref_for_offset (&rhs,
2030                                                      TREE_TYPE (top_racc->base),
2031                                                      offset, lacc->type, false);
2032                   gcc_assert (repl_found);
2033                 }
2034             }
2035
2036           stmt = gimple_build_assign (get_access_replacement (lacc), rhs);
2037           gsi_insert_after (new_gsi, stmt, GSI_NEW_STMT);
2038           update_stmt (stmt);
2039           sra_stats.subreplacements++;
2040         }
2041       else if (*refreshed == SRA_UDH_NONE
2042                && lacc->grp_read && !lacc->grp_covered)
2043         *refreshed = handle_unscalarized_data_in_subtree (top_racc, lhs,
2044                                                           old_gsi);
2045
2046       if (lacc->first_child)
2047         load_assign_lhs_subreplacements (lacc->first_child, top_racc,
2048                                          left_offset, right_offset,
2049                                          old_gsi, new_gsi, refreshed, lhs);
2050       lacc = lacc->next_sibling;
2051     }
2052   while (lacc);
2053 }
2054
2055 /* Modify assignments with a CONSTRUCTOR on their RHS.  STMT contains a pointer
2056    to the assignment and GSI is the statement iterator pointing at it.  Returns
2057    the same values as sra_modify_assign.  */
2058
2059 static enum scan_assign_result
2060 sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
2061 {
2062   tree lhs = gimple_assign_lhs (*stmt);
2063   struct access *acc;
2064
2065   acc = get_access_for_expr (lhs);
2066   if (!acc)
2067     return SRA_SA_NONE;
2068
2069   if (VEC_length (constructor_elt,
2070                   CONSTRUCTOR_ELTS (gimple_assign_rhs1 (*stmt))) > 0)
2071     {
2072       /* I have never seen this code path trigger but if it can happen the
2073          following should handle it gracefully.  */
2074       if (access_has_children_p (acc))
2075         generate_subtree_copies (acc->first_child, acc->base, 0, 0, 0, gsi,
2076                                  true, true);
2077       return SRA_SA_PROCESSED;
2078     }
2079
2080   if (acc->grp_covered)
2081     {
2082       init_subtree_with_zero (acc, gsi, false);
2083       unlink_stmt_vdef (*stmt);
2084       gsi_remove (gsi, true);
2085       return SRA_SA_REMOVED;
2086     }
2087   else
2088     {
2089       init_subtree_with_zero (acc, gsi, true);
2090       return SRA_SA_PROCESSED;
2091     }
2092 }
2093
2094
2095 /* Callback of scan_function to process assign statements.  It examines both
2096    sides of the statement, replaces them with a scalare replacement if there is
2097    one and generating copying of replacements if scalarized aggregates have been
2098    used in the assignment.  STMT is a pointer to the assign statement, GSI is
2099    used to hold generated statements for type conversions and subtree
2100    copying.  */
2101
2102 static enum scan_assign_result
2103 sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi,
2104                    void *data ATTRIBUTE_UNUSED)
2105 {
2106   struct access *lacc, *racc;
2107   tree lhs, rhs;
2108   bool modify_this_stmt = false;
2109   bool force_gimple_rhs = false;
2110   location_t loc = gimple_location (*stmt);
2111
2112   if (!gimple_assign_single_p (*stmt))
2113     return SRA_SA_NONE;
2114   lhs = gimple_assign_lhs (*stmt);
2115   rhs = gimple_assign_rhs1 (*stmt);
2116
2117   if (TREE_CODE (rhs) == CONSTRUCTOR)
2118     return sra_modify_constructor_assign (stmt, gsi);
2119
2120   if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (lhs) == REALPART_EXPR
2121       || TREE_CODE (rhs) == IMAGPART_EXPR || TREE_CODE (lhs) == IMAGPART_EXPR
2122       || TREE_CODE (rhs) == BIT_FIELD_REF || TREE_CODE (lhs) == BIT_FIELD_REF)
2123     {
2124       modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (*stmt),
2125                                           gsi, false, data);
2126       modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (*stmt),
2127                                            gsi, true, data);
2128       return modify_this_stmt ? SRA_SA_PROCESSED : SRA_SA_NONE;
2129     }
2130
2131   lacc = get_access_for_expr (lhs);
2132   racc = get_access_for_expr (rhs);
2133   if (!lacc && !racc)
2134     return SRA_SA_NONE;
2135
2136   if (lacc && lacc->grp_to_be_replaced)
2137     {
2138       lhs = get_access_replacement (lacc);
2139       gimple_assign_set_lhs (*stmt, lhs);
2140       modify_this_stmt = true;
2141       if (lacc->grp_partial_lhs)
2142         force_gimple_rhs = true;
2143       sra_stats.exprs++;
2144     }
2145
2146   if (racc && racc->grp_to_be_replaced)
2147     {
2148       rhs = get_access_replacement (racc);
2149       modify_this_stmt = true;
2150       if (racc->grp_partial_lhs)
2151         force_gimple_rhs = true;
2152       sra_stats.exprs++;
2153     }
2154
2155   if (modify_this_stmt)
2156     {
2157       if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
2158         {
2159           /* If we can avoid creating a VIEW_CONVERT_EXPR do so.
2160              ???  This should move to fold_stmt which we simply should
2161              call after building a VIEW_CONVERT_EXPR here.  */
2162           if (AGGREGATE_TYPE_P (TREE_TYPE (lhs))
2163               && !access_has_children_p (lacc))
2164             {
2165               tree expr = unshare_expr (lhs);
2166               if (build_ref_for_offset (&expr, TREE_TYPE (lhs), 0,
2167                                         TREE_TYPE (rhs), false))
2168                 {
2169                   lhs = expr;
2170                   gimple_assign_set_lhs (*stmt, expr);
2171                 }
2172             }
2173           else if (AGGREGATE_TYPE_P (TREE_TYPE (rhs))
2174                    && !access_has_children_p (racc))
2175             {
2176               tree expr = unshare_expr (rhs);
2177               if (build_ref_for_offset (&expr, TREE_TYPE (rhs), 0,
2178                                         TREE_TYPE (lhs), false))
2179                 rhs = expr;
2180             }
2181           if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
2182             {
2183               rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), rhs);
2184               if (!is_gimple_reg (lhs))
2185                 force_gimple_rhs = true;
2186             }
2187         }
2188
2189       if (force_gimple_rhs)
2190         rhs = force_gimple_operand_gsi (gsi, rhs, true, NULL_TREE,
2191                                         true, GSI_SAME_STMT);
2192       if (gimple_assign_rhs1 (*stmt) != rhs)
2193         {
2194           gimple_assign_set_rhs_from_tree (gsi, rhs);
2195           gcc_assert (*stmt == gsi_stmt (*gsi));
2196         }
2197     }
2198
2199   /* From this point on, the function deals with assignments in between
2200      aggregates when at least one has scalar reductions of some of its
2201      components.  There are three possible scenarios: Both the LHS and RHS have
2202      to-be-scalarized components, 2) only the RHS has or 3) only the LHS has.
2203
2204      In the first case, we would like to load the LHS components from RHS
2205      components whenever possible.  If that is not possible, we would like to
2206      read it directly from the RHS (after updating it by storing in it its own
2207      components).  If there are some necessary unscalarized data in the LHS,
2208      those will be loaded by the original assignment too.  If neither of these
2209      cases happen, the original statement can be removed.  Most of this is done
2210      by load_assign_lhs_subreplacements.
2211
2212      In the second case, we would like to store all RHS scalarized components
2213      directly into LHS and if they cover the aggregate completely, remove the
2214      statement too.  In the third case, we want the LHS components to be loaded
2215      directly from the RHS (DSE will remove the original statement if it
2216      becomes redundant).
2217
2218      This is a bit complex but manageable when types match and when unions do
2219      not cause confusion in a way that we cannot really load a component of LHS
2220      from the RHS or vice versa (the access representing this level can have
2221      subaccesses that are accessible only through a different union field at a
2222      higher level - different from the one used in the examined expression).
2223      Unions are fun.
2224
2225      Therefore, I specially handle a fourth case, happening when there is a
2226      specific type cast or it is impossible to locate a scalarized subaccess on
2227      the other side of the expression.  If that happens, I simply "refresh" the
2228      RHS by storing in it is scalarized components leave the original statement
2229      there to do the copying and then load the scalar replacements of the LHS.
2230      This is what the first branch does.  */
2231
2232   if (contains_view_convert_expr_p (rhs) || contains_view_convert_expr_p (lhs)
2233       || (access_has_children_p (racc)
2234           && !ref_expr_for_all_replacements_p (racc, lhs, racc->offset))
2235       || (access_has_children_p (lacc)
2236           && !ref_expr_for_all_replacements_p (lacc, rhs, lacc->offset)))
2237     {
2238       if (access_has_children_p (racc))
2239         generate_subtree_copies (racc->first_child, racc->base, 0, 0, 0,
2240                                  gsi, false, false);
2241       if (access_has_children_p (lacc))
2242         generate_subtree_copies (lacc->first_child, lacc->base, 0, 0, 0,
2243                                  gsi, true, true);
2244       sra_stats.separate_lhs_rhs_handling++;
2245     }
2246   else
2247     {
2248       if (access_has_children_p (lacc) && access_has_children_p (racc))
2249         {
2250           gimple_stmt_iterator orig_gsi = *gsi;
2251           enum unscalarized_data_handling refreshed;
2252
2253           if (lacc->grp_read && !lacc->grp_covered)
2254             refreshed = handle_unscalarized_data_in_subtree (racc, lhs, gsi);
2255           else
2256             refreshed = SRA_UDH_NONE;
2257
2258           load_assign_lhs_subreplacements (lacc->first_child, racc,
2259                                            lacc->offset, racc->offset,
2260                                            &orig_gsi, gsi, &refreshed, lhs);
2261           if (refreshed != SRA_UDH_RIGHT)
2262             {
2263               if (*stmt == gsi_stmt (*gsi))
2264                 gsi_next (gsi);
2265
2266               unlink_stmt_vdef (*stmt);
2267               gsi_remove (&orig_gsi, true);
2268               sra_stats.deleted++;
2269               return SRA_SA_REMOVED;
2270             }
2271         }
2272       else
2273         {
2274           if (access_has_children_p (racc))
2275             {
2276               if (!racc->grp_unscalarized_data)
2277                 {
2278                   generate_subtree_copies (racc->first_child, lhs,
2279                                            racc->offset, 0, 0, gsi,
2280                                            false, false);
2281                   gcc_assert (*stmt == gsi_stmt (*gsi));
2282                   unlink_stmt_vdef (*stmt);
2283                   gsi_remove (gsi, true);
2284                   sra_stats.deleted++;
2285                   return SRA_SA_REMOVED;
2286                 }
2287               else
2288                 generate_subtree_copies (racc->first_child, lhs,
2289                                          racc->offset, 0, 0, gsi, false, true);
2290             }
2291           else if (access_has_children_p (lacc))
2292             generate_subtree_copies (lacc->first_child, rhs, lacc->offset,
2293                                      0, 0, gsi, true, true);
2294         }
2295     }
2296   return modify_this_stmt ? SRA_SA_PROCESSED : SRA_SA_NONE;
2297 }
2298
2299 /* Generate statements initializing scalar replacements of parts of function
2300    parameters.  */
2301
2302 static void
2303 initialize_parameter_reductions (void)
2304 {
2305   gimple_stmt_iterator gsi;
2306   gimple_seq seq = NULL;
2307   tree parm;
2308
2309   for (parm = DECL_ARGUMENTS (current_function_decl);
2310        parm;
2311        parm = TREE_CHAIN (parm))
2312     {
2313       VEC (access_p, heap) *access_vec;
2314       struct access *access;
2315
2316       if (!bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
2317         continue;
2318       access_vec = get_base_access_vector (parm);
2319       if (!access_vec)
2320         continue;
2321
2322       if (!seq)
2323         {
2324           seq = gimple_seq_alloc ();
2325           gsi = gsi_start (seq);
2326         }
2327
2328       for (access = VEC_index (access_p, access_vec, 0);
2329            access;
2330            access = access->next_grp)
2331         generate_subtree_copies (access, parm, 0, 0, 0, &gsi, true, true);
2332     }
2333
2334   if (seq)
2335     gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR), seq);
2336 }
2337
2338 /* The "main" function of intraprocedural SRA passes.  Runs the analysis and if
2339    it reveals there are components of some aggregates to be scalarized, it runs
2340    the required transformations.  */
2341 static unsigned int
2342 perform_intra_sra (void)
2343 {
2344   int ret = 0;
2345   sra_initialize ();
2346
2347   if (!find_var_candidates ())
2348     goto out;
2349
2350   if (!scan_function (build_access_from_expr, build_accesses_from_assign, NULL,
2351                       true, NULL))
2352     goto out;
2353
2354   if (!analyze_all_variable_accesses ())
2355     goto out;
2356
2357   scan_function (sra_modify_expr, sra_modify_assign, NULL,
2358                  false, NULL);
2359   initialize_parameter_reductions ();
2360
2361   statistics_counter_event (cfun, "Scalar replacements created",
2362                             sra_stats.replacements);
2363   statistics_counter_event (cfun, "Modified expressions", sra_stats.exprs);
2364   statistics_counter_event (cfun, "Subtree copy stmts",
2365                             sra_stats.subtree_copies);
2366   statistics_counter_event (cfun, "Subreplacement stmts",
2367                             sra_stats.subreplacements);
2368   statistics_counter_event (cfun, "Deleted stmts", sra_stats.deleted);
2369   statistics_counter_event (cfun, "Separate LHS and RHS handling",
2370                             sra_stats.separate_lhs_rhs_handling);
2371
2372   ret = TODO_update_ssa;
2373
2374  out:
2375   sra_deinitialize ();
2376   return ret;
2377 }
2378
2379 /* Perform early intraprocedural SRA.  */
2380 static unsigned int
2381 early_intra_sra (void)
2382 {
2383   sra_mode = SRA_MODE_EARLY_INTRA;
2384   return perform_intra_sra ();
2385 }
2386
2387 /* Perform "late" intraprocedural SRA.  */
2388 static unsigned int
2389 late_intra_sra (void)
2390 {
2391   sra_mode = SRA_MODE_INTRA;
2392   return perform_intra_sra ();
2393 }
2394
2395
2396 static bool
2397 gate_intra_sra (void)
2398 {
2399   return flag_tree_sra != 0;
2400 }
2401
2402
2403 struct gimple_opt_pass pass_sra_early =
2404 {
2405  {
2406   GIMPLE_PASS,
2407   "esra",                               /* name */
2408   gate_intra_sra,                       /* gate */
2409   early_intra_sra,                      /* execute */
2410   NULL,                                 /* sub */
2411   NULL,                                 /* next */
2412   0,                                    /* static_pass_number */
2413   TV_TREE_SRA,                          /* tv_id */
2414   PROP_cfg | PROP_ssa,                  /* properties_required */
2415   0,                                    /* properties_provided */
2416   0,                                    /* properties_destroyed */
2417   0,                                    /* todo_flags_start */
2418   TODO_dump_func
2419   | TODO_update_ssa
2420   | TODO_ggc_collect
2421   | TODO_verify_ssa                     /* todo_flags_finish */
2422  }
2423 };
2424
2425
2426 struct gimple_opt_pass pass_sra =
2427 {
2428  {
2429   GIMPLE_PASS,
2430   "sra",                                /* name */
2431   gate_intra_sra,                       /* gate */
2432   late_intra_sra,                       /* execute */
2433   NULL,                                 /* sub */
2434   NULL,                                 /* next */
2435   0,                                    /* static_pass_number */
2436   TV_TREE_SRA,                          /* tv_id */
2437   PROP_cfg | PROP_ssa,                  /* properties_required */
2438   0,                                    /* properties_provided */
2439   0,                                    /* properties_destroyed */
2440   TODO_update_address_taken,            /* todo_flags_start */
2441   TODO_dump_func
2442   | TODO_update_ssa
2443   | TODO_ggc_collect
2444   | TODO_verify_ssa                     /* todo_flags_finish */
2445  }
2446 };