[Beignet] [PATCH 06/10 OpenCL-2.0] Add WORKGROUP_OP instruction selection.

junyan.he at inbox.com junyan.he at inbox.com
Wed Apr 22 20:26:13 PDT 2015


From: Junyan He <junyan.he at linux.intel.com>

Signed-off-by: Junyan He <junyan.he at linux.intel.com>
---
 .../src/backend/gen_insn_gen7_schedule_info.hxx    |    1 +
 backend/src/backend/gen_insn_selection.cpp         |   42 +++++++++++++++++++-
 backend/src/backend/gen_insn_selection.hpp         |    1 +
 backend/src/backend/gen_insn_selection.hxx         |    1 +
 4 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/backend/src/backend/gen_insn_gen7_schedule_info.hxx b/backend/src/backend/gen_insn_gen7_schedule_info.hxx
index d054820..37aaaf8 100644
--- a/backend/src/backend/gen_insn_gen7_schedule_info.hxx
+++ b/backend/src/backend/gen_insn_gen7_schedule_info.hxx
@@ -42,3 +42,4 @@ DECL_GEN7_SCHEDULE(Atomic,          80,        1,        1)
 DECL_GEN7_SCHEDULE(I64MUL,          20,        40,      20)
 DECL_GEN7_SCHEDULE(I64SATADD,       20,        40,      20)
 DECL_GEN7_SCHEDULE(I64SATSUB,       20,        40,      20)
+DECL_GEN7_SCHEDULE(WorkGroupOp,     80,         1,       1)
diff --git a/backend/src/backend/gen_insn_selection.cpp b/backend/src/backend/gen_insn_selection.cpp
index 797233e..37fa55d 100644
--- a/backend/src/backend/gen_insn_selection.cpp
+++ b/backend/src/backend/gen_insn_selection.cpp
@@ -646,6 +646,8 @@ namespace gbe
     void I64DIV(Reg dst, Reg src0, Reg src1, GenRegister *tmp, int tmp_int);
     /*! 64-bit integer remainder of division */
     void I64REM(Reg dst, Reg src0, Reg src1, GenRegister *tmp, int tmp_int);
+    /*! Work Group Operations */
+    void WORKGROUP_OP(uint32_t wg_op, Reg dst, GenRegister src, GenRegister nextThreadID);
     /* common functions for both binary instruction and sel_cmp and compare instruction.
        It will handle the IMM or normal register assignment, and will try to avoid LOADI
        as much as possible. */
@@ -1563,6 +1565,16 @@ namespace gbe
       insn->dst(i + 1) = tmp[i];
   }
 
+  void Selection::Opaque::WORKGROUP_OP(uint32_t wg_op, Reg dst, GenRegister src, GenRegister nextThreadID) {
+    SelectionInstruction *insn = this->appendInsn(SEL_OP_WORKGROUP_OP, 2, 2);
+    insn->extra.workgroupOp = wg_op;
+    insn->dst(0) = dst;
+    insn->dst(1) = nextThreadID;
+
+    insn->src(0) = src;
+    insn->src(1) = nextThreadID;
+  }
+
   // Boiler plate to initialize the selection library at c++ pre-main
   static SelectionLibrary *selLib = NULL;
   static void destroySelectionLibrary(void) { GBE_DELETE(selLib); }
@@ -4076,7 +4088,7 @@ namespace gbe
     DECL_CTOR(ConvertInstruction, 1, 1);
   };
 
-  /*! Convert instruction pattern */
+  /*! Atomic instruction pattern */
   DECL_PATTERN(AtomicInstruction)
   {
     INLINE bool emitOne(Selection::Opaque &sel, const ir::AtomicInstruction &insn, bool &markChildren) const
@@ -4292,9 +4304,37 @@ namespace gbe
 
       if (workGroupOp == WORKGROUP_OP_BROADCAST) {
         return emitWGBroadcast(sel, insn);
+      } else if (workGroupOp >= WORKGROUP_OP_REDUCE_ADD && workGroupOp <= WORKGROUP_OP_EXCLUSIVE_MAX) {
+        const uint32_t slmAddr = insn.getSlmAddr();
+        /* First, we create the TheadID/localID map, in order to get which thread hold the next 16 workitems. */
+        if (!sel.storeThreadMap) {
+          this->storeThreadID(sel, slmAddr);
+          sel.storeThreadMap = true;
+        }
+
+        /* Then we insert a barrier to make sure all the var we are interested in
+           have been assigned the final value. */
+        sel.BARRIER(GenRegister::ud8grf(sel.reg(FAMILY_DWORD)), sel.selReg(sel.reg(FAMILY_DWORD)), syncLocalBarrier);
+
+        /* Third, get the next thread ID which we will Forward MSG to. */
+        GenRegister nextThreadID = getNextThreadID(sel, slmAddr);
+
+        const Type type = insn.getType();
+        const GenRegister dst = sel.selReg(insn.getDst(0), type);
+        const uint32_t srcNum = insn.getSrcNum();
+        GBE_ASSERT(srcNum == 3);
+        GBE_ASSERT(insn.getSrc(1) == ir::ocl::threadn);
+        GBE_ASSERT(insn.getSrc(2) == ir::ocl::threadid);
+        GenRegister src = sel.selReg(insn.getSrc(0), type);
+	sel.push(); {
+	  sel.curr.flag = 0;
+	  sel.curr.subFlag = 1;
+	  sel.WORKGROUP_OP(workGroupOp, dst, src, nextThreadID);
+	} sel.pop();
       } else {
         GBE_ASSERT(0);
       }
+
       return true;
     }
     DECL_CTOR(WorkGroupInstruction, 1, 1);
diff --git a/backend/src/backend/gen_insn_selection.hpp b/backend/src/backend/gen_insn_selection.hpp
index 6a08180..018a1a2 100644
--- a/backend/src/backend/gen_insn_selection.hpp
+++ b/backend/src/backend/gen_insn_selection.hpp
@@ -132,6 +132,7 @@ namespace gbe
       };
       uint32_t barrierType;
       bool longjmp;
+      uint32_t workgroupOp;
     } extra;
     /*! Gen opcode */
     uint8_t opcode;
diff --git a/backend/src/backend/gen_insn_selection.hxx b/backend/src/backend/gen_insn_selection.hxx
index 09f5aaf..567d186 100644
--- a/backend/src/backend/gen_insn_selection.hxx
+++ b/backend/src/backend/gen_insn_selection.hxx
@@ -89,3 +89,4 @@ DECL_SELECTION_IR(ENDIF, UnaryInstruction)
 DECL_SELECTION_IR(ELSE, UnaryInstruction)
 DECL_SELECTION_IR(READ_ARF, UnaryInstruction)
 DECL_SELECTION_IR(WHILE, UnaryInstruction)
+DECL_SELECTION_IR(WORKGROUP_OP, WorkGroupOpInstruction)
-- 
1.7.9.5





More information about the Beignet mailing list