forked from OSchip/llvm-project
parent
770142e49f
commit
3924cb0267
|
@ -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><2 x i64></tt></td>
|
||||
<td class="left">Vector of 2 64-bit integer values.</td>
|
||||
</tr>
|
||||
<tr class="layout">
|
||||
<td class="left"><tt><4 x i64*></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>
|
||||
<result> = getelementptr <pty>* <ptrval>{, <ty> <idx>}*
|
||||
<result> = getelementptr inbounds <pty>* <ptrval>{, <ty> <idx>}*
|
||||
<result> = getelementptr <ptr vector> ptrval, <vector index type> 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 <4 x i32*> %P to <4 x i64><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 <4 x i32> %G to <4 x i8*><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 <2 x int> %V to i64; <i>; yields i64: %V</i>
|
||||
%Z = bitcast <2 x int> %V to i64; <i>; yields i64: %V</i>
|
||||
%Z = bitcast <2 x i32*> %V to <2 x i64*> <i>; yields <2 x i64*></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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
//
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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()) {
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
@ -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 )
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue