summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/LangRef.html13
-rw-r--r--include/llvm/Constant.h10
-rw-r--r--lib/AsmParser/LLParser.cpp6
-rw-r--r--lib/Bitcode/Writer/ValueEnumerator.cpp11
-rw-r--r--lib/VMCore/Constants.cpp41
-rw-r--r--lib/VMCore/Instructions.cpp11
-rw-r--r--lib/VMCore/Type.cpp28
-rw-r--r--lib/VMCore/Verifier.cpp41
-rw-r--r--test/Assembler/getelementptr.ll19
-rw-r--r--test/Assembler/getelementptr_vec_idx1.ll10
-rw-r--r--test/Assembler/getelementptr_vec_idx2.ll10
-rw-r--r--test/Assembler/getelementptr_vec_idx3.ll10
-rw-r--r--test/Assembler/getelementptr_vec_struct.ll10
-rw-r--r--test/Transforms/LoopVectorize/gcc-examples.ll4
14 files changed, 156 insertions, 68 deletions
diff --git a/docs/LangRef.html b/docs/LangRef.html
index ed47f1f00e..cdb76848e2 100644
--- a/docs/LangRef.html
+++ b/docs/LangRef.html
@@ -5419,9 +5419,11 @@ specified by the <var>operation</var> argument:</p>
<p>The type of each index argument depends on the type it is indexing into.
When indexing into a (optionally packed) structure, only <tt>i32</tt>
- integer <b>constants</b> 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.</p>
+ integer <b>constants</b> are allowed (when using a vector of indices they
+ must all be the <b>same</b> <tt>i32</tt> 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.</p>
<p>For example, let's consider a C code fragment and how it gets compiled to
LLVM:</p>
@@ -5520,9 +5522,8 @@ define i32* @foo(%struct.ST* %s) {
%iptr = getelementptr [10 x i32]* @arr, i16 0, i16 0
</pre>
-<p>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: </p>
+<p>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: </p>
<pre class="doc_code">
%A = getelementptr <4 x i8*> %ptrs, <4 x i64> %offsets,
</pre>
diff --git a/include/llvm/Constant.h b/include/llvm/Constant.h
index 7fecf4c7b4..bbd1b1a6e2 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 ac803c5783..de404728be 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 1ed9004eb5..cf3839d4b0 100644
--- a/lib/Bitcode/Writer/ValueEnumerator.cpp
+++ b/lib/Bitcode/Writer/ValueEnumerator.cpp
@@ -24,8 +24,8 @@
#include <algorithm>
using namespace llvm;
-static bool isIntegerValue(const std::pair<const Value*, unsigned> &V) {
- return V.first->getType()->isIntegerTy();
+static bool isIntOrIntVectorValue(const std::pair<const Value*, unsigned> &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 a4e21e16b3..f96fb1d401 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<ConstantAggregateZero>(this))
+ return getNullValue(this->getType()->getVectorElementType());
+ if (const ConstantDataVector *CV = dyn_cast<ConstantDataVector>(this))
+ return CV->getSplatValue();
+ if (const ConstantVector *CV = dyn_cast<ConstantVector>(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<ConstantInt>(this))
+ return CI->getValue();
+ assert(this->getSplatValue() && "Doesn't contain a unique integer!");
+ const Constant *C = this->getAggregateElement(0U);
+ assert(C && isa<ConstantInt>(C) && "Not a vector of numbers!");
+ return cast<ConstantInt>(C)->getValue();
+}
+
+
//---- ConstantPointerNull::get() implementation.
//
@@ -1739,6 +1764,9 @@ Constant *ConstantExpr::getSelect(Constant *C, Constant *V1, Constant *V2) {
Constant *ConstantExpr::getGetElementPtr(Constant *C, ArrayRef<Value *> 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<Value *> Idxs,
assert(Ty && "GEP indices invalid!");
unsigned AS = C->getType()->getPointerAddressSpace();
Type *ReqTy = Ty->getPointerTo(AS);
+ if (VectorType *VecTy = dyn_cast<VectorType>(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<Constant*> 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<Constant>(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 94bd2a1563..ca7cd4eb97 100644
--- a/lib/VMCore/Instructions.cpp
+++ b/lib/VMCore/Instructions.cpp
@@ -1353,16 +1353,7 @@ GetElementPtrInst::GetElementPtrInst(const GetElementPtrInst &GEPI)
///
template <typename IndexTy>
static Type *getIndexedTypeInternal(Type *Ptr, ArrayRef<IndexTy> IdxList) {
- if (Ptr->isVectorTy()) {
- assert(IdxList.size() == 1 &&
- "GEP with vector pointers must have a single index");
- PointerType *PTy = dyn_cast<PointerType>(
- cast<VectorType>(Ptr)->getElementType());
- assert(PTy && "Gep with invalid vector pointer found");
- return PTy->getElementType();
- }
-
- PointerType *PTy = dyn_cast<PointerType>(Ptr);
+ PointerType *PTy = dyn_cast<PointerType>(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 1656ab2cab..4d75a7e060 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<StructType>(this)) {
- unsigned Idx = (unsigned)cast<ConstantInt>(V)->getZExtValue();
+ unsigned Idx =
+ (unsigned)cast<Constant>(V)->getUniqueInteger().getZExtValue();
assert(indexValid(Idx) && "Invalid structure index!");
return STy->getElementType(Idx);
}
-
+
return cast<SequentialType>(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<StructType>(this)) {
- // Structure indexes require 32-bit integer constants.
- if (V->getType()->isIntegerTy(32))
- if (const ConstantInt *CU = dyn_cast<ConstantInt>(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<Constant>(V);
+ if (C && V->getType()->isVectorTy())
+ C = C->getSplatValue();
+ const ConstantInt *CU = dyn_cast_or_null<ConstantInt>(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<PointerType>(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 eb40b09d29..3782957f3b 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<PointerType>(TargetTy)->getElementType()->isSized(),
"GEP into unsized type!", &GEP);
+ Assert1(GEP.getPointerOperandType()->isVectorTy() ==
+ GEP.getType()->isVectorTy(), "Vector GEP must return a vector value",
+ &GEP);
SmallVector<Value*, 16> 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<PointerType>(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<VectorType>(GEP.getType())->getElementType();
- Assert1(ElemPtr->isPointerTy(),
- "Vector GEP pointer operand is not a pointer!", &GEP);
- unsigned IndexWidth = cast<VectorType>(IndexTy)->getNumElements();
- unsigned GepWidth = cast<VectorType>(GEP.getType())->getNumElements();
- Assert1(IndexWidth == GepWidth, "Invalid GEP index vector width", &GEP);
- Assert1(ElTy == cast<PointerType>(ElemPtr)->getElementType(),
- "Vector GEP type does not match pointer type!", &GEP);
+ Assert2(GEP.getType()->getScalarType()->isPointerTy() &&
+ cast<PointerType>(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 ce6866d544..af03fca6d2 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> <i32 1, i32 2>, <2 x i32> <i32 2, i32 3>, <2 x i32> <i32 1, i32 1>)
+
+; 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> <i32 5, i32 9>, <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> <i32 0, i32 0>, <2 x i8> <i8 0, i8 1>
+ 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 0000000000..d2479f4404
--- /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> <i32 5, i32 9>
+ ret i32 %w
+}
diff --git a/test/Assembler/getelementptr_vec_idx2.ll b/test/Assembler/getelementptr_vec_idx2.ll
new file mode 100644
index 0000000000..8b71ce3095
--- /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 0000000000..1f6c29b3cc
--- /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> <i32 5, i32 9>
+ ret i32 %w
+}
diff --git a/test/Assembler/getelementptr_vec_struct.ll b/test/Assembler/getelementptr_vec_struct.ll
new file mode 100644
index 0000000000..ec66836bac
--- /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> <i32 5, i32 9>, <2 x i32> <i32 0, i32 1>
+ ret <2 x i32*> %w
+}
diff --git a/test/Transforms/LoopVectorize/gcc-examples.ll b/test/Transforms/LoopVectorize/gcc-examples.ll
index fce29d2404..2243a77d3b 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: