diff options
Diffstat (limited to 'llvm/lib/Analysis/BasicAliasAnalysis.cpp')
-rw-r--r-- | llvm/lib/Analysis/BasicAliasAnalysis.cpp | 122 |
1 files changed, 73 insertions, 49 deletions
diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp index f9275da..1440906 100644 --- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -806,8 +806,12 @@ AliasResult BasicAAResult::alias(const MemoryLocation &LocA, if (Locs.first.Ptr > Locs.second.Ptr) std::swap(Locs.first, Locs.second); auto CacheIt = AAQI.AliasCache.find(Locs); - if (CacheIt != AAQI.AliasCache.end()) - return CacheIt->second; + if (CacheIt != AAQI.AliasCache.end()) { + // This code exists to skip a second BasicAA call while recursing into + // BestAA. Don't make use of assumptions here. + const auto &Entry = CacheIt->second; + return Entry.isDefinitive() ? Entry.Result : MayAlias; + } AliasResult Alias = aliasCheck(LocA.Ptr, LocA.Size, LocA.AATags, LocB.Ptr, LocB.Size, LocB.AATags, AAQI); @@ -1376,42 +1380,20 @@ AliasResult BasicAAResult::aliasPHI(const PHINode *PN, LocationSize PNSize, // on corresponding edges. if (const PHINode *PN2 = dyn_cast<PHINode>(V2)) if (PN2->getParent() == PN->getParent()) { - AAQueryInfo::LocPair Locs(MemoryLocation(PN, PNSize, PNAAInfo), - MemoryLocation(V2, V2Size, V2AAInfo)); - if (PN > V2) - std::swap(Locs.first, Locs.second); - // Analyse the PHIs' inputs under the assumption that the PHIs are - // NoAlias. - // If the PHIs are May/MustAlias there must be (recursively) an input - // operand from outside the PHIs' cycle that is MayAlias/MustAlias or - // there must be an operation on the PHIs within the PHIs' value cycle - // that causes a MayAlias. - // Pretend the phis do not alias. - AliasResult Alias = NoAlias; - AliasResult OrigAliasResult; - { - // Limited lifetime iterator invalidated by the aliasCheck call below. - auto CacheIt = AAQI.AliasCache.find(Locs); - assert((CacheIt != AAQI.AliasCache.end()) && - "There must exist an entry for the phi node"); - OrigAliasResult = CacheIt->second; - CacheIt->second = NoAlias; - } - + Optional<AliasResult> Alias; for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { AliasResult ThisAlias = aliasCheck(PN->getIncomingValue(i), PNSize, PNAAInfo, PN2->getIncomingValueForBlock(PN->getIncomingBlock(i)), V2Size, V2AAInfo, AAQI); - Alias = MergeAliasResults(ThisAlias, Alias); - if (Alias == MayAlias) + if (Alias) + *Alias = MergeAliasResults(*Alias, ThisAlias); + else + Alias = ThisAlias; + if (*Alias == MayAlias) break; } - - // Reset if speculation failed. - if (Alias != NoAlias) - AAQI.updateResult(Locs, OrigAliasResult); - return Alias; + return *Alias; } SmallVector<Value *, 4> V1Srcs; @@ -1630,64 +1612,106 @@ AliasResult BasicAAResult::aliasCheck(const Value *V1, LocationSize V1Size, MemoryLocation(V2, V2Size, V2AAInfo)); if (V1 > V2) std::swap(Locs.first, Locs.second); - std::pair<AAQueryInfo::AliasCacheT::iterator, bool> Pair = - AAQI.AliasCache.try_emplace(Locs, MayAlias); - if (!Pair.second) - return Pair.first->second; + const auto &Pair = AAQI.AliasCache.try_emplace( + Locs, AAQueryInfo::CacheEntry{NoAlias, 0}); + if (!Pair.second) { + auto &Entry = Pair.first->second; + if (!Entry.isDefinitive()) { + // Remember that we used an assumption. + ++Entry.NumAssumptionUses; + ++NumAssumptionUses; + } + return Entry.Result; + } + int OrigNumAssumptionUses = NumAssumptionUses; + unsigned OrigNumAssumptionBasedResults = AssumptionBasedResults.size(); + AliasResult Result = aliasCheckRecursive(V1, V1Size, V1AAInfo, V2, V2Size, + V2AAInfo, AAQI, O1, O2); + + auto It = AAQI.AliasCache.find(Locs); + assert(It != AAQI.AliasCache.end() && "Must be in cache"); + auto &Entry = It->second; + + // Check whether a NoAlias assumption has been used, but disproven. + bool AssumptionDisproven = Entry.NumAssumptionUses > 0 && Result != NoAlias; + if (AssumptionDisproven) + Result = MayAlias; + + // This is a definitive result now, when considered as a root query. + NumAssumptionUses -= Entry.NumAssumptionUses; + Entry.Result = Result; + Entry.NumAssumptionUses = -1; + + // If the assumption has been disproven, remove any results that may have + // been based on this assumption. Do this after the Entry updates above to + // avoid iterator invalidation. + if (AssumptionDisproven) + while (AssumptionBasedResults.size() > OrigNumAssumptionBasedResults) + AAQI.AliasCache.erase(AssumptionBasedResults.pop_back_val()); + + // The result may still be based on assumptions higher up in the chain. + // Remember it, so it can be purged from the cache later. + if (OrigNumAssumptionUses != NumAssumptionUses && Result != MayAlias) + AssumptionBasedResults.push_back(Locs); + return Result; +} + +AliasResult BasicAAResult::aliasCheckRecursive( + const Value *V1, LocationSize V1Size, const AAMDNodes &V1AAInfo, + const Value *V2, LocationSize V2Size, const AAMDNodes &V2AAInfo, + AAQueryInfo &AAQI, const Value *O1, const Value *O2) { if (const GEPOperator *GV1 = dyn_cast<GEPOperator>(V1)) { AliasResult Result = aliasGEP(GV1, V1Size, V1AAInfo, V2, V2Size, V2AAInfo, O1, O2, AAQI); if (Result != MayAlias) - return AAQI.updateResult(Locs, Result); + return Result; } else if (const GEPOperator *GV2 = dyn_cast<GEPOperator>(V2)) { AliasResult Result = aliasGEP(GV2, V2Size, V2AAInfo, V1, V1Size, V1AAInfo, O2, O1, AAQI); if (Result != MayAlias) - return AAQI.updateResult(Locs, Result); + return Result; } if (const PHINode *PN = dyn_cast<PHINode>(V1)) { AliasResult Result = aliasPHI(PN, V1Size, V1AAInfo, V2, V2Size, V2AAInfo, O2, AAQI); if (Result != MayAlias) - return AAQI.updateResult(Locs, Result); + return Result; } else if (const PHINode *PN = dyn_cast<PHINode>(V2)) { AliasResult Result = aliasPHI(PN, V2Size, V2AAInfo, V1, V1Size, V1AAInfo, O1, AAQI); if (Result != MayAlias) - return AAQI.updateResult(Locs, Result); + return Result; } if (const SelectInst *S1 = dyn_cast<SelectInst>(V1)) { AliasResult Result = aliasSelect(S1, V1Size, V1AAInfo, V2, V2Size, V2AAInfo, O2, AAQI); if (Result != MayAlias) - return AAQI.updateResult(Locs, Result); + return Result; } else if (const SelectInst *S2 = dyn_cast<SelectInst>(V2)) { AliasResult Result = aliasSelect(S2, V2Size, V2AAInfo, V1, V1Size, V1AAInfo, O1, AAQI); if (Result != MayAlias) - return AAQI.updateResult(Locs, Result); + return Result; } // If both pointers are pointing into the same object and one of them // accesses the entire object, then the accesses must overlap in some way. - if (O1 == O2) + if (O1 == O2) { + bool NullIsValidLocation = NullPointerIsDefined(&F); if (V1Size.isPrecise() && V2Size.isPrecise() && (isObjectSize(O1, V1Size.getValue(), DL, TLI, NullIsValidLocation) || isObjectSize(O2, V2Size.getValue(), DL, TLI, NullIsValidLocation))) - return AAQI.updateResult(Locs, PartialAlias); + return PartialAlias; + } // Recurse back into the best AA results we have, potentially with refined // memory locations. We have already ensured that BasicAA has a MayAlias // cache result for these, so any recursion back into BasicAA won't loop. - AliasResult Result = getBestAAResults().alias(Locs.first, Locs.second, AAQI); - if (Result != MayAlias) - return AAQI.updateResult(Locs, Result); - - // MayAlias is already in the cache. - return MayAlias; + return getBestAAResults().alias(MemoryLocation(V1, V1Size, V1AAInfo), + MemoryLocation(V2, V2Size, V2AAInfo), AAQI); } /// Check whether two Values can be considered equivalent. |