rs6000-p8swap.c (const_load_sequence_p): Revise this function to return false if...
authorKelvin Nilsen <kelvin@gcc.gnu.org>
Wed, 27 Sep 2017 23:43:26 +0000 (23:43 +0000)
committerKelvin Nilsen <kelvin@gcc.gnu.org>
Wed, 27 Sep 2017 23:43:26 +0000 (23:43 +0000)
gcc/ChangeLog:

2017-09-27  Kelvin Nilsen  <kelvin@gcc.gnu.org>

* config/rs6000/rs6000-p8swap.c (const_load_sequence_p): Revise
this function to return false if the definition used by the swap
instruction is artificial, or if the memory address from which the
constant value is loaded is not represented by a base address held
in a register or if the base address register is a frame or stack
pointer.  Additionally, return false if the base address of the
loaded constant is a SYMBOL_REF but is not considered to be a
constant.
(replace_swapped_load_constant): New function.
(rs6000_analyze_swaps): Add a new pass to replace a swap of a
loaded constant vector with a load of a swapped constant vector.

gcc/testsuite/ChangeLog:

2017-09-27  Kelvin Nilsen  <kelvin@gcc.gnu.org>

* gcc.target/powerpc/swaps-p8-28.c: New test.
* gcc.target/powerpc/swaps-p8-29.c: New test.
* gcc.target/powerpc/swaps-p8-30.c: New test.
* gcc.target/powerpc/swaps-p8-31.c: New test.
* gcc.target/powerpc/swaps-p8-32.c: New test.
* gcc.target/powerpc/swaps-p8-33.c: New test.
* gcc.target/powerpc/swaps-p8-34.c: New test.
* gcc.target/powerpc/swaps-p8-35.c: New test.
* gcc.target/powerpc/swaps-p8-36.c: New test.
* gcc.target/powerpc/swaps-p8-37.c: New test.
* gcc.target/powerpc/swaps-p8-38.c: New test.
* gcc.target/powerpc/swaps-p8-39.c: New test.
* gcc.target/powerpc/swaps-p8-40.c: New test.
* gcc.target/powerpc/swaps-p8-41.c: New test.
* gcc.target/powerpc/swaps-p8-42.c: New test.
* gcc.target/powerpc/swaps-p8-43.c: New test.
* gcc.target/powerpc/swaps-p8-44.c: New test.
* gcc.target/powerpc/swaps-p8-45.c: New test.

From-SVN: r253240

21 files changed:
gcc/ChangeLog
gcc/config/rs6000/rs6000-p8swap.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/powerpc/swaps-p8-28.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/swaps-p8-29.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/swaps-p8-30.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/swaps-p8-31.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/swaps-p8-32.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/swaps-p8-33.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/swaps-p8-34.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/swaps-p8-35.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/swaps-p8-36.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/swaps-p8-37.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/swaps-p8-38.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/swaps-p8-39.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/swaps-p8-40.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/swaps-p8-41.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/swaps-p8-42.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/swaps-p8-43.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/swaps-p8-44.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/swaps-p8-45.c [new file with mode: 0644]

index 737c4af..8a48274 100644 (file)
@@ -1,3 +1,17 @@
+2017-09-27  Kelvin Nilsen  <kelvin@gcc.gnu.org>
+
+       * config/rs6000/rs6000-p8swap.c (const_load_sequence_p): Revise
+       this function to return false if the definition used by the swap
+       instruction is artificial, or if the memory address from which the
+       constant value is loaded is not represented by a base address held
+       in a register or if the base address register is a frame or stack
+       pointer.  Additionally, return false if the base address of the
+       loaded constant is a SYMBOL_REF but is not considered to be a
+       constant.
+       (replace_swapped_load_constant): New function.
+       (rs6000_analyze_swaps): Add a new pass to replace a swap of a
+       loaded constant vector with a load of a swapped constant vector.
+
 2017-09-27  Carl Love  <cel@us.ibm.com>
 
        * config/rs6000/rs6000-builtin.def (BU_FP_1MISC_1): Add define macro.
index 7d2c97f..83df9c8 100644 (file)
@@ -335,21 +335,26 @@ const_load_sequence_p (swap_web_entry *insn_entry, rtx insn)
 
   const_rtx tocrel_base;
 
