On Fri, 25 Apr 2014, Martin Jambor wrote:

> Hi,
> 
> the patch below is inspired by PR 57297 (the most relevant comments
> are #4 and #5).  The problem is that currently SRA creates memory
> loads and stores with alias type of whatever happens to be in
> access->base.  However, at least when using placement or some nasty
> type-casting, it is possible that the same aggregate, represented by
> the same access structure, is accessed using different alias types in
> one function.  This might lead to bogus memory access reordering, at
> least in theory.  This patch therefore makes sure all SRA created
> accesses have the same alias type as the load/store they originated
> from.
> 
> Because load_assign_lhs_subreplacements did not look like it could
> accept one more parameter, I encapsulated all of them in a structure.
> I wrote this patch in December, I admit I don't remember what the new
> testcase aims for, but I assume I added it for a reason :-)
> 
> Bootstrapped and tested on x86_64-linux.  OK for trunk?

Ok.

Thanks,
Richard.

> Thanks,
> 
> Martin
> 
> 
> 2014-04-24  Martin Jambor  <mjam...@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.
> 
> 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
> index 0000000..6cbc0b4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/sra-14.c
> @@ -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;
> +}
> +
> diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
> index 49bbee3..4a24e6a 100644
> --- a/gcc/tree-sra.c
> +++ b/gcc/tree-sra.c
> @@ -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
> 
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746
GF: Jeff Hawn, Jennifer Guild, Felix Imend"orffer

Reply via email to