[Beignet] [PATCH 2/5 V2] Add the WorkGroupInstruction as a new type of instruction.

junyan.he at inbox.com junyan.he at inbox.com
Tue Nov 17 22:06:44 PST 2015


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

Signed-off-by: Junyan He <junyan.he at linux.intel.com>
---
 backend/src/ir/instruction.cpp |  160 ++++++++++++++++++++++++++++++++++++++++
 backend/src/ir/instruction.hpp |   28 +++++++
 backend/src/ir/instruction.hxx |    1 +
 3 files changed, 189 insertions(+)

diff --git a/backend/src/ir/instruction.cpp b/backend/src/ir/instruction.cpp
index 6ed0b89..33be93a 100644
--- a/backend/src/ir/instruction.cpp
+++ b/backend/src/ir/instruction.cpp
@@ -949,6 +949,36 @@ namespace ir {
       Register dst[0], src[0];
     };
 
+    class ALIGNED_INSTRUCTION WorkGroupInstruction :
+      public BasePolicy,
+      public TupleSrcPolicy<WorkGroupInstruction>,
+      public NDstPolicy<WorkGroupInstruction, 1>
+    {
+      public:
+        INLINE WorkGroupInstruction(WorkGroupOps opcode, uint32_t slmAddr, Register dst,
+            Tuple srcTuple, uint8_t srcNum, Type type) {
+          this->opcode = OP_WORKGROUP;
+          this->workGroupOp = opcode;
+          this->type = type;
+          this->dst[0] = dst;
+          this->src = srcTuple;
+          this->srcNum = srcNum;
+          this->slmAddr = slmAddr;
+        }
+        INLINE Type getType(void) const { return this->type; }
+        INLINE bool wellFormed(const Function &fn, std::string &whyNot) const;
+        INLINE void out(std::ostream &out, const Function &fn) const;
+        INLINE WorkGroupOps getWorkGroupOpcode(void) const { return this->workGroupOp; }
+        uint32_t getSlmAddr(void) const { return this->slmAddr; }
+
+        WorkGroupOps workGroupOp:5;
+        uint32_t srcNum:3;          //!< Source Number
+        uint32_t slmAddr:24;        //!< Thread Map in SLM.
+        Type type;                  //!< Type of the instruction
+        Tuple src;
+        Register dst[1];
+    };
+
 #undef ALIGNED_INSTRUCTION
 
     /////////////////////////////////////////////////////////////////////////
@@ -1378,6 +1408,54 @@ namespace ir {
       return true;
     }
 
+    INLINE bool WorkGroupInstruction::wellFormed(const Function &fn, std::string &whyNot) const {
+      const RegisterFamily family = getFamily(this->type);
+      if (UNLIKELY(checkSpecialRegForWrite(dst[0], fn, whyNot) == false))
+        return false;
+      if (UNLIKELY(checkRegisterData(family, dst[0], fn, whyNot) == false))
+        return false;
+      const Register src0 = fn.getRegister(src, 0);
+      if (UNLIKELY(checkRegisterData(family, src0, fn, whyNot) == false))
+        return false;
+
+      switch (this->workGroupOp) {
+        case WORKGROUP_OP_ANY:
+        case WORKGROUP_OP_ALL:
+        case WORKGROUP_OP_REDUCE_ADD:
+        case WORKGROUP_OP_REDUCE_MIN:
+        case WORKGROUP_OP_REDUCE_MAX:
+        case WORKGROUP_OP_INCLUSIVE_ADD:
+        case WORKGROUP_OP_INCLUSIVE_MIN:
+        case WORKGROUP_OP_INCLUSIVE_MAX:
+        case WORKGROUP_OP_EXCLUSIVE_ADD:
+        case WORKGROUP_OP_EXCLUSIVE_MIN:
+        case WORKGROUP_OP_EXCLUSIVE_MAX:
+          if (this->srcNum != 1) {
+            whyNot = "Wrong number of source.";
+            return false;
+          }
+          break;
+        case WORKGROUP_OP_BROADCAST:
+          if (this->srcNum <= 1) {
+            whyNot = "Wrong number of source.";
+            return false;
+          } else {
+            const RegisterFamily fam = FAMILY_DWORD;
+            for (uint32_t srcID = 1; srcID < this->srcNum; ++srcID) {
+              const Register regID = fn.getRegister(src, srcID);
+              if (UNLIKELY(checkRegisterData(fam, regID, fn, whyNot) == false))
+                return false;
+            }
+          }
+          break;
+        default:
+          whyNot = "No such work group function.";
+          return false;
+      }
+
+      return true;
+    }
+
 #undef CHECK_TYPE
 
     /////////////////////////////////////////////////////////////////////////
