mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-05-20 20:38:48 +00:00
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@189000 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4efbeb2700
commit
f73826bef0
@ -22,26 +22,29 @@
|
|||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
class Constant;
|
class APInt;
|
||||||
class Argument;
|
class Argument;
|
||||||
class Instruction;
|
class AssemblyAnnotationWriter;
|
||||||
class BasicBlock;
|
class BasicBlock;
|
||||||
class GlobalValue;
|
class Constant;
|
||||||
|
class DataLayout;
|
||||||
class Function;
|
class Function;
|
||||||
class GlobalVariable;
|
|
||||||
class GlobalAlias;
|
class GlobalAlias;
|
||||||
|
class GlobalValue;
|
||||||
|
class GlobalVariable;
|
||||||
class InlineAsm;
|
class InlineAsm;
|
||||||
|
class Instruction;
|
||||||
|
class LLVMContext;
|
||||||
|
class MDNode;
|
||||||
|
class StringRef;
|
||||||
|
class Twine;
|
||||||
|
class Type;
|
||||||
|
class ValueHandleBase;
|
||||||
class ValueSymbolTable;
|
class ValueSymbolTable;
|
||||||
|
class raw_ostream;
|
||||||
|
|
||||||
template<typename ValueTy> class StringMapEntry;
|
template<typename ValueTy> class StringMapEntry;
|
||||||
typedef StringMapEntry<Value*> ValueName;
|
typedef StringMapEntry<Value*> ValueName;
|
||||||
class raw_ostream;
|
|
||||||
class AssemblyAnnotationWriter;
|
|
||||||
class ValueHandleBase;
|
|
||||||
class LLVMContext;
|
|
||||||
class Twine;
|
|
||||||
class MDNode;
|
|
||||||
class Type;
|
|
||||||
class StringRef;
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Value Class
|
// Value Class
|
||||||
@ -287,6 +290,22 @@ public:
|
|||||||
return const_cast<Value*>(this)->stripInBoundsConstantOffsets();
|
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
|
/// \brief Strips off unneeded pointer casts and any in-bounds offsets from
|
||||||
/// the specified value, returning the original pointer value.
|
/// the specified value, returning the original pointer value.
|
||||||
///
|
///
|
||||||
|
@ -393,6 +393,40 @@ Value *Value::stripInBoundsConstantOffsets() {
|
|||||||
return stripPointerCastsAndOffsets<PSK_InBoundsConstantIndices>(this);
|
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() {
|
Value *Value::stripInBoundsOffsets() {
|
||||||
return stripPointerCastsAndOffsets<PSK_InBounds>(this);
|
return stripPointerCastsAndOffsets<PSK_InBounds>(this);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user