[Beignet] [PATCH 1/2] GBE: Support composite type constant.

Ruiling Song ruiling.song at intel.com
Tue Sep 17 19:18:42 PDT 2013


struct/vector/array of vector/struct of array/array of struct.

Also fix a bug 'constant index into constant array get wrong result'
brought in by patch 'Fix non-4byte program global constant issue'.

Signed-off-by: Ruiling Song <ruiling.song at intel.com>
---
 backend/src/llvm/llvm_gen_backend.cpp |  201 +++++++++++++++++++++------------
 1 file changed, 130 insertions(+), 71 deletions(-)

diff --git a/backend/src/llvm/llvm_gen_backend.cpp b/backend/src/llvm/llvm_gen_backend.cpp
index f357977..859107f 100644
--- a/backend/src/llvm/llvm_gen_backend.cpp
+++ b/backend/src/llvm/llvm_gen_backend.cpp
@@ -460,7 +460,8 @@ namespace gbe
     }
 
     virtual bool doInitialization(Module &M);
-
+    /*! helper function for parsing global constant data */
+    void getConstantData(const Constant * c, void* mem, uint32_t& offset) const;
     void collectGlobalConstant(void) const;
 
     bool runOnFunction(Function &F) {
@@ -559,6 +560,99 @@ namespace gbe
   };
 
   char GenWriter::ID = 0;
+  void getSequentialData(const ConstantDataSequential *cda, void *ptr, uint32_t &offset) {
+    StringRef data = cda->getRawDataValues();
+    memcpy((char*)ptr+offset, data.data(), data.size());
+    offset += data.size();
+    return;
+  }
+
+  void GenWriter::getConstantData(const Constant * c, void* mem, uint32_t& offset) const {
+    Type * type = c->getType();
+    Type::TypeID id = type->getTypeID();
+
+    GBE_ASSERT(c);
+    if(isa<UndefValue>(c)) {
+      uint32_t n = c->getNumOperands();
+      Type * opTy = type->getArrayElementType();
+      uint32_t size = opTy->getIntegerBitWidth()/ 8;
+      offset += size*n;
+      return;
+    }
+    switch(id) {
+      case Type::TypeID::StructTyID:
+        {
+          const StructType * strTy = cast<StructType>(c->getType());
+          uint32_t size = 0;
+
+          for(uint32_t op=0; op < strTy->getNumElements(); op++)
+          {
+            Type* elementType = strTy->getElementType(op);
+            uint32_t align = 8 * getAlignmentByte(unit, elementType);
+            uint32_t padding = getPadding(size, align);
+            size += padding;
+            size += getTypeBitSize(unit, elementType);
+
+            offset += padding/8;
+            const Constant* sub = cast<Constant>(c->getOperand(op));
+            GBE_ASSERT(sub);
+            getConstantData(sub, mem, offset);
+          }
+          break;
+        }
+      case Type::TypeID::ArrayTyID:
+        {
+          const ConstantDataSequential *cds = dyn_cast<ConstantDataSequential>(c);
+          if(cds)
+            getSequentialData(cds, mem, offset);
+          else {
+            const ConstantArray *ca = dyn_cast<ConstantArray>(c);
+            const ArrayType *arrTy = ca->getType();
+            Type* elemTy = arrTy->getElementType();
+            uint32_t elemSize = getTypeBitSize(unit, elemTy);
+            uint32_t padding = getPadding(elemSize, 8 * getAlignmentByte(unit, elemTy));
+            padding /= 8;
+            uint32_t ops = c->getNumOperands();
+            for(uint32_t op = 0; op < ops; ++op) {
+              Constant * ca = dyn_cast<Constant>(c->getOperand(op));
+              getConstantData(ca, mem, offset);
+              offset += padding;
+            }
+          }
+          break;
+        }
+      case Type::TypeID::VectorTyID:
+        {
+          const ConstantDataSequential *cds = dyn_cast<ConstantDataSequential>(c);
+          GBE_ASSERT(cds);
+          getSequentialData(cds, mem, offset);
+          break;
+        }
+      case Type::TypeID::IntegerTyID:
+        {
+          const ConstantInt *ci = dyn_cast<ConstantInt>(c);
+          *(uint64_t *)((char*)mem + offset) = ci->isNegative() ? ci->getSExtValue() : ci->getZExtValue();
+          offset += ci->getBitWidth() / 8;
+          break;
+        }
+      case Type::TypeID::FloatTyID:
+        {
+          const ConstantFP *cf = dyn_cast<ConstantFP>(c);
+          *(float *)((char*)mem + offset) = cf->getValueAPF().convertToFloat();
+          offset += sizeof(float);
+          break;
+        }
+      case Type::TypeID::DoubleTyID:
+        {
+          const ConstantFP *cf = dyn_cast<ConstantFP>(c);
+          *(double *)((char*)mem + offset) = cf->getValueAPF().convertToDouble();
+          offset += sizeof(double);
+          break;
+        }
+      default:
+        NOT_IMPLEMENTED;
+    }
+  }
 
   void GenWriter::collectGlobalConstant(void) const {
     const Module::GlobalListType &globalList = TheModule->getGlobalList();
@@ -569,68 +663,13 @@ namespace gbe
       if(addrSpace == ir::AddressSpace::MEM_CONSTANT) {
         GBE_ASSERT(v.hasInitializer());
         const Constant *c = v.getInitializer();
-        if (c->getType()->getTypeID() != Type::ArrayTyID) {
-          void *mem = malloc(sizeof(double));
-          int size = 0;
-          switch(c->getType()->getTypeID()) {
-            case Type::TypeID::IntegerTyID: {
-              const ConstantInt *ci = dyn_cast<ConstantInt>(c);
-              *(uint64_t *)mem = ci->isNegative() ? ci->getSExtValue() : ci->getZExtValue();
-              size = ci->getBitWidth() / 8;
-              break;
-            }
-            case Type::TypeID::FloatTyID: {
-              const ConstantFP *cf = dyn_cast<ConstantFP>(c);
-              *(float *)mem = cf->getValueAPF().convertToFloat();
-              size = sizeof(float);
-              break;
-            }
-            case Type::TypeID::DoubleTyID: {
-              const ConstantFP *cf = dyn_cast<ConstantFP>(c);
-              *(double *)mem = cf->getValueAPF().convertToDouble();
-              size = sizeof(double);
-              break;
-            }
-            default:
-              NOT_IMPLEMENTED;
-          }
-          unit.newConstant((char *)mem, name, size, size);
-          free(mem);
-          continue;
-        }
-        GBE_ASSERT(c->getType()->getTypeID() == Type::ArrayTyID);
-        const ConstantDataArray *cda = dyn_cast<ConstantDataArray>(c);
-        GBE_ASSERT(cda);
-        unsigned len = cda->getNumElements();
-        uint64_t elementSize = cda->getElementByteSize();
-        Type::TypeID typeID = cda->getElementType()->getTypeID();
-        void *mem = malloc(elementSize * len);
-        for(unsigned j = 0; j < len; j ++) {
-          switch(typeID) {
-            case Type::TypeID::FloatTyID:
-             {
-              float f = cda->getElementAsFloat(j);
-              memcpy((float *)mem + j, &f, elementSize);
-             }
-              break;
-            case Type::TypeID::DoubleTyID:
-             {
-              double d = cda->getElementAsDouble(j);
-              memcpy((double *)mem + j, &d, elementSize);
-             }
-              break;
-            case Type::TypeID::IntegerTyID:
-             {
-              uint64_t u = (uint64_t) cda->getElementAsInteger(j);
-              memcpy((char *)mem + j*elementSize, &u, elementSize);
-             }
-              break;
-            default:
-              NOT_IMPLEMENTED;
-          }
-        }
+        Type * type = c->getType();
 
-        unit.newConstant((char *)mem, name, elementSize * len, sizeof(unsigned));
+        uint32_t size = getTypeByteSize(unit, type);
+        void* mem = malloc(size);
+        uint32_t offset = 0;
+        getConstantData(c, mem, offset);
+        unit.newConstant((char *)mem, name, size, sizeof(unsigned));
         free(mem);
       }
     }
