From: Zhigang Gong Date: Mon, 17 Mar 2014 10:08:17 +0000 (+0800) Subject: GBE: Add if/endif/brc/brd instruction support. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c56848409caf951e35ac7462294c278d31a813ab;p=contrib%2Fbeignet.git GBE: Add if/endif/brc/brd instruction support. Signed-off-by: Zhigang Gong Reviewed-by: "Yang, Rong R" Reviewed-by: "Song, Ruiling" --- diff --git a/backend/src/backend/gen/gen_mesa_disasm.c b/backend/src/backend/gen/gen_mesa_disasm.c index 1f5adc9..84ef0c8 100644 --- a/backend/src/backend/gen/gen_mesa_disasm.c +++ b/backend/src/backend/gen/gen_mesa_disasm.c @@ -100,8 +100,9 @@ static const struct { [GEN_OPCODE_SENDC] = { .name = "sendc", .nsrc = 1, .ndst = 1 }, [GEN_OPCODE_NOP] = { .name = "nop", .nsrc = 0, .ndst = 0 }, [GEN_OPCODE_JMPI] = { .name = "jmpi", .nsrc = 0, .ndst = 0 }, + [GEN_OPCODE_BRD] = { .name = "brd", .nsrc = 1, .ndst = 0 }, [GEN_OPCODE_IF] = { .name = "if", .nsrc = 2, .ndst = 0 }, - [GEN_OPCODE_IFF] = { .name = "iff", .nsrc = 2, .ndst = 1 }, + [GEN_OPCODE_BRC] = { .name = "brc", .nsrc = 1, .ndst = 0 }, [GEN_OPCODE_WHILE] = { .name = "while", .nsrc = 2, .ndst = 0 }, [GEN_OPCODE_ELSE] = { .name = "else", .nsrc = 2, .ndst = 0 }, [GEN_OPCODE_BREAK] = { .name = "break", .nsrc = 2, .ndst = 0 }, @@ -113,7 +114,7 @@ static const struct { [GEN_OPCODE_POP] = { .name = "pop", .nsrc = 2, .ndst = 0 }, [GEN_OPCODE_WAIT] = { .name = "wait", .nsrc = 1, .ndst = 0 }, [GEN_OPCODE_DO] = { .name = "do", .nsrc = 0, .ndst = 0 }, - [GEN_OPCODE_ENDIF] = { .name = "endif", .nsrc = 2, .ndst = 0 }, + [GEN_OPCODE_ENDIF] = { .name = "endif", .nsrc = 1, .ndst = 0 }, }; static const char *conditional_modifier[16] = { diff --git a/backend/src/backend/gen_context.cpp b/backend/src/backend/gen_context.cpp index 88d4866..c46127a 100644 --- a/backend/src/backend/gen_context.cpp +++ b/backend/src/backend/gen_context.cpp @@ -213,6 +213,32 @@ namespace gbe p->pop(); break; } + case SEL_OP_BRC: + { + const ir::LabelIndex label0(insn.index), label1(insn.index1); + const LabelPair labelPair(label0, label1); + const GenRegister src = ra->genReg(insn.src(0)); + this->branchPos3.push_back(std::make_pair(labelPair, p->store.size())); + p->BRC(src); + } + break; + case SEL_OP_BRD: + insertJumpPos(insn); + p->BRD(src); + break; + case SEL_OP_ENDIF: + insertJumpPos(insn); + p->ENDIF(src); + break; + case SEL_OP_IF: + { + const ir::LabelIndex label0(insn.index), label1(insn.index1); + const LabelPair labelPair(label0, label1, insn.offset0, insn.offset1); + const GenRegister src = ra->genReg(insn.src(0)); + this->branchPos3.push_back(std::make_pair(labelPair, p->store.size())); + p->IF(src); + } + break; default: NOT_IMPLEMENTED; } } @@ -1646,10 +1672,14 @@ namespace gbe } } - void GenContext::emitJumpInstruction(const SelectionInstruction &insn) { + void GenContext::insertJumpPos(const SelectionInstruction &insn) { const ir::LabelIndex label(insn.index); - const GenRegister src = ra->genReg(insn.src(0)); this->branchPos2.push_back(std::make_pair(label, p->store.size())); + } + + void GenContext::emitJumpInstruction(const SelectionInstruction &insn) { + insertJumpPos(insn); + const GenRegister src = ra->genReg(insn.src(0)); p->JMPI(src); } diff --git a/backend/src/backend/gen_context.hpp b/backend/src/backend/gen_context.hpp index 6ec43cc..bd01c49 100644 --- a/backend/src/backend/gen_context.hpp +++ b/backend/src/backend/gen_context.hpp @@ -150,8 +150,20 @@ namespace gbe virtual Kernel *allocateKernel(void); /*! Store the position of each label instruction in the Gen ISA stream */ map labelPos; + typedef struct LabelPair { + LabelPair(ir::LabelIndex l0, ir::LabelIndex l1, + int16_t offset0 = 0, int16_t offset1 = 0) : + l0(l0), l1(l1), offset0(offset0), offset1(offset1) {}; + ir::LabelIndex l0; + ir::LabelIndex l1; + int16_t offset0; + int16_t offset1; + } LabelPair; /*! Store the Gen instructions to patch */ + vector> branchPos3; vector> branchPos2; + + void insertJumpPos(const SelectionInstruction &insn); /*! Encode Gen ISA */ GenEncoder *p; /*! Instruction selection on Gen ISA (pre-register allocation) */ diff --git a/backend/src/backend/gen_defs.hpp b/backend/src/backend/gen_defs.hpp index ffa38c0..7c49497 100644 --- a/backend/src/backend/gen_defs.hpp +++ b/backend/src/backend/gen_defs.hpp @@ -128,8 +128,9 @@ enum opcode { GEN_OPCODE_F32TO16 = 19, GEN_OPCODE_F16TO32 = 20, GEN_OPCODE_JMPI = 32, + GEN_OPCODE_BRD = 33, GEN_OPCODE_IF = 34, - GEN_OPCODE_IFF = 35, + GEN_OPCODE_BRC = 35, GEN_OPCODE_ELSE = 36, GEN_OPCODE_ENDIF = 37, GEN_OPCODE_DO = 38, diff --git a/backend/src/backend/gen_encoder.cpp b/backend/src/backend/gen_encoder.cpp index 9853a56..fc7e53d 100644 --- a/backend/src/backend/gen_encoder.cpp +++ b/backend/src/backend/gen_encoder.cpp @@ -959,6 +959,9 @@ namespace gbe ALU2(PLN) ALU2(MACH) ALU3(MAD) + // ALU2(BRC) + // ALU1(ENDIF) + // ALU1(IF) void GenEncoder::SUBB(GenRegister dest, GenRegister src0, GenRegister src1) { push(); @@ -1053,12 +1056,24 @@ namespace gbe NOP(); } +#define ALU2_BRA(OP) \ + void GenEncoder::OP(GenRegister src) { \ + alu2(this, GEN_OPCODE_##OP, GenRegister::null(), GenRegister::null(), src); \ + } + + ALU2_BRA(IF) + ALU2_BRA(ENDIF) + ALU2_BRA(BRD) + ALU2_BRA(BRC) + void GenEncoder::patchJMPI(uint32_t insnID, int32_t jumpDistance) { GenInstruction &insn = this->store[insnID]; GBE_ASSERT(insnID < this->store.size()); - GBE_ASSERT(insn.header.opcode == GEN_OPCODE_JMPI); + GBE_ASSERT(insn.header.opcode == GEN_OPCODE_JMPI || + insn.header.opcode == GEN_OPCODE_BRD || + insn.header.opcode == GEN_OPCODE_ENDIF); if ( jumpDistance > -32769 && jumpDistance < 32768 ) { - this->setSrc1(&insn, GenRegister::immd(jumpDistance)); + this->setSrc1(&insn, GenRegister::immd(jumpDistance)); } else if ( insn.header.predicate_control == GEN_PREDICATE_NONE ) { // For the conditional jump distance out of S15 range, we need to use an // inverted jmp followed by a add ip, ip, distance to implement. diff --git a/backend/src/backend/gen_encoder.hpp b/backend/src/backend/gen_encoder.hpp index 8d9a497..4bb208f 100644 --- a/backend/src/backend/gen_encoder.hpp +++ b/backend/src/backend/gen_encoder.hpp @@ -122,6 +122,8 @@ namespace gbe ALU2(PLN) ALU3(MAD) //ALU2(MOV_DF); + ALU2(BRC) + ALU1(BRD) #undef ALU1 #undef ALU2 #undef ALU3 @@ -134,6 +136,14 @@ namespace gbe void FENCE(GenRegister dst); /*! Jump indexed instruction */ void JMPI(GenRegister src); + /*! IF indexed instruction */ + void IF(GenRegister src); + /*! ENDIF indexed instruction */ + void ENDIF(GenRegister src); + /*! BRC indexed instruction */ + void BRC(GenRegister src); + /*! BRD indexed instruction */ + void BRD(GenRegister src); /*! Compare instructions */ void CMP(uint32_t conditional, GenRegister src0, GenRegister src1, GenRegister dst = GenRegister::null()); /*! Select with embedded compare (like sel.le ...) */ @@ -184,7 +194,7 @@ namespace gbe /*! Extended math function (1 source) */ void MATH(GenRegister dst, uint32_t function, GenRegister src); - /*! Patch JMPI (located at index insnID) with the given jump distance */ + /*! Patch JMPI/BRC/BRD (located at index insnID) with the given jump distance */ void patchJMPI(uint32_t insnID, int32_t jumpDistance); //////////////////////////////////////////////////////////////////////// diff --git a/backend/src/backend/gen_insn_selection.cpp b/backend/src/backend/gen_insn_selection.cpp index 84f3fd4..d86e04c 100644 --- a/backend/src/backend/gen_insn_selection.cpp +++ b/backend/src/backend/gen_insn_selection.cpp @@ -538,6 +538,14 @@ namespace gbe void LABEL(ir::LabelIndex label); /*! Jump indexed instruction */ void JMPI(Reg src, ir::LabelIndex target); + /*! IF indexed instruction */ + void IF(Reg src, ir::LabelIndex jip, ir::LabelIndex uip, int16_t offset0, int16_t offset1); + /*! ENDIF indexed instruction */ + void ENDIF(Reg src, ir::LabelIndex jip); + /*! BRD indexed instruction */ + void BRD(Reg src, ir::LabelIndex jip); + /*! BRC indexed instruction */ + void BRC(Reg src, ir::LabelIndex jip, ir::LabelIndex uip); /*! Compare instructions */ void CMP(uint32_t conditional, Reg src0, Reg src1, Reg dst = GenRegister::null()); /*! Select instruction with embedded comparison */ @@ -960,6 +968,35 @@ namespace gbe insn->index = uint16_t(index); } + void Selection::Opaque::BRD(Reg src, ir::LabelIndex jip) { + SelectionInstruction *insn = this->appendInsn(SEL_OP_BRD, 0, 1); + insn->src(0) = src; + insn->index = uint16_t(jip); + } + + void Selection::Opaque::BRC(Reg src, ir::LabelIndex jip, ir::LabelIndex uip) { + SelectionInstruction *insn = this->appendInsn(SEL_OP_BRC, 0, 1); + insn->src(0) = src; + insn->index = uint16_t(jip); + insn->index1 = uint16_t(uip); + } + + void Selection::Opaque::IF(Reg src, ir::LabelIndex jip, ir::LabelIndex uip, + int16_t offset0, int16_t offset1) { + SelectionInstruction *insn = this->appendInsn(SEL_OP_IF, 0, 1); + insn->src(0) = src; + insn->index = uint16_t(jip); + insn->index1 = uint16_t(uip); + insn->offset0 = offset0; + insn->offset1 = offset1; + } + + void Selection::Opaque::ENDIF(Reg src, ir::LabelIndex jip) { + SelectionInstruction *insn = this->appendInsn(SEL_OP_IF, 0, 1); + insn->src(0) = src; + insn->index = uint16_t(jip); + } + void Selection::Opaque::CMP(uint32_t conditional, Reg src0, Reg src1, Reg dst) { SelectionInstruction *insn = this->appendInsn(SEL_OP_CMP, 1, 2); insn->src(0) = src0; @@ -3197,7 +3234,6 @@ namespace gbe using namespace ir; const GenRegister ip = sel.selReg(ocl::blockip, TYPE_U16); const LabelIndex jip = sel.ctx.getLabelIndex(&insn); - const uint32_t simdWidth = sel.ctx.getSimdWidth(); // We will not emit any jump if we must go the next block anyway const BasicBlock *curr = insn.getParent(); diff --git a/backend/src/backend/gen_insn_selection.hpp b/backend/src/backend/gen_insn_selection.hpp index 0fde1df..04fbb9f 100644 --- a/backend/src/backend/gen_insn_selection.hpp +++ b/backend/src/backend/gen_insn_selection.hpp @@ -132,6 +132,12 @@ namespace gbe uint8_t srcNum:4; /*! To store various indices */ uint16_t index; + /*! For BRC/IF to store the UIP */ + uint16_t index1; + /*! For IF instruction to adjust the corresponding ENDIF's position. */ + /*! as endif is not at the begining of any BBs.*/ + uint16_t offset0; + uint16_t offset1; /*! instruction ID used for vector allocation. */ uint32_t ID; /*! Variable sized. Destinations and sources go here */ diff --git a/backend/src/backend/gen_insn_selection.hxx b/backend/src/backend/gen_insn_selection.hxx index 564dbc5..d318f8e 100644 --- a/backend/src/backend/gen_insn_selection.hxx +++ b/backend/src/backend/gen_insn_selection.hxx @@ -80,3 +80,7 @@ DECL_SELECTION_IR(CONVI64_TO_I, UnaryInstruction) DECL_SELECTION_IR(CONVI64_TO_F, I64ToFloatInstruction) DECL_SELECTION_IR(CONVF_TO_I64, FloatToI64Instruction) DECL_SELECTION_IR(I64MADSAT, I64MADSATInstruction) +DECL_SELECTION_IR(BRC, BinaryInstruction) +DECL_SELECTION_IR(BRD, UnaryInstruction) +DECL_SELECTION_IR(IF, UnaryInstruction) +DECL_SELECTION_IR(ENDIF, UnaryInstruction)