]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-sra.c (sra_modify_expr): Generate new memory accesses with same alias type as...
authorMartin Jambor <mjambor@suse.cz>
Mon, 28 Apr 2014 16:55:40 +0000 (18:55 +0200)
committerMartin Jambor <jamborm@gcc.gnu.org>
Mon, 28 Apr 2014 16:55:40 +0000 (18:55 +0200)
2014-04-28  Martin Jambor  <mjambor@suse.cz>

* tree-sra.c (sra_modify_expr): Generate new memory accesses with
same alias type as the original statement.
(subreplacement_assignment_data): New type.
(handle_unscalarized_data_in_subtree): New type of parameter,
generate new memory accesses with same alias type as the original
statement.
(load_assign_lhs_subreplacements): Likewise.
(sra_modify_constructor_assign): Generate new memory accesses with
same alias type as the original statement.

testsuite/
        * gcc.dg/tree-ssa/sra-14.c: New test.

From-SVN: r209868

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/sra-14.c [new file with mode: 0644]
gcc/tree-sra.c

index 7a1894b380430afddd00f022da4986d846fbc8c1..61c8eccd90b86866c54c47282676b32a5b1ae92d 100644 (file)
@@ -1,3 +1,15 @@
+2014-04-28  Martin Jambor  <mjambor@suse.cz>
+
+       * tree-sra.c (sra_modify_expr): Generate new memory accesses with
+       same alias type as the original statement.
+       (subreplacement_assignment_data): New type.
+       (handle_unscalarized_data_in_subtree): New type of parameter,
+       generate new memory accesses with same alias type as the original
+       statement.
+       (load_assign_lhs_subreplacements): Likewise.
+       (sra_modify_constructor_assign): Generate new memory accesses with
+       same alias type as the original statement.
+
 2014-04-28  Richard Biener  <rguenther@suse.de>
 
        * tree-pass.h (TODO_verify_il): Define.
