aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/LangRef.html52
-rw-r--r--include/llvm/DerivedTypes.h2
-rw-r--r--include/llvm/Instructions.h39
-rw-r--r--include/llvm/Operator.h4
-rw-r--r--include/llvm/Target/TargetLowering.h15
-rw-r--r--include/llvm/Type.h4
-rw-r--r--lib/Analysis/ConstantFolding.cpp3
-rw-r--r--lib/Analysis/InstructionSimplify.cpp7
-rw-r--r--lib/Analysis/ValueTracking.cpp10
-rw-r--r--lib/AsmParser/LLParser.cpp35
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp2
-rw-r--r--lib/Transforms/InstCombine/InstCombineCalls.cpp2
-rw-r--r--lib/Transforms/InstCombine/InstructionCombining.cpp9
-rw-r--r--lib/Transforms/Scalar/IndVarSimplify.cpp5
-rw-r--r--lib/Transforms/Scalar/ScalarReplAggregates.cpp2
-rw-r--r--lib/VMCore/Constants.cpp16
-rw-r--r--lib/VMCore/Instructions.cpp34
-rw-r--r--lib/VMCore/Type.cpp10
-rw-r--r--lib/VMCore/Verifier.cpp72
-rw-r--r--test/CodeGen/X86/pointer-vector.ll138
-rw-r--r--test/CodeGen/X86/vector-gep.ll77
-rw-r--r--test/Feature/const_pv.ll8
-rw-r--r--test/Feature/global_pv.ll14
-rw-r--r--test/Transforms/InstCombine/vector_gep1.ll37
-rw-r--r--test/Transforms/InstSimplify/vector_gep.ll8
-rw-r--r--unittests/VMCore/InstructionsTest.cpp97
26 files changed, 631 insertions, 71 deletions
diff --git a/docs/LangRef.html b/docs/LangRef.html
index 2329bdb1c8..12c140f823 100644
--- a/docs/LangRef.html
+++ b/docs/LangRef.html
@@ -2189,8 +2189,8 @@ in signal handlers).</p>
</pre>
<p>The number of elements is a constant integer value larger than 0; elementtype
- may be any integer or floating point type. Vectors of size zero are not
- allowed, and pointers are not allowed as the element type.</p>
+ may be any integer or floating point type, or a pointer to these types.
+ Vectors of size zero are not allowed. </p>
<h5>Examples:</h5>
<table class="layout">
@@ -2206,6 +2206,10 @@ in signal handlers).</p>
<td class="left"><tt>&lt;2 x i64&gt;</tt></td>
<td class="left">Vector of 2 64-bit integer values.</td>
</tr>
+ <tr class="layout">
+ <td class="left"><tt>&lt;4 x i64*&gt;</tt></td>
+ <td class="left">Vector of 4 pointers to 64-bit integer values.</td>
+ </tr>
</table>
</div>
@@ -5069,6 +5073,7 @@ specified by the <var>operation</var> argument:</p>
<pre>
&lt;result&gt; = getelementptr &lt;pty&gt;* &lt;ptrval&gt;{, &lt;ty&gt; &lt;idx&gt;}*
&lt;result&gt; = getelementptr inbounds &lt;pty&gt;* &lt;ptrval&gt;{, &lt;ty&gt; &lt;idx&gt;}*
+ &lt;result&gt; = getelementptr &lt;ptr vector&gt; ptrval, &lt;vector index type&gt; idx
</pre>
<h5>Overview:</h5>
@@ -5077,7 +5082,8 @@ specified by the <var>operation</var> argument:</p>
It performs address calculation only and does not access memory.</p>
<h5>Arguments:</h5>
-<p>The first argument is always a pointer, and forms the basis of the
+<p>The first argument is always a pointer or a vector of pointers,
+ and forms the basis of the
calculation. The remaining arguments are indices that indicate which of the
elements of the aggregate object are indexed. The interpretation of each
index is dependent on the type being indexed into. The first index always
@@ -5162,7 +5168,9 @@ entry:
precise signed arithmetic are not an <i>in bounds</i> address of that
allocated object. The <i>in bounds</i> addresses for an allocated object
are all the addresses that point into the object, plus the address one
- byte past the end.</p>
+ byte past the end.
+ In cases where the base is a vector of pointers the <tt>inbounds</tt> keyword
+ applies to each of the computations element-wise. </p>
<p>If the <tt>inbounds</tt> keyword is not present, the offsets are added to
the base address with silently-wrapping two's complement arithmetic. If the
@@ -5189,6 +5197,13 @@ entry:
%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>
+<pre class="doc_code">
+ %A = getelementptr <4 x i8*> %ptrs, <4 x i64> %offsets,
+</pre>
+
</div>
</div>
@@ -5561,13 +5576,16 @@ entry:
</pre>
<h5>Overview:</h5>
-<p>The '<tt>ptrtoint</tt>' instruction converts the pointer <tt>value</tt> to
- the integer type <tt>ty2</tt>.</p>
+<p>The '<tt>ptrtoint</tt>' instruction converts the pointer or a vector of
+ pointers <tt>value</tt> to
+ the integer (or vector of integers) type <tt>ty2</tt>.</p>
<h5>Arguments:</h5>
<p>The '<tt>ptrtoint</tt>' instruction takes a <tt>value</tt> to cast, which
- must be a <a href="#t_pointer">pointer</a> value, and a type to cast it to
- <tt>ty2</tt>, which must be an <a href="#t_integer">integer</a> type.</p>
+ must be a a value of type <a href="#t_pointer">pointer</a> or a vector of
+ pointers, and a type to cast it to
+ <tt>ty2</tt>, which must be an <a href="#t_integer">integer</a> or a vector
+ of integers type.</p>
<h5>Semantics:</h5>
<p>The '<tt>ptrtoint</tt>' instruction converts <tt>value</tt> to integer type
@@ -5580,8 +5598,9 @@ entry:
<h5>Example:</h5>
<pre>
- %X = ptrtoint i32* %X to i8 <i>; yields truncation on 32-bit architecture</i>
- %Y = ptrtoint i32* %x to i64 <i>; yields zero extension on 32-bit architecture</i>
+ %X = ptrtoint i32* %P to i8 <i>; yields truncation on 32-bit architecture</i>
+ %Y = ptrtoint i32* %P to i64 <i>; yields zero extension on 32-bit architecture</i>
+ %Z = ptrtoint &lt;4 x i32*&gt; %P to &lt;4 x i64&gt;<i>; yields vector zero extension for a vector of addresses on 32-bit architecture</i>
</pre>
</div>
@@ -5620,6 +5639,7 @@ entry:
%X = inttoptr i32 255 to i32* <i>; yields zero extension on 64-bit architecture</i>
%Y = inttoptr i32 255 to i32* <i>; yields no-op on 32-bit architecture</i>
%Z = inttoptr i64 0 to i32* <i>; yields truncation on 32-bit architecture</i>
+ %Z = inttoptr &lt;4 x i32&gt; %G to &lt;4 x i8*&gt;<i>; yields truncation of vector G to four pointers</i>
</pre>
</div>
@@ -5654,8 +5674,9 @@ entry:
<p>The '<tt>bitcast</tt>' instruction converts <tt>value</tt> to type
<tt>ty2</tt>. It is always a <i>no-op cast</i> because no bits change with
this conversion. The conversion is done as if the <tt>value</tt> had been
- stored to memory and read back as type <tt>ty2</tt>. Pointer types may only
- be converted to other pointer types with this instruction. To convert
+ stored to memory and read back as type <tt>ty2</tt>.
+ Pointer (or vector of pointers) types may only be converted to other pointer
+ (or vector of pointers) types with this instruction. To convert
pointers to other types, use the <a href="#i_inttoptr">inttoptr</a> or
<a href="#i_ptrtoint">ptrtoint</a> instructions first.</p>
@@ -5663,7 +5684,8 @@ entry:
<pre>
%X = bitcast i8 255 to i8 <i>; yields i8 :-1</i>
%Y = bitcast i32* %x to sint* <i>; yields sint*:%x</i>
- %Z = bitcast &lt;2 x int&gt; %V to i64; <i>; yields i64: %V</i>
+ %Z = bitcast &lt;2 x int&gt; %V to i64; <i>; yields i64: %V</i>
+ %Z = bitcast &lt;2 x i32*&gt; %V to &lt;2 x i64*&gt; <i>; yields &lt;2 x i64*&gt;</i>
</pre>
</div>
@@ -5694,8 +5716,8 @@ entry:
<h5>Overview:</h5>
<p>The '<tt>icmp</tt>' instruction returns a boolean value or a vector of
- boolean values based on comparison of its two integer, integer vector, or
- pointer operands.</p>
+ boolean values based on comparison of its two integer, integer vector,
+ pointer, or pointer vector operands.</p>
<h5>Arguments:</h5>
<p>The '<tt>icmp</tt>' instruction takes three operands. The first operand is
diff --git a/include/llvm/DerivedTypes.h b/include/llvm/DerivedTypes.h
index 445c3deb7c..b9ade512cf 100644
--- a/include/llvm/DerivedTypes.h
+++ b/include/llvm/DerivedTypes.h
@@ -374,6 +374,7 @@ public:
///
static VectorType *getInteger(VectorType *VTy) {
unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits();
+ assert(EltBits && "Element size must be of a non-zero size");
Type *EltTy = IntegerType::get(VTy->getContext(), EltBits);
return VectorType::get(EltTy, VTy->getNumElements());
}
@@ -408,6 +409,7 @@ public:
unsigned getNumElements() const { return NumElements; }
/// @brief Return the number of bits in the Vector type.
+ /// Returns zero when the vector is a vector of pointers.
unsigned getBitWidth() const {
return NumElements * getElementType()->getPrimitiveSizeInBits();
}
diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h
index 3faab35bf6..e87950eb39 100644
--- a/include/llvm/Instructions.h
+++ b/include/llvm/Instructions.h
@@ -776,6 +776,10 @@ public:
static Type *getIndexedType(Type *Ptr, ArrayRef<Constant *> IdxList);
static Type *getIndexedType(Type *Ptr, ArrayRef<uint64_t> IdxList);
+ /// getIndexedType - Returns the address space used by the GEP pointer.
+ ///
+ static unsigned getAddressSpace(Value *Ptr);
+
inline op_iterator idx_begin() { return op_begin()+1; }
inline const_op_iterator idx_begin() const { return op_begin()+1; }
inline op_iterator idx_end() { return op_end(); }
@@ -788,7 +792,7 @@ public:
return getOperand(0);
}
static unsigned getPointerOperandIndex() {
- return 0U; // get index for modifying correct operand
+ return 0U; // get index for modifying correct operand.
}
unsigned getPointerAddressSpace() const {
@@ -797,10 +801,25 @@ public:
/// getPointerOperandType - Method to return the pointer operand as a
/// PointerType.
- PointerType *getPointerOperandType() const {
- return reinterpret_cast<PointerType*>(getPointerOperand()->getType());
+ Type *getPointerOperandType() const {
+ return getPointerOperand()->getType();
}
+ /// GetGEPReturnType - Returns the pointer type returned by the GEP
+ /// instruction, which may be a vector of pointers.
+ static Type *getGEPReturnType(Value *Ptr, ArrayRef<Value *> IdxList) {
+ Type *PtrTy = PointerType::get(checkGEPType(
+ getIndexedType(Ptr->getType(), IdxList)),
+ getAddressSpace(Ptr));
+ // Vector GEP
+ if (Ptr->getType()->isVectorTy()) {
+ unsigned NumElem = cast<VectorType>(Ptr->getType())->getNumElements();
+ return VectorType::get(PtrTy, NumElem);
+ }
+
+ // Scalar GEP
+ return PtrTy;
+ }
unsigned getNumIndices() const { // Note: always non-negative
return getNumOperands() - 1;
@@ -847,10 +866,7 @@ GetElementPtrInst::GetElementPtrInst(Value *Ptr,
unsigned Values,
const Twine &NameStr,
Instruction *InsertBefore)
- : Instruction(PointerType::get(checkGEPType(
- getIndexedType(Ptr->getType(), IdxList)),
- cast<PointerType>(Ptr->getType())
- ->getAddressSpace()),
+ : Instruction(getGEPReturnType(Ptr, IdxList),
GetElementPtr,
OperandTraits<GetElementPtrInst>::op_end(this) - Values,
Values, InsertBefore) {
@@ -861,10 +877,7 @@ GetElementPtrInst::GetElementPtrInst(Value *Ptr,
unsigned Values,
const Twine &NameStr,
BasicBlock *InsertAtEnd)
- : Instruction(PointerType::get(checkGEPType(
- getIndexedType(Ptr->getType(), IdxList)),
- cast<PointerType>(Ptr->getType())
- ->getAddressSpace()),
+ : Instruction(getGEPReturnType(Ptr, IdxList),
GetElementPtr,
OperandTraits<GetElementPtrInst>::op_end(this) - Values,
Values, InsertAtEnd) {
@@ -905,7 +918,7 @@ public:
"Both operands to ICmp instruction are not of the same type!");
// Check that the operands are the right type
assert((getOperand(0)->getType()->isIntOrIntVectorTy() ||
- getOperand(0)->getType()->isPointerTy()) &&
+ getOperand(0)->getType()->getScalarType()->isPointerTy()) &&
"Invalid operand types for ICmp instruction");
}
@@ -945,7 +958,7 @@ public:
"Both operands to ICmp instruction are not of the same type!");
// Check that the operands are the right type
assert((getOperand(0)->getType()->isIntOrIntVectorTy() ||
- getOperand(0)->getType()->isPointerTy()) &&
+ getOperand(0)->getType()->getScalarType()->isPointerTy()) &&
"Invalid operand types for ICmp instruction");
}
diff --git a/include/llvm/Operator.h b/include/llvm/Operator.h
index 48a5796383..abd6a1939d 100644
--- a/include/llvm/Operator.h
+++ b/include/llvm/Operator.h
@@ -261,8 +261,8 @@ public:
/// getPointerOperandType - Method to return the pointer operand as a
/// PointerType.
- PointerType *getPointerOperandType() const {
- return reinterpret_cast<PointerType*>(getPointerOperand()->getType());
+ Type *getPointerOperandType() const {
+ return getPointerOperand()->getType();
}
unsigned getNumIndices() const { // Note: always non-negative
diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h
index 3fe3a38b2a..67179fc8f4 100644
--- a/include/llvm/Target/TargetLowering.h
+++ b/include/llvm/Target/TargetLowering.h
@@ -520,8 +520,19 @@ public:
/// AllowUnknown is true, this will return MVT::Other for types with no EVT
/// counterpart (e.g. structs), otherwise it will assert.
EVT getValueType(Type *Ty, bool AllowUnknown = false) const {
- EVT VT = EVT::getEVT(Ty, AllowUnknown);
- return VT == MVT::iPTR ? PointerTy : VT;
+ // Lower scalar pointers to native pointer types.
+ if (Ty->isPointerTy()) return PointerTy;
+
+ if (Ty->isVectorTy()) {
+ VectorType *VTy = cast<VectorType>(Ty);
+ Type *Elm = VTy->getElementType();
+ // Lower vectors of pointers to native pointer types.
+ if (Elm->isPointerTy())
+ Elm = EVT(PointerTy).getTypeForEVT(Ty->getContext());
+ return EVT::getVectorVT(Ty->getContext(), EVT::getEVT(Elm, false),
+ VTy->getNumElements());
+ }
+ return EVT::getEVT(Ty, AllowUnknown);
}
/// getByValTypeAlignment - Return the desired alignment for ByVal aggregate
diff --git a/include/llvm/Type.h b/include/llvm/Type.h
index 43b7dc5788..a571b4dbe5 100644
--- a/include/llvm/Type.h
+++ b/include/llvm/Type.h
@@ -273,6 +273,10 @@ public:
/// otherwise return 'this'.
Type *getScalarType();
+ /// getNumElements - If this is a vector type, return the number of elements,
+ /// otherwise return zero.
+ unsigned getNumElements();
+
//===--------------------------------------------------------------------===//
// Type Iteration support.
//
diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp
index d12476885e..7e98b21888 100644
--- a/lib/Analysis/ConstantFolding.cpp
+++ b/lib/Analysis/ConstantFolding.cpp
@@ -580,7 +580,8 @@ static Constant *SymbolicallyEvaluateGEP(ArrayRef<Constant *> Ops,
Type *ResultTy, const TargetData *TD,
const TargetLibraryInfo *TLI) {
Constant *Ptr = Ops[0];
- if (!TD || !cast<PointerType>(Ptr->getType())->getElementType()->isSized())
+ if (!TD || !cast<PointerType>(Ptr->getType())->getElementType()->isSized() ||
+ !Ptr->getType()->isPointerTy())
return 0;
Type *IntPtrTy = TD->getIntPtrType(Ptr->getContext());
diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp
index b52f643545..f1cfd6cead 100644
--- a/lib/Analysis/InstructionSimplify.cpp
+++ b/lib/Analysis/InstructionSimplify.cpp
@@ -1764,7 +1764,7 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
// also a case of comparing two zero-extended values.
if (RExt == CI && MaxRecurse)
if (Value *V = SimplifyICmpInst(ICmpInst::getUnsignedPredicate(Pred),
- SrcOp, Trunc, TD, TLI, DT, MaxRecurse-1))
+ SrcOp, Trunc, TD, TLI, DT, MaxRecurse-1))
return V;
// Otherwise the upper bits of LHS are zero while RHS has a non-zero bit
@@ -2359,7 +2359,10 @@ Value *llvm::SimplifySelectInst(Value *CondVal, Value *TrueVal, Value *FalseVal,
Value *llvm::SimplifyGEPInst(ArrayRef<Value *> Ops, const TargetData *TD,
const DominatorTree *) {
// The type of the GEP pointer operand.
- PointerType *PtrTy = cast<PointerType>(Ops[0]->getType());
+ PointerType *PtrTy = dyn_cast<PointerType>(Ops[0]->getType());
+ // The GEP pointer operand is not a pointer, it's a vector of pointers.
+ if (!PtrTy)
+ return 0;
// getelementptr P -> P.
if (Ops.size() == 1)
diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp
index 58adc26a1d..0d016e21f2 100644
--- a/lib/Analysis/ValueTracking.cpp
+++ b/lib/Analysis/ValueTracking.cpp
@@ -63,13 +63,14 @@ void llvm::ComputeMaskedBits(Value *V, const APInt &Mask,
assert(V && "No Value?");
assert(Depth <= MaxDepth && "Limit Search Depth");
unsigned BitWidth = Mask.getBitWidth();
- assert((V->getType()->isIntOrIntVectorTy() || V->getType()->isPointerTy())
- && "Not integer or pointer type!");
+ assert((V->getType()->isIntOrIntVectorTy() ||
+ V->getType()->getScalarType()->isPointerTy()) &&
+ "Not integer or pointer type!");
assert((!TD ||
TD->getTypeSizeInBits(V->getType()->getScalarType()) == BitWidth) &&
(!V->getType()->isIntOrIntVectorTy() ||
V->getType()->getScalarSizeInBits() == BitWidth) &&
- KnownZero.getBitWidth() == BitWidth &&
+ KnownZero.getBitWidth() == BitWidth &&
KnownOne.getBitWidth() == BitWidth &&
"V, Mask, KnownOne and KnownZero should have same BitWidth");
@@ -1557,7 +1558,8 @@ Value *llvm::FindInsertedValue(Value *V, ArrayRef<unsigned> idx_range,
Value *llvm::GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset,
const TargetData &TD) {
Operator *PtrOp = dyn_cast<Operator>(Ptr);
- if (PtrOp == 0) return Ptr;
+ if (PtrOp == 0 || Ptr->getType()->isVectorTy())
+ return Ptr;
// Just look through bitcasts.
if (PtrOp->getOpcode() == Instruction::BitCast)
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index 212c9fb38d..1ef69105d6 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -1607,7 +1607,8 @@ 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 or integer");
+ return Error(TypeLoc,
+ "vector element type must be fp, integer or a pointer to these types");
Result = VectorType::get(EltTy, unsigned(Size));
} else {
if (!ArrayType::isValidElementType(EltTy))
@@ -1966,9 +1967,10 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
return Error(ID.Loc, "constant vector must not be empty");
if (!Elts[0]->getType()->isIntegerTy() &&
- !Elts[0]->getType()->isFloatingPointTy())
+ !Elts[0]->getType()->isFloatingPointTy() &&
+ !Elts[0]->getType()->isPointerTy())
return Error(FirstEltLoc,
- "vector elements must have integer or floating point type");
+ "vector elements must have integer, pointer or floating point type");
// Verify that all the vector elements have the same type.
for (unsigned i = 1, e = Elts.size(); i != e; ++i)
@@ -2160,7 +2162,7 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
} else {
assert(Opc == Instruction::ICmp && "Unexpected opcode for CmpInst!");
if (!Val0->getType()->isIntOrIntVectorTy() &&
- !Val0->getType()->isPointerTy())
+ !Val0->getType()->getScalarType()->isPointerTy())
return Error(ID.Loc, "icmp requires pointer or integer operands");
ID.ConstantVal = ConstantExpr::getICmp(Pred, Val0, Val1);
}
@@ -2294,7 +2296,8 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
return true;
if (Opc == Instruction::GetElementPtr) {
- if (Elts.size() == 0 || !Elts[0]->getType()->isPointerTy())
+ if (Elts.size() == 0 ||
+ !Elts[0]->getType()->getScalarType()->isPointerTy())
return Error(ID.Loc, "getelementptr requires pointer operand");
ArrayRef<Constant *> Indices(Elts.begin() + 1, Elts.end());
@@ -3329,7 +3332,7 @@ bool LLParser::ParseCompare(Instruction *&Inst, PerFunctionState &PFS,
} else {
assert(Opc == Instruction::ICmp && "Unknown opcode for CmpInst!");
if (!LHS->getType()->isIntOrIntVectorTy() &&
- !LHS->getType()->isPointerTy())
+ !LHS->getType()->getScalarType()->isPointerTy())
return Error(Loc, "icmp requires integer operands");
Inst = new ICmpInst(CmpInst::Predicate(Pred), LHS, RHS);
}
@@ -3877,13 +3880,15 @@ int LLParser::ParseFence(Instruction *&Inst, PerFunctionState &PFS) {
/// ParseGetElementPtr
/// ::= 'getelementptr' 'inbounds'? TypeAndValue (',' TypeAndValue)*
int LLParser::ParseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS) {
- Value *Ptr, *Val; LocTy Loc, EltLoc;
+ Value *Ptr = 0;
+ Value *Val = 0;
+ LocTy Loc, EltLoc;
bool InBounds = EatIfPresent(lltok::kw_inbounds);
if (ParseTypeAndValue(Ptr, Loc, PFS)) return true;
- if (!Ptr->getType()->isPointerTy())
+ if (!Ptr->getType()->getScalarType()->isPointerTy())
return Error(Loc, "base of getelementptr must be a pointer");
SmallVector<Value*, 16> Indices;
@@ -3894,11 +3899,23 @@ int LLParser::ParseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS) {
break;
}
if (ParseTypeAndValue(Val, EltLoc, PFS)) return true;
- if (!Val->getType()->isIntegerTy())
+ if (!Val->getType()->getScalarType()->isIntegerTy())
return Error(EltLoc, "getelementptr index must be an integer");
+ if (Val->getType()->isVectorTy() != Ptr->getType()->isVectorTy())
+ return Error(EltLoc, "getelementptr index type missmatch");
+ if (Val->getType()->isVectorTy()) {
+ unsigned ValNumEl = cast<VectorType>(Val->getType())->getNumElements();
+ unsigned PtrNumEl = cast<VectorType>(Ptr->getType())->getNumElements();
+ if (ValNumEl != PtrNumEl)
+ return Error(EltLoc,
+ "getelementptr vector index has a wrong number of elements");
+ }
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/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index a77401e359..ac24ce5868 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3099,7 +3099,7 @@ void SelectionDAGBuilder::visitGetElementPtr(const User &I) {
unsigned Amt = ElementSize.logBase2();
IdxN = DAG.getNode(ISD::SHL, getCurDebugLoc(),
N.getValueType(), IdxN,
- DAG.getConstant(Amt, TLI.getPointerTy()));
+ DAG.getConstant(Amt, IdxN.getValueType()));
} else {
SDValue Scale = DAG.getConstant(ElementSize, TLI.getPointerTy());
IdxN = DAG.getNode(ISD::MUL, getCurDebugLoc(),
diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 81dad7e022..27c7c54a9c 100644
--- a/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -265,6 +265,8 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
// Get the current byte offset into the thing. Use the original
// operand in case we're looking through a bitcast.
SmallVector<Value*, 8> Ops(GEP->idx_begin(), GEP->idx_end());
+ if (!GEP->getPointerOperandType()->isPointerTy())
+ return 0;
Offset = TD->getIndexedOffset(GEP->getPointerOperandType(), Ops);
Op1 = GEP->getPointerOperand()->stripPointerCasts();
diff --git a/lib/Transforms/InstCombine/InstructionCombining.cpp b/lib/Transforms/InstCombine/InstructionCombining.cpp
index 50794deba3..af065cd886 100644
--- a/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -831,7 +831,8 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
MadeChange = true;
}
- if ((*I)->getType() != IntPtrTy) {
+ Type *IndexTy = (*I)->getType();
+ if (IndexTy != IntPtrTy && !IndexTy->isVectorTy()) {
// If we are using a wider index than needed for this platform, shrink
// it to what we need. If narrower, sign-extend it to what we need.
// This explicit cast can make subsequent optimizations more obvious.
@@ -914,7 +915,11 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
// Handle gep(bitcast x) and gep(gep x, 0, 0, 0).
Value *StrippedPtr = PtrOp->stripPointerCasts();
- PointerType *StrippedPtrTy =cast<PointerType>(StrippedPtr->getType());
+ PointerType *StrippedPtrTy = dyn_cast<PointerType>(StrippedPtr->getType());
+ // We do not handle pointer-vector geps here
+ if (!StrippedPtr)
+ return 0;
+
if (StrippedPtr != PtrOp &&
StrippedPtrTy->getAddressSpace() == GEP.getPointerAddressSpace()) {
diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp
index ea083e36ca..1176cc9a04 100644
--- a/lib/Transforms/Scalar/IndVarSimplify.cpp
+++ b/lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -178,6 +178,11 @@ bool IndVarSimplify::isValidRewrite(Value *FromVal, Value *ToVal) {
// base of a recurrence. This handles the case in which SCEV expansion
// converts a pointer type recurrence into a nonrecurrent pointer base
// indexed by an integer recurrence.
+
+ // If the GEP base pointer is a vector of pointers, abort.
+ if (!FromPtr->getType()->isPointerTy() || !ToPtr->getType()->isPointerTy())
+ return false;
+
const SCEV *FromBase = SE->getPointerBase(SE->getSCEV(FromPtr));
const SCEV *ToBase = SE->getPointerBase(SE->getSCEV(ToPtr));
if (FromBase == ToBase)
diff --git a/lib/Transforms/Scalar/ScalarReplAggregates.cpp b/lib/Transforms/Scalar/ScalarReplAggregates.cpp
index 4b14efcd06..bc70c51cc0 100644
--- a/lib/Transforms/Scalar/ScalarReplAggregates.cpp
+++ b/lib/Transforms/Scalar/ScalarReplAggregates.cpp
@@ -453,6 +453,8 @@ bool ConvertToScalarInfo::CanConvertToScalar(Value *V, uint64_t Offset) {
// Compute the offset that this GEP adds to the pointer.
SmallVector<Value*, 8> Indices(GEP->op_begin()+1, GEP->op_end());
+ if (!GEP->getPointerOperandType()->isPointerTy())
+ return false;
uint64_t GEPOffset = TD.getIndexedOffset(GEP->getPointerOperandType(),
Indices);
// See if all uses can be converted.
diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp
index cd94da1353..a1489123ca 100644
--- a/lib/VMCore/Constants.cpp
+++ b/lib/VMCore/Constants.cpp
@@ -1398,14 +1398,22 @@ Constant *ConstantExpr::getFPToSI(Constant *C, Type *Ty) {
}
Constant *ConstantExpr::getPtrToInt(Constant *C, Type *DstTy) {
- assert(C->getType()->isPointerTy() && "PtrToInt source must be pointer");
- assert(DstTy->isIntegerTy() && "PtrToInt destination must be integral");
+ assert(C->getType()->getScalarType()->isPointerTy() &&
+ "PtrToInt source must be pointer or pointer vector");
+ assert(DstTy->getScalarType()->isIntegerTy() &&
+ "PtrToInt destination must be integer or integer vector");
+ assert(C->getType()->getNumElements() == DstTy->getNumElements() &&
+ "Invalid cast between a different number of vector elements");
return getFoldedCast(Instruction::PtrToInt, C, DstTy);
}
Constant *ConstantExpr::getIntToPtr(Constant *C, Type *DstTy) {
- assert(C->getType()->isIntegerTy() && "IntToPtr source must be integral");
- assert(DstTy->isPointerTy() && "IntToPtr destination must be a pointer");
+ assert(C->getType()->getScalarType()->isIntegerTy() &&
+ "IntToPtr source must be integer or integer vector");
+ assert(DstTy->getScalarType()->isPointerTy() &&
+ "IntToPtr destination must be a pointer or pointer vector");
+ assert(C->getType()->getNumElements() == DstTy->getNumElements() &&
+ "Invalid cast between a different number of vector elements");
return getFoldedCast(Instruction::IntToPtr, C, DstTy);
}
diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp
index 6fa904e4e4..4784f0c6e0 100644
--- a/lib/VMCore/Instructions.cpp
+++ b/lib/VMCore/Instructions.cpp
@@ -1359,6 +1359,15 @@ 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);
if (!PTy) return 0; // Type isn't a pointer type!
Type *Agg = PTy->getElementType();
@@ -1366,7 +1375,7 @@ static Type *getIndexedTypeInternal(Type *Ptr, ArrayRef<IndexTy> IdxList) {
// Handle the special case of the empty set index set, which is always valid.
if (IdxList.empty())
return Agg;
-
+
// If there is at least one index, the top level type must be sized, otherwise
// it cannot be 'stepped over'.
if (!Agg->isSized())
@@ -1396,6 +1405,19 @@ Type *GetElementPtrInst::getIndexedType(Type *Ptr, ArrayRef<uint64_t> IdxList) {
return getIndexedTypeInternal(Ptr, IdxList);
}
+unsigned GetElementPtrInst::getAddressSpace(Value *Ptr) {
+ Type *Ty = Ptr->getType();
+
+ if (VectorType *VTy = dyn_cast<VectorType>(Ty))
+ Ty = VTy->getElementType();
+
+ if (PointerType *PTy = dyn_cast<PointerType>(Ty))
+ return PTy->getAddressSpace();
+
+ assert(false && "Invalid GEP pointer type");
+ return 0;
+}
+
/// hasAllZeroIndices - Return true if all of the indices of this GEP are
/// zeros. If so, the result pointer and the first operand have the same
/// value, just potentially different types.
@@ -2654,9 +2676,15 @@ CastInst::castIsValid(Instruction::CastOps op, Value *S, Type *DstTy) {
return SrcTy->isFPOrFPVectorTy() && DstTy->isIntOrIntVectorTy() &&
SrcLength == DstLength;
case Instruction::PtrToInt:
- return SrcTy->isPointerTy() && DstTy->isIntegerTy();
+ if (SrcTy->getNumElements() != DstTy->getNumElements())
+ return false;
+ return SrcTy->getScalarType()->isPointerTy() &&
+ DstTy->getScalarType()->isIntegerTy();
case Instruction::IntToPtr:
- return SrcTy->isIntegerTy() && DstTy->isPointerTy();
+ if (SrcTy->getNumElements() != DstTy->getNumElements())
+ return false;
+ return SrcTy->getScalarType()->isIntegerTy() &&
+ DstTy->getScalarType()->isPointerTy();
case Instruction::BitCast:
// BitCast implies a no-op cast of type only. No bits change.
// However, you can't cast pointers to anything but pointers.
diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp
index 10184bc6f0..469defdb85 100644
--- a/lib/VMCore/Type.cpp
+++ b/lib/VMCore/Type.cpp
@@ -46,6 +46,14 @@ Type *Type::getScalarType() {
return this;
}
+/// getNumElements - If this is a vector type, return the number of elements,
+/// otherwise return zero.
+unsigned Type::getNumElements() {
+ if (VectorType *VTy = dyn_cast<VectorType>(this))
+ return VTy->getNumElements();
+ return 0;
+}
+
/// isIntegerTy - Return true if this is an IntegerType of the specified width.
bool Type::isIntegerTy(unsigned Bitwidth) const {
return isIntegerTy() && cast<IntegerType>(this)->getBitWidth() == Bitwidth;
@@ -664,6 +672,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();
}
diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp
index 9564b7d71f..f74d762be9 100644
--- a/lib/VMCore/Verifier.cpp
+++ b/lib/VMCore/Verifier.cpp
@@ -1035,8 +1035,19 @@ void Verifier::visitPtrToIntInst(PtrToIntInst &I) {
Type *SrcTy = I.getOperand(0)->getType();
Type *DestTy = I.getType();
- Assert1(SrcTy->isPointerTy(), "PtrToInt source must be pointer", &I);
- Assert1(DestTy->isIntegerTy(), "PtrToInt result must be integral", &I);
+ Assert1(SrcTy->getScalarType()->isPointerTy(),
+ "PtrToInt source must be pointer", &I);
+ Assert1(DestTy->getScalarType()->isIntegerTy(),
+ "PtrToInt result must be integral", &I);
+ Assert1(SrcTy->isVectorTy() == DestTy->isVectorTy(),
+ "PtrToInt type mismatch", &I);
+
+ if (SrcTy->isVectorTy()) {
+ VectorType *VSrc = dyn_cast<VectorType>(SrcTy);
+ VectorType *VDest = dyn_cast<VectorType>(DestTy);
+ Assert1(VSrc->getNumElements() == VDest->getNumElements(),
+ "PtrToInt Vector width mismatch", &I);
+ }
visitInstruction(I);
}
@@ -1046,9 +1057,18 @@ void Verifier::visitIntToPtrInst(IntToPtrInst &I) {
Type *SrcTy = I.getOperand(0)->getType();
Type *DestTy = I.getType();
- Assert1(SrcTy->isIntegerTy(), "IntToPtr source must be an integral", &I);
- Assert1(DestTy->isPointerTy(), "IntToPtr result must be a pointer",&I);
-
+ Assert1(SrcTy->getScalarType()->isIntegerTy(),
+ "IntToPtr source must be an integral", &I);
+ Assert1(DestTy->getScalarType()->isPointerTy(),
+ "IntToPtr result must be a pointer",&I);
+ Assert1(SrcTy->isVectorTy() == DestTy->isVectorTy(),
+ "IntToPtr type mismatch", &I);
+ if (SrcTy->isVectorTy()) {
+ VectorType *VSrc = dyn_cast<VectorType>(SrcTy);
+ VectorType *VDest = dyn_cast<VectorType>(DestTy);
+ Assert1(VSrc->getNumElements() == VDest->getNumElements(),
+ "IntToPtr Vector width mismatch", &I);
+ }
visitInstruction(I);
}
@@ -1245,7 +1265,7 @@ void Verifier::visitICmpInst(ICmpInst &IC) {
Assert1(Op0Ty == Op1Ty,
"Both operands to ICmp instruction are not of the same type!", &IC);
// Check that the operands are the right type
- Assert1(Op0Ty->isIntOrIntVectorTy() || Op0Ty->isPointerTy(),
+ Assert1(Op0Ty->isIntOrIntVectorTy() || Op0Ty->getScalarType()->isPointerTy(),
"Invalid operand types for ICmp instruction", &IC);
// Check that the predicate is valid.
Assert1(IC.getPredicate() >= CmpInst::FIRST_ICMP_PREDICATE &&
@@ -1295,17 +1315,43 @@ void Verifier::visitShuffleVectorInst(ShuffleVectorInst &SV) {
}
void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) {
- Assert1(cast<PointerType>(GEP.getOperand(0)->getType())
- ->getElementType()->isSized(),
+ Type *TargetTy = GEP.getPointerOperandType();
+ if (VectorType *VTy = dyn_cast<VectorType>(TargetTy))
+ TargetTy = VTy->getElementType();
+
+ Assert1(dyn_cast<PointerType>(TargetTy),
+ "GEP base pointer is not a vector or a vector of pointers", &GEP);
+ Assert1(cast<PointerType>(TargetTy)->getElementType()->isSized(),
"GEP into unsized type!", &GEP);
-
+
SmallVector<Value*, 16> Idxs(GEP.idx_begin(), GEP.idx_end());
Type *ElTy =
- GetElementPtrInst::getIndexedType(GEP.getOperand(0)->getType(), Idxs);
+ GetElementPtrInst::getIndexedType(GEP.getPointerOperandType(), Idxs);
Assert1(ElTy, "Invalid indices for GEP pointer type!", &GEP);
- Assert2(GEP.getType()->isPointerTy() &&
- cast<PointerType>(GEP.getType())->getElementType() == ElTy,
- "GEP is not of right type for indices!", &GEP, ElTy);
+
+ 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);
+ }
visitInstruction(GEP);
}
diff --git a/test/CodeGen/X86/pointer-vector.ll b/test/CodeGen/X86/pointer-vector.ll
new file mode 100644
index 0000000000..9c1c521312
--- /dev/null
+++ b/test/CodeGen/X86/pointer-vector.ll
@@ -0,0 +1,138 @@
+; RUN: llc < %s -march=x86 -mcpu=corei7 | FileCheck %s
+; RUN: opt -instsimplify %s -disable-output
+
+;CHECK: SHUFF0
+define <8 x i32*> @SHUFF0(<4 x i32*> %ptrv) nounwind {
+entry:
+ %G = shufflevector <4 x i32*> %ptrv, <4 x i32*> %ptrv, <8 x i32> <i32 2, i32 7, i32 1, i32 2, i32 4, i32 5, i32 1, i32 1>
+;CHECK: pshufd
+ ret <8 x i32*> %G
+;CHECK: ret
+}
+
+;CHECK: SHUFF1
+define <4 x i32*> @SHUFF1(<4 x i32*> %ptrv) nounwind {
+entry:
+ %G = shufflevector <4 x i32*> %ptrv, <4 x i32*> %ptrv, <4 x i32> <i32 2, i32 7, i32 7, i32 2>
+;CHECK: pshufd
+ ret <4 x i32*> %G
+;CHECK: ret
+}
+
+;CHECK: SHUFF3
+define <4 x i8*> @SHUFF3(<4 x i8*> %ptrv) nounwind {
+entry:
+ %G = shufflevector <4 x i8*> %ptrv, <4 x i8*> undef, <4 x i32> <i32 2, i32 7, i32 1, i32 2>
+;CHECK: pshufd
+ ret <4 x i8*> %G
+;CHECK: ret
+}
+
+;CHECK: LOAD0
+define <4 x i8*> @LOAD0(<4 x i8*>* %p) nounwind {
+entry:
+ %G = load <4 x i8*>* %p
+;CHECK: movaps
+ ret <4 x i8*> %G
+;CHECK: ret
+}
+
+;CHECK: LOAD1
+define <4 x i8*> @LOAD1(<4 x i8*>* %p) nounwind {
+entry:
+ %G = load <4 x i8*>* %p
+;CHECK: movdqa
+;CHECK: pshufd
+;CHECK: movdqa
+ %T = shufflevector <4 x i8*> %G, <4 x i8*> %G, <4 x i32> <i32 7, i32 1, i32 4, i32 3>
+ store <4 x i8*> %T, <4 x i8*>* %p
+ ret <4 x i8*> %G
+;CHECK: ret
+}
+
+;CHECK: LOAD2
+define <4 x i8*> @LOAD2(<4 x i8*>* %p) nounwind {
+entry:
+ %I = alloca <4 x i8*>
+;CHECK: sub
+ %G = load <4 x i8*>* %p
+;CHECK: movaps
+ store <4 x i8*> %G, <4 x i8*>* %I
+;CHECK: movaps
+ %Z = load <4 x i8*>* %I
+ ret <4 x i8*> %Z
+;CHECK: add
+;CHECK: ret
+}
+
+;CHECK: INT2PTR0
+define <4 x i32> @INT2PTR0(<4 x i8*>* %p) nounwind {
+entry:
+ %G = load <4 x i8*>* %p
+;CHECK: movl
+;CHECK: movaps
+ %K = ptrtoint <4 x i8*> %G to <4 x i32>
+;CHECK: ret
+ ret <4 x i32> %K
+}
+
+;CHECK: INT2PTR1
+define <4 x i32*> @INT2PTR1(<4 x i8>* %p) nounwind {
+entry:
+ %G = load <4 x i8>* %p
+;CHECK: movl
+;CHECK: movd
+;CHECK: pshufb
+;CHECK: pand
+ %K = inttoptr <4 x i8> %G to <4 x i32*>
+;CHECK: ret
+ ret <4 x i32*> %K
+}
+
+;CHECK: BITCAST0
+define <4 x i32*> @BITCAST0(<4 x i8*>* %p) nounwind {
+entry:
+ %G = load <4 x i8*>* %p
+;CHECK: movl
+ %T = bitcast <4 x i8*> %G to <4 x i32*>
+;CHECK: movaps
+;CHECK: ret
+ ret <4 x i32*> %T
+}
+
+;CHECK: BITCAST1
+define <2 x i32*> @BITCAST1(<2 x i8*>* %p) nounwind {
+entry:
+ %G = load <2 x i8*>* %p
+;CHECK: movl
+;CHECK: movd
+;CHECK: pinsrd
+ %T = bitcast <2 x i8*> %G to <2 x i32*>
+;CHECK: ret
+ ret <2 x i32*> %T
+}
+
+;CHECK: ICMP0
+define <4 x i32> @ICMP0(<4 x i8*>* %p0, <4 x i8*>* %p1) nounwind {
+entry:
+ %g0 = load <4 x i8*>* %p0
+ %g1 = load <4 x i8*>* %p1
+ %k = icmp sgt <4 x i8*> %g0, %g1
+ ;CHECK: pcmpgtd
+ %j = select <4 x i1> %k, <4 x i32> <i32 0, i32 1, i32 2, i32 4>, <4 x i32> <i32 9, i32 8, i32 7, i32 6>
+ ret <4 x i32> %j
+ ;CHECK: ret
+}
+
+;CHECK: ICMP1
+define <4 x i32> @ICMP1(<4 x i8*>* %p0, <4 x i8*>* %p1) nounwind {
+entry:
+ %g0 = load <4 x i8*>* %p0
+ %g1 = load <4 x i8*>* %p1
+ %k = icmp eq <4 x i8*> %g0, %g1
+ ;CHECK: pcmpeqd
+ %j = select <4 x i1> %k, <4 x i32> <i32 0, i32 1, i32 2, i32 4>, <4 x i32> <i32 9, i32 8, i32 7, i32 6>
+ ret <4 x i32> %j
+ ;CHECK: ret
+}
+
diff --git a/test/CodeGen/X86/vector-gep.ll b/test/CodeGen/X86/vector-gep.ll
new file mode 100644
index 0000000000..d032eda88b
--- /dev/null
+++ b/test/CodeGen/X86/vector-gep.ll
@@ -0,0 +1,77 @@
+; RUN: llc < %s -march=x86 -mcpu=corei7-avx | FileCheck %s
+; RUN: opt -instsimplify %s -disable-output
+
+;CHECK: AGEP0
+define <4 x i32*> @AGEP0(i32* %ptr) nounwind {
+entry:
+ %vecinit.i = insertelement <4 x i32*> undef, i32* %ptr, i32 0
+ %vecinit2.i = insertelement <4 x i32*> %vecinit.i, i32* %ptr, i32 1
+ %vecinit4.i = insertelement <4 x i32*> %vecinit2.i, i32* %ptr, i32 2
+ %vecinit6.i = insertelement <4 x i32*> %vecinit4.i, i32* %ptr, i32 3
+;CHECK: pslld
+;CHECK: padd
+ %A2 = getelementptr <4 x i32*> %vecinit6.i, <4 x i32> <i32 1, i32 2, i32 3, i32 4>
+;CHECK: pslld
+;CHECK: padd
+ %A3 = getelementptr <4 x i32*> %A2, <4 x i32> <i32 10, i32 14, i32 19, i32 233>
+ ret <4 x i32*> %A3
+;CHECK: ret
+}
+
+;CHECK: AGEP1
+define i32 @AGEP1(<4 x i32*> %param) nounwind {
+entry:
+;CHECK: pslld
+;CHECK: padd
+ %A2 = getelementptr <4 x i32*> %param, <4 x i32> <i32 1, i32 2, i32 3, i32 4>
+ %k = extractelement <4 x i32*> %A2, i32 3
+ %v = load i32* %k
+ ret i32 %v
+;CHECK: ret
+}
+
+;CHECK: AGEP2
+define i32 @AGEP2(<4 x i32*> %param, <4 x i32> %off) nounwind {
+entry:
+;CHECK: pslld
+;CHECK: padd
+ %A2 = getelementptr <4 x i32*> %param, <4 x i32> %off
+ %k = extractelement <4 x i32*> %A2, i32 3
+ %v = load i32* %k
+ ret i32 %v
+;CHECK: ret
+}
+
+;CHECK: AGEP3
+define <4 x i32*> @AGEP3(<4 x i32*> %param, <4 x i32> %off) nounwind {
+entry:
+;CHECK: pslld
+;CHECK: padd
+ %A2 = getelementptr <4 x i32*> %param, <4 x i32> %off
+ %v = alloca i32
+ %k = insertelement <4 x i32*> %A2, i32* %v, i32 3
+ ret <4 x i32*> %k
+;CHECK: ret
+}
+
+;CHECK: AGEP4
+define <4 x i8*> @AGEP4(<4 x i8*> %param, <4 x i32> %off) nounwind {
+entry:
+;CHECK: pslld
+;CHECK: padd
+ %A = getelementptr <4 x i8*> %param, <4 x i32> %off
+ ret <4 x i8*> %A
+;CHECK: ret
+}
+
+;CHECK: AGEP5
+define <4 x i8*> @AGEP5(<4 x i8*> %param, <4 x i8> %off) nounwind {
+entry:
+;CHECK: pslld
+;CHECK: padd
+ %A = getelementptr <4 x i8*> %param, <4 x i8> %off
+ ret <4 x i8*> %A
+;CHECK: ret
+}
+
+
diff --git a/test/Feature/const_pv.ll b/test/Feature/const_pv.ll
new file mode 100644
index 0000000000..6fd6abdccf
--- /dev/null
+++ b/test/Feature/const_pv.ll
@@ -0,0 +1,8 @@
+; RUN: llvm-as %s -disable-output
+@G = constant <3 x i64> ptrtoint (<3 x i8*> <i8* null, i8* null, i8* null> to <3 x i64>)
+
+@G1 = global i8 zeroinitializer
+@g = constant <2 x i8*> getelementptr (<2 x i8*> <i8* @G1, i8* @G1>, <2 x i32> <i32 0, i32 0>)
+
+@t = constant <2 x i1> icmp ((<2 x i32> ptrtoint (<2 x i8*> zeroinitializer to <2 x i32>), <2 x i32> zeroinitializer )
+
diff --git a/test/Feature/global_pv.ll b/test/Feature/global_pv.ll
new file mode 100644
index 0000000000..d257ec077a
--- /dev/null
+++ b/test/Feature/global_pv.ll
@@ -0,0 +1,14 @@
+; RUN: opt -instcombine -S -o - %s | llvm-as
+; RUN: opt -instcombine -globalopt -S -o - %s | llvm-as
+@G1 = global i32 zeroinitializer
+@G2 = global i32 zeroinitializer
+@g = global <2 x i32*> zeroinitializer
+%0 = type { i32, void ()* }
+@llvm.global_ctors = appending global [1 x %0] [%0 { i32 65535, void ()* @test }]
+define internal void @test() {
+ %A = insertelement <2 x i32*> undef, i32* @G1, i32 0
+ %B = insertelement <2 x i32*> %A, i32* @G2, i32 1
+ store <2 x i32*> %B, <2 x i32*>* @g
+ ret void
+}
+
diff --git a/test/Transforms/InstCombine/vector_gep1.ll b/test/Transforms/InstCombine/vector_gep1.ll
new file mode 100644
index 0000000000..6523622995
--- /dev/null
+++ b/test/Transforms/InstCombine/vector_gep1.ll
@@ -0,0 +1,37 @@
+; RUN: opt -instcombine %s -disable-output
+; RUN: opt -instsimplify %s -disable-output
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@G1 = global i8 zeroinitializer
+
+define <2 x i1> @test(<2 x i8*> %a, <2 x i8*> %b) {
+ %A = icmp eq <2 x i8*> %a, %b
+ ret <2 x i1> %A
+}
+
+define <2 x i1> @test2(<2 x i8*> %a) {
+ %A = inttoptr <2 x i32> <i32 1, i32 2> to <2 x i8*>
+ %B = icmp ult <2 x i8*> %A, zeroinitializer
+ ret <2 x i1> %B
+}
+
+define <2 x i1> @test3(<2 x i8*> %a) {
+ %g = getelementptr <2 x i8*> %a, <2 x i32> <i32 1, i32 0>
+ %B = icmp ult <2 x i8*> %g, zeroinitializer
+ ret <2 x i1> %B
+}
+
+define <1 x i1> @test4(<1 x i8*> %a) {
+ %g = getelementptr <1 x i8*> %a, <1 x i32> <i32 1>
+ %B = icmp ult <1 x i8*> %g, zeroinitializer
+ ret <1 x i1> %B
+}
+
+define <2 x i1> @test5(<2 x i8*> %a) {
+ %w = getelementptr <2 x i8*> %a, <2 x i32> zeroinitializer
+ %e = getelementptr <2 x i8*> %w, <2 x i32> <i32 5, i32 9>
+ %g = getelementptr <2 x i8*> %e, <2 x i32> <i32 1, i32 0>
+ %B = icmp ult <2 x i8*> %g, zeroinitializer
+ ret <2 x i1> %B
+}
diff --git a/test/Transforms/InstSimplify/vector_gep.ll b/test/Transforms/InstSimplify/vector_gep.ll
new file mode 100644
index 0000000000..f65260e00f
--- /dev/null
+++ b/test/Transforms/InstSimplify/vector_gep.ll
@@ -0,0 +1,8 @@
+;RUN: opt -instsimplify %s -disable-output
+declare void @helper(<2 x i8*>)
+define void @test(<2 x i8*> %a) {
+ %A = getelementptr <2 x i8*> %a, <2 x i32> <i32 0, i32 0>
+ call void @helper(<2 x i8*> %A)
+ ret void
+}
+
diff --git a/unittests/VMCore/InstructionsTest.cpp b/unittests/VMCore/InstructionsTest.cpp
index f0197bb671..218a9a08c4 100644
--- a/unittests/VMCore/InstructionsTest.cpp
+++ b/unittests/VMCore/InstructionsTest.cpp
@@ -13,6 +13,8 @@
#include "llvm/DerivedTypes.h"
#include "llvm/LLVMContext.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/Analysis/ValueTracking.h"
+#include "llvm/Target/TargetData.h"
#include "gtest/gtest.h"
namespace llvm {
@@ -129,5 +131,100 @@ TEST(InstructionsTest, CastInst) {
EXPECT_EQ(CastInst::SExt, CastInst::getCastOpcode(c8, true, V8x64Ty, true));
}
+
+
+TEST(InstructionsTest, VectorGep) {
+ LLVMContext &C(getGlobalContext());
+
+ // Type Definitions
+ PointerType *Ptri8Ty = PointerType::get(IntegerType::get(C, 8), 0);
+ PointerType *Ptri32Ty = PointerType::get(IntegerType::get(C, 8), 0);
+
+ VectorType *V2xi8PTy = VectorType::get(Ptri8Ty, 2);
+ VectorType *V2xi32PTy = VectorType::get(Ptri32Ty, 2);
+
+ // Test different aspects of the vector-of-pointers type
+ // and GEPs which use this type.
+ ConstantInt *Ci32a = ConstantInt::get(C, APInt(32, 1492));
+ ConstantInt *Ci32b = ConstantInt::get(C, APInt(32, 1948));
+ std::vector<Constant*> ConstVa(2, Ci32a);
+ std::vector<Constant*> ConstVb(2, Ci32b);
+ Constant *C2xi32a = ConstantVector::get(ConstVa);
+ Constant *C2xi32b = ConstantVector::get(ConstVb);
+
+ CastInst *PtrVecA = new IntToPtrInst(C2xi32a, V2xi32PTy);
+ CastInst *PtrVecB = new IntToPtrInst(C2xi32b, V2xi32PTy);
+
+ ICmpInst *ICmp0 = new ICmpInst(ICmpInst::ICMP_SGT, PtrVecA, PtrVecB);
+ ICmpInst *ICmp1 = new ICmpInst(ICmpInst::ICMP_ULT, PtrVecA, PtrVecB);
+ EXPECT_NE(ICmp0, ICmp1); // suppress warning.
+
+ GetElementPtrInst *Gep0 = GetElementPtrInst::Create(PtrVecA, C2xi32a);
+ GetElementPtrInst *Gep1 = GetElementPtrInst::Create(PtrVecA, C2xi32b);
+ GetElementPtrInst *Gep2 = GetElementPtrInst::Create(PtrVecB, C2xi32a);
+ GetElementPtrInst *Gep3 = GetElementPtrInst::Create(PtrVecB, C2xi32b);
+
+ CastInst *BTC0 = new BitCastInst(Gep0, V2xi8PTy);
+ CastInst *BTC1 = new BitCastInst(Gep1, V2xi8PTy);
+ CastInst *BTC2 = new BitCastInst(Gep2, V2xi8PTy);
+ CastInst *BTC3 = new BitCastInst(Gep3, V2xi8PTy);
+
+ Value *S0 = BTC0->stripPointerCasts();
+ Value *S1 = BTC1->stripPointerCasts();
+ Value *S2 = BTC2->stripPointerCasts();
+ Value *S3 = BTC3->stripPointerCasts();
+
+ EXPECT_NE(S0, Gep0);
+ EXPECT_NE(S1, Gep1);
+ EXPECT_NE(S2, Gep2);
+ EXPECT_NE(S3, Gep3);
+
+ int64_t Offset;
+ TargetData TD("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3"
+ "2:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80"
+ ":128:128-n8:16:32:64-S128");
+ // Make sure we don't crash
+ GetPointerBaseWithConstantOffset(Gep0, Offset, TD);
+ GetPointerBaseWithConstantOffset(Gep1, Offset, TD);
+ GetPointerBaseWithConstantOffset(Gep2, Offset, TD);
+ GetPointerBaseWithConstantOffset(Gep3, Offset, TD);
+
+ // Gep of Geps
+ GetElementPtrInst *GepII0 = GetElementPtrInst::Create(Gep0, C2xi32b);
+ GetElementPtrInst *GepII1 = GetElementPtrInst::Create(Gep1, C2xi32a);
+ GetElementPtrInst *GepII2 = GetElementPtrInst::Create(Gep2, C2xi32b);
+ GetElementPtrInst *GepII3 = GetElementPtrInst::Create(Gep3, C2xi32a);
+
+ EXPECT_EQ(GepII0->getNumIndices(), 1u);
+ EXPECT_EQ(GepII1->getNumIndices(), 1u);
+ EXPECT_EQ(GepII2->getNumIndices(), 1u);
+ EXPECT_EQ(GepII3->getNumIndices(), 1u);
+
+ EXPECT_FALSE(GepII0->hasAllZeroIndices());
+ EXPECT_FALSE(GepII1->hasAllZeroIndices());
+ EXPECT_FALSE(GepII2->hasAllZeroIndices());
+ EXPECT_FALSE(GepII3->hasAllZeroIndices());
+
+ delete GepII0;
+ delete GepII1;
+ delete GepII2;
+ delete GepII3;
+
+ delete BTC0;
+ delete BTC1;
+ delete BTC2;
+ delete BTC3;
+
+ delete Gep0;
+ delete Gep1;
+ delete Gep2;
+ delete Gep3;
+
+ delete ICmp0;
+ delete ICmp1;
+ delete PtrVecA;
+ delete PtrVecB;
+}
+
} // end anonymous namespace
} // end namespace llvm