reimplement GetPointerBaseWithConstantOffset().

The new code is an improved copy of the code I deleted from Analysis/Loads.cpp.
One less compute-constant-gep-offset implementation. yay :)

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171326 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nuno Lopes
2012-12-31 20:48:35 +00:00
parent 0a9ff4cab3
commit 5cec34754d

View File

@ -1672,40 +1672,30 @@ Value *llvm::FindInsertedValue(Value *V, ArrayRef<unsigned> idx_range,
/// base and offset to the caller. /// base and offset to the caller.
Value *llvm::GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, Value *llvm::GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset,
const DataLayout &TD) { const DataLayout &TD) {
Operator *PtrOp = dyn_cast<Operator>(Ptr); unsigned BitWidth = TD.getPointerSizeInBits();
if (PtrOp == 0 || Ptr->getType()->isVectorTy()) APInt ByteOffset(BitWidth, 0);
return Ptr; while (1) {
if (Ptr->getType()->isVectorTy())
break;
// Just look through bitcasts. if (GEPOperator *GEP = dyn_cast<GEPOperator>(Ptr)) {
if (PtrOp->getOpcode() == Instruction::BitCast) APInt GEPOffset(BitWidth, 0);
return GetPointerBaseWithConstantOffset(PtrOp->getOperand(0), Offset, TD); if (!GEP->accumulateConstantOffset(TD, GEPOffset))
break;
// If this is a GEP with constant indices, we can look through it. ByteOffset += GEPOffset;
GEPOperator *GEP = dyn_cast<GEPOperator>(PtrOp); Ptr = GEP->getPointerOperand();
if (GEP == 0 || !GEP->hasAllConstantIndices()) return Ptr; } else if (Operator::getOpcode(Ptr) == Instruction::BitCast) {
Ptr = cast<Operator>(Ptr)->getOperand(0);
gep_type_iterator GTI = gep_type_begin(GEP); } else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(Ptr)) {
for (User::op_iterator I = GEP->idx_begin(), E = GEP->idx_end(); I != E; if (GA->mayBeOverridden())
++I, ++GTI) { break;
ConstantInt *OpC = cast<ConstantInt>(*I); Ptr = GA->getAliasee();
if (OpC->isZero()) continue;
// Handle a struct and array indices which add their offset to the pointer.
if (StructType *STy = dyn_cast<StructType>(*GTI)) {
Offset += TD.getStructLayout(STy)->getElementOffset(OpC->getZExtValue());
} else { } else {
uint64_t Size = TD.getTypeAllocSize(GTI.getIndexedType()); break;
Offset += OpC->getSExtValue()*Size;
} }
} }
Offset = ByteOffset.getSExtValue();
// Re-sign extend from the pointer size if needed to get overflow edge cases return Ptr;
// right.
unsigned PtrSize = TD.getPointerSizeInBits();
if (PtrSize < 64)
Offset = SignExtend64(Offset, PtrSize);
return GetPointerBaseWithConstantOffset(GEP->getPointerOperand(), Offset, TD);
} }