index 41c082116e73b1c45e3f0c0cc55af61102789b01..b2f07c669c437abb7770132c65deaa16567d0452 100644 (file)
@@ -1,3 +1,7 @@
+2014-04-28  Martin Jambor  <mjambor@suse.cz>
+
+        * gcc.dg/tree-ssa/sra-14.c: New test.
+
 2014-04-28  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/60092
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sra-14.c b/gcc/testsuite/gcc.dg/tree-ssa/sra-14.c
new file mode 100644 (file)
index 0000000..6cbc0b4
--- /dev/null
@@ -0,0 +1,70 @@
+/* { dg-do run } */
+/* { dg-options "-O1" } */
+
+struct S
+{
+  int i, j;
+};
+
+struct Z
+{
+  struct S d, s;
+};
+
+struct S __attribute__ ((noinline, noclone))
+get_s (void)
+{
+  struct S s;
+  s.i = 5;
+  s.j = 6;
+
+  return s;
+}
+
+struct S __attribute__ ((noinline, noclone))
+get_d (void)
+{
+  struct S d;
+  d.i = 0;
+  d.j = 0;
+
+  return d;
+}
+
+int __attribute__ ((noinline, noclone))
+get_c (void)
+{
+  return 1;
+}
+
+int __attribute__ ((noinline, noclone))
+my_nop (int i)
+{
+  return i;
+}
+
+int __attribute__ ((noinline, noclone))
+foo (void)
+{
+  struct Z z;
+  int i, c = get_c ();
+
+  z.d = get_d ();
+  z.s = get_s ();
+
+  for (i = 0; i < c; i++)
+    {
+      z.s.i = my_nop (z.s.i);
+      z.s.j = my_nop (z.s.j);
+    }
+
+  return z.s.i + z.s.j;
+}
+
+int main (int argc, char *argv[])
+{
+  if (foo () != 11)
+    __builtin_abort ();
+  return 0;
+}
+
index 49bbee3deb762e609c29fb521f0e701f18282b0e..4a24e6a1b70a5f869b0a222741d7bba990ce2ca3 100644 (file)
@@ -2769,7 +2769,7 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
 {
   location_t loc;
   struct access *access;
-  tree type, bfr;
+  tree type, bfr, orig_expr;
 
   if (TREE_CODE (*expr) == BIT_FIELD_REF)
     {
@@ -2785,6 +2785,7 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
   if (!access)
     return false;
   type = TREE_TYPE (*expr);
+  orig_expr = *expr;
 
   loc = gimple_location (gsi_stmt (*gsi));
   gimple_stmt_iterator alt_gsi = gsi_none ();
@@ -2811,8 +2812,7 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
        {
          tree ref;
 
-         ref = build_ref_for_model (loc, access->base, access->offset, access,
-                                    NULL, false);
+         ref = build_ref_for_model (loc, orig_expr, 0, access, NULL, false);
 
          if (write)
            {
@@ -2863,7 +2863,7 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
       else
        start_offset = chunk_size = 0;
 
-      generate_subtree_copies (access->first_child, access->base, 0,
+      generate_subtree_copies (access->first_child, orig_expr, access->offset,
                               start_offset, chunk_size, gsi, write, write,
                               loc);
     }
@@ -2877,53 +2877,70 @@ enum unscalarized_data_handling { SRA_UDH_NONE,  /* Nothing done so far. */
                                  SRA_UDH_RIGHT, /* Data flushed to the RHS. */
                                  SRA_UDH_LEFT }; /* Data flushed to the LHS. */
 
+struct subreplacement_assignment_data
+{
+  /* Offset of the access representing the lhs of the assignment.  */
+  HOST_WIDE_INT left_offset;
+
+  /* LHS and RHS of the original assignment.  */
+  tree assignment_lhs, assignment_rhs;
+
+  /* Access representing the rhs of the whole assignment.  */
+  struct access *top_racc;
+
+  /* Stmt iterator used for statement insertions after the original assignment.
+   It points to the main GSI used to traverse a BB during function body
+   modification.  */
+  gimple_stmt_iterator *new_gsi;
+
+  /* Stmt iterator used for statement insertions before the original
+   assignment.  Keeps on pointing to the original statement.  */
+  gimple_stmt_iterator old_gsi;
+
+  /* Location of the assignment.   */
+  location_t loc;
+
+  /* Keeps the information whether we have needed to refresh replacements of
+   the LHS and from which side of the assignments this takes place.  */
+  enum unscalarized_data_handling refreshed;
+};
+
 /* Store all replacements in the access tree rooted in TOP_RACC either to their
    base aggregate if there are unscalarized data or directly to LHS of the
    statement that is pointed to by GSI otherwise.  */
 
-static enum unscalarized_data_handling
-handle_unscalarized_data_in_subtree (struct access *top_racc,
-                                    gimple_stmt_iterator *gsi)
+static void
+handle_unscalarized_data_in_subtree (struct subreplacement_assignment_data *sad)
 {
-  if (top_racc->grp_unscalarized_data)
+  tree src;
+  if (sad->top_racc->grp_unscalarized_data)
     {
-      generate_subtree_copies (top_racc->first_child, top_racc->base, 0, 0, 0,
-                              gsi, false, false,
-                              gimple_location (gsi_stmt (*gsi)));
-      return SRA_UDH_RIGHT;
+      src = sad->assignment_rhs;
+      sad->refreshed = SRA_UDH_RIGHT;
     }
   else
     {
-      tree lhs = gimple_assign_lhs (gsi_stmt (*gsi));
-      generate_subtree_copies (top_racc->first_child, lhs, top_racc->offset,
-                              0, 0, gsi, false, false,
-                              gimple_location (gsi_stmt (*gsi)));
-      return SRA_UDH_LEFT;
+      src = sad->assignment_lhs;
+      sad->refreshed = SRA_UDH_LEFT;
     }
+  generate_subtree_copies (sad->top_racc->first_child, src,
+                          sad->top_racc->offset, 0, 0,
+                          &sad->old_gsi, false, false, sad->loc);
 }
 
-
 /* Try to generate statements to load all sub-replacements in an access subtree
-   formed by children of LACC from scalar replacements in the TOP_RACC subtree.
-   If that is not possible, refresh the TOP_RACC base aggregate and load the
-   accesses from it.  LEFT_OFFSET is the offset of the left whole subtree being
-   copied. NEW_GSI is stmt iterator used for statement insertions after the
-   original assignment, OLD_GSI is used to insert statements before the
-   assignment.  *REFRESHED keeps the information whether we have needed to
-   refresh replacements of the LHS and from which side of the assignments this
-   takes place.  */
+   formed by children of LACC from scalar replacements in the SAD->top_racc
+   subtree.  If that is not possible, refresh the SAD->top_racc base aggregate
+   and load the accesses from it.  */
 
 static void
-load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc,
-                                HOST_WIDE_INT left_offset,
-                                gimple_stmt_iterator *old_gsi,
-                                gimple_stmt_iterator *new_gsi,
-                                enum unscalarized_data_handling *refreshed)
+load_assign_lhs_subreplacements (struct access *lacc,
+                                struct subreplacement_assignment_data *sad)
 {
-  location_t loc = gimple_location (gsi_stmt (*old_gsi));
   for (lacc = lacc->first_child; lacc; lacc = lacc->next_sibling)
     {
-      HOST_WIDE_INT offset = lacc->offset - left_offset + top_racc->offset;
+      HOST_WIDE_INT offset;
+      offset = lacc->offset - sad->left_offset + sad->top_racc->offset;
 
       if (lacc->grp_to_be_replaced)
        {
@@ -2931,53 +2948,57 @@ load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc,
          gimple stmt;
          tree rhs;
 
-         racc = find_access_in_subtree (top_racc, offset, lacc->size);
+         racc = find_access_in_subtree (sad->top_racc, offset, lacc->size);
          if (racc && racc->grp_to_be_replaced)
            {
              rhs = get_access_replacement (racc);
              if (!useless_type_conversion_p (lacc->type, racc->type))
-               rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, lacc->type, rhs);
+               rhs = fold_build1_loc (sad->loc, VIEW_CONVERT_EXPR,
+                                      lacc->type, rhs);
 
              if (racc->grp_partial_lhs && lacc->grp_partial_lhs)
-               rhs = force_gimple_operand_gsi (old_gsi, rhs, true, NULL_TREE,
-                                               true, GSI_SAME_STMT);
+               rhs = force_gimple_operand_gsi (&sad->old_gsi, rhs, true,
+                                               NULL_TREE, true, GSI_SAME_STMT);
            }
          else
            {
              /* No suitable access on the right hand side, need to load from
                 the aggregate.  See if we have to update it first... */
-             if (*refreshed == SRA_UDH_NONE)
-               *refreshed = handle_unscalarized_data_in_subtree (top_racc,
-                                                                 old_gsi);
+             if (sad->refreshed == SRA_UDH_NONE)
+               handle_unscalarized_data_in_subtree (sad);
 
-             if (*refreshed == SRA_UDH_LEFT)
-               rhs = build_ref_for_model (loc, lacc->base, lacc->offset, lacc,
-                                           new_gsi, true);
+             if (sad->refreshed == SRA_UDH_LEFT)
+               rhs = build_ref_for_model (sad->loc, sad->assignment_lhs,
+                                          lacc->offset - sad->left_offset,
+                                          lacc, sad->new_gsi, true);
              else
-               rhs = build_ref_for_model (loc, top_racc->base, offset, lacc,
-                                           new_gsi, true);
+               rhs = build_ref_for_model (sad->loc, sad->assignment_rhs,
+                                          lacc->offset - sad->left_offset,
+                                          lacc, sad->new_gsi, true);
              if (lacc->grp_partial_lhs)
-               rhs = force_gimple_operand_gsi (new_gsi, rhs, true, NULL_TREE,
+               rhs = force_gimple_operand_gsi (sad->new_gsi,
+                                               rhs, true, NULL_TREE,
                                                false, GSI_NEW_STMT);
            }
 
          stmt = gimple_build_assign (get_access_replacement (lacc), rhs);
-         gsi_insert_after (new_gsi, stmt, GSI_NEW_STMT);
-         gimple_set_location (stmt, loc);
+         gsi_insert_after (sad->new_gsi, stmt, GSI_NEW_STMT);
+         gimple_set_location (stmt, sad->loc);
          update_stmt (stmt);
          sra_stats.subreplacements++;
        }
       else
        {
-         if (*refreshed == SRA_UDH_NONE
+         if (sad->refreshed == SRA_UDH_NONE
              && lacc->grp_read && !lacc->grp_covered)
-           *refreshed = handle_unscalarized_data_in_subtree (top_racc,
-                                                             old_gsi);
+           handle_unscalarized_data_in_subtree (sad);
+
          if (lacc && lacc->grp_to_be_debug_replaced)
            {
              gimple ds;
              tree drhs;
-             struct access *racc = find_access_in_subtree (top_racc, offset,
+             struct access *racc = find_access_in_subtree (sad->top_racc,
+                                                           offset,
                                                            lacc->size);
 
              if (racc && racc->grp_to_be_replaced)
@@ -2987,27 +3008,26 @@ load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc,
                  else
                    drhs = NULL;
                }
-             else if (*refreshed == SRA_UDH_LEFT)
-               drhs = build_debug_ref_for_model (loc, lacc->base, lacc->offset,
-                                                 lacc);
-             else if (*refreshed == SRA_UDH_RIGHT)
-               drhs = build_debug_ref_for_model (loc, top_racc->base, offset,
-                                                 lacc);
+             else if (sad->refreshed == SRA_UDH_LEFT)
+               drhs = build_debug_ref_for_model (sad->loc, lacc->base,
+                                                 lacc->offset, lacc);
+             else if (sad->refreshed == SRA_UDH_RIGHT)
+               drhs = build_debug_ref_for_model (sad->loc, sad->top_racc->base,
+                                                 offset, lacc);
              else
                drhs = NULL_TREE;
              if (drhs
                  && !useless_type_conversion_p (lacc->type, TREE_TYPE (drhs)))
-               drhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
+               drhs = fold_build1_loc (sad->loc, VIEW_CONVERT_EXPR,
                                        lacc->type, drhs);
              ds = gimple_build_debug_bind (get_access_replacement (lacc),
-                                           drhs, gsi_stmt (*old_gsi));
-             gsi_insert_after (new_gsi, ds, GSI_NEW_STMT);
+                                           drhs, gsi_stmt (sad->old_gsi));
+             gsi_insert_after (sad->new_gsi, ds, GSI_NEW_STMT);
            }
        }
 
       if (lacc->first_child)
-       load_assign_lhs_subreplacements (lacc, top_racc, left_offset,
-                                        old_gsi, new_gsi, refreshed);
+       load_assign_lhs_subreplacements (lacc, sad);
     }
 }
 
@@ -3053,7 +3073,7 @@ sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
       /* I have never seen this code path trigger but if it can happen the
         following should handle it gracefully.  */
       if (access_has_children_p (acc))
-       generate_subtree_copies (acc->first_child, acc->base, 0, 0, 0, gsi,
+       generate_subtree_copies (acc->first_child, lhs, acc->offset, 0, 0, gsi,
                                 true, true, loc);
       return SRA_AM_MODIFIED;
     }
@@ -3261,7 +3281,7 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi)
       || stmt_ends_bb_p (*stmt))
     {
       if (access_has_children_p (racc))
-       generate_subtree_copies (racc->first_child, racc->base, 0, 0, 0,
+       generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0,
                                 gsi, false, false, loc);
       if (access_has_children_p (lacc))
        {
@@ -3271,7 +3291,7 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi)
              alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi)));
              gsi = &alt_gsi;
            }
