Hi,

This patch is to add the support for float from/to long conversion
vectorization.  ISA 2.06 supports the vector version instructions
for conversion between float and long long (both signed and unsigned),
but vectorizer can't exploit them since the optab check fails.
So this patch is mainly to add related optab supports.

I've verified the functionality on both LE and BE.  Bootstrapped and
regress tested on powerpc64le-linux-gnu.


Thanks,
Kewen

--- 
gcc/ChangeLog

2019-09-27  Kewen Lin  <li...@gcc.gnu.org>

        * config/rs6000/vsx.md (vec_pack[su]_float_v2di): New define_expand.
        (vec_unpack_[su]fix_trunc_hi_v4sf): Likewise.
        (vec_unpack_[su]fix_trunc_lo_v4sf): Likewise.

gcc/testsuite/ChangeLog

2019-09-27  Kewen Lin  <li...@gcc.gnu.org>

        * gcc.target/powerpc/conv-vectorize-1.c: New test.
        * gcc.target/powerpc/conv-vectorize-2.c: New test.
diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md
index 7633171..ef32971 100644
--- a/gcc/config/rs6000/vsx.md
+++ b/gcc/config/rs6000/vsx.md
@@ -5538,3 +5538,42 @@
   operands[SFBOOL_TMP_VSX_DI] = gen_rtx_REG (DImode, regno_tmp_vsx);
   operands[SFBOOL_MTVSR_D_V4SF] = gen_rtx_REG (V4SFmode, regno_mtvsr_d);
 })
+
+;; Support signed/unsigned long long to float conversion vectorization.
+(define_expand "vec_pack<su>_float_v2di"
+  [(match_operand:V4SF 0 "vfloat_operand")
+   (any_float:V4SF (parallel [(match_operand:V2DI 1 "vint_operand")
+     (match_operand:V2DI 2 "vint_operand")]))]
+  "TARGET_VSX"
+{
+  rtx r1 = gen_reg_rtx (V4SFmode);
+  rtx r2 = gen_reg_rtx (V4SFmode);
+  emit_insn (gen_vsx_xvcv<su>xdsp (r1, operands[1]));
+  emit_insn (gen_vsx_xvcv<su>xdsp (r2, operands[2]));
+  rs6000_expand_extract_even (operands[0], r1, r2);
+  DONE;
+})
+
+;; Support float to signed/unsigned long long conversion vectorization.
+(define_expand "vec_unpack_<su>fix_trunc_hi_v4sf"
+  [(match_operand:V2DI 0 "vint_operand")
+   (any_fix:V2DI (match_operand:V4SF 1 "vfloat_operand"))]
+  "TARGET_VSX"
+{
+  rtx reg = gen_reg_rtx (V4SFmode);
+  rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN);
+  emit_insn (gen_vsx_xvcvsp<su>xds (operands[0], reg));
+  DONE;
+})
+
+(define_expand "vec_unpack_<su>fix_trunc_lo_v4sf"
+  [(match_operand:V2DI 0 "vint_operand")
+   (any_fix:V2DI (match_operand:V4SF 1 "vfloat_operand"))]
+  "TARGET_VSX"
+{
+  rtx reg = gen_reg_rtx (V4SFmode);
+  rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN);
+  emit_insn (gen_vsx_xvcvsp<su>xds (operands[0], reg));
+  DONE;
+})
+
diff --git a/gcc/testsuite/gcc.target/powerpc/conv-vectorize-1.c 
b/gcc/testsuite/gcc.target/powerpc/conv-vectorize-1.c
new file mode 100644
index 0000000..d96db14
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/conv-vectorize-1.c
@@ -0,0 +1,37 @@
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -ftree-vectorize -mvsx" } */
+
+/* Test vectorizer can exploit vector conversion instructions to convert
+   unsigned/signed long long to float.  */
+
+#include <stddef.h>
+
+#define SIZE 32
+#define ALIGN 16
+
+float sflt_array[SIZE] __attribute__ ((__aligned__ (ALIGN)));
+float uflt_array[SIZE] __attribute__ ((__aligned__ (ALIGN)));
+
+unsigned long long ulong_array[SIZE] __attribute__ ((__aligned__ (ALIGN)));
+signed long long slong_array[SIZE] __attribute__ ((__aligned__ (ALIGN)));
+
+void
+convert_slong_to_float (void)
+{
+  size_t i;
+
+  for (i = 0; i < SIZE; i++)
+    sflt_array[i] = (float) slong_array[i];
+}
+
+void
+convert_ulong_to_float (void)
+{
+  size_t i;
+
+  for (i = 0; i < SIZE; i++)
+    uflt_array[i] = (float) ulong_array[i];
+}
+
+/* { dg-final { scan-assembler {\mxvcvsxdsp\M} } } */
+/* { dg-final { scan-assembler {\mxvcvuxdsp\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/conv-vectorize-2.c 
b/gcc/testsuite/gcc.target/powerpc/conv-vectorize-2.c
new file mode 100644
index 0000000..5dd5dea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/conv-vectorize-2.c
@@ -0,0 +1,37 @@
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -ftree-vectorize -mvsx" } */
+
+/* Test vectorizer can exploit vector conversion instructions to convert
+   float to unsigned/signed long long.  */
+
+#include <stddef.h>
+
+#define SIZE 32
+#define ALIGN 16
+
+float sflt_array[SIZE] __attribute__ ((__aligned__ (ALIGN)));
+float uflt_array[SIZE] __attribute__ ((__aligned__ (ALIGN)));
+
+unsigned long long ulong_array[SIZE] __attribute__ ((__aligned__ (ALIGN)));
+signed long long slong_array[SIZE] __attribute__ ((__aligned__ (ALIGN)));
+
+void
+convert_float_to_slong (void)
+{
+  size_t i;
+
+  for (i = 0; i < SIZE; i++)
+    slong_array[i] = (signed long long) sflt_array[i];
+}
+
+void
+convert_float_to_ulong (void)
+{
+  size_t i;
+
+  for (i = 0; i < SIZE; i++)
+    ulong_array[i] = (unsigned long long) uflt_array[i];
+}
+
+/* { dg-final { scan-assembler {\mxvcvspsxds\M} } } */
+/* { dg-final { scan-assembler {\mxvcvspuxds\M} } } */

Reply via email to