[llvm-branch-commits] [llvm] a3904cc - [BasicAA] Handle recursive queries more efficiently
Nikita Popov via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Jan 14 11:38:48 PST 2021
Author: Nikita Popov
Date: 2021-01-14T20:32:41+01:00
New Revision: a3904cc77f181cff7355357688edfc392a236f5d
URL: https://github.com/llvm/llvm-project/commit/a3904cc77f181cff7355357688edfc392a236f5d
DIFF: https://github.com/llvm/llvm-project/commit/a3904cc77f181cff7355357688edfc392a236f5d.diff
LOG: [BasicAA] Handle recursive queries more efficiently
An alias query currently works out roughly like this:
* Look up location pair in cache.
* Perform BasicAA logic (including cache lookup and insertion...)
* Perform a recursive query using BestAAResults.
* Look up location pair in cache (and thus do not recurse into BasicAA)
* Query all the other AA providers.
* Query all the other AA providers.
This is a lot of unnecessary work, all ultimately caused by the
BestAAResults query at the end of aliasCheck(). The reason we perform
it, is that aliasCheck() is getting called recursively, and we of
course want those recursive queries to also make use of other AA
providers, not just BasicAA. We can solve this by making the recursive
queries directly use BestAAResults (which will check both BasicAA
and other providers), rather than recursing into aliasCheck().
There are some tradeoffs:
* We can no longer pass through the precomputed underlying object
to aliasCheck(). This is not a major concern, because nowadays
getUnderlyingObject() is quite cheap.
* Results from other AA providers are no longer cached inside
BasicAA. The way this worked was already a bit iffy, in that a
result could be cached, but if it was MayAlias, we'd still end
up re-querying other providers anyway. If we want to cache
non-BasicAA results, we should do that in a more principled manner.
In any case, despite those tradeoffs, this works out to be a decent
compile-time improvment. I think it also simplifies the mental model
of how BasicAA works. It took me quite a while to fully understand
how these things interact.
Differential Revision: https://reviews.llvm.org/D90094
Added:
Modified:
llvm/include/llvm/Analysis/BasicAliasAnalysis.h
llvm/lib/Analysis/BasicAliasAnalysis.cpp
llvm/lib/Analysis/GlobalsModRef.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/BasicAliasAnalysis.h b/llvm/include/llvm/Analysis/BasicAliasAnalysis.h
index 635c35585f81..b95365d0481f 100644
--- a/llvm/include/llvm/Analysis/BasicAliasAnalysis.h
+++ b/llvm/include/llvm/Analysis/BasicAliasAnalysis.h
@@ -240,18 +240,17 @@ class BasicAAResult : public AAResultBase<BasicAAResult> {
AliasResult aliasPHI(const PHINode *PN, LocationSize PNSize,
const AAMDNodes &PNAAInfo, const Value *V2,
LocationSize V2Size, const AAMDNodes &V2AAInfo,
- const Value *UnderV2, AAQueryInfo &AAQI);
+ AAQueryInfo &AAQI);
AliasResult aliasSelect(const SelectInst *SI, LocationSize SISize,
const AAMDNodes &SIAAInfo, const Value *V2,
LocationSize V2Size, const AAMDNodes &V2AAInfo,
- const Value *UnderV2, AAQueryInfo &AAQI);
+ AAQueryInfo &AAQI);
AliasResult aliasCheck(const Value *V1, LocationSize V1Size,
const AAMDNodes &V1AATag, const Value *V2,
LocationSize V2Size, const AAMDNodes &V2AATag,
- AAQueryInfo &AAQI, const Value *O1 = nullptr,
- const Value *O2 = nullptr);
+ AAQueryInfo &AAQI);
AliasResult aliasCheckRecursive(const Value *V1, LocationSize V1Size,
const AAMDNodes &V1AATag, const Value *V2,
diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index 313a85ccc4de..29fd58e6e5d7 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -798,26 +798,8 @@ AliasResult BasicAAResult::alias(const MemoryLocation &LocA,
AAQueryInfo &AAQI) {
assert(notDifferentParent(LocA.Ptr, LocB.Ptr) &&
"BasicAliasAnalysis doesn't support interprocedural queries.");
-
- // If we have a directly cached entry for these locations, we have recursed
- // through this once, so just return the cached results. Notably, when this
- // happens, we don't clear the cache.
- AAQueryInfo::LocPair Locs(LocA, LocB);
- if (Locs.first.Ptr > Locs.second.Ptr)
- std::swap(Locs.first, Locs.second);
- auto CacheIt = AAQI.AliasCache.find(Locs);
- 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);
-
- assert(VisitedPhiBBs.empty());
- return Alias;
+ return aliasCheck(LocA.Ptr, LocA.Size, LocA.AATags, LocB.Ptr, LocB.Size,
+ LocB.AATags, AAQI);
}
/// Checks to see if the specified callsite can clobber the specified memory
@@ -1130,16 +1112,17 @@ AliasResult BasicAAResult::aliasGEP(
if (isGEPBaseAtNegativeOffset(GEP2, DecompGEP2, DecompGEP1, V1Size))
return NoAlias;
// Do the base pointers alias?
- AliasResult BaseAlias = aliasCheck(
- UnderlyingV1, LocationSize::beforeOrAfterPointer(), AAMDNodes(),
- UnderlyingV2, LocationSize::beforeOrAfterPointer(), AAMDNodes(), AAQI);
+ AliasResult BaseAlias = getBestAAResults().alias(
+ MemoryLocation::getBeforeOrAfter(UnderlyingV1),
+ MemoryLocation::getBeforeOrAfter(UnderlyingV2), AAQI);
// For GEPs with identical offsets, we can preserve the size and AAInfo
// when performing the alias check on the underlying objects.
if (BaseAlias == MayAlias && DecompGEP1.Offset == DecompGEP2.Offset &&
DecompGEP1.VarIndices == DecompGEP2.VarIndices) {
- AliasResult PreciseBaseAlias = aliasCheck(
- UnderlyingV1, V1Size, V1AAInfo, UnderlyingV2, V2Size, V2AAInfo, AAQI);
+ AliasResult PreciseBaseAlias = getBestAAResults().alias(
+ MemoryLocation(UnderlyingV1, V1Size, V1AAInfo),
+ MemoryLocation(UnderlyingV2, V2Size, V2AAInfo), AAQI);
if (PreciseBaseAlias == NoAlias)
return NoAlias;
}
@@ -1165,9 +1148,9 @@ AliasResult BasicAAResult::aliasGEP(
if (!V1Size.hasValue() && !V2Size.hasValue())
return MayAlias;
- AliasResult R = aliasCheck(
- UnderlyingV1, LocationSize::beforeOrAfterPointer(), AAMDNodes(),
- V2, V2Size, V2AAInfo, AAQI, nullptr, UnderlyingV2);
+ AliasResult R = getBestAAResults().alias(
+ MemoryLocation::getBeforeOrAfter(UnderlyingV1),
+ MemoryLocation(V2, V2Size, V2AAInfo), AAQI);
if (R != MustAlias) {
// If V2 may alias GEP base pointer, conservatively returns MayAlias.
// If V2 is known not to alias GEP base pointer, then the two values
@@ -1340,31 +1323,33 @@ AliasResult
BasicAAResult::aliasSelect(const SelectInst *SI, LocationSize SISize,
const AAMDNodes &SIAAInfo, const Value *V2,
LocationSize V2Size, const AAMDNodes &V2AAInfo,
- const Value *UnderV2, AAQueryInfo &AAQI) {
+ AAQueryInfo &AAQI) {
// If the values are Selects with the same condition, we can do a more precise
// check: just check for aliases between the values on corresponding arms.
if (const SelectInst *SI2 = dyn_cast<SelectInst>(V2))
if (SI->getCondition() == SI2->getCondition()) {
- AliasResult Alias =
- aliasCheck(SI->getTrueValue(), SISize, SIAAInfo, SI2->getTrueValue(),
- V2Size, V2AAInfo, AAQI);
+ AliasResult Alias = getBestAAResults().alias(
+ MemoryLocation(SI->getTrueValue(), SISize, SIAAInfo),
+ MemoryLocation(SI2->getTrueValue(), V2Size, V2AAInfo), AAQI);
if (Alias == MayAlias)
return MayAlias;
- AliasResult ThisAlias =
- aliasCheck(SI->getFalseValue(), SISize, SIAAInfo,
- SI2->getFalseValue(), V2Size, V2AAInfo, AAQI);
+ AliasResult ThisAlias = getBestAAResults().alias(
+ MemoryLocation(SI->getFalseValue(), SISize, SIAAInfo),
+ MemoryLocation(SI2->getFalseValue(), V2Size, V2AAInfo), AAQI);
return MergeAliasResults(ThisAlias, Alias);
}
// If both arms of the Select node NoAlias or MustAlias V2, then returns
// NoAlias / MustAlias. Otherwise, returns MayAlias.
- AliasResult Alias = aliasCheck(V2, V2Size, V2AAInfo, SI->getTrueValue(),
- SISize, SIAAInfo, AAQI, UnderV2);
+ AliasResult Alias = getBestAAResults().alias(
+ MemoryLocation(V2, V2Size, V2AAInfo),
+ MemoryLocation(SI->getTrueValue(), SISize, SIAAInfo), AAQI);
if (Alias == MayAlias)
return MayAlias;
- AliasResult ThisAlias = aliasCheck(V2, V2Size, V2AAInfo, SI->getFalseValue(),
- SISize, SIAAInfo, AAQI, UnderV2);
+ AliasResult ThisAlias = getBestAAResults().alias(
+ MemoryLocation(V2, V2Size, V2AAInfo),
+ MemoryLocation(SI->getFalseValue(), SISize, SIAAInfo), AAQI);
return MergeAliasResults(ThisAlias, Alias);
}
@@ -1374,7 +1359,7 @@ AliasResult BasicAAResult::aliasPHI(const PHINode *PN, LocationSize PNSize,
const AAMDNodes &PNAAInfo, const Value *V2,
LocationSize V2Size,
const AAMDNodes &V2AAInfo,
- const Value *UnderV2, AAQueryInfo &AAQI) {
+ AAQueryInfo &AAQI) {
// If the values are PHIs in the same block, we can do a more precise
// as well as efficient check: just check for aliases between the values
// on corresponding edges.
@@ -1382,10 +1367,12 @@ AliasResult BasicAAResult::aliasPHI(const PHINode *PN, LocationSize PNSize,
if (PN2->getParent() == PN->getParent()) {
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);
+ AliasResult ThisAlias = getBestAAResults().alias(
+ MemoryLocation(PN->getIncomingValue(i), PNSize, PNAAInfo),
+ MemoryLocation(
+ PN2->getIncomingValueForBlock(PN->getIncomingBlock(i)), V2Size,
+ V2AAInfo),
+ AAQI);
if (Alias)
*Alias = MergeAliasResults(*Alias, ThisAlias);
else
@@ -1473,8 +1460,9 @@ AliasResult BasicAAResult::aliasPHI(const PHINode *PN, LocationSize PNSize,
AAQueryInfo NewAAQI;
AAQueryInfo *UseAAQI = BlockInserted ? &NewAAQI : &AAQI;
- AliasResult Alias = aliasCheck(V2, V2Size, V2AAInfo, V1Srcs[0], PNSize,
- PNAAInfo, *UseAAQI, UnderV2);
+ AliasResult Alias = getBestAAResults().alias(
+ MemoryLocation(V2, V2Size, V2AAInfo),
+ MemoryLocation(V1Srcs[0], PNSize, PNAAInfo), *UseAAQI);
// Early exit if the check of the first PHI source against V2 is MayAlias.
// Other results are not possible.
@@ -1490,8 +1478,9 @@ AliasResult BasicAAResult::aliasPHI(const PHINode *PN, LocationSize PNSize,
for (unsigned i = 1, e = V1Srcs.size(); i != e; ++i) {
Value *V = V1Srcs[i];
- AliasResult ThisAlias = aliasCheck(V2, V2Size, V2AAInfo, V, PNSize,
- PNAAInfo, *UseAAQI, UnderV2);
+ AliasResult ThisAlias = getBestAAResults().alias(
+ MemoryLocation(V2, V2Size, V2AAInfo),
+ MemoryLocation(V, PNSize, PNAAInfo), *UseAAQI);
Alias = MergeAliasResults(ThisAlias, Alias);
if (Alias == MayAlias)
break;
@@ -1506,8 +1495,7 @@ AliasResult BasicAAResult::aliasCheck(const Value *V1, LocationSize V1Size,
const AAMDNodes &V1AAInfo,
const Value *V2, LocationSize V2Size,
const AAMDNodes &V2AAInfo,
- AAQueryInfo &AAQI, const Value *O1,
- const Value *O2) {
+ AAQueryInfo &AAQI) {
// If either of the memory references is empty, it doesn't matter what the
// pointer values are.
if (V1Size.isZero() || V2Size.isZero())
@@ -1535,11 +1523,8 @@ AliasResult BasicAAResult::aliasCheck(const Value *V1, LocationSize V1Size,
return NoAlias; // Scalars cannot alias each other
// Figure out what objects these things are pointing to if we can.
- if (O1 == nullptr)
- O1 = getUnderlyingObject(V1, MaxLookupSearchDepth);
-
- if (O2 == nullptr)
- O2 = getUnderlyingObject(V2, MaxLookupSearchDepth);
+ const Value *O1 = getUnderlyingObject(V1, MaxLookupSearchDepth);
+ const Value *O2 = getUnderlyingObject(V2, MaxLookupSearchDepth);
// Null values in the default address space don't point to any object, so they
// don't alias any other pointer.
@@ -1675,24 +1660,24 @@ AliasResult BasicAAResult::aliasCheckRecursive(
if (const PHINode *PN = dyn_cast<PHINode>(V1)) {
AliasResult Result =
- aliasPHI(PN, V1Size, V1AAInfo, V2, V2Size, V2AAInfo, O2, AAQI);
+ aliasPHI(PN, V1Size, V1AAInfo, V2, V2Size, V2AAInfo, AAQI);
if (Result != MayAlias)
return Result;
} else if (const PHINode *PN = dyn_cast<PHINode>(V2)) {
AliasResult Result =
- aliasPHI(PN, V2Size, V2AAInfo, V1, V1Size, V1AAInfo, O1, AAQI);
+ aliasPHI(PN, V2Size, V2AAInfo, V1, V1Size, V1AAInfo, AAQI);
if (Result != MayAlias)
return Result;
}
if (const SelectInst *S1 = dyn_cast<SelectInst>(V1)) {
AliasResult Result =
- aliasSelect(S1, V1Size, V1AAInfo, V2, V2Size, V2AAInfo, O2, AAQI);
+ aliasSelect(S1, V1Size, V1AAInfo, V2, V2Size, V2AAInfo, AAQI);
if (Result != MayAlias)
return Result;
} else if (const SelectInst *S2 = dyn_cast<SelectInst>(V2)) {
AliasResult Result =
- aliasSelect(S2, V2Size, V2AAInfo, V1, V1Size, V1AAInfo, O1, AAQI);
+ aliasSelect(S2, V2Size, V2AAInfo, V1, V1Size, V1AAInfo, AAQI);
if (Result != MayAlias)
return Result;
}
@@ -1707,11 +1692,7 @@ AliasResult BasicAAResult::aliasCheckRecursive(
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.
- return getBestAAResults().alias(MemoryLocation(V1, V1Size, V1AAInfo),
- MemoryLocation(V2, V2Size, V2AAInfo), AAQI);
+ return MayAlias;
}
/// Check whether two Values can be considered equivalent.
diff --git a/llvm/lib/Analysis/GlobalsModRef.cpp b/llvm/lib/Analysis/GlobalsModRef.cpp
index 20d54959e0fb..145baf82b65b 100644
--- a/llvm/lib/Analysis/GlobalsModRef.cpp
+++ b/llvm/lib/Analysis/GlobalsModRef.cpp
@@ -827,8 +827,10 @@ AliasResult GlobalsAAResult::alias(const MemoryLocation &LocA,
const MemoryLocation &LocB,
AAQueryInfo &AAQI) {
// Get the base object these pointers point to.
- const Value *UV1 = getUnderlyingObject(LocA.Ptr);
- const Value *UV2 = getUnderlyingObject(LocB.Ptr);
+ const Value *UV1 =
+ getUnderlyingObject(LocA.Ptr->stripPointerCastsAndInvariantGroups());
+ const Value *UV2 =
+ getUnderlyingObject(LocB.Ptr->stripPointerCastsAndInvariantGroups());
// If either of the underlying values is a global, they may be non-addr-taken
// globals, which we can answer queries about.
More information about the llvm-branch-commits
mailing list