[Beignet] [PATCH V2 4/6] Add recompile in kernel side.

Yang Rong rong.r.yang at intel.com
Thu Apr 18 00:18:05 PDT 2013


When recompile, allocate the curbe for constant buffer and patch ia's addrIMM

Signed-off-by: Yang Rong <rong.r.yang at intel.com>
---
 backend/src/backend/context.cpp     |   41 +++++++++++++++++++++++++++++++++++
 backend/src/backend/context.hpp     |    6 +++++
 backend/src/backend/gen_context.cpp |   13 +++++++++++
 backend/src/backend/gen_context.hpp |    2 ++
 backend/src/backend/gen_encoder.cpp |   20 ++++++++++++-----
 backend/src/backend/gen_encoder.hpp |    4 ++++
 backend/src/backend/gen_program.cpp |   14 ++++++------
 backend/src/backend/gen_program.hpp |    3 +++
 backend/src/backend/program.cpp     |   19 ++++++++++++++--
 backend/src/backend/program.h       |   11 +++++++++-
 backend/src/backend/program.hpp     |   15 +++++++++++++
 11 files changed, 132 insertions(+), 16 deletions(-)

diff --git a/backend/src/backend/context.cpp b/backend/src/backend/context.cpp
index 0a26b3d..2313d3d 100644
--- a/backend/src/backend/context.cpp
+++ b/backend/src/backend/context.cpp
@@ -288,6 +288,7 @@ namespace gbe
 
   Kernel *Context::compileKernel(void) {
     this->kernel = this->allocateKernel();
+    this->kernel->bCurbeChanged = false;
     this->kernel->simdWidth = this->simdWidth;
     this->buildPatchList();
     this->buildArgList();
@@ -303,6 +304,42 @@ namespace gbe
     return this->kernel;
   }
 
+  void Context::recompileKernel(void) {
+    //content's unit have destroyed after compiler, so can't use unti, fn in recompiler
+    if(this->kernel->bCurbeChanged) {
+      this->reallocCurbe();
+      this->patchCBOffsets();
+      this->kernel->bCurbeChanged = false;
+    }
+  }
+
+  void Context::reallocCurbe(void) {
+    for (uint32_t argID = 0; argID < kernel->argNum; ++argID) {
+      if(kernel->args[argID].type != GBE_ARG_CONSTANT_PTR)
+        continue;
+      if(kernel->args[argID].bufSize == kernel->args[argID].allocedSize)
+        continue;
+
+      //free previous
+      int32_t offset = kernel->getCurbeOffset(GBE_CURBE_EXTRA_ARGUMENT, argID+GBE_CONSTANT_BUFFER);
+      if(offset >= 0)
+          deallocate(offset+GEN_REG_SIZE);
+      kernel->args[argID].allocedSize = 0;
+
+      if(kernel->args[argID].bufSize > 0) {
+        newCurbeEntry(GBE_CURBE_EXTRA_ARGUMENT, GBE_CONSTANT_BUFFER+argID, kernel->args[argID].bufSize, 32);
+        kernel->args[argID].allocedSize = kernel->args[argID].bufSize;
+      }
+
+      //add to cbCurbeOffsets
+      std::sort(kernel->patches.begin(), kernel->patches.end());
+      offset = kernel->getCurbeOffset(GBE_CURBE_EXTRA_ARGUMENT, argID+GBE_CONSTANT_BUFFER);
+      GBE_ASSERT(offset>=0);
+      cbCurbeOffsets.insert(std::make_pair(kernel->args[argID].reg, offset+GEN_REG_SIZE));
+    }
+    kernel->curbeSize = ALIGN(kernel->curbeSize, GEN_REG_SIZE);
+  }
+
   int16_t Context::allocate(int16_t size, int16_t alignment) {
     return partitioner->allocate(size, alignment);
   }
