@@ -42,12 +42,6 @@ using namespace swift;
42
42
// / loads, function calls without side effects and (some) exclusivity checks
43
43
using InstSet = llvm::SmallPtrSet<SILInstruction *, 8 >;
44
44
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
-
51
45
// / A subset of instruction which may have side effects.
52
46
// / Doesn't contain ones that have special handling (e.g. fix_lifetime)
53
47
using WriteSet = SmallPtrSet<SILInstruction *, 8 >;
@@ -171,7 +165,7 @@ static bool hoistInstructions(SILLoop *Loop, DominanceInfo *DT,
171
165
getDominatingBlocks (domBlocks, Loop, DT);
172
166
173
167
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.
175
169
for (auto InstIt = CurBB->begin (), E = CurBB->end (); InstIt != E;) {
176
170
SILInstruction *Inst = &*InstIt;
177
171
++InstIt;
@@ -292,32 +286,46 @@ static bool sinkInstructions(std::unique_ptr<LoopNestSummary> &LoopSummary,
292
286
return Changed;
293
287
}
294
288
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
+
295
301
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) {
299
304
auto *Loop = LoopSummary->Loop ;
300
305
DEBUG (llvm::errs () << " Hoist and Sink pairs attempt\n " );
301
306
auto Preheader = Loop->getLoopPreheader ();
302
307
assert (Preheader && " Expected a preheader" );
303
308
304
309
bool Changed = false ;
305
310
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)) {
310
317
continue ;
311
318
}
312
- DEBUG (llvm::dbgs () << " Hoisted " << *Up );
313
- for (auto *instSink : SinkDownSet ) {
319
+ DEBUG (llvm::dbgs () << " Hoisted " << *BI );
320
+ for (auto *instSink : Ends ) {
314
321
if (!sinkInstruction (DT, LoopSummary, instSink, LI)) {
315
322
llvm_unreachable (" LICM: Could not perform must-sink instruction" );
316
323
}
317
324
}
318
325
DEBUG (llvm::errs () << " Successfully hosited and sank pair\n " );
319
326
Changed = true ;
320
327
}
328
+
321
329
return Changed;
322
330
}
323
331
@@ -343,8 +351,9 @@ class LoopTreeOptimization {
343
351
// / Instructions that we may be able to sink down
344
352
InstSet SinkDown;
345
353
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;
348
357
349
358
public:
350
359
LoopTreeOptimization (SILLoop *TopLevelLoop, SILLoopInfo *LI,
@@ -403,7 +412,7 @@ bool LoopTreeOptimization::optimize() {
403
412
// Reset the data structures for next loop in the list
404
413
HoistUp.clear ();
405
414
SinkDown.clear ();
406
- HoistingPairs .clear ();
415
+ SpecialHoist .clear ();
407
416
} while (currChanged);
408
417
409
418
// Store the summary for parent loops to use.
@@ -472,11 +481,12 @@ static bool canHoistUpDefault(SILInstruction *inst, SILLoop *Loop,
472
481
// 1) Inside the same loop (sink to loop exists)
473
482
// Potential TODO: At loop exit block
474
483
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) {
480
490
auto *BB = User->getParent ();
481
491
if (Loop->getBlocksSet ().count (BB) != 0 ) {
482
492
continue ;
@@ -486,40 +496,18 @@ static bool handledEndAccesses(BeginAccessInst *BI, SILLoop *Loop) {
486
496
return true ;
487
497
}
488
498
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) {
493
502
if (BI->getEnforcement () != SILAccessEnforcement::Dynamic) {
494
- return ;
503
+ return false ;
495
504
}
496
505
497
506
const AccessedStorage &storage =
498
507
findAccessedStorageNonNested (BI->getSource ());
499
508
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 ;
520
510
}
521
- DEBUG (llvm::dbgs () << " Found " << matchingEnds.size () << " End accesses"
522
- << " \n " );
523
511
524
512
auto BIAccessedStorageNonNested = findAccessedStorageNonNested (BI);
525
513
auto safeBeginPred = [&](BeginAccessInst *OtherBI) {
@@ -530,9 +518,8 @@ static void analyzeBeginAccess(BeginAccessInst *BI,
530
518
findAccessedStorageNonNested (OtherBI));
531
519
};
532
520
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));
536
523
}
537
524
538
525
// Analyzes current loop for hosting/sinking potential:
@@ -556,8 +543,6 @@ void LoopTreeOptimization::analyzeCurrentLoop(
556
543
SmallVector<FixLifetimeInst *, 8 > FixLifetimes;
557
544
// Contains begin_access, we might be able to hoist them.
558
545
SmallVector<BeginAccessInst *, 8 > BeginAccesses;
559
- // Contains end_access, we might be able to sink them.
560
- SmallVector<EndAccessInst *, 8 > EndAccesses;
561
546
562
547
for (auto *BB : Loop->getBlocks ()) {
563
548
for (auto &Inst : *BB) {
@@ -582,13 +567,6 @@ void LoopTreeOptimization::analyzeCurrentLoop(
582
567
checkSideEffects (Inst, MayWrites);
583
568
break ;
584
569
}
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
- }
592
570
case swift::SILInstructionKind::CondFailInst: {
593
571
// We can (and must) hoist cond_fail instructions if the operand is
594
572
// invariant. We must hoist them so that we preserve memory safety. A
@@ -651,7 +629,9 @@ void LoopTreeOptimization::analyzeCurrentLoop(
651
629
<< " \n " );
652
630
continue ;
653
631
}
654
- analyzeBeginAccess (BI, BeginAccesses, EndAccesses, HoistingPairs);
632
+ if (analyzeBeginAccess (BI, BeginAccesses)) {
633
+ SpecialHoist.insert (BI);
634
+ }
655
635
}
656
636
}
657
637
@@ -664,8 +644,8 @@ bool LoopTreeOptimization::optimizeLoop(
664
644
bool currChanged = false ;
665
645
currChanged |= hoistInstructions (CurrentLoop, DomTree, HoistUp);
666
646
currChanged |= sinkInstructions (CurrSummary, DomTree, LoopInfo, SinkDown);
667
- currChanged |= hoistAndSinkInstructionPairs (CurrSummary, DomTree, LoopInfo,
668
- HoistingPairs );
647
+ currChanged |=
648
+ hoistSpecialInstruction (CurrSummary, DomTree, LoopInfo, SpecialHoist );
669
649
Changed |= currChanged;
670
650
return currChanged;
671
651
}
0 commit comments