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);
// 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;
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.