@@ -1531,7 +1609,78 @@ namespace ir {
           out << "." << syncStr[field];
     }
 
+    INLINE void WorkGroupInstruction::out(std::ostream &out, const Function &fn) const {
+      this->outOpcode(out);
 
+      switch (this->workGroupOp) {
+        case WORKGROUP_OP_ANY:
+          out << "_" << "ANY";
+          break;
+        case WORKGROUP_OP_ALL:
+          out << "_" << "ALL";
+          break;
+        case WORKGROUP_OP_REDUCE_ADD:
+          out << "_" << "REDUCE_ADD";
+          break;
+        case WORKGROUP_OP_REDUCE_MIN:
+          out << "_" << "REDUCE_MIN";
+          break;
+        case WORKGROUP_OP_REDUCE_MAX:
+          out << "_" << "REDUCE_MAX";
+          break;
+        case WORKGROUP_OP_INCLUSIVE_ADD:
+          out << "_" << "INCLUSIVE_ADD";
+          break;
+        case WORKGROUP_OP_INCLUSIVE_MIN:
+          out << "_" << "INCLUSIVE_MIN";
+          break;
+        case WORKGROUP_OP_INCLUSIVE_MAX:
+          out << "_" << "INCLUSIVE_MAX";
+          break;
+        case WORKGROUP_OP_EXCLUSIVE_ADD:
+          out << "_" << "EXCLUSIVE_ADD";
+          break;
+        case WORKGROUP_OP_EXCLUSIVE_MIN:
+          out << "_" << "EXCLUSIVE_MIN";
+          break;
+        case WORKGROUP_OP_EXCLUSIVE_MAX:
+          out << "_" << "EXCLUSIVE_MAX";
+          break;
+        case WORKGROUP_OP_BROADCAST:
+          out << "_" << "BROADCAST";
+          break;
+        default:
+          GBE_ASSERT(0);
+      }
+
+      out << " %" << this->getDst(fn, 0);
+      out << " %" << this->getSrc(fn, 0);
+
+      if (this->workGroupOp == WORKGROUP_OP_BROADCAST) {
+        do {
+          int localN = srcNum - 1;
+          GBE_ASSERT(localN);
+          out << " Local X:";
+          out << " %" << this->getSrc(fn, 1);
+          localN--;
+          if (!localN)
+            break;
+
+          out << " Local Y:";
+          out << " %" << this->getSrc(fn, 2);
+          localN--;
+          if (!localN)
+            break;
+
+          out << " Local Z:";
+          out << " %" << this->getSrc(fn, 3);
+          localN--;
+          GBE_ASSERT(!localN);
+        } while(0);
+      }
+
+      out << "TheadID Map at SLM: " << this->slmAddr;
+    }
   } /* namespace internal */
 
   std::ostream &operator<< (std::ostream &out, AddressSpace addrSpace) {
@@ -1684,6 +1833,10 @@ START_INTROSPECTION(VmeInstruction)
 #include "ir/instruction.hxx"
 END_INTROSPECTION(VmeInstruction)
 
+START_INTROSPECTION(WorkGroupInstruction)
+#include "ir/instruction.hxx"
+END_INTROSPECTION(WorkGroupInstruction)
+
 #undef END_INTROSPECTION
 #undef START_INTROSPECTION
 #undef DECL_INSN
@@ -1889,6 +2042,9 @@ DECL_MEM_FN(CalcTimestampInstruction, uint32_t, getPointNum(void), getPointNum()
 DECL_MEM_FN(CalcTimestampInstruction, uint32_t, getTimestamptType(void), getTimestamptType())
 DECL_MEM_FN(StoreProfilingInstruction, uint32_t, getProfilingType(void), getProfilingType())
 DECL_MEM_FN(StoreProfilingInstruction, uint32_t, getBTI(void), getBTI())
+DECL_MEM_FN(WorkGroupInstruction, Type, getType(void), getType())
+DECL_MEM_FN(WorkGroupInstruction, WorkGroupOps, getWorkGroupOpcode(void), getWorkGroupOpcode())
+DECL_MEM_FN(WorkGroupInstruction, uint32_t, getSlmAddr(void), getSlmAddr())
 
 #undef DECL_MEM_FN
 
@@ -2174,6 +2330,10 @@ DECL_MEM_FN(MemInstruction, void,     setBtiReg(Register reg), setBtiReg(reg))
     return internal::StoreProfilingInstruction(bti, profilingType).convert();
   }
 
+  Instruction WORKGROUP(WorkGroupOps opcode, uint32_t slmAddr, Register dst, Tuple srcTuple, uint8_t srcNum, Type type) {
+    return internal::WorkGroupInstruction(opcode, slmAddr, dst, srcTuple, srcNum, type).convert();
+  }
+
   std::ostream &operator<< (std::ostream &out, const Instruction &insn) {
     const Function &fn = insn.getFunction();
     const BasicBlock *bb = insn.getParent();
diff --git a/backend/src/ir/instruction.hpp b/backend/src/ir/instruction.hpp
index 7862bbf..3a5a681 100644
--- a/backend/src/ir/instruction.hpp
+++ b/backend/src/ir/instruction.hpp
@@ -89,6 +89,22 @@ namespace ir {
     ATOMIC_OP_INVALID
   };
 
+  enum WorkGroupOps {
+    WORKGROUP_OP_ANY = 1,
+    WORKGROUP_OP_ALL = 2,
+    WORKGROUP_OP_BROADCAST = 3,
+    WORKGROUP_OP_REDUCE_ADD = 4,
+    WORKGROUP_OP_REDUCE_MIN = 5,
+    WORKGROUP_OP_REDUCE_MAX = 6,
+    WORKGROUP_OP_INCLUSIVE_ADD = 7,
+    WORKGROUP_OP_INCLUSIVE_MIN = 8,
+    WORKGROUP_OP_INCLUSIVE_MAX = 9,
+    WORKGROUP_OP_EXCLUSIVE_ADD = 10,
+    WORKGROUP_OP_EXCLUSIVE_MIN = 11,
+    WORKGROUP_OP_EXCLUSIVE_MAX = 12,
+    WORKGROUP_OP_INVALID
+  };
+
   /* Vote function per hardware thread */
   enum VotePredicate : uint8_t {
     VOTE_ALL = 0,
@@ -576,6 +592,16 @@ namespace ir {
     static bool isClassOf(const Instruction &insn);
   };
 
+  /*! Related to Work Group. */
+  class WorkGroupInstruction : public Instruction {
+  public:
+    /*! Return true if the given instruction is an instance of this class */
+    static bool isClassOf(const Instruction &insn);
+    Type getType(void) const;
+    WorkGroupOps getWorkGroupOpcode(void) const;
+    uint32_t getSlmAddr(void) const;
+  };
+
   /*! Specialize the instruction. Also performs typechecking first based on the
    *  opcode. Crashes if it fails
    */
@@ -797,6 +823,8 @@ namespace ir {
   Instruction CALC_TIMESTAMP(uint32_t pointNum, uint32_t tsType);
   /*! calculate the execute timestamp for profiling */
   Instruction STORE_PROFILING(uint32_t bti, uint32_t Type);
+  /*! work group */
+  Instruction WORKGROUP(WorkGroupOps opcode, uint32_t slmAddr, Register dst, Tuple srcTuple, uint8_t srcNum, Type type);
 } /* namespace ir */
 } /* namespace gbe */
 
diff --git a/backend/src/ir/instruction.hxx b/backend/src/ir/instruction.hxx
index 1282747..e08889d 100644
--- a/backend/src/ir/instruction.hxx
+++ b/backend/src/ir/instruction.hxx
@@ -109,3 +109,4 @@ DECL_INSN(ELSE, BranchInstruction)
 DECL_INSN(WHILE, BranchInstruction)
 DECL_INSN(CALC_TIMESTAMP, CalcTimestampInstruction)
 DECL_INSN(STORE_PROFILING, StoreProfilingInstruction)
+DECL_INSN(WORKGROUP, WorkGroupInstruction)
-- 
1.7.9.5





More information about the Beignet mailing list