class DominatorTree;
class OrderedBasicBlock;
+ /// The default value for MaxUsesToExplore argument. It's relatively small to
+ /// keep the cost of analysis reasonable for clients like BasicAliasAnalysis,
+ /// where the results can't be cached.
+ /// TODO: we should probably introduce a caching CaptureTracking analysis and
+ /// use it where possible. The caching version can use much higher limit or
+ /// don't have this cap at all.
+ unsigned constexpr DefaultMaxUsesToExplore = 20;
+
/// PointerMayBeCaptured - Return true if this pointer value may be captured
/// by the enclosing function (which is required to exist). This routine can
/// be expensive, so consider caching the results. The boolean ReturnCaptures
/// counts as capturing it or not. The boolean StoreCaptures specified
/// whether storing the value (or part of it) into memory anywhere
/// automatically counts as capturing it or not.
+ /// MaxUsesToExplore specifies how many uses should the analysis explore for
+ /// one value before giving up due too "too many uses".
bool PointerMayBeCaptured(const Value *V,
bool ReturnCaptures,
- bool StoreCaptures);
+ bool StoreCaptures,
+ unsigned MaxUsesToExplore = DefaultMaxUsesToExplore);
/// PointerMayBeCapturedBefore - Return true if this pointer value may be
/// captured by the enclosing function (which is required to exist). If a
/// or not. Captures by the provided instruction are considered if the
/// final parameter is true. An ordered basic block in \p OBB could be used
/// to speed up capture-tracker queries.
+ /// MaxUsesToExplore specifies how many uses should the analysis explore for
+ /// one value before giving up due too "too many uses".
bool PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures,
bool StoreCaptures, const Instruction *I,
const DominatorTree *DT, bool IncludeI = false,
- OrderedBasicBlock *OBB = nullptr);
+ OrderedBasicBlock *OBB = nullptr,
+ unsigned MaxUsesToExplore = DefaultMaxUsesToExplore);
/// This callback is used in conjunction with PointerMayBeCaptured. In
/// addition to the interface here, you'll need to provide your own getters
/// PointerMayBeCaptured - Visit the value and the values derived from it and
/// find values which appear to be capturing the pointer value. This feeds
/// results into and is controlled by the CaptureTracker object.
- void PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker);
+ /// MaxUsesToExplore specifies how many uses should the analysis explore for
+ /// one value before giving up due too "too many uses".
+ void PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker,
+ unsigned MaxUsesToExplore = DefaultMaxUsesToExplore);
} // end namespace llvm
#endif
/// storing the value (or part of it) into memory anywhere automatically
/// counts as capturing it or not.
bool llvm::PointerMayBeCaptured(const Value *V,
- bool ReturnCaptures, bool StoreCaptures) {
+ bool ReturnCaptures, bool StoreCaptures,
+ unsigned MaxUsesToExplore) {
assert(!isa<GlobalValue>(V) &&
"It doesn't make sense to ask whether a global is captured.");
bool llvm::PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures,
bool StoreCaptures, const Instruction *I,
const DominatorTree *DT, bool IncludeI,
- OrderedBasicBlock *OBB) {
+ OrderedBasicBlock *OBB,
+ unsigned MaxUsesToExplore) {
assert(!isa<GlobalValue>(V) &&
"It doesn't make sense to ask whether a global is captured.");
bool UseNewOBB = OBB == nullptr;
return CB.Captured;
}
-/// TODO: Write a new FunctionPass AliasAnalysis so that it can keep
-/// a cache. Then we can move the code from BasicAliasAnalysis into
-/// that path, and remove this threshold.
-static unsigned const Threshold = 20;
-
-void llvm::PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker) {
+void llvm::PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker,
+ unsigned MaxUsesToExplore) {
assert(V->getType()->isPointerTy() && "Capture is for pointers only!");
- SmallVector<const Use *, Threshold> Worklist;
- SmallSet<const Use *, Threshold> Visited;
+ SmallVector<const Use *, DefaultMaxUsesToExplore> Worklist;
+ SmallSet<const Use *, DefaultMaxUsesToExplore> Visited;
auto AddUses = [&](const Value *V) {
unsigned Count = 0;
for (const Use &U : V->uses()) {
// If there are lots of uses, conservatively say that the value
// is captured to avoid taking too much compile time.
- if (Count++ >= Threshold)
+ if (Count++ >= MaxUsesToExplore)
return Tracker->tooManyUses();
if (!Visited.insert(&U).second)
continue;