[Beignet] [PATCH v3 3/3] move simpleBlock check and if/endif optimize after select.

xionghu.luo at intel.com xionghu.luo at intel.com
Mon Feb 13 14:03:15 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.

v2: as the GenInstructionState flag/subFlag default value is 0.0, so
isSimpleBlock function return false if the insn state uses 0.1 as flag.
This rule could make function more straight forward, no need to enum
the special instructions except SEL_OP_SEL_CMP(no predication per spec).
v3: update code per review comments. remove duplicate code; redefine
MACRO name;endifOffset rename patch moved to later patchset.

Signed-off-by: Luo Xionghu <xionghu.luo at intel.com>
---
 backend/src/CMakeLists.txt                        |   1 +
 backend/src/backend/gen_context.cpp               |  13 ++-
 backend/src/backend/gen_insn_selection.hpp        |   2 +
 backend/src/backend/gen_insn_selection_if_opt.cpp | 109 ++++++++++++++++++++++
 4 files changed, 123 insertions(+), 2 deletions(-)
 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 7c1f4db..c9ff833 100644
--- a/backend/src/CMakeLists.txt
+++ b/backend/src/CMakeLists.txt
@@ -113,6 +113,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 bb104cf..79a3e62 100644
--- a/backend/src/backend/gen_context.cpp
+++ b/backend/src/backend/gen_context.cpp
@@ -3632,16 +3632,25 @@ namespace gbe
     kernel->curbeSize = ALIGN(kernel->curbeSize, GEN_REG_SIZE);
   }
 
+  BVAR(OCL_OUTPUT_SEL_IR_AFTER_SELECT, false);
   BVAR(OCL_OUTPUT_SEL_IR, false);
   BVAR(OCL_OPTIMIZE_SEL_IR, true);
+  BVAR(OCL_OPTIMIZE_IF_BLOCK, true);
   bool GenContext::emitCode(void) {
     GenKernel *genKernel = static_cast<GenKernel*>(this->kernel);
     sel->select();
+    if (OCL_OUTPUT_SEL_IR_AFTER_SELECT) {
+      sel->addID();
+      outputSelectionIR(*this, this->sel, genKernel->getName());
+    }
     if (OCL_OPTIMIZE_SEL_IR)
       sel->optimize();
-    sel->addID();
-    if (OCL_OUTPUT_SEL_IR)
+    if (OCL_OPTIMIZE_IF_BLOCK)
+      sel->if_opt();
+    if (OCL_OUTPUT_SEL_IR) {
+      sel->addID();
       outputSelectionIR(*this, this->sel, genKernel->getName());
+    }
     schedulePreRegAllocation(*this, *this->sel);
     sel->addID();
     if (UNLIKELY(ra->allocate(*this->sel) == false))
diff --git a/backend/src/backend/gen_insn_selection.hpp b/backend/src/backend/gen_insn_selection.hpp
index 2c70bd8..0eeaa5d 100644
--- a/backend/src/backend/gen_insn_selection.hpp
+++ b/backend/src/backend/gen_insn_selection.hpp
@@ -323,6 +323,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..a99b465
--- /dev/null
+++ b/backend/src/backend/gen_insn_selection_if_opt.cpp
@@ -0,0 +1,109 @@
+
+#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;
+      bool endif_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 || (curr.flag == 0 && curr.subFlag == 1)) {
+            return false;
+          }
+
+          if (insn.opcode == SEL_OP_ELSE) {
+            return false;
+          }
+
+          if (insn.opcode == SEL_OP_SEL_CMP) {
+            return false;
+          }
+        }
+
+        if (insn.opcode == SEL_OP_ENDIF) {
+            endif_exits = true;
+          break;
+        }
+      }
+
+      if (!if_exits || !endif_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(); ) {
+            // remove if and endif, change instruction flags.
+            SelectionInstruction &insn = *iter;
+            if (insn.opcode == SEL_OP_IF && !if_find) {
+              iter = selBlock.insnList.erase(&insn);
+              if_find = true;
+            } else if (insn.opcode == SEL_OP_ENDIF) {
+              iter = selBlock.insnList.erase(&insn);
+              optimized = true;
+            } else {
+              if (if_find) {
+                insn.state.predicate = GEN_PREDICATE_NORMAL;
+                insn.state.flag = 0;
+                insn.state.subFlag = 1;
+              }
+              ++iter;
+            }
+          }
+      }
+  }
+
+  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