OSDN Git Service

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