Skip to content

Commit

Permalink
IR: Change the gep_type_iterator API to avoid always exposing the "cu…
Browse files Browse the repository at this point in the history
…rrent" type.

Instead, expose whether the current type is an array or a struct, if an array
what the upper bound is, and if a struct the struct type itself. This is
in preparation for a later change which will make PointerType derive from
Type rather than SequentialType.

Differential Revision: https://reviews.llvm.org/D26594

llvm-svn: 288458
  • Loading branch information
pcc committed Dec 2, 2016
1 parent 6afcab3 commit ab85225
Show file tree
Hide file tree
Showing 31 changed files with 141 additions and 144 deletions.
24 changes: 12 additions & 12 deletions llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -482,18 +482,20 @@ class TargetTransformInfoImplCRTPBase : public TargetTransformInfoImplBase {
int64_t BaseOffset = 0;
int64_t Scale = 0;

// Assumes the address space is 0 when Ptr is nullptr.
unsigned AS =
(Ptr == nullptr ? 0 : Ptr->getType()->getPointerAddressSpace());
auto GTI = gep_type_begin(PointeeType, AS, Operands);
auto GTI = gep_type_begin(PointeeType, Operands);
for (auto I = Operands.begin(); I != Operands.end(); ++I, ++GTI) {
// We assume that the cost of Scalar GEP with constant index and the
// cost of Vector GEP with splat constant index are the same.
const ConstantInt *ConstIdx = dyn_cast<ConstantInt>(*I);
if (!ConstIdx)
if (auto Splat = getSplatValue(*I))
ConstIdx = dyn_cast<ConstantInt>(Splat);
if (isa<SequentialType>(*GTI)) {
if (StructType *STy = GTI.getStructTypeOrNull()) {
// For structures the index is always splat or scalar constant
assert(ConstIdx && "Unexpected GEP index");
uint64_t Field = ConstIdx->getZExtValue();
BaseOffset += DL.getStructLayout(STy)->getElementOffset(Field);
} else {
int64_t ElementSize = DL.getTypeAllocSize(GTI.getIndexedType());
if (ConstIdx)
BaseOffset += ConstIdx->getSExtValue() * ElementSize;
Expand All @@ -504,17 +506,15 @@ class TargetTransformInfoImplCRTPBase : public TargetTransformInfoImplBase {
return TTI::TCC_Basic;
Scale = ElementSize;
}
} else {
StructType *STy = cast<StructType>(*GTI);
// For structures the index is always splat or scalar constant
assert(ConstIdx && "Unexpected GEP index");
uint64_t Field = ConstIdx->getZExtValue();
BaseOffset += DL.getStructLayout(STy)->getElementOffset(Field);
}
}

// Assumes the address space is 0 when Ptr is nullptr.
unsigned AS =
(Ptr == nullptr ? 0 : Ptr->getType()->getPointerAddressSpace());
if (static_cast<T *>(this)->isLegalAddressingMode(
PointerType::get(*GTI, AS), const_cast<GlobalValue *>(BaseGV),
PointerType::get(Type::getInt8Ty(PointeeType->getContext()), AS),
const_cast<GlobalValue *>(BaseGV),
BaseOffset, HasBaseReg, Scale, AS)) {
return TTI::TCC_Free;
}
Expand Down
96 changes: 58 additions & 38 deletions llvm/include/llvm/IR/GetElementPtrTypeIterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#define LLVM_IR_GETELEMENTPTRTYPEITERATOR_H

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/User.h"
Expand All @@ -33,18 +33,15 @@ namespace llvm {
Type *, ptrdiff_t> super;

ItTy OpIt;
PointerIntPair<Type *, 1> CurTy;
unsigned AddrSpace;

PointerUnion<StructType *, Type *> CurTy;
enum { Unbounded = -1ull };
uint64_t NumElements = Unbounded;
generic_gep_type_iterator() = default;

public:
static generic_gep_type_iterator begin(Type *Ty, unsigned AddrSpace,
ItTy It) {
static generic_gep_type_iterator begin(Type *Ty, ItTy It) {
generic_gep_type_iterator I;
I.CurTy.setPointer(Ty);
I.CurTy.setInt(true);
I.AddrSpace = AddrSpace;
I.CurTy = Ty;
I.OpIt = It;
return I;
}
Expand All @@ -63,41 +60,68 @@ namespace llvm {
return !operator==(x);
}

Type *operator*() const {
if (CurTy.getInt())
return CurTy.getPointer()->getPointerTo(AddrSpace);
return CurTy.getPointer();
}

// FIXME: Make this the iterator's operator*() after the 4.0 release.
// operator*() had a different meaning in earlier releases, so we're
// temporarily not giving this iterator an operator*() to avoid a subtle
// semantics break.
Type *getIndexedType() const {
if (CurTy.getInt())
return CurTy.getPointer();
CompositeType *CT = cast<CompositeType>(CurTy.getPointer());
return CT->getTypeAtIndex(getOperand());
if (auto *T = CurTy.dyn_cast<Type *>())
return T;
return CurTy.get<StructType *>()->getTypeAtIndex(getOperand());
}

// This is a non-standard operator->. It allows you to call methods on the
// current type directly.
Type *operator->() const { return operator*(); }

Value *getOperand() const { return const_cast<Value *>(&**OpIt); }

generic_gep_type_iterator& operator++() { // Preincrement
if (CurTy.getInt()) {
CurTy.setInt(false);
} else if (CompositeType *CT =
dyn_cast<CompositeType>(CurTy.getPointer())) {
CurTy.setPointer(CT->getTypeAtIndex(getOperand()));
} else {
CurTy.setPointer(nullptr);
}
Type *Ty = getIndexedType();
if (auto *ATy = dyn_cast<ArrayType>(Ty)) {
CurTy = ATy->getElementType();
NumElements = ATy->getNumElements();
} else if (auto *VTy = dyn_cast<VectorType>(Ty)) {
CurTy = VTy->getElementType();
NumElements = VTy->getNumElements();
} else
CurTy = dyn_cast<StructType>(Ty);
++OpIt;
return *this;
}

generic_gep_type_iterator operator++(int) { // Postincrement
generic_gep_type_iterator tmp = *this; ++*this; return tmp;
}

// All of the below API is for querying properties of the "outer type", i.e.
// the type that contains the indexed type. Most of the time this is just
// the type that was visited immediately prior to the indexed type, but for
// the first element this is an unbounded array of the GEP's source element
// type, for which there is no clearly corresponding IR type (we've
// historically used a pointer type as the outer type in this case, but
// pointers will soon lose their element type).
//
// FIXME: Most current users of this class are just interested in byte
// offsets (a few need to know whether the outer type is a struct because
// they are trying to replace a constant with a variable, which is only
// legal for arrays, e.g. canReplaceOperandWithVariable in SimplifyCFG.cpp);
// we should provide a more minimal API here that exposes not much more than
// that.

bool isStruct() const { return CurTy.is<StructType *>(); }
bool isSequential() const { return CurTy.is<Type *>(); }

StructType *getStructType() const { return CurTy.get<StructType *>(); }

StructType *getStructTypeOrNull() const {
return CurTy.dyn_cast<StructType *>();
}

bool isBoundedSequential() const {
return isSequential() && NumElements != Unbounded;
}

uint64_t getSequentialNumElements() const {
assert(isBoundedSequential());
return NumElements;
}
};

typedef generic_gep_type_iterator<> gep_type_iterator;
Expand All @@ -106,8 +130,6 @@ namespace llvm {
auto *GEPOp = cast<GEPOperator>(GEP);
return gep_type_iterator::begin(
GEPOp->getSourceElementType(),
cast<PointerType>(GEPOp->getPointerOperandType()->getScalarType())
->getAddressSpace(),
GEP->op_begin() + 1);
}

Expand All @@ -119,8 +141,6 @@ namespace llvm {
auto &GEPOp = cast<GEPOperator>(GEP);
return gep_type_iterator::begin(
GEPOp.getSourceElementType(),
cast<PointerType>(GEPOp.getPointerOperandType()->getScalarType())
->getAddressSpace(),
GEP.op_begin() + 1);
}

Expand All @@ -130,13 +150,13 @@ namespace llvm {

template<typename T>
inline generic_gep_type_iterator<const T *>
gep_type_begin(Type *Op0, unsigned AS, ArrayRef<T> A) {
return generic_gep_type_iterator<const T *>::begin(Op0, AS, A.begin());
gep_type_begin(Type *Op0, ArrayRef<T> A) {
return generic_gep_type_iterator<const T *>::begin(Op0, A.begin());
}

template<typename T>
inline generic_gep_type_iterator<const T *>
gep_type_end(Type * /*Op0*/, unsigned /*AS*/, ArrayRef<T> A) {
gep_type_end(Type * /*Op0*/, ArrayRef<T> A) {
return generic_gep_type_iterator<const T *>::end(A.end());
}

Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/Transforms/Utils/Local.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &DL, User *GEP,
continue;

// Handle a struct index, which adds its field offset to the pointer.
if (StructType *STy = dyn_cast<StructType>(*GTI)) {
if (StructType *STy = GTI.getStructTypeOrNull()) {
if (OpC->getType()->isVectorTy())
OpC = OpC->getSplatValue();

Expand Down
8 changes: 4 additions & 4 deletions llvm/lib/Analysis/BasicAliasAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -412,10 +412,10 @@ bool BasicAAResult::DecomposeGEPExpression(const Value *V,
// Assume all GEP operands are constants until proven otherwise.
bool GepHasConstantOffset = true;
for (User::const_op_iterator I = GEPOp->op_begin() + 1, E = GEPOp->op_end();
I != E; ++I) {
I != E; ++I, ++GTI) {
const Value *Index = *I;
// Compute the (potentially symbolic) offset in bytes for this index.
if (StructType *STy = dyn_cast<StructType>(*GTI++)) {
if (StructType *STy = GTI.getStructTypeOrNull()) {
// For a struct, add the member offset.
unsigned FieldNo = cast<ConstantInt>(Index)->getZExtValue();
if (FieldNo == 0)
Expand All @@ -431,13 +431,13 @@ bool BasicAAResult::DecomposeGEPExpression(const Value *V,
if (CIdx->isZero())
continue;
Decomposed.OtherOffset +=
DL.getTypeAllocSize(*GTI) * CIdx->getSExtValue();
DL.getTypeAllocSize(GTI.getIndexedType()) * CIdx->getSExtValue();
continue;
}

GepHasConstantOffset = false;

uint64_t Scale = DL.getTypeAllocSize(*GTI);
uint64_t Scale = DL.getTypeAllocSize(GTI.getIndexedType());
unsigned ZExtBits = 0, SExtBits = 0;

// If the integer type is smaller than the pointer size, it is implicitly
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Analysis/InlineCost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ bool CallAnalyzer::accumulateGEPOffset(GEPOperator &GEP, APInt &Offset) {
continue;

// Handle a struct index, which adds its field offset to the pointer.
if (StructType *STy = dyn_cast<StructType>(*GTI)) {
if (StructType *STy = GTI.getStructTypeOrNull()) {
unsigned ElementIdx = OpC->getZExtValue();
const StructLayout *SL = DL.getStructLayout(STy);
Offset += APInt(IntPtrWidth, SL->getElementOffset(ElementIdx));
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1231,7 +1231,7 @@ static void computeKnownBitsFromOperator(const Operator *I, APInt &KnownZero,
gep_type_iterator GTI = gep_type_begin(I);
for (unsigned i = 1, e = I->getNumOperands(); i != e; ++i, ++GTI) {
Value *Index = I->getOperand(i);
if (StructType *STy = dyn_cast<StructType>(*GTI)) {
if (StructType *STy = GTI.getStructTypeOrNull()) {
// Handle struct member offset arithmetic.

// Handle case when index is vector zeroinitializer
Expand Down Expand Up @@ -1730,7 +1730,7 @@ static bool isGEPKnownNonNull(const GEPOperator *GEP, unsigned Depth,
for (gep_type_iterator GTI = gep_type_begin(GEP), GTE = gep_type_end(GEP);
GTI != GTE; ++GTI) {
// Struct types are easy -- they must always be indexed by a constant.
if (StructType *STy = dyn_cast<StructType>(*GTI)) {
if (StructType *STy = GTI.getStructTypeOrNull()) {
ConstantInt *OpC = cast<ConstantInt>(GTI.getOperand());
unsigned ElementIdx = OpC->getZExtValue();
const StructLayout *SL = Q.DL.getStructLayout(STy);
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Analysis/VectorUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,11 @@ unsigned llvm::getGEPInductionOperand(const GetElementPtrInst *Gep) {
while (LastOperand > 1 && match(Gep->getOperand(LastOperand), m_Zero())) {
// Find the type we're currently indexing into.
gep_type_iterator GEPTI = gep_type_begin(Gep);
std::advance(GEPTI, LastOperand - 1);
std::advance(GEPTI, LastOperand - 2);

// If it's a type with the same allocation size as the result of the GEP we
// can peel off the zero index.
if (DL.getTypeAllocSize(*GEPTI) != GEPAllocSize)
if (DL.getTypeAllocSize(GEPTI.getIndexedType()) != GEPAllocSize)
break;
--LastOperand;
}
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/CodeGenPrepare.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3261,7 +3261,7 @@ bool AddressingModeMatcher::matchOperationAddr(User *AddrInst, unsigned Opcode,
int64_t ConstantOffset = 0;
gep_type_iterator GTI = gep_type_begin(AddrInst);
for (unsigned i = 1, e = AddrInst->getNumOperands(); i != e; ++i, ++GTI) {
if (StructType *STy = dyn_cast<StructType>(*GTI)) {
if (StructType *STy = GTI.getStructTypeOrNull()) {
const StructLayout *SL = DL.getStructLayout(STy);
unsigned Idx =
cast<ConstantInt>(AddrInst->getOperand(i))->getZExtValue();
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ bool FastISel::selectGetElementPtr(const User *I) {
for (gep_type_iterator GTI = gep_type_begin(I), E = gep_type_end(I);
GTI != E; ++GTI) {
const Value *Idx = GTI.getOperand();
if (auto *StTy = dyn_cast<StructType>(*GTI)) {
if (StructType *StTy = GTI.getStructTypeOrNull()) {
uint64_t Field = cast<ConstantInt>(Idx)->getZExtValue();
if (Field) {
// N = N + Offset
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3274,7 +3274,7 @@ void SelectionDAGBuilder::visitGetElementPtr(const User &I) {
for (gep_type_iterator GTI = gep_type_begin(&I), E = gep_type_end(&I);
GTI != E; ++GTI) {
const Value *Idx = GTI.getOperand();
if (StructType *StTy = dyn_cast<StructType>(*GTI)) {
if (StructType *StTy = GTI.getStructTypeOrNull()) {
unsigned Field = cast<Constant>(Idx)->getUniqueInteger().getZExtValue();
if (Field) {
// N = N + Offset
Expand Down
5 changes: 2 additions & 3 deletions llvm/lib/ExecutionEngine/Interpreter/Execution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -999,15 +999,14 @@ GenericValue Interpreter::executeGEPOperation(Value *Ptr, gep_type_iterator I,
uint64_t Total = 0;

for (; I != E; ++I) {
if (StructType *STy = dyn_cast<StructType>(*I)) {
if (StructType *STy = I.getStructTypeOrNull()) {
const StructLayout *SLO = getDataLayout().getStructLayout(STy);

const ConstantInt *CPU = cast<ConstantInt>(I.getOperand());
unsigned Index = unsigned(CPU->getZExtValue());

Total += SLO->getElementOffset(Index);
} else {
SequentialType *ST = cast<SequentialType>(*I);
// Get the index number for the array... which must be long type...
GenericValue IdxGV = getOperandValue(I.getOperand(), SF);

Expand All @@ -1020,7 +1019,7 @@ GenericValue Interpreter::executeGEPOperation(Value *Ptr, gep_type_iterator I,
assert(BitWidth == 64 && "Invalid index type for getelementptr");
Idx = (int64_t)IdxGV.IntVal.getZExtValue();
}
Total += getDataLayout().getTypeAllocSize(ST->getElementType()) * Idx;
Total += getDataLayout().getTypeAllocSize(I.getIndexedType()) * Idx;
}
}

Expand Down
Loading

0 comments on commit ab85225

Please sign in to comment.