diff options
author | Philip Reames <listmail@philipreames.com> | 2021-03-24 16:18:09 -0700 |
---|---|---|
committer | Philip Reames <listmail@philipreames.com> | 2021-03-24 16:20:41 -0700 |
commit | 4054b8322fd8ef706bd486128a57bc8b709e2319 (patch) | |
tree | f567b86c8f5ad35b87a44f0f0c6d126a40827805 /llvm/lib/IR/Value.cpp | |
parent | c8ef98e5de0ec5ebd4efc80ad8938ed53b268ce3 (diff) | |
download | llvm-4054b8322fd8ef706bd486128a57bc8b709e2319.zip llvm-4054b8322fd8ef706bd486128a57bc8b709e2319.tar.gz llvm-4054b8322fd8ef706bd486128a57bc8b709e2319.tar.bz2 |
[deref] Implement initial set of inference rules for deref-at-point
This implements a subset of the initial set of inference rules proposed in the llvm-dev thread "RFC: Decomposing deref(N) into deref(N) + nofree". The nolias one got moved to a separate review as there was some concerns raised which require further discussion.
Differential Revision: https://reviews.llvm.org/D99135
Diffstat (limited to 'llvm/lib/IR/Value.cpp')
-rw-r--r-- | llvm/lib/IR/Value.cpp | 61 |
1 files changed, 59 insertions, 2 deletions
diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp index cfb91b5..8c06d4f 100644 --- a/llvm/lib/IR/Value.cpp +++ b/llvm/lib/IR/Value.cpp @@ -728,6 +728,64 @@ 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()); + + // Cases that can simply never be deallocated + // *) Constants aren't allocated per se, thus not deallocated either. + if (isa<Constant>(V)) + return false; + + const Function *F = nullptr; + if (auto *I = dyn_cast<Instruction>(V)) + F = I->getFunction(); + if (auto *A = dyn_cast<Argument>(V)) + F = A->getParent(); + + if (!F) + return true; + + // A pointer to an object in a function which neither frees, nor can arrange + // for another thread to free on its behalf, can not be freed in the scope + // of the function. + if (F->doesNotFreeMemory() && F->hasNoSync()) + return false; + + // With garbage collection, deallocation typically occurs solely at or after + // safepoints. If we're compiling for a collector which uses the + // gc.statepoint infrastructure, safepoints aren't explicitly present + // in the IR until after lowering from abstract to physical machine model. + // The collector could chose to mix explicit deallocation and gc'd objects + // which is why we need the explicit opt in on a per collector basis. + if (!F->hasGC()) + return true; + + const auto &GCName = F->getGC(); + const StringRef StatepointExampleName("statepoint-example"); + if (GCName != StatepointExampleName) + return true; + + auto *PT = cast<PointerType>(V->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 + // RewriteStatepointsForGC (and probably needs better factored.) + return true; + + // It is cheaper to scan for a declaration than to scan for a use in this + // function. Note that gc.statepoint is a type overloaded function so the + // usual trick of requesting declaration of the intrinsic from the module + // doesn't work. + for (auto &Fn : *F->getParent()) + if (Fn.getIntrinsicID() == Intrinsic::experimental_gc_statepoint) + return true; + return false; +} + + uint64_t Value::getPointerDereferenceableBytes(const DataLayout &DL, bool &CanBeNull, bool &CanBeFreed) const { @@ -735,7 +793,7 @@ uint64_t Value::getPointerDereferenceableBytes(const DataLayout &DL, uint64_t DerefBytes = 0; CanBeNull = false; - CanBeFreed = UseDerefAtPointSemantics; + CanBeFreed = UseDerefAtPointSemantics && canBeFreed(this); if (const Argument *A = dyn_cast<Argument>(this)) { DerefBytes = A->getDereferenceableBytes(); if (DerefBytes == 0) { @@ -798,7 +856,6 @@ uint64_t Value::getPointerDereferenceableBytes(const DataLayout &DL, // CanBeNull flag. DerefBytes = DL.getTypeStoreSize(GV->getValueType()).getFixedSize(); CanBeNull = false; - CanBeFreed = false; } } return DerefBytes; |