This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR65310


This fixes a wrong-code bug in vectorization which extracts alignment
from something not (enough) related to the original memory reference
in the IL.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Richard.

2015-03-04  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/65310
	* tree-vect-data-refs.c (vect_compute_data_ref_alignment):
	Properly preserve alignment of the base of the access.

	* gcc.dg/vect/pr65310.c: New testcase.

Index: gcc/tree-vect-data-refs.c
===================================================================
*** gcc/tree-vect-data-refs.c	(revision 221149)
--- gcc/tree-vect-data-refs.c	(working copy)
*************** vect_compute_data_ref_alignment (struct
*** 650,656 ****
    tree base, base_addr;
    bool base_aligned;
    tree misalign;
!   tree aligned_to, alignment;
  
    if (dump_enabled_p ())
      dump_printf_loc (MSG_NOTE, vect_location,
--- 650,657 ----
    tree base, base_addr;
    bool base_aligned;
    tree misalign;
!   tree aligned_to;
!   unsigned HOST_WIDE_INT alignment;
  
    if (dump_enabled_p ())
      dump_printf_loc (MSG_NOTE, vect_location,
*************** vect_compute_data_ref_alignment (struct
*** 720,755 ****
  	}
      }
  
!   base = build_fold_indirect_ref (base_addr);
!   alignment = ssize_int (TYPE_ALIGN (vectype)/BITS_PER_UNIT);
  
!   if ((aligned_to && tree_int_cst_compare (aligned_to, alignment) < 0)
        || !misalign)
      {
        if (dump_enabled_p ())
  	{
  	  dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
  	                   "Unknown alignment for access: ");
! 	  dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, base);
  	  dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
  	}
        return true;
      }
  
!   if ((DECL_P (base)
!        && tree_int_cst_compare (ssize_int (DECL_ALIGN_UNIT (base)),
! 				alignment) >= 0)
!       || (TREE_CODE (base_addr) == SSA_NAME
! 	  && tree_int_cst_compare (ssize_int (TYPE_ALIGN_UNIT (TREE_TYPE (
! 						      TREE_TYPE (base_addr)))),
! 				   alignment) >= 0)
!       || (get_pointer_alignment (base_addr) >= TYPE_ALIGN (vectype)))
      base_aligned = true;
    else
      base_aligned = false;
  
    if (!base_aligned)
      {
        /* Do not change the alignment of global variables here if
  	 flag_section_anchors is enabled as we already generated
  	 RTL for other functions.  Most global variables should
--- 721,763 ----
  	}
      }
  
!   alignment = TYPE_ALIGN_UNIT (vectype);
  
!   if ((compare_tree_int (aligned_to, alignment) < 0)
        || !misalign)
      {
        if (dump_enabled_p ())
  	{
  	  dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
  	                   "Unknown alignment for access: ");
! 	  dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, ref);
  	  dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
  	}
        return true;
      }
  
!   /* To look at alignment of the base we have to preserve an inner MEM_REF
!      as that carries alignment information of the actual access.  */
!   base = ref;
!   while (handled_component_p (base))
!     base = TREE_OPERAND (base, 0);
!   if (TREE_CODE (base) == MEM_REF)
!     base = build2 (MEM_REF, TREE_TYPE (base), base_addr,
! 		   build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)), 0));
! 
!   if (get_object_alignment (base) >= TYPE_ALIGN (vectype))
      base_aligned = true;
    else
      base_aligned = false;
  
    if (!base_aligned)
      {
+       /* Strip an inner MEM_REF to a bare decl if possible.  */
+       if (TREE_CODE (base) == MEM_REF
+ 	  && integer_zerop (TREE_OPERAND (base, 1))
+ 	  && TREE_CODE (TREE_OPERAND (base, 0)) == ADDR_EXPR)
+ 	base = TREE_OPERAND (TREE_OPERAND (base, 0), 0);
+ 
        /* Do not change the alignment of global variables here if
  	 flag_section_anchors is enabled as we already generated
  	 RTL for other functions.  Most global variables should
*************** vect_compute_data_ref_alignment (struct
*** 784,790 ****
    /* If this is a backward running DR then first access in the larger
       vectype actually is N-1 elements before the address in the DR.
       Adjust misalign accordingly.  */
!   if (tree_int_cst_compare (DR_STEP (dr), size_zero_node) < 0)
      {
        tree offset = ssize_int (TYPE_VECTOR_SUBPARTS (vectype) - 1);
        /* DR_STEP(dr) is the same as -TYPE_SIZE of the scalar type,
--- 792,798 ----
    /* If this is a backward running DR then first access in the larger
       vectype actually is N-1 elements before the address in the DR.
       Adjust misalign accordingly.  */
!   if (tree_int_cst_sgn (DR_STEP (dr)) < 0)
      {
        tree offset = ssize_int (TYPE_VECTOR_SUBPARTS (vectype) - 1);
        /* DR_STEP(dr) is the same as -TYPE_SIZE of the scalar type,
*************** vect_compute_data_ref_alignment (struct
*** 794,812 ****
        misalign = size_binop (PLUS_EXPR, misalign, offset);
      }
  
!   /* Modulo alignment.  */
!   misalign = size_binop (FLOOR_MOD_EXPR, misalign, alignment);
! 
!   if (!tree_fits_uhwi_p (misalign))
!     {
!       /* Negative or overflowed misalignment value.  */
!       if (dump_enabled_p ())
! 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
! 	                 "unexpected misalign value\n");
!       return false;
!     }
! 
!   SET_DR_MISALIGNMENT (dr, tree_to_uhwi (misalign));
  
    if (dump_enabled_p ())
      {
--- 802,809 ----
        misalign = size_binop (PLUS_EXPR, misalign, offset);
      }
  
!   SET_DR_MISALIGNMENT (dr,
! 		       wi::mod_floor (misalign, alignment, SIGNED).to_uhwi ());
  
    if (dump_enabled_p ())
      {
Index: gcc/testsuite/gcc.dg/vect/pr65310.c
===================================================================
*** gcc/testsuite/gcc.dg/vect/pr65310.c	(revision 0)
--- gcc/testsuite/gcc.dg/vect/pr65310.c	(working copy)
***************
*** 0 ****
--- 1,23 ----
+ /* { dg-do compile } */
+ 
+ struct a 
+ {
+   int a[100];
+ };
+ typedef struct a b __attribute__ ((aligned (32)));
+ typedef struct a c __attribute__ ((aligned (8)));
+ 
+ int t(b *a)
+ {
+   int i;
+   c *ptr = a;
+   for (i=0;i<100;i++)
+     ptr->a[i]++;
+ }
+ 
+ /* The memory access is through a pointer of type c which means
+    *ptr is not aligned.  */
+ 
+ /* { dg-final { scan-tree-dump "can't force alignment" "vect" } } */
+ /* { dg-final { scan-tree-dump-not "misalign = 0" "vect" } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]