rs6000.md (bswaphi2_reg): On ISA 3.0 systems, enable generating XXBRH if the value...
authorMichael Meissner <meissner@linux.vnet.ibm.com>
Fri, 10 Nov 2017 22:59:40 +0000 (22:59 +0000)
committerMichael Meissner <meissner@gcc.gnu.org>
Fri, 10 Nov 2017 22:59:40 +0000 (22:59 +0000)
[gcc]
2017-11-10  Michael Meissner  <meissner@linux.vnet.ibm.com>

* config/rs6000/rs6000.md (bswaphi2_reg): On ISA 3.0 systems,
enable generating XXBRH if the value is in a vector register.
(bswapsi2_reg): On ISA 3.0 systems, enable generating XXBRW if the
value is in a vector register.
(bswapdi2_reg): On ISA 3.0 systems, always use XXBRD to do
register to register bswap64's instead of doing the GPR sequence
used on previous machines.
(bswapdi2_xxbrd): New insn.
(bswapdi2_reg): Disallow on ISA 3.0.
(register to register bswap64 splitter): Do not split the insn on
ISA 3.0 systems that use XXBRD.

[gcc/testsuite]
2017-11-10  Michael Meissner  <meissner@linux.vnet.ibm.com>

* gcc.target/powerpc/p9-xxbr-3.c: New test.

From-SVN: r254643

gcc/ChangeLog
gcc/config/rs6000/rs6000.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/powerpc/p9-xxbr-3.c [new file with mode: 0644]

index 9e5b934..9dcaca4 100644 (file)
@@ -1,3 +1,17 @@
+2017-11-10  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+       * config/rs6000/rs6000.md (bswaphi2_reg): On ISA 3.0 systems,
+       enable generating XXBRH if the value is in a vector register.
+       (bswapsi2_reg): On ISA 3.0 systems, enable generating XXBRW if the
+       value is in a vector register.
+       (bswapdi2_reg): On ISA 3.0 systems, always use XXBRD to do
+       register to register bswap64's instead of doing the GPR sequence
+       used on previous machines.
+       (bswapdi2_xxbrd): New insn.
+       (bswapdi2_reg): Disallow on ISA 3.0.
+       (register to register bswap64 splitter): Do not split the insn on
+       ISA 3.0 systems that use XXBRD.
+
 2017-11-10  Martin Sebor  <msebor@redhat.com>
 
        PR c/81117
index 7025b00..9b0f872 100644 (file)
   [(set_attr "type" "store")])
 
 (define_insn_and_split "bswaphi2_reg"
-  [(set (match_operand:HI 0 "gpc_reg_operand" "=&r")
+  [(set (match_operand:HI 0 "gpc_reg_operand" "=&r,wo")
        (bswap:HI
-        (match_operand:HI 1 "gpc_reg_operand" "r")))
-   (clobber (match_scratch:SI 2 "=&r"))]
+        (match_operand:HI 1 "gpc_reg_operand" "r,wo")))
+   (clobber (match_scratch:SI 2 "=&r,X"))]
   ""
-  "#"
-  "reload_completed"
+  "@
+   #
+   xxbrh %x0,%x1"
+  "reload_completed && int_reg_operand (operands[0], HImode)"
   [(set (match_dup 3)
        (and:SI (lshiftrt:SI (match_dup 4)
                             (const_int 8))
   operands[3] = simplify_gen_subreg (SImode, operands[0], HImode, 0);
   operands[4] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
 }
-  [(set_attr "length" "12")
-   (set_attr "type" "*")])
+  [(set_attr "length" "12,4")
+   (set_attr "type" "*,vecperm")])
 
 ;; We are always BITS_BIG_ENDIAN, so the bit positions below in
 ;; zero_extract insns do not change for -mlittle.
 (define_insn_and_split "bswapsi2_reg"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=&r,wo")
        (bswap:SI
-        (match_operand:SI 1 "gpc_reg_operand" "r")))]
+        (match_operand:SI 1 "gpc_reg_operand" "r,wo")))]
   ""
-  "#"
-  "reload_completed"
+  "@
+   #
+   xxbrw %x0,%x1"
+  "reload_completed && int_reg_operand (operands[0], SImode)"
   [(set (match_dup 0)                                  ; DABC
        (rotate:SI (match_dup 1)
                   (const_int 24)))
                        (const_int 255))
                (and:SI (match_dup 0)
                        (const_int -256))))]
-  "")
+  ""
+  [(set_attr "length" "12,4")
+   (set_attr "type" "*,vecperm")])
 
 ;; On systems with LDBRX/STDBRX generate the loads/stores directly, just like
 ;; we do for L{H,W}BRX and ST{H,W}BRX above.  If not, we have to generate more
        emit_insn (gen_bswapdi2_load (dest, src));
       else if (MEM_P (dest))
        emit_insn (gen_bswapdi2_store (dest, src));
+      else if (TARGET_P9_VECTOR)
+       emit_insn (gen_bswapdi2_xxbrd (dest, src));
       else
        emit_insn (gen_bswapdi2_reg (dest, src));
       DONE;
     }
 