@@ -818,18 +857,38 @@ namespace gbe
         return ir::Register(reg);
       }
       if (isa<ConstantExpr>(CPV)) {
+        uint32_t TypeIndex;
+        uint32_t constantOffset = 0;
+        uint32_t offset = 0;
         ConstantExpr *CE = dyn_cast<ConstantExpr>(CPV);
-        GBE_ASSERT(CE->isGEPWithNoNotionalOverIndexing());
-        auto pointer = CE->getOperand(0);
-        auto offset1 = dyn_cast<ConstantInt>(CE->getOperand(1));
-        GBE_ASSERT(offset1->getZExtValue() == 0);
-        auto offset2 = dyn_cast<ConstantInt>(CE->getOperand(2));
-        int type_size = pointer->getType()->getPrimitiveSizeInBits() / 8;
-        int type_offset = offset2->getSExtValue() * type_size;
-        auto pointer_name = pointer->getName().str();
+
+        // currently only GetElementPtr is handled
+        GBE_ASSERT(CE->getOpcode() == Instruction::GetElementPtr);
+        Value *pointer = CE->getOperand(0);
+        CompositeType* CompTy = cast<CompositeType>(pointer->getType());
+        for(uint32_t op=1; op<CE->getNumOperands(); ++op) {
+          ConstantInt* ConstOP = dyn_cast<ConstantInt>(CE->getOperand(op));
+          GBE_ASSERT(ConstOP);
+          TypeIndex = ConstOP->getZExtValue();
+          for(uint32_t ty_i=0; ty_i<TypeIndex; ty_i++)
+          {
+            Type* elementType = CompTy->getTypeAtIndex(ty_i);
+            uint32_t align = getAlignmentByte(unit, elementType);
+            offset += getPadding(offset, align);
+            offset += getTypeByteSize(unit, elementType);
+          }
+
+          const uint32_t align = getAlignmentByte(unit, CompTy->getTypeAtIndex(TypeIndex));
+          offset += getPadding(offset, align);
+
+          constantOffset += offset;
+          CompTy = dyn_cast<CompositeType>(CompTy->getTypeAtIndex(TypeIndex));
+        }
+
+        const std::string &pointer_name = pointer->getName().str();
         ir::Register pointer_reg = ir::Register(unit.getConstantSet().getConstant(pointer_name).getReg());
         ir::Register offset_reg = ctx.reg(ir::RegisterFamily::FAMILY_DWORD);
-        ctx.LOADI(ir::Type::TYPE_S32, offset_reg, ctx.newIntegerImmediate(type_offset, ir::Type::TYPE_S32));
+        ctx.LOADI(ir::Type::TYPE_S32, offset_reg, ctx.newIntegerImmediate(constantOffset, ir::Type::TYPE_S32));
         ir::Register reg = ctx.reg(ir::RegisterFamily::FAMILY_DWORD);
         ctx.ADD(ir::Type::TYPE_S32, reg, pointer_reg, offset_reg);
         return reg;
-- 
1.7.9.5



More information about the Beignet mailing list