Hi, the attached patch is a start at cleaning up tree-vect-data-refs.c. I refactored some stuff I found strange and/or difficult to understand. Probably more to come.
The misalignment calculation in vect_compute_data_ref_alignment seems quite coarse, is there any work planned for the future? No regressions on s390x and amd64. Regards Robin -- gcc/ChangeLog: 2016-04-13 Robin Dapp <rd...@linux.vnet.ibm.com> * tree-vectorizer.h (dr_misalignment): Introduce named DR_MISALIGNMENT constants. (aligned_access_p): Use constants. (known_alignment_for_access_p): Likewise. * tree-vect-data-refs.c (vect_compute_data_ref_alignment): Improve output messages and cleanup. (vect_duplicate_ssa_name_ptr_info): Use new constants. (vect_enhance_data_refs_alignment): Likewise. (vect_supportable_dr_alignment): Likewise. (vect_update_misalignment_for_peel): Likewise. gcc/testsuite/ChangeLog: 2016-04-13 Robin Dapp <rd...@linux.vnet.ibm.com> * gcc.dg/vect/vect-outer-3a-big-array.c: Use new output message. * gcc.dg/vect/vect-outer-3a.c: Likewise.
diff --git a/gcc/testsuite/gcc.dg/vect/vect-outer-3a-big-array.c b/gcc/testsuite/gcc.dg/vect/vect-outer-3a-big-array.c index 1316e80..d9bfcdf 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-outer-3a-big-array.c +++ b/gcc/testsuite/gcc.dg/vect/vect-outer-3a-big-array.c @@ -49,4 +49,4 @@ int main (void) } /* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" { xfail { vect_no_align && { ! vect_hw_misalign } } } } } */ -/* { dg-final { scan-tree-dump-times "step doesn't divide the vector-size" 1 "vect" } } */ +/* { dg-final { scan-tree-dump-times "step is not a multiple of the vector size" 1 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-outer-3a.c b/gcc/testsuite/gcc.dg/vect/vect-outer-3a.c index 6a7ab91..7030a64 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-outer-3a.c +++ b/gcc/testsuite/gcc.dg/vect/vect-outer-3a.c @@ -49,4 +49,4 @@ int main (void) } /* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" { xfail { vect_no_align && { ! vect_hw_misalign } } } } } */ -/* { dg-final { scan-tree-dump-times "step doesn't divide the vector-size" 1 "vect" } } */ +/* { dg-final { scan-tree-dump-times "step is not a multiple of the vector size" 1 "vect" } } */ diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c index f8695b1..3c9cef4 100644 --- a/gcc/tree-vect-data-refs.c +++ b/gcc/tree-vect-data-refs.c @@ -689,10 +689,9 @@ vect_compute_data_ref_alignment (struct data_reference *dr) struct loop *loop = NULL; tree ref = DR_REF (dr); tree vectype; - tree base, base_addr; - tree misalign = NULL_TREE; - tree aligned_to; - unsigned HOST_WIDE_INT alignment; + tree base_addr; + tree misalign; + tree dr_alignment; if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, @@ -702,11 +701,13 @@ vect_compute_data_ref_alignment (struct data_reference *dr) loop = LOOP_VINFO_LOOP (loop_vinfo); /* Initialize misalignment to unknown. */ - SET_DR_MISALIGNMENT (dr, -1); + SET_DR_MISALIGNMENT (dr, DR_MISALIGNMENT_UNKNOWN); - if (tree_fits_shwi_p (DR_STEP (dr))) + misalign = NULL_TREE; + tree step = DR_STEP (dr); + if (tree_fits_shwi_p (step)) misalign = DR_INIT (dr); - aligned_to = DR_ALIGNED_TO (dr); + dr_alignment = DR_ALIGNED_TO (dr); base_addr = DR_BASE_ADDRESS (dr); vectype = STMT_VINFO_VECTYPE (stmt_info); @@ -714,27 +715,25 @@ vect_compute_data_ref_alignment (struct data_reference *dr) vectorized (LOOP), we use the base and misalignment information relative to the outer-loop (LOOP). This is ok only if the misalignment stays the same throughout the execution of the inner-loop, which is why - we have to check that the stride of the dataref in the inner-loop evenly - divides by the vector size. */ + we have to check that the stride of the dataref in the inner-loop is a + multiple of the vector size. */ if (loop && nested_in_vect_loop_p (loop, stmt)) { - tree step = DR_STEP (dr); - if (tree_fits_shwi_p (step) && tree_to_shwi (step) % GET_MODE_SIZE (TYPE_MODE (vectype)) == 0) { if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, - "inner step divides the vector-size.\n"); + "inner step is a multiple of the vector size.\n"); misalign = STMT_VINFO_DR_INIT (stmt_info); - aligned_to = STMT_VINFO_DR_ALIGNED_TO (stmt_info); + dr_alignment = STMT_VINFO_DR_ALIGNED_TO (stmt_info); base_addr = STMT_VINFO_DR_BASE_ADDRESS (stmt_info); } else { if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "inner step doesn't divide the vector-size.\n"); + "inner step is not a multiple of the vector size.\n"); misalign = NULL_TREE; } } @@ -742,10 +741,9 @@ vect_compute_data_ref_alignment (struct data_reference *dr) /* Similarly we can only use base and misalignment information relative to an innermost loop if the misalignment stays the same throughout the execution of the loop. As above, this is the case if the stride of - the dataref evenly divides by the vector size. */ + the dataref is a multiple of the vector size. */ else { - tree step = DR_STEP (dr); unsigned vf = loop ? LOOP_VINFO_VECT_FACTOR (loop_vinfo) : 1; if (tree_fits_shwi_p (step) @@ -754,14 +752,14 @@ vect_compute_data_ref_alignment (struct data_reference *dr) { if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "step doesn't divide the vector-size.\n"); + "step is not a multiple of the vector size.\n"); misalign = NULL_TREE; } } - /* To look at alignment of the base we have to preserve an inner MEM_REF + /* To look at the alignment of the base we have to preserve an inner MEM_REF as that carries alignment information of the actual access. */ - base = ref; + tree base = ref; while (handled_component_p (base)) base = TREE_OPERAND (base, 0); if (TREE_CODE (base) == MEM_REF) @@ -769,12 +767,14 @@ vect_compute_data_ref_alignment (struct data_reference *dr) build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)), 0)); unsigned int base_alignment = get_object_alignment (base); - if (base_alignment >= TYPE_ALIGN (TREE_TYPE (vectype))) - DR_VECT_AUX (dr)->base_element_aligned = true; + unsigned HOST_WIDE_INT vectype_align = TYPE_ALIGN (vectype); + unsigned HOST_WIDE_INT vectype_elt_align = TYPE_ALIGN (TREE_TYPE (vectype)); + unsigned HOST_WIDE_INT vectype_align_unit = TYPE_ALIGN_UNIT (vectype); - alignment = TYPE_ALIGN_UNIT (vectype); + if (base_alignment >= vectype_elt_align) + DR_VECT_AUX (dr)->base_element_aligned = true; - if ((compare_tree_int (aligned_to, alignment) < 0) + if ((compare_tree_int (dr_alignment, vectype_align_unit) < 0) || !misalign) { if (dump_enabled_p ()) @@ -787,7 +787,7 @@ vect_compute_data_ref_alignment (struct data_reference *dr) return true; } - if (base_alignment < TYPE_ALIGN (vectype)) + if (base_alignment < vectype_align) { /* Strip an inner MEM_REF to a bare decl if possible. */ if (TREE_CODE (base) == MEM_REF @@ -795,7 +795,7 @@ vect_compute_data_ref_alignment (struct data_reference *dr) && TREE_CODE (TREE_OPERAND (base, 0)) == ADDR_EXPR) base = TREE_OPERAND (TREE_OPERAND (base, 0), 0); - if (!vect_can_force_dr_alignment_p (base, TYPE_ALIGN (vectype))) + if (!vect_can_force_dr_alignment_p (base, vectype_align)) { if (dump_enabled_p ()) { @@ -825,18 +825,18 @@ vect_compute_data_ref_alignment (struct data_reference *dr) /* 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) + if (tree_int_cst_sgn (step) < 0) { tree offset = ssize_int (TYPE_VECTOR_SUBPARTS (vectype) - 1); /* DR_STEP(dr) is the same as -TYPE_SIZE of the scalar type, otherwise we wouldn't be here. */ - offset = fold_build2 (MULT_EXPR, ssizetype, offset, DR_STEP (dr)); + offset = fold_build2 (MULT_EXPR, ssizetype, offset, step); /* PLUS because DR_STEP was negative. */ misalign = size_binop (PLUS_EXPR, misalign, offset); } - SET_DR_MISALIGNMENT (dr, - wi::mod_floor (misalign, alignment, SIGNED).to_uhwi ()); + SET_DR_MISALIGNMENT (dr, wi::mod_floor + (misalign, vectype_align_unit, SIGNED).to_uhwi ()); if (dump_enabled_p ()) { @@ -887,7 +887,7 @@ vect_update_misalignment_for_peel (struct data_reference *dr, continue; gcc_assert (DR_MISALIGNMENT (dr) / dr_size == DR_MISALIGNMENT (dr_peel) / dr_peel_size); - SET_DR_MISALIGNMENT (dr, 0); + SET_DR_MISALIGNMENT (dr, DR_MISALIGNMENT_NONE); return; } @@ -904,8 +904,9 @@ vect_update_misalignment_for_peel (struct data_reference *dr, } if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, "Setting misalignment to -1.\n"); - SET_DR_MISALIGNMENT (dr, -1); + dump_printf_loc (MSG_NOTE, vect_location, + "Setting misalignment to UNKNOWN (-1).\n"); + SET_DR_MISALIGNMENT (dr, DR_MISALIGNMENT_UNKNOWN); } @@ -1843,7 +1844,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) else LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) = DR_MISALIGNMENT (dr0); - SET_DR_MISALIGNMENT (dr0, 0); + SET_DR_MISALIGNMENT (dr0, DR_MISALIGNMENT_NONE); if (dump_enabled_p ()) { dump_printf_loc (MSG_NOTE, vect_location, @@ -1960,7 +1961,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) { stmt_vec_info stmt_info = vinfo_for_stmt (stmt); dr = STMT_VINFO_DATA_REF (stmt_info); - SET_DR_MISALIGNMENT (dr, 0); + SET_DR_MISALIGNMENT (dr, DR_MISALIGNMENT_NONE); if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "Alignment of access forced using versioning.\n"); @@ -4022,7 +4023,7 @@ vect_duplicate_ssa_name_ptr_info (tree name, data_reference *dr, duplicate_ssa_name_ptr_info (name, DR_PTR_INFO (dr)); unsigned int align = TYPE_ALIGN_UNIT (STMT_VINFO_VECTYPE (stmt_info)); int misalign = DR_MISALIGNMENT (dr); - if (misalign == -1) + if (misalign == DR_MISALIGNMENT_UNKNOWN) mark_ptr_info_alignment_unknown (SSA_NAME_PTR_INFO (name)); else set_ptr_info_alignment (SSA_NAME_PTR_INFO (name), align, misalign); @@ -5877,9 +5878,8 @@ vect_can_force_dr_alignment_p (const_tree decl, unsigned int alignment) /* Return whether the data reference DR is supported with respect to its alignment. - If CHECK_ALIGNED_ACCESSES is TRUE, check if the access is supported even - it is aligned, i.e., check if it is possible to vectorize it with different - alignment. */ + If CHECK_ALIGNED_ACCESSES is TRUE, check if it is possible to vectorize + the already aligned DR with a different alignment. */ enum dr_alignment_support vect_supportable_dr_alignment (struct data_reference *dr, @@ -5973,11 +5973,14 @@ vect_supportable_dr_alignment (struct data_reference *dr, } } */ + bool is_packed = false; + tree type = (TREE_TYPE (DR_REF (dr))); + + if (!known_alignment_for_access_p (dr)) + is_packed = not_size_aligned (DR_REF (dr)); + if (DR_IS_READ (dr)) { - bool is_packed = false; - tree type = (TREE_TYPE (DR_REF (dr))); - if (optab_handler (vec_realign_load_optab, mode) != CODE_FOR_nothing && (!targetm.vectorize.builtin_mask_for_load || targetm.vectorize.builtin_mask_for_load ())) @@ -5991,30 +5994,14 @@ vect_supportable_dr_alignment (struct data_reference *dr, else return dr_explicit_realign_optimized; } - if (!known_alignment_for_access_p (dr)) - is_packed = not_size_aligned (DR_REF (dr)); - - if ((TYPE_USER_ALIGN (type) && !is_packed) - || targetm.vectorize. - support_vector_misalignment (mode, type, - DR_MISALIGNMENT (dr), is_packed)) - /* Can't software pipeline the loads, but can at least do them. */ - return dr_unaligned_supported; } - else - { - bool is_packed = false; - tree type = (TREE_TYPE (DR_REF (dr))); - if (!known_alignment_for_access_p (dr)) - is_packed = not_size_aligned (DR_REF (dr)); - - if ((TYPE_USER_ALIGN (type) && !is_packed) - || targetm.vectorize. - support_vector_misalignment (mode, type, - DR_MISALIGNMENT (dr), is_packed)) - return dr_unaligned_supported; - } + if ((TYPE_USER_ALIGN (type) && !is_packed) + || targetm.vectorize. + support_vector_misalignment (mode, type, + DR_MISALIGNMENT (dr), is_packed)) + /* Can't software pipeline the loads, but can at least do them. */ + return dr_unaligned_supported; /* Unsupported. */ return dr_unaligned_unsupported; diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index bd1d55a..c0b17c0 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -911,12 +911,15 @@ dr_misalignment (struct data_reference *dr) #define DR_MISALIGNMENT(DR) dr_misalignment (DR) #define SET_DR_MISALIGNMENT(DR, VAL) set_dr_misalignment (DR, VAL) +#define DR_MISALIGNMENT_UNKNOWN (-1) +#define DR_MISALIGNMENT_NONE (0) + /* Return TRUE if the data access is aligned, and FALSE otherwise. */ static inline bool aligned_access_p (struct data_reference *data_ref_info) { - return (DR_MISALIGNMENT (data_ref_info) == 0); + return (DR_MISALIGNMENT (data_ref_info) == DR_MISALIGNMENT_NONE); } /* Return TRUE if the alignment of the data access is known, and FALSE @@ -925,7 +928,7 @@ aligned_access_p (struct data_reference *data_ref_info) static inline bool known_alignment_for_access_p (struct data_reference *data_ref_info) { - return (DR_MISALIGNMENT (data_ref_info) != -1); + return (DR_MISALIGNMENT (data_ref_info) != DR_MISALIGNMENT_UNKNOWN); }