From: Alina Sbirlea Date: Tue, 5 Feb 2019 23:52:08 +0000 (+0000) Subject: [BasicAA] Cache nonEscapingLocalObjects for alias() calls. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8eb5349a5c07f3e79a55098e0b880e5c25c86fcb;p=llvm [BasicAA] Cache nonEscapingLocalObjects for alias() calls. Summary: Use a small cache for Values tested by nonEscapingLocalObject(). Since the calls to PointerMayBeCaptured are fairly expensive, this saves a good amount of compile time for anything relying heavily on BasicAA.alias() calls. This uses the same approach as the AliasCache, i.e. the cache is reset after each alias() call. The cache is not used or updated by modRefInfo calls since it's harder to know when to reset the cache. Testcases that show improvements with this patch are too large to include. Example compile time improvement: 7s to 6s. Reviewers: chandlerc, sunfish Subscribers: sanjoy, jlebar, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D57627 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@353245 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Analysis/BasicAliasAnalysis.h b/include/llvm/Analysis/BasicAliasAnalysis.h index d612abc78c5..29f584cea8e 100644 --- a/include/llvm/Analysis/BasicAliasAnalysis.h +++ b/include/llvm/Analysis/BasicAliasAnalysis.h @@ -144,6 +144,8 @@ private: using LocPair = std::pair; using AliasCacheTy = SmallDenseMap; AliasCacheTy AliasCache; + using IsCapturedCacheTy = SmallDenseMap; + IsCapturedCacheTy IsCapturedCache; /// Tracks phi nodes we have visited. /// diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp index e3d44788514..382a70b8066 100644 --- a/lib/Analysis/BasicAliasAnalysis.cpp +++ b/lib/Analysis/BasicAliasAnalysis.cpp @@ -116,25 +116,44 @@ bool BasicAAResult::invalidate(Function &Fn, const PreservedAnalyses &PA, /// Returns true if the pointer is to a function-local object that never /// escapes from the function. -static bool isNonEscapingLocalObject(const Value *V) { +static bool isNonEscapingLocalObject( + const Value *V, + SmallDenseMap *IsCapturedCache = nullptr) { + SmallDenseMap::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(V) || isNoAliasCall(V)) + if (isa(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. - return !PointerMayBeCaptured(V, false, /*StoreCaptures=*/true); + 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(V)) - if (A->hasByValAttr() || A->hasNoAliasAttr()) + 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. - return !PointerMayBeCaptured(V, false, /*StoreCaptures=*/true); + auto Ret = !PointerMayBeCaptured(V, false, /*StoreCaptures=*/true); + if (IsCapturedCache) + CacheIt->second = Ret; + return Ret; + } return false; } @@ -816,6 +835,7 @@ AliasResult BasicAAResult::alias(const MemoryLocation &LocA, // SmallDenseMap if it ever grows larger. // FIXME: This should really be shrink_to_inline_capacity_and_clear(). AliasCache.shrink_and_clear(); + IsCapturedCache.shrink_and_clear(); VisitedPhiBBs.clear(); return Alias; } @@ -1754,9 +1774,9 @@ AliasResult BasicAAResult::aliasCheck(const Value *V1, LocationSize V1Size, // temporary store the nocapture argument's value in a temporary memory // location if that memory location doesn't escape. Or it may pass a // nocapture value to other functions as long as they don't capture it. - if (isEscapeSource(O1) && isNonEscapingLocalObject(O2)) + if (isEscapeSource(O1) && isNonEscapingLocalObject(O2, &IsCapturedCache)) return NoAlias; - if (isEscapeSource(O2) && isNonEscapingLocalObject(O1)) + if (isEscapeSource(O2) && isNonEscapingLocalObject(O1, &IsCapturedCache)) return NoAlias; }