From: Luo Xionghu <[email protected]> the if opt could be a independent pass like function by checking the instruction state changes and special instructions like I64, mixed bit etc. this could reduce the code complexit of structure code.
Signed-off-by: Luo Xionghu <[email protected]> --- backend/src/CMakeLists.txt | 1 + backend/src/backend/gen_context.cpp | 8 +- backend/src/backend/gen_insn_selection.cpp | 25 ++++ backend/src/backend/gen_insn_selection.hpp | 4 + backend/src/backend/gen_insn_selection_if_opt.cpp | 138 ++++++++++++++++++++++ 5 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 backend/src/backend/gen_insn_selection_if_opt.cpp diff --git a/backend/src/CMakeLists.txt b/backend/src/CMakeLists.txt index 6ff25e7..c98ab3d 100644 --- a/backend/src/CMakeLists.txt +++ b/backend/src/CMakeLists.txt @@ -104,6 +104,7 @@ set (GBE_SRC backend/gen_insn_selection.cpp backend/gen_insn_selection.hpp backend/gen_insn_selection_optimize.cpp + backend/gen_insn_selection_if_opt.cpp backend/gen_insn_scheduling.cpp backend/gen_insn_scheduling.hpp backend/gen_insn_selection_output.cpp diff --git a/backend/src/backend/gen_context.cpp b/backend/src/backend/gen_context.cpp index 10e2c9e..769cd86 100644 --- a/backend/src/backend/gen_context.cpp +++ b/backend/src/backend/gen_context.cpp @@ -3617,14 +3617,20 @@ namespace gbe kernel->curbeSize = ALIGN(kernel->curbeSize, GEN_REG_SIZE); } + BVAR(OCL_OUTPUT_BEFORE_OPT, false); BVAR(OCL_OUTPUT_SEL_IR, false); BVAR(OCL_OPTIMIZE_SEL_IR, true); + BVAR(OCL_OPTIMIZE_IF_IR, true); bool GenContext::emitCode(void) { GenKernel *genKernel = static_cast<GenKernel*>(this->kernel); sel->select(); + sel->addID(); + if (OCL_OUTPUT_BEFORE_OPT) + outputSelectionIR(*this, this->sel, genKernel->getName()); if (OCL_OPTIMIZE_SEL_IR) sel->optimize(); - sel->addID(); + if (OCL_OPTIMIZE_IF_IR) + sel->if_opt(); if (OCL_OUTPUT_SEL_IR) outputSelectionIR(*this, this->sel, genKernel->getName()); schedulePreRegAllocation(*this, *this->sel); diff --git a/backend/src/backend/gen_insn_selection.cpp b/backend/src/backend/gen_insn_selection.cpp index eeb46ce..35685aa 100644 --- a/backend/src/backend/gen_insn_selection.cpp +++ b/backend/src/backend/gen_insn_selection.cpp @@ -265,6 +265,31 @@ namespace gbe this->opcode == SEL_OP_MAD; } + bool SelectionInstruction::isI64(void) const { + return this->opcode == SEL_OP_I64AND || + this->opcode == SEL_OP_I64OR || + this->opcode == SEL_OP_I64XOR || + this->opcode == SEL_OP_I64SHR || + this->opcode == SEL_OP_I64SHL || + this->opcode == SEL_OP_I64ASR || + this->opcode == SEL_OP_I64ADD || + this->opcode == SEL_OP_I64SATADD || + this->opcode == SEL_OP_I64SUB || + this->opcode == SEL_OP_I64SATSUB || + this->opcode == SEL_OP_I64MUL || + this->opcode == SEL_OP_I64DIV || + this->opcode == SEL_OP_I64REM || + this->opcode == SEL_OP_I64CMP || + this->opcode == SEL_OP_I64_MUL_HI || + this->opcode == SEL_OP_I64HADD || + this->opcode == SEL_OP_I64RHADD || + this->opcode == SEL_OP_CONVI_TO_I64 || + this->opcode == SEL_OP_CONVI64_TO_I || + this->opcode == SEL_OP_CONVF_TO_I64 || + this->opcode == SEL_OP_CONVI64_TO_F || + this->opcode == SEL_OP_I64MADSAT; + } + /////////////////////////////////////////////////////////////////////////// // SelectionVector /////////////////////////////////////////////////////////////////////////// diff --git a/backend/src/backend/gen_insn_selection.hpp b/backend/src/backend/gen_insn_selection.hpp index f4cc948..272da26 100644 --- a/backend/src/backend/gen_insn_selection.hpp +++ b/backend/src/backend/gen_insn_selection.hpp @@ -84,6 +84,8 @@ namespace gbe bool isLabel(void) const; /*! Is it a simple navtive instruction (i.e. will be one simple ISA) */ bool isNative(void) const; + /*! Is it a I64 instruction */ + bool isI64(void) const; /*! Get the destination register */ GenRegister &dst(uint32_t dstID) { return regs[dstID]; } /*! Get the source register */ @@ -318,6 +320,8 @@ namespace gbe void optimize(void); uint32_t opt_features; + void if_opt(void); + /* Add insn ID for sel IR */ void addID(void); const GenContext &getCtx(); diff --git a/backend/src/backend/gen_insn_selection_if_opt.cpp b/backend/src/backend/gen_insn_selection_if_opt.cpp new file mode 100644 index 0000000..b884ea6 --- /dev/null +++ b/backend/src/backend/gen_insn_selection_if_opt.cpp @@ -0,0 +1,138 @@ + +#include "backend/gen_insn_selection.hpp" +#include "backend/gen_context.hpp" +#include "ir/function.hpp" +#include "ir/liveness.hpp" +#include "ir/profile.hpp" +#include "sys/cvar.hpp" +#include "sys/vector.hpp" +#include <algorithm> +#include <climits> +#include <map> + +namespace gbe +{ + class IfOptimizer + { + public: + IfOptimizer(const GenContext& ctx, SelectionBlock& selblock) : ctx(ctx), selBlock(selblock) {} + void run(); + bool isSimpleBlock(); + void removeSimpleIfEndif(); + ~IfOptimizer() {} + protected: + const GenContext &ctx; //in case that we need it + SelectionBlock &selBlock; + bool optimized; + }; + + bool IfOptimizer::isSimpleBlock() { + + if(selBlock.insnList.size() > 20) + return false; + + bool if_exits = false; + for (auto &insn : selBlock.insnList) { + if (insn.opcode == SEL_OP_IF) { + if_exits = true; + continue; + } + if(if_exits) { + GenInstructionState curr = insn.state; + if (curr.execWidth == 1 || curr.predicate != GEN_PREDICATE_NONE || curr.flagIndex != 0) { + return false; + } + + // Predication is not allowed. + if (insn.opcode == SEL_OP_SEL_CMP) { + return false; + } + + //I64 instructions. + if (insn.isI64()) { + return false; + } + + if (insn.opcode == SEL_OP_CALC_TIMESTAMP) { + return false; + } + + //subgroup instructions introduce CMP instruction after select. + if (insn.opcode == SEL_OP_SUBGROUP_OP || insn.opcode == SEL_OP_SIMD_SHUFFLE) { + return false; + } + + //mixed bti may introduce CMP instruction after select. + if ((insn.opcode == SEL_OP_BYTE_GATHER || + insn.opcode == SEL_OP_BYTE_SCATTER || + insn.opcode == SEL_OP_READ64 || + insn.opcode == SEL_OP_WRITE64 || + insn.opcode == SEL_OP_UNTYPED_READ || + insn.opcode == SEL_OP_UNTYPED_WRITE || + insn.opcode == SEL_OP_ATOMIC) && + curr.flag == 0 && curr.subFlag == 1) + return false; + } + if (insn.opcode == SEL_OP_ENDIF) { + break; + } + } + + if (!if_exits) + return false; + + return true; + } + + void IfOptimizer::removeSimpleIfEndif() { + if(isSimpleBlock()) { + GenInstructionState curr; + bool if_find = false; + for (auto iter = selBlock.insnList.begin(); iter != selBlock.insnList.end(); iter++ ) { + //remove if and endif, change instruction flags. + SelectionInstruction& insn = *iter; + if(insn.opcode == SEL_OP_IF && !if_find) { + iter = selBlock.insnList.erase(&insn); + if (iter == selBlock.insnList.end()) { + break; + } + SelectionInstruction &next = *iter; + next.state.predicate = GEN_PREDICATE_NORMAL; + next.state.flag = 0; + next.state.subFlag = 1; + if_find = true; + continue; + } + + if(!if_find) + continue; + + insn.state.predicate = GEN_PREDICATE_NORMAL; + insn.state.flag = 0; + insn.state.subFlag = 1; + if (insn.opcode == SEL_OP_ENDIF) { + selBlock.insnList.erase(&insn); + optimized = true; + break; + } + } + } + } + + void IfOptimizer::run() + { + optimized = false; + removeSimpleIfEndif(); + } + + void Selection::if_opt() + { + //do basic block level optimization + for (SelectionBlock &block : *blockList) { + IfOptimizer ifopt(getCtx(), block); + ifopt.run(); + } + + } +} /* namespace gbe */ + -- 2.5.0 _______________________________________________ Beignet mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/beignet
