From 5e762bb671b602164d31ffdd19500e8c9c355bf0 Mon Sep 17 00:00:00 2001 From: Benjamin Segovia Date: Tue, 5 Jun 2012 00:07:51 +0000 Subject: [PATCH] Finished first implementation of the boiler plate code to separate instruction selection from the rest (final encoding and register allocation). Neither debugged nor activated. --- backend/src/backend/gen_context.cpp | 170 ++++++++++++++++++++++++++--- backend/src/backend/gen_context.hpp | 13 ++- backend/src/backend/gen_insn_selection.cpp | 4 +- backend/src/backend/gen_insn_selection.hpp | 2 +- backend/src/backend/gen_reg_allocation.cpp | 34 ++++++ backend/src/backend/gen_reg_allocation.hpp | 5 +- 6 files changed, 206 insertions(+), 22 deletions(-) diff --git a/backend/src/backend/gen_context.cpp b/backend/src/backend/gen_context.cpp index 4afcd0a..982c89d 100644 --- a/backend/src/backend/gen_context.cpp +++ b/backend/src/backend/gen_context.cpp @@ -592,7 +592,10 @@ namespace gbe } } - void GenContext::emitFenceInstruction(const ir::FenceInstruction &insn) {} + void GenContext::emitFenceInstruction(const ir::FenceInstruction &insn) { + NOT_IMPLEMENTED; + } + void GenContext::emitLabelInstruction(const ir::LabelInstruction &insn) { using namespace ir; const LabelIndex label = insn.getLabelIndex(); @@ -691,6 +694,19 @@ namespace gbe }); } + void GenContext::emitInstructionStream2(void) { + // Emit Gen ISA + sel->foreachInstruction([&](const SelectionInstruction &insn) { + const uint32_t opcode = insn.opcode; + switch (opcode) { +#define DECL_SELECTION_IR(OPCODE, FAMILY) \ + case SEL_OP_##OPCODE: this->emit##FAMILY(insn); break; +#include "backend/gen_insn_selection.hxx" +#undef DECL_INSN + } + }); + } + void GenContext::patchBranches(void) { using namespace ir; for (auto pair : branchPos) { @@ -702,28 +718,156 @@ namespace gbe } } + void GenContext::patchBranches2(void) { + using namespace ir; + for (auto pair : branchPos2) { + const LabelIndex label = pair.first; + const int32_t insnID = pair.second; + const int32_t targetID = labelPos.find(label)->second; + p->patchJMPI(insnID, (targetID-insnID-1) * 2); + } + } + ///////////////////// XXX /////////////////////// void GenContext::emitLabelInstruction(const SelectionInstruction &insn) { const ir::LabelIndex label(insn.index); this->labelPos.insert(std::make_pair(label, p->insnNum)); } + /*! XXX Make both structures the same! */ + INLINE void setInstructionState(GenInstructionState &dst, + const SelectionState &src) + { + dst.execWidth = src.execWidth; + dst.quarterControl = src.quarterControl; + dst.noMask = src.noMask; + dst.flag = src.flag; + dst.subFlag = src.subFlag; + dst.predicate = src.predicate; + dst.inversePredicate = src.inversePredicate; + } + void GenContext::emitUnaryInstruction(const SelectionInstruction &insn) { + const GenReg dst = ra->genReg(insn.dst[0]); + const GenReg src = ra->genReg(insn.src[0]); + p->push(); + setInstructionState(p->curr, insn.state); + switch (insn.opcode) { + case SEL_OP_MOV: p->MOV(dst, src); break; + default: NOT_IMPLEMENTED; + } + p->pop(); + } + + void GenContext::emitBinaryInstruction(const SelectionInstruction &insn) { + const GenReg dst = ra->genReg(insn.dst[0]); + const GenReg src0 = ra->genReg(insn.src[0]); + const GenReg src1 = ra->genReg(insn.src[1]); + p->push(); + setInstructionState(p->curr, insn.state); + switch (insn.opcode) { + case SEL_OP_AND: p->AND(dst, src0, src1); break; + case SEL_OP_OR: p->OR(dst, src0, src1); break; + case SEL_OP_XOR: p->XOR(dst, src0, src1); break; + case SEL_OP_SHR: p->SHR(dst, src0, src1); break; + case SEL_OP_SHL: p->SHL(dst, src0, src1); break; + case SEL_OP_RSR: p->RSR(dst, src0, src1); break; + case SEL_OP_RSL: p->RSL(dst, src0, src1); break; + case SEL_OP_ASR: p->ASR(dst, src0, src1); break; + case SEL_OP_ADD: p->ADD(dst, src0, src1); break; + case SEL_OP_MUL: p->MUL(dst, src0, src1); break; + case SEL_OP_MACH: p->MACH(dst, src0, src1); break; + default: NOT_IMPLEMENTED; + } + p->pop(); + } + void GenContext::emitSelectInstruction(const SelectionInstruction &insn) { + NOT_IMPLEMENTED; } - void GenContext::emitBinaryInstruction(const SelectionInstruction &insn){} - void GenContext::emitSelectInstruction(const SelectionInstruction &insn){} - void GenContext::emitCompareInstruction(const SelectionInstruction &insn){} - void GenContext::emitJumpInstruction(const SelectionInstruction &insn){} - void GenContext::emitEotInstruction(const SelectionInstruction &insn){} - void GenContext::emitNoOpInstruction(const SelectionInstruction &insn){} - void GenContext::emitWaitInstruction(const SelectionInstruction &insn){} - void GenContext::emitMathInstruction(const SelectionInstruction &insn){} - void GenContext::emitUntypedReadInstruction(const SelectionInstruction &insn){} - void GenContext::emitUntypedWriteInstruction(const SelectionInstruction &insn){} - void GenContext::emitByteGatherInstruction(const SelectionInstruction &insn){} - void GenContext::emitByteScatterInstruction(const SelectionInstruction &insn){} + void GenContext::emitNoOpInstruction(const SelectionInstruction &insn) { + NOT_IMPLEMENTED; + } + + void GenContext::emitWaitInstruction(const SelectionInstruction &insn) { + NOT_IMPLEMENTED; + } + + void GenContext::emitMathInstruction(const SelectionInstruction &insn) { + NOT_IMPLEMENTED; + } + + void GenContext::emitCompareInstruction(const SelectionInstruction &insn) { + const GenReg src0 = ra->genReg(insn.src[0]); + const GenReg src1 = ra->genReg(insn.src[1]); + p->push(); + setInstructionState(p->curr, insn.state); + p->CMP(insn.function, src0, src1); + p->pop(); + } + + void GenContext::emitJumpInstruction(const SelectionInstruction &insn) { + const ir::LabelIndex label(insn.index); + const GenReg src = ra->genReg(insn.src[0]); + this->branchPos2.push_back(std::make_pair(label, p->insnNum)); + p->push(); + setInstructionState(p->curr, insn.state); + p->JMPI(src); + p->pop(); + } + + void GenContext::emitEotInstruction(const SelectionInstruction &insn) { + p->push(); + p->curr.predicate = GEN_PREDICATE_NONE; + p->curr.execWidth = 8; + p->curr.noMask = 1; + p->MOV(GenReg::f8grf(127,0), GenReg::f8grf(0,0)); + p->EOT(127); + p->pop(); + } + + void GenContext::emitUntypedReadInstruction(const SelectionInstruction &insn) { + const GenReg dst = ra->genReg(insn.dst[0]); + const GenReg src = ra->genReg(insn.src[0]); + const uint32_t bti = insn.function; + const uint32_t elemNum = insn.elem; + p->push(); + setInstructionState(p->curr, insn.state); + p->UNTYPED_READ(dst, src, bti, elemNum); + p->pop(); + } + + void GenContext::emitUntypedWriteInstruction(const SelectionInstruction &insn) { + const GenReg src = ra->genReg(insn.src[0]); + const uint32_t bti = insn.function; + const uint32_t elemNum = insn.elem; + p->push(); + setInstructionState(p->curr, insn.state); + p->UNTYPED_WRITE(src, bti, elemNum); + p->pop(); + } + + void GenContext::emitByteGatherInstruction(const SelectionInstruction &insn) { + const GenReg dst = ra->genReg(insn.dst[0]); + const GenReg src = ra->genReg(insn.src[0]); + const uint32_t bti = insn.function; + const uint32_t elemSize = insn.elem; + p->push(); + setInstructionState(p->curr, insn.state); + p->BYTE_GATHER(dst, src, bti, elemSize); + p->pop(); + } + + void GenContext::emitByteScatterInstruction(const SelectionInstruction &insn) { + const GenReg src = ra->genReg(insn.src[0]); + const uint32_t bti = insn.function; + const uint32_t elemSize = insn.elem; + p->push(); + setInstructionState(p->curr, insn.state); + p->BYTE_SCATTER(src, bti, elemSize); + p->pop(); + } BVAR(OCL_OUTPUT_ASM, false); void GenContext::emitCode(void) { diff --git a/backend/src/backend/gen_context.hpp b/backend/src/backend/gen_context.hpp index 67a76e0..cef3096 100644 --- a/backend/src/backend/gen_context.hpp +++ b/backend/src/backend/gen_context.hpp @@ -38,7 +38,8 @@ namespace gbe class GenEmitter; // Helps emitting Gen ISA class GenRegAllocator; // Handle the register allocation class Selection; // Performs instruction selection - class SelectionInstruction; // Pre-RA GEN instruction + class SelectionInstruction; // Pre-RA Gen instruction + class SelectionReg; // Pre-RA Gen register /*! Context is the helper structure to build the Gen ISA or simulation code * from GenIR @@ -62,8 +63,12 @@ namespace gbe void emitStackPointer(void); /*! Emit the instructions */ void emitInstructionStream(void); + /*! Emit the instructions */ + void emitInstructionStream2(void); /*! Set the correct target values for the branches */ void patchBranches(void); + /*! Set the correct target values for the branches */ + void patchBranches2(void); /*! Bool registers will use scalar words. So we will consider them as * scalars in Gen backend */ @@ -72,8 +77,6 @@ namespace gbe INLINE bool isSpecialReg(ir::Register reg) const { return fn.isSpecialReg(reg); } - /*! Build the final physical register */ - GenReg getGenReg(ir::Register reg, const SelectionReg &selReg) const; /*! Emit instruction per family */ void emitUnaryInstruction(const ir::UnaryInstruction &insn); @@ -121,12 +124,12 @@ namespace gbe /*! Implements base class */ virtual Kernel *allocateKernel(void); - /*! Simplistic allocation to start with */ - // map RA; /*! Store the position of each label instruction in the Gen ISA stream */ map labelPos; /*! Store the position of each branch instruction in the Gen ISA stream */ map branchPos; + /*! Store the Gen instructions to patch */ + vector> branchPos2; /*! Encode Gen ISA */ GenEmitter *p; /*! Instruction selection on Gen ISA (pre-register allocation) */ diff --git a/backend/src/backend/gen_insn_selection.cpp b/backend/src/backend/gen_insn_selection.cpp index 2b236da..0dc6db8 100644 --- a/backend/src/backend/gen_insn_selection.cpp +++ b/backend/src/backend/gen_insn_selection.cpp @@ -246,9 +246,8 @@ namespace gbe insn->dstNum = 0; } - void Selection::EOT(Reg src) { + void Selection::EOT(void) { SelectionInstruction *insn = this->appendInsn(); - insn->src[0] = src; insn->opcode = SEL_OP_EOT; insn->state = this->curr; insn->srcNum = 1; @@ -936,6 +935,7 @@ namespace gbe this->EOT(127); this->pop(); #endif + this->EOT(); } else if (opcode == OP_BRA) { const LabelIndex dst = insn.getLabelIndex(); const LabelIndex src = insn.getParent()->getLabelIndex(); diff --git a/backend/src/backend/gen_insn_selection.hpp b/backend/src/backend/gen_insn_selection.hpp index 12553b8..5b9f007 100644 --- a/backend/src/backend/gen_insn_selection.hpp +++ b/backend/src/backend/gen_insn_selection.hpp @@ -730,7 +730,7 @@ namespace gbe /*! Compare instructions */ void CMP(uint32_t conditional, Reg src0, Reg src1); /*! EOT is used to finish GPGPU threads */ - void EOT(Reg src); + void EOT(void); /*! No-op */ void NOP(void); /*! Wait instruction (used for the barrier) */ diff --git a/backend/src/backend/gen_reg_allocation.cpp b/backend/src/backend/gen_reg_allocation.cpp index 67ff558..5e416e5 100644 --- a/backend/src/backend/gen_reg_allocation.cpp +++ b/backend/src/backend/gen_reg_allocation.cpp @@ -351,6 +351,40 @@ namespace gbe grfOffset = this->createGenReg(reg, grfOffset); } + INLINE void setGenReg(GenReg &dst, const SelectionReg &src) { + dst.type = src.type; + dst.file = src.file; + dst.negation = src.negation; + dst.absolute = src.absolute; + dst.vstride = src.vstride; + dst.width = src.width; + dst.hstride = src.hstride; + dst.address_mode = GEN_ADDRESS_DIRECT; + dst.dw1.ud = src.immediate.ud; + } + + GenReg GenRegAllocator::genReg(const SelectionReg ®) { + // Right now, only GRF are allocated ... + if (reg.file == GEN_GENERAL_REGISTER_FILE) { + GBE_ASSERT(RA.contains(reg.reg) != false); + GenReg dst = RA.find(reg.reg)->second; + // XXX Fix that properly (ir::Type is *not* needed) + if (reg.quarter != 0) + dst = this->genRegQn(reg.reg, reg.quarter+1, ir::TYPE_S32); + else + setGenReg(dst, reg); + return dst; + } + // Other registers are already physical registers + else { + GenReg dst; + setGenReg(dst, reg); + dst.nr = reg.nr; + dst.subnr = reg.subnr; + return dst; + } + } + GenReg GenRegAllocator::genReg(ir::Register reg, ir::Type type) { const uint32_t genType = getGenType(type); auto it = RA.find(reg); diff --git a/backend/src/backend/gen_reg_allocation.hpp b/backend/src/backend/gen_reg_allocation.hpp index a408af2..eea06de 100644 --- a/backend/src/backend/gen_reg_allocation.hpp +++ b/backend/src/backend/gen_reg_allocation.hpp @@ -31,7 +31,8 @@ namespace gbe { - class Selection; // pre-register allocation code generation + class Selection; // Pre-register allocation code generation + class SelectionReg; // Pre-register allocation Gen register /*! Provides the location of a register in a vector */ typedef std::pair VectorLocation; @@ -43,6 +44,8 @@ namespace gbe GenRegAllocator(GenContext &ctx); /*! Perform the register allocation */ void allocate(Selection &selection); + /*! Return the Gen register from the selection register */ + GenReg genReg(const SelectionReg ®); /*! Return the Gen register from the GenIR one */ GenReg genReg(ir::Register, ir::Type type = ir::TYPE_FLOAT); /*! Compute the quarterth register part when using SIMD8 with Qn (n in 2,3,4) */ -- 2.7.4