Skip to content

Commit 2a1debb

Browse files
jaladreipsigcbot
authored andcommitted
Refactor AllocationLivenessAnalyzer to use SetVector instead of DenseSet
DenseSet would be preferred since it is a more mature container type than SetVector. Unfortunately, iteration over lifetime ends and lifetime edges should be deterministic and only SetVector guarantees that.
1 parent ae46135 commit 2a1debb

File tree

2 files changed

+26
-16
lines changed

2 files changed

+26
-16
lines changed

IGC/AdaptorCommon/LivenessUtils/AllocationLivenessAnalyzer.cpp

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ void AllocationLivenessAnalyzer::getAnalysisUsage(llvm::AnalysisUsage &AU) const
122122
getAdditionalAnalysisUsage(AU);
123123
}
124124

125-
void AllocationLivenessAnalyzer::implementCallSpecificBehavior(CallInst *callI, Use* use, SmallVector<Use *> &worklist,
125+
void AllocationLivenessAnalyzer::implementCallSpecificBehavior(CallInst *callI, Use *use, SmallVector<Use *> &worklist,
126126
SetVector<Instruction *> &allUsers,
127127
SetVector<Instruction *> &lifetimeLeakingUsers) {
128128

@@ -137,8 +137,8 @@ void AllocationLivenessAnalyzer::implementCallSpecificBehavior(CallInst *callI,
137137
}
138138

139139
template <typename range>
140-
static inline void doWorkLoop(SmallVector<BasicBlock *> &worklist, DenseSet<BasicBlock *> &bbSet1,
141-
DenseSet<BasicBlock *> &bbSet2, std::function<range(BasicBlock *)> iterate,
140+
static inline void doWorkLoop(SmallVectorImpl<BasicBlock *> &worklist, SetVector<BasicBlock *> &bbSet1,
141+
SetVector<BasicBlock *> &bbSet2, std::function<range(BasicBlock *)> iterate,
142142
std::function<bool(BasicBlock *)> continueCondition) {
143143
// perform data flow analysis
144144
while (!worklist.empty()) {
@@ -152,7 +152,7 @@ static inline void doWorkLoop(SmallVector<BasicBlock *> &worklist, DenseSet<Basi
152152
for (auto *pbb : iterate(currbb)) {
153153
addToSet1 = true;
154154

155-
bool inserted = bbSet2.insert(pbb).second;
155+
bool inserted = bbSet2.insert(pbb);
156156

157157
if (inserted)
158158
worklist.push_back(pbb);
@@ -211,13 +211,13 @@ AllocationLivenessAnalyzer::LivenessData::LivenessData(Instruction *allocationIn
211211

212212
// add terminators to users, so we can later add them to our lifetimeEnd vector
213213
auto leakingbbOnlyIn = leakingbbIn;
214-
set_subtract(leakingbbOnlyIn, leakingbbOut);
214+
leakingbbOnlyIn.set_subtract(leakingbbOut);
215215

216216
for (auto *bb : leakingbbOnlyIn)
217217
usersOfAllocation.insert(bb->getTerminator());
218218

219-
set_union(bbIn, leakingbbIn);
220-
set_union(bbOut, leakingbbOut);
219+
bbIn.set_union(leakingbbIn);
220+
bbOut.set_union(leakingbbOut);
221221
}
222222

223223
// if the lifetime escapes any loop, we should make sure all the loops blocks are included
@@ -260,7 +260,7 @@ AllocationLivenessAnalyzer::LivenessData::LivenessData(Instruction *allocationIn
260260
// substract the inflow blocks from the outflow blocks to find the block which starts the lifetime - there should be
261261
// only one!
262262
auto bbOutOnly = bbOut;
263-
set_subtract(bbOutOnly, bbIn);
263+
bbOutOnly.set_subtract(bbIn);
264264

265265
IGC_ASSERT_MESSAGE(bbOutOnly.size() == 1, "Multiple lifetime start blocks?");
266266

@@ -287,7 +287,7 @@ AllocationLivenessAnalyzer::LivenessData::LivenessData(Instruction *allocationIn
287287
} else {
288288
// find all blocks where lifetime flows in, but doesnt flow out
289289
auto bbOnlyIn = bbIn;
290-
set_subtract(bbOnlyIn, bbOut);
290+
bbOnlyIn.set_subtract(bbOut);
291291

292292
for (auto *bb : bbOnlyIn) {
293293
for (auto &I : llvm::reverse(*bb)) {
@@ -316,11 +316,19 @@ AllocationLivenessAnalyzer::LivenessData::LivenessData(Instruction *allocationIn
316316
}
317317

318318
bool AllocationLivenessAnalyzer::LivenessData::OverlapsWith(const LivenessData &LD) const {
319+
320+
// SetVector doesn't support set_intersect...
321+
// set_intersect(overlapIn, LD.bbIn);
322+
// so we emulate it via formula A ^ B = A - (A - B)
319323
auto overlapIn = bbIn;
320-
set_intersect(overlapIn, LD.bbIn);
324+
auto AminusBIn = bbIn;
325+
AminusBIn.set_subtract(LD.bbIn);
326+
overlapIn.set_subtract(AminusBIn);
321327

322328
auto overlapOut = bbOut;
323-
set_intersect(overlapOut, LD.bbOut);
329+
auto AminusBOut = bbOut;
330+
AminusBOut.set_subtract(LD.bbOut);
331+
overlapOut.set_subtract(AminusBOut);
324332

325333
// check if both lifetimes flow out or in the same block, this means overlap
326334
if (!overlapIn.empty() || !overlapOut.empty())
@@ -364,7 +372,10 @@ bool AllocationLivenessAnalyzer::LivenessData::OverlapsWith(const LivenessData &
364372
}
365373

366374
bool AllocationLivenessAnalyzer::LivenessData::ContainsInstruction(const llvm::Instruction &I) const {
367-
auto *bb = I.getParent();
375+
376+
// SetVector::contains seems to have underimplemented const-correctness
377+
// the const_cast is not needed for DenseSet based implementation, but then we introduce nondetereministic behavior when iterating
378+
auto *bb = const_cast<BasicBlock *>(I.getParent());
368379

369380
// if the LD is contained in a single block, bbIn and bbOut are going to be empty.
370381
// TODO: maybe LivenessData deserves a flag to mark livenesses contained in a single block?
@@ -417,8 +428,7 @@ static bool tryFindPointerOrigin(GetElementPtrInst *Ptr, SmallVectorImpl<Instruc
417428
return tryFindPointerOriginImpl(Ptr->getPointerOperand(), origins, cache);
418429
}
419430

420-
static bool tryFindPointerOrigin(SelectInst *Ptr, SmallVectorImpl<Instruction *> &origins,
421-
DenseSet<Value *> &cache) {
431+
static bool tryFindPointerOrigin(SelectInst *Ptr, SmallVectorImpl<Instruction *> &origins, DenseSet<Value *> &cache) {
422432
return tryFindPointerOriginImpl(Ptr->getTrueValue(), origins, cache) &&
423433
tryFindPointerOriginImpl(Ptr->getFalseValue(), origins, cache);
424434
}

IGC/AdaptorCommon/LivenessUtils/AllocationLivenessAnalyzer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ class AllocationLivenessAnalyzer : public llvm::FunctionPass {
3939

4040
llvm::SmallVector<Edge> lifetimeEndEdges;
4141

42-
llvm::DenseSet<llvm::BasicBlock *> bbIn;
43-
llvm::DenseSet<llvm::BasicBlock *> bbOut;
42+
llvm::SetVector<llvm::BasicBlock *> bbIn;
43+
llvm::SetVector<llvm::BasicBlock *> bbOut;
4444

4545
LivenessData(llvm::Instruction *allocationInstruction, llvm::SetVector<llvm::Instruction *> &&usersOfAllocation,
4646
const llvm::LoopInfo &LI, const llvm::DominatorTree &DT,

0 commit comments

Comments
 (0)