[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