Skip to content

Commit ff31020

Browse files
committed
[OpaquePtr][LoopAccessAnalysis] Support opaque pointers
Previously we relied on the pointee type to determine what type we need to do runtime pointer access checks. With opaque pointers, we can access a pointer with more than one type, so now we keep track of all the types we're accessing a pointer's memory with. Also some other minor getPointerElementType() removals. Reviewed By: #opaque-pointers, nikic Differential Revision: https://reviews.llvm.org/D119047
1 parent 022baf7 commit ff31020

File tree

3 files changed

+244
-54
lines changed

3 files changed

+244
-54
lines changed

llvm/include/llvm/Analysis/LoopAccessAnalysis.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,8 +406,8 @@ class RuntimePointerChecking {
406406
/// according to the assumptions that we've made during the analysis.
407407
/// The method might also version the pointer stride according to \p Strides,
408408
/// and add new predicates to \p PSE.
409-
void insert(Loop *Lp, Value *Ptr, bool WritePtr, unsigned DepSetId,
410-
unsigned ASId, const ValueToValueMap &Strides,
409+
void insert(Loop *Lp, Value *Ptr, Type *AccessTy, bool WritePtr,
410+
unsigned DepSetId, unsigned ASId, const ValueToValueMap &Strides,
411411
PredicatedScalarEvolution &PSE);
412412

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

llvm/lib/Analysis/LoopAccessAnalysis.cpp

Lines changed: 63 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,9 @@ RuntimeCheckingPtrGroup::RuntimeCheckingPtrGroup(
189189
///
190190
/// There is no conflict when the intervals are disjoint:
191191
/// NoConflict = (P2.Start >= P1.End) || (P1.Start >= P2.End)
192-
void RuntimePointerChecking::insert(Loop *Lp, Value *Ptr, bool WritePtr,
193-
unsigned DepSetId, unsigned ASId,
192+
void RuntimePointerChecking::insert(Loop *Lp, Value *Ptr, Type *AccessTy,
193+
bool WritePtr, unsigned DepSetId,
194+
unsigned ASId,
194195
const ValueToValueMap &Strides,
195196
PredicatedScalarEvolution &PSE) {
196197
// Get the stride replaced scev.
@@ -227,8 +228,7 @@ void RuntimePointerChecking::insert(Loop *Lp, Value *Ptr, bool WritePtr,
227228
// Add the size of the pointed element to ScEnd.
228229
auto &DL = Lp->getHeader()->getModule()->getDataLayout();
229230
Type *IdxTy = DL.getIndexType(Ptr->getType());
230-
const SCEV *EltSizeSCEV =
231-
SE->getStoreSizeOfExpr(IdxTy, Ptr->getType()->getPointerElementType());
231+
const SCEV *EltSizeSCEV = SE->getStoreSizeOfExpr(IdxTy, AccessTy);
232232
ScEnd = SE->getAddExpr(ScEnd, EltSizeSCEV);
233233

234234
Pointers.emplace_back(Ptr, ScStart, ScEnd, WritePtr, DepSetId, ASId, Sc);
@@ -522,19 +522,19 @@ class AccessAnalysis {
522522
: TheLoop(TheLoop), AST(*AA), LI(LI), DepCands(DA), PSE(PSE) {}
523523

524524
/// Register a load and whether it is only read from.
525-
void addLoad(MemoryLocation &Loc, bool IsReadOnly) {
525+
void addLoad(MemoryLocation &Loc, Type *AccessTy, bool IsReadOnly) {
526526
Value *Ptr = const_cast<Value*>(Loc.Ptr);
527527
AST.add(Ptr, LocationSize::beforeOrAfterPointer(), Loc.AATags);
528-
Accesses.insert(MemAccessInfo(Ptr, false));
528+
Accesses[MemAccessInfo(Ptr, false)].insert(AccessTy);
529529
if (IsReadOnly)
530530
ReadOnlyPtr.insert(Ptr);
531531
}
532532

533533
/// Register a store.
534-
void addStore(MemoryLocation &Loc) {
534+
void addStore(MemoryLocation &Loc, Type *AccessTy) {
535535
Value *Ptr = const_cast<Value*>(Loc.Ptr);
536536
AST.add(Ptr, LocationSize::beforeOrAfterPointer(), Loc.AATags);
537-
Accesses.insert(MemAccessInfo(Ptr, true));
537+
Accesses[MemAccessInfo(Ptr, true)].insert(AccessTy);
538538
}
539539

540540
/// Check if we can emit a run-time no-alias check for \p Access.
@@ -545,12 +545,11 @@ class AccessAnalysis {
545545
/// we will attempt to use additional run-time checks in order to get
546546
/// the bounds of the pointer.
547547
bool createCheckForAccess(RuntimePointerChecking &RtCheck,
548-
MemAccessInfo Access,
548+
MemAccessInfo Access, Type *AccessTy,
549549
const ValueToValueMap &Strides,
550550
DenseMap<Value *, unsigned> &DepSetId,
551551
Loop *TheLoop, unsigned &RunningDepId,
552-
unsigned ASId, bool ShouldCheckStride,
553-
bool Assume);
552+
unsigned ASId, bool ShouldCheckStride, bool Assume);
554553

555554
/// Check whether we can check the pointers at runtime for
556555
/// non-intersection.
@@ -583,14 +582,15 @@ class AccessAnalysis {
583582
MemAccessInfoList &getDependenciesToCheck() { return CheckDeps; }
584583

585584
private:
586-
typedef SetVector<MemAccessInfo> PtrAccessSet;
585+
typedef MapVector<MemAccessInfo, SmallSetVector<Type *, 1>> PtrAccessMap;
587586

588587
/// Go over all memory access and check whether runtime pointer checks
589588
/// are needed and build sets of dependency check candidates.
590589
void processMemAccesses();
591590

592-
/// Set of all accesses.
593-
PtrAccessSet Accesses;
591+
/// Map of all accesses. Values are the types used to access memory pointed to
592+
/// by the pointer.
593+
PtrAccessMap Accesses;
594594

595595
/// The loop being checked.
596596
const Loop *TheLoop;
@@ -652,12 +652,12 @@ static bool hasComputableBounds(PredicatedScalarEvolution &PSE,
652652

653653
/// Check whether a pointer address cannot wrap.
654654
static bool isNoWrap(PredicatedScalarEvolution &PSE,
655-
const ValueToValueMap &Strides, Value *Ptr, Loop *L) {
655+
const ValueToValueMap &Strides, Value *Ptr, Type *AccessTy,
656+
Loop *L) {
656657
const SCEV *PtrScev = PSE.getSCEV(Ptr);
657658
if (PSE.getSE()->isLoopInvariant(PtrScev, L))
658659
return true;
659660

660-
Type *AccessTy = Ptr->getType()->getPointerElementType();
661661
int64_t Stride = getPtrStride(PSE, AccessTy, Ptr, L, Strides);
662662
if (Stride == 1 || PSE.hasNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW))
663663
return true;
@@ -689,7 +689,7 @@ static void visitPointers(Value *StartPtr, const Loop &InnermostLoop,
689689
}
690690

691691
bool AccessAnalysis::createCheckForAccess(RuntimePointerChecking &RtCheck,
692-
MemAccessInfo Access,
692+
MemAccessInfo Access, Type *AccessTy,
693693
const ValueToValueMap &StridesMap,
694694
DenseMap<Value *, unsigned> &DepSetId,
695695
Loop *TheLoop, unsigned &RunningDepId,
@@ -702,7 +702,7 @@ bool AccessAnalysis::createCheckForAccess(RuntimePointerChecking &RtCheck,
702702

703703
// When we run after a failing dependency check we have to make sure
704704
// we don't have wrapping pointers.
705-
if (ShouldCheckWrap && !isNoWrap(PSE, StridesMap, Ptr, TheLoop)) {
705+
if (ShouldCheckWrap && !isNoWrap(PSE, StridesMap, Ptr, AccessTy, TheLoop)) {
706706
auto *Expr = PSE.getSCEV(Ptr);
707707
if (!Assume || !isa<SCEVAddRecExpr>(Expr))
708708
return false;
@@ -723,11 +723,11 @@ bool AccessAnalysis::createCheckForAccess(RuntimePointerChecking &RtCheck,
723723
DepId = RunningDepId++;
724724

725725
bool IsWrite = Access.getInt();
726-
RtCheck.insert(TheLoop, Ptr, IsWrite, DepId, ASId, StridesMap, PSE);
726+
RtCheck.insert(TheLoop, Ptr, AccessTy, IsWrite, DepId, ASId, StridesMap, PSE);
727727
LLVM_DEBUG(dbgs() << "LAA: Found a runtime check ptr:" << *Ptr << '\n');
728728

729729
return true;
730-
}
730+
}
731731

732732
bool AccessAnalysis::canCheckPtrAtRT(RuntimePointerChecking &RtCheck,
733733
ScalarEvolution *SE, Loop *TheLoop,
@@ -788,12 +788,15 @@ bool AccessAnalysis::canCheckPtrAtRT(RuntimePointerChecking &RtCheck,
788788
}
789789

790790
for (auto &Access : AccessInfos) {
791-
if (!createCheckForAccess(RtCheck, Access, StridesMap, DepSetId, TheLoop,
792-
RunningDepId, ASId, ShouldCheckWrap, false)) {
793-
LLVM_DEBUG(dbgs() << "LAA: Can't find bounds for ptr:"
794-
<< *Access.getPointer() << '\n');
795-
Retries.push_back(Access);
796-
CanDoAliasSetRT = false;
791+
for (auto &AccessTy : Accesses[Access]) {
792+
if (!createCheckForAccess(RtCheck, Access, AccessTy, StridesMap,
793+
DepSetId, TheLoop, RunningDepId, ASId,
794+
ShouldCheckWrap, false)) {
795+
LLVM_DEBUG(dbgs() << "LAA: Can't find bounds for ptr:"
796+
<< *Access.getPointer() << '\n');
797+
Retries.push_back(Access);
798+
CanDoAliasSetRT = false;
799+
}
797800
}
798801
}
799802

@@ -815,13 +818,16 @@ bool AccessAnalysis::canCheckPtrAtRT(RuntimePointerChecking &RtCheck,
815818
// We know that we need these checks, so we can now be more aggressive
816819
// and add further checks if required (overflow checks).
817820
CanDoAliasSetRT = true;
818-
for (auto Access : Retries)
819-
if (!createCheckForAccess(RtCheck, Access, StridesMap, DepSetId,
820-
TheLoop, RunningDepId, ASId,
821-
ShouldCheckWrap, /*Assume=*/true)) {
822-
CanDoAliasSetRT = false;
823-
break;
821+
for (auto Access : Retries) {
822+
for (auto &AccessTy : Accesses[Access]) {
823+
if (!createCheckForAccess(RtCheck, Access, AccessTy, StridesMap,
824+
DepSetId, TheLoop, RunningDepId, ASId,
825+
ShouldCheckWrap, /*Assume=*/true)) {
826+
CanDoAliasSetRT = false;
827+
break;
828+
}
824829
}
830+
}
825831
}
826832

827833
CanDoRT &= CanDoAliasSetRT;
@@ -886,9 +892,12 @@ void AccessAnalysis::processMemAccesses() {
886892
LLVM_DEBUG(dbgs() << "LAA: Accesses(" << Accesses.size() << "):\n");
887893
LLVM_DEBUG({
888894
for (auto A : Accesses)
889-
dbgs() << "\t" << *A.getPointer() << " (" <<
890-
(A.getInt() ? "write" : (ReadOnlyPtr.count(A.getPointer()) ?
891-
"read-only" : "read")) << ")\n";
895+
dbgs() << "\t" << *A.first.getPointer() << " ("
896+
<< (A.first.getInt()
897+
? "write"
898+
: (ReadOnlyPtr.count(A.first.getPointer()) ? "read-only"
899+
: "read"))
900+
<< ")\n";
892901
});
893902

894903
// The AliasSetTracker has nicely partitioned our pointers by metadata
@@ -907,24 +916,24 @@ void AccessAnalysis::processMemAccesses() {
907916
UnderlyingObjToAccessMap ObjToLastAccess;
908917

909918
// Set of access to check after all writes have been processed.
910-
PtrAccessSet DeferredAccesses;
919+
PtrAccessMap DeferredAccesses;
911920

912921
// Iterate over each alias set twice, once to process read/write pointers,
913922
// and then to process read-only pointers.
914923
for (int SetIteration = 0; SetIteration < 2; ++SetIteration) {
915924
bool UseDeferred = SetIteration > 0;
916-
PtrAccessSet &S = UseDeferred ? DeferredAccesses : Accesses;
925+
PtrAccessMap &S = UseDeferred ? DeferredAccesses : Accesses;
917926

918927
for (const auto &AV : AS) {
919928
Value *Ptr = AV.getValue();
920929

921930
// For a single memory access in AliasSetTracker, Accesses may contain
922931
// both read and write, and they both need to be handled for CheckDeps.
923932
for (const auto &AC : S) {
924-
if (AC.getPointer() != Ptr)
933+
if (AC.first.getPointer() != Ptr)
925934
continue;
926935

927-
bool IsWrite = AC.getInt();
936+
bool IsWrite = AC.first.getInt();
928937

929938
// If we're using the deferred access set, then it contains only
930939
// reads.
@@ -946,7 +955,9 @@ void AccessAnalysis::processMemAccesses() {
946955
// consecutive as "read-only" pointers (so that we check
947956
// "a[b[i]] +="). Hence, we need the second check for "!IsWrite".
948957
if (!UseDeferred && IsReadOnlyPtr) {
949-
DeferredAccesses.insert(Access);
958+
// We only use the pointer keys, the types vector values don't
959+
// matter.
960+
DeferredAccesses.insert({Access, {}});
950961
continue;
951962
}
952963

@@ -1518,8 +1529,8 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
15181529
Value *BPtr = B.getPointer();
15191530
bool AIsWrite = A.getInt();
15201531
bool BIsWrite = B.getInt();
1521-
Type *ATy = APtr->getType()->getPointerElementType();
1522-
Type *BTy = BPtr->getType()->getPointerElementType();
1532+
Type *ATy = getLoadStoreType(InstMap[AIdx]);
1533+
Type *BTy = getLoadStoreType(InstMap[BIdx]);
15231534

15241535
// Two reads are independent.
15251536
if (!AIsWrite && !BIsWrite)
@@ -1842,8 +1853,6 @@ bool LoopAccessInfo::canAnalyzeLoop() {
18421853
void LoopAccessInfo::analyzeLoop(AAResults *AA, LoopInfo *LI,
18431854
const TargetLibraryInfo *TLI,
18441855
DominatorTree *DT) {
1845-
typedef SmallPtrSet<Value*, 16> ValueSet;
1846-
18471856
// Holds the Load and Store instructions.
18481857
SmallVector<LoadInst *, 16> Loads;
18491858
SmallVector<StoreInst *, 16> Stores;
@@ -1975,11 +1984,11 @@ void LoopAccessInfo::analyzeLoop(AAResults *AA, LoopInfo *LI,
19751984
// for read and once for write, it will only appear once (on the write
19761985
// list). This is okay, since we are going to check for conflicts between
19771986
// writes and between reads and writes, but not between reads and reads.
1978-
ValueSet Seen;
1987+
SmallSet<std::pair<Value *, Type *>, 16> Seen;
19791988

19801989
// Record uniform store addresses to identify if we have multiple stores
19811990
// to the same address.
1982-
ValueSet UniformStores;
1991+
SmallPtrSet<Value *, 16> UniformStores;
19831992

19841993
for (StoreInst *ST : Stores) {
19851994
Value *Ptr = ST->getPointerOperand();
@@ -1990,7 +1999,8 @@ void LoopAccessInfo::analyzeLoop(AAResults *AA, LoopInfo *LI,
19901999

19912000
// If we did *not* see this pointer before, insert it to the read-write
19922001
// list. At this phase it is only a 'write' list.
1993-
if (Seen.insert(Ptr).second) {
2002+
Type *AccessTy = getLoadStoreType(ST);
2003+
if (Seen.insert({Ptr, AccessTy}).second) {
19942004
++NumReadWrites;
19952005

19962006
MemoryLocation Loc = MemoryLocation::get(ST);
@@ -2001,9 +2011,9 @@ void LoopAccessInfo::analyzeLoop(AAResults *AA, LoopInfo *LI,
20012011
Loc.AATags.TBAA = nullptr;
20022012

20032013
visitPointers(const_cast<Value *>(Loc.Ptr), *TheLoop,
2004-
[&Accesses, Loc](Value *Ptr) {
2014+
[&Accesses, AccessTy, Loc](Value *Ptr) {
20052015
MemoryLocation NewLoc = Loc.getWithNewPtr(Ptr);
2006-
Accesses.addStore(NewLoc);
2016+
Accesses.addStore(NewLoc, AccessTy);
20072017
});
20082018
}
20092019
}
@@ -2027,7 +2037,8 @@ void LoopAccessInfo::analyzeLoop(AAResults *AA, LoopInfo *LI,
20272037
// read a few words, modify, and write a few words, and some of the
20282038
// words may be written to the same address.
20292039
bool IsReadOnlyPtr = false;
2030-
if (Seen.insert(Ptr).second ||
2040+
Type *AccessTy = getLoadStoreType(LD);
2041+
if (Seen.insert({Ptr, AccessTy}).second ||
20312042
!getPtrStride(*PSE, LD->getType(), Ptr, TheLoop, SymbolicStrides)) {
20322043
++NumReads;
20332044
IsReadOnlyPtr = true;
@@ -2049,9 +2060,9 @@ void LoopAccessInfo::analyzeLoop(AAResults *AA, LoopInfo *LI,
20492060
Loc.AATags.TBAA = nullptr;
20502061

20512062
visitPointers(const_cast<Value *>(Loc.Ptr), *TheLoop,
2052-
[&Accesses, Loc, IsReadOnlyPtr](Value *Ptr) {
2063+
[&Accesses, AccessTy, Loc, IsReadOnlyPtr](Value *Ptr) {
20532064
MemoryLocation NewLoc = Loc.getWithNewPtr(Ptr);
2054-
Accesses.addLoad(NewLoc, IsReadOnlyPtr);
2065+
Accesses.addLoad(NewLoc, AccessTy, IsReadOnlyPtr);
20552066
});
20562067
}
20572068

0 commit comments

Comments
 (0)