mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-05-13 01:15:32 +00:00
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:
parent
e060eb8916
commit
84dfc32ff9
@ -263,14 +263,32 @@ public:
|
|||||||
return true; // Values are always values.
|
return true; // Values are always values.
|
||||||
}
|
}
|
||||||
|
|
||||||
/// stripPointerCasts - This method strips off any unneeded pointer
|
/// stripPointerCasts - This method strips off any unneeded pointer casts and
|
||||||
/// casts from the specified value, returning the original uncasted value.
|
/// all-zero GEPs from the specified value, returning the original uncasted
|
||||||
/// Note that the returned value has pointer type if the specified value does.
|
/// value. If this is called on a non-pointer value, it returns 'this'.
|
||||||
Value *stripPointerCasts();
|
Value *stripPointerCasts();
|
||||||
const Value *stripPointerCasts() const {
|
const Value *stripPointerCasts() const {
|
||||||
return const_cast<Value*>(this)->stripPointerCasts();
|
return const_cast<Value*>(this)->stripPointerCasts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// stripConstantOffsets - This method strips off unneeded pointer casts and
|
||||||
|
/// all-constant GEPs from the specified value, returning the original
|
||||||
|
/// pointer value. If this is called on a non-pointer value, it returns
|
||||||
|
/// 'this'.
|
||||||
|
Value *stripConstantOffsets();
|
||||||
|
const Value *stripConstantOffsets() const {
|
||||||
|
return const_cast<Value*>(this)->stripConstantOffsets();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// stripInBoundsOffsets - This method strips off unneeded pointer casts and
|
||||||
|
/// any in-bounds Offsets from the specified value, returning the original
|
||||||
|
/// pointer value. If this is called on a non-pointer value, it returns
|
||||||
|
/// 'this'.
|
||||||
|
Value *stripInBoundsOffsets();
|
||||||
|
const Value *stripInBoundsOffsets() const {
|
||||||
|
return const_cast<Value*>(this)->stripInBoundsOffsets();
|
||||||
|
}
|
||||||
|
|
||||||
/// isDereferenceablePointer - Test if this value is always a pointer to
|
/// isDereferenceablePointer - Test if this value is always a pointer to
|
||||||
/// allocated and suitably aligned memory for a simple load or store.
|
/// allocated and suitably aligned memory for a simple load or store.
|
||||||
bool isDereferenceablePointer() const;
|
bool isDereferenceablePointer() const;
|
||||||
|
@ -1522,28 +1522,6 @@ static Value *ExtractEquivalentCondition(Value *V, CmpInst::Predicate Pred,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// stripPointerAdjustments - This is like Value::stripPointerCasts, but also
|
|
||||||
/// removes inbounds gep operations, regardless of their indices.
|
|
||||||
static Value *stripPointerAdjustmentsImpl(Value *V,
|
|
||||||
SmallPtrSet<GEPOperator*, 8> &VisitedGEPs) {
|
|
||||||
GEPOperator *GEP = dyn_cast<GEPOperator>(V);
|
|
||||||
if (GEP == 0 || !GEP->isInBounds())
|
|
||||||
return V;
|
|
||||||
|
|
||||||
// If we've already seen this GEP, we will end up infinitely looping. This
|
|
||||||
// can happen in unreachable code.
|
|
||||||
if (!VisitedGEPs.insert(GEP))
|
|
||||||
return V;
|
|
||||||
|
|
||||||
return stripPointerAdjustmentsImpl(GEP->getOperand(0)->stripPointerCasts(),
|
|
||||||
VisitedGEPs);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Value *stripPointerAdjustments(Value *V) {
|
|
||||||
SmallPtrSet<GEPOperator*, 8> VisitedGEPs;
|
|
||||||
return stripPointerAdjustmentsImpl(V, VisitedGEPs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
|
/// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
|
||||||
/// fold the result. If not, this returns null.
|
/// fold the result. If not, this returns null.
|
||||||
@ -1625,9 +1603,9 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
|
|||||||
// Be more aggressive about stripping pointer adjustments when checking a
|
// Be more aggressive about stripping pointer adjustments when checking a
|
||||||
// comparison of an alloca address to another object. We can rip off all
|
// comparison of an alloca address to another object. We can rip off all
|
||||||
// inbounds GEP operations, even if they are variable.
|
// inbounds GEP operations, even if they are variable.
|
||||||
LHSPtr = stripPointerAdjustments(LHSPtr);
|
LHSPtr = LHSPtr->stripInBoundsOffsets();
|
||||||
if (llvm::isIdentifiedObject(LHSPtr)) {
|
if (llvm::isIdentifiedObject(LHSPtr)) {
|
||||||
RHSPtr = stripPointerAdjustments(RHSPtr);
|
RHSPtr = RHSPtr->stripInBoundsOffsets();
|
||||||
if (llvm::isKnownNonNull(LHSPtr) || llvm::isKnownNonNull(RHSPtr)) {
|
if (llvm::isKnownNonNull(LHSPtr) || llvm::isKnownNonNull(RHSPtr)) {
|
||||||
// If both sides are different identified objects, they aren't equal
|
// If both sides are different identified objects, they aren't equal
|
||||||
// unless they're null.
|
// unless they're null.
|
||||||
@ -1644,7 +1622,7 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
|
|||||||
if (llvm::isKnownNonNull(LHSPtr) && isa<ConstantPointerNull>(RHSPtr))
|
if (llvm::isKnownNonNull(LHSPtr) && isa<ConstantPointerNull>(RHSPtr))
|
||||||
return ConstantInt::get(ITy, CmpInst::isFalseWhenEqual(Pred));
|
return ConstantInt::get(ITy, CmpInst::isFalseWhenEqual(Pred));
|
||||||
} else if (isa<Argument>(LHSPtr)) {
|
} else if (isa<Argument>(LHSPtr)) {
|
||||||
RHSPtr = stripPointerAdjustments(RHSPtr);
|
RHSPtr = RHSPtr->stripInBoundsOffsets();
|
||||||
// An alloca can't be equal to an argument.
|
// An alloca can't be equal to an argument.
|
||||||
if (isa<AllocaInst>(RHSPtr))
|
if (isa<AllocaInst>(RHSPtr))
|
||||||
return ConstantInt::get(ITy, CmpInst::isFalseWhenEqual(Pred));
|
return ConstantInt::get(ITy, CmpInst::isFalseWhenEqual(Pred));
|
||||||
|
@ -317,20 +317,43 @@ void Value::replaceAllUsesWith(Value *New) {
|
|||||||
BB->replaceSuccessorsPhiUsesWith(cast<BasicBlock>(New));
|
BB->replaceSuccessorsPhiUsesWith(cast<BasicBlock>(New));
|
||||||
}
|
}
|
||||||
|
|
||||||
Value *Value::stripPointerCasts() {
|
namespace {
|
||||||
if (!getType()->isPointerTy())
|
// Various metrics for how much to strip off of pointers.
|
||||||
return this;
|
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
|
// 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.
|
// instruction in an unreachable block, which may be on a cycle.
|
||||||
SmallPtrSet<Value *, 4> Visited;
|
SmallPtrSet<Value *, 4> Visited;
|
||||||
|
|
||||||
Value *V = this;
|
|
||||||
Visited.insert(V);
|
Visited.insert(V);
|
||||||
do {
|
do {
|
||||||
if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
|
if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
|
||||||
if (!GEP->hasAllZeroIndices())
|
switch (StripKind) {
|
||||||
return V;
|
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();
|
V = GEP->getPointerOperand();
|
||||||
} else if (Operator::getOpcode(V) == Instruction::BitCast) {
|
} else if (Operator::getOpcode(V) == Instruction::BitCast) {
|
||||||
V = cast<Operator>(V)->getOperand(0);
|
V = cast<Operator>(V)->getOperand(0);
|
||||||
@ -346,6 +369,19 @@ Value *Value::stripPointerCasts() {
|
|||||||
|
|
||||||
return V;
|
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
|
/// isDereferenceablePointer - Test if this value is always a pointer to
|
||||||
/// allocated and suitably aligned memory for a simple load or store.
|
/// allocated and suitably aligned memory for a simple load or store.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user