diff --git a/docs/LangRef.html b/docs/LangRef.html index ed47f1f00ed..cdb76848e2d 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -5419,9 +5419,11 @@ specified by the operation argument:

The type of each index argument depends on the type it is indexing into. When indexing into a (optionally packed) structure, only i32 - integer constants are allowed. When indexing into an array, pointer - or vector, integers of any width are allowed, and they are not required to be - constant. These integers are treated as signed values where relevant.

+ integer constants are allowed (when using a vector of indices they + must all be the same i32 integer constant). When indexing + into an array, pointer or vector, integers of any width are allowed, and + they are not required to be constant. These integers are treated as signed + values where relevant.

For example, let's consider a C code fragment and how it gets compiled to LLVM:

@@ -5520,9 +5522,8 @@ define i32* @foo(%struct.ST* %s) { %iptr = getelementptr [10 x i32]* @arr, i16 0, i16 0 -

In cases where the pointer argument is a vector of pointers, only a - single index may be used, and the number of vector elements has to be - the same. For example:

+

In cases where the pointer argument is a vector of pointers, each index must + be a vector with the same number of elements. For example:

  %A = getelementptr <4 x i8*> %ptrs, <4 x i64> %offsets,
 
diff --git a/include/llvm/Constant.h b/include/llvm/Constant.h index 7fecf4c7b45..bbd1b1a6e2c 100644 --- a/include/llvm/Constant.h +++ b/include/llvm/Constant.h @@ -97,7 +97,15 @@ public: /// 'this' is a constant expr. Constant *getAggregateElement(unsigned Elt) const; Constant *getAggregateElement(Constant *Elt) const; - + + /// getSplatValue - If this is a splat vector constant, meaning that all of + /// the elements have the same value, return that value. Otherwise return 0. + Constant *getSplatValue() const; + + /// If C is a constant integer then return its value, otherwise C must be a + /// vector of constant integers, all equal, and the common value is returned. + const APInt &getUniqueInteger() const; + /// destroyConstant - Called if some element of this constant is no longer /// valid. At this point only other constants may be on the use_list for this /// constant. Any constants on our Use list must also be destroy'd. The diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index ac803c57833..de404728be6 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -1697,8 +1697,7 @@ bool LLParser::ParseArrayVectorType(Type *&Result, bool isVector) { if ((unsigned)Size != Size) return Error(SizeLoc, "size too large for vector"); if (!VectorType::isValidElementType(EltTy)) - return Error(TypeLoc, - "vector element type must be fp, integer or a pointer to these types"); + return Error(TypeLoc, "invalid vector element type"); Result = VectorType::get(EltTy, unsigned(Size)); } else { if (!ArrayType::isValidElementType(EltTy)) @@ -4032,9 +4031,6 @@ int LLParser::ParseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS) { Indices.push_back(Val); } - if (Val && Val->getType()->isVectorTy() && Indices.size() != 1) - return Error(EltLoc, "vector getelementptrs must have a single index"); - if (!GetElementPtrInst::getIndexedType(Ptr->getType(), Indices)) return Error(Loc, "invalid getelementptr indices"); Inst = GetElementPtrInst::Create(Ptr, Indices); diff --git a/lib/Bitcode/Writer/ValueEnumerator.cpp b/lib/Bitcode/Writer/ValueEnumerator.cpp index 1ed9004eb5a..cf3839d4b0a 100644 --- a/lib/Bitcode/Writer/ValueEnumerator.cpp +++ b/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -24,8 +24,8 @@ #include using namespace llvm; -static bool isIntegerValue(const std::pair &V) { - return V.first->getType()->isIntegerTy(); +static bool isIntOrIntVectorValue(const std::pair &V) { + return V.first->getType()->isIntOrIntVectorTy(); } /// ValueEnumerator - Enumerate module-level information. @@ -192,10 +192,11 @@ void ValueEnumerator::OptimizeConstants(unsigned CstStart, unsigned CstEnd) { CstSortPredicate P(*this); std::stable_sort(Values.begin()+CstStart, Values.begin()+CstEnd, P); - // Ensure that integer constants are at the start of the constant pool. This - // is important so that GEP structure indices come before gep constant exprs. + // Ensure that integer and vector of integer constants are at the start of the + // constant pool. This is important so that GEP structure indices come before + // gep constant exprs. std::partition(Values.begin()+CstStart, Values.begin()+CstEnd, - isIntegerValue); + isIntOrIntVectorValue); // Rebuild the modified portion of ValueMap. for (; CstStart != CstEnd; ++CstStart) diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index a4e21e16b3f..f96fb1d4019 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -1213,6 +1213,19 @@ void ConstantVector::destroyConstant() { destroyConstantImpl(); } +/// getSplatValue - If this is a splat vector constant, meaning that all of +/// the elements have the same value, return that value. Otherwise return 0. +Constant *Constant::getSplatValue() const { + assert(this->getType()->isVectorTy() && "Only valid for vectors!"); + if (isa(this)) + return getNullValue(this->getType()->getVectorElementType()); + if (const ConstantDataVector *CV = dyn_cast(this)) + return CV->getSplatValue(); + if (const ConstantVector *CV = dyn_cast(this)) + return CV->getSplatValue(); + return 0; +} + /// getSplatValue - If this is a splat constant, where all of the /// elements have the same value, return that value. Otherwise return null. Constant *ConstantVector::getSplatValue() const { @@ -1225,6 +1238,18 @@ Constant *ConstantVector::getSplatValue() const { return Elt; } +/// If C is a constant integer then return its value, otherwise C must be a +/// vector of constant integers, all equal, and the common value is returned. +const APInt &Constant::getUniqueInteger() const { + if (const ConstantInt *CI = dyn_cast(this)) + return CI->getValue(); + assert(this->getSplatValue() && "Doesn't contain a unique integer!"); + const Constant *C = this->getAggregateElement(0U); + assert(C && isa(C) && "Not a vector of numbers!"); + return cast(C)->getValue(); +} + + //---- ConstantPointerNull::get() implementation. // @@ -1739,6 +1764,9 @@ Constant *ConstantExpr::getSelect(Constant *C, Constant *V1, Constant *V2) { Constant *ConstantExpr::getGetElementPtr(Constant *C, ArrayRef Idxs, bool InBounds) { + assert(C->getType()->isPtrOrPtrVectorTy() && + "Non-pointer type for constant GetElementPtr expression"); + if (Constant *FC = ConstantFoldGetElementPtr(C, InBounds, Idxs)) return FC; // Fold a few common cases. @@ -1747,15 +1775,22 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C, ArrayRef Idxs, assert(Ty && "GEP indices invalid!"); unsigned AS = C->getType()->getPointerAddressSpace(); Type *ReqTy = Ty->getPointerTo(AS); + if (VectorType *VecTy = dyn_cast(C->getType())) + ReqTy = VectorType::get(ReqTy, VecTy->getNumElements()); - assert(C->getType()->isPointerTy() && - "Non-pointer type for constant GetElementPtr expression"); // Look up the constant in the table first to ensure uniqueness std::vector ArgVec; ArgVec.reserve(1 + Idxs.size()); ArgVec.push_back(C); - for (unsigned i = 0, e = Idxs.size(); i != e; ++i) + for (unsigned i = 0, e = Idxs.size(); i != e; ++i) { + assert(Idxs[i]->getType()->isVectorTy() == ReqTy->isVectorTy() && + "getelementptr index type missmatch"); + assert((!Idxs[i]->getType()->isVectorTy() || + ReqTy->getVectorNumElements() == + Idxs[i]->getType()->getVectorNumElements()) && + "getelementptr index type missmatch"); ArgVec.push_back(cast(Idxs[i])); + } const ExprMapKeyType Key(Instruction::GetElementPtr, ArgVec, 0, InBounds ? GEPOperator::IsInBounds : 0); diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index 94bd2a15632..ca7cd4eb978 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -1353,16 +1353,7 @@ GetElementPtrInst::GetElementPtrInst(const GetElementPtrInst &GEPI) /// template static Type *getIndexedTypeInternal(Type *Ptr, ArrayRef IdxList) { - if (Ptr->isVectorTy()) { - assert(IdxList.size() == 1 && - "GEP with vector pointers must have a single index"); - PointerType *PTy = dyn_cast( - cast(Ptr)->getElementType()); - assert(PTy && "Gep with invalid vector pointer found"); - return PTy->getElementType(); - } - - PointerType *PTy = dyn_cast(Ptr); + PointerType *PTy = dyn_cast(Ptr->getScalarType()); if (!PTy) return 0; // Type isn't a pointer type! Type *Agg = PTy->getElementType(); diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp index 1656ab2cab3..4d75a7e060f 100644 --- a/lib/VMCore/Type.cpp +++ b/lib/VMCore/Type.cpp @@ -629,11 +629,12 @@ StructType *Module::getTypeByName(StringRef Name) const { Type *CompositeType::getTypeAtIndex(const Value *V) { if (StructType *STy = dyn_cast(this)) { - unsigned Idx = (unsigned)cast(V)->getZExtValue(); + unsigned Idx = + (unsigned)cast(V)->getUniqueInteger().getZExtValue(); assert(indexValid(Idx) && "Invalid structure index!"); return STy->getElementType(Idx); } - + return cast(this)->getElementType(); } Type *CompositeType::getTypeAtIndex(unsigned Idx) { @@ -646,15 +647,19 @@ Type *CompositeType::getTypeAtIndex(unsigned Idx) { } bool CompositeType::indexValid(const Value *V) const { if (const StructType *STy = dyn_cast(this)) { - // Structure indexes require 32-bit integer constants. - if (V->getType()->isIntegerTy(32)) - if (const ConstantInt *CU = dyn_cast(V)) - return CU->getZExtValue() < STy->getNumElements(); - return false; + // Structure indexes require (vectors of) 32-bit integer constants. In the + // vector case all of the indices must be equal. + if (!V->getType()->getScalarType()->isIntegerTy(32)) + return false; + const Constant *C = dyn_cast(V); + if (C && V->getType()->isVectorTy()) + C = C->getSplatValue(); + const ConstantInt *CU = dyn_cast_or_null(C); + return CU && CU->getZExtValue() < STy->getNumElements(); } - + // Sequential types can be indexed by any integer. - return V->getType()->isIntegerTy(); + return V->getType()->isIntOrIntVectorTy(); } bool CompositeType::indexValid(unsigned Idx) const { @@ -717,9 +722,8 @@ VectorType *VectorType::get(Type *elementType, unsigned NumElements) { } bool VectorType::isValidElementType(Type *ElemTy) { - if (PointerType *PTy = dyn_cast(ElemTy)) - ElemTy = PTy->getElementType(); - return ElemTy->isIntegerTy() || ElemTy->isFloatingPointTy(); + return ElemTy->isIntegerTy() || ElemTy->isFloatingPointTy() || + ElemTy->isPointerTy(); } //===----------------------------------------------------------------------===// diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index eb40b09d29f..3782957f3b3 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -1375,34 +1375,31 @@ void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) { "GEP base pointer is not a vector or a vector of pointers", &GEP); Assert1(cast(TargetTy)->getElementType()->isSized(), "GEP into unsized type!", &GEP); + Assert1(GEP.getPointerOperandType()->isVectorTy() == + GEP.getType()->isVectorTy(), "Vector GEP must return a vector value", + &GEP); SmallVector Idxs(GEP.idx_begin(), GEP.idx_end()); Type *ElTy = GetElementPtrInst::getIndexedType(GEP.getPointerOperandType(), Idxs); Assert1(ElTy, "Invalid indices for GEP pointer type!", &GEP); - if (GEP.getPointerOperandType()->isPointerTy()) { - // Validate GEPs with scalar indices. - Assert2(GEP.getType()->isPointerTy() && - cast(GEP.getType())->getElementType() == ElTy, - "GEP is not of right type for indices!", &GEP, ElTy); - } else { - // Validate GEPs with a vector index. - Assert1(Idxs.size() == 1, "Invalid number of indices!", &GEP); - Value *Index = Idxs[0]; - Type *IndexTy = Index->getType(); - Assert1(IndexTy->isVectorTy(), - "Vector GEP must have vector indices!", &GEP); - Assert1(GEP.getType()->isVectorTy(), - "Vector GEP must return a vector value", &GEP); - Type *ElemPtr = cast(GEP.getType())->getElementType(); - Assert1(ElemPtr->isPointerTy(), - "Vector GEP pointer operand is not a pointer!", &GEP); - unsigned IndexWidth = cast(IndexTy)->getNumElements(); - unsigned GepWidth = cast(GEP.getType())->getNumElements(); - Assert1(IndexWidth == GepWidth, "Invalid GEP index vector width", &GEP); - Assert1(ElTy == cast(ElemPtr)->getElementType(), - "Vector GEP type does not match pointer type!", &GEP); + Assert2(GEP.getType()->getScalarType()->isPointerTy() && + cast(GEP.getType()->getScalarType())->getElementType() + == ElTy, "GEP is not of right type for indices!", &GEP, ElTy); + + if (GEP.getPointerOperandType()->isVectorTy()) { + // Additional checks for vector GEPs. + unsigned GepWidth = GEP.getPointerOperandType()->getVectorNumElements(); + Assert1(GepWidth == GEP.getType()->getVectorNumElements(), + "Vector GEP result width doesn't match operand's", &GEP); + for (unsigned i = 0, e = Idxs.size(); i != e; ++i) { + Type *IndexTy = Idxs[i]->getType(); + Assert1(IndexTy->isVectorTy(), + "Vector GEP must have vector indices!", &GEP); + unsigned IndexWidth = IndexTy->getVectorNumElements(); + Assert1(IndexWidth == GepWidth, "Invalid GEP index vector width", &GEP); + } } visitInstruction(GEP); } diff --git a/test/Assembler/getelementptr.ll b/test/Assembler/getelementptr.ll index ce6866d5441..af03fca6d2c 100644 --- a/test/Assembler/getelementptr.ll +++ b/test/Assembler/getelementptr.ll @@ -7,12 +7,12 @@ @C = global i32* getelementptr ([2 x [3 x [5 x [7 x i32]]]]* @A, i64 3, i64 2, i64 0, i64 0, i64 7523) ; CHECK: @C = global i32* getelementptr ([2 x [3 x [5 x [7 x i32]]]]* @A, i64 39, i64 1, i64 1, i64 4, i64 5) -;; Verify that i16 indices work. +; Verify that i16 indices work. @x = external global {i32, i32} @y = global i32* getelementptr ({ i32, i32 }* @x, i16 42, i32 0) ; CHECK: @y = global i32* getelementptr ({ i32, i32 }* @x, i16 42, i32 0) -; see if i92 indices work too. +; See if i92 indices work too. define i32 *@test({i32, i32}* %t, i92 %n) { ; CHECK: @test ; CHECK: %B = getelementptr { i32, i32 }* %t, i92 %n, i32 0 @@ -20,3 +20,18 @@ define i32 *@test({i32, i32}* %t, i92 %n) { ret i32* %B } +; Verify that constant expression vector GEPs work. + +@z = global <2 x i32*> getelementptr (<2 x [3 x {i32, i32}]*> zeroinitializer, <2 x i32> , <2 x i32> , <2 x i32> ) + +; Verify that struct GEP works with a vector of pointers. +define <2 x i32*> @test7(<2 x {i32, i32}*> %a) { + %w = getelementptr <2 x {i32, i32}*> %a, <2 x i32> , <2 x i32> zeroinitializer + ret <2 x i32*> %w +} + +; Verify that array GEP works with a vector of pointers. +define <2 x i8*> @test8(<2 x [2 x i8]*> %a) { + %w = getelementptr <2 x [2 x i8]*> %a, <2 x i32> , <2 x i8> + ret <2 x i8*> %w +} diff --git a/test/Assembler/getelementptr_vec_idx1.ll b/test/Assembler/getelementptr_vec_idx1.ll new file mode 100644 index 00000000000..d2479f44048 --- /dev/null +++ b/test/Assembler/getelementptr_vec_idx1.ll @@ -0,0 +1,10 @@ +; RUN: not llvm-as < %s >/dev/null 2> %t +; RUN: FileCheck %s < %t +; Test that a vector index is only used with a vector pointer. + +; CHECK: getelementptr index type missmatch + +define i32 @test(i32* %a) { + %w = getelementptr i32* %a, <2 x i32> + ret i32 %w +} diff --git a/test/Assembler/getelementptr_vec_idx2.ll b/test/Assembler/getelementptr_vec_idx2.ll new file mode 100644 index 00000000000..8b71ce3095b --- /dev/null +++ b/test/Assembler/getelementptr_vec_idx2.ll @@ -0,0 +1,10 @@ +; RUN: not llvm-as < %s >/dev/null 2> %t +; RUN: FileCheck %s < %t +; Test that a vector pointer is only used with a vector index. + +; CHECK: getelementptr index type missmatch + +define <2 x i32> @test(<2 x i32*> %a) { + %w = getelementptr <2 x i32*> %a, i32 2 + ret <2 x i32> %w +} diff --git a/test/Assembler/getelementptr_vec_idx3.ll b/test/Assembler/getelementptr_vec_idx3.ll new file mode 100644 index 00000000000..1f6c29b3ccc --- /dev/null +++ b/test/Assembler/getelementptr_vec_idx3.ll @@ -0,0 +1,10 @@ +; RUN: not llvm-as < %s >/dev/null 2> %t +; RUN: FileCheck %s < %t +; Test that vector indices have the same number of elements as the pointer. + +; CHECK: getelementptr index type missmatch + +define <4 x i32> @test(<4 x i32>* %a) { + %w = getelementptr <4 x i32>* %a, <2 x i32> + ret i32 %w +} diff --git a/test/Assembler/getelementptr_vec_struct.ll b/test/Assembler/getelementptr_vec_struct.ll new file mode 100644 index 00000000000..ec66836bac1 --- /dev/null +++ b/test/Assembler/getelementptr_vec_struct.ll @@ -0,0 +1,10 @@ +; RUN: not llvm-as < %s >/dev/null 2> %t +; RUN: FileCheck %s < %t +; Test that a vector struct index with non-equal elements is rejected. + +; CHECK: invalid getelementptr indices + +define <2 x i32*> @test7(<2 x {i32, i32}*> %a) { + %w = getelementptr <2 x {i32, i32}*> %a, <2 x i32> , <2 x i32> + ret <2 x i32*> %w +} diff --git a/test/Transforms/LoopVectorize/gcc-examples.ll b/test/Transforms/LoopVectorize/gcc-examples.ll index fce29d24048..2243a77d3bc 100644 --- a/test/Transforms/LoopVectorize/gcc-examples.ll +++ b/test/Transforms/LoopVectorize/gcc-examples.ll @@ -391,9 +391,9 @@ define void @example13(i32** nocapture %A, i32** nocapture %B, i32* nocapture %o ret void } -; Can't vectorize because of reductions. +; Can vectorize. ;CHECK: @example14 -;CHECK-NOT: <4 x i32> +;CHECK: <4 x i32> ;CHECK: ret void define void @example14(i32** nocapture %in, i32** nocapture %coeff, i32* nocapture %out) nounwind uwtable ssp { .preheader3: