This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR65310
- From: Richard Biener <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 4 Mar 2015 14:32:59 +0100 (CET)
- Subject: [PATCH] Fix PR65310
- Authentication-results: sourceware.org; auth=none
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" } } */