[Beignet] [PATCH] GBE: unify element type before insertelement in legalize pass.

Ruiling Song ruiling.song at intel.com
Wed Feb 25 18:33:37 PST 2015


large integer type like i96 may be expanded to be low 64bit and high 32bit.
When it is cast to <i32 x 3>, we should first make the expanded type to be
of same type, here i32. insertelement could not insert element of different type.
Then we can do insertelement one by one to generate the <i32 x 3> vector.

This could fix the bug:
https://bugs.freedesktop.org/show_bug.cgi?id=89167

Signed-off-by: Ruiling Song <ruiling.song at intel.com>
---
 backend/src/llvm/ExpandLargeIntegers.cpp |   45 +++++++++++++++++++++++++++---
 1 file changed, 41 insertions(+), 4 deletions(-)

diff --git a/backend/src/llvm/ExpandLargeIntegers.cpp b/backend/src/llvm/ExpandLargeIntegers.cpp
index 194622c..912fda2 100644
--- a/backend/src/llvm/ExpandLargeIntegers.cpp
+++ b/backend/src/llvm/ExpandLargeIntegers.cpp
@@ -347,7 +347,7 @@ static Value *buildVectorOrScalar(ConversionState &State, IRBuilder<> &IRB, Smal
   }
 }
 
-void getSplitedValue(ConversionState &State, Value *Val, SmallVector<Value *, 16> &Result) {
+static void getSplitedValue(ConversionState &State, Value *Val, SmallVector<Value *, 16> &Result) {
   while (shouldConvert(Val)) {
     ValuePair Convert = State.getConverted(Val);
     Result.push_back(Convert.Lo);
@@ -356,6 +356,40 @@ void getSplitedValue(ConversionState &State, Value *Val, SmallVector<Value *, 16
   Result.push_back(Val);
 }
 
+// make all the elements in Src use the same llvm::Type, and return them in Dst
+static void unifyElementType(IRBuilder<> &IRB, SmallVector<Value *, 16> &Src, SmallVector<Value *, 16> &Dst) {
+  unsigned MinWidth = Src[0]->getType()->getPrimitiveSizeInBits();
+  bool Unified = true;
+  for (unsigned i = 0; i < Src.size(); i++) {
+    Type *Ty = Src[i]->getType();
+    unsigned BitWidth = Ty->getPrimitiveSizeInBits();
+    if(BitWidth != MinWidth) Unified = false;
+    if(BitWidth < MinWidth) MinWidth = BitWidth;
+  }
+
+  if (Unified) {
+    for (unsigned i = 0; i < Src.size(); i++)
+      Dst.push_back(Src[i]);
+  } else {
+    Type *IntTy = IntegerType::get(IRB.getContext(), 32);
+    Type *ElemTy = IntegerType::get(IRB.getContext(), MinWidth);
+    for (unsigned i = 0; i < Src.size(); i++) {
+      Type *Ty = Src[i]->getType();
+      unsigned Size = Ty->getPrimitiveSizeInBits();
+      assert((Size % MinWidth) == 0);
+
+      if (Size > MinWidth) {
+        VectorType *VecTy = VectorType::get(ElemTy, Size/MinWidth);
+        Value *Casted = IRB.CreateBitCast(Src[i], VecTy);
+        for (unsigned j = 0; j < Size/MinWidth; j++)
+          Dst.push_back(IRB.CreateExtractElement(Casted, ConstantInt::get(IntTy, j)));
+      } else {
+        Dst.push_back(Src[i]);
+      }
+    }
+  }
+}
+
 static void convertInstruction(Instruction *Inst, ConversionState &State,
                                const DataLayout &DL) {
   DEBUG(dbgs() << "Expanding Large Integer: " << *Inst << "\n");
@@ -422,15 +456,18 @@ static void convertInstruction(Instruction *Inst, ConversionState &State,
     if (DstVec) {
       // integer to vector, get all children and bitcast
       SmallVector<Value *, 16> Split;
+      SmallVector<Value *, 16> Unified;
       getSplitedValue(State, Operand, Split);
+      // unify element type, this is required by insertelement
+      unifyElementType(IRB, Split, Unified);
 
       Value *vec = NULL;
-      unsigned ElemNo = Split.size();
-      Type *ElemTy = Split[0]->getType();
+      unsigned ElemNo = Unified.size();
+      Type *ElemTy = Unified[0]->getType();
       for (unsigned i = 0; i < ElemNo; ++i) {
         Value *tmp = vec ? vec : UndefValue::get(VectorType::get(ElemTy, ElemNo));
         Value *idx = ConstantInt::get(IntTy, i);
-        vec = IRB.CreateInsertElement(tmp, Split[i], idx);
+        vec = IRB.CreateInsertElement(tmp, Unified[i], idx);
       }
       if (vec->getType() != Cast->getType())
         vec = IRB.CreateBitCast(vec, Cast->getType());
-- 
1.7.10.4



More information about the Beignet mailing list