diff options
Diffstat (limited to 'contrib/llvm/lib/IR/Value.cpp')
-rw-r--r-- | contrib/llvm/lib/IR/Value.cpp | 128 |
1 files changed, 121 insertions, 7 deletions
diff --git a/contrib/llvm/lib/IR/Value.cpp b/contrib/llvm/lib/IR/Value.cpp index 4d224a0..6ae37fa 100644 --- a/contrib/llvm/lib/IR/Value.cpp +++ b/contrib/llvm/lib/IR/Value.cpp @@ -34,6 +34,7 @@ #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> + using namespace llvm; //===----------------------------------------------------------------------===// @@ -58,6 +59,8 @@ Value::Value(Type *ty, unsigned scid) (SubclassID < ConstantFirstVal || SubclassID > ConstantLastVal)) assert((VTy->isFirstClassType() || VTy->isVoidTy()) && "Cannot create non-first-class values except for constants!"); + static_assert(sizeof(Value) == 3 * sizeof(void *) + 2 * sizeof(unsigned), + "Value too big"); } Value::~Value() { @@ -195,6 +198,10 @@ StringRef Value::getName() const { } void Value::setNameImpl(const Twine &NewName) { + // Fast-path: LLVMContext can be set to strip out non-GlobalValue names + if (getContext().shouldDiscardValueNames() && !isa<GlobalValue>(this)) + return; + // Fast path for common IRBuilder case of setName("") when there is no name. if (NewName.isTriviallyEmpty() && !hasName()) return; @@ -358,7 +365,7 @@ static bool contains(Value *Expr, Value *V) { SmallPtrSet<ConstantExpr *, 4> Cache; return contains(Cache, CE, C); } -#endif +#endif // NDEBUG void Value::replaceAllUsesWith(Value *New) { assert(New && "Value::replaceAllUsesWith(<null>) is invalid!"); @@ -379,7 +386,7 @@ void Value::replaceAllUsesWith(Value *New) { // constant because they are uniqued. if (auto *C = dyn_cast<Constant>(U.getUser())) { if (!isa<GlobalValue>(C)) { - C->handleOperandChange(this, New, &U); + C->handleOperandChange(this, New); continue; } } @@ -410,7 +417,6 @@ void Value::replaceUsesOutsideBlock(Value *New, BasicBlock *BB) { continue; U.set(New); } - return; } namespace { @@ -454,10 +460,16 @@ static Value *stripPointerCastsAndOffsets(Value *V) { 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()) + if (StripKind == PSK_ZeroIndices || GA->isInterposable()) return V; V = GA->getAliasee(); } else { + if (auto CS = CallSite(V)) + if (Value *RV = CS.getReturnedArgOperand()) { + V = RV; + continue; + } + return V; } assert(V->getType()->isPointerTy() && "Unexpected operand type!"); @@ -465,7 +477,7 @@ static Value *stripPointerCastsAndOffsets(Value *V) { return V; } -} // namespace +} // end anonymous namespace Value *Value::stripPointerCasts() { return stripPointerCastsAndOffsets<PSK_ZeroIndicesAndAliases>(this); @@ -507,6 +519,12 @@ Value *Value::stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, } else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) { V = GA->getAliasee(); } else { + if (auto CS = CallSite(V)) + if (Value *RV = CS.getReturnedArgOperand()) { + V = RV; + continue; + } + return V; } assert(V->getType()->isPointerTy() && "Unexpected operand type!"); @@ -519,6 +537,104 @@ Value *Value::stripInBoundsOffsets() { return stripPointerCastsAndOffsets<PSK_InBounds>(this); } +unsigned Value::getPointerDereferenceableBytes(const DataLayout &DL, + bool &CanBeNull) const { + assert(getType()->isPointerTy() && "must be pointer"); + + unsigned DerefBytes = 0; + CanBeNull = false; + if (const Argument *A = dyn_cast<Argument>(this)) { + DerefBytes = A->getDereferenceableBytes(); + if (DerefBytes == 0 && A->hasByValAttr() && A->getType()->isSized()) { + DerefBytes = DL.getTypeStoreSize(A->getType()); + CanBeNull = false; + } + if (DerefBytes == 0) { + DerefBytes = A->getDereferenceableOrNullBytes(); + CanBeNull = true; + } + } else if (auto CS = ImmutableCallSite(this)) { + DerefBytes = CS.getDereferenceableBytes(0); + if (DerefBytes == 0) { + DerefBytes = CS.getDereferenceableOrNullBytes(0); + CanBeNull = true; + } + } else if (const LoadInst *LI = dyn_cast<LoadInst>(this)) { + if (MDNode *MD = LI->getMetadata(LLVMContext::MD_dereferenceable)) { + ConstantInt *CI = mdconst::extract<ConstantInt>(MD->getOperand(0)); + DerefBytes = CI->getLimitedValue(); + } + if (DerefBytes == 0) { + if (MDNode *MD = + LI->getMetadata(LLVMContext::MD_dereferenceable_or_null)) { + ConstantInt *CI = mdconst::extract<ConstantInt>(MD->getOperand(0)); + DerefBytes = CI->getLimitedValue(); + } + CanBeNull = true; + } + } else if (auto *AI = dyn_cast<AllocaInst>(this)) { + if (AI->getAllocatedType()->isSized()) { + DerefBytes = DL.getTypeStoreSize(AI->getAllocatedType()); + CanBeNull = false; + } + } else if (auto *GV = dyn_cast<GlobalVariable>(this)) { + if (GV->getValueType()->isSized() && !GV->hasExternalWeakLinkage()) { + // TODO: Don't outright reject hasExternalWeakLinkage but set the + // CanBeNull flag. + DerefBytes = DL.getTypeStoreSize(GV->getValueType()); + CanBeNull = false; + } + } + return DerefBytes; +} + +unsigned Value::getPointerAlignment(const DataLayout &DL) const { + assert(getType()->isPointerTy() && "must be pointer"); + + unsigned Align = 0; + if (auto *GO = dyn_cast<GlobalObject>(this)) { + Align = GO->getAlignment(); + if (Align == 0) { + if (auto *GVar = dyn_cast<GlobalVariable>(GO)) { + Type *ObjectType = GVar->getValueType(); + if (ObjectType->isSized()) { + // If the object is defined in the current Module, we'll be giving + // it the preferred alignment. Otherwise, we have to assume that it + // may only have the minimum ABI alignment. + if (GVar->isStrongDefinitionForLinker()) + Align = DL.getPreferredAlignment(GVar); + else + Align = DL.getABITypeAlignment(ObjectType); + } + } + } + } else if (const Argument *A = dyn_cast<Argument>(this)) { + Align = A->getParamAlignment(); + + if (!Align && A->hasStructRetAttr()) { + // An sret parameter has at least the ABI alignment of the return type. + Type *EltTy = cast<PointerType>(A->getType())->getElementType(); + if (EltTy->isSized()) + Align = DL.getABITypeAlignment(EltTy); + } + } else if (const AllocaInst *AI = dyn_cast<AllocaInst>(this)) { + Align = AI->getAlignment(); + if (Align == 0) { + Type *AllocatedType = AI->getAllocatedType(); + if (AllocatedType->isSized()) + Align = DL.getPrefTypeAlignment(AllocatedType); + } + } else if (auto CS = ImmutableCallSite(this)) + Align = CS.getAttributes().getParamAlignment(AttributeSet::ReturnIndex); + else if (const LoadInst *LI = dyn_cast<LoadInst>(this)) + if (MDNode *MD = LI->getMetadata(LLVMContext::MD_align)) { + ConstantInt *CI = mdconst::extract<ConstantInt>(MD->getOperand(0)); + Align = CI->getLimitedValue(); + } + + return Align; +} + Value *Value::DoPHITranslation(const BasicBlock *CurBB, const BasicBlock *PredBB) { PHINode *PN = dyn_cast<PHINode>(this); @@ -644,7 +760,6 @@ void ValueHandleBase::RemoveFromUseList() { } } - void ValueHandleBase::ValueIsDeleted(Value *V) { assert(V->HasValueHandle && "Should only be called if ValueHandles present"); @@ -701,7 +816,6 @@ void ValueHandleBase::ValueIsDeleted(Value *V) { } } - void ValueHandleBase::ValueIsRAUWd(Value *Old, Value *New) { assert(Old->HasValueHandle &&"Should only be called if ValueHandles present"); assert(Old != New && "Changing value into itself!"); |