mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 12:43:36 +01:00
[BasicAA] Fix BatchAA results for phi-phi assumptions
Add a flag that disables caching when computing aliasing results potentially based on a phi-phi NoAlias assumption. We'll still insert cache entries temporarily to catch infinite recursion, but will drop them afterwards, so they won't persist in BatchAA. Differential Revision: https://reviews.llvm.org/D91936
This commit is contained in:
parent
d9907a3994
commit
72e8f65d22
@ -162,6 +162,10 @@ private:
|
|||||||
/// Tracks instructions visited by pointsToConstantMemory.
|
/// Tracks instructions visited by pointsToConstantMemory.
|
||||||
SmallPtrSet<const Value *, 16> Visited;
|
SmallPtrSet<const Value *, 16> Visited;
|
||||||
|
|
||||||
|
/// Whether to disable persistent caching in AAQI. This is used to prevent
|
||||||
|
/// caching of results based on temporary assumptions.
|
||||||
|
bool DisableCache = false;
|
||||||
|
|
||||||
static const Value *
|
static const Value *
|
||||||
GetLinearExpression(const Value *V, APInt &Scale, APInt &Offset,
|
GetLinearExpression(const Value *V, APInt &Scale, APInt &Offset,
|
||||||
unsigned &ZExtBits, unsigned &SExtBits,
|
unsigned &ZExtBits, unsigned &SExtBits,
|
||||||
@ -216,6 +220,12 @@ private:
|
|||||||
LocationSize V2Size, const AAMDNodes &V2AATag,
|
LocationSize V2Size, const AAMDNodes &V2AATag,
|
||||||
AAQueryInfo &AAQI, const Value *O1 = nullptr,
|
AAQueryInfo &AAQI, const Value *O1 = nullptr,
|
||||||
const Value *O2 = nullptr);
|
const Value *O2 = nullptr);
|
||||||
|
|
||||||
|
AliasResult aliasCheckRecursive(const Value *V1, LocationSize V1Size,
|
||||||
|
const AAMDNodes &V1AATag, const Value *V2,
|
||||||
|
LocationSize V2Size, const AAMDNodes &V2AATag,
|
||||||
|
AAQueryInfo &AAQI, const Value *O1,
|
||||||
|
const Value *O2);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Analysis pass providing a never-invalidated alias analysis result.
|
/// Analysis pass providing a never-invalidated alias analysis result.
|
||||||
|
@ -1489,8 +1489,10 @@ AliasResult BasicAAResult::aliasPHI(const PHINode *PN, LocationSize PNSize,
|
|||||||
// operand from outside the PHIs' cycle that is MayAlias/MustAlias or
|
// operand from outside the PHIs' cycle that is MayAlias/MustAlias or
|
||||||
// there must be an operation on the PHIs within the PHIs' value cycle
|
// there must be an operation on the PHIs within the PHIs' value cycle
|
||||||
// that causes a MayAlias.
|
// that causes a MayAlias.
|
||||||
// Pretend the phis do not alias.
|
// Disable persistent caching, so intermediate results based on a
|
||||||
AliasResult Alias = NoAlias;
|
// possibly incorrect assumption do not get cached.
|
||||||
|
bool OrigDisableCache = DisableCache;
|
||||||
|
DisableCache = true;
|
||||||
AliasResult OrigAliasResult;
|
AliasResult OrigAliasResult;
|
||||||
{
|
{
|
||||||
// Limited lifetime iterator invalidated by the aliasCheck call below.
|
// Limited lifetime iterator invalidated by the aliasCheck call below.
|
||||||
@ -1501,6 +1503,7 @@ AliasResult BasicAAResult::aliasPHI(const PHINode *PN, LocationSize PNSize,
|
|||||||
CacheIt->second = NoAlias;
|
CacheIt->second = NoAlias;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AliasResult Alias = NoAlias;
|
||||||
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
|
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
|
||||||
AliasResult ThisAlias =
|
AliasResult ThisAlias =
|
||||||
aliasCheck(PN->getIncomingValue(i), PNSize, PNAAInfo,
|
aliasCheck(PN->getIncomingValue(i), PNSize, PNAAInfo,
|
||||||
@ -1514,6 +1517,7 @@ AliasResult BasicAAResult::aliasPHI(const PHINode *PN, LocationSize PNSize,
|
|||||||
// Reset if speculation failed.
|
// Reset if speculation failed.
|
||||||
if (Alias != NoAlias)
|
if (Alias != NoAlias)
|
||||||
AAQI.updateResult(Locs, OrigAliasResult);
|
AAQI.updateResult(Locs, OrigAliasResult);
|
||||||
|
DisableCache = OrigDisableCache;
|
||||||
return Alias;
|
return Alias;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1753,59 +1757,73 @@ AliasResult BasicAAResult::aliasCheck(const Value *V1, LocationSize V1Size,
|
|||||||
if (!Pair.second)
|
if (!Pair.second)
|
||||||
return Pair.first->second;
|
return Pair.first->second;
|
||||||
|
|
||||||
|
AliasResult Result = aliasCheckRecursive(V1, V1Size, V1AAInfo, V2, V2Size,
|
||||||
|
V2AAInfo, AAQI, O1, O2);
|
||||||
|
|
||||||
|
// If caching is disabled, remove the entry once the recursive checks are
|
||||||
|
// done. We only needed it to prevent infinite recursion.
|
||||||
|
if (DisableCache)
|
||||||
|
AAQI.AliasCache.erase(AAQI.AliasCache.find(Locs));
|
||||||
|
else if (Result != MayAlias)
|
||||||
|
AAQI.updateResult(Locs, Result);
|
||||||
|
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)) {
|
if (const GEPOperator *GV1 = dyn_cast<GEPOperator>(V1)) {
|
||||||
AliasResult Result =
|
AliasResult Result =
|
||||||
aliasGEP(GV1, V1Size, V1AAInfo, V2, V2Size, V2AAInfo, O1, O2, AAQI);
|
aliasGEP(GV1, V1Size, V1AAInfo, V2, V2Size, V2AAInfo, O1, O2, AAQI);
|
||||||
if (Result != MayAlias)
|
if (Result != MayAlias)
|
||||||
return AAQI.updateResult(Locs, Result);
|
return Result;
|
||||||
} else if (const GEPOperator *GV2 = dyn_cast<GEPOperator>(V2)) {
|
} else if (const GEPOperator *GV2 = dyn_cast<GEPOperator>(V2)) {
|
||||||
AliasResult Result =
|
AliasResult Result =
|
||||||
aliasGEP(GV2, V2Size, V2AAInfo, V1, V1Size, V1AAInfo, O2, O1, AAQI);
|
aliasGEP(GV2, V2Size, V2AAInfo, V1, V1Size, V1AAInfo, O2, O1, AAQI);
|
||||||
if (Result != MayAlias)
|
if (Result != MayAlias)
|
||||||
return AAQI.updateResult(Locs, Result);
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const PHINode *PN = dyn_cast<PHINode>(V1)) {
|
if (const PHINode *PN = dyn_cast<PHINode>(V1)) {
|
||||||
AliasResult Result =
|
AliasResult Result =
|
||||||
aliasPHI(PN, V1Size, V1AAInfo, V2, V2Size, V2AAInfo, O2, AAQI);
|
aliasPHI(PN, V1Size, V1AAInfo, V2, V2Size, V2AAInfo, O2, AAQI);
|
||||||
if (Result != MayAlias)
|
if (Result != MayAlias)
|
||||||
return AAQI.updateResult(Locs, Result);
|
return Result;
|
||||||
} else if (const PHINode *PN = dyn_cast<PHINode>(V2)) {
|
} else if (const PHINode *PN = dyn_cast<PHINode>(V2)) {
|
||||||
AliasResult Result =
|
AliasResult Result =
|
||||||
aliasPHI(PN, V2Size, V2AAInfo, V1, V1Size, V1AAInfo, O1, AAQI);
|
aliasPHI(PN, V2Size, V2AAInfo, V1, V1Size, V1AAInfo, O1, AAQI);
|
||||||
if (Result != MayAlias)
|
if (Result != MayAlias)
|
||||||
return AAQI.updateResult(Locs, Result);
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const SelectInst *S1 = dyn_cast<SelectInst>(V1)) {
|
if (const SelectInst *S1 = dyn_cast<SelectInst>(V1)) {
|
||||||
AliasResult Result =
|
AliasResult Result =
|
||||||
aliasSelect(S1, V1Size, V1AAInfo, V2, V2Size, V2AAInfo, O2, AAQI);
|
aliasSelect(S1, V1Size, V1AAInfo, V2, V2Size, V2AAInfo, O2, AAQI);
|
||||||
if (Result != MayAlias)
|
if (Result != MayAlias)
|
||||||
return AAQI.updateResult(Locs, Result);
|
return Result;
|
||||||
} else if (const SelectInst *S2 = dyn_cast<SelectInst>(V2)) {
|
} else if (const SelectInst *S2 = dyn_cast<SelectInst>(V2)) {
|
||||||
AliasResult Result =
|
AliasResult Result =
|
||||||
aliasSelect(S2, V2Size, V2AAInfo, V1, V1Size, V1AAInfo, O1, AAQI);
|
aliasSelect(S2, V2Size, V2AAInfo, V1, V1Size, V1AAInfo, O1, AAQI);
|
||||||
if (Result != MayAlias)
|
if (Result != MayAlias)
|
||||||
return AAQI.updateResult(Locs, Result);
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If both pointers are pointing into the same object and one of them
|
// 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.
|
// 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() &&
|
if (V1Size.isPrecise() && V2Size.isPrecise() &&
|
||||||
(isObjectSize(O1, V1Size.getValue(), DL, TLI, NullIsValidLocation) ||
|
(isObjectSize(O1, V1Size.getValue(), DL, TLI, NullIsValidLocation) ||
|
||||||
isObjectSize(O2, V2Size.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
|
// Recurse back into the best AA results we have, potentially with refined
|
||||||
// memory locations. We have already ensured that BasicAA has a MayAlias
|
// memory locations. We have already ensured that BasicAA has a MayAlias
|
||||||
// cache result for these, so any recursion back into BasicAA won't loop.
|
// cache result for these, so any recursion back into BasicAA won't loop.
|
||||||
AliasResult Result = getBestAAResults().alias(Locs.first, Locs.second, AAQI);
|
return getBestAAResults().alias(MemoryLocation(V1, V1Size, V1AAInfo),
|
||||||
if (Result != MayAlias)
|
MemoryLocation(V2, V2Size, V2AAInfo), AAQI);
|
||||||
return AAQI.updateResult(Locs, Result);
|
|
||||||
|
|
||||||
// MayAlias is already in the cache.
|
|
||||||
return MayAlias;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check whether two Values can be considered equivalent.
|
/// Check whether two Values can be considered equivalent.
|
||||||
|
@ -295,8 +295,7 @@ TEST_F(AliasAnalysisTest, BatchAAPhiAssumption) {
|
|||||||
|
|
||||||
BatchAAResults BatchAA(AA);
|
BatchAAResults BatchAA(AA);
|
||||||
EXPECT_EQ(MayAlias, BatchAA.alias(ALoc, BLoc));
|
EXPECT_EQ(MayAlias, BatchAA.alias(ALoc, BLoc));
|
||||||
// TODO: This is incorrect.
|
EXPECT_EQ(MayAlias, BatchAA.alias(ANextLoc, BNextLoc));
|
||||||
EXPECT_EQ(NoAlias, BatchAA.alias(ANextLoc, BNextLoc));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class AAPassInfraTest : public testing::Test {
|
class AAPassInfraTest : public testing::Test {
|
||||||
|
Loading…
Reference in New Issue
Block a user