aboutsummaryrefslogtreecommitdiff
path: root/lib/IR/Value.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/IR/Value.cpp')
-rw-r--r--lib/IR/Value.cpp128
1 files changed, 121 insertions, 7 deletions
diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp
index 4d224a041349..6ae37fa6f15a 100644
--- a/lib/IR/Value.cpp
+++ b/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!");