Add support for vectors of pointers.

llvm-svn: 145801
This commit is contained in:
Nadav Rotem 2011-12-05 06:29:09 +00:00
parent 770142e49f
commit 3924cb0267
26 changed files with 631 additions and 71 deletions

View File

@ -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

View File

@ -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();
}

View File

@ -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");
}

View File

@ -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

View File

@ -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

View File

@ -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.
//

View File

@ -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());

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -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(),

View File

@ -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();

View File

@ -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()) {

View File

@ -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)

View File

@ -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.

View File

@ -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);
}

View File

@ -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.

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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 )

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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