This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, rs6000] Handle vector reductions in swap optimization
- From: Bill Schmidt <wschmidt at linux dot vnet dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: dje dot gcc at gmail dot com
- Date: Wed, 06 Jan 2016 16:37:40 -0600
- Subject: [PATCH, rs6000] Handle vector reductions in swap optimization
- Authentication-results: sourceware.org; auth=none
Hi,
Swap optimization is missing some opportunities when vector reductions
are present. This patch adds logic to recognize vector-reduction
patterns and mark them as swappable. Some of these are very easy to
recognize, given the presence of a specific unspec. For V2DF
reductions, we have to recognize a specific somewhat complex pattern.
I've added test cases to verify swap optimization works correctly on
reductions for V2DF and V4SF.
Bootstrapped and tested on powerpc64le-unknown-linux-gnu with no
regressions. Is this ok for trunk? I would also like to backport this
to GCC 5 after a settling period.
Thanks,
Bill
[gcc]
2016-01-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
* config/rs6000/rs6000.c (v2df_reduction_p): New function.
(rtx_is_swappable_p): Reductions are swappable.
(insn_is_swappable_p): V2DF reductions are swappable.
[gcc/testsuite]
2016-01-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
* gcc.target/powerpc/swaps-p8-23.c: New test.
* gcc.target/powerpc/swaps-p8-24.c: Likewise.
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c (revision 232109)
+++ gcc/config/rs6000/rs6000.c (working copy)
@@ -36648,6 +36648,44 @@ const_load_sequence_p (swap_web_entry *insn_entry,
return true;
}
+/* Return TRUE iff OP matches a V2DF reduction pattern. See the
+ definition of vsx_reduc_<VEC_reduc_name>_v2df in vsx.md. */
+static bool
+v2df_reduction_p (rtx op)
+{
+ if (GET_MODE (op) != V2DFmode)
+ return false;
+
+ enum rtx_code code = GET_CODE (op);
+ if (code != PLUS && code != SMIN && code != SMAX)
+ return false;
+
+ rtx concat = XEXP (op, 0);
+ if (GET_CODE (concat) != VEC_CONCAT)
+ return false;
+
+ rtx select0 = XEXP (concat, 0);
+ rtx select1 = XEXP (concat, 1);
+ if (GET_CODE (select0) != VEC_SELECT || GET_CODE (select1) != VEC_SELECT)
+ return false;
+
+ rtx reg0 = XEXP (select0, 0);
+ rtx reg1 = XEXP (select1, 0);
+ if (!rtx_equal_p (reg0, reg1) || !REG_P (reg0))
+ return false;
+
+ rtx parallel0 = XEXP (select0, 1);
+ rtx parallel1 = XEXP (select1, 1);
+ if (GET_CODE (parallel0) != PARALLEL || GET_CODE (parallel1) != PARALLEL)
+ return false;
+
+ if (!rtx_equal_p (XVECEXP (parallel0, 0, 0), const1_rtx)
+ || !rtx_equal_p (XVECEXP (parallel1, 0, 0), const0_rtx))
+ return false;
+
+ return true;
+}
+
/* Return 1 iff OP is an operand that will not be affected by having
vector doublewords swapped in memory. */
static unsigned int
@@ -36719,6 +36757,8 @@ rtx_is_swappable_p (rtx op, unsigned int *special)
*special = SH_XXPERMDI;
return 1;
}
+ else if (v2df_reduction_p (op))
+ return 1;
else
return 0;
@@ -36783,6 +36823,9 @@ rtx_is_swappable_p (rtx op, unsigned int *special)
case UNSPEC_VSPLT_DIRECT:
*special = SH_SPLAT;
return 1;
+ case UNSPEC_REDUC_PLUS:
+ case UNSPEC_REDUC:
+ return 1;
}
}
@@ -36907,6 +36950,15 @@ insn_is_swappable_p (swap_web_entry *insn_entry, r
return 1;
}
+ /* V2DF reductions are always swappable. */
+ if (GET_CODE (body) == PARALLEL)
+ {
+ rtx expr = XVECEXP (body, 0, 0);
+ if (GET_CODE (expr) == SET
+ && v2df_reduction_p (SET_SRC (expr)))
+ return 1;
+ }
+
/* An UNSPEC_VPERM is ok if the mask operand is loaded from the
constant pool. */
if (GET_CODE (body) == SET
Index: gcc/testsuite/gcc.target/powerpc/swaps-p8-23.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/swaps-p8-23.c (revision 0)
+++ gcc/testsuite/gcc.target/powerpc/swaps-p8-23.c (working copy)
@@ -0,0 +1,26 @@
+/* { dg-do compile { target { powerpc64le-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O3 -ffast-math" } */
+/* { dg-final { scan-assembler "lxvd2x" } } */
+/* { dg-final { scan-assembler-not "xxpermdi" } } */
+
+/* Verify that swap optimization works correctly in the presence of
+ a V2DFmode reduction. */
+
+extern double optvalue;
+extern void obfuscate (double, unsigned int);
+
+void
+foo (double *x, double *y, unsigned int n, unsigned int m)
+{
+ unsigned int i, j;
+ double sacc;
+ for (j = 0; j < m; ++j)
+ {
+ sacc = 0.0;
+ for (i = 0; i < n; ++i)
+ sacc += x[i] * y[i];
+ obfuscate (sacc, n);
+ }
+ optvalue = n * 2.0 * m;
+}
Index: gcc/testsuite/gcc.target/powerpc/swaps-p8-24.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/swaps-p8-24.c (revision 0)
+++ gcc/testsuite/gcc.target/powerpc/swaps-p8-24.c (working copy)
@@ -0,0 +1,26 @@
+/* { dg-do compile { target { powerpc64le-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O3 -ffast-math" } */
+/* { dg-final { scan-assembler "lxvd2x" } } */
+/* { dg-final { scan-assembler-not "xxpermdi" } } */
+
+/* Verify that swap optimization works correctly in the presence of
+ a V4SFmode reduction. */
+
+extern double optvalue;
+extern void obfuscate (float, unsigned int);
+
+void
+foo (float *x, float *y, unsigned int n, unsigned int m)
+{
+ unsigned int i, j;
+ float sacc;
+ for (j = 0; j < m; ++j)
+ {
+ sacc = 0.0f;
+ for (i = 0; i < n; ++i)
+ sacc += x[i] * y[i];
+ obfuscate (sacc, n);
+ }
+ optvalue = n * 2.0f * m;
+}