gcc/
authorChristophe Lyon <christophe.lyon@linaro.org>
Tue, 30 Aug 2016 15:13:28 +0000 (17:13 +0200)
committerYvan Roux <yvan.roux@linaro.org>
Wed, 7 Sep 2016 20:08:00 +0000 (22:08 +0200)
Backport from trunk r236502.
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.

gcc/testsuite/
Backport from trunk r236502, r236503.
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.

gcc/testsuite/
Backport from trunk r237207.
2016-06-08  Prathamesh Kulkarni  <prathamesh.kulkarni@linaro.org>

* gcc.dg/vect/section-anchors-vect-70.c: Rename to aligned-section-anchors-vect-71.c.
* gcc.dg/vect/section-anchors-vect-71.c: Rename to aligned-section-anchors-vect-72.c.
* gcc.dg/vect/section-anchors-vect-72.c: Rename to aligned-section-anchors-vect-72.c.

Change-Id: I71a89ccfbb98e1a7976f74875fa954d1f0f365a9

gcc/testsuite/gcc.dg/vect/aligned-section-anchors-vect-70.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/aligned-section-anchors-vect-71.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/aligned-section-anchors-vect-72.c [new file with mode: 0644]
gcc/tree-vectorizer.c

diff --git a/gcc/testsuite/gcc.dg/vect/aligned-section-anchors-vect-70.c b/gcc/testsuite/gcc.dg/vect/aligned-section-anchors-vect-70.c
new file mode 100644 (file)
index 0000000..7010a52
--- /dev/null
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target section_anchors } */
+/* { dg-require-effective-target vect_int } */
+
+#define N 32
+
+/* Increase alignment of struct if an array's offset is multiple of alignment of
+   vector type corresponding to it's scalar type.
+   For the below test-case:
+   offsetof(e) == 8 bytes. 
+   i) For arm: let x = alignment of vector type corresponding to int,
+   x == 8 bytes.
+   Since offsetof(e) % x == 0, set DECL_ALIGN(a, b, c) to x.
+   ii) For aarch64, ppc: x == 16 bytes.
+   Since offsetof(e) % x != 0, don't increase alignment of a, b, c.
+*/
+
+static struct A {
+  int p1, p2;
+  int e[N];
+} a, b, c;
+
+int foo(void)
+{
+  for (int i = 0; i < N; i++)
+    a.e[i] = b.e[i] + c.e[i];
+
+   return a.e[0];
+}
+
+/* { dg-final { scan-ipa-dump-times "Increasing alignment of decl" 0 "increase_alignment" { target aarch64*-*-* } } } */
+/* { dg-final { scan-ipa-dump-times "Increasing alignment of decl" 0 "increase_alignment" { target powerpc64*-*-* } } } */
+/* { dg-final { scan-ipa-dump-times "Increasing alignment of decl" 3 "increase_alignment" { target arm*-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/aligned-section-anchors-vect-71.c b/gcc/testsuite/gcc.dg/vect/aligned-section-anchors-vect-71.c
new file mode 100644 (file)
index 0000000..7cbd1dc
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target section_anchors } */
+/* { dg-require-effective-target vect_int } */
+
+/* Should not increase alignment of the struct because
+   sizeof (A.e) < sizeof(corresponding vector type).  */
+
+#define N 3
+
+static struct A {
+  int p1, p2;
+  int e[N];
+} a, b, c;
+
+int foo(void)
+{
+  for (int i = 0; i < N; i++)
+    a.e[i] = b.e[i] + c.e[i];
+
+   return a.e[0];
+}
+
+/* { dg-final { scan-ipa-dump-times "Increasing alignment of decl" 0 "increase_alignment" { target aarch64*-*-* } } } */
+/* { dg-final { scan-ipa-dump-times "Increasing alignment of decl" 0 "increase_alignment" { target powerpc64*-*-* } } } */
+/* { dg-final { scan-ipa-dump-times "Increasing alignment of decl" 0 "increase_alignment" { target arm*-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/aligned-section-anchors-vect-72.c b/gcc/testsuite/gcc.dg/vect/aligned-section-anchors-vect-72.c
new file mode 100644 (file)
index 0000000..873fabe
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target section_anchors } */
+/* { dg-require-effective-target vect_int } */
+
+#define N 32
+
+/* Clone of section-anchors-vect-70.c having nested struct.  */
+
+struct S
+{
+  int e[N];
+};
+
+static struct A {
+  int p1, p2;
+  struct S s; 
+} a, b, c;
+
+int foo(void)
+{
+  for (int i = 0; i < N; i++)
+    a.s.e[i] = b.s.e[i] + c.s.e[i];
+
+   return a.s.e[0];
+}
+
+/* { dg-final { scan-ipa-dump-times "Increasing alignment of decl" 0 "increase_alignment" { target aarch64*-*-* } } } */
+/* { dg-final { scan-ipa-dump-times "Increasing alignment of decl" 0 "increase_alignment" { target powerpc64*-*-* } } } */
+/* { dg-final { scan-ipa-dump-times "Increasing alignment of decl" 3 "increase_alignment" { target arm*-*-* } } } */
index 2b25b45..2669813 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;
 }