forked from OSchip/llvm-project
[NFC][CaptureTracking] Move static function isNonEscapingLocalObject to llvm namespace
Function isNonEscapingLocalObject is a static one within BasicAliasAnalysis.cpp. It wraps around PointerMayBeCaptured of CaptureTracking, checking whether a pointer is to a function-local object, which never escapes from the function. Although at the moment, isNonEscapingLocalObject is used only by BasicAliasAnalysis, its functionality can be used by other pass(es), one of which I will put up for review very soon. Instead of copying the contents of this static function, I move it to llvm scope, and place it amongst other functions with similar functionality in CaptureTracking. The rationale for the location are: - Pointer escape and pointer being captured are actually two sides of the same coin - isNonEscapingLocalObject is wrapping around another function in CaptureTracking Reviewed By: jdoerfert (Johannes Doerfert) Differential Revision: https://reviews.llvm.org/D89465
This commit is contained in:
parent
67f189e93c
commit
224fd6ff48
|
@ -13,6 +13,8 @@
|
|||
#ifndef LLVM_ANALYSIS_CAPTURETRACKING_H
|
||||
#define LLVM_ANALYSIS_CAPTURETRACKING_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Value;
|
||||
|
@ -94,6 +96,12 @@ namespace llvm {
|
|||
/// is zero, a default value is assumed.
|
||||
void PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker,
|
||||
unsigned MaxUsesToExplore = 0);
|
||||
|
||||
/// Returns true if the pointer is to a function-local object that never
|
||||
/// escapes from the function.
|
||||
bool isNonEscapingLocalObject(
|
||||
const Value *V,
|
||||
SmallDenseMap<const Value *, bool, 8> *IsCapturedCache = nullptr);
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
|
|
@ -115,50 +115,6 @@ bool BasicAAResult::invalidate(Function &Fn, const PreservedAnalyses &PA,
|
|||
// Useful predicates
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Returns true if the pointer is to a function-local object that never
|
||||
/// escapes from the function.
|
||||
static bool isNonEscapingLocalObject(
|
||||
const Value *V,
|
||||
SmallDenseMap<const Value *, bool, 8> *IsCapturedCache = nullptr) {
|
||||
SmallDenseMap<const Value *, bool, 8>::iterator CacheIt;
|
||||
if (IsCapturedCache) {
|
||||
bool Inserted;
|
||||
std::tie(CacheIt, Inserted) = IsCapturedCache->insert({V, false});
|
||||
if (!Inserted)
|
||||
// Found cached result, return it!
|
||||
return CacheIt->second;
|
||||
}
|
||||
|
||||
// If this is a local allocation, check to see if it escapes.
|
||||
if (isa<AllocaInst>(V) || isNoAliasCall(V)) {
|
||||
// Set StoreCaptures to True so that we can assume in our callers that the
|
||||
// pointer is not the result of a load instruction. Currently
|
||||
// PointerMayBeCaptured doesn't have any special analysis for the
|
||||
// StoreCaptures=false case; if it did, our callers could be refined to be
|
||||
// more precise.
|
||||
auto Ret = !PointerMayBeCaptured(V, false, /*StoreCaptures=*/true);
|
||||
if (IsCapturedCache)
|
||||
CacheIt->second = Ret;
|
||||
return Ret;
|
||||
}
|
||||
|
||||
// If this is an argument that corresponds to a byval or noalias argument,
|
||||
// then it has not escaped before entering the function. Check if it escapes
|
||||
// inside the function.
|
||||
if (const Argument *A = dyn_cast<Argument>(V))
|
||||
if (A->hasByValAttr() || A->hasNoAliasAttr()) {
|
||||
// Note even if the argument is marked nocapture, we still need to check
|
||||
// for copies made inside the function. The nocapture attribute only
|
||||
// specifies that there are no copies made that outlive the function.
|
||||
auto Ret = !PointerMayBeCaptured(V, false, /*StoreCaptures=*/true);
|
||||
if (IsCapturedCache)
|
||||
CacheIt->second = Ret;
|
||||
return Ret;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Returns true if the pointer is one which would have been considered an
|
||||
/// escape by isNonEscapingLocalObject.
|
||||
static bool isEscapeSource(const Value *V) {
|
||||
|
|
|
@ -395,3 +395,44 @@ void llvm::PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker,
|
|||
|
||||
// All uses examined.
|
||||
}
|
||||
|
||||
bool llvm::isNonEscapingLocalObject(
|
||||
const Value *V, SmallDenseMap<const Value *, bool, 8> *IsCapturedCache) {
|
||||
SmallDenseMap<const Value *, bool, 8>::iterator CacheIt;
|
||||
if (IsCapturedCache) {
|
||||
bool Inserted;
|
||||
std::tie(CacheIt, Inserted) = IsCapturedCache->insert({V, false});
|
||||
if (!Inserted)
|
||||
// Found cached result, return it!
|
||||
return CacheIt->second;
|
||||
}
|
||||
|
||||
// If this is a local allocation, check to see if it escapes.
|
||||
if (isa<AllocaInst>(V) || isNoAliasCall(V)) {
|
||||
// Set StoreCaptures to True so that we can assume in our callers that the
|
||||
// pointer is not the result of a load instruction. Currently
|
||||
// PointerMayBeCaptured doesn't have any special analysis for the
|
||||
// StoreCaptures=false case; if it did, our callers could be refined to be
|
||||
// more precise.
|
||||
auto Ret = !PointerMayBeCaptured(V, false, /*StoreCaptures=*/true);
|
||||
if (IsCapturedCache)
|
||||
CacheIt->second = Ret;
|
||||
return Ret;
|
||||
}
|
||||
|
||||
// If this is an argument that corresponds to a byval or noalias argument,
|
||||
// then it has not escaped before entering the function. Check if it escapes
|
||||
// inside the function.
|
||||
if (const Argument *A = dyn_cast<Argument>(V))
|
||||
if (A->hasByValAttr() || A->hasNoAliasAttr()) {
|
||||
// Note even if the argument is marked nocapture, we still need to check
|
||||
// for copies made inside the function. The nocapture attribute only
|
||||
// specifies that there are no copies made that outlive the function.
|
||||
auto Ret = !PointerMayBeCaptured(V, false, /*StoreCaptures=*/true);
|
||||
if (IsCapturedCache)
|
||||
CacheIt->second = Ret;
|
||||
return Ret;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue