@@ -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 \
new file mode 100644
@@ -0,0 +1,223 @@
+/* Increase alignment
+ Copyright (C) 2003-2020 Free Software Foundation, Inc.
+ Contributed by Dorit Naishlos <dorit@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;
+}
+
+/* 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);
+}
@@ -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. */