[Beignet] [Patch v2 4/4] move simpleBlock check and if/endif optimize after select.

xionghu.luo at intel.com xionghu.luo at intel.com
Fri Jan 6 14:40:43 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).

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.hpp        |   2 +
 backend/src/backend/gen_insn_selection_if_opt.cpp | 119 ++++++++++++++++++++++
 4 files changed, 129 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.hpp b/backend/src/backend/gen_insn_selection.hpp
index f4cc948..88ae44f 100644
--- a/backend/src/backend/gen_insn_selection.hpp
+++ b/backend/src/backend/gen_insn_selection.hpp
@@ -318,6 +318,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..026f5b9
--- /dev/null
+++ b/backend/src/backend/gen_insn_selection_if_opt.cpp
@@ -0,0 +1,119 @@
+
+#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(); 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