diff options
author | rander <rander.wang@intel.com> | 2017-05-19 16:19:13 +0800 |
---|---|---|
committer | Yang Rong <rong.r.yang@intel.com> | 2017-06-09 19:36:21 +0800 |
commit | 0fd1ef5a1643973c1369b203ce596729e00da8ec (patch) | |
tree | e3a21c296c9c7d2582c1e3b21d9b01b75389d5cd | |
parent | b8fe58d5e60d98b2958b0a8825cc1be3ec621666 (diff) |
backend: add sqrt-div pattern to instruction select
there some patterns like:
sqrt r1, r2;
load r4, 1.0; ===> rqrt r3, r2
div r3, r4, r1;
Signed-off-by: rander.wang <rander.wang@intel.com>
Reviewed-by: Pan Xiuli <xiuli.pan@intel.com>
-rw-r--r-- | backend/src/backend/gen_insn_selection.cpp | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/backend/src/backend/gen_insn_selection.cpp b/backend/src/backend/gen_insn_selection.cpp index 1a883ead..7498f382 100644 --- a/backend/src/backend/gen_insn_selection.cpp +++ b/backend/src/backend/gen_insn_selection.cpp @@ -3698,6 +3698,74 @@ extern bool OCL_DEBUGINFO; // first defined by calling BVAR in program.cpp } }; + /*! there some patterns like: + sqrt r1, r2; + load r4, 1.0; ===> rqrt r3, r2 + div r3, r4, r1; */ + class SqrtDivInstructionPattern : public SelectionPattern { + public: + /*! Register the pattern for all opcodes of the family */ + SqrtDivInstructionPattern(void) : SelectionPattern(1, 1) { this->opcodes.push_back(ir::OP_DIV); } + + /*! Implements base class */ + virtual bool emit(Selection::Opaque &sel, SelectionDAG &dag) const { + using namespace ir; + + // We are good to try. We need a MUL for one of the two sources + const ir::BinaryInstruction &insn = cast<ir::BinaryInstruction>(dag.insn); + if (insn.getType() != TYPE_FLOAT) + return false; + SelectionDAG *child0 = dag.child[0]; + SelectionDAG *child1 = dag.child[1]; + const GenRegister dst = sel.selReg(insn.getDst(0), TYPE_FLOAT); + + if (child1 && child1->insn.getOpcode() == OP_SQR) { + GBE_ASSERT(cast<ir::UnaryInstruction>(child1->insn).getType() == TYPE_FLOAT); + GenRegister srcSQR = sel.selReg(child1->insn.getSrc(0), TYPE_FLOAT); + const GenRegister tmp = sel.selReg(sel.reg(ir::FAMILY_DWORD), ir::TYPE_FLOAT); + const GenRegister src0 = sel.selReg(insn.getSrc(0), TYPE_FLOAT); + float immVal = 0.0f; + + if (child0 && child0->insn.getOpcode() == OP_LOADI) { + const auto &loadimm = cast<LoadImmInstruction>(child0->insn); + const Immediate imm = loadimm.getImmediate(); + const Type type = imm.getType(); + if (type == TYPE_FLOAT) + immVal = imm.getFloatValue(); + else if (type == TYPE_S32 || type == TYPE_U32) + immVal = imm.getIntegerValue(); + } + + sel.push(); + if (sel.isScalarReg(insn.getDst(0))) + sel.curr.execWidth = 1; + + if (immVal == 1.0f) { + sel.MATH(dst, GEN_MATH_FUNCTION_RSQ, srcSQR); + if (child1->child[0]) + child1->child[0]->isRoot = 1; + } else { + sel.MATH(tmp, GEN_MATH_FUNCTION_RSQ, srcSQR); + if (immVal != 0.0f) { + GenRegister isrc = GenRegister::immf(immVal); + sel.MUL(dst, tmp, isrc); + } else { + sel.MUL(dst, src0, tmp); + if (child0) + child0->isRoot = 1; + } + + if (child1->child[0]) + child1->child[0]->isRoot = 1; + } + sel.pop(); + + return true; + } + return false; + } + }; + /*! sel.{le,l,ge...} like patterns */ class SelectModifierInstructionPattern : public SelectionPattern { @@ -8084,6 +8152,7 @@ extern bool OCL_DEBUGINFO; // first defined by calling BVAR in program.cpp SelectionLibrary::SelectionLibrary(void) { this->insert<UnaryInstructionPattern>(); + this->insert<SqrtDivInstructionPattern>(); this->insert<BinaryInstructionPattern>(); this->insert<TypedWriteInstructionPattern>(); this->insert<SyncInstructionPattern>(); |