summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/src/ir/instruction.cpp161
-rw-r--r--backend/src/ir/instruction.hpp28
-rw-r--r--backend/src/ir/instruction.hxx1
3 files changed, 190 insertions, 0 deletions
diff --git a/backend/src/ir/instruction.cpp b/backend/src/ir/instruction.cpp
index c7facfbd..734e66b7 100644
--- a/backend/src/ir/instruction.cpp
+++ b/backend/src/ir/instruction.cpp
@@ -964,6 +964,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
/////////////////////////////////////////////////////////////////////////
@@ -1395,6 +1425,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
/////////////////////////////////////////////////////////////////////////
@@ -1552,6 +1630,78 @@ namespace ir {
this->outOpcode(out);
}
+ 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) {
@@ -1708,6 +1858,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
@@ -1914,6 +2068,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
@@ -2204,6 +2361,10 @@ DECL_MEM_FN(MemInstruction, void, setBtiReg(Register reg), setBtiReg(reg))
return internal::WaitInstruction().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 76ffd778..9881ff49 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,
@@ -582,6 +598,16 @@ namespace ir {
/*! Return true if the given instruction is an instance of this class */
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
@@ -807,6 +833,8 @@ namespace ir {
/*! wait */
Instruction WAIT(void);
+ /*! 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 efdd4c5e..27c71594 100644
--- a/backend/src/ir/instruction.hxx
+++ b/backend/src/ir/instruction.hxx
@@ -110,3 +110,4 @@ DECL_INSN(WHILE, BranchInstruction)
DECL_INSN(CALC_TIMESTAMP, CalcTimestampInstruction)
DECL_INSN(STORE_PROFILING, StoreProfilingInstruction)
DECL_INSN(WAIT, WaitInstruction)
+DECL_INSN(WORKGROUP, WorkGroupInstruction)