Skip to content

Commit 472efd4

Browse files
committed
[loop-region-analysis] Store the exiting regions from loops that we compute and used to just throw away.
I need this for loop-arc since I need to be able to analyze all "loop-exits" when I just have the parent loop region. We are already computing this information and throwing it away, so there should be no compile time impact.
1 parent a3a329f commit 472efd4

File tree

3 files changed

+624
-270
lines changed

3 files changed

+624
-270
lines changed

include/swift/SILOptimizer/Analysis/LoopRegionAnalysis.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,10 @@ class LoopRegion {
399399
/// Subregions array by the RPO number of its header.
400400
llvm::SmallVector<std::pair<unsigned, unsigned>, 2> Subloops;
401401

402+
/// A list of subregions with non-local successors. This is the actual ID
403+
/// of the subregion since we do not care about any ordering.
404+
llvm::SmallVector<unsigned, 2> ExitingSubregions;
405+
402406
subregion_iterator begin() const {
403407
return subregion_iterator(Subregions.begin(), &Subloops);
404408
}
@@ -498,6 +502,14 @@ class LoopRegion {
498502
return std::find(subregion_begin(), End, R->getID()) != End;
499503
}
500504

505+
/// Returns an ArrayRef containing IDs of the exiting subregions of this
506+
/// region. The exit regions associated with the exiting subregions are the
507+
/// end points of the non-local edges. This asserts if this is a region
508+
/// representing a block.
509+
ArrayRef<unsigned> getExitingSubregions() const {
510+
return getSubregionData().ExitingSubregions;
511+
}
512+
501513
using pred_const_iterator = decltype(Preds)::const_iterator;
502514
pred_const_iterator pred_begin() const { return Preds.begin(); }
503515
pred_const_iterator pred_end() const { return Preds.end(); }

lib/SILOptimizer/Analysis/LoopRegionAnalysis.cpp

Lines changed: 58 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -503,11 +503,9 @@ rewriteLoopHeaderPredecessors(LoopTy *SubLoop, RegionTy *SubLoopRegion) {
503503
return SubLoopHeaderRegion;
504504
}
505505

506-
static void
507-
getExitingRegions(LoopRegionFunctionInfo *LRFI,
508-
SILLoop *Loop,
509-
LoopRegion *LRegion,
510-
llvm::SmallVectorImpl<LoopRegion *> &ExitingRegions) {
506+
static void getExitingRegions(LoopRegionFunctionInfo *LRFI, SILLoop *Loop,
507+
LoopRegion *LRegion,
508+
llvm::SmallVectorImpl<unsigned> &ExitingRegions) {
511509
llvm::SmallVector<SILBasicBlock *, 8> ExitingBlocks;
512510
Loop->getExitingBlocks(ExitingBlocks);
513511

@@ -520,7 +518,7 @@ getExitingRegions(LoopRegionFunctionInfo *LRFI,
520518
Region = LRFI->getRegion(RegionParentID);
521519
RegionParentID = Region->getParentID();
522520
}
523-
ExitingRegions.push_back(Region);
521+
ExitingRegions.push_back(Region->getID());
524522
}
525523

526524
// We can have a loop subregion that has multiple exiting edges from the
@@ -530,9 +528,7 @@ getExitingRegions(LoopRegionFunctionInfo *LRFI,
530528
// In order to make sure we have a deterministic ordering when we visiting
531529
// exiting subregions, we need to sort our exiting regions by ID, not pointer
532530
// value.
533-
sortUnique(ExitingRegions, [](LoopRegion *R1, LoopRegion *R2) -> bool {
534-
return R1->getID() < R2->getID();
535-
});
531+
sortUnique(ExitingRegions);
536532
}
537533

538534
/// For each exiting block:
@@ -561,17 +557,18 @@ rewriteLoopExitingBlockSuccessors(LoopTy *Loop, RegionTy *LRegion) {
561557
// region which the block is a subregion of. Since we initialize our data
562558
// structure by processing the loop nest bottom up, this should always give us
563559
// the correct region for the level of the loop we are processing.
564-
llvm::SmallVector<RegionTy *, 8> ExitingRegions;
565-
getExitingRegions(this, Loop, LRegion, ExitingRegions);
560+
auto &ExitingSubregions = LRegion->getSubregionData().ExitingSubregions;
561+
getExitingRegions(this, Loop, LRegion, ExitingSubregions);
566562

567563
// Then for each exiting region ER of the Loop L...
568564
DEBUG(llvm::dbgs() << " Visiting Exit Blocks...\n");
569-
for (auto *ExitingRegion : ExitingRegions) {
565+
for (unsigned ExitingSubregionID : ExitingSubregions) {
566+
auto *ExitingSubregion = getRegion(ExitingSubregionID);
570567
DEBUG(llvm::dbgs() << " Exiting Region: "
571-
<< ExitingRegion->getID() << "\n");
568+
<< ExitingSubregion->getID() << "\n");
572569

573570
// For each successor region S of ER...
574-
for (auto SuccID : ExitingRegion->getSuccs()) {
571+
for (auto SuccID : ExitingSubregion->getSuccs()) {
575572
DEBUG(llvm::dbgs() << " Succ: " << SuccID.ID
576573
<< ". IsNonLocal: "
577574
<< (SuccID.IsNonLocal ? "true" : "false") << "\n");
@@ -588,22 +585,22 @@ rewriteLoopExitingBlockSuccessors(LoopTy *Loop, RegionTy *LRegion) {
588585
auto *SuccRegion = getRegion(SuccID.ID);
589586
if (!LRegion->containsSubregion(SuccRegion)) {
590587
DEBUG(llvm::dbgs() << " Is not a subregion, replacing.\n");
591-
SuccRegion->replacePred(ExitingRegion->ID, LRegion->ID);
592-
if (ExitingRegion->IsUnknownControlFlowEdgeTail)
588+
SuccRegion->replacePred(ExitingSubregion->ID, LRegion->ID);
589+
if (ExitingSubregion->IsUnknownControlFlowEdgeTail)
593590
LRegion->IsUnknownControlFlowEdgeTail = true;
594591
// If the successor region is already in this LRegion this returns that
595592
// regions index. Otherwise it returns a new index.
596593
unsigned Index = LRegion->addSucc(SuccRegion);
597-
ExitingRegion->replaceSucc(SuccID,
598-
LoopRegion::SuccessorID(Index, true));
599-
propagateLivenessDownNonLocalSuccessorEdges(ExitingRegion);
594+
ExitingSubregion->replaceSucc(SuccID,
595+
LoopRegion::SuccessorID(Index, true));
596+
propagateLivenessDownNonLocalSuccessorEdges(ExitingSubregion);
600597
continue;
601598
}
602599

603600
// Otherwise, we know S is in L. If the RPO number of S is less than the
604601
// RPO number of ER, then we know that the edge in between them is not a
605602
// backedge and thus we do not want to clip the edge.
606-
if (SuccRegion->getRPONumber() > ExitingRegion->getRPONumber()) {
603+
if (SuccRegion->getRPONumber() > ExitingSubregion->getRPONumber()) {
607604
DEBUG(llvm::dbgs() << " Is a subregion, but not a "
608605
"backedge, not removing.\n");
609606
continue;
@@ -613,8 +610,8 @@ rewriteLoopExitingBlockSuccessors(LoopTy *Loop, RegionTy *LRegion) {
613610
DEBUG(llvm::dbgs() << " Is a subregion and a backedge, "
614611
"removing.\n");
615612
auto Iter =
616-
std::remove(SuccRegion->Preds.begin(), SuccRegion->Preds.end(),
617-
ExitingRegion->getID());
613+
std::remove(SuccRegion->Preds.begin(), SuccRegion->Preds.end(),
614+
ExitingSubregion->getID());
618615
SuccRegion->Preds.erase(Iter);
619616
}
620617
}
@@ -688,9 +685,17 @@ propagateLivenessDownNonLocalSuccessorEdges(LoopRegion *Parent) {
688685

689686
while (Worklist.size()) {
690687
LoopRegion *R = Worklist.pop_back_val();
688+
691689
for (unsigned SubregionID : R->getSubregions()) {
692690
LoopRegion *Subregion = getRegion(SubregionID);
693691
bool ShouldVisit = false;
692+
693+
// Make sure we can identify when the subregion has at least one dead
694+
// non-local edge and no remaining live edges. In such a case, we need to
695+
// remove the subregion from the exiting subregion array of R after the
696+
// loop.
697+
bool HasDeadNonLocalEdge = false;
698+
bool HasNoLiveLocalEdges = true;
694699
for (auto &SuccID : Subregion->Succs) {
695700
// If the successor is already dead, skip it. We should have visited all
696701
// its children when we marked it as dead.
@@ -703,18 +708,31 @@ propagateLivenessDownNonLocalSuccessorEdges(LoopRegion *Parent) {
703708

704709
// If the non-local successor edge points to a parent successor that is
705710
// not dead continue.
706-
if (R->Succs[SuccID->ID].hasValue())
711+
if (R->Succs[SuccID->ID].hasValue()) {
712+
HasNoLiveLocalEdges = false;
707713
continue;
714+
}
708715

709-
// Ok, we found a target! Mark is as dead and make sure that we visit
710-
// the subregion's children.
716+
// Ok, we found a target! Mark it as dead and make sure that we visit
717+
// the subregion's children if it is not a block.
718+
HasDeadNonLocalEdge = true;
711719
ShouldVisit = true;
712720

713721
// This is safe to do since when erasing in a BlotSetVector, we do not
714722
// invalidate the iterators.
715723
Subregion->Succs.erase(*SuccID);
716724
}
717725

726+
// Remove Subregion from R's exiting subregion array if Subregion no
727+
// longer has /any/ non-local successors.
728+
if (HasDeadNonLocalEdge && HasNoLiveLocalEdges) {
729+
auto &ExitingSubregions = R->getSubregionData().ExitingSubregions;
730+
auto Iter =
731+
std::remove(ExitingSubregions.begin(), ExitingSubregions.end(),
732+
Subregion->getID());
733+
ExitingSubregions.erase(Iter);
734+
}
735+
718736
if (ShouldVisit)
719737
Worklist.push_back(Subregion);
720738
}
@@ -816,6 +834,21 @@ void LoopRegionFunctionInfo::print(raw_ostream &os) const {
816834
for (unsigned I : SortedSuccs) {
817835
os << "\n (parentindex:" << I << ")";
818836
}
837+
os << ")\n";
838+
839+
os << " (exiting-subregs";
840+
if (!R->isBlock()) {
841+
llvm::SmallVector<unsigned, 4> ExitingSubregions;
842+
auto ExitingSubRegs = R->getExitingSubregions();
843+
std::copy(ExitingSubRegs.begin(), ExitingSubRegs.end(),
844+
std::back_inserter(ExitingSubregions));
845+
std::sort(ExitingSubregions.begin(), ExitingSubregions.begin());
846+
for (unsigned SubregionID : ExitingSubregions) {
847+
os << "\n ";
848+
LoopRegion *Subregion = getRegion(SubregionID);
849+
Subregion->print(os, true);
850+
}
851+
}
819852
os << "))\n";
820853
}
821854
}

0 commit comments

Comments
 (0)