131
131
namespace swift {
132
132
133
133
// / 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
135
137
// / data structure that represents the subregions of the loop/function. This
136
138
// / data is tail allocated so that the basic block case is not penalized by
137
139
// / storing this unnecessary information.
@@ -319,6 +321,66 @@ class LoopRegion {
319
321
};
320
322
using subregion_reverse_iterator = std::reverse_iterator<subregion_iterator>;
321
323
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
+
322
384
private:
323
385
// / A pointer to one of a Loop, Basic Block, or Function represented by this
324
386
// / region.
@@ -383,6 +445,13 @@ class LoopRegion {
383
445
// / used as the RPO number for the whole region.
384
446
unsigned RPONumOfHeaderBlock;
385
447
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
+
386
455
// / A list of subregion IDs of this region sorted in RPO order.
387
456
// /
388
457
// / This takes advantage of the fact that the ID of a basic block is the
@@ -430,6 +499,29 @@ class LoopRegion {
430
499
Subloops.push_back ({Header->ID , L->ID });
431
500
}
432
501
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
+
433
525
// / Once we finish processing a loop, we sort its subregions so that they
434
526
// / are guaranteed to be in RPO order. This works because each BB's ID is
435
527
// / its RPO number and we represent loops by the RPO number of their
@@ -441,7 +533,6 @@ class LoopRegion {
441
533
// / going to sort just to be careful while bringing this up.
442
534
void sortSubregions () { std::sort (Subregions.begin (), Subregions.end ()); }
443
535
};
444
-
445
536
public:
446
537
~LoopRegion ();
447
538
@@ -476,21 +567,34 @@ class LoopRegion {
476
567
return getSubregionData ().end ();
477
568
}
478
569
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
+
481
582
subregion_reverse_iterator subregion_rbegin () const {
482
583
if (isBlock ())
483
584
return subregion_reverse_iterator ();
484
585
return getSubregionData ().rbegin ();
485
586
}
587
+
486
588
subregion_reverse_iterator subregion_rend () const {
487
589
if (isBlock ())
488
590
return subregion_reverse_iterator ();
489
591
return getSubregionData ().rend ();
490
592
}
593
+
491
594
llvm::iterator_range<subregion_iterator> getSubregions () const {
492
595
return {subregion_begin (), subregion_end ()};
493
596
}
597
+
494
598
llvm::iterator_range<subregion_reverse_iterator>
495
599
getReverseSubregions () const {
496
600
return {subregion_rbegin (), subregion_rend ()};
@@ -510,6 +614,50 @@ class LoopRegion {
510
614
return getSubregionData ().ExitingSubregions ;
511
615
}
512
616
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
+
513
661
using pred_const_iterator = decltype (Preds)::const_iterator;
514
662
pred_const_iterator pred_begin () const { return Preds.begin (); }
515
663
pred_const_iterator pred_end () const { return Preds.end (); }
@@ -570,7 +718,7 @@ class LoopRegion {
570
718
571
719
// / Return the ID of the parent region of this BB. Asserts if this is a
572
720
// / function region.
573
- unsigned getParentID () const { return * ParentID; }
721
+ Optional< unsigned > getParentID () const { return ParentID; }
574
722
575
723
unsigned getRPONumber () const {
576
724
if (isBlock ())
@@ -781,9 +929,16 @@ class LoopRegionFunctionInfo {
781
929
return IDToRegionMap[RegionID];
782
930
}
783
931
784
- RegionTy *getRegionForNonLocalSuccessor (const LoopRegion *Child,
932
+ RegionTy *getRegionForNonLocalSuccessor (const RegionTy *Child,
785
933
unsigned SuccID) const ;
786
934
935
+ Optional<unsigned > getGrandparentID (const RegionTy *GrandChild) {
936
+ if (auto ParentID = GrandChild->getParentID ()) {
937
+ return getRegion (*ParentID)->getParentID ();
938
+ }
939
+ return None;
940
+ }
941
+
787
942
// / Look up the region associated with this block and return it. Asserts if
788
943
// / the block does not have a region associated with it.
789
944
// /
0 commit comments