Index: llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h =================================================================== --- llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h +++ llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h @@ -86,6 +86,16 @@ return V; } +/// A wrapper for GetUnderlyingObjCPtr used for results memoization. +inline const Value * +GetUnderlyingObjCPtrCached(const Value *V, const DataLayout &DL, + DenseMap &Cache) { + if (auto InCache = Cache.lookup(V)) + return InCache; + + return Cache[V] = GetUnderlyingObjCPtr(V, DL); +} + /// The RCIdentity root of a value \p V is a dominating value U for which /// retaining or releasing U is equivalent to retaining or releasing V. In other /// words, ARC operations on \p V are equivalent to ARC operations on \p U. Index: llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.h =================================================================== --- llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.h +++ llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.h @@ -56,6 +56,8 @@ CachedResultsTy CachedResults; + DenseMap UnderlyingObjCPtrCache; + bool relatedCheck(const Value *A, const Value *B, const DataLayout &DL); bool relatedSelect(const SelectInst *A, const Value *B); bool relatedPHI(const PHINode *A, const Value *B); @@ -73,6 +75,7 @@ void clear() { CachedResults.clear(); + UnderlyingObjCPtrCache.clear(); } }; Index: llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.cpp =================================================================== --- llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.cpp +++ llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.cpp @@ -115,14 +115,6 @@ bool ProvenanceAnalysis::relatedCheck(const Value *A, const Value *B, const DataLayout &DL) { - // Skip past provenance pass-throughs. - A = GetUnderlyingObjCPtr(A, DL); - B = GetUnderlyingObjCPtr(B, DL); - - // Quick check. - if (A == B) - return true; - // Ask regular AliasAnalysis, for a first approximation. switch (AA->alias(A, B)) { case NoAlias: @@ -171,6 +163,13 @@ bool ProvenanceAnalysis::related(const Value *A, const Value *B, const DataLayout &DL) { + A = GetUnderlyingObjCPtrCached(A, DL, UnderlyingObjCPtrCache); + B = GetUnderlyingObjCPtrCached(B, DL, UnderlyingObjCPtrCache); + + // Quick check. + if (A == B) + return true; + // Begin by inserting a conservative value into the map. If the insertion // fails, we have the answer already. If it succeeds, leave it there until we // compute the real answer to guard against recursive queries.