[Beignet] [PATCH 2/3] GBE: fix the large if/endif block issue.

Yang, Rong R rong.r.yang at intel.com
Mon Apr 28 19:15:24 PDT 2014


One comment.

-----Original Message-----
From: Beignet [mailto:beignet-bounces at lists.freedesktop.org] On Behalf Of Zhigang Gong
Sent: Monday, April 28, 2014 9:01 AM
To: beignet at lists.freedesktop.org
Cc: Gong, Zhigang
Subject: [Beignet] [PATCH 2/3] GBE: fix the large if/endif block issue.

Some test cases have some very large block which contains more than 32768/2 instructions which could fit into one if/endif block.

This patch introduce a ifendif fix switch at the GenContext.
Once we encounter one of such error, we set the switch on and then recompile the kernel. When the switch is on, we will insert extra endif/if pair to the block to split one if/endif block to multiple ones to fix the large if/endif issue.

Signed-off-by: Zhigang Gong <zhigang.gong at intel.com>
---
 backend/src/backend/gen_context.cpp        | 21 ++++++++++++++-------
 backend/src/backend/gen_context.hpp        | 16 +++++++++++++++-
 backend/src/backend/gen_insn_selection.cpp | 19 ++++++++++++++++---
 backend/src/backend/gen_program.cpp        |  8 ++++++++
 backend/src/backend/gen_reg_allocation.cpp |  9 ++++-----
 5 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/backend/src/backend/gen_context.cpp b/backend/src/backend/gen_context.cpp
index 349349d..64b822e 100644
--- a/backend/src/backend/gen_context.cpp
+++ b/backend/src/backend/gen_context.cpp
@@ -52,6 +52,7 @@ namespace gbe
     this->p = NULL;
     this->sel = NULL;
     this->ra = NULL;
+    this->ifEndifFix = false;
   }
 
   GenContext::~GenContext(void) {
@@ -72,6 +73,7 @@ namespace gbe
     this->ra = GBE_NEW(GenRegAllocator, *this);
     this->branchPos2.clear();
     this->branchPos3.clear();
+    this->errCode = NO_ERROR;
   }
 
   void GenContext::emitInstructionStream(void) { @@ -97,7 +99,7 @@ namespace gbe
 	p->NOP();
   }
 
-  void GenContext::patchBranches(void) {
+  bool GenContext::patchBranches(void) {
     using namespace ir;
     for (auto pair : branchPos2) {
       const LabelIndex label = pair.first; @@ -108,14 +110,17 @@ namespace gbe
     for (auto pair : branchPos3) {
       const LabelPair labelPair = pair.first;
       const int32_t insnID = pair.second;
-      // FIXME the 'labelPair' implementation must be fixed, as it is hard to
-      // convert InstructionSelection offset to ASM offset since asm maybe compacted
       const int32_t jip = labelPos.find(labelPair.l0)->second;
       const int32_t uip = labelPos.find(labelPair.l1)->second;
-      assert((jip - insnID) < 32767 && (jip - insnID) > -32768);
-      assert((uip - insnID) < 32767 && (uip - insnID) > -32768);
+      if (((jip - insnID) > 32767 || (jip - insnID) < -32768) ||
+          ((uip - insnID) > 32768 || (uip - insnID) < -32768)) {
+        // The only possible error instruction is if/endif here.
+        errCode = OUT_OF_RANGE_IF_ENDIF; 
+        return false;
+      }
       p->patchJMPI(insnID, (((uip - insnID)) << 16) | ((jip - insnID)));
     }
+    return true;
   }
 
   void GenContext::clearFlagRegister(void) { @@ -2013,7 +2018,8 @@ namespace gbe
     this->clearFlagRegister();
     this->emitStackPointer();
     this->emitInstructionStream();
-    this->patchBranches();
+    if (this->patchBranches() == false)
+      return false;
     genKernel->insnNum = p->store.size();
     genKernel->insns = GBE_NEW_ARRAY_NO_ARG(GenInstruction, genKernel->insnNum);
     std::memcpy(genKernel->insns, &p->store[0], genKernel->insnNum * sizeof(GenInstruction)); @@ -2024,7 +2030,8 @@ namespace gbe
       GenNativeInstruction insn;
       std::cout << "  L0:" << std::endl;
       for (uint32_t insnID = 0; insnID < genKernel->insnNum; ) {
-        if (labelPos.find((ir::LabelIndex)(curLabel + 1))->second == insnID) {
+        if (labelPos.find((ir::LabelIndex)(curLabel + 1))->second == insnID &&
+            curLabel < this->getFunction().labelNum()) {
           std::cout << "  L" << curLabel + 1 << ":" << std::endl;
           curLabel = (ir::LabelIndex)(curLabel + 1);
         }
diff --git a/backend/src/backend/gen_context.hpp b/backend/src/backend/gen_context.hpp
index dfddd28..3b59797 100644
--- a/backend/src/backend/gen_context.hpp
+++ b/backend/src/backend/gen_context.hpp
@@ -42,6 +42,13 @@ namespace gbe
   class SelectionInstruction; // Pre-RA Gen instruction
   class SelectionReg;         // Pre-RA Gen register
   class GenRegister;
+  typedef enum {
+    NO_ERROR,
+    REGISTER_ALLOCATION_FAIL,
+    REGISTER_SPILL_EXCEED_THRESHOLD,
+    REGISTER_SPILL_FAIL,
+    OUT_OF_RANGE_IF_ENDIF,
+  } CompileErrorCode;
 
   /*! Context is the helper structure to build the Gen ISA or simulation code
    *  from GenIR
@@ -73,7 +80,7 @@ namespace gbe
     /*! Emit the instructions */
     void emitInstructionStream(void);
     /*! Set the correct target values for the branches */
-    void patchBranches(void);
+    bool patchBranches(void);
     /*! Forward ir::Function isSpecialReg method */
     INLINE bool isSpecialReg(ir::Register reg) const {
       return fn.isSpecialReg(reg);
@@ -177,12 +184,19 @@ namespace gbe
     uint32_t reservedSpillRegs;
     bool limitRegisterPressure;
     bool relaxMath;
+    const bool getIFENDIFFix(void) const { return ifEndifFix; }
+    void setIFENDIFFix(bool fix) { ifEndifFix = fix; }
+    const CompileErrorCode getErrCode() { return errCode; }
   private:
+    CompileErrorCode errCode;
+    bool ifEndifFix;
     /*! Build the curbe patch list for the given kernel */
     void buildPatchList(void);
     /*! allocate a new curbe register and insert to curbe pool. */
     void allocCurbeReg(ir::Register reg, gbe_curbe_type value, uint32_t subValue = 0);
 
+    friend GenRegAllocator;               //!< need to access errCode directly. 
+
   };
 
 } /* namespace gbe */
diff --git a/backend/src/backend/gen_insn_selection.cpp b/backend/src/backend/gen_insn_selection.cpp
index 420737c..d484212 100644
--- a/backend/src/backend/gen_insn_selection.cpp
+++ b/backend/src/backend/gen_insn_selection.cpp
@@ -196,7 +196,7 @@ namespace gbe
   // SelectionBlock
   ///////////////////////////////////////////////////////////////////////////
 
-  SelectionBlock::SelectionBlock(const ir::BasicBlock *bb) : bb(bb) {}
+  SelectionBlock::SelectionBlock(const ir::BasicBlock *bb) : bb(bb), 
+ endifLabel( (ir::LabelIndex) 0){}
 
   void SelectionBlock::append(ir::Register reg) { tmp.push_back(reg); }
 
@@ -975,7 +975,7 @@ namespace gbe
     this->LABEL(this->block->endifLabel);
     SelectionInstruction *insn = this->appendInsn(SEL_OP_ENDIF, 0, 1);
     insn->src(0) = src;
-    insn->index = uint16_t(jip);
+    insn->index = uint16_t(this->block->endifLabel);
   }
 
   void Selection::Opaque::CMP(uint32_t conditional, Reg src0, Reg src1, Reg dst) { @@ -1476,13 +1476,26 @@ namespace gbe
         // If there is no branch at the end of this block.
 
         // Try all the patterns from best to worst
-
         do {
           if ((*it)->emit(*this, dag))
             break;
           ++it;
         } while (it != end);
         GBE_ASSERT(it != end);
+        // If we are in if/endif fix mode, and this block is
+        // large enough, we need to insert endif/if pair to eliminate
+        // the too long if/endif block.
+        if (this->ctx.getIFENDIFFix() &&
+            this->block->insnList.size() != 0 &&
+            this->block->insnList.size() % 1000 == 0 &&
+            (uint16_t)this->block->endifLabel != 0) {
>>>>>>>if needEndif is false, also need this Endif?


+          ir::LabelIndex jip = this->block->endifLabel;
+          this->ENDIF(GenRegister::immd(0), jip);
+          this->push();
+            this->curr.predicate = GEN_PREDICATE_NORMAL;
+            this->IF(GenRegister::immd(0), jip, jip);
+          this->pop();
+        }
 
         if (needEndif) {
           const ir::BasicBlock *curr = insn.getParent(); diff --git a/backend/src/backend/gen_program.cpp b/backend/src/backend/gen_program.cpp
index 3a4421a..8aaea6a 100644
--- a/backend/src/backend/gen_program.cpp
+++ b/backend/src/backend/gen_program.cpp
@@ -118,9 +118,17 @@ namespace gbe {
       ctx->startNewCG(simdWidth, reservedSpillRegs, limitRegisterPressure);
       kernel = ctx->compileKernel();
       if (kernel != NULL) {
+        GBE_ASSERT(ctx->getErrCode() == NO_ERROR);
         break;
       }
       fn->getImageSet()->clearInfo();
+      // If we get a out of range if/endif error.
+      // We need to set the context to if endif fix mode and restart the previous compile.
+      if ( ctx->getErrCode() == OUT_OF_RANGE_IF_ENDIF && !ctx->getIFENDIFFix() ) {
+        ctx->setIFENDIFFix(true);
+        codeGen--;
+      } else
+        GBE_ASSERT(!(ctx->getErrCode() == OUT_OF_RANGE_IF_ENDIF && 
+ ctx->getIFENDIFFix()));
     }
     //GBE_DELETE(ctx);
 
diff --git a/backend/src/backend/gen_reg_allocation.cpp b/backend/src/backend/gen_reg_allocation.cpp
index 339125d..a10f57c 100644
--- a/backend/src/backend/gen_reg_allocation.cpp
+++ b/backend/src/backend/gen_reg_allocation.cpp
@@ -598,6 +598,7 @@ namespace gbe
   IVAR(OCL_SIMD16_SPILL_THRESHOLD, 0, 16, 256);
   bool GenRegAllocator::Opaque::allocateGRFs(Selection &selection) {
     // Perform the linear scan allocator
+    ctx.errCode = REGISTER_ALLOCATION_FAIL;
     const uint32_t regNum = ctx.sel->getRegNum();
     for (uint32_t startID = 0; startID < regNum; ++startID) {
       const GenRegInterval &interval = *this->starting[startID]; @@ -651,20 +652,18 @@ namespace gbe
       GBE_ASSERT(reservedReg != 0);
       if (ctx.getSimdWidth() == 16) {
         if (spilledRegs.size() > (unsigned int)OCL_SIMD16_SPILL_THRESHOLD) {
-          if (GBE_DEBUG)
-            std::cerr << "WARN: exceed simd 16 spill threshold ("
-                      << spilledRegs.size() << ">" << OCL_SIMD16_SPILL_THRESHOLD
-                      << ")" << std::endl;
+          ctx.errCode = REGISTER_SPILL_EXCEED_THRESHOLD;
           return false;
         }
       }
       allocateScratchForSpilled();
       bool success = selection.spillRegs(spilledRegs, reservedReg);
       if (!success) {
-        std::cerr << "Fail to spill registers." << std::endl;
+        ctx.errCode = REGISTER_SPILL_FAIL;
         return false;
       }
     }
+    ctx.errCode = NO_ERROR;
     return true;
   }
 
--
1.8.3.2

_______________________________________________
Beignet mailing list
Beignet at lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/beignet


More information about the Beignet mailing list