This patch implements IFN_GOMP_SIMT_REDUCE for AMD GCN, and ensures that
the instructions are handled properly in the simt_vect pass.  The actual
reduction algorithm reuses the SIMD code.

The placeholder xchg_bfly instructions that were just there to allow the build
to succeed can now be removed.

Note: 64-lane reductions are not currently supported on RDNA devices in SIMD
mode, and this limitation will also apply to SIMT mode.

gcc/ChangeLog:

        * config/gcn/gcn.md (UNSPECV_SIMT_REDUCE): New unspecv value.
        (UNSPEC_SIMT_XCHG_BFLY): Remove.
        (SIMT_REDUCE_MODE): New mode iterator.
        (omp_simt_xchg_bfly): Delete.
        (omp_simt_reduce): New.
        (@omp_simt_xchg_bfly<mode>): Delete.
        (@omp_simt_reduce<mode>): New.
        * config/gcn/gcn-valu.md (V64_SIMT_REDUCE_MODE): New mode iterator.
        (omp_simt_xchg_bfly<mode>): Delete.
        (omp_simt_reduce<mode>): New.
        * config/gcn/gcn-simt-vectorize.cc (pass_gcn_simt_vectorize::execute):
        Remove the UNSPEC_SIMT_XCHG_BFLY special case. Add new
        UNSPEC_VOLATILE case for UNSPECV_SIMT_REDUCE.
---
 gcc/config/gcn/gcn-simt-vectorize.cc | 24 +++++++++++++++-
 gcc/config/gcn/gcn-valu.md           | 41 ++++++++++++++++++++++------
 gcc/config/gcn/gcn.md                | 31 ++++++++++++---------
 3 files changed, 74 insertions(+), 22 deletions(-)

diff --git a/gcc/config/gcn/gcn-simt-vectorize.cc 
b/gcc/config/gcn/gcn-simt-vectorize.cc
index 2052eb1741a..8007f6a7fbc 100644
--- a/gcc/config/gcn/gcn-simt-vectorize.cc
+++ b/gcc/config/gcn/gcn-simt-vectorize.cc
@@ -1693,7 +1693,6 @@ pass_gcn_simt_vectorize::execute (function *fn)
                  /* Some UNSPECs have special handling.  */
                  switch (XINT (x, 1))
                    {
-                   case UNSPEC_SIMT_XCHG_BFLY:
                    case UNSPEC_DIV_FMAS:
                      /* The second unspec argument remains scalar, but
                         we do want to recurse into the first argument.  */
@@ -1713,6 +1712,29 @@ pass_gcn_simt_vectorize::execute (function *fn)
                    }
                  break;
 
+               case UNSPEC_VOLATILE:
+                 /* Some UNSPEC_VOLATILEs have special handling.  */
+                 switch (XINT (x, 1))
+                   {
+                   case UNSPECV_SIMT_REDUCE:
+                     /* The second unspec argument remains scalar, but
+                        we do want to recurse into the first argument.  */
+                     delayed_substitute = &XVECEXP (x, 0, 0);
+                     do_transform = true;
+
+                     if (dump_file && (dump_flags & TDF_DETAILS))
+                       {
+                         fprintf (dump_file, "      no-op: ");
+                         dump_value_with_mode (dump_file, XVECEXP (x, 0, 1));
+                         fprintf (dump_file, " (special case)\n");
+                       }
+                     break;
+
+                   default:
+                     do_transform = true;
+                   }
+                 break;
+
                case IF_THEN_ELSE:
                  if (pc_write)
                    {
diff --git a/gcc/config/gcn/gcn-valu.md b/gcc/config/gcn/gcn-valu.md
index 9672b25ea48..697d769587d 100644
--- a/gcc/config/gcn/gcn-valu.md
+++ b/gcc/config/gcn/gcn-valu.md
@@ -4693,14 +4693,39 @@ (define_insn_and_split 
"*vsubreg_read<V64_MOV:mode>di_insn"
     operands[4] = gcn_vec_constant (<MODE>mode, 0);
   })
 
