diff options
Diffstat (limited to 'lib/IR/Value.cpp')
-rw-r--r-- | lib/IR/Value.cpp | 47 |
1 files changed, 40 insertions, 7 deletions
diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp index 81d7efa..62a3b31 100644 --- a/lib/IR/Value.cpp +++ b/lib/IR/Value.cpp @@ -365,7 +365,8 @@ static Value *stripPointerCastsAndOffsets(Value *V) { break; } V = GEP->getPointerOperand(); - } else if (Operator::getOpcode(V) == Instruction::BitCast) { + } else if (Operator::getOpcode(V) == Instruction::BitCast || + Operator::getOpcode(V) == Instruction::AddrSpaceCast) { V = cast<Operator>(V)->getOperand(0); } else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) { if (StripKind == PSK_ZeroIndices || GA->mayBeOverridden()) @@ -393,6 +394,42 @@ 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; + APInt GEPOffset(Offset); + if (!GEP->accumulateConstantOffset(DL, GEPOffset)) + return V; + Offset = GEPOffset; + 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); } @@ -698,9 +735,5 @@ void ValueHandleBase::ValueIsRAUWd(Value *Old, Value *New) { #endif } -// Default implementation for CallbackVH. -void CallbackVH::allUsesReplacedWith(Value *) {} - -void CallbackVH::deleted() { - setValPtr(NULL); -} +// Pin the vtable to this file. +void CallbackVH::anchor() {} |