From 550fa0931855ee93f340dee752a8bb9b1a70cbc5 Mon Sep 17 00:00:00 2001 From: Prathamesh Kulkarni Date: Fri, 20 May 2016 09:35:46 +0000 Subject: [PATCH] tree-vectorizer.c (get_vec_alignment_for_decl): New static function. 2016-05-20 Prathamesh Kulkarni * tree-vectorizer.c (get_vec_alignment_for_decl): New static function. (get_vec_alignment_for_array_decl): Likewise. (get_vec_alignment_for_record_decl): Likewise. (increase_alignment::execute): Move code to find alignment to get_vec_alignment_for_array_decl and call get_vec_alignment_for_decl. (type_align_map): New hash_map. testsuite/ * gcc.dg/vect/section-anchors-vect-70.c: New test-case. * gcc.dg/vect/section-anchors-vect-71.c: Likewise. * gcc.dg/vect/section-anchors-vect-72.c: Likewise. From-SVN: r236502 --- gcc/ChangeLog | 9 +++ gcc/testsuite/ChangeLog | 6 ++ gcc/tree-vectorizer.c | 132 +++++++++++++++++++++++++++++++++++----- 3 files changed, 133 insertions(+), 14 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d40ec666567..c6b2a23159d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2016-05-20 Prathamesh Kulkarni + + * tree-vectorizer.c (get_vec_alignment_for_decl): New static function. + (get_vec_alignment_for_array_decl): Likewise. + (get_vec_alignment_for_record_decl): Likewise. + (increase_alignment::execute): Move code to find alignment to + get_vec_alignment_for_array_decl and call get_vec_alignment_for_decl. + (type_align_map): New hash_map. + 2016-05-20 Richard Guenther PR tree-optimization/29756 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2d061d08819..fa29e0cb4c0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2016-05-20 Prathamesh Kulkarni + + * gcc.dg/vect/section-anchors-vect-70.c: New test-case. + * gcc.dg/vect/section-anchors-vect-71.c: Likewise. + * gcc.dg/vect/section-anchors-vect-72.c: Likewise. + 2016-05-20 Richard Guenther PR tree-optimization/29756 diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c index 2b25b4503ac..26698135f54 100644 --- a/gcc/tree-vectorizer.c +++ b/gcc/tree-vectorizer.c @@ -794,38 +794,142 @@ make_pass_slp_vectorize (gcc::context *ctxt) This should involve global alignment analysis and in the future also array padding. */ +static unsigned get_vec_alignment_for_type (tree); +static hash_map *type_align_map; + +/* Return alignment of array's vector type corresponding to scalar type. + 0 if no vector type exists. */ +static unsigned +get_vec_alignment_for_array_type (tree type) +{ + gcc_assert (TREE_CODE (type) == ARRAY_TYPE); + + tree vectype = get_vectype_for_scalar_type (strip_array_types (type)); + if (!vectype + || !TYPE_SIZE (type) + || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST + || tree_int_cst_lt (TYPE_SIZE (type), TYPE_SIZE (vectype))) + return 0; + + return TYPE_ALIGN (vectype); +} + +/* Return alignment of field having maximum alignment of vector type + corresponding to it's scalar type. For now, we only consider fields whose + offset is a multiple of it's vector alignment. + 0 if no suitable field is found. */ +static unsigned +get_vec_alignment_for_record_type (tree type) +{ + gcc_assert (TREE_CODE (type) == RECORD_TYPE); + + unsigned max_align = 0, alignment; + HOST_WIDE_INT offset; + tree offset_tree; + + if (TYPE_PACKED (type)) + return 0; + + unsigned *slot = type_align_map->get (type); + if (slot) + return *slot; + + for (tree field = first_field (type); + field != NULL_TREE; + field = DECL_CHAIN (field)) + { + /* Skip if not FIELD_DECL or if alignment is set by user. */ + if (TREE_CODE (field) != FIELD_DECL + || DECL_USER_ALIGN (field) + || DECL_ARTIFICIAL (field)) + continue; + + /* We don't need to process the type further if offset is variable, + since the offsets of remaining members will also be variable. */ + if (TREE_CODE (DECL_FIELD_OFFSET (field)) != INTEGER_CST + || TREE_CODE (DECL_FIELD_BIT_OFFSET (field)) != INTEGER_CST) + break; + + /* Similarly stop processing the type if offset_tree + does not fit in unsigned HOST_WIDE_INT. */ + offset_tree = bit_position (field); + if (!tree_fits_uhwi_p (offset_tree)) + break; + + offset = tree_to_uhwi (offset_tree); + alignment = get_vec_alignment_for_type (TREE_TYPE (field)); + + /* Get maximum alignment of vectorized field/array among those members + whose offset is multiple of the vector alignment. */ + if (alignment + && (offset % alignment == 0) + && (alignment > max_align)) + max_align = alignment; + } + + type_align_map->put (type, max_align); + return max_align; +} + +/* Return alignment of vector type corresponding to decl's scalar type + or 0 if it doesn't exist or the vector alignment is lesser than + decl's alignment. */ +static unsigned +get_vec_alignment_for_type (tree type) +{ + if (type == NULL_TREE) + return 0; + + gcc_assert (TYPE_P (type)); + + static unsigned alignment = 0; + switch (TREE_CODE (type)) + { + case ARRAY_TYPE: + alignment = get_vec_alignment_for_array_type (type); + break; + case RECORD_TYPE: + alignment = get_vec_alignment_for_record_type (type); + break; + default: + alignment = 0; + break; + } + + return (alignment > TYPE_ALIGN (type)) ? alignment : 0; +} + +/* Entry point to increase_alignment pass. */ static unsigned int increase_alignment (void) { varpool_node *vnode; vect_location = UNKNOWN_LOCATION; + type_align_map = new hash_map; /* Increase the alignment of all global arrays for vectorization. */ FOR_EACH_DEFINED_VARIABLE (vnode) { - tree vectype, decl = vnode->decl; - tree t; + tree decl = vnode->decl; unsigned int alignment; - t = TREE_TYPE (decl); - if (TREE_CODE (t) != ARRAY_TYPE) - continue; - vectype = get_vectype_for_scalar_type (strip_array_types (t)); - if (!vectype) - continue; - alignment = TYPE_ALIGN (vectype); - if (DECL_ALIGN (decl) >= alignment) - continue; - - if (vect_can_force_dr_alignment_p (decl, alignment)) + if ((decl_in_symtab_p (decl) + && !symtab_node::get (decl)->can_increase_alignment_p ()) + || DECL_USER_ALIGN (decl) || DECL_ARTIFICIAL (decl)) + continue; + + alignment = get_vec_alignment_for_type (TREE_TYPE (decl)); + if (alignment && vect_can_force_dr_alignment_p (decl, alignment)) { - vnode->increase_alignment (TYPE_ALIGN (vectype)); + vnode->increase_alignment (alignment); dump_printf (MSG_NOTE, "Increasing alignment of decl: "); dump_generic_expr (MSG_NOTE, TDF_SLIM, decl); dump_printf (MSG_NOTE, "\n"); } } + + delete type_align_map; return 0; } -- 2.30.2