-  /* Find the unique use in the swap and locate its def.  If the def
-     isn't unique, punt.  */
   struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
   df_ref use;
   FOR_EACH_INSN_INFO_USE (use, insn_info)
     {
       struct df_link *def_link = DF_REF_CHAIN (use);
-      if (!def_link || def_link->next)
+
+      /* If there is no def or the def is artificial or there are
+        multiple defs, punt.  */
+      if (!def_link || !def_link->ref || DF_REF_IS_ARTIFICIAL (def_link->ref)
+         || def_link->next)
        return false;
 
       rtx def_insn = DF_REF_INSN (def_link->ref);
       unsigned uid2 = INSN_UID (def_insn);
+      /* If this is not a load or is not a swap, return false.  */
       if (!insn_entry[uid2].is_load || !insn_entry[uid2].is_swap)
        return false;
 
+      /* If the source of the rtl def is not a set from memory, return
+        false.  */
       rtx body = PATTERN (def_insn);
       if (GET_CODE (body) != SET
          || GET_CODE (SET_SRC (body)) != VEC_SELECT
@@ -358,11 +363,17 @@ const_load_sequence_p (swap_web_entry *insn_entry, rtx insn)
 
       rtx mem = XEXP (SET_SRC (body), 0);
       rtx base_reg = XEXP (mem, 0);
+      /* If the base address for the memory expression is not
+        represented by a register, punt.  */
+      if (!REG_P (base_reg))
+       return false;
 
       df_ref base_use;
       insn_info = DF_INSN_INFO_GET (def_insn);
       FOR_EACH_INSN_INFO_USE (base_use, insn_info)
        {
+         /* If base_use does not represent base_reg, look for another
+            use.  */
          if (!rtx_equal_p (DF_REF_REG (base_use), base_reg))
            continue;
 
@@ -370,6 +381,14 @@ const_load_sequence_p (swap_web_entry *insn_entry, rtx insn)
          if (!base_def_link || base_def_link->next)
            return false;
 
+         /* Constants held on the stack are not "true" constants
+            because their values are not part of the static load
+            image.  If this constant's base reference is a stack
+            or frame pointer, it is seen as an artificial
+            reference.  */
+         if (DF_REF_IS_ARTIFICIAL (base_def_link->ref))
+           return false;
+
          rtx tocrel_insn = DF_REF_INSN (base_def_link->ref);
          rtx tocrel_body = PATTERN (tocrel_insn);
          rtx base, offset;
@@ -383,8 +402,26 @@ const_load_sequence_p (swap_web_entry *insn_entry, rtx insn)
          if (!toc_relative_expr_p (tocrel_expr, false, &tocrel_base, NULL))
            return false;
          split_const (XVECEXP (tocrel_base, 0, 0), &base, &offset);
+
          if (GET_CODE (base) != SYMBOL_REF || !CONSTANT_POOL_ADDRESS_P (base))
            return false;
+         else
+           {
+             /* FIXME: The conditions under which
+                 ((GET_CODE (const_vector) == SYMBOL_REF) &&
+                  !CONSTANT_POOL_ADDRESS_P (const_vector))
+                are not well understood.  This code prevents
+                an internal compiler error which will occur in
+                replace_swapped_load_constant () if we were to return
+                true.  Some day, we should figure out how to properly
+                handle this condition in
+                replace_swapped_load_constant () and then we can
+                remove this special test.  */
+             rtx const_vector = get_pool_constant (base);
+             if (GET_CODE (const_vector) == SYMBOL_REF
+                 && !CONSTANT_POOL_ADDRESS_P (const_vector))
+                   return false;
+           }
        }
     }
   return true;
@@ -1281,6 +1318,195 @@ replace_swap_with_copy (swap_web_entry *insn_entry, unsigned i)
   insn->set_deleted ();
 }
 
