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 <rguent...@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" } } */