[Beignet] [PATCH 4/4] move simpleBlock check and if/endif optimize after select.
xionghu.luo at intel.com
xionghu.luo at intel.com
Thu Jan 5 11:12:04 UTC 2017
From: Luo Xionghu <xionghu.luo at intel.com>
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 <xionghu.luo at intel.com>
---
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
More information about the Beignet
mailing list