-(define_insn "omp_simt_xchg_bfly<mode>"
-  [(set (match_operand:V_MOV 0 "register_operand"   "=v")
-       (unspec:V_MOV
-         [(match_operand:V_MOV 1 "register_operand" "v")
-          (match_operand:SI 2 "nonmemory_operand"  "Sg")]
-         UNSPEC_SIMT_XCHG_BFLY))]
-  "flag_simt_mode"
-  "; %0 = simt_xchg_bfly %1 %2")
+(define_mode_iterator V64_SIMT_REDUCE_MODE
+  [V64QI V64HI V64SI V64DI V64SF V64DF])
+
+(define_insn_and_split "omp_simt_reduce<mode>"
+  [(set (match_operand:V64_SIMT_REDUCE_MODE 0 "register_operand" "=v")
+       (unspec_volatile:V64_SIMT_REDUCE_MODE
+         [(match_operand:V64_SIMT_REDUCE_MODE 1 "register_operand" "v")
+          (match_operand:SI 2 "const_int_operand" "n")]
+         UNSPECV_SIMT_REDUCE))]
+  "flag_simt_mode && TARGET_DPP_FULL"
+  "#"
+  "can_create_pseudo_p ()"
+  [(const_int 0)]
+  {
+    enum rtx_code rcode = (enum rtx_code) INTVAL (operands[2]);
+    int unspec = (rcode == PLUS ? UNSPEC_PLUS_DPP_SHR
+                 : rcode == UMIN ? UNSPEC_UMIN_DPP_SHR
+                 : rcode == SMIN ? UNSPEC_SMIN_DPP_SHR
+                 : rcode == UMAX ? UNSPEC_UMAX_DPP_SHR
+                 : rcode == SMAX ? UNSPEC_SMAX_DPP_SHR
+                 : rcode == AND ? UNSPEC_AND_DPP_SHR
+                 : rcode == IOR ? UNSPEC_IOR_DPP_SHR
+                 : rcode == XOR ? UNSPEC_XOR_DPP_SHR
+                 : 0);
+    gcc_assert (unspec);
+
+    rtx tmp = gcn_expand_reduc_scalar (<MODE>mode, operands[1], unspec);
+    rtx last_lane = GEN_INT (GET_MODE_NUNITS (<MODE>mode) - 1);
+    rtx scalar = gen_reg_rtx (<SCALAR_MODE>mode);
+    emit_insn (gen_vec_extract<mode><scalar_mode> (scalar, tmp, last_lane));
+    emit_insn (gen_vec_duplicate<mode> (operands[0], scalar));
+    DONE;
+  })
 
 (define_insn_and_split "omp_simt_vote_any_v64si"
   [(set (match_operand:V64SI 0 "register_operand" "=v")
diff --git a/gcc/config/gcn/gcn.md b/gcc/config/gcn/gcn.md
index 4f084606363..fda958da309 100644
--- a/gcc/config/gcn/gcn.md
+++ b/gcc/config/gcn/gcn.md
@@ -65,7 +65,8 @@ (define_c_enum "unspecv" [
   UNSPECV_ICACHE_INV
   UNSPECV_SIMT_FORK UNSPECV_SIMT_JOIN
   UNSPECV_SIMT_ENTER UNSPECV_SIMT_EXIT
-  UNSPECV_SIMT_EXEC_BARRIER])
+  UNSPECV_SIMT_EXEC_BARRIER
+  UNSPECV_SIMT_REDUCE])
 
 (define_c_enum "unspec" [
   UNSPEC_ADDPTR
@@ -93,7 +94,6 @@ (define_c_enum "unspec" [
   UNSPEC_LDEXP UNSPEC_FREXP_EXP UNSPEC_FREXP_MANT
   UNSPEC_DIV_SCALE UNSPEC_DIV_FMAS UNSPEC_DIV_FIXUP
   UNSPEC_PAIR
-  UNSPEC_SIMT_XCHG_BFLY
   UNSPEC_SIMT_VOTE_ANY UNSPEC_SIMT_LAST_LANE UNSPEC_SIMT_XCHG_IDX
   UNSPEC_VSUBREG_WRITE UNSPEC_VSUBREG_READ
   UNSPEC_ENSURE_SCALAR])
@@ -2714,26 +2714,31 @@ (define_expand "omp_simt_lane"
        (reg:SI LANE_ID_REG))]
   "flag_simt_mode")
 
+(define_mode_iterator SIMT_REDUCE_MODE [QI HI SI DI SF DF])
+
+;; Implement IFN_GOMP_SIMT_REDUCE: reduce operand 1 across all active SIMT
+;; lanes using the reduction operator (an rtx_code) given as a const_int in
+;; operand 2, leaving the result broadcast into every lane.
 ; This pseudo instruction should be replaced by the simt_vect pass
-(define_expand "omp_simt_xchg_bfly"
+(define_expand "omp_simt_reduce"
   [(match_operand 0 "register_operand")
    (match_operand 1 "register_operand")
-   (match_operand:SI 2 "nonmemory_operand")]
+   (match_operand:SI 2 "const_int_operand")]
   "flag_simt_mode"
   {
-    emit_insn (gen_omp_simt_xchg_bfly (GET_MODE (operands[0]), operands[0],
-                                      operands[1], operands[2]));
+    emit_insn (gen_omp_simt_reduce (GET_MODE (operands[0]), operands[0],
+                                   operands[1], operands[2]));
     DONE;
   })
 
-(define_insn "@omp_simt_xchg_bfly<mode>"
-  [(set (match_operand:MOV_MODE 0 "register_operand" "=r")
-       (unspec:MOV_MODE
-         [(match_operand:MOV_MODE 1 "register_operand" "r")
-          (match_operand:SI 2 "nonmemory_operand" "ri")]
-         UNSPEC_SIMT_XCHG_BFLY))]
+(define_insn "@omp_simt_reduce<mode>"
+  [(set (match_operand:SIMT_REDUCE_MODE 0 "register_operand" "=r")
+       (unspec_volatile:SIMT_REDUCE_MODE
+         [(match_operand:SIMT_REDUCE_MODE 1 "register_operand" "r")
+          (match_operand:SI 2 "const_int_operand" "n")]
+         UNSPECV_SIMT_REDUCE))]
   "flag_simt_mode"
-  "; %0 = simt_xchg_bfly %1 %2")
+  "; %0 = simt_reduce %1 %2")
 
 ;; Implement IFN_GOMP_SIMT_VOTE_ANY:
 ;; set operand 0 to zero iff all lanes supply zero in operand 1
-- 
2.54.0

Reply via email to