aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/LoopAccessAnalysis.cpp
diff options
context:
space:
mode:
authorFlorian Hahn <flo@fhahn.com>2020-07-30 19:12:28 +0100
committerFlorian Hahn <flo@fhahn.com>2020-07-30 19:21:14 +0100
commit2062b3707c1ef698deaa9abc571b937fdd077168 (patch)
tree9841a8f5a297ab319d2f8556a66973191db05987 /llvm/lib/Analysis/LoopAccessAnalysis.cpp
parent6b8c641d8ea2b1a0294f556450941199e06e65a5 (diff)
downloadllvm-2062b3707c1ef698deaa9abc571b937fdd077168.zip
llvm-2062b3707c1ef698deaa9abc571b937fdd077168.tar.gz
llvm-2062b3707c1ef698deaa9abc571b937fdd077168.tar.bz2
[LAA] Avoid adding pointers to the checks if they are not needed.
Currently we skip alias sets with only reads or a single write and no reads, but still add the pointers to the list of pointers in RtCheck. This can lead to cases where we try to access a pointer that does not exist when grouping checks. In most cases, the way we access PositionMap masked that, as the value would default to index 0. But in the example in PR46854 it causes a crash. This patch updates the logic to avoid adding pointers for alias sets that do not need any checks. It makes things slightly more verbose, by first checking the numbers of reads/writes and bailing out early if we don't need checks for the alias set. I think this makes the logic a bit simpler to follow. Reviewed By: anemet Differential Revision: https://reviews.llvm.org/D84608
Diffstat (limited to 'llvm/lib/Analysis/LoopAccessAnalysis.cpp')
-rw-r--r--llvm/lib/Analysis/LoopAccessAnalysis.cpp60
1 files changed, 33 insertions, 27 deletions
diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index ae282a7..f409cd3 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -393,7 +393,10 @@ void RuntimePointerChecking::groupChecks(
// equivalence class, the iteration order is deterministic.
for (auto MI = DepCands.member_begin(LeaderI), ME = DepCands.member_end();
MI != ME; ++MI) {
- unsigned Pointer = PositionMap[MI->getPointer()];
+ auto PointerI = PositionMap.find(MI->getPointer());
+ assert(PointerI != PositionMap.end() &&
+ "pointer in equivalence class not found in PositionMap");
+ unsigned Pointer = PointerI->second;
bool Merged = false;
// Mark this pointer as seen.
Seen.insert(Pointer);
@@ -726,52 +729,55 @@ bool AccessAnalysis::canCheckPtrAtRT(RuntimePointerChecking &RtCheck,
SmallVector<MemAccessInfo, 4> Retries;
+ // First, count how many write and read accesses are in the alias set. Also
+ // collect MemAccessInfos for later.
+ SmallVector<MemAccessInfo, 4> AccessInfos;
for (auto A : AS) {
Value *Ptr = A.getValue();
bool IsWrite = Accesses.count(MemAccessInfo(Ptr, true));
- MemAccessInfo Access(Ptr, IsWrite);
if (IsWrite)
++NumWritePtrChecks;
else
++NumReadPtrChecks;
+ AccessInfos.emplace_back(Ptr, IsWrite);
+ }
+ // We do not need runtime checks for this alias set, if there are no writes
+ // or a single write and no reads.
+ if (NumWritePtrChecks == 0 ||
+ (NumWritePtrChecks == 1 && NumReadPtrChecks == 0)) {
+ assert((AS.size() <= 1 ||
+ all_of(AS,
+ [this](auto AC) {
+ MemAccessInfo AccessWrite(AC.getValue(), true);
+ return DepCands.findValue(AccessWrite) == DepCands.end();
+ })) &&
+ "Can only skip updating CanDoRT below, if all entries in AS "
+ "are reads or there is at most 1 entry");
+ continue;
+ }
+
+ for (auto &Access : AccessInfos) {
if (!createCheckForAccess(RtCheck, Access, StridesMap, DepSetId, TheLoop,
RunningDepId, ASId, ShouldCheckWrap, false)) {
- LLVM_DEBUG(dbgs() << "LAA: Can't find bounds for ptr:" << *Ptr << '\n');
+ LLVM_DEBUG(dbgs() << "LAA: Can't find bounds for ptr:"
+ << *Access.getPointer() << '\n');
Retries.push_back(Access);
CanDoAliasSetRT = false;
}
}
- // If we have at least two writes or one write and a read then we need to
- // check them. But there is no need to checks if there is only one
- // dependence set for this alias set.
- //
// Note that this function computes CanDoRT and MayNeedRTCheck
// independently. For example CanDoRT=false, MayNeedRTCheck=false means that
// we have a pointer for which we couldn't find the bounds but we don't
// actually need to emit any checks so it does not matter.
- bool NeedsAliasSetRTCheck = false;
- if (!(IsDepCheckNeeded && CanDoAliasSetRT && RunningDepId == 2)) {
- NeedsAliasSetRTCheck = (NumWritePtrChecks >= 2 ||
- (NumReadPtrChecks >= 1 && NumWritePtrChecks >= 1));
- // For alias sets without at least 2 writes or 1 write and 1 read, there
- // is no need to generate RT checks and CanDoAliasSetRT for this alias set
- // does not impact whether runtime checks can be generated.
- if (!NeedsAliasSetRTCheck) {
- assert((AS.size() <= 1 ||
- all_of(AS,
- [this](auto AC) {
- MemAccessInfo AccessWrite(AC.getValue(), true);
- return DepCands.findValue(AccessWrite) ==
- DepCands.end();
- })) &&
- "Can only skip updating CanDoRT below, if all entries in AS "
- "are reads or there is at most 1 entry");
- continue;
- }
- }
+ //
+ // We need runtime checks for this alias set, if there are at least 2
+ // dependence sets (in which case RunningDepId > 2) or if we need to re-try
+ // any bound checks (because in that case the number of dependence sets is
+ // incomplete).
+ bool NeedsAliasSetRTCheck = RunningDepId > 2 || !Retries.empty();
// We need to perform run-time alias checks, but some pointers had bounds
// that couldn't be checked.