+/* Given that swap_insn represents a swap of a load of a constant
+   vector value, replace with a single instruction that loads a
+   swapped variant of the original constant.
+
+   The "natural" representation of a byte array in memory is the same
+   for big endian and little endian.
+
+   unsigned char byte_array[] =
+     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f };
+
+   However, when loaded into a vector register, the representation
+   depends on endian conventions.
+
+   In big-endian mode, the register holds:
+
+     MSB                                            LSB
+     [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f ]
+
+   In little-endian mode, the register holds:
+
+     MSB                                            LSB
+     [ f, e, d, c, b, a, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 ]
+
+   Word arrays require different handling.  Consider the word array:
+
+   unsigned int word_array[] =
+     { 0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f };
+
+   The in-memory representation depends on endian configuration.  The
+   equivalent array, declared as a byte array, in memory would be:
+
+   unsigned char big_endian_word_array_data[] =
+     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f }
+
+   unsigned char little_endian_word_array_data[] =
+     { 3, 2, 1, 0, 7, 6, 5, 4, b, a, 9, 8, f, e, d, c }
+
+   In big-endian mode, the register holds:
+
+     MSB                                            LSB
+     [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f ]
+
+   In little-endian mode, the register holds:
+
+     MSB                                            LSB
+     [ c, d, e, f, 8, 9, a, b, 4, 5, 6, 7, 0, 1, 2, 3 ]
+
+
+  Similar transformations apply to the vector of half-word and vector
+  of double-word representations.
+
+  For now, don't handle vectors of quad-precision values.  Just return.
+  A better solution is to fix the code generator to emit lvx/stvx for
+  those.  */
+static void
+replace_swapped_load_constant (swap_web_entry *insn_entry, rtx swap_insn)
+{
+  /* Find the load.  */
+  struct df_insn_info *insn_info = DF_INSN_INFO_GET (swap_insn);
+  rtx_insn *load_insn;
+  df_ref use  = DF_INSN_INFO_USES (insn_info);
+  struct df_link *def_link = DF_REF_CHAIN (use);
+  gcc_assert (def_link && !def_link->next);
+
+  load_insn = DF_REF_INSN (def_link->ref);
+  gcc_assert (load_insn);
+
+  /* Find the TOC-relative symbol access.  */
+  insn_info = DF_INSN_INFO_GET (load_insn);
+  use = DF_INSN_INFO_USES (insn_info);
+
+  def_link = DF_REF_CHAIN (use);
+  gcc_assert (def_link && !def_link->next);
+
+  rtx_insn *tocrel_insn = DF_REF_INSN (def_link->ref);
+  gcc_assert (tocrel_insn);
+
+  /* Find the embedded CONST_VECTOR.  We have to call toc_relative_expr_p
+     to set tocrel_base; otherwise it would be unnecessary as we've
+     already established it will return true.  */
+  rtx base, offset;
+  rtx tocrel_expr = SET_SRC (PATTERN (tocrel_insn));
+  const_rtx tocrel_base;
+
+  /* There is an extra level of indirection for small/large code models.  */
+  if (GET_CODE (tocrel_expr) == MEM)
+    tocrel_expr = XEXP (tocrel_expr, 0);
+
+  if (!toc_relative_expr_p (tocrel_expr, false, &tocrel_base, NULL))
+    gcc_unreachable ();
+
+  split_const (XVECEXP (tocrel_base, 0, 0), &base, &offset);
+  rtx const_vector = get_pool_constant (base);
+
+  /* With the extra indirection, get_pool_constant will produce the
+     real constant from the reg_equal expression, so get the real
+     constant.  */
+  if (GET_CODE (const_vector) == SYMBOL_REF)
+    const_vector = get_pool_constant (const_vector);
+  gcc_assert (GET_CODE (const_vector) == CONST_VECTOR);
+
+  rtx new_mem;
+  enum machine_mode mode = GET_MODE (const_vector);
+
+  /* Create an adjusted constant from the original constant.  */
+  if (mode == V1TImode)
+    /* Leave this code as is.  */
+    return;
+  else if (mode == V16QImode)
+    {
+      rtx vals = gen_rtx_PARALLEL (mode, rtvec_alloc (16));
+      int i;
+
+      for (i = 0; i < 16; i++)
+       XVECEXP (vals, 0, ((i+8) % 16)) = XVECEXP (const_vector, 0, i);
+      rtx new_const_vector = gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0));
+      new_mem = force_const_mem (mode, new_const_vector);
+    }
+  else if ((mode == V8HImode)
+#ifdef HAVE_V8HFmode
+          || (mode == V8HFmode)
+#endif
+          )
+    {
+      rtx vals = gen_rtx_PARALLEL (mode, rtvec_alloc (8));
+      int i;
+
+      for (i = 0; i < 8; i++)
+       XVECEXP (vals, 0, ((i+4) % 8)) = XVECEXP (const_vector, 0, i);
+      rtx new_const_vector = gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0));
+      new_mem = force_const_mem (mode, new_const_vector);
+    }
+  else if ((mode == V4SImode) || (mode == V4SFmode))
+    {
+      rtx vals = gen_rtx_PARALLEL (mode, rtvec_alloc (4));
+      int i;
+
+      for (i = 0; i < 4; i++)
+       XVECEXP (vals, 0, ((i+2) % 4)) = XVECEXP (const_vector, 0, i);
+      rtx new_const_vector = gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0));
+      new_mem = force_const_mem (mode, new_const_vector);
+    }
+  else if ((mode == V2DImode) || (mode == V2DFmode))
+    {
+      rtx vals = gen_rtx_PARALLEL (mode, rtvec_alloc (2));
+      int i;
+
+      for (i = 0; i < 2; i++)
+       XVECEXP (vals, 0, ((i+1) % 2)) = XVECEXP (const_vector, 0, i);
+      rtx new_const_vector = gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0));
+      new_mem = force_const_mem (mode, new_const_vector);
+    }
+  else
+    {
+      /* We do not expect other modes to be constant-load-swapped.  */
+      gcc_unreachable ();
+    }
+
+  /* This gives us a MEM whose base operand is a SYMBOL_REF, which we
+     can't recognize.  Force the SYMBOL_REF into a register.  */
+  if (!REG_P (XEXP (new_mem, 0))) {
+    rtx base_reg = force_reg (Pmode, XEXP (new_mem, 0));
+    XEXP (new_mem, 0) = base_reg;
+
+    /* Move the newly created insn ahead of the load insn.  */
+    /* The last insn is the the insn that forced new_mem into a register.  */
+    rtx_insn *force_insn = get_last_insn ();
+    /* Remove this insn from the end of the instruction sequence.  */
+    remove_insn (force_insn);
+    rtx_insn *before_load_insn = PREV_INSN (load_insn);
+
+    /* And insert this insn back into the sequence before the previous
+       load insn so this new expression will be available when the
+       existing load is modified to load the swapped constant.  */
+    add_insn_after (force_insn, before_load_insn, BLOCK_FOR_INSN (load_insn));
+    df_insn_rescan (before_load_insn);
+    df_insn_rescan (force_insn);
+  }
+
+  /* Replace the MEM in the load instruction and rescan it.  */
+  XEXP (SET_SRC (PATTERN (load_insn)), 0) = new_mem;
+  INSN_CODE (load_insn) = -1; /* Force re-recognition.  */
+  df_insn_rescan (load_insn);
+
+  unsigned int uid = INSN_UID (swap_insn);
+  mark_swaps_for_removal (insn_entry, uid);
+  replace_swap_with_copy (insn_entry, uid);
+}
+
 /* Dump the swap table to DUMP_FILE.  */
 static void
 dump_swap_insn_table (swap_web_entry *insn_entry)
@@ -1873,6 +2099,44 @@ rs6000_analyze_swaps (function *fun)
 
   /* Clean up.  */
   free (insn_entry);
+
+  /* Use additional pass over rtl to replace swap(load(vector constant))
+     with load(swapped vector constant). */
+  swap_web_entry *pass2_insn_entry;
+  pass2_insn_entry = XCNEWVEC (swap_web_entry, get_max_uid ());
+
+  /* Walk the insns to gather basic data.  */
+  FOR_ALL_BB_FN (bb, fun)
+    FOR_BB_INSNS_SAFE (bb, insn, curr_insn)
+    {
+      unsigned int uid = INSN_UID (insn);
+      if (NONDEBUG_INSN_P (insn))
+       {
+         pass2_insn_entry[uid].insn = insn;
+
+         pass2_insn_entry[uid].is_relevant = 1;
+         pass2_insn_entry[uid].is_load = insn_is_load_p (insn);
+         pass2_insn_entry[uid].is_store = insn_is_store_p (insn);
+
+         /* Determine if this is a doubleword swap.  If not,
+            determine whether it can legally be swapped.  */
+         if (insn_is_swap_p (insn))
+           pass2_insn_entry[uid].is_swap = 1;
+       }
+    }
+
+  e = get_max_uid ();
+  for (unsigned i = 0; i < e; ++i)
+    if (pass2_insn_entry[i].is_swap && !pass2_insn_entry[i].is_load
+       && !pass2_insn_entry[i].is_store)
+      {
+       insn = pass2_insn_entry[i].insn;
+       if (const_load_sequence_p (pass2_insn_entry, insn))
+         replace_swapped_load_constant (pass2_insn_entry, insn);
+      }
+
+  /* Clean up.  */
+  free (pass2_insn_entry);
   return 0;
 }
 
