[gcc]
authorwschmidt <wschmidt@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 31 Aug 2015 01:02:47 +0000 (01:02 +0000)
committerwschmidt <wschmidt@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 31 Aug 2015 01:02:47 +0000 (01:02 +0000)
2015-08-30  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>

* config/rs6000/rs6000.c (swap_web_entry): Enlarge
special_handling bitfield.
(special_handling_values): Add SH_XXPERMDI and SH_CONCAT.
(rtx_is_swappable_p): Add handling for vec_select/vec_concat form
that represents a general xxpermdi.
(insn_is_swappable_p): Add handling for vec_concat of two
doublewords, which maps to a specific xxpermdi.
(adjust_xxpermdi): New function.
(adjust_concat): Likewise.
(handle_special_swappables): Call adjust_xxpermdi and
adjust_concat.
(dump_swap_insn_table): Handle SH_XXPERMDI and SH_CONCAT.

[gcc/testsuite]

2015-08-30  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>

* gcc.target/powerpc/swaps-p8-19.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@227331 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/rs6000/rs6000.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/powerpc/swaps-p8-19.c [new file with mode: 0644]

index 9150a6e..f91964d 100644 (file)
@@ -1,3 +1,18 @@
+2015-08-30  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
+
+       * config/rs6000/rs6000.c (swap_web_entry): Enlarge
+       special_handling bitfield.
+       (special_handling_values): Add SH_XXPERMDI and SH_CONCAT.
+       (rtx_is_swappable_p): Add handling for vec_select/vec_concat form
+       that represents a general xxpermdi.
+       (insn_is_swappable_p): Add handling for vec_concat of two
+       doublewords, which maps to a specific xxpermdi.
+       (adjust_xxpermdi): New function.
+       (adjust_concat): Likewise.
+       (handle_special_swappables): Call adjust_xxpermdi and
+       adjust_concat.
+       (dump_swap_insn_table): Handle SH_XXPERMDI and SH_CONCAT.
+
 2015-08-30  Rich Felker <dalias@libc.org>
 
        * config.gcc (supported_defaults): Handle sh[123456ble]*-*-*
index 93fdece..500effa 100644 (file)
@@ -34986,7 +34986,7 @@ class swap_web_entry : public web_entry_base
   /* A nonzero value indicates what kind of special handling for this
      insn is required if doublewords are swapped.  Undefined if
      is_swappable is not set.  */
-  unsigned int special_handling : 3;
+  unsigned int special_handling : 4;
   /* Set if the web represented by this entry cannot be optimized.  */
   unsigned int web_not_optimizable : 1;
   /* Set if this insn should be deleted.  */
@@ -35000,7 +35000,9 @@ enum special_handling_values {
   SH_NOSWAP_LD,
   SH_NOSWAP_ST,
   SH_EXTRACT,
-  SH_SPLAT
+  SH_SPLAT,
+  SH_XXPERMDI,
+  SH_CONCAT
 };
 
 /* Union INSN with all insns containing definitions that reach USE.
@@ -35192,6 +35194,20 @@ rtx_is_swappable_p (rtx op, unsigned int *special)
          *special = SH_EXTRACT;
          return 1;
        }
+      /* An XXPERMDI is ok if we adjust the lanes.  Note that if the
+        XXPERMDI is a swap operation, it will be identified by
+        insn_is_swap_p and therefore we won't get here.  */
+      else if (GET_CODE (XEXP (op, 0)) == VEC_CONCAT
+              && (GET_MODE (XEXP (op, 0)) == V4DFmode
+                  || GET_MODE (XEXP (op, 0)) == V4DImode)
+              && GET_CODE ((parallel = XEXP (op, 1))) == PARALLEL
+              && XVECLEN (parallel, 0) == 2
+              && GET_CODE (XVECEXP (parallel, 0, 0)) == CONST_INT
+              && GET_CODE (XVECEXP (parallel, 0, 1)) == CONST_INT)
+       {
+         *special = SH_XXPERMDI;
+         return 1;
+       }
       else
        return 0;
 
@@ -35369,6 +35385,17 @@ insn_is_swappable_p (swap_web_entry *insn_entry, rtx insn,
       return 1;
     }
 
+  /* A concatenation of two doublewords is ok if we reverse the
+     order of the inputs.  */
+  if (GET_CODE (body) == SET
+      && GET_CODE (SET_SRC (body)) == VEC_CONCAT
+      && (GET_MODE (SET_SRC (body)) == V2DFmode
+         || GET_MODE (SET_SRC (body)) == V2DImode))
+    {
+      *special = SH_CONCAT;
+      return 1;
+    }
+
   /* Otherwise check the operands for vector lane violations.  */
   return rtx_is_swappable_p (body, special);
 }
