Skip to content

Commit 4ee2cef

Browse files
committed
Introduce getPointers method
For clients that want to iterate the deduplicated pointers. Also consistently distinguish memory location vs. pointer iteration.
1 parent e1c2fbf commit 4ee2cef

File tree

8 files changed

+51
-26
lines changed

8 files changed

+51
-26
lines changed

llvm/include/llvm/Analysis/AliasSetTracker.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include "llvm/ADT/DenseMap.h"
2222
#include "llvm/ADT/DenseMapInfo.h"
23+
#include "llvm/ADT/SmallVector.h"
2324
#include "llvm/ADT/ilist.h"
2425
#include "llvm/ADT/ilist_node.h"
2526
#include "llvm/Analysis/MemoryLocation.h"
@@ -116,14 +117,20 @@ class AliasSet : public ilist_node<AliasSet> {
116117
/// Merge the specified alias set into this alias set.
117118
void mergeSetIn(AliasSet &AS, AliasSetTracker &AST, BatchAAResults &BatchAA);
118119

119-
// Alias Set iteration - Allow access to all of the pointers which are part of
120-
// this alias set.
120+
// Alias Set iteration - Allow access to all of the memory locations which are
121+
// part of this alias set.
121122
using iterator = std::vector<MemoryLocation>::const_iterator;
122123
iterator begin() const { return MemoryLocs.begin(); }
123124
iterator end() const { return MemoryLocs.end(); }
124125

125126
unsigned size() { return MemoryLocs.size(); }
126127

128+
/// Retrieve the pointer values for the memory locations in this alias set.
129+
/// The order matches that of the memory locations, but duplicate pointer
130+
/// values are omitted.
131+
using PointerVector = SmallVector<const Value *, 8>;
132+
PointerVector getPointers() const;
133+
127134
void print(raw_ostream &OS) const;
128135
void dump() const;
129136

llvm/lib/Analysis/AliasSetTracker.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,25 @@ ModRefInfo AliasSet::aliasesUnknownInst(const Instruction *Inst,
207207
return MR;
208208
}
209209

210+
AliasSet::PointerVector AliasSet::getPointers() const {
211+
// To deduplicate pointer values, use a linear scan if the number of elements
212+
// is small, or a set if large. This is the same idea as SmallSetVector. In
213+
// addition, we can allocate space for the result vector upfront.
214+
PointerVector Result;
215+
if (MemoryLocs.size() <= Result.capacity()) {
216+
for (const MemoryLocation &MemLoc : MemoryLocs)
217+
if (llvm::find(Result, MemLoc.Ptr) == Result.end())
218+
Result.push_back(MemLoc.Ptr);
219+
} else {
220+
Result.reserve(MemoryLocs.size());
221+
DenseSet<const Value *> Seen;
222+
for (const MemoryLocation &MemLoc : MemoryLocs)
223+
if (Seen.insert(MemLoc.Ptr).second)
224+
Result.push_back(MemLoc.Ptr);
225+
}
226+
return Result;
227+
}
228+
210229
void AliasSetTracker::clear() {
211230
PointerMap.clear();
212231
AliasSets.clear();

llvm/lib/Analysis/LoopAccessAnalysis.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,6 +1115,7 @@ bool AccessAnalysis::canCheckPtrAtRT(RuntimePointerChecking &RtCheck,
11151115
int NumWritePtrChecks = 0;
11161116
bool CanDoAliasSetRT = true;
11171117
++ASId;
1118+
auto ASPointers = AS.getPointers();
11181119

11191120
// We assign consecutive id to access from different dependence sets.
11201121
// Accesses within the same set don't need a runtime check.
@@ -1126,8 +1127,8 @@ bool AccessAnalysis::canCheckPtrAtRT(RuntimePointerChecking &RtCheck,
11261127
// First, count how many write and read accesses are in the alias set. Also
11271128
// collect MemAccessInfos for later.
11281129
SmallVector<MemAccessInfo, 4> AccessInfos;
1129-
for (const auto &A : AS) {
1130-
Value *Ptr = const_cast<Value *>(A.Ptr);
1130+
for (const Value *Ptr_ : ASPointers) {
1131+
Value *Ptr = const_cast<Value *>(Ptr_);
11311132
bool IsWrite = Accesses.count(MemAccessInfo(Ptr, true));
11321133
if (IsWrite)
11331134
++NumWritePtrChecks;
@@ -1140,10 +1141,10 @@ bool AccessAnalysis::canCheckPtrAtRT(RuntimePointerChecking &RtCheck,
11401141
// or a single write and no reads.
11411142
if (NumWritePtrChecks == 0 ||
11421143
(NumWritePtrChecks == 1 && NumReadPtrChecks == 0)) {
1143-
assert((AS.size() <= 1 ||
1144-
all_of(AS,
1145-
[this](auto AC) {
1146-
MemAccessInfo AccessWrite(const_cast<Value *>(AC.Ptr),
1144+
assert((ASPointers.size() <= 1 ||
1145+
all_of(ASPointers,
1146+
[this](auto Ptr) {
1147+
MemAccessInfo AccessWrite(const_cast<Value *>(Ptr),
11471148
true);
11481149
return DepCands.findValue(AccessWrite) == DepCands.end();
11491150
})) &&
@@ -1272,8 +1273,9 @@ void AccessAnalysis::processMemAccesses() {
12721273
// set.
12731274
for (const auto &AS : AST) {
12741275
// Note that both the alias-set tracker and the alias sets themselves used
1275-
// linked lists internally and so the iteration order here is deterministic
1276-
// (matching the original instruction order within each set).
1276+
// ordered collections internally and so the iteration order here is
1277+
// deterministic.
1278+
auto ASPointers = AS.getPointers();
12771279

12781280
bool SetHasWrite = false;
12791281

@@ -1290,8 +1292,8 @@ void AccessAnalysis::processMemAccesses() {
12901292
bool UseDeferred = SetIteration > 0;
12911293
PtrAccessMap &S = UseDeferred ? DeferredAccesses : Accesses;
12921294

1293-
for (const auto &AV : AS) {
1294-
Value *Ptr = const_cast<Value *>(AV.Ptr);
1295+
for (const Value *Ptr_ : ASPointers) {
1296+
Value *Ptr = const_cast<Value *>(Ptr_);
12951297

12961298
// For a single memory access in AliasSetTracker, Accesses may contain
12971299
// both read and write, and they both need to be handled for CheckDeps.

llvm/lib/Transforms/Scalar/LICM.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2323,8 +2323,8 @@ collectPromotionCandidates(MemorySSA *MSSA, AliasAnalysis *AA, Loop *L) {
23232323
SmallVector<std::pair<SmallSetVector<Value *, 8>, bool>, 0> Result;
23242324
for (auto [Set, HasReadsOutsideSet] : Sets) {
23252325
SmallSetVector<Value *, 8> PointerMustAliases;
2326-
for (const auto &ASI : *Set)
2327-
PointerMustAliases.insert(const_cast<Value *>(ASI.Ptr));
2326+
for (const auto &MemLoc : *Set)
2327+
PointerMustAliases.insert(const_cast<Value *>(MemLoc.Ptr));
23282328
Result.emplace_back(std::move(PointerMustAliases), HasReadsOutsideSet);
23292329
}
23302330

llvm/lib/Transforms/Scalar/LoopVersioningLICM.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,8 @@ bool LoopVersioningLICM::legalLoopMemoryAccesses() {
263263
// Check for Mod & MayAlias
264264
HasMayAlias |= AS.isMayAlias();
265265
HasMod |= AS.isMod();
266-
for (const auto &A : AS) {
267-
const Value *Ptr = A.Ptr;
266+
for (const auto &MemLoc : AS) {
267+
const Value *Ptr = MemLoc.Ptr;
268268
// Alias tracker should have pointers of same data type.
269269
//
270270
// FIXME: check no longer effective since opaque pointers?

polly/lib/Analysis/ScopBuilder.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3255,10 +3255,8 @@ ScopBuilder::buildAliasGroupsForAccesses() {
32553255
if (AS.isMustAlias() || AS.isForwardingAliasSet())
32563256
continue;
32573257
AliasGroupTy AG;
3258-
llvm::SmallPtrSet<const Value *, 8> Seen;
3259-
for (auto &MemLoc : AS)
3260-
if (Seen.insert(MemLoc.Ptr).second)
3261-
AG.push_back(PtrToAcc[const_cast<Value *>(MemLoc.Ptr)]);
3258+
for (const Value *Ptr : AS.getPointers())
3259+
AG.push_back(PtrToAcc[const_cast<Value *>(Ptr)]);
32623260
if (AG.size() < 2)
32633261
continue;
32643262
AliasGroups.push_back(std::move(AG));

polly/lib/Analysis/ScopDetection.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,8 @@ bool ScopDetection::isValidAccess(Instruction *Inst, const SCEV *AF,
11491149
// sure the base pointer is not an instruction defined inside the scop.
11501150
// However, we can ignore loads that will be hoisted.
11511151

1152+
auto ASPointers = AS.getPointers();
1153+
11521154
InvariantLoadsSetTy VariantLS, InvariantLS;
11531155
// In order to detect loads which are dependent on other invariant loads
11541156
// as invariant, we use fixed-point iteration method here i.e we iterate
@@ -1158,9 +1160,8 @@ bool ScopDetection::isValidAccess(Instruction *Inst, const SCEV *AF,
11581160
const unsigned int VariantSize = VariantLS.size(),
11591161
InvariantSize = InvariantLS.size();
11601162

1161-
for (const auto &MemLoc : AS) {
1162-
Instruction *Inst =
1163-
dyn_cast<Instruction>(const_cast<Value *>(MemLoc.Ptr));
1163+
for (const Value *Ptr : ASPointers) {
1164+
Instruction *Inst = dyn_cast<Instruction>(const_cast<Value *>(Ptr));
11641165
if (Inst && Context.CurRegion.contains(Inst)) {
11651166
auto *Load = dyn_cast<LoadInst>(Inst);
11661167
if (Load && InvariantLS.count(Load))

polly/lib/Analysis/ScopDetectionDiagnostic.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -638,9 +638,7 @@ bool ReportNonSimpleMemoryAccess::classof(const RejectReason *RR) {
638638

639639
ReportAlias::ReportAlias(Instruction *Inst, AliasSet &AS)
640640
: RejectReason(RejectReasonKind::Alias), Inst(Inst) {
641-
for (const auto &I : AS)
642-
if (!llvm::is_contained(Pointers, I.Ptr))
643-
Pointers.push_back(I.Ptr);
641+
llvm::append_range(Pointers, AS.getPointers());
644642
}
645643

646644
std::string ReportAlias::formatInvalidAlias(std::string Prefix,

0 commit comments

Comments
 (0)