Skip to content

Commit c3ddaf9

Browse files
author
Joe Shajrawi
committed
[LICM] Further refactoring: Simplify hosting of begin access instructions - get rid of HoistPairSet and hoistAndSinkInstructionPair
1 parent f56b5d8 commit c3ddaf9

File tree

1 file changed

+46
-66
lines changed

1 file changed

+46
-66
lines changed

lib/SILOptimizer/LoopTransforms/LICM.cpp

Lines changed: 46 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,6 @@ using namespace swift;
4242
/// loads, function calls without side effects and (some) exclusivity checks
4343
using InstSet = llvm::SmallPtrSet<SILInstruction *, 8>;
4444

45-
/// Instruction pairs which need to be hoisted together:
46-
/// e.g. If we hoist a begin access, we need to sink the matching end access
47-
/// The target of each hoist instruction can be multiple sinks. As such,
48-
/// A pair consists of an instruction to a set of matching sink instructions
49-
using HoistPairSet = llvm::SmallVector<std::pair<SILInstruction *, InstSet>, 8>;
50-
5145
/// A subset of instruction which may have side effects.
5246
/// Doesn't contain ones that have special handling (e.g. fix_lifetime)
5347
using WriteSet = SmallPtrSet<SILInstruction *, 8>;
@@ -171,7 +165,7 @@ static bool hoistInstructions(SILLoop *Loop, DominanceInfo *DT,
171165
getDominatingBlocks(domBlocks, Loop, DT);
172166

173167
for (auto *CurBB : domBlocks) {
174-
// We now that the block is guaranteed to be executed. Hoist if we can.
168+
// We know that the block is guaranteed to be executed. Hoist if we can.
175169
for (auto InstIt = CurBB->begin(), E = CurBB->end(); InstIt != E;) {
176170
SILInstruction *Inst = &*InstIt;
177171
++InstIt;
@@ -292,32 +286,46 @@ static bool sinkInstructions(std::unique_ptr<LoopNestSummary> &LoopSummary,
292286
return Changed;
293287
}
294288

289+
static void getEndAccesses(BeginAccessInst *BI,
290+
SmallVectorImpl<EndAccessInst *> &EndAccesses) {
291+
for (auto Use : BI->getUses()) {
292+
auto *User = Use->getUser();
293+
auto *EI = dyn_cast<EndAccessInst>(User);
294+
if (!EI) {
295+
continue;
296+
}
297+
EndAccesses.push_back(EI);
298+
}
299+
}
300+
295301
static bool
296-
hoistAndSinkInstructionPairs(std::unique_ptr<LoopNestSummary> &LoopSummary,
297-
DominanceInfo *DT, SILLoopInfo *LI,
298-
HoistPairSet &Pairs) {
302+
hoistSpecialInstruction(std::unique_ptr<LoopNestSummary> &LoopSummary,
303+
DominanceInfo *DT, SILLoopInfo *LI, InstSet &Special) {
299304
auto *Loop = LoopSummary->Loop;
300305
DEBUG(llvm::errs() << " Hoist and Sink pairs attempt\n");
301306
auto Preheader = Loop->getLoopPreheader();
302307
assert(Preheader && "Expected a preheader");
303308

304309
bool Changed = false;
305310

306-
for (auto pair : Pairs) {
307-
auto *Up = pair.first;
308-
auto &SinkDownSet = pair.second;
309-
if (!hoistInstruction(DT, Up, Loop, Preheader)) {
311+
for (auto *Inst : Special) {
312+
auto *BI = dyn_cast<BeginAccessInst>(Inst);
313+
assert(BI && "Only BeginAccessInst are supported");
314+
SmallVector<EndAccessInst *, 2> Ends;
315+
getEndAccesses(BI, Ends);
316+
if (!hoistInstruction(DT, BI, Loop, Preheader)) {
310317
continue;
311318
}
312-
DEBUG(llvm::dbgs() << "Hoisted " << *Up);
313-
for (auto *instSink : SinkDownSet) {
319+
DEBUG(llvm::dbgs() << "Hoisted " << *BI);
320+
for (auto *instSink : Ends) {
314321
if (!sinkInstruction(DT, LoopSummary, instSink, LI)) {
315322
llvm_unreachable("LICM: Could not perform must-sink instruction");
316323
}
317324
}
318325
DEBUG(llvm::errs() << " Successfully hosited and sank pair\n");
319326
Changed = true;
320327
}
328+
321329
return Changed;
322330
}
323331

@@ -343,8 +351,9 @@ class LoopTreeOptimization {
343351
/// Instructions that we may be able to sink down
344352
InstSet SinkDown;
345353

346-
/// Instruction pairs that we may be able to hoist and sink
347-
HoistPairSet HoistingPairs;
354+
/// Hoistable Instructions that need special treatment
355+
/// e.g. begin_access
356+
InstSet SpecialHoist;
348357

349358
public:
350359
LoopTreeOptimization(SILLoop *TopLevelLoop, SILLoopInfo *LI,
@@ -403,7 +412,7 @@ bool LoopTreeOptimization::optimize() {
403412
// Reset the data structures for next loop in the list
404413
HoistUp.clear();
405414
SinkDown.clear();
406-
HoistingPairs.clear();
415+
SpecialHoist.clear();
407416
} while (currChanged);
408417

409418
// Store the summary for parent loops to use.
@@ -472,11 +481,12 @@ static bool canHoistUpDefault(SILInstruction *inst, SILLoop *Loop,
472481
// 1) Inside the same loop (sink to loop exists)
473482
// Potential TODO: At loop exit block
474483
static bool handledEndAccesses(BeginAccessInst *BI, SILLoop *Loop) {
475-
for (auto Use : BI->getUses()) {
476-
auto *User = Use->getUser();
477-
if (!dyn_cast<EndAccessInst>(User)) {
478-
continue;
479-
}
484+
SmallVector<EndAccessInst *, 2> AllEnds;
485+
getEndAccesses(BI, AllEnds);
486+
if (AllEnds.empty()) {
487+
return false;
488+
}
489+
for (auto *User : AllEnds) {
480490
auto *BB = User->getParent();
481491
if (Loop->getBlocksSet().count(BB) != 0) {
482492
continue;
@@ -486,40 +496,18 @@ static bool handledEndAccesses(BeginAccessInst *BI, SILLoop *Loop) {
486496
return true;
487497
}
488498

489-
static void analyzeBeginAccess(BeginAccessInst *BI,
490-
SmallVector<BeginAccessInst *, 8> &BeginAccesses,
491-
SmallVector<EndAccessInst *, 8> &EndAccesses,
492-
HoistPairSet &HoistingPairs) {
499+
static bool
500+
analyzeBeginAccess(BeginAccessInst *BI,
501+
SmallVector<BeginAccessInst *, 8> &BeginAccesses) {
493502
if (BI->getEnforcement() != SILAccessEnforcement::Dynamic) {
494-
return;
503+
return false;
495504
}
496505

497506
const AccessedStorage &storage =
498507
findAccessedStorageNonNested(BI->getSource());
499508
if (!storage) {
500-
return;
501-
}
502-
503-
// find matching end accesses:
504-
InstSet matchingEnds;
505-
auto matchingEndPred = [&](EndAccessInst *EI) {
506-
return EI->getBeginAccess() == BI;
507-
};
508-
for (auto matchingEnd = std::find_if(EndAccesses.begin(), EndAccesses.end(),
509-
matchingEndPred);
510-
matchingEnd != EndAccesses.end();
511-
matchingEnd =
512-
std::find_if(matchingEnd, EndAccesses.end(), matchingEndPred)) {
513-
auto *EI = *matchingEnd;
514-
matchingEnds.insert(EI);
515-
++matchingEnd;
516-
}
517-
if (matchingEnds.empty()) {
518-
// no matching end within the loop
519-
return;
509+
return false;
520510
}
521-
DEBUG(llvm::dbgs() << "Found " << matchingEnds.size() << " End accesses"
522-
<< "\n");
523511

524512
auto BIAccessedStorageNonNested = findAccessedStorageNonNested(BI);
525513
auto safeBeginPred = [&](BeginAccessInst *OtherBI) {
@@ -530,9 +518,8 @@ static void analyzeBeginAccess(BeginAccessInst *BI,
530518
findAccessedStorageNonNested(OtherBI));
531519
};
532520

533-
if (std::all_of(BeginAccesses.begin(), BeginAccesses.end(), safeBeginPred)) {
534-
HoistingPairs.emplace_back(std::make_pair(BI, std::move(matchingEnds)));
535-
}
521+
return (
522+
std::all_of(BeginAccesses.begin(), BeginAccesses.end(), safeBeginPred));
536523
}
537524

538525
// Analyzes current loop for hosting/sinking potential:
@@ -556,8 +543,6 @@ void LoopTreeOptimization::analyzeCurrentLoop(
556543
SmallVector<FixLifetimeInst *, 8> FixLifetimes;
557544
// Contains begin_access, we might be able to hoist them.
558545
SmallVector<BeginAccessInst *, 8> BeginAccesses;
559-
// Contains end_access, we might be able to sink them.
560-
SmallVector<EndAccessInst *, 8> EndAccesses;
561546

562547
for (auto *BB : Loop->getBlocks()) {
563548
for (auto &Inst : *BB) {
@@ -582,13 +567,6 @@ void LoopTreeOptimization::analyzeCurrentLoop(
582567
checkSideEffects(Inst, MayWrites);
583568
break;
584569
}
585-
case SILInstructionKind::EndAccessInst: {
586-
auto *EI = dyn_cast<EndAccessInst>(&Inst);
587-
assert(EI && "Expected an End Access");
588-
EndAccesses.push_back(EI);
589-
checkSideEffects(Inst, MayWrites);
590-
break;
591-
}
592570
case swift::SILInstructionKind::CondFailInst: {
593571
// We can (and must) hoist cond_fail instructions if the operand is
594572
// invariant. We must hoist them so that we preserve memory safety. A
@@ -651,7 +629,9 @@ void LoopTreeOptimization::analyzeCurrentLoop(
651629
<< "\n");
652630
continue;
653631
}
654-
analyzeBeginAccess(BI, BeginAccesses, EndAccesses, HoistingPairs);
632+
if (analyzeBeginAccess(BI, BeginAccesses)) {
633+
SpecialHoist.insert(BI);
634+
}
655635
}
656636
}
657637

@@ -664,8 +644,8 @@ bool LoopTreeOptimization::optimizeLoop(
664644
bool currChanged = false;
665645
currChanged |= hoistInstructions(CurrentLoop, DomTree, HoistUp);
666646
currChanged |= sinkInstructions(CurrSummary, DomTree, LoopInfo, SinkDown);
667-
currChanged |= hoistAndSinkInstructionPairs(CurrSummary, DomTree, LoopInfo,
668-
HoistingPairs);
647+
currChanged |=
648+
hoistSpecialInstruction(CurrSummary, DomTree, LoopInfo, SpecialHoist);
669649
Changed |= currChanged;
670650
return currChanged;
671651
}

0 commit comments

Comments
 (0)