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

junyan.he at inbox.com junyan.he at inbox.com
Mon Apr 20 23:11:09 PDT 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 |  158 ++++++++++++++++++++++++++++++++++++++++
 backend/src/ir/instruction.hpp |   29 +++++++-
 backend/src/ir/instruction.hxx |    1 +
 3 files changed, 187 insertions(+), 1 deletion(-)

diff --git a/backend/src/ir/instruction.cpp b/backend/src/ir/instruction.cpp
index 797552f..02498bc 100644
--- a/backend/src/ir/instruction.cpp
+++ b/backend/src/ir/instruction.cpp
@@ -676,6 +676,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];
+    };
+
     class ALIGNED_INSTRUCTION ReadARFInstruction :
       public BasePolicy,
       public NSrcPolicy<ReadARFInstruction, 0>,
@@ -1118,6 +1148,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
 
     /////////////////////////////////////////////////////////////////////////
@@ -1253,7 +1331,76 @@ 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) {
+        int localN = srcNum - 1;
+        GBE_ASSERT(localN);
+        out << " Local X:";
+        out << " %" << this->getSrc(fn, 1);
+        localN--;
+        if (!localN)
+          return;
+
+        out << " Local Y:";
+        out << " %" << this->getSrc(fn, 2);
+        localN--;
+        if (!localN)
+          return;
 
+        out << " Local Z:";
+        out << " %" << this->getSrc(fn, 3);
+        localN--;
+        GBE_ASSERT(!localN);
+      }
+
+      out << "TheadID Map at SLM: " << this->slmAddr;
+    }
   } /* namespace internal */
 
   std::ostream &operator<< (std::ostream &out, AddressSpace addrSpace) {
@@ -1381,6 +1528,10 @@ START_INTROSPECTION(LabelInstruction)
 #include "ir/instruction.hxx"
 END_INTROSPECTION(LabelInstruction)
 
+START_INTROSPECTION(WorkGroupInstruction)
+#include "ir/instruction.hxx"
+END_INTROSPECTION(WorkGroupInstruction)
+
 #undef END_INTROSPECTION
 #undef START_INTROSPECTION
 #undef DECL_INSN
@@ -1574,6 +1725,9 @@ DECL_MEM_FN(TypedWriteInstruction, Type, getCoordType(void), getCoordType())
 DECL_MEM_FN(TypedWriteInstruction, uint8_t, getImageIndex(void), getImageIndex())
 DECL_MEM_FN(GetImageInfoInstruction, uint32_t, getInfoType(void), getInfoType())
 DECL_MEM_FN(GetImageInfoInstruction, uint8_t, getImageIndex(void), getImageIndex())
+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
 
@@ -1792,6 +1946,10 @@ DECL_MEM_FN(GetImageInfoInstruction, uint8_t, getImageIndex(void), getImageIndex
     return internal::GetImageInfoInstruction(infoType, dst, imageIndex, infoReg).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 24d27aa..49d5e17 100644
--- a/backend/src/ir/instruction.hpp
+++ b/backend/src/ir/instruction.hpp
@@ -78,6 +78,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,
@@ -512,6 +528,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
    */
@@ -715,7 +741,8 @@ namespace ir {
   Instruction GET_IMAGE_INFO(int infoType, Register dst, uint8_t imageIndex, Register infoReg);
   /*! label labelIndex */
   Instruction LABEL(LabelIndex labelIndex);
-
+  /*! 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 de4abfb..f2ef722 100644
--- a/backend/src/ir/instruction.hxx
+++ b/backend/src/ir/instruction.hxx
@@ -102,3 +102,4 @@ DECL_INSN(IF, BranchInstruction)
 DECL_INSN(ENDIF, BranchInstruction)
 DECL_INSN(ELSE, BranchInstruction)
 DECL_INSN(WHILE, BranchInstruction)
+DECL_INSN(WORKGROUP, WorkGroupInstruction)
-- 
1.7.9.5



More information about the Beignet mailing list