the binary pattern assumes the two src operands have the same type, while simd shuffle is not the case, so add a separate pattern for it.
Signed-off-by: Guo Yejun <[email protected]> --- backend/src/backend/gen8_context.cpp | 38 ++++++------ backend/src/backend/gen8_context.hpp | 1 + backend/src/backend/gen_context.cpp | 68 ++++++++++++---------- backend/src/backend/gen_context.hpp | 1 + .../src/backend/gen_insn_gen7_schedule_info.hxx | 1 + backend/src/backend/gen_insn_selection.cpp | 55 +++++++++++++---- backend/src/backend/gen_insn_selection.hxx | 2 +- backend/src/ir/instruction.cpp | 24 +++++++- backend/src/ir/instruction.hpp | 8 +++ backend/src/ir/instruction.hxx | 2 +- 10 files changed, 136 insertions(+), 64 deletions(-) diff --git a/backend/src/backend/gen8_context.cpp b/backend/src/backend/gen8_context.cpp index 69d3916..284e0a3 100644 --- a/backend/src/backend/gen8_context.cpp +++ b/backend/src/backend/gen8_context.cpp @@ -236,6 +236,27 @@ namespace gbe } } + void Gen8Context::emitSimdShuffleInstruction(const SelectionInstruction &insn) { + const GenRegister dst = ra->genReg(insn.dst(0)); + const GenRegister src0 = ra->genReg(insn.src(0)); + const GenRegister src1 = ra->genReg(insn.src(1)); + assert(insn.opcode == SEL_OP_SIMD_SHUFFLE); + + uint32_t simd = p->curr.execWidth; + if (src1.file == GEN_IMMEDIATE_VALUE) { + uint32_t offset = src1.value.ud % simd; + GenRegister reg = GenRegister::suboffset(src0, offset); + p->MOV(dst, GenRegister::retype(GenRegister::ud1grf(reg.nr, reg.subnr / typeSize(reg.type)), reg.type)); + } else { + uint32_t base = src0.nr * 32 + src0.subnr * 4; + GenRegister baseReg = GenRegister::immuw(base); + const GenRegister a0 = GenRegister::addr8(0); + p->ADD(a0, GenRegister::unpacked_uw(src1.nr, src1.subnr / typeSize(GEN_TYPE_UW)), baseReg); + GenRegister indirect = GenRegister::to_indirect1xN(src0, 0, 0); + p->MOV(dst, indirect); + } + } + void Gen8Context::emitBinaryInstruction(const SelectionInstruction &insn) { const GenRegister dst = ra->genReg(insn.dst(0)); const GenRegister src0 = ra->genReg(insn.src(0)); @@ -255,23 +276,6 @@ namespace gbe p->ADD(dst, dst, src1); break; } - case SEL_OP_SIMD_SHUFFLE: - { - uint32_t simd = p->curr.execWidth; - if (src1.file == GEN_IMMEDIATE_VALUE) { - uint32_t offset = src1.value.ud % simd; - GenRegister reg = GenRegister::suboffset(src0, offset); - p->MOV(dst, GenRegister::retype(GenRegister::ud1grf(reg.nr, reg.subnr / typeSize(reg.type)), reg.type)); - } else { - uint32_t base = src0.nr * 32 + src0.subnr * 4; - GenRegister baseReg = GenRegister::immuw(base); - const GenRegister a0 = GenRegister::addr8(0); - p->ADD(a0, GenRegister::unpacked_uw(src1.nr, src1.subnr / typeSize(GEN_TYPE_UW)), baseReg); - GenRegister indirect = GenRegister::to_indirect1xN(src0, 0, 0); - p->MOV(dst, indirect); - } - break; - } default: GenContext::emitBinaryInstruction(insn); } diff --git a/backend/src/backend/gen8_context.hpp b/backend/src/backend/gen8_context.hpp index 8827955..364824b 100644 --- a/backend/src/backend/gen8_context.hpp +++ b/backend/src/backend/gen8_context.hpp @@ -50,6 +50,7 @@ namespace gbe virtual void emitUnaryInstruction(const SelectionInstruction &insn); virtual void emitUnaryWithTempInstruction(const SelectionInstruction &insn); + virtual void emitSimdShuffleInstruction(const SelectionInstruction &insn); virtual void emitBinaryInstruction(const SelectionInstruction &insn); virtual void emitBinaryWithTempInstruction(const SelectionInstruction &insn); virtual void emitI64MULHIInstruction(const SelectionInstruction &insn); diff --git a/backend/src/backend/gen_context.cpp b/backend/src/backend/gen_context.cpp index db27377..e16b0a9 100644 --- a/backend/src/backend/gen_context.cpp +++ b/backend/src/backend/gen_context.cpp @@ -545,6 +545,42 @@ namespace gbe } } + void GenContext::emitSimdShuffleInstruction(const SelectionInstruction &insn) { + const GenRegister dst = ra->genReg(insn.dst(0)); + const GenRegister src0 = ra->genReg(insn.src(0)); + const GenRegister src1 = ra->genReg(insn.src(1)); + assert(insn.opcode == SEL_OP_SIMD_SHUFFLE); + + uint32_t simd = p->curr.execWidth; + if (src1.file == GEN_IMMEDIATE_VALUE) { + uint32_t offset = src1.value.ud % simd; + GenRegister reg = GenRegister::suboffset(src0, offset); + p->MOV(dst, GenRegister::retype(GenRegister::ud1grf(reg.nr, reg.subnr / typeSize(reg.type)), reg.type)); + } else { + uint32_t base = src0.nr * 32 + src0.subnr * 4; + GenRegister baseReg = GenRegister::immuw(base); + const GenRegister a0 = GenRegister::addr8(0); + + p->push(); + if (simd == 8) { + p->ADD(a0, GenRegister::unpacked_uw(src1.nr, src1.subnr / typeSize(GEN_TYPE_UW)), baseReg); + GenRegister indirect = GenRegister::to_indirect1xN(src0, 0, 0); + p->MOV(dst, indirect); + } else if (simd == 16) { + p->curr.execWidth = 8; + p->ADD(a0, GenRegister::unpacked_uw(src1.nr, src1.subnr / typeSize(GEN_TYPE_UW)), baseReg); + GenRegister indirect = GenRegister::to_indirect1xN(src0, 0, 0); + p->MOV(dst, indirect); + + p->curr.quarterControl = 1; + p->ADD(a0, GenRegister::unpacked_uw(src1.nr+1, src1.subnr / typeSize(GEN_TYPE_UW)), baseReg); + p->MOV(GenRegister::offset(dst, 1, 0), indirect); + } else + NOT_IMPLEMENTED; + p->pop(); + } + } + void GenContext::emitBinaryInstruction(const SelectionInstruction &insn) { const GenRegister dst = ra->genReg(insn.dst(0)); const GenRegister src0 = ra->genReg(insn.src(0)); @@ -595,38 +631,6 @@ namespace gbe p->MOV(xdst.bottom_half(), xsrc1.bottom_half()); } break; - case SEL_OP_SIMD_SHUFFLE: - { - uint32_t simd = p->curr.execWidth; - if (src1.file == GEN_IMMEDIATE_VALUE) { - uint32_t offset = src1.value.ud % simd; - GenRegister reg = GenRegister::suboffset(src0, offset); - p->MOV(dst, GenRegister::retype(GenRegister::ud1grf(reg.nr, reg.subnr / typeSize(reg.type)), reg.type)); - } else { - uint32_t base = src0.nr * 32 + src0.subnr * 4; - GenRegister baseReg = GenRegister::immuw(base); - const GenRegister a0 = GenRegister::addr8(0); - - p->push(); - if (simd == 8) { - p->ADD(a0, GenRegister::unpacked_uw(src1.nr, src1.subnr / typeSize(GEN_TYPE_UW)), baseReg); - GenRegister indirect = GenRegister::to_indirect1xN(src0, 0, 0); - p->MOV(dst, indirect); - } else if (simd == 16) { - p->curr.execWidth = 8; - p->ADD(a0, GenRegister::unpacked_uw(src1.nr, src1.subnr / typeSize(GEN_TYPE_UW)), baseReg); - GenRegister indirect = GenRegister::to_indirect1xN(src0, 0, 0); - p->MOV(dst, indirect); - - p->curr.quarterControl = 1; - p->ADD(a0, GenRegister::unpacked_uw(src1.nr+1, src1.subnr / typeSize(GEN_TYPE_UW)), baseReg); - p->MOV(GenRegister::offset(dst, 1, 0), indirect); - } else - NOT_IMPLEMENTED; - p->pop(); - } - } - break; default: NOT_IMPLEMENTED; } } diff --git a/backend/src/backend/gen_context.hpp b/backend/src/backend/gen_context.hpp index a85657c..11bea74 100644 --- a/backend/src/backend/gen_context.hpp +++ b/backend/src/backend/gen_context.hpp @@ -127,6 +127,7 @@ namespace gbe virtual void emitUnaryInstruction(const SelectionInstruction &insn); virtual void emitUnaryWithTempInstruction(const SelectionInstruction &insn); virtual void emitBinaryInstruction(const SelectionInstruction &insn); + virtual void emitSimdShuffleInstruction(const SelectionInstruction &insn); virtual void emitBinaryWithTempInstruction(const SelectionInstruction &insn); void emitTernaryInstruction(const SelectionInstruction &insn); virtual void emitI64MULHIInstruction(const SelectionInstruction &insn); diff --git a/backend/src/backend/gen_insn_gen7_schedule_info.hxx b/backend/src/backend/gen_insn_gen7_schedule_info.hxx index d054820..d073770 100644 --- a/backend/src/backend/gen_insn_gen7_schedule_info.hxx +++ b/backend/src/backend/gen_insn_gen7_schedule_info.hxx @@ -3,6 +3,7 @@ DECL_GEN7_SCHEDULE(Label, 0, 0, 0) DECL_GEN7_SCHEDULE(Unary, 20, 4, 2) DECL_GEN7_SCHEDULE(UnaryWithTemp, 20, 40, 20) DECL_GEN7_SCHEDULE(Binary, 20, 4, 2) +DECL_GEN7_SCHEDULE(SimdShuffle, 20, 4, 2) DECL_GEN7_SCHEDULE(BinaryWithTemp, 20, 40, 20) DECL_GEN7_SCHEDULE(Ternary, 20, 4, 2) DECL_GEN7_SCHEDULE(I64Shift, 20, 40, 20) diff --git a/backend/src/backend/gen_insn_selection.cpp b/backend/src/backend/gen_insn_selection.cpp index af5ab9c..dd757a5 100644 --- a/backend/src/backend/gen_insn_selection.cpp +++ b/backend/src/backend/gen_insn_selection.cpp @@ -543,7 +543,6 @@ namespace gbe ALU1(RNDD) ALU1(RNDU) ALU2(MACH) - ALU2(SIMD_SHUFFLE) ALU1(LZD) ALU3(MAD) ALU2WithTemp(MUL_HI) @@ -565,6 +564,8 @@ namespace gbe #undef ALU2WithTemp #undef ALU3 #undef I64Shift + /*! simd shuffle */ + void SIMD_SHUFFLE(Reg dst, Reg src0, Reg src1); /*! Convert 64-bit integer to 32-bit float */ void CONVI64_TO_F(Reg dst, Reg src, GenRegister tmp[6]); /*! Convert 64-bit integer to 32-bit float */ @@ -1652,6 +1653,14 @@ namespace gbe insn->src(2) = src2; } + void Selection::Opaque::SIMD_SHUFFLE(Reg dst, Reg src0, Reg src1) + { + SelectionInstruction *insn = this->appendInsn(SEL_OP_SIMD_SHUFFLE, 1, 2); + insn->dst(0) = dst; + insn->src(0) = src0; + insn->src(1) = src1; + } + void Selection::Opaque::I64CMP(uint32_t conditional, Reg src0, Reg src1, GenRegister tmp[3]) { SelectionInstruction *insn = this->appendInsn(SEL_OP_I64CMP, 3, 2); insn->src(0) = src0; @@ -2815,17 +2824,6 @@ namespace gbe case OP_UPSAMPLE_LONG: sel.UPSAMPLE_LONG(dst, src0, src1); break; - case OP_SIMD_SHUFFLE: - { - if (src1.file == GEN_IMMEDIATE_VALUE) - sel.SIMD_SHUFFLE(dst, src0, src1); - else { - GenRegister shiftL = GenRegister::udxgrf(sel.curr.execWidth, sel.reg(FAMILY_DWORD)); - sel.SHL(shiftL, src1, GenRegister::immud(0x2)); - sel.SIMD_SHUFFLE(dst, src0, shiftL); - } - } - break; default: NOT_IMPLEMENTED; } sel.pop(); @@ -4973,6 +4971,38 @@ namespace gbe } }; + class SimdShuffleInstructionPattern : public SelectionPattern + { + public: + SimdShuffleInstructionPattern(void) : SelectionPattern(1,1) { + this->opcodes.push_back(ir::OP_SIMD_SHUFFLE); + } + INLINE bool emit(Selection::Opaque &sel, SelectionDAG &dag) const { + using namespace ir; + const ir::SimdShuffleInstruction &insn = cast<SimdShuffleInstruction>(dag.insn); + assert(insn.getOpcode() == OP_SIMD_SHUFFLE); + const Type type = insn.getType(); + GenRegister dst = sel.selReg(insn.getDst(0), type); + + sel.push(); + + GenRegister src0, src1; + bool inverse = false; + sel.getSrcGenRegImm(dag, src0, src1, type, inverse); + + if (src1.file == GEN_IMMEDIATE_VALUE) + sel.SIMD_SHUFFLE(dst, src0, src1); + else { + GenRegister shiftL = GenRegister::udxgrf(sel.curr.execWidth, sel.reg(FAMILY_DWORD)); + sel.SHL(shiftL, src1, GenRegister::immud(0x2)); + sel.SIMD_SHUFFLE(dst, src0, shiftL); + } + + sel.pop(); + return true; + } + }; + /*! Get a region of a register */ class RegionInstructionPattern : public SelectionPattern { @@ -5247,6 +5277,7 @@ namespace gbe this->insert<GetImageInfoInstructionPattern>(); this->insert<ReadARFInstructionPattern>(); this->insert<RegionInstructionPattern>(); + this->insert<SimdShuffleInstructionPattern>(); this->insert<IndirectMovInstructionPattern>(); this->insert<NullaryInstructionPattern>(); diff --git a/backend/src/backend/gen_insn_selection.hxx b/backend/src/backend/gen_insn_selection.hxx index 79f2ce1..adbb137 100644 --- a/backend/src/backend/gen_insn_selection.hxx +++ b/backend/src/backend/gen_insn_selection.hxx @@ -26,7 +26,7 @@ DECL_SELECTION_IR(SHL, BinaryInstruction) DECL_SELECTION_IR(RSR, BinaryInstruction) DECL_SELECTION_IR(RSL, BinaryInstruction) DECL_SELECTION_IR(ASR, BinaryInstruction) -DECL_SELECTION_IR(SIMD_SHUFFLE, BinaryInstruction) +DECL_SELECTION_IR(SIMD_SHUFFLE, SimdShuffleInstruction) DECL_SELECTION_IR(I64SHR, I64ShiftInstruction) DECL_SELECTION_IR(I64SHL, I64ShiftInstruction) DECL_SELECTION_IR(I64ASR, I64ShiftInstruction) diff --git a/backend/src/ir/instruction.cpp b/backend/src/ir/instruction.cpp index 12d70a6..a31d04c 100644 --- a/backend/src/ir/instruction.cpp +++ b/backend/src/ir/instruction.cpp @@ -741,6 +741,21 @@ namespace ir { Register src[0]; }; + class ALIGNED_INSTRUCTION SimdShuffleInstruction : public NaryInstruction<2> + { + public: + SimdShuffleInstruction(Type type, + Register dst, + Register src0, + Register src1) { + this->opcode = OP_SIMD_SHUFFLE; + this->type = type; + this->dst[0] = dst; + this->src[0] = src0; + this->src[1] = src1; + } + }; + class ALIGNED_INSTRUCTION RegionInstruction : public BasePolicy, public NSrcPolicy<RegionInstruction, 1>, @@ -1461,6 +1476,10 @@ START_INTROSPECTION(RegionInstruction) #include "ir/instruction.hxx" END_INTROSPECTION(RegionInstruction) +START_INTROSPECTION(SimdShuffleInstruction) +#include "ir/instruction.hxx" +END_INTROSPECTION(SimdShuffleInstruction) + START_INTROSPECTION(IndirectMovInstruction) #include "ir/instruction.hxx" END_INTROSPECTION(IndirectMovInstruction) @@ -1652,6 +1671,7 @@ DECL_MEM_FN(BranchInstruction, LabelIndex, getLabelIndex(void), getLabelIndex()) DECL_MEM_FN(SyncInstruction, uint32_t, getParameters(void), getParameters()) DECL_MEM_FN(ReadARFInstruction, Type, getType(void), getType()) DECL_MEM_FN(ReadARFInstruction, ARFRegister, getARFRegister(void), getARFRegister()) +DECL_MEM_FN(SimdShuffleInstruction, Type, getType(void), getType()) DECL_MEM_FN(RegionInstruction, uint32_t, getOffset(void), getOffset()) DECL_MEM_FN(IndirectMovInstruction, uint32_t, getOffset(void), getOffset()) DECL_MEM_FN(IndirectMovInstruction, Type, getType(void), getType()) @@ -1751,7 +1771,6 @@ DECL_MEM_FN(GetImageInfoInstruction, uint8_t, getImageIndex(void), getImageIndex DECL_EMIT_FUNCTION(RHADD) DECL_EMIT_FUNCTION(I64HADD) DECL_EMIT_FUNCTION(I64RHADD) - DECL_EMIT_FUNCTION(SIMD_SHUFFLE) #undef DECL_EMIT_FUNCTION @@ -1881,6 +1900,9 @@ DECL_MEM_FN(GetImageInfoInstruction, uint8_t, getImageIndex(void), getImageIndex Instruction REGION(Register dst, Register src, uint32_t offset) { return internal::RegionInstruction(dst, src, offset).convert(); } + Instruction SIMD_SHUFFLE(Type type, Register dst, Register src0, Register src1) { + return internal::SimdShuffleInstruction(type, dst, src0, src1).convert(); + } Instruction INDIRECT_MOV(Type type, Register dst, Register src0, Register src1, uint32_t offset) { return internal::IndirectMovInstruction(type, dst, src0, src1, offset).convert(); diff --git a/backend/src/ir/instruction.hpp b/backend/src/ir/instruction.hpp index ec4d00d..cf8d839 100644 --- a/backend/src/ir/instruction.hpp +++ b/backend/src/ir/instruction.hpp @@ -522,6 +522,14 @@ namespace ir { static bool isClassOf(const Instruction &insn); }; + /*! simd shuffle */ + class SimdShuffleInstruction : public Instruction { + public: + Type getType(void) const; + /*! Return true if the given instruction is an instance of this class */ + static bool isClassOf(const Instruction &insn); + }; + /*! return a region of a register, make sure the offset does not exceed the register size */ class RegionInstruction : public Instruction { public: diff --git a/backend/src/ir/instruction.hxx b/backend/src/ir/instruction.hxx index 1001837..81548c9 100644 --- a/backend/src/ir/instruction.hxx +++ b/backend/src/ir/instruction.hxx @@ -59,7 +59,7 @@ DECL_INSN(BSB, BinaryInstruction) DECL_INSN(OR, BinaryInstruction) DECL_INSN(XOR, BinaryInstruction) DECL_INSN(AND, BinaryInstruction) -DECL_INSN(SIMD_SHUFFLE, BinaryInstruction) +DECL_INSN(SIMD_SHUFFLE, SimdShuffleInstruction) DECL_INSN(SEL, SelectInstruction) DECL_INSN(EQ, CompareInstruction) DECL_INSN(NE, CompareInstruction) -- 1.9.1 _______________________________________________ Beignet mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/beignet