-         generate_subtree_copies (lacc->first_child, lacc->base, 0, 0, 0,
+         generate_subtree_copies (lacc->first_child, lhs, lacc->offset, 0, 0,
                                   gsi, true, true, loc);
        }
       sra_stats.separate_lhs_rhs_handling++;
@@ -3301,21 +3321,26 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi)
          && !lacc->grp_unscalarizable_region
          && !racc->grp_unscalarizable_region)
        {
-         gimple_stmt_iterator orig_gsi = *gsi;
-         enum unscalarized_data_handling refreshed;
+         struct subreplacement_assignment_data sad;
+
+         sad.left_offset = lacc->offset;
+         sad.assignment_lhs = lhs;
+         sad.assignment_rhs = rhs;
+         sad.top_racc = racc;
+         sad.old_gsi = *gsi;
+         sad.new_gsi = gsi;
+         sad.loc = gimple_location (*stmt);
+         sad.refreshed = SRA_UDH_NONE;
 
          if (lacc->grp_read && !lacc->grp_covered)
-           refreshed = handle_unscalarized_data_in_subtree (racc, gsi);
-         else
-           refreshed = SRA_UDH_NONE;
+           handle_unscalarized_data_in_subtree (&sad);
 
-         load_assign_lhs_subreplacements (lacc, racc, lacc->offset,
-                                          &orig_gsi, gsi, &refreshed);
-         if (refreshed != SRA_UDH_RIGHT)
+         load_assign_lhs_subreplacements (lacc, &sad);
+         if (sad.refreshed != SRA_UDH_RIGHT)
            {
              gsi_next (gsi);
              unlink_stmt_vdef (*stmt);
-             gsi_remove (&orig_gsi, true);
+             gsi_remove (&sad.old_gsi, true);
              release_defs (*stmt);
              sra_stats.deleted++;
              return SRA_AM_REMOVED;
@@ -3344,7 +3369,7 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi)
          /* Restore the aggregate RHS from its components so the
             prevailing aggregate copy does the right thing.  */
          if (access_has_children_p (racc))
-           generate_subtree_copies (racc->first_child, racc->base, 0, 0, 0,
+           generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0,
                                     gsi, false, false, loc);
          /* Re-load the components of the aggregate copy destination.
             But use the RHS aggregate to load from to expose more