[AA] Make ModRefInfo a bitmask enum (NFC)

Mark ModRefInfo as a bitmask enum, which allows using normal
& and | operators on it. This supersedes various functions like
unionModRef() and intersectModRef(). I think this makes the code
cleaner than going through helper functions...

Differential Revision: https://reviews.llvm.org/D130870
This commit is contained in:
Nikita Popov 2022-08-01 08:16:54 +02:00
parent 34ae308c73
commit b128e057c1
7 changed files with 40 additions and 38 deletions

View File

@ -152,6 +152,7 @@ enum class ModRefInfo : uint8_t {
Mod = 2,
/// The access may reference and may modify the value stored in memory.
ModRef = Ref | Mod,
LLVM_MARK_AS_BITMASK_ENUM(ModRef),
};
LLVM_NODISCARD inline bool isNoModRef(const ModRefInfo MRI) {
@ -170,25 +171,31 @@ LLVM_NODISCARD inline bool isRefSet(const ModRefInfo MRI) {
return static_cast<int>(MRI) & static_cast<int>(ModRefInfo::Ref);
}
[[deprecated("Use operator | instead")]]
LLVM_NODISCARD inline ModRefInfo setMod(const ModRefInfo MRI) {
return ModRefInfo(static_cast<int>(MRI) | static_cast<int>(ModRefInfo::Mod));
return MRI | ModRefInfo::Mod;
}
[[deprecated("Use operator | instead")]]
LLVM_NODISCARD inline ModRefInfo setRef(const ModRefInfo MRI) {
return ModRefInfo(static_cast<int>(MRI) | static_cast<int>(ModRefInfo::Ref));
return MRI | ModRefInfo::Ref;
}
[[deprecated("Use operator & instead")]]
LLVM_NODISCARD inline ModRefInfo clearMod(const ModRefInfo MRI) {
return ModRefInfo(static_cast<int>(MRI) & static_cast<int>(ModRefInfo::Ref));
return MRI & ModRefInfo::Ref;
}
[[deprecated("Use operator & instead")]]
LLVM_NODISCARD inline ModRefInfo clearRef(const ModRefInfo MRI) {
return ModRefInfo(static_cast<int>(MRI) & static_cast<int>(ModRefInfo::Mod));
return MRI & ModRefInfo::Mod;
}
[[deprecated("Use operator | instead")]]
LLVM_NODISCARD inline ModRefInfo unionModRef(const ModRefInfo MRI1,
const ModRefInfo MRI2) {
return ModRefInfo(static_cast<int>(MRI1) | static_cast<int>(MRI2));
return MRI1 | MRI2;
}
[[deprecated("Use operator & instead")]]
LLVM_NODISCARD inline ModRefInfo intersectModRef(const ModRefInfo MRI1,
const ModRefInfo MRI2) {
return ModRefInfo(static_cast<int>(MRI1) & static_cast<int>(MRI2));
return MRI1 & MRI2;
}
/// The locations at which a function might access memory.

View File

@ -178,7 +178,7 @@ ModRefInfo AAResults::getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) {
ModRefInfo Result = ModRefInfo::ModRef;
for (const auto &AA : AAs) {
Result = intersectModRef(Result, AA->getArgModRefInfo(Call, ArgIdx));
Result &= AA->getArgModRefInfo(Call, ArgIdx);
// Early-exit the moment we reach the bottom of the lattice.
if (isNoModRef(Result))
@ -226,7 +226,7 @@ ModRefInfo AAResults::getModRefInfo(const CallBase *Call,
ModRefInfo Result = ModRefInfo::ModRef;
for (const auto &AA : AAs) {
Result = intersectModRef(Result, AA->getModRefInfo(Call, Loc, AAQI));
Result &= AA->getModRefInfo(Call, Loc, AAQI);
// Early-exit the moment we reach the bottom of the lattice.
if (isNoModRef(Result))
@ -240,9 +240,9 @@ ModRefInfo AAResults::getModRefInfo(const CallBase *Call,
return ModRefInfo::NoModRef;
if (onlyReadsMemory(MRB))
Result = clearMod(Result);
Result &= ModRefInfo::Ref;
else if (onlyWritesMemory(MRB))
Result = clearRef(Result);
Result &= ModRefInfo::Mod;
if (onlyAccessesArgPointees(MRB) || onlyAccessesInaccessibleOrArgMem(MRB)) {
ModRefInfo AllArgsMask = ModRefInfo::NoModRef;
@ -255,23 +255,21 @@ ModRefInfo AAResults::getModRefInfo(const CallBase *Call,
MemoryLocation ArgLoc =
MemoryLocation::getForArgument(Call, ArgIdx, TLI);
AliasResult ArgAlias = alias(ArgLoc, Loc, AAQI);
if (ArgAlias != AliasResult::NoAlias) {
ModRefInfo ArgMask = getArgModRefInfo(Call, ArgIdx);
AllArgsMask = unionModRef(AllArgsMask, ArgMask);
}
if (ArgAlias != AliasResult::NoAlias)
AllArgsMask |= getArgModRefInfo(Call, ArgIdx);
}
}
// Return NoModRef if no alias found with any argument.
if (isNoModRef(AllArgsMask))
return ModRefInfo::NoModRef;
// Logical & between other AA analyses and argument analysis.
Result = intersectModRef(Result, AllArgsMask);
Result &= AllArgsMask;
}
// If Loc is a constant memory location, the call definitely could not
// modify the memory location.
if (isModSet(Result) && pointsToConstantMemory(Loc, AAQI, /*OrLocal*/ false))
Result = clearMod(Result);
Result &= ModRefInfo::Ref;
return Result;
}
@ -287,7 +285,7 @@ ModRefInfo AAResults::getModRefInfo(const CallBase *Call1,
ModRefInfo Result = ModRefInfo::ModRef;
for (const auto &AA : AAs) {
Result = intersectModRef(Result, AA->getModRefInfo(Call1, Call2, AAQI));
Result &= AA->getModRefInfo(Call1, Call2, AAQI);
// Early-exit the moment we reach the bottom of the lattice.
if (isNoModRef(Result))
@ -313,9 +311,9 @@ ModRefInfo AAResults::getModRefInfo(const CallBase *Call1,
// If Call1 only reads memory, the only dependence on Call2 can be
// from Call1 reading memory written by Call2.
if (onlyReadsMemory(Call1B))
Result = clearMod(Result);
Result &= ModRefInfo::Ref;
else if (onlyWritesMemory(Call1B))
Result = clearRef(Result);
Result &= ModRefInfo::Mod;
// If Call2 only access memory through arguments, accumulate the mod/ref
// information from Call1's references to the memory referenced by
@ -346,10 +344,9 @@ ModRefInfo AAResults::getModRefInfo(const CallBase *Call1,
// ModRefC1 indicates what Call1 might do to Call2ArgLoc, and we use
// above ArgMask to update dependence info.
ModRefInfo ModRefC1 = getModRefInfo(Call1, Call2ArgLoc, AAQI);
ArgMask = intersectModRef(ArgMask, ModRefC1);
ArgMask &= getModRefInfo(Call1, Call2ArgLoc, AAQI);
R = intersectModRef(unionModRef(R, ArgMask), Result);
R = (R | ArgMask) & Result;
if (R == Result)
break;
}
@ -378,7 +375,7 @@ ModRefInfo AAResults::getModRefInfo(const CallBase *Call1,
ModRefInfo ModRefC2 = getModRefInfo(Call2, Call1ArgLoc, AAQI);
if ((isModSet(ArgModRefC1) && isModOrRefSet(ModRefC2)) ||
(isRefSet(ArgModRefC1) && isModSet(ModRefC2)))
R = intersectModRef(unionModRef(R, ArgModRefC1), Result);
R = (R | ArgModRefC1) & Result;
if (R == Result)
break;
@ -746,7 +743,7 @@ bool AAResults::canInstructionRangeModRef(const Instruction &I1,
++E; // Convert from inclusive to exclusive range.
for (; I != E; ++I) // Check every instruction in range
if (isModOrRefSet(intersectModRef(getModRefInfo(&*I, Loc), Mode)))
if (isModOrRefSet(getModRefInfo(&*I, Loc) & Mode))
return true;
return false;
}

View File

@ -459,7 +459,7 @@ void AliasSetTracker::add(Instruction *I) {
using namespace PatternMatch;
if (Call->use_empty() &&
match(Call, m_Intrinsic<Intrinsic::invariant_start>()))
CallMask = clearMod(CallMask);
CallMask &= ModRefInfo::Ref;
for (auto IdxArgPair : enumerate(Call->args())) {
int ArgIdx = IdxArgPair.index();
@ -469,7 +469,7 @@ void AliasSetTracker::add(Instruction *I) {
MemoryLocation ArgLoc =
MemoryLocation::getForArgument(Call, ArgIdx, nullptr);
ModRefInfo ArgMask = AA.getArgModRefInfo(Call, ArgIdx);
ArgMask = intersectModRef(CallMask, ArgMask);
ArgMask &= CallMask;
if (!isNoModRef(ArgMask))
addPointer(ArgLoc, getAccessFromModRef(ArgMask));
}

View File

@ -940,12 +940,12 @@ ModRefInfo BasicAAResult::getModRefInfo(const CallBase *Call,
// Operand aliases 'Object', but call doesn't modify it. Strengthen
// initial assumption and keep looking in case if there are more aliases.
if (Call->onlyReadsMemory(OperandNo)) {
Result = setRef(Result);
Result |= ModRefInfo::Ref;
continue;
}
// Operand aliases 'Object' but call only writes into it.
if (Call->onlyWritesMemory(OperandNo)) {
Result = setMod(Result);
Result |= ModRefInfo::Mod;
continue;
}
// This operand aliases 'Object' and call reads and writes into it.
@ -988,9 +988,9 @@ ModRefInfo BasicAAResult::getModRefInfo(const CallBase *Call,
// It's also possible for Loc to alias both src and dest, or neither.
ModRefInfo rv = ModRefInfo::NoModRef;
if (SrcAA != AliasResult::NoAlias || Call->hasReadingOperandBundles())
rv = setRef(rv);
rv |= ModRefInfo::Ref;
if (DestAA != AliasResult::NoAlias || Call->hasClobberingOperandBundles())
rv = setMod(rv);
rv |= ModRefInfo::Mod;
return rv;
}

View File

@ -160,7 +160,7 @@ public:
if (AlignedMap *P = Info.getPointer()) {
auto I = P->Map.find(&GV);
if (I != P->Map.end())
GlobalMRI = unionModRef(GlobalMRI, I->second);
GlobalMRI |= I->second;
}
return GlobalMRI;
}
@ -185,7 +185,7 @@ public:
Info.setPointer(P);
}
auto &GlobalMRI = P->Map[&GV];
GlobalMRI = unionModRef(GlobalMRI, NewMRI);
GlobalMRI |= NewMRI;
}
/// Clear a global's ModRef info. Should be used when a global is being
@ -938,8 +938,8 @@ ModRefInfo GlobalsAAResult::getModRefInfo(const CallBase *Call,
if (const Function *F = Call->getCalledFunction())
if (NonAddressTakenGlobals.count(GV))
if (const FunctionInfo *FI = getFunctionInfo(F))
Known = unionModRef(FI->getModRefInfoForGlobal(*GV),
getModRefInfoForArgument(Call, GV, AAQI));
Known = FI->getModRefInfoForGlobal(*GV) |
getModRefInfoForArgument(Call, GV, AAQI);
return Known;
}

View File

@ -2003,8 +2003,7 @@ mayLoopAccessLocation(Value *Ptr, ModRefInfo Access, Loop *L,
for (auto *B : L->blocks())
for (auto &I : *B)
if (Ignored.count(&I) == 0 &&
isModOrRefSet(
intersectModRef(AA.getModRefInfo(&I, StoreLoc), Access)))
isModOrRefSet(AA.getModRefInfo(&I, StoreLoc) & Access))
return true;
return false;

View File

@ -1028,8 +1028,7 @@ mayLoopAccessLocation(Value *Ptr, ModRefInfo Access, Loop *L,
for (BasicBlock *B : L->blocks())
for (Instruction &I : *B)
if (!IgnoredInsts.contains(&I) &&
isModOrRefSet(
intersectModRef(AA.getModRefInfo(&I, StoreLoc), Access)))
isModOrRefSet(AA.getModRefInfo(&I, StoreLoc) & Access))
return true;
return false;
}