[Beignet] [PATCH 1/3] GBE: support const private array initialization.

Ruiling Song ruiling.song at intel.com
Wed Dec 3 18:52:09 PST 2014


Developers are allowed to declare initialized private array like below:

void func() {
  const arr[]={1, 2, 3, 4};
}

The implementation is simply put them into __constant memory space.

Signed-off-by: Ruiling Song <ruiling.song at intel.com>
---
 backend/src/backend/gen_insn_selection.cpp |   43 +++++++++++-----------
 backend/src/llvm/llvm_gen_backend.cpp      |   54 +++++++++++++++-------------
 2 files changed, 53 insertions(+), 44 deletions(-)

diff --git a/backend/src/backend/gen_insn_selection.cpp b/backend/src/backend/gen_insn_selection.cpp
index 96970c7..7ea2498 100644
--- a/backend/src/backend/gen_insn_selection.cpp
+++ b/backend/src/backend/gen_insn_selection.cpp
@@ -2844,7 +2844,6 @@ namespace gbe
                    vector<GenRegister> &dst2,
                    GenRegister addr,
                    uint32_t valueNum,
-                   ir::AddressSpace space,
                    ir::BTI bti) const
     {
       for (uint32_t x = 0; x < bti.count; x++) {
@@ -2852,7 +2851,7 @@ namespace gbe
           for (uint32_t dstID = 0; dstID < valueNum; ++dstID)
             dst2[dstID] = sel.selReg(sel.reg(ir::FAMILY_DWORD), ir::TYPE_U32);
 
-        GenRegister temp = getRelativeAddress(sel, addr, space, bti.bti[x]);
+        GenRegister temp = getRelativeAddress(sel, addr, bti.bti[x]);
         sel.UNTYPED_READ(temp, dst2.data(), valueNum, bti.bti[x]);
         if(x > 0) {
           sel.push();
@@ -2878,7 +2877,7 @@ namespace gbe
       vector<GenRegister> dst2(valueNum);
       for (uint32_t dstID = 0; dstID < valueNum; ++dstID)
         dst2[dstID] = dst[dstID] = sel.selReg(insn.getValue(dstID), TYPE_U32);
-      readDWord(sel, dst, dst2, addr, valueNum, insn.getAddressSpace(), bti);
+      readDWord(sel, dst, dst2, addr, valueNum, bti);
     }
 
     void emitDWordGather(Selection::Opaque &sel,
@@ -2925,7 +2924,7 @@ namespace gbe
       GBE_ASSERT(valueNum == 1);
       GBE_ASSERT(bti.count == 1);
       vector<GenRegister> dst(valueNum);
-      GenRegister tmpAddr = getRelativeAddress(sel, addr, insn.getAddressSpace(), bti.bti[0]);
+      GenRegister tmpAddr = getRelativeAddress(sel, addr, bti.bti[0]);
       for ( uint32_t dstID = 0; dstID < valueNum; ++dstID)
         dst[dstID] = sel.selReg(insn.getValue(dstID), ir::TYPE_U64);
       sel.READ64(tmpAddr, dst.data(), valueNum, bti.bti[0]);
@@ -2996,7 +2995,7 @@ namespace gbe
         tmp2[i] = tmp[i] = GenRegister::udxgrf(simdWidth, tmpReg[i]);
       }
 
-      readDWord(sel, tmp, tmp2, address, tmpRegNum, insn.getAddressSpace(), bti);
+      readDWord(sel, tmp, tmp2, address, tmpRegNum, bti);
 
       for(uint32_t i = 0; i < tmpRegNum; i++) {
         unsigned int elemNum = (valueNum - i * (4 / typeSize)) > 4/typeSize ?
@@ -3099,7 +3098,7 @@ namespace gbe
               sel.ADD(alignedAddr, alignedAddr, GenRegister::immud(pos * 4));
             sel.pop();
           }
-          readDWord(sel, t1, t2, alignedAddr, width, insn.getAddressSpace(), bti);
+          readDWord(sel, t1, t2, alignedAddr, width, bti);
           remainedReg -= width;
           pos += width;
         } while(remainedReg);
@@ -3124,7 +3123,7 @@ namespace gbe
           if (x > 0)
             tmp = sel.selReg(sel.reg(family, simdWidth == 1), insn.getValueType());
 
-          GenRegister addr = getRelativeAddress(sel, address, insn.getAddressSpace(), bti.bti[x]);
+          GenRegister addr = getRelativeAddress(sel, address, bti.bti[x]);
           readByteAsDWord(sel, elemSize, addr, tmp, simdWidth, bti.bti[x]);
           if (x > 0) {
             sel.push();
@@ -3151,8 +3150,8 @@ namespace gbe
       sel.INDIRECT_MOVE(dst, src);
     }
 
-    INLINE GenRegister getRelativeAddress(Selection::Opaque &sel, GenRegister address, ir::AddressSpace space, uint8_t bti) const {
-      if(space == ir::MEM_LOCAL || space == ir::MEM_CONSTANT)
+    INLINE GenRegister getRelativeAddress(Selection::Opaque &sel, GenRegister address, uint8_t bti) const {
+      if (bti == 0xfe || bti == BTI_CONSTANT)
         return address;
 
       sel.push();
@@ -3162,6 +3161,14 @@ namespace gbe
       sel.pop();
       return temp;
     }
+    // check whether all binded table index point to constant memory
+    INLINE bool isAllConstant(const ir::BTI &bti) const {
+      for (int x = 0; x < bti.count; x++) {
+         if (bti.bti[x] != BTI_CONSTANT)
+           return false;
+      }
+      return true;
+    }
 
     INLINE bool emitOne(Selection::Opaque &sel, const ir::LoadInstruction &insn, bool &markChildren) const {
       using namespace ir;
@@ -3179,14 +3186,10 @@ namespace gbe
         sel.ADD(temp, address, sel.selReg(ocl::slmoffset, ir::TYPE_U32));
         address = temp;
       }
-      BTI bti;
-      if (space == MEM_CONSTANT || space == MEM_LOCAL) {
-        bti.bti[0] = space == MEM_CONSTANT ? BTI_CONSTANT : 0xfe;
-        bti.count = 1;
-      } else {
-        bti = insn.getBTI();
-      }
-      if (space == MEM_CONSTANT) {
+      const BTI &bti = insn.getBTI();
+      bool allConstant = isAllConstant(bti);
+
+      if (allConstant) {
         // XXX TODO read 64bit constant through constant cache
         // Per HW Spec, constant cache messages can read at least DWORD data.
         // So, byte/short data type, we have to read through data cache.
@@ -3291,8 +3294,8 @@ namespace gbe
       }
     }
 
-    INLINE GenRegister getRelativeAddress(Selection::Opaque &sel, GenRegister address, ir::AddressSpace space, uint8_t bti) const {
-      if(space == ir::MEM_LOCAL || space == ir::MEM_CONSTANT)
+    INLINE GenRegister getRelativeAddress(Selection::Opaque &sel, GenRegister address, uint8_t bti) const {
+      if(bti == 0xfe)
         return address;
 
       sel.push();
@@ -3318,7 +3321,7 @@ namespace gbe
 
       BTI bti = insn.getBTI();
       for (int x = 0; x < bti.count; x++) {
-        GenRegister temp = getRelativeAddress(sel, address, space, bti.bti[x]);
+        GenRegister temp = getRelativeAddress(sel, address, bti.bti[x]);
         if (insn.isAligned() == true && elemSize == GEN_BYTE_SCATTER_QWORD)
           this->emitWrite64(sel, insn, temp, bti.bti[x]);
         else if (insn.isAligned() == true && elemSize == GEN_BYTE_SCATTER_DWORD)
diff --git a/backend/src/llvm/llvm_gen_backend.cpp b/backend/src/llvm/llvm_gen_backend.cpp
index b6cb4c7..5bff92b 100644
--- a/backend/src/llvm/llvm_gen_backend.cpp
+++ b/backend/src/llvm/llvm_gen_backend.cpp
@@ -848,7 +848,7 @@ namespace gbe
       if(!v.isConstantUsed()) continue;
       const char *name = v.getName().data();
       unsigned addrSpace = v.getType()->getAddressSpace();
-      if(addrSpace == ir::AddressSpace::MEM_CONSTANT) {
+      if(addrSpace == ir::AddressSpace::MEM_CONSTANT || v.isConstant()) {
         GBE_ASSERT(v.hasInitializer());
         const Constant *c = v.getInitializer();
         Type * type = c->getType();
@@ -1924,7 +1924,7 @@ namespace gbe
         this->newRegister(const_cast<GlobalVariable*>(&v));
         ir::Register reg = regTranslator.getScalar(const_cast<GlobalVariable*>(&v), 0);
         ctx.LOADI(ir::TYPE_S32, reg, ctx.newIntegerImmediate(oldSlm + padding/8, ir::TYPE_S32));
-      } else if(addrSpace == ir::MEM_CONSTANT) {
+      } else if(addrSpace == ir::MEM_CONSTANT || v.isConstant()) {
         GBE_ASSERT(v.hasInitializer());
         this->newRegister(const_cast<GlobalVariable*>(&v));
         ir::Register reg = regTranslator.getScalar(const_cast<GlobalVariable*>(&v), 0);
@@ -1942,7 +1942,7 @@ namespace gbe
           ctx.getFunction().getPrintfSet()->setIndexBufBTI(btiBase);
           globalPointer.insert(std::make_pair(&v, incBtiBase()));
           regTranslator.newScalarProxy(ir::ocl::printfiptr, const_cast<GlobalVariable*>(&v));
-	} else if(v.getName().str().substr(0, 4) == ".str") {
+        } else if(v.getName().str().substr(0, 4) == ".str") {
           /* When there are multi printf statements in multi kernel fucntions within the same
              translate unit, if they have the same sting parameter, such as
              kernel_func1 () {
@@ -1955,7 +1955,7 @@ namespace gbe
              So when translating the kernel_func1, we can not unref that global var, so we will
              get here. Just ignore it to avoid assert. */
         } else {
-          GBE_ASSERT(0);
+          GBE_ASSERT(0 && "Unsupported private memory access pattern");
         }
       }
     }
@@ -3873,27 +3873,33 @@ handle_write_image:
       for (unsigned i = 0; i < origins.size(); i++) {
         uint8_t new_bti = 0;
         Value *origin = origins[i];
-        unsigned space = origin->getType()->getPointerAddressSpace();
-        switch (space) {
-          case 0:
-            new_bti = BTI_PRIVATE;
-            break;
-          case 1:
-          {
-            GlobalPtrIter iter = globalPointer.find(origin);
-            GBE_ASSERT(iter != globalPointer.end());
-            new_bti = iter->second;
-            break;
+        // all constant put into constant cache, including __constant & const __private
+        if (isa<GlobalVariable>(origin)
+            && dyn_cast<GlobalVariable>(origin)->isConstant()) {
+          new_bti = BTI_CONSTANT;
+        } else {
+          unsigned space = origin->getType()->getPointerAddressSpace();
+          switch (space) {
+            case 0:
+              new_bti = BTI_PRIVATE;
+              break;
+            case 1:
+            {
+              GlobalPtrIter iter = globalPointer.find(origin);
+              GBE_ASSERT(iter != globalPointer.end());
+              new_bti = iter->second;
+              break;
+            }
+            case 2:
+              new_bti = BTI_CONSTANT;
+              break;
+            case 3:
+              new_bti = 0xfe;
+              break;
+            default:
+              GBE_ASSERT(0 && "address space not unhandled in gatherBTI()\n");
+              break;
           }
-          case 2:
-            new_bti = BTI_CONSTANT;
-            break;
-          case 3:
-            new_bti = 0xfe;
-            break;
-          default:
-            GBE_ASSERT(0 && "address space not unhandled in gatherBTI()\n");
-            break;
         }
 
         // avoid duplicate
-- 
1.7.10.4



More information about the Beignet mailing list