aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/IR/Value.cpp
diff options
context:
space:
mode:
authorPhilip Reames <listmail@philipreames.com>2021-04-01 08:29:47 -0700
committerPhilip Reames <listmail@philipreames.com>2021-04-01 08:34:40 -0700
commite2c6621e638e4dc30963293bff052784d3a3305a (patch)
treeed681a2a130dddfdda9c236aa43d1df0fbdc4676 /llvm/lib/IR/Value.cpp
parentce61def529e2d9ef46b79c9d1f489d69b45b95bf (diff)
downloadllvm-e2c6621e638e4dc30963293bff052784d3a3305a.zip
llvm-e2c6621e638e4dc30963293bff052784d3a3305a.tar.gz
llvm-e2c6621e638e4dc30963293bff052784d3a3305a.tar.bz2
[deref-at-point] restrict inference of dereferenceability based on allocsize attribute
Support deriving dereferenceability facts from allocation sites with known object sizes while correctly accounting for any possibly frees between allocation and use site. (At the moment, we're conservative and only allowing it in functions where we know we can't free.) This is part of the work on deref-at-point semantics. I'm making the change unconditional as the miscompile in this case is way too easy to trip by accident, and the optimization was only recently added (by me). There will be a follow up patch wiring through TLI since that should now be doable without introducing widespread miscompiles. Differential Revision: https://reviews.llvm.org/D95815
Diffstat (limited to 'llvm/lib/IR/Value.cpp')
-rw-r--r--llvm/lib/IR/Value.cpp20
1 files changed, 8 insertions, 12 deletions
diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp
index fb4eb9a..bf48d09 100644
--- a/llvm/lib/IR/Value.cpp
+++ b/llvm/lib/IR/Value.cpp
@@ -728,27 +728,24 @@ Value::stripInBoundsOffsets(function_ref<void(const Value *)> Func) const {
return stripPointerCastsAndOffsets<PSK_InBounds>(this, Func);
}
-// Return true if the memory object referred to by V can by freed in the scope
-// for which the SSA value defining the allocation is statically defined. E.g.
-// deallocation after the static scope of a value does not count.
-static bool canBeFreed(const Value *V) {
- assert(V->getType()->isPointerTy());
+bool Value::canBeFreed() const {
+ assert(getType()->isPointerTy());
// Cases that can simply never be deallocated
// *) Constants aren't allocated per se, thus not deallocated either.
- if (isa<Constant>(V))
+ if (isa<Constant>(this))
return false;
// Handle byval/byref/sret/inalloca/preallocated arguments. The storage
// lifetime is guaranteed to be longer than the callee's lifetime.
- if (auto *A = dyn_cast<Argument>(V))
+ if (auto *A = dyn_cast<Argument>(this))
if (A->hasPointeeInMemoryValueAttr())
return false;
const Function *F = nullptr;
- if (auto *I = dyn_cast<Instruction>(V))
+ if (auto *I = dyn_cast<Instruction>(this))
F = I->getFunction();
- if (auto *A = dyn_cast<Argument>(V))
+ if (auto *A = dyn_cast<Argument>(this))
F = A->getParent();
if (!F)
@@ -774,7 +771,7 @@ static bool canBeFreed(const Value *V) {
if (GCName != StatepointExampleName)
return true;
- auto *PT = cast<PointerType>(V->getType());
+ auto *PT = cast<PointerType>(this->getType());
if (PT->getAddressSpace() != 1)
// For the sake of this example GC, we arbitrarily pick addrspace(1) as our
// GC managed heap. This must match the same check in
@@ -791,7 +788,6 @@ static bool canBeFreed(const Value *V) {
return false;
}
-
uint64_t Value::getPointerDereferenceableBytes(const DataLayout &DL,
bool &CanBeNull,
bool &CanBeFreed) const {
@@ -799,7 +795,7 @@ uint64_t Value::getPointerDereferenceableBytes(const DataLayout &DL,
uint64_t DerefBytes = 0;
CanBeNull = false;
- CanBeFreed = UseDerefAtPointSemantics && canBeFreed(this);
+ CanBeFreed = UseDerefAtPointSemantics && canBeFreed();
if (const Argument *A = dyn_cast<Argument>(this)) {
DerefBytes = A->getDereferenceableBytes();
if (DerefBytes == 0) {