tree-vectorizer.c (get_vec_alignment_for_decl): New static function.
authorPrathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
Fri, 20 May 2016 09:35:46 +0000 (09:35 +0000)
committerPrathamesh Kulkarni <prathamesh3492@gcc.gnu.org>
Fri, 20 May 2016 09:35:46 +0000 (09:35 +0000)
2016-05-20  Prathamesh Kulkarni  <prathamesh.kulkarni@linaro.org>

* 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
gcc/testsuite/ChangeLog
gcc/tree-vectorizer.c

index d40ec66656794246de928dd0a4ead91b3049cbf9..c6b2a23159d04a0e32298df6df9c079cb341c1d0 100644 (file)
@@ -1,3 +1,12 @@
+2016-05-20  Prathamesh Kulkarni  <prathamesh.kulkarni@linaro.org>
+
+       * 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  <rguenther@suse.de>
 
        PR tree-optimization/29756
index 2d061d08819871b14823d75398ad881fd473fb59..fa29e0cb4c0dc49c43f1b2649a46ceb0a17f06ce 100644 (file)
@@ -1,3 +1,9 @@
+2016-05-20  Prathamesh Kulkarni  <prathamesh.kulkarni@linaro.org>
+
+       * 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  <rguenther@suse.de>
 
        PR tree-optimization/29756
index 2b25b4503ac3323f360b3245645b0e0b4ba38e17..26698135f541575f0bbf75ba06ae652dfbd9f55c 100644 (file)
@@ -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<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);
+
+  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<tree, unsigned>;
 
   /* 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;
 }