Refactor some methods to look through bitcasts and GEPs on pointers into

a common collection of methods on Value, and share their implementation.
We had two variations in two different places already, and I need the
third variation for inline cost estimation.

Reviewed by Duncan Sands on IRC, but further comments here welcome.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152490 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chandler Carruth
2012-03-10 08:39:09 +00:00
parent e060eb8916
commit 84dfc32ff9
3 changed files with 66 additions and 34 deletions

View File

@@ -317,20 +317,43 @@ void Value::replaceAllUsesWith(Value *New) {
BB->replaceSuccessorsPhiUsesWith(cast<BasicBlock>(New));
}
Value *Value::stripPointerCasts() {
if (!getType()->isPointerTy())
return this;
namespace {
// Various metrics for how much to strip off of pointers.
enum PointerStripKind {
PSK_ZeroIndices,
PSK_ConstantIndices,
PSK_InBounds,
PSK_All
};
template <PointerStripKind StripKind>
static Value *stripPointerCastsAndOffsets(Value *V) {
if (!V->getType()->isPointerTy())
return V;
// Even though we don't look through PHI nodes, we could be called on an
// instruction in an unreachable block, which may be on a cycle.
SmallPtrSet<Value *, 4> Visited;
Value *V = this;
Visited.insert(V);
do {
if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
if (!GEP->hasAllZeroIndices())
return V;
switch (StripKind) {
case PSK_ZeroIndices:
if (!GEP->hasAllZeroIndices())
return V;
break;
case PSK_ConstantIndices:
if (!GEP->hasAllConstantIndices())
return V;
break;
case PSK_InBounds:
if (!GEP->isInBounds())
return V;
break;
case PSK_All:
break;
}
V = GEP->getPointerOperand();
} else if (Operator::getOpcode(V) == Instruction::BitCast) {
V = cast<Operator>(V)->getOperand(0);
@@ -346,6 +369,19 @@ Value *Value::stripPointerCasts() {
return V;
}
} // namespace
Value *Value::stripPointerCasts() {
return stripPointerCastsAndOffsets<PSK_ZeroIndices>(this);
}
Value *Value::stripConstantOffsets() {
return stripPointerCastsAndOffsets<PSK_ConstantIndices>(this);
}
Value *Value::stripInBoundsOffsets() {
return stripPointerCastsAndOffsets<PSK_InBounds>(this);
}
/// isDereferenceablePointer - Test if this value is always a pointer to
/// allocated and suitably aligned memory for a simple load or store.