@@ -35658,6 +35685,49 @@ adjust_splat (rtx_insn *insn)
     fprintf (dump_file, "Changing lane for splat %d\n", INSN_UID (insn));
 }
 
+/* Given OP that contains an XXPERMDI operation (that is not a doubleword
+   swap), reverse the order of the source operands and adjust the indices
+   of the source lanes to account for doubleword reversal.  */
+static void
+adjust_xxpermdi (rtx_insn *insn)
+{
+  rtx set = PATTERN (insn);
+  rtx select = XEXP (set, 1);
+  rtx concat = XEXP (select, 0);
+  rtx src0 = XEXP (concat, 0);
+  XEXP (concat, 0) = XEXP (concat, 1);
+  XEXP (concat, 1) = src0;
+  rtx parallel = XEXP (select, 1);
+  int lane0 = INTVAL (XVECEXP (parallel, 0, 0));
+  int lane1 = INTVAL (XVECEXP (parallel, 0, 1));
+  int new_lane0 = 3 - lane1;
+  int new_lane1 = 3 - lane0;
+  XVECEXP (parallel, 0, 0) = GEN_INT (new_lane0);
+  XVECEXP (parallel, 0, 1) = GEN_INT (new_lane1);
+  INSN_CODE (insn) = -1; /* Force re-recognition.  */
+  df_insn_rescan (insn);
+
+  if (dump_file)
+    fprintf (dump_file, "Changing lanes for xxpermdi %d\n", INSN_UID (insn));
+}
+
+/* Given OP that contains a VEC_CONCAT operation of two doublewords,
+   reverse the order of those inputs.  */
+static void
+adjust_concat (rtx_insn *insn)
+{
+  rtx set = PATTERN (insn);
+  rtx concat = XEXP (set, 1);
+  rtx src0 = XEXP (concat, 0);
+  XEXP (concat, 0) = XEXP (concat, 1);
+  XEXP (concat, 1) = src0;
+  INSN_CODE (insn) = -1; /* Force re-recognition.  */
+  df_insn_rescan (insn);
+
+  if (dump_file)
+    fprintf (dump_file, "Reversing inputs for concat %d\n", INSN_UID (insn));
+}
+
 /* The insn described by INSN_ENTRY[I] can be swapped, but only
    with special handling.  Take care of that here.  */
 static void
@@ -35704,6 +35774,14 @@ handle_special_swappables (swap_web_entry *insn_entry, unsigned i)
       /* Change the lane on a direct-splat operation.  */
       adjust_splat (insn);
       break;
+    case SH_XXPERMDI:
+      /* Change the lanes on an XXPERMDI operation.  */
+      adjust_xxpermdi (insn);
+      break;
+    case SH_CONCAT:
+      /* Reverse the order of a concatenation operation.  */
+      adjust_concat (insn);
+      break;
     }
 }
 
@@ -35776,6 +35854,10 @@ dump_swap_insn_table (swap_web_entry *insn_entry)
              fputs ("special:extract ", dump_file);
            else if (insn_entry[i].special_handling == SH_SPLAT)
              fputs ("special:splat ", dump_file);
+           else if (insn_entry[i].special_handling == SH_XXPERMDI)
+             fputs ("special:xxpermdi ", dump_file);
+           else if (insn_entry[i].special_handling == SH_CONCAT)
+             fputs ("special:concat ", dump_file);
          }
        if (insn_entry[i].web_not_optimizable)
          fputs ("unoptimizable ", dump_file);
index 1d8373d..8869251 100644 (file)
@@ -1,3 +1,7 @@
+2015-08-30  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
+
+       * gcc.target/powerpc/swaps-p8-19.c: New test.
+
 2015-08-29 Jerry DeLisle  <jvdelisle@gcc.gnu.org>
 
        PR fortran/67367
diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-19.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-19.c
new file mode 100644 (file)
index 0000000..6dffbb9
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile { target { powerpc64le-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-O2 -ftree-vectorize -mcpu=power8 -ffast-math -fvect-cost-model=unlimited" } */
+
+/* This tests special handling for various uses of xxpermdi, other than
+   to perform doubleword swaps.  */
+
+void foo (_Complex double *self, _Complex double *a, _Complex double *b,
+         int a1, int a2)
+{
+  int i, j;
+  for (i = 0; i < a1; ++i)
+    for (j = 0; j < a2; ++j)
+      self[i] = self[i] + a[i,j] * b[j];
+}
+
+/* { dg-final { scan-assembler-times "xxpermdi .*,.*,.*,0" 1 } } */
+/* { dg-final { scan-assembler-times "xxpermdi .*,.*,.*,1" 1 } } */
+/* { dg-final { scan-assembler-times "xxpermdi .*,.*,.*,2" 1 } } */
+/* { dg-final { scan-assembler-times "xxpermdi .*,.*,.*,3" 1 } } */