index c1542b9..0b5f5ee 100644 (file)
@@ -1,3 +1,24 @@
+2017-09-27  Kelvin Nilsen  <kelvin@gcc.gnu.org>
+
+       * gcc.target/powerpc/swaps-p8-28.c: New test.
+       * gcc.target/powerpc/swaps-p8-29.c: New test.
+       * gcc.target/powerpc/swaps-p8-30.c: New test.
+       * gcc.target/powerpc/swaps-p8-31.c: New test.
+       * gcc.target/powerpc/swaps-p8-32.c: New test.
+       * gcc.target/powerpc/swaps-p8-33.c: New test.
+       * gcc.target/powerpc/swaps-p8-34.c: New test.
+       * gcc.target/powerpc/swaps-p8-35.c: New test.
+       * gcc.target/powerpc/swaps-p8-36.c: New test.
+       * gcc.target/powerpc/swaps-p8-37.c: New test.
+       * gcc.target/powerpc/swaps-p8-38.c: New test.
+       * gcc.target/powerpc/swaps-p8-39.c: New test.
+       * gcc.target/powerpc/swaps-p8-40.c: New test.
+       * gcc.target/powerpc/swaps-p8-41.c: New test.
+       * gcc.target/powerpc/swaps-p8-42.c: New test.
+       * gcc.target/powerpc/swaps-p8-43.c: New test.
+       * gcc.target/powerpc/swaps-p8-44.c: New test.
+       * gcc.target/powerpc/swaps-p8-45.c: New test.
+
 2017-09-27 Carl Love  <cel@us.ibm.com>
        * gcc.target/powerpc/builtin-fctid-fctiw-runnable.c: New test file
        for the __builtin_fctid and __builtin_fctiw.
diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-28.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-28.c
new file mode 100644 (file)
index 0000000..4e96d92
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-require-effective-target p8vector_hw } */
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O3 " } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+vector char y = { 0, 1, 2, 3,
+                 4, 5, 6, 7,
+                 8, 9, 10, 11,
+                 12, 13, 14, 15 };
+
+vector char
+foo (void)
+{
+  return y;
+}
+
+int
+main (int argc, char *argv[])
+{
+  vector char fetched_value = foo ();
+  if (fetched_value[0] != 0 || fetched_value[15] != 15)
+    abort ();
+  else
+    return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-29.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-29.c
new file mode 100644 (file)
index 0000000..c1ed7d3
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-require-effective-target p8vector_hw } */
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O3 " } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+const vector char y = { 0, 1, 2, 3,
+                       4, 5, 6, 7,
+                       8, 9, 10, 11,
+                       12, 13, 14, 15 };
+
+vector char
+foo (void)
+{
+  return y;
+}
+
+int
+main (int argc, char *argv[])
+{
+  vector char fetched_value = foo ();
+  if (fetched_value[0] != 0 || fetched_value[15] != 15)
+    abort ();
+  else
+    return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-30.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-30.c
new file mode 100644 (file)
index 0000000..4e265d5
--- /dev/null
@@ -0,0 +1,31 @@
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-do compile { target { powerpc64le-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O3 " } */
+/* { dg-final { scan-assembler-not "xxpermdi" } } */
+/* { dg-final { scan-assembler-not "xxswapd" } } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+const vector char y = { 0, 1, 2, 3,
+                       4, 5, 6, 7,
+                       8, 9, 10, 11,
+                       12, 13, 14, 15 };
+
+vector char
+foo (void)
+{
+  return y;
+}
+
+int
+main (int argc, char *argv[])
+{
+  vector char fetched_value = foo ();
+  if (fetched_value[0] != 0 || fetched_value[15] != 15)
+    abort ();
+  else
+    return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-31.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-31.c
new file mode 100644 (file)
index 0000000..1711dd1
--- /dev/null
@@ -0,0 +1,27 @@
+/* { dg-require-effective-target p8vector_hw } */
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O3 " } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+vector short y = { 0, 1, 2, 3,
+                  4, 5, 6, 7 };
+
+vector short
+foo (void)
+{
+  return y;
+}
+
+int
+main (int argc, char *argv[])
+{
+  vector short fetched_value = foo ();
+  if (fetched_value[0] != 0 || fetched_value[7] != 7)
+    abort ();
+  else
+    return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-32.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-32.c
new file mode 100644 (file)
index 0000000..8f13719
--- /dev/null
@@ -0,0 +1,27 @@
+/* { dg-require-effective-target p8vector_hw } */
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O3 " } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+const vector short y = { 0, 1, 2, 3,
+                        4, 5, 6, 7 };
+
+vector short
+foo (void)
+{
+  return y;
+}
+
+int
+main (int argc, char *argv[])
+{
+  vector short fetched_value = foo ();
+  if (fetched_value[0] != 0 || fetched_value[7] != 7)
+    abort ();
+  else
+    return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-33.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-33.c
new file mode 100644 (file)
index 0000000..8e76ba9
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-do compile { target { powerpc64le-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O3 " } */
+/* { dg-final { scan-assembler-not "xxpermdi" } } */
+/* { dg-final { scan-assembler-not "xxswapd" } } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+const vector short y = { 0, 1, 2, 3,
+                        4, 5, 6, 7 };
+
+vector short
+foo (void)
+{
+  return y;
+}
+
+int
+main (int argc, char *argv[])
+{
+  vector short fetched_value = foo ();
+  if (fetched_value[0] != 0 || fetched_value[15] != 15)
+    abort ();
+  else
+    return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-34.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-34.c
new file mode 100644 (file)
index 0000000..7eb39e3
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-require-effective-target p8vector_hw } */
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O3 " } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+vector int y = { 0, 1, 2, 3 };
+
+vector int
+foo (void)
+{
+  return y;
+}
+
+int
+main (int argc, char *argv[])
+{
+  vector int fetched_value = foo ();
+  if (fetched_value[0] != 0 || fetched_value[3] != 3)
+    abort ();
+  else
+    return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-35.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-35.c
new file mode 100644 (file)
index 0000000..99ca991
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-require-effective-target p8vector_hw } */
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O3 " } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+const vector int y = { 0, 1, 2, 3 };
+
+vector int
+foo (void)
+{
+  return y;
+}
+
+int
+main (int argc, char *argv[])
+{
+  vector int fetched_value = foo ();
+  if (fetched_value[0] != 0 || fetched_value[3] != 3)
+    abort ();
+  else
+    return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-36.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-36.c
new file mode 100644 (file)
index 0000000..6c067b3
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-do compile { target { powerpc64le-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O3 " } */
+/* { dg-final { scan-assembler-not "xxpermdi" } } */
+/* { dg-final { scan-assembler-not "xxswapd" } } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+const vector int y = { 0, 1, 2, 3 };
+
+vector int
+foo (void)
+{
+  return y;
+}
+
+int
+main (int argc, char *argv[])
+{
+  vector int fetched_value = foo ();
+  if (fetched_value[0] != 0 || fetched_value[3] != 3)
+    abort ();
+  else
+    return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-37.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-37.c
new file mode 100644 (file)
index 0000000..ac5f7cc
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-require-effective-target p8vector_hw } */
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O3 " } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+vector float y = { 0.0f, 0.1f, 0.2f, 0.3f };
+
+vector float
+foo (void)
+{
+  return y;
+}
+
+int
+main (int argc, char *argv[])
+{
+  vector float fetched_value = foo ();
+  if (fetched_value[0] != 0.0f || fetched_value[3] != 0.3f)
+    abort ();
+  else
+    return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-38.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-38.c
new file mode 100644 (file)
index 0000000..b05536b
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-require-effective-target p8vector_hw } */
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O3 " } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+const vector float y = { 0.0f, 0.1f, 0.2f, 0.3f };
+
+vector float
+foo (void)
+{
+  return y;
+}
+
+int
+main (int argc, char *argv[])
+{
+  vector float fetched_value = foo ();
+  if (fetched_value[0] != 0.0f || fetched_value[3] != 0.3f)
+    abort ();
+  else
+    return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-39.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-39.c
new file mode 100644 (file)
index 0000000..b76f5c4
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-do compile { target { powerpc64le-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O3 " } */
+/* { dg-final { scan-assembler-not "xxpermdi" } } */
+/* { dg-final { scan-assembler-not "xxswapd" } } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+const vector float y = { 0.0f, 0.1f, 0.2f, 0.3f };
+
+vector float
+foo (void)
+{
+  return y;
+}
+
+int
+main (int argc, char *argv[])
+{
+  vector float fetched_value = foo ();
+  if (fetched_value[0] != 0.0f || fetched_value[3] != 0.3)
+    abort ();
+  else
+    return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-40.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-40.c
new file mode 100644 (file)
index 0000000..2f48d0d
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-require-effective-target p8vector_hw } */
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O3 " } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+vector long long int y = { 0, 1 };
+
+vector long long int
+foo (void)
+{
+  return y;
+}
+
+int
+main (int argc, int *argv[])
+{
+  vector long long int fetched_value = foo ();
+  if (fetched_value[0] != 0 || fetched_value[1] != 1)
+    abort ();
+  else
+    return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-41.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-41.c
new file mode 100644 (file)
index 0000000..a6fda12
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-require-effective-target p8vector_hw } */
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O3 " } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+const vector long long int y = { 0, 1 };
+
+vector long long int
+foo (void)
+{
+  return y;
+}
+
+int
+main (int argc, char *argv[])
+{
+  vector long long int fetched_value = foo ();
+  if (fetched_value[0] != 0 || fetched_value[1] != 1)
+    abort ();
+  else
+    return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-42.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-42.c
new file mode 100644 (file)
index 0000000..5e4073f
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-do compile { target { powerpc64le-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O3 " } */
+/* { dg-final { scan-assembler-not "xxpermdi" } } */
+/* { dg-final { scan-assembler-not "xxswapd" } } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+const vector long long int y = { 0, 1 };
+
+vector long long int
+foo (void)
+{
+  return y;
+}
+
+int
+main (int argc, char *argv[])
+{
+  vector long long int fetched_value = foo ();
+  if (fetched_value[0] != 0 || fetched_value[1] != 1)
+    abort ();
+  else
+    return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-43.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-43.c
new file mode 100644 (file)
index 0000000..383394c
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-require-effective-target p8vector_hw } */
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O3 " } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+vector double y = { 0.0, 0.1 };
+
+vector double
+foo (void)
+{
+  return y;
+}
+
+int
+main (int argc, char *argv[])
+{
+  vector double fetched_value = foo ();
+  if (fetched_value[0] != 0 || fetched_value[1] != 0.1)
+    abort ();
+  else
+    return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-44.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-44.c
new file mode 100644 (file)
index 0000000..06323a9
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-require-effective-target p8vector_hw } */
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O3 " } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+const vector double y = { 0.0, 0.1 };
+
+vector double
+foo (void)
+{
+  return y;
+}
+
+int
+main (int argc, char *argv[])
+{
+  vector double fetched_value = foo ();
+  if (fetched_value[0] != 0.0 || fetched_value[1] != 0.1)
+    abort ();
+  else
+    return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-45.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-45.c
new file mode 100644 (file)
index 0000000..2129bea
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-do compile { target { powerpc64le-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O3 " } */
+/* { dg-final { scan-assembler-not "xxpermdi" } } */
+/* { dg-final { scan-assembler-not "xxswapd" } } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+const vector double y = { 0.0, 0.1 };
+
+vector double
+foo (void)
+{
+  return y;
+}
+
+int
+main (int argc, char *argv[])
+{
+  vector double fetched_value = foo ();
+  if (fetched_value[0] != 0.0 || fetched_value[15] != 0.1)
+    abort ();
+  else
+    return 0;
+}