Skip to content

Commit 280a514

Browse files
committed
Merge pull request #1689 from gottesmm/loop-region-store-backedges
[loop-region] Track the backedges of all loop regions.
2 parents 7772ae7 + 406a7c9 commit 280a514

File tree

3 files changed

+725
-260
lines changed

3 files changed

+725
-260
lines changed

include/swift/SILOptimizer/Analysis/LoopRegionAnalysis.h

Lines changed: 161 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,9 @@
131131
namespace swift {
132132

133133
/// A loop region is a data structure which represents one of a basic block,
134-
/// loop, or function. In the case of a loop, function, it contains an internal
134+
/// loop, or function.
135+
///
136+
/// In the case of a loop, function, it contains an internal
135137
/// data structure that represents the subregions of the loop/function. This
136138
/// data is tail allocated so that the basic block case is not penalized by
137139
/// storing this unnecessary information.
@@ -319,6 +321,66 @@ class LoopRegion {
319321
};
320322
using subregion_reverse_iterator = std::reverse_iterator<subregion_iterator>;
321323

324+
/// An iterator that knows how to iterate over the backedge indices of a
325+
/// region.
326+
class backedge_iterator
327+
: public std::iterator<std::bidirectional_iterator_tag, unsigned> {
328+
friend struct SubregionData;
329+
using InnerIterTy = llvm::SmallVectorImpl<unsigned>::const_iterator;
330+
llvm::Optional<InnerIterTy> InnerIter;
331+
332+
backedge_iterator(llvm::SmallVectorImpl<unsigned>::const_iterator iter)
333+
: InnerIter(iter) {}
334+
335+
public:
336+
using value_type = unsigned;
337+
using reference = unsigned;
338+
using pointer = void;
339+
using iterator_category = std::bidirectional_iterator_tag;
340+
using difference_type = int;
341+
342+
/// Construct a backedge_iterator suitable for use with a basic block. It
343+
/// does not contain any data and can only be compared against another
344+
/// invalid iterator (for which it will return true). Any other usage
345+
/// results in an unreachable being hit.
346+
backedge_iterator() : InnerIter() {}
347+
348+
bool hasValue() const { return InnerIter.hasValue(); }
349+
350+
/// Return the index of the current backedge index.
351+
unsigned operator*() const { return **InnerIter; }
352+
353+
backedge_iterator &operator++() {
354+
++(*InnerIter);
355+
return *this;
356+
}
357+
backedge_iterator operator++(int) {
358+
backedge_iterator iter = *this;
359+
++iter;
360+
return iter;
361+
}
362+
backedge_iterator &operator--() {
363+
--(*InnerIter);
364+
return *this;
365+
}
366+
backedge_iterator operator--(int) {
367+
backedge_iterator iter = *this;
368+
--iter;
369+
return iter;
370+
}
371+
bool operator==(backedge_iterator rhs) const {
372+
if (InnerIter.hasValue() != rhs.InnerIter.hasValue())
373+
llvm_unreachable("Comparing uncomparable iterators");
374+
// Now we know that the two either both have values or both do not have
375+
// values.
376+
if (!InnerIter.hasValue())
377+
return true;
378+
return *InnerIter == *rhs.InnerIter;
379+
}
380+
bool operator!=(backedge_iterator rhs) const { return !(*this == rhs); }
381+
};
382+
using backedge_reverse_iterator = std::reverse_iterator<backedge_iterator>;
383+
322384
private:
323385
/// A pointer to one of a Loop, Basic Block, or Function represented by this
324386
/// region.
@@ -383,6 +445,13 @@ class LoopRegion {
383445
/// used as the RPO number for the whole region.
384446
unsigned RPONumOfHeaderBlock;
385447

448+
/// The RPO number of the back edge blocks of this loop. We use a
449+
/// SmallVector of size 1 since after loop canonicalization we will always
450+
/// have exactly one back edge block. But we want to be correct even in a
451+
/// non-canonicalized case implying that we need to be able to support
452+
/// multiple backedge blocks.
453+
llvm::SmallVector<unsigned, 1> BackedgeRegions;
454+
386455
/// A list of subregion IDs of this region sorted in RPO order.
387456
///
388457
/// This takes advantage of the fact that the ID of a basic block is the
@@ -430,6 +499,29 @@ class LoopRegion {
430499
Subloops.push_back({Header->ID, L->ID});
431500
}
432501

502+
void addBackedgeSubregion(unsigned ID) {
503+
if (count(BackedgeRegions, ID))
504+
return;
505+
BackedgeRegions.push_back(ID);
506+
}
507+
508+
backedge_iterator backedge_begin() const {
509+
return backedge_iterator(BackedgeRegions.begin());
510+
}
511+
backedge_iterator backedge_end() const {
512+
return backedge_iterator(BackedgeRegions.end());
513+
}
514+
backedge_reverse_iterator backedge_rbegin() const {
515+
return backedge_reverse_iterator(backedge_begin());
516+
}
517+
backedge_reverse_iterator backedge_rend() const {
518+
return backedge_reverse_iterator(backedge_end());
519+
}
520+
bool backedge_empty() const { return BackedgeRegions.empty(); }
521+
unsigned backedge_size() const { return BackedgeRegions.size(); }
522+
523+
ArrayRef<unsigned> getBackedgeRegions() const { return BackedgeRegions; }
524+
433525
/// Once we finish processing a loop, we sort its subregions so that they
434526
/// are guaranteed to be in RPO order. This works because each BB's ID is
435527
/// its RPO number and we represent loops by the RPO number of their
@@ -441,7 +533,6 @@ class LoopRegion {
441533
/// going to sort just to be careful while bringing this up.
442534
void sortSubregions() { std::sort(Subregions.begin(), Subregions.end()); }
443535
};
444-
445536
public:
446537
~LoopRegion();
447538

@@ -476,21 +567,34 @@ class LoopRegion {
476567
return getSubregionData().end();
477568
}
478569

479-
bool subregions_empty() const { return getSubregionData().empty(); }
480-
unsigned subregions_size() const { return getSubregionData().size(); }
570+
bool subregions_empty() const {
571+
if (isBlock())
572+
return true;
573+
return getSubregionData().empty();
574+
}
575+
576+
unsigned subregions_size() const {
577+
if (isBlock())
578+
return 0;
579+
return getSubregionData().size();
580+
}
581+
481582
subregion_reverse_iterator subregion_rbegin() const {
482583
if (isBlock())
483584
return subregion_reverse_iterator();
484585
return getSubregionData().rbegin();
485586
}
587+
486588
subregion_reverse_iterator subregion_rend() const {
487589
if (isBlock())
488590
return subregion_reverse_iterator();
489591
return getSubregionData().rend();
490592
}
593+
491594
llvm::iterator_range<subregion_iterator> getSubregions() const {
492595
return {subregion_begin(), subregion_end()};
493596
}
597+
494598
llvm::iterator_range<subregion_reverse_iterator>
495599
getReverseSubregions() const {
496600
return {subregion_rbegin(), subregion_rend()};
@@ -510,6 +614,50 @@ class LoopRegion {
510614
return getSubregionData().ExitingSubregions;
511615
}
512616

617+
bool isBackedgeRegion(unsigned ID) const {
618+
if (isBlock())
619+
return false;
620+
return count(getSubregionData().getBackedgeRegions(), ID);
621+
}
622+
623+
ArrayRef<unsigned> getBackedgeRegions() const {
624+
if (isBlock())
625+
return ArrayRef<unsigned>();
626+
return getSubregionData().getBackedgeRegions();
627+
}
628+
629+
Optional<unsigned> getBackedgeRegion() const {
630+
if (isBlock())
631+
return None;
632+
auto bedge_begin = getSubregionData().backedge_begin();
633+
auto bedge_end = getSubregionData().backedge_end();
634+
if (bedge_begin == bedge_end)
635+
return None;
636+
return *bedge_begin;
637+
}
638+
639+
using backedge_iterator = backedge_iterator;
640+
backedge_iterator backedge_begin() const {
641+
if (isBlock())
642+
return backedge_iterator();
643+
return getSubregionData().backedge_begin();
644+
}
645+
backedge_iterator backedge_end() const {
646+
if (isBlock())
647+
return backedge_iterator();
648+
return getSubregionData().backedge_end();
649+
}
650+
bool backedge_empty() const {
651+
if (isBlock())
652+
return true;
653+
return getSubregionData().backedge_empty();
654+
}
655+
unsigned backedge_size() const {
656+
if (isBlock())
657+
return 0;
658+
return getSubregionData().backedge_size();
659+
}
660+
513661
using pred_const_iterator = decltype(Preds)::const_iterator;
514662
pred_const_iterator pred_begin() const { return Preds.begin(); }
515663
pred_const_iterator pred_end() const { return Preds.end(); }
@@ -570,7 +718,7 @@ class LoopRegion {
570718

571719
/// Return the ID of the parent region of this BB. Asserts if this is a
572720
/// function region.
573-
unsigned getParentID() const { return *ParentID; }
721+
Optional<unsigned> getParentID() const { return ParentID; }
574722

575723
unsigned getRPONumber() const {
576724
if (isBlock())
@@ -781,9 +929,16 @@ class LoopRegionFunctionInfo {
781929
return IDToRegionMap[RegionID];
782930
}
783931

784-
RegionTy *getRegionForNonLocalSuccessor(const LoopRegion *Child,
932+
RegionTy *getRegionForNonLocalSuccessor(const RegionTy *Child,
785933
unsigned SuccID) const;
786934

935+
Optional<unsigned> getGrandparentID(const RegionTy *GrandChild) {
936+
if (auto ParentID = GrandChild->getParentID()) {
937+
return getRegion(*ParentID)->getParentID();
938+
}
939+
return None;
940+
}
941+
787942
/// Look up the region associated with this block and return it. Asserts if
788943
/// the block does not have a region associated with it.
789944
///

0 commit comments

Comments
 (0)