[PATCH, PR 55590] Avoid more pessimistic alignments in SRA

Martin Jambor mjambor@suse.cz
Tue Dec 4 15:41:00 GMT 2012


Hi,

when working at the IPA-SRA misalignment problems I have noticed that
the traditional intraprocedural SRA can also produce this when the
MEM_REF it is after is hidden below a handled component.  Fortunately,
now that get_object_alignment looks into MEM_REFS for alignment, we
can use it directly on the given base, as is done in the following
patch.  When we know the alignment of the originally requested base we
also only combine it with only the requested offset, as opposed to
also including the offset returned by get_addr_base_and_unit_offset.

The patch has passed bootstrap and testing on x86_64-linux and
powerpc64-linux, the same is currently in progress on sparc64-linux.

OK for trunk if it passes there as well?

Thanks,

Martin


2012-12-04  Martin Jambor  <mjambor@suse.cz>

	PR tree-optimization/55590
	* tree-sra.c (build_ref_for_offset): Use get_object_alignment to
	get base alignment.

	* testsuite/gcc.target/i386/pr55590-1.c: New test.
	* testsuite/gcc.target/i386/pr55590-2.c: Likewise.

*** /dev/null	Thu Oct 25 13:49:30 2012
--- gcc/testsuite/gcc.target/i386/pr55590-1.c	Tue Dec  4 11:36:54 2012
***************
*** 0 ****
--- 1,27 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -mavx" } */
+ 
+ #include <immintrin.h>
+ 
+ struct S
+ {
+   __m128 a, b;
+ };
+ 
+ struct T
+ {
+   int a;
+   struct S s;
+ };
+ 
+ 
+ void foo (struct T *p, __m128 v)
+ {
+   struct S s;
+ 
+   s = p->s;
+   s.b = _mm_add_ps(s.b, v);
+   p->s = s;
+ }
+ 
+ /* { dg-final { scan-assembler-not "vmovups" } } */
*** /dev/null	Thu Oct 25 13:49:30 2012
--- gcc/testsuite/gcc.target/i386/pr55590-2.c	Tue Dec  4 11:37:02 2012
***************
*** 0 ****
--- 1,27 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -mavx" } */
+ 
+ #include <immintrin.h>
+ 
+ struct S
+ {
+   __m128 a, b;
+ };
+ 
+ struct T
+ {
+   int a;
+   struct S s[8];
+ };
+ 
+ 
+ void foo (struct T *p, int i, __m128 v)
+ {
+   struct S s;
+ 
+   s = p->s[i];
+   s.b = _mm_add_ps(s.b, v);
+   p->s[i] = s;
+ }
+ 
+ /* { dg-final { scan-assembler-not "vmovups" } } */
*** /tmp/nagqRb_tree-sra.c	Tue Dec  4 13:24:05 2012
--- gcc/tree-sra.c	Tue Dec  4 13:12:10 2012
*************** make_fancy_name (tree expr)
*** 1423,1429 ****
     EXP_TYPE at the given OFFSET.  If BASE is something for which
     get_addr_base_and_unit_offset returns NULL, gsi must be non-NULL and is used
     to insert new statements either before or below the current one as specified
!    by INSERT_AFTER.  This function is not capable of handling bitfields.  */
  
  tree
  build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset,
--- 1423,1432 ----
     EXP_TYPE at the given OFFSET.  If BASE is something for which
     get_addr_base_and_unit_offset returns NULL, gsi must be non-NULL and is used
     to insert new statements either before or below the current one as specified
!    by INSERT_AFTER.  This function is not capable of handling bitfields.
! 
!    BASE must be either a declaration or a memory reference that has correct
!    alignment ifformation embeded in it (e.g. a pre-existing one in SRA).  */
  
  tree
  build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset,
*************** build_ref_for_offset (location_t loc, tr
*** 1433,1440 ****
    tree prev_base = base;
    tree off;
    HOST_WIDE_INT base_offset;
!   unsigned HOST_WIDE_INT misalign;
!   unsigned int align;
  
    gcc_checking_assert (offset % BITS_PER_UNIT == 0);
  
--- 1436,1442 ----
    tree prev_base = base;
    tree off;
    HOST_WIDE_INT base_offset;
!   unsigned int misalign, align = get_object_alignment (base);
  
    gcc_checking_assert (offset % BITS_PER_UNIT == 0);
  
*************** build_ref_for_offset (location_t loc, tr
*** 1476,1497 ****
        base = build_fold_addr_expr (unshare_expr (base));
      }
  
!   /* If prev_base were always an originally performed access
!      we can extract more optimistic alignment information
!      by looking at the access mode.  That would constrain the
!      alignment of base + base_offset which we would need to
!      adjust according to offset.  */
!   if (!get_pointer_alignment_1 (base, &align, &misalign))
!     {
!       gcc_assert (misalign == 0);
!       if (TREE_CODE (prev_base) == MEM_REF
! 	  || TREE_CODE (prev_base) == TARGET_MEM_REF)
! 	align = TYPE_ALIGN (TREE_TYPE (prev_base));
!     }
!   misalign += (tree_to_double_int (off)
! 	       .sext (TYPE_PRECISION (TREE_TYPE (off))).low
! 	       * BITS_PER_UNIT);
!   misalign = misalign & (align - 1);
    if (misalign != 0)
      align = (misalign & -misalign);
    if (align < TYPE_ALIGN (exp_type))
--- 1478,1484 ----
        base = build_fold_addr_expr (unshare_expr (base));
      }
  
!   misalign = offset & (align - 1);
    if (misalign != 0)
      align = (misalign & -misalign);
    if (align < TYPE_ALIGN (exp_type))



More information about the Gcc-patches mailing list