diff options
author | Nikita Popov <npopov@redhat.com> | 2022-09-01 16:51:00 +0200 |
---|---|---|
committer | Nikita Popov <npopov@redhat.com> | 2022-09-22 11:15:20 +0200 |
commit | ab25ea6d357e0446bc53cbc6a7372fc79f24740d (patch) | |
tree | ba89fb5749099348377421cb8ff1cda5861e33f8 /llvm/lib/Analysis/AliasAnalysis.cpp | |
parent | cc61c822e05c51e494c50d1e72f963750116ef08 (diff) | |
download | llvm-ab25ea6d357e0446bc53cbc6a7372fc79f24740d.zip llvm-ab25ea6d357e0446bc53cbc6a7372fc79f24740d.tar.gz llvm-ab25ea6d357e0446bc53cbc6a7372fc79f24740d.tar.bz2 |
[AA] Model operand bundles more precisely
Based on D130896, we can model operand bundles more precisely. In
addition to the baseline ModRefBehavior, a reading/clobbering operand
bundle may also read/write all locations. For example, a memcpy with
deopt bundle can read any memory, but only write argument memory.
This means that getModRefInfo() for memcpy with a pointer that does
not alias the arguments results in Ref, rather than ModRef, without
the need to implement any special handling.
Differential Revision: https://reviews.llvm.org/D130980
Diffstat (limited to 'llvm/lib/Analysis/AliasAnalysis.cpp')
-rw-r--r-- | llvm/lib/Analysis/AliasAnalysis.cpp | 48 |
1 files changed, 25 insertions, 23 deletions
diff --git a/llvm/lib/Analysis/AliasAnalysis.cpp b/llvm/lib/Analysis/AliasAnalysis.cpp index 85d17d0..2a2b49f 100644 --- a/llvm/lib/Analysis/AliasAnalysis.cpp +++ b/llvm/lib/Analysis/AliasAnalysis.cpp @@ -235,35 +235,37 @@ ModRefInfo AAResults::getModRefInfo(const CallBase *Call, // Try to refine the mod-ref info further using other API entry points to the // aggregate set of AA results. - auto MRB = getModRefBehavior(Call); - if (MRB.onlyAccessesInaccessibleMem()) - return ModRefInfo::NoModRef; - // TODO: Exclude inaccessible memory location here. - Result &= MRB.getModRef(); + // We can completely ignore inaccessible memory here, because MemoryLocations + // can only reference accessible memory. + auto MRB = getModRefBehavior(Call).getWithoutLoc( + FunctionModRefBehavior::InaccessibleMem); + if (MRB.doesNotAccessMemory()) + return ModRefInfo::NoModRef; - if (MRB.onlyAccessesArgPointees() || MRB.onlyAccessesInaccessibleOrArgMem()) { + ModRefInfo ArgMR = MRB.getModRef(FunctionModRefBehavior::ArgMem); + ModRefInfo OtherMR = + MRB.getWithoutLoc(FunctionModRefBehavior::ArgMem).getModRef(); + if ((ArgMR | OtherMR) != OtherMR) { + // Refine the modref info for argument memory. We only bother to do this + // if ArgMR is not a subset of OtherMR, otherwise this won't have an impact + // on the final result. ModRefInfo AllArgsMask = ModRefInfo::NoModRef; - if (MRB.doesAccessArgPointees()) { - for (const auto &I : llvm::enumerate(Call->args())) { - const Value *Arg = I.value(); - if (!Arg->getType()->isPointerTy()) - continue; - unsigned ArgIdx = I.index(); - MemoryLocation ArgLoc = - MemoryLocation::getForArgument(Call, ArgIdx, TLI); - AliasResult ArgAlias = alias(ArgLoc, Loc, AAQI); - if (ArgAlias != AliasResult::NoAlias) - AllArgsMask |= getArgModRefInfo(Call, ArgIdx); - } + for (const auto &I : llvm::enumerate(Call->args())) { + const Value *Arg = I.value(); + if (!Arg->getType()->isPointerTy()) + continue; + unsigned ArgIdx = I.index(); + MemoryLocation ArgLoc = MemoryLocation::getForArgument(Call, ArgIdx, TLI); + AliasResult ArgAlias = alias(ArgLoc, Loc, AAQI); + 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 &= AllArgsMask; + ArgMR &= AllArgsMask; } + Result &= ArgMR | OtherMR; + // If Loc is a constant memory location, the call definitely could not // modify the memory location. if (isModSet(Result) && pointsToConstantMemory(Loc, AAQI, /*OrLocal*/ false)) |