[llvm] r197908 - Fix Scalarizer handling of vector GEPs with multiple index operands

Richard Sandiford rsandifo at linux.vnet.ibm.com
Mon Dec 23 06:45:00 PST 2013


Author: rsandifo
Date: Mon Dec 23 08:45:00 2013
New Revision: 197908

URL: http://llvm.org/viewvc/llvm-project?rev=197908&view=rev
Log:
Fix Scalarizer handling of vector GEPs with multiple index operands

The old code only worked for one index operand.  Also handle "inbounds".

Modified:
    llvm/trunk/lib/Transforms/Scalar/Scalarizer.cpp
    llvm/trunk/test/Transforms/Scalarizer/basic.ll

Modified: llvm/trunk/lib/Transforms/Scalar/Scalarizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/Scalarizer.cpp?rev=197908&r1=197907&r2=197908&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/Scalarizer.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/Scalarizer.cpp Mon Dec 23 08:45:00 2013
@@ -42,6 +42,8 @@ typedef SmallVector<std::pair<Instructio
 // component of a scattered vector or vector pointer.
 class Scatterer {
 public:
+  Scatterer() {}
+
   // Scatter V into Size components.  If new instructions are needed,
   // insert them before BBI in BB.  If Cache is nonnull, use it to cache
   // the results.
@@ -97,16 +99,6 @@ struct BinarySplitter {
   BinaryOperator &BO;
 };
 
-// GEPSpliiter()(Builder, X, Y, Name) uses Builder to create
-// a single GEP called Name with operands X and Y.
-struct GEPSplitter {
-  GEPSplitter() {}
-  Value *operator()(IRBuilder<> &Builder, Value *Op0, Value *Op1,
-                    const Twine &Name) const {
-    return Builder.CreateGEP(Op0, Op1, Name);
-  }
-};
-
 // Information about a load or store that we're scalarizing.
 struct VectorLayout {
   VectorLayout() : VecTy(0), ElemTy(0), VecAlign(0), ElemSize(0) {}
@@ -429,7 +421,36 @@ bool Scalarizer::visitBinaryOperator(Bin
 }
 
 bool Scalarizer::visitGetElementPtrInst(GetElementPtrInst &GEPI) {
-  return splitBinary(GEPI, GEPSplitter());
+  VectorType *VT = dyn_cast<VectorType>(GEPI.getType());
+  if (!VT)
+    return false;
+
+  IRBuilder<> Builder(GEPI.getParent(), &GEPI);
+  unsigned NumElems = VT->getNumElements();
+  unsigned NumIndices = GEPI.getNumIndices();
+
+  Scatterer Base = scatter(&GEPI, GEPI.getOperand(0));
+
+  SmallVector<Scatterer, 8> Ops;
+  Ops.resize(NumIndices);
+  for (unsigned I = 0; I < NumIndices; ++I)
+    Ops[I] = scatter(&GEPI, GEPI.getOperand(I + 1));
+
+  ValueVector Res;
+  Res.resize(NumElems);
+  for (unsigned I = 0; I < NumElems; ++I) {
+    SmallVector<Value *, 8> Indices;
+    Indices.resize(NumIndices);
+    for (unsigned J = 0; J < NumIndices; ++J)
+      Indices[J] = Ops[J][I];
+    Res[I] = Builder.CreateGEP(Base[I], Indices,
+                               GEPI.getName() + ".i" + Twine(I));
+    if (GEPI.isInBounds())
+      if (GetElementPtrInst *NewGEPI = dyn_cast<GetElementPtrInst>(Res[I]))
+        NewGEPI->setIsInBounds();
+  }
+  gather(&GEPI, Res);
+  return true;
 }
 
 bool Scalarizer::visitCastInst(CastInst &CI) {

Modified: llvm/trunk/test/Transforms/Scalarizer/basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Scalarizer/basic.ll?rev=197908&r1=197907&r2=197908&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/Scalarizer/basic.ll (original)
+++ llvm/trunk/test/Transforms/Scalarizer/basic.ll Mon Dec 23 08:45:00 2013
@@ -382,6 +382,38 @@ define void @f12(<4 x i32> *%dest, <4 x
   ret void
 }
 
+; Test vector GEPs with more than one index.
+define void @f13(<4 x float *> *%dest, <4 x [4 x float] *> %ptr, <4 x i32> %i,
+                 float *%other) {
+; CHECK-LABEL: @f13(
+; CHECK: %dest.i0 = bitcast <4 x float*>* %dest to float**
+; CHECK: %dest.i1 = getelementptr float** %dest.i0, i32 1
+; CHECK: %dest.i2 = getelementptr float** %dest.i0, i32 2
+; CHECK: %dest.i3 = getelementptr float** %dest.i0, i32 3
+; CHECK: %i.i0 = extractelement <4 x i32> %i, i32 0
+; CHECK: %ptr.i0 = extractelement <4 x [4 x float]*> %ptr, i32 0
+; CHECK: %val.i0 = getelementptr inbounds [4 x float]* %ptr.i0, i32 0, i32 %i.i0
+; CHECK: %i.i1 = extractelement <4 x i32> %i, i32 1
+; CHECK: %ptr.i1 = extractelement <4 x [4 x float]*> %ptr, i32 1
+; CHECK: %val.i1 = getelementptr inbounds [4 x float]* %ptr.i1, i32 1, i32 %i.i1
+; CHECK: %i.i2 = extractelement <4 x i32> %i, i32 2
+; CHECK: %ptr.i2 = extractelement <4 x [4 x float]*> %ptr, i32 2
+; CHECK: %val.i2 = getelementptr inbounds [4 x float]* %ptr.i2, i32 2, i32 %i.i2
+; CHECK: %i.i3 = extractelement <4 x i32> %i, i32 3
+; CHECK: %ptr.i3 = extractelement <4 x [4 x float]*> %ptr, i32 3
+; CHECK: %val.i3 = getelementptr inbounds [4 x float]* %ptr.i3, i32 3, i32 %i.i3
+; CHECK: store float* %val.i0, float** %dest.i0, align 32
+; CHECK: store float* %val.i1, float** %dest.i1, align 8
+; CHECK: store float* %val.i2, float** %dest.i2, align 16
+; CHECK: store float* %val.i3, float** %dest.i3, align 8
+; CHECK: ret void
+  %val = getelementptr inbounds <4 x [4 x float] *> %ptr,
+                                <4 x i32> <i32 0, i32 1, i32 2, i32 3>,
+                                <4 x i32> %i
+  store <4 x float *> %val, <4 x float *> *%dest
+  ret void
+}
+
 !0 = metadata !{ metadata !"root" }
 !1 = metadata !{ metadata !"set1", metadata !0 }
 !2 = metadata !{ metadata !"set2", metadata !0 }





More information about the llvm-commits mailing list