Skip to content

Commit 7aa8a67

Browse files
committed
Revert "[LAA] Initial support for runtime checks with pointer selects."
This reverts commit 5890b30 as per discussion on the review thread: https://reviews.llvm.org/D114487#3547560.
1 parent b0f868f commit 7aa8a67

File tree

3 files changed

+70
-113
lines changed

3 files changed

+70
-113
lines changed

llvm/include/llvm/Analysis/LoopAccessAnalysis.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -420,8 +420,8 @@ class RuntimePointerChecking {
420420
/// according to the assumptions that we've made during the analysis.
421421
/// The method might also version the pointer stride according to \p Strides,
422422
/// and add new predicates to \p PSE.
423-
void insert(Loop *Lp, Value *Ptr, const SCEV *PtrExpr, Type *AccessTy,
424-
bool WritePtr, unsigned DepSetId, unsigned ASId,
423+
void insert(Loop *Lp, Value *Ptr, Type *AccessTy, bool WritePtr,
424+
unsigned DepSetId, unsigned ASId, const ValueToValueMap &Strides,
425425
PredicatedScalarEvolution &PSE);
426426

427427
/// No run-time memory checking is necessary.

llvm/lib/Analysis/LoopAccessAnalysis.cpp

Lines changed: 67 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
#include "llvm/IR/Instructions.h"
4848
#include "llvm/IR/Operator.h"
4949
#include "llvm/IR/PassManager.h"
50-
#include "llvm/IR/PatternMatch.h"
5150
#include "llvm/IR/Type.h"
5251
#include "llvm/IR/Value.h"
5352
#include "llvm/IR/ValueHandle.h"
@@ -66,7 +65,6 @@
6665
#include <vector>
6766

6867
using namespace llvm;
69-
using namespace llvm::PatternMatch;
7068

7169
#define DEBUG_TYPE "loop-accesses"
7270

@@ -190,19 +188,22 @@ RuntimeCheckingPtrGroup::RuntimeCheckingPtrGroup(
190188
///
191189
/// There is no conflict when the intervals are disjoint:
192190
/// NoConflict = (P2.Start >= P1.End) || (P1.Start >= P2.End)
193-
void RuntimePointerChecking::insert(Loop *Lp, Value *Ptr, const SCEV *PtrExpr,
194-
Type *AccessTy, bool WritePtr,
195-
unsigned DepSetId, unsigned ASId,
191+
void RuntimePointerChecking::insert(Loop *Lp, Value *Ptr, Type *AccessTy,
192+
bool WritePtr, unsigned DepSetId,
193+
unsigned ASId,
194+
const ValueToValueMap &Strides,
196195
PredicatedScalarEvolution &PSE) {
196+
// Get the stride replaced scev.
197+
const SCEV *Sc = replaceSymbolicStrideSCEV(PSE, Strides, Ptr);
197198
ScalarEvolution *SE = PSE.getSE();
198199

199200
const SCEV *ScStart;
200201
const SCEV *ScEnd;
201202

202-
if (SE->isLoopInvariant(PtrExpr, Lp)) {
203-
ScStart = ScEnd = PtrExpr;
203+
if (SE->isLoopInvariant(Sc, Lp)) {
204+
ScStart = ScEnd = Sc;
204205
} else {
205-
const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(PtrExpr);
206+
const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(Sc);
206207
assert(AR && "Invalid addrec expression");
207208
const SCEV *Ex = PSE.getBackedgeTakenCount();
208209

@@ -229,7 +230,7 @@ void RuntimePointerChecking::insert(Loop *Lp, Value *Ptr, const SCEV *PtrExpr,
229230
const SCEV *EltSizeSCEV = SE->getStoreSizeOfExpr(IdxTy, AccessTy);
230231
ScEnd = SE->getAddExpr(ScEnd, EltSizeSCEV);
231232

232-
Pointers.emplace_back(Ptr, ScStart, ScEnd, WritePtr, DepSetId, ASId, PtrExpr);
233+
Pointers.emplace_back(Ptr, ScStart, ScEnd, WritePtr, DepSetId, ASId, Sc);
233234
}
234235

235236
void RuntimePointerChecking::tryToCreateDiffCheck(
@@ -455,11 +456,9 @@ void RuntimePointerChecking::groupChecks(
455456

456457
unsigned TotalComparisons = 0;
457458

458-
DenseMap<Value *, SmallVector<unsigned>> PositionMap;
459-
for (unsigned Index = 0; Index < Pointers.size(); ++Index) {
460-
auto Iter = PositionMap.insert({Pointers[Index].PointerValue, {}});
461-
Iter.first->second.push_back(Index);
462-
}
459+
DenseMap<Value *, unsigned> PositionMap;
460+
for (unsigned Index = 0; Index < Pointers.size(); ++Index)
461+
PositionMap[Pointers[Index].PointerValue] = Index;
463462

464463
// We need to keep track of what pointers we've already seen so we
465464
// don't process them twice.
@@ -490,35 +489,34 @@ void RuntimePointerChecking::groupChecks(
490489
auto PointerI = PositionMap.find(MI->getPointer());
491490
assert(PointerI != PositionMap.end() &&
492491
"pointer in equivalence class not found in PositionMap");
493-
for (unsigned Pointer : PointerI->second) {
494-
bool Merged = false;
495-
// Mark this pointer as seen.
496-
Seen.insert(Pointer);
497-
498-
// Go through all the existing sets and see if we can find one
499-
// which can include this pointer.
500-
for (RuntimeCheckingPtrGroup &Group : Groups) {
501-
// Don't perform more than a certain amount of comparisons.
502-
// This should limit the cost of grouping the pointers to something
503-
// reasonable. If we do end up hitting this threshold, the algorithm
504-
// will create separate groups for all remaining pointers.
505-
if (TotalComparisons > MemoryCheckMergeThreshold)
506-
break;
507-
508-
TotalComparisons++;
509-
510-
if (Group.addPointer(Pointer, *this)) {
511-
Merged = true;
512-
break;
513-
}
492+
unsigned Pointer = PointerI->second;
493+
bool Merged = false;
494+
// Mark this pointer as seen.
495+
Seen.insert(Pointer);
496+
497+
// Go through all the existing sets and see if we can find one
498+
// which can include this pointer.
499+
for (RuntimeCheckingPtrGroup &Group : Groups) {
500+
// Don't perform more than a certain amount of comparisons.
501+
// This should limit the cost of grouping the pointers to something
502+
// reasonable. If we do end up hitting this threshold, the algorithm
503+
// will create separate groups for all remaining pointers.
504+
if (TotalComparisons > MemoryCheckMergeThreshold)
505+
break;
506+
507+
TotalComparisons++;
508+
509+
if (Group.addPointer(Pointer, *this)) {
510+
Merged = true;
511+
break;
514512
}
515-
516-
if (!Merged)
517-
// We couldn't add this pointer to any existing set or the threshold
518-
// for the number of comparisons has been reached. Create a new group
519-
// to hold the current pointer.
520-
Groups.push_back(RuntimeCheckingPtrGroup(Pointer, *this));
521513
}
514+
515+
if (!Merged)
516+
// We couldn't add this pointer to any existing set or the threshold
517+
// for the number of comparisons has been reached. Create a new group
518+
// to hold the current pointer.
519+
Groups.push_back(RuntimeCheckingPtrGroup(Pointer, *this));
522520
}
523521

524522
// We've computed the grouped checks for this partition.
@@ -717,8 +715,11 @@ class AccessAnalysis {
717715
/// Check whether a pointer can participate in a runtime bounds check.
718716
/// If \p Assume, try harder to prove that we can compute the bounds of \p Ptr
719717
/// by adding run-time checks (overflow checks) if necessary.
720-
static bool hasComputableBounds(PredicatedScalarEvolution &PSE, Value *Ptr,
721-
const SCEV *PtrScev, Loop *L, bool Assume) {
718+
static bool hasComputableBounds(PredicatedScalarEvolution &PSE,
719+
const ValueToValueMap &Strides, Value *Ptr,
720+
Loop *L, bool Assume) {
721+
const SCEV *PtrScev = replaceSymbolicStrideSCEV(PSE, Strides, Ptr);
722+
722723
// The bounds for loop-invariant pointer is trivial.
723724
if (PSE.getSE()->isLoopInvariant(PtrScev, L))
724725
return true;
@@ -781,56 +782,34 @@ bool AccessAnalysis::createCheckForAccess(RuntimePointerChecking &RtCheck,
781782
bool Assume) {
782783
Value *Ptr = Access.getPointer();
783784

784-
ScalarEvolution &SE = *PSE.getSE();
785-
SmallVector<const SCEV *> TranslatedPtrs;
786-
if (auto *SI = dyn_cast<SelectInst>(Ptr))
787-
TranslatedPtrs = {SE.getSCEV(SI->getOperand(1)),
788-
SE.getSCEV(SI->getOperand(2))};
789-
else
790-
TranslatedPtrs = {replaceSymbolicStrideSCEV(PSE, StridesMap, Ptr)};
785+
if (!hasComputableBounds(PSE, StridesMap, Ptr, TheLoop, Assume))
786+
return false;
791787

792-
for (const SCEV *PtrExpr : TranslatedPtrs) {
793-
if (!hasComputableBounds(PSE, Ptr, PtrExpr, TheLoop, Assume))
788+
// When we run after a failing dependency check we have to make sure
789+
// we don't have wrapping pointers.
790+
if (ShouldCheckWrap && !isNoWrap(PSE, StridesMap, Ptr, AccessTy, TheLoop)) {
791+
auto *Expr = PSE.getSCEV(Ptr);
792+
if (!Assume || !isa<SCEVAddRecExpr>(Expr))
794793
return false;
794+
PSE.setNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW);
795+
}
795796

796-
// When we run after a failing dependency check we have to make sure
797-
// we don't have wrapping pointers.
798-
if (ShouldCheckWrap) {
799-
// Skip wrap checking when translating pointers.
800-
if (TranslatedPtrs.size() > 1)
801-
return false;
797+
// The id of the dependence set.
798+
unsigned DepId;
802799

803-
if (!isNoWrap(PSE, StridesMap, Ptr, AccessTy, TheLoop)) {
804-
auto *Expr = PSE.getSCEV(Ptr);
805-
if (!Assume || !isa<SCEVAddRecExpr>(Expr))
806-
return false;
807-
PSE.setNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW);
808-
}
809-
}
810-
// If there's only one option for Ptr, look it up after bounds and wrap
811-
// checking, because assumptions might have been added to PSE.
812-
if (TranslatedPtrs.size() == 1)
813-
TranslatedPtrs[0] = replaceSymbolicStrideSCEV(PSE, StridesMap, Ptr);
814-
}
815-
816-
for (const SCEV *PtrExpr : TranslatedPtrs) {
817-
// The id of the dependence set.
818-
unsigned DepId;
819-
820-
if (isDependencyCheckNeeded()) {
821-
Value *Leader = DepCands.getLeaderValue(Access).getPointer();
822-
unsigned &LeaderId = DepSetId[Leader];
823-
if (!LeaderId)
824-
LeaderId = RunningDepId++;
825-
DepId = LeaderId;
826-
} else
827-
// Each access has its own dependence set.
828-
DepId = RunningDepId++;
800+
if (isDependencyCheckNeeded()) {
801+
Value *Leader = DepCands.getLeaderValue(Access).getPointer();
802+
unsigned &LeaderId = DepSetId[Leader];
803+
if (!LeaderId)
804+
LeaderId = RunningDepId++;
805+
DepId = LeaderId;
806+
} else
807+
// Each access has its own dependence set.
808+
DepId = RunningDepId++;
829809

830-
bool IsWrite = Access.getInt();
831-
RtCheck.insert(TheLoop, Ptr, PtrExpr, AccessTy, IsWrite, DepId, ASId, PSE);
832-
LLVM_DEBUG(dbgs() << "LAA: Found a runtime check ptr:" << *Ptr << '\n');
833-
}
810+
bool IsWrite = Access.getInt();
811+
RtCheck.insert(TheLoop, Ptr, AccessTy, IsWrite, DepId, ASId, StridesMap, PSE);
812+
LLVM_DEBUG(dbgs() << "LAA: Found a runtime check ptr:" << *Ptr << '\n');
834813

835814
return true;
836815
}

llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,10 @@ target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
44

55
; CHECK-LABEL: function 'forked_ptrs_simple':
66
; CHECK-NEXT: loop:
7-
; CHECK-NEXT: Memory dependences are safe with run-time checks
7+
; CHECK-NEXT: Report: cannot identify array bounds
88
; CHECK-NEXT: Dependences:
99
; CHECK-NEXT: Run-time memory checks:
10-
; CHECK-NEXT: Check 0:
11-
; CHECK-NEXT: Comparing group ([[G1:.+]]):
12-
; CHECK-NEXT: %gep.Dest = getelementptr inbounds float, float* %Dest, i64 %iv
13-
; CHECK-NEXT: %gep.Dest = getelementptr inbounds float, float* %Dest, i64 %iv
14-
; CHECK-NEXT: Against group ([[G2:.+]]):
15-
; CHECK-NEXT: %select = select i1 %cmp, float* %gep.1, float* %gep.2
16-
; CHECK-NEXT: Check 1:
17-
; CHECK-NEXT: Comparing group ([[G1]]):
18-
; CHECK-NEXT: %gep.Dest = getelementptr inbounds float, float* %Dest, i64 %iv
19-
; CHECK-NEXT: %gep.Dest = getelementptr inbounds float, float* %Dest, i64 %iv
20-
; CHECK-NEXT: Against group ([[G3:.+]]):
21-
; CHECK-NEXT: %select = select i1 %cmp, float* %gep.1, float* %gep.2
2210
; CHECK-NEXT: Grouped accesses:
23-
; CHECK-NEXT: Group [[G1]]
24-
; CHECK-NEXT: (Low: %Dest High: (400 + %Dest))
25-
; CHECK-NEXT: Member: {%Dest,+,4}<nuw><%loop>
26-
; CHECK-NEXT: Member: {%Dest,+,4}<nuw><%loop>
27-
; CHECK-NEXT: Group [[G2]]:
28-
; CHECK-NEXT: (Low: %Base1 High: (400 + %Base1))
29-
; CHECK-NEXT: Member: {%Base1,+,4}<nw><%loop>
30-
; CHECK-NEXT: Group [[G3]]:
31-
; CHECK-NEXT: (Low: %Base2 High: (400 + %Base2))
32-
; CHECK-NEXT: Member: {%Base2,+,4}<nw><%loop>
3311
; CHECK-EMPTY:
3412
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
3513
; CHECK-NEXT: SCEV assumptions:

0 commit comments

Comments
 (0)