forked from OSchip/llvm-project
Add a new helper method to Value to strip in-bounds constant offsets of
pointers, but accumulate the offset into an APInt in the process of stripping it. This is a pretty handy thing to have, such as when trying to determine if two pointers are at some constant relative offset. I'll be committing a patch shortly to use it for exactly that purpose. llvm-svn: 189000
This commit is contained in:
parent
774cf3190c
commit
989e630871
|
@ -22,26 +22,29 @@
|
|||
|
||||
namespace llvm {
|
||||
|
||||
class Constant;
|
||||
class APInt;
|
||||
class Argument;
|
||||
class Instruction;
|
||||
class AssemblyAnnotationWriter;
|
||||
class BasicBlock;
|
||||
class GlobalValue;
|
||||
class Constant;
|
||||
class DataLayout;
|
||||
class Function;
|
||||
class GlobalVariable;
|
||||
class GlobalAlias;
|
||||
class GlobalValue;
|
||||
class GlobalVariable;
|
||||
class InlineAsm;
|
||||
class Instruction;
|
||||
class LLVMContext;
|
||||
class MDNode;
|
||||
class StringRef;
|
||||
class Twine;
|
||||
class Type;
|
||||
class ValueHandleBase;
|
||||
class ValueSymbolTable;
|
||||
class raw_ostream;
|
||||
|
||||
template<typename ValueTy> class StringMapEntry;
|
||||
typedef StringMapEntry<Value*> ValueName;
|
||||
class raw_ostream;
|
||||
class AssemblyAnnotationWriter;
|
||||
class ValueHandleBase;
|
||||
class LLVMContext;
|
||||
class Twine;
|
||||
class MDNode;
|
||||
class Type;
|
||||
class StringRef;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Value Class
|
||||
|
@ -287,6 +290,22 @@ public:
|
|||
return const_cast<Value*>(this)->stripInBoundsConstantOffsets();
|
||||
}
|
||||
|
||||
/// \brief Strips like \c stripInBoundsConstantOffsets but also accumulates
|
||||
/// the constant offset stripped.
|
||||
///
|
||||
/// Stores the resulting constant offset stripped into the APInt provided.
|
||||
/// The provided APInt will be extended or truncated as needed to be the
|
||||
/// correct bitwidth for an offset of this pointer type.
|
||||
///
|
||||
/// If this is called on a non-pointer value, it returns 'this'.
|
||||
Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL,
|
||||
APInt &Offset);
|
||||
const Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL,
|
||||
APInt &Offset) const {
|
||||
return const_cast<Value *>(this)
|
||||
->stripAndAccumulateInBoundsConstantOffsets(DL, Offset);
|
||||
}
|
||||
|
||||
/// \brief Strips off unneeded pointer casts and any in-bounds offsets from
|
||||
/// the specified value, returning the original pointer value.
|
||||
///
|
||||
|
|
|
@ -393,6 +393,40 @@ Value *Value::stripInBoundsConstantOffsets() {
|
|||
return stripPointerCastsAndOffsets<PSK_InBoundsConstantIndices>(this);
|
||||
}
|
||||
|
||||
Value *Value::stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL,
|
||||
APInt &Offset) {
|
||||
if (!getType()->isPointerTy())
|
||||
return this;
|
||||
|
||||
assert(Offset.getBitWidth() == DL.getPointerSizeInBits(cast<PointerType>(
|
||||
getType())->getAddressSpace()) &&
|
||||
"The offset must have exactly as many bits as our pointer.");
|
||||
|
||||
// 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;
|
||||
Visited.insert(this);
|
||||
Value *V = this;
|
||||
do {
|
||||
if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
|
||||
if (!GEP->isInBounds())
|
||||
return V;
|
||||
if (!GEP->accumulateConstantOffset(DL, Offset))
|
||||
return V;
|
||||
V = GEP->getPointerOperand();
|
||||
} else if (Operator::getOpcode(V) == Instruction::BitCast) {
|
||||
V = cast<Operator>(V)->getOperand(0);
|
||||
} else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) {
|
||||
V = GA->getAliasee();
|
||||
} else {
|
||||
return V;
|
||||
}
|
||||
assert(V->getType()->isPointerTy() && "Unexpected operand type!");
|
||||
} while (Visited.insert(V));
|
||||
|
||||
return V;
|
||||
}
|
||||
|
||||
Value *Value::stripInBoundsOffsets() {
|
||||
return stripPointerCastsAndOffsets<PSK_InBounds>(this);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue