On Sun, 26 Jun 2011, Martin Jambor wrote:

> Hi,
> 
> under some circumstances involving user specified alignment and/or
> packed attributes, SRA can create a misaligned MEM_REF.  As the
> testcase demonstrates, it is not enough to not consider variables with
> these type attributes, mainly because we might attempt to load/store
> the scalar replacements from/to right/left sides of original aggregate
> assignments which might be misaligned.
> 
> I'm wondering whether this approach isn't too heavy-handed but I have
> not been able to convince myself that anything short of this is
> sufficient, esp. in presence of the all-time-SRA-favorite type-casts,
> one-field-structures and unions.  At the very least I therefore do
> this only for strict-alignment architectures, where this is actually
> an issue.
> 
> I have verified the testcase fails with a "bus error" on sparc64 and
> passes when the patch is applied.  I have run make -k test for c and
> c++ on sparc64-linux without any issues as well as traditional
> bootstrap and full testsuite run on x86_64-linux.  OK for trunk and
> for 4.6 when unfrozen?
> 
> Thanks,
> 
> Martin
> 
> 
> 2011-06-24  Martin Jambor  <mjam...@suse.cz>
> 
>       PR tree-optimization/49094
>       * tree-sra.c (potential_alignment_issues): New function.
>       (build_accesses_from_assign): Use it.
> 
>       * testsuite/gcc.dg/tree-ssa/pr49094.c: New test.
> 
> 
> Index: src/gcc/tree-sra.c
> ===================================================================
> --- src.orig/gcc/tree-sra.c
> +++ src/gcc/tree-sra.c
> @@ -1023,6 +1023,33 @@ disqualify_ops_if_throwing_stmt (gimple
>    return false;
>  }
>  
> +/* Return true iff type of EXP or any of the types it is based on are
> +   user-aligned and packed.  */
> +
> +static bool
> +potential_alignment_issues (tree exp)
> +{
> +  if (!STRICT_ALIGNMENT)
> +    return false;
> +
> +  while (true)
> +    {
> +      tree type = TREE_TYPE (exp);
> +
> +      if (TYPE_USER_ALIGN (type)
> +       || TYPE_PACKED (type))
> +     return true;
> +
> +      if (handled_component_p (exp))
> +     exp = TREE_OPERAND (exp, 0);
> +      else
> +     break;
> +    }

I think you want something like

static bool
tree_non_mode_aligned_mem_p (tree exp)
{
  enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
  unsigned int align;

  if (mode == BLKmode
      || !STRICT_ALIGNMENT)
    return false;

  align = get_object_alignment (exp, BIGGEST_ALIGNMENT);
  if (GET_MODE_ALIGNMENT (mode) > align)
    return true;

  return false;
}

as for STRICT_ALIGNMENT targets we assume that the loads/stores SRA
inserts have the alignment of the mode.

Richard.

> +  return false;
> +}
> +
> +
>  /* Scan expressions occuring in STMT, create access structures for all 
> accesses
>     to candidates for scalarization and remove those candidates which occur in
>     statements or expressions that prevent them from being split apart.  
> Return
> @@ -1047,7 +1074,10 @@ build_accesses_from_assign (gimple stmt)
>    lacc = build_access_from_expr_1 (lhs, stmt, true);
>  
>    if (lacc)
> -    lacc->grp_assignment_write = 1;
> +    {
> +      lacc->grp_assignment_write = 1;
> +      lacc->grp_unscalarizable_region |= potential_alignment_issues (rhs);
> +    }
>  
>    if (racc)
>      {
> @@ -1055,6 +1085,7 @@ build_accesses_from_assign (gimple stmt)
>        if (should_scalarize_away_bitmap && !gimple_has_volatile_ops (stmt)
>         && !is_gimple_reg_type (racc->type))
>       bitmap_set_bit (should_scalarize_away_bitmap, DECL_UID (racc->base));
> +      racc->grp_unscalarizable_region |= potential_alignment_issues (lhs);
>      }
>  
>    if (lacc && racc
> Index: src/gcc/testsuite/gcc.dg/tree-ssa/pr49094.c
> ===================================================================
> --- /dev/null
> +++ src/gcc/testsuite/gcc.dg/tree-ssa/pr49094.c
> @@ -0,0 +1,38 @@
> +/* { dg-do run } */
> +/* { dg-options "-O" } */
> +
> +struct in_addr {
> +     unsigned int s_addr;
> +};
> +
> +struct ip {
> +     unsigned char ip_p;
> +     unsigned short ip_sum;
> +     struct  in_addr ip_src,ip_dst;
> +} __attribute__ ((aligned(1), packed));
> +
> +struct ip ip_fw_fwd_addr;
> +
> +int test_alignment( char *m )
> +{
> +  struct ip *ip = (struct ip *) m;
> +  struct in_addr pkt_dst;
> +  pkt_dst = ip->ip_dst ;
> +  if( pkt_dst.s_addr == 0 )
> +    return 1;
> +  else
> +    return 0;
> +}
> +
> +int __attribute__ ((noinline, noclone))
> +intermediary (char *p)
> +{
> +  return test_alignment (p);
> +}
> +
> +int
> +main (int argc, char *argv[])
> +{
> +  ip_fw_fwd_addr.ip_dst.s_addr = 1;
> +  return intermediary ((void *) &ip_fw_fwd_addr);
> +}
> 
> 

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

Reply via email to