From eba2365f23db0cae29e9a187ec16bb64e49be5d6 Mon Sep 17 00:00:00 2001 From: Artur Pilipenko Date: Thu, 29 Nov 2018 20:08:12 +0000 Subject: [PATCH] Introduce MaxUsesToExplore argument to capture tracking Currently CaptureTracker gives up if it encounters a value with more than 20 uses. The motivation for this cap is to keep it relatively cheap for BasicAliasAnalysis use case, where the results can't be cached. Although, other clients of CaptureTracker might be ok with higher cost. This patch introduces an argument for PointerMayBeCaptured functions to specify the max number of uses to explore. The motivation for this change is a downstream user of CaptureTracker, but I believe upstream clients of CaptureTracker might also benefit from more fine grained cap. Reviewed By: hfinkel Differential Revision: https://reviews.llvm.org/D55042 llvm-svn: 347910 --- llvm/include/llvm/Analysis/CaptureTracking.h | 23 ++++++++++++++++++++--- llvm/lib/Analysis/CaptureTracking.cpp | 20 +++++++++----------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/llvm/include/llvm/Analysis/CaptureTracking.h b/llvm/include/llvm/Analysis/CaptureTracking.h index 7a869a5..aaaaff9 100644 --- a/llvm/include/llvm/Analysis/CaptureTracking.h +++ b/llvm/include/llvm/Analysis/CaptureTracking.h @@ -22,6 +22,14 @@ namespace llvm { 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 @@ -29,9 +37,12 @@ namespace llvm { /// 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 @@ -44,10 +55,13 @@ namespace llvm { /// 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 @@ -75,7 +89,10 @@ namespace llvm { /// 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 diff --git a/llvm/lib/Analysis/CaptureTracking.cpp b/llvm/lib/Analysis/CaptureTracking.cpp index 2596789..7c74c65 100644 --- a/llvm/lib/Analysis/CaptureTracking.cpp +++ b/llvm/lib/Analysis/CaptureTracking.cpp @@ -158,7 +158,8 @@ namespace { /// 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(V) && "It doesn't make sense to ask whether a global is captured."); @@ -186,7 +187,8 @@ bool llvm::PointerMayBeCaptured(const Value *V, 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(V) && "It doesn't make sense to ask whether a global is captured."); bool UseNewOBB = OBB == nullptr; @@ -207,22 +209,18 @@ bool llvm::PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures, 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 Worklist; - SmallSet Visited; + SmallVector Worklist; + SmallSet 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; -- 2.7.4