@@ -421,6 +458,10 @@ namespace gbe
       kernel->args = NULL;
     for (uint32_t argID = 0; argID < kernel->argNum; ++argID) {
       const auto &arg = fn.getArg(argID);
+      kernel->args[argID].bufSize = 0;
+      kernel->args[argID].allocedSize = 0;
+      //in recompiler, unit have been destroyed, so record Register here
+      kernel->args[argID].reg = arg.reg;
       switch (arg.type) {
         case ir::FunctionArgument::VALUE:
         case ir::FunctionArgument::STRUCTURE:
diff --git a/backend/src/backend/context.hpp b/backend/src/backend/context.hpp
index 3b6e635..c897769 100644
--- a/backend/src/backend/context.hpp
+++ b/backend/src/backend/context.hpp
@@ -57,6 +57,8 @@ namespace gbe
     virtual ~Context(void);
     /*! Compile the code */
     Kernel *compileKernel(void);
+    void recompileKernel(void);
+    void reallocCurbe(void);
     /*! Tells if the labels is used */
     INLINE bool isLabelUsed(ir::LabelIndex index) const {
       return usedLabels.contains(index);
@@ -93,6 +95,8 @@ namespace gbe
   protected:
     /*! Build the instruction stream. Return false if failed */
     virtual bool emitCode(void) = 0;
+    /*! Patch the curbe gen register offset */
+    virtual void patchCBOffsets(void) = 0;
     /*! Allocate a new empty kernel (to be implemented) */
     virtual Kernel *allocateKernel(void) = 0;
     /*! Look if a stack is needed and allocate it */
@@ -118,6 +122,7 @@ namespace gbe
     /*! Provide for each branch and label the label index target */
     typedef map<const ir::Instruction*, ir::LabelIndex> JIPMap;
     typedef map<const ir::Register, ir::Register> ConstBasePropMap;
+    typedef map<const ir::Register, uint32_t> CBRegOffsetMap;
     const ir::Unit &unit;                 //!< Unit that contains the kernel
     const ir::Function &fn;               //!< Function to compile
     std::string name;                     //!< Name of the kernel to compile
@@ -128,6 +133,7 @@ namespace gbe
     set<ir::LabelIndex> usedLabels;       //!< Set of all used labels
     JIPMap JIPs;                          //!< Where to jump all labels/branches
     ConstBasePropMap constBaseProps;      //!< const buffer reg propagation regs
+    CBRegOffsetMap cbCurbeOffsets;          //!< const buffer base ir reg --> curbe reg offset Map
     uint32_t simdWidth;                   //!< Number of lanes per HW threads
     GBE_CLASS(Context);                   //!< Use custom allocators
   };
diff --git a/backend/src/backend/gen_context.cpp b/backend/src/backend/gen_context.cpp
index 54c6d77..a240fec 100644
--- a/backend/src/backend/gen_context.cpp
+++ b/backend/src/backend/gen_context.cpp
@@ -84,6 +84,19 @@ namespace gbe
     }
   }
 
+  void GenContext::patchCBOffsets(void) {
+    using namespace ir;
+    for (auto pair : cbMovePos) {
+      const Register reg = pair.first;
+      const int32_t insnID = pair.second;
+      const int32_t offset = cbCurbeOffsets.find(reg)->second;
+      p->patchAddrIMM(insnID+1, offset);
+    }
+
+    GenKernel *genKernel = static_cast<GenKernel*>(this->kernel);
+    std::memcpy(genKernel->insns, &p->store[0], genKernel->insnNum * sizeof(GenInstruction));
+  }
+
   void GenContext::emitStackPointer(void) {
     using namespace ir;
 
diff --git a/backend/src/backend/gen_context.hpp b/backend/src/backend/gen_context.hpp
index 8aabcd8..1f80e7b 100644
--- a/backend/src/backend/gen_context.hpp
+++ b/backend/src/backend/gen_context.hpp
@@ -55,6 +55,8 @@ namespace gbe
     ~GenContext(void);
     /*! Implements base class */
     virtual bool emitCode(void);
+    /*! Patch the curbe gen register offset */
+    virtual void patchCBOffsets(void);
     /*! Function we emit code for */
     INLINE const ir::Function &getFunction(void) const { return fn; }
     /*! Simd width chosen for the current function */
diff --git a/backend/src/backend/gen_encoder.cpp b/backend/src/backend/gen_encoder.cpp
index ed7c256..9970cac 100644
--- a/backend/src/backend/gen_encoder.cpp
+++ b/backend/src/backend/gen_encoder.cpp
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright © 2012 Intel Corporation
  *
  * This library is free software; you can redistribute it and/or
@@ -21,7 +21,7 @@
  Copyright (C) Intel Corp.  2006.  All Rights Reserved.
  Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
  develop this 3D driver.
- 
+
  Permission is hereby granted, free of charge, to any person obtaining
  a copy of this software and associated documentation files (the
  "Software"), to deal in the Software without restriction, including
@@ -29,11 +29,11 @@
  distribute, sublicense, and/or sell copies of the Software, and to
  permit persons to whom the Software is furnished to do so, subject to
  the following conditions:
- 
+
  The above copyright notice and this permission notice (including the
  next paragraph) shall be included in all copies or substantial
  portions of the Software.
- 
+
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -41,7 +41,7 @@
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- 
+
  **********************************************************************/
  /*
   * Authors:
@@ -301,7 +301,7 @@ namespace gbe
          insn->bits3.da16.src1_reg_nr = reg.nr;
        }
 
-       if (reg.width == GEN_WIDTH_1 && 
+       if (reg.width == GEN_WIDTH_1 &&
            insn->header.execution_size == GEN_WIDTH_1) {
          insn->bits3.da1.src1_horiz_stride = GEN_HORIZONTAL_STRIDE_0;
          insn->bits3.da1.src1_width = GEN_WIDTH_1;
@@ -686,6 +686,14 @@ namespace gbe
     this->setSrc1(&insn, GenRegister::immd(jumpDistance));
   }
 
+  void GenEncoder::patchAddrIMM(uint32_t insnID, int32_t offset) {
+    GenInstruction &insn = this->store[insnID];
+    assert(insnID < this->store.size());
+    assert(insn.header.opcode == GEN_OPCODE_MOV);
+    insn.bits2.ia1.src0_indirect_offset = offset;
+    //this->setSrc1(&insn, GenRegister::immuw(offset));
+  }
+
   void GenEncoder::CMP(uint32_t conditional, GenRegister src0, GenRegister src1) {
     if (needToSplitCmp(this, src0, src1) == false) {
       GenInstruction *insn = this->next(GEN_OPCODE_CMP);
diff --git a/backend/src/backend/gen_encoder.hpp b/backend/src/backend/gen_encoder.hpp
index 7e26f0a..8d66289 100644
--- a/backend/src/backend/gen_encoder.hpp
+++ b/backend/src/backend/gen_encoder.hpp
@@ -65,6 +65,7 @@ namespace gbe
   public:
     /*! simdWidth is the default width for the instructions */
     GenEncoder(uint32_t simdWidth, uint32_t gen);
+
     /*! Size of the stack (should be large enough) */
     enum { MAX_STATE_NUM = 16 };
     /*! Push the current instruction state */
@@ -156,6 +157,9 @@ namespace gbe
     /*! Patch JMPI (located at index insnID) with the given jump distance */
     void patchJMPI(uint32_t insnID, int32_t jumpDistance);
 
+    /*! Patch the constant buffer ia mov offset */
+    void patchAddrIMM(uint32_t insnID, int32_t offset);
+
     ////////////////////////////////////////////////////////////////////////
     // Helper functions to encode
     ////////////////////////////////////////////////////////////////////////
diff --git a/backend/src/backend/gen_program.cpp b/backend/src/backend/gen_program.cpp
index 8a7efdb..4cac5ba 100644
--- a/backend/src/backend/gen_program.cpp
+++ b/backend/src/backend/gen_program.cpp
@@ -37,12 +37,12 @@
 namespace gbe {
 
   GenKernel::GenKernel(const std::string &name) :
-    Kernel(name), insns(NULL), insnNum(0)
+    Kernel(name), insns(NULL), insnNum(0), cxt(NULL)
   {}
-  GenKernel::~GenKernel(void) { GBE_SAFE_DELETE_ARRAY(insns); }
+  GenKernel::~GenKernel(void) { GBE_DELETE(cxt); GBE_SAFE_DELETE_ARRAY(insns); }
   const char *GenKernel::getCode(void) const { return (const char*) insns; }
   size_t GenKernel::getCodeSize(void) const { return insnNum * sizeof(GenInstruction); }
-
+  void GenKernel::recompile(void) { cxt->recompileKernel(); }
   GenProgram::GenProgram(void) {}
   GenProgram::~GenProgram(void) {}
 
@@ -58,7 +58,6 @@ namespace gbe {
   };
 
   Kernel *GenProgram::compileKernel(const ir::Unit &unit, const std::string &name) {
-
     // Be careful when the simdWidth is forced by the programmer. We can see it
     // when the function already provides the simd width we need to use (i.e.
     // non zero)
@@ -76,16 +75,17 @@ namespace gbe {
       unit.getFunction(name)->setSimdWidth(simdWidth);
       Context *ctx = GBE_NEW(GenContext, unit, name, limitRegisterPressure);
       kernel = ctx->compileKernel();
-      GBE_DELETE(ctx);
-      if (kernel != NULL)
+      if (kernel != NULL) {
+        ((GenKernel *)kernel)->cxt = (GenContext *)ctx;
         break;
+      }
+      GBE_DELETE(ctx);
     }
 
     // XXX spill must be implemented
     GBE_ASSERTM(kernel != NULL, "Register spilling not supported yet!");
     return kernel;
   }
-
   static gbe_program genProgramNewFromBinary(const char *binary, size_t size) {
     NOT_IMPLEMENTED;
     return NULL;
diff --git a/backend/src/backend/gen_program.hpp b/backend/src/backend/gen_program.hpp
index 68b0427..f41eb0c 100644
--- a/backend/src/backend/gen_program.hpp
+++ b/backend/src/backend/gen_program.hpp
@@ -27,6 +27,7 @@
 
 #include "backend/program.h"
 #include "backend/program.hpp"
+#include "backend/gen_context.hpp"
 
 // Gen ISA instruction
 struct GenInstruction;
@@ -44,8 +45,10 @@ namespace gbe
     virtual const char *getCode(void) const;
     /*! Implements base class */
     virtual size_t getCodeSize(void) const;
+    virtual void recompile(void);
     GenInstruction *insns; //!< Instruction stream
     uint32_t insnNum;      //!< Number of instructions
+    GenContext *cxt;
     GBE_CLASS(GenKernel);  //!< Use custom allocators
   };
 
diff --git a/backend/src/backend/program.cpp b/backend/src/backend/program.cpp
index df0df28..66ecc0d 100644
--- a/backend/src/backend/program.cpp
+++ b/backend/src/backend/program.cpp
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright © 2012 Intel Corporation
  *
  * This library is free software; you can redistribute it and/or
@@ -229,6 +229,18 @@ namespace gbe {
     return kernel->getUseSLM() ? 1 : 0;
   }
 
+  static void kernelSetConstBufSize(gbe_kernel genKernel, uint32_t argID, size_t sz) {
+    if (genKernel == NULL) return;
+    gbe::Kernel *kernel = (gbe::Kernel*) genKernel;
+    kernel->setConstBufSize(argID, sz);
+  }
+
+  static void kernelRecompile(gbe_kernel genKernel){
+    if(genKernel == NULL) return;
+    gbe::Kernel *kernel = (gbe::Kernel *) genKernel;
+    kernel->recompile();
+  }
+
   static uint32_t kernelGetRequiredWorkGroupSize(gbe_kernel kernel, uint32_t dim) {
     return 0u;
   }
@@ -251,6 +263,8 @@ GBE_EXPORT_SYMBOL gbe_kernel_get_simd_width_cb *gbe_kernel_get_simd_width = NULL
 GBE_EXPORT_SYMBOL gbe_kernel_get_curbe_offset_cb *gbe_kernel_get_curbe_offset = NULL;
 GBE_EXPORT_SYMBOL gbe_kernel_get_curbe_size_cb *gbe_kernel_get_curbe_size = NULL;
 GBE_EXPORT_SYMBOL gbe_kernel_get_stack_size_cb *gbe_kernel_get_stack_size = NULL;
+GBE_EXPORT_SYMBOL gbe_kernel_set_const_buffer_size_cb *gbe_kernel_set_const_buffer_size = NULL;
+GBE_EXPORT_SYMBOL gbe_kernel_recompile_cb *gbe_kernel_recompile = NULL;
 GBE_EXPORT_SYMBOL gbe_kernel_get_required_work_group_size_cb *gbe_kernel_get_required_work_group_size = NULL;
 GBE_EXPORT_SYMBOL gbe_kernel_use_slm_cb *gbe_kernel_use_slm = NULL;
 
@@ -275,6 +289,8 @@ namespace gbe
       gbe_kernel_get_curbe_offset = gbe::kernelGetCurbeOffset;
       gbe_kernel_get_curbe_size = gbe::kernelGetCurbeSize;
       gbe_kernel_get_stack_size = gbe::kernelGetStackSize;
+      gbe_kernel_set_const_buffer_size = gbe::kernelSetConstBufSize;
+      gbe_kernel_recompile = gbe::kernelRecompile;
       gbe_kernel_get_required_work_group_size = gbe::kernelGetRequiredWorkGroupSize;
       gbe_kernel_use_slm = gbe::kernelUseSLM;
       genSetupCallBacks();
@@ -283,4 +299,3 @@ namespace gbe
 
   static CallBackInitializer cbInitializer;
 } /* namespace gbe */
-
diff --git a/backend/src/backend/program.h b/backend/src/backend/program.h
index b90c1df..08db4eb 100644
--- a/backend/src/backend/program.h
+++ b/backend/src/backend/program.h
@@ -81,7 +81,8 @@ enum gbe_curbe_type {
 
 /*! Extra arguments use the negative range of sub-values */
 enum gbe_extra_argument {
-  GBE_STACK_BUFFER = 0 /* Give stack location in curbe */
+  GBE_STACK_BUFFER = 0, /* Give stack location in curbe */
+  GBE_CONSTANT_BUFFER = 1 /* constant buffer argument location in curbe */
 };
 
 /*! Create a new program from the given source code (zero terminated string) */
@@ -155,6 +156,14 @@ extern gbe_kernel_get_curbe_size_cb *gbe_kernel_get_curbe_size;
 typedef int32_t (gbe_kernel_get_stack_size_cb)(gbe_kernel);
 extern gbe_kernel_get_stack_size_cb *gbe_kernel_get_stack_size;
 
+/*! Set the const pointer arg size */
+typedef void (gbe_kernel_set_const_buffer_size_cb)(gbe_kernel, uint32_t argID, size_t sz);
+extern gbe_kernel_set_const_buffer_size_cb *gbe_kernel_set_const_buffer_size;
+
+/*! Recompiler kernel when enqueue only for const now */
+typedef void (gbe_kernel_recompile_cb)(gbe_kernel);
+extern gbe_kernel_recompile_cb *gbe_kernel_recompile;
+
 /*! Get the curbe offset where to put the data. Returns -1 if not required */
 typedef int32_t (gbe_kernel_get_curbe_offset_cb)(gbe_kernel, enum gbe_curbe_type type, uint32_t sub_type);
 extern gbe_kernel_get_curbe_offset_cb *gbe_kernel_get_curbe_offset;
diff --git a/backend/src/backend/program.hpp b/backend/src/backend/program.hpp
index e0f7dba..a8b2615 100644
--- a/backend/src/backend/program.hpp
+++ b/backend/src/backend/program.hpp
@@ -25,6 +25,7 @@
 #ifndef __GBE_PROGRAM_HPP__
 #define __GBE_PROGRAM_HPP__
 
+#include "ir/instruction.hpp"
 #include "backend/program.h"
 #include "sys/hash_map.hpp"
 #include "sys/vector.hpp"
@@ -42,6 +43,9 @@ namespace gbe {
   struct KernelArgument {
     gbe_arg_type type; //!< Pointer, structure, image, regular value?
     uint32_t size;     //!< Size of the argument
+    uint32_t bufSize;  //!< Size of constant buffer
+    uint32_t allocedSize;  //!< Size of alloced cb, used to check whether need realloc cb
+    ir::Register reg;  //!< because of some member of context like unit and fn destoryed when recompiler, save reg for it
   };
 
   /*! Stores the offset where to patch where to patch */
@@ -94,6 +98,16 @@ namespace gbe {
     INLINE uint32_t getSIMDWidth(void) const { return this->simdWidth; }
     /*! Says if SLM is needed for it */
     INLINE bool getUseSLM(void) const { return this->useSLM; }
+    void setConstBufSize(uint32_t argID, size_t sz) {
+        if(argID >= argNum) return;
+        if(args[argID].type != GBE_ARG_CONSTANT_PTR) return;
+        if(args[argID].bufSize != sz) {
+          this->bCurbeChanged = true;
+          args[argID].bufSize = sz;
+        }
+    }
+    /* recompile for constant buffer alloc */
+    virtual void recompile(void) = 0;
   protected:
     friend class Context;      //!< Owns the kernels
     const std::string name;    //!< Kernel name
@@ -104,6 +118,7 @@ namespace gbe {
     uint32_t simdWidth;        //!< SIMD size for the kernel (lane number)
     uint32_t stackSize;        //!< Stack size (may be 0 if unused)
     bool useSLM;               //!< SLM requires a special HW config
+    bool     bCurbeChanged;
     GBE_CLASS(Kernel);         //!< Use custom allocators
   };
 
-- 
1.7.9.5



More information about the Beignet mailing list