+  if (TARGET_P9_VECTOR && !MEM_P (src) && !MEM_P (dest))
+    {
+      emit_insn (gen_bswapdi2_xxbrd (dest, src));
+      DONE;
+    }
+
   if (!TARGET_POWERPC64)
     {
       /* 32-bit mode needs fewer scratch registers, but 32-bit addressing mode
   "stdbrx %1,%y0"
   [(set_attr "type" "store")])
 
+(define_insn "bswapdi2_xxbrd"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=wo")
+       (bswap:DI (match_operand:DI 1 "gpc_reg_operand" "wo")))]
+  "TARGET_P9_VECTOR"
+  "xxbrd %x0,%x1"
+  [(set_attr "type" "vecperm")])
+
 (define_insn "bswapdi2_reg"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
        (bswap:DI (match_operand:DI 1 "gpc_reg_operand" "r")))
    (clobber (match_scratch:DI 2 "=&r"))
    (clobber (match_scratch:DI 3 "=&r"))]
-  "TARGET_POWERPC64 && TARGET_LDBRX"
+  "TARGET_POWERPC64 && TARGET_LDBRX && !TARGET_P9_VECTOR"
   "#"
   [(set_attr "length" "36")])
 
        (bswap:DI (match_operand:DI 1 "gpc_reg_operand" "")))
    (clobber (match_operand:DI 2 "gpc_reg_operand" ""))
    (clobber (match_operand:DI 3 "gpc_reg_operand" ""))]
-  "TARGET_POWERPC64 && reload_completed"
+  "TARGET_POWERPC64 && !TARGET_P9_VECTOR && reload_completed"
   [(const_int 0)]
   "
 {
index 92379eb..2741168 100644 (file)
@@ -1,3 +1,7 @@
+2017-11-10  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+       * gcc.target/powerpc/p9-xxbr-3.c: New test.
+
 2017-11-10  Uros Bizjak  <ubizjak@gmail.com>
 
        * gcc.target/i386/force-indirect-call-1.c: Merge scan strings.
diff --git a/gcc/testsuite/gcc.target/powerpc/p9-xxbr-3.c b/gcc/testsuite/gcc.target/powerpc/p9-xxbr-3.c
new file mode 100644 (file)
index 0000000..98ad7eb
--- /dev/null
@@ -0,0 +1,99 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mpower9-vector -O2" } */
+
+/* Verify that the XXBR{H,W} instructions are generated if the value is
+   forced to be in a vector register, and XXBRD is generated all of the
+   time for register bswap64's.  */
+
+unsigned short
+do_bswap16_mem (unsigned short *p)
+{
+  return __builtin_bswap16 (*p);       /* LHBRX.  */
+}
+
+unsigned short
+do_bswap16_reg (unsigned short a)
+{
+  return __builtin_bswap16 (a);                /* gpr sequences.  */
+}
+
+void
+do_bswap16_store (unsigned short *p, unsigned short a)
+{
+  *p = __builtin_bswap16 (a);          /* STHBRX.  */
+}
+
+unsigned short
+do_bswap16_vect (unsigned short a)
+{
+  __asm__ (" # %x0" : "+v" (a));
+  return __builtin_bswap16 (a);                /* XXBRW.  */
+}
+
+unsigned int
+do_bswap32_mem (unsigned int *p)
+{
+  return __builtin_bswap32 (*p);       /* LWBRX.  */
+}
+
+unsigned int
+do_bswap32_reg (unsigned int a)
+{
+  return __builtin_bswap32 (a);                /* gpr sequences.  */
+}
+
+void
+do_bswap32_store (unsigned int *p, unsigned int a)
+{
+  *p = __builtin_bswap32 (a);          /* STWBRX.  */
+}
+
+unsigned int
+do_bswap32_vect (unsigned int a)
+{
+  __asm__ (" # %x0" : "+v" (a));
+  return __builtin_bswap32 (a);                /* XXBRW.  */
+}
+
+unsigned long
+do_bswap64_mem (unsigned long *p)
+{
+  return __builtin_bswap64 (*p);       /* LDBRX.  */
+}
+
+unsigned long
+do_bswap64_reg (unsigned long a)
+{
+  return __builtin_bswap64 (a);                /* gpr sequences.  */
+}
+
+void
+do_bswap64_store (unsigned long *p, unsigned int a)
+{
+  *p = __builtin_bswap64 (a);          /* STDBRX.  */
+}
+
+double
+do_bswap64_double (unsigned long a)
+{
+  return (double) __builtin_bswap64 (a);       /* XXBRD.  */
+}
+
+unsigned long
+do_bswap64_vect (unsigned long a)
+{
+  __asm__ (" # %x0" : "+v" (a));       /* XXBRD.  */
+  return __builtin_bswap64 (a);
+}
+
+/* Make sure XXBR{H,W,D} is not generated by default.  */
+/* { dg-final { scan-assembler-times "xxbrd"  3  } } */
+/* { dg-final { scan-assembler-times "xxbrh"  1  } } */
+/* { dg-final { scan-assembler-times "xxbrw"  1  } } */
+/* { dg-final { scan-assembler-times "ldbrx"  1  } } */
+/* { dg-final { scan-assembler-times "lhbrx"  1  } } */
+/* { dg-final { scan-assembler-times "lwbrx"  1  } } */
+/* { dg-final { scan-assembler-times "stdbrx" 1  } } */
+/* { dg-final { scan-assembler-times "sthbrx" 1  } } */
+/* { dg-final { scan-assembler-times "stwbrx" 1  } } */