Hi Richard: The local variable alignment adjustment was removed at this commit: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=26d7a5e690169ac04acde90070b0092c41b71c7e
And it's a little bit indirectly, it called from estimate_stack_frame_size, call stack like: estimate_stack_frame_size -> expand_one_var -> add_stack_var -> align_local_variable I created a new pass for local variable alignment adjustment, and then Andrew Pinski suggest me can added into ipa_increase_alignment, because that doing similar things but for global variable. However the ipa_increase_alignment belong tree-vectorizer.c, which is weird place to adjust local variable alignment, so I moved out into a new file, so do you think just create a stand alone simple pass for doing that is better than this way? Thanks :) On Fri, Mar 27, 2020 at 8:33 PM Richard Biener <richard.guent...@gmail.com> wrote: > > On Fri, Mar 27, 2020 at 1:28 PM Kito Cheng <kito.ch...@sifive.com> wrote: > > > > - The alignment for local variable was adjust during > > estimate_stack_frame_size, > > however it seems wrong spot to adjust that. > > > > - So we must adjust at some point, and here is already a pass to adjust > > alignment, which is ipa-increase-alignment, used for tree vectorization. > > > > - We move out the pass from tree-vectorizer.c into > > ipa-increase-alignment.cc. > > > > - This patch fix gfortran.dg/pr45636.f90 for arm and riscv. > > > > - Regression test on riscv32/riscv64 and x86_64-linux-gnu, no new fail > > introduced. > > Sorry, but the diff is completely illegible due to the move to a different > file. > > I also dont' see that you remove local variable alignment adjustment from > estimate_stack_frame_size (but I would agree that adjusting there is wrong). > > Please do not move the code and re-post. > > Richard. > > > gcc/ChangeLog > > > > PR target/90811 > > * Makefile.in (OBJS): Add ipa-increase-alignment.o. > > * tree-vectorizer.c (get_vec_alignment_for_type): Moved to > > ipa-increase-alignment.cc. > > (type_align_map): Ditto. > > (get_vec_alignment_for_array_type): Ditto. > > (get_vec_alignment_for_record_type): Ditto. > > (increase_alignment): Ditto. > > (pass_data_ipa_increase_alignment): Ditto. > > (pass_ipa_increase_alignment): Ditto. > > (make_pass_ipa_increase_alignment): Ditto. > > * ipa-increase-alignment.cc (get_vec_alignment_for_type) Moved > > from ipa-increase-alignment.cc. > > (type_align_map): Ditto. > > (get_vec_alignment_for_array_type): Ditto. > > (get_vec_alignment_for_record_type): Ditto. > > (increase_alignment): Ditto. > > (pass_data_ipa_increase_alignment): Ditto. > > (pass_ipa_increase_alignment): Ditto. > > (make_pass_ipa_increase_alignment): Ditto. > > (increase_alignment): New. > > (increase_alignment_local_var): New. > > (increase_alignment_global_var): New. > > --- > > gcc/Makefile.in | 1 + > > gcc/ipa-increase-alignment.cc | 251 ++++++++++++++++++++++++++++++++++ > > gcc/tree-vectorizer.c | 189 ------------------------- > > 3 files changed, 252 insertions(+), 189 deletions(-) > > create mode 100644 gcc/ipa-increase-alignment.cc > > > > diff --git a/gcc/Makefile.in b/gcc/Makefile.in > > index fa9923bb270..2c11252911c 100644 > > --- a/gcc/Makefile.in > > +++ b/gcc/Makefile.in > > @@ -1408,6 +1408,7 @@ OBJS = \ > > ipa-inline.o \ > > ipa-comdats.o \ > > ipa-visibility.o \ > > + ipa-increase-alignment.o \ > > ipa-inline-analysis.o \ > > ipa-inline-transform.o \ > > ipa-predicate.o \ > > diff --git a/gcc/ipa-increase-alignment.cc b/gcc/ipa-increase-alignment.cc > > new file mode 100644 > > index 00000000000..d09917c185f > > --- /dev/null > > +++ b/gcc/ipa-increase-alignment.cc > > @@ -0,0 +1,251 @@ > > +/* Vectorizer > > + Copyright (C) 2003-2020 Free Software Foundation, Inc. > > + Contributed by Dorit Naishlos <do...@il.ibm.com> > > + > > +This file is part of GCC. > > + > > +GCC is free software; you can redistribute it and/or modify it under > > +the terms of the GNU General Public License as published by the Free > > +Software Foundation; either version 3, or (at your option) any later > > +version. > > + > > +GCC is distributed in the hope that it will be useful, but WITHOUT ANY > > +WARRANTY; without even the implied warranty of MERCHANTABILITY or > > +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License > > +for more details. > > + > > +You should have received a copy of the GNU General Public License > > +along with GCC; see the file COPYING3. If not see > > +<http://www.gnu.org/licenses/>. */ > > + > > +#include "config.h" > > +#include "system.h" > > +#include "coretypes.h" > > +#include "backend.h" > > +#include "target.h" > > +#include "tree.h" > > +#include "gimple.h" > > +#include "tree-pass.h" > > +#include "cgraph.h" > > +#include "fold-const.h" > > +#include "gimple-iterator.h" > > +#include "tree-cfg.h" > > +#include "cfgloop.h" > > +#include "tree-vectorizer.h" > > +#include "tm_p.h" > > + > > + > > +/* Increase alignment of global arrays to improve vectorization potential. > > + TODO: > > + - Consider also structs that have an array field. > > + - Use ipa analysis to prune arrays that can't be vectorized? > > + This should involve global alignment analysis and in the future also > > + array padding. */ > > + > > +static unsigned get_vec_alignment_for_type (tree); > > +static hash_map<tree, unsigned> *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); > > + poly_uint64 array_size, vector_size; > > + > > + tree scalar_type = strip_array_types (type); > > + tree vectype = get_related_vectype_for_scalar_type (VOIDmode, > > scalar_type); > > + if (!vectype > > + || !poly_int_tree_p (TYPE_SIZE (type), &array_size) > > + || !poly_int_tree_p (TYPE_SIZE (vectype), &vector_size) > > + || maybe_lt (array_size, vector_size)) > > + 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; > > +} > > + > > +/* Adjust alignment for local variable. */ > > +static void > > +increase_alignment_local_var (void) > > +{ > > + size_t i; > > + tree var; > > + struct cgraph_node *node; > > + unsigned int align; > > + > > + FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) > > + { > > + function *fun = node->get_fun (); > > + FOR_EACH_LOCAL_DECL (fun, i, var) > > + { > > + align = LOCAL_DECL_ALIGNMENT (var); > > + > > + SET_DECL_ALIGN (var, align); > > + } > > + } > > +} > > + > > +/* Adjust alignment for global variable, only used for tree vectorization > > + currently. */ > > +static void > > +increase_alignment_global_var (void) > > +{ > > + if (!(flag_section_anchors && flag_tree_loop_vectorize)) > > + return; > > + > > + varpool_node *vnode; > > + > > + vect_location = dump_user_location_t (); > > + type_align_map = new hash_map<tree, unsigned>; > > + > > + /* Increase the alignment of all global arrays for vectorization. */ > > + FOR_EACH_DEFINED_VARIABLE (vnode) > > + { > > + tree decl = vnode->decl; > > + unsigned int 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 (alignment); > > + if (dump_enabled_p ()) > > + dump_printf (MSG_NOTE, "Increasing alignment of decl: %T\n", > > decl); > > + } > > + } > > + > > + delete type_align_map; > > +} > > + > > +/* Entry point to increase_alignment pass. */ > > +static unsigned int > > +increase_alignment (void) > > +{ > > + increase_alignment_local_var (); > > + increase_alignment_global_var (); > > + return 0; > > +} > > + > > + > > +namespace { > > + > > +const pass_data pass_data_ipa_increase_alignment = > > +{ > > + SIMPLE_IPA_PASS, /* type */ > > + "increase_alignment", /* name */ > > + OPTGROUP_LOOP | OPTGROUP_VEC, /* optinfo_flags */ > > + TV_IPA_OPT, /* tv_id */ > > + 0, /* properties_required */ > > + 0, /* properties_provided */ > > + 0, /* properties_destroyed */ > > + 0, /* todo_flags_start */ > > + 0, /* todo_flags_finish */ > > +}; > > + > > +class pass_ipa_increase_alignment : public simple_ipa_opt_pass > > +{ > > +public: > > + pass_ipa_increase_alignment (gcc::context *ctxt) > > + : simple_ipa_opt_pass (pass_data_ipa_increase_alignment, ctxt) > > + {} > > + > > + virtual unsigned int execute (function *) { return increase_alignment > > (); } > > + > > +}; // class pass_ipa_increase_alignment > > + > > +} // anon namespace > > + > > +simple_ipa_opt_pass * > > +make_pass_ipa_increase_alignment (gcc::context *ctxt) > > +{ > > + return new pass_ipa_increase_alignment (ctxt); > > +} > > diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c > > index 8f9444d58a3..e9caf91e174 100644 > > --- a/gcc/tree-vectorizer.c > > +++ b/gcc/tree-vectorizer.c > > @@ -1340,195 +1340,6 @@ make_pass_slp_vectorize (gcc::context *ctxt) > > return new pass_slp_vectorize (ctxt); > > } > > > > - > > -/* Increase alignment of global arrays to improve vectorization potential. > > - TODO: > > - - Consider also structs that have an array field. > > - - Use ipa analysis to prune arrays that can't be vectorized? > > - This should involve global alignment analysis and in the future also > > - array padding. */ > > - > > -static unsigned get_vec_alignment_for_type (tree); > > -static hash_map<tree, unsigned> *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); > > - poly_uint64 array_size, vector_size; > > - > > - tree scalar_type = strip_array_types (type); > > - tree vectype = get_related_vectype_for_scalar_type (VOIDmode, > > scalar_type); > > - if (!vectype > > - || !poly_int_tree_p (TYPE_SIZE (type), &array_size) > > - || !poly_int_tree_p (TYPE_SIZE (vectype), &vector_size) > > - || maybe_lt (array_size, vector_size)) > > - 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 = dump_user_location_t (); > > - type_align_map = new hash_map<tree, unsigned>; > > - > > - /* Increase the alignment of all global arrays for vectorization. */ > > - FOR_EACH_DEFINED_VARIABLE (vnode) > > - { > > - tree decl = vnode->decl; > > - unsigned int 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 (alignment); > > - if (dump_enabled_p ()) > > - dump_printf (MSG_NOTE, "Increasing alignment of decl: %T\n", > > decl); > > - } > > - } > > - > > - delete type_align_map; > > - return 0; > > -} > > - > > - > > -namespace { > > - > > -const pass_data pass_data_ipa_increase_alignment = > > -{ > > - SIMPLE_IPA_PASS, /* type */ > > - "increase_alignment", /* name */ > > - OPTGROUP_LOOP | OPTGROUP_VEC, /* optinfo_flags */ > > - TV_IPA_OPT, /* tv_id */ > > - 0, /* properties_required */ > > - 0, /* properties_provided */ > > - 0, /* properties_destroyed */ > > - 0, /* todo_flags_start */ > > - 0, /* todo_flags_finish */ > > -}; > > - > > -class pass_ipa_increase_alignment : public simple_ipa_opt_pass > > -{ > > -public: > > - pass_ipa_increase_alignment (gcc::context *ctxt) > > - : simple_ipa_opt_pass (pass_data_ipa_increase_alignment, ctxt) > > - {} > > - > > - /* opt_pass methods: */ > > - virtual bool gate (function *) > > - { > > - return flag_section_anchors && flag_tree_loop_vectorize; > > - } > > - > > - virtual unsigned int execute (function *) { return increase_alignment > > (); } > > - > > -}; // class pass_ipa_increase_alignment > > - > > -} // anon namespace > > - > > -simple_ipa_opt_pass * > > -make_pass_ipa_increase_alignment (gcc::context *ctxt) > > -{ > > - return new pass_ipa_increase_alignment (ctxt); > > -} > > - > > /* If the condition represented by T is a comparison or the SSA name > > result of a comparison, extract the comparison's operands. Represent > > T as NE_EXPR <T, 0> otherwise. */ > > -- > > 2.25.2 > >