@@ -119,6 +119,101 @@ auto GenericCycle<ContextT>::getCyclePredecessor() const -> BlockT * {
119
119
return Out;
120
120
}
121
121
122
+ // / \brief Verify that this is actually a well-formed cycle in the CFG.
123
+ template <typename ContextT> void GenericCycle<ContextT>::verifyCycle() const {
124
+ #ifndef NDEBUG
125
+ assert (!Blocks.empty () && " Cycle cannot be empty." );
126
+ DenseSet<BlockT *> Blocks;
127
+ for (BlockT *BB : blocks ()) {
128
+ assert (Blocks.insert (BB).second ); // duplicates in block list?
129
+ }
130
+ assert (!Entries.empty () && " Cycle must have one or more entries." );
131
+
132
+ DenseSet<BlockT *> Entries;
133
+ for (BlockT *Entry : entries ()) {
134
+ assert (Entries.insert (Entry).second ); // duplicate entry?
135
+ assert (contains (Entry));
136
+ }
137
+
138
+ // Setup for using a depth-first iterator to visit every block in the cycle.
139
+ SmallVector<BlockT *, 8 > ExitBBs;
140
+ getExitBlocks (ExitBBs);
141
+ df_iterator_default_set<BlockT *> VisitSet;
142
+ VisitSet.insert (ExitBBs.begin (), ExitBBs.end ());
143
+
144
+ // Keep track of the BBs visited.
145
+ SmallPtrSet<BlockT *, 8 > VisitedBBs;
146
+
147
+ // Check the individual blocks.
148
+ for (BlockT *BB : depth_first_ext (getHeader (), VisitSet)) {
149
+ assert (llvm::any_of (llvm::children<BlockT *>(BB),
150
+ [&](BlockT *B) { return contains (B); }) &&
151
+ " Cycle block has no in-cycle successors!" );
152
+
153
+ assert (llvm::any_of (llvm::inverse_children<BlockT *>(BB),
154
+ [&](BlockT *B) { return contains (B); }) &&
155
+ " Cycle block has no in-cycle predecessors!" );
156
+
157
+ DenseSet<BlockT *> OutsideCyclePreds;
158
+ for (BlockT *B : llvm::inverse_children<BlockT *>(BB))
159
+ if (!contains (B))
160
+ OutsideCyclePreds.insert (B);
161
+
162
+ if (Entries.contains (BB)) {
163
+ assert (!OutsideCyclePreds.empty () && " Entry is unreachable!" );
164
+ } else if (!OutsideCyclePreds.empty ()) {
165
+ // A non-entry block shouldn't be reachable from outside the cycle,
166
+ // though it is permitted if the predecessor is not itself actually
167
+ // reachable.
168
+ BlockT *EntryBB = &BB->getParent ()->front ();
169
+ for (BlockT *CB : depth_first (EntryBB))
170
+ assert (!OutsideCyclePreds.contains (CB) &&
171
+ " Non-entry block reachable from outside!" );
172
+ }
173
+ assert (BB != &getHeader ()->getParent ()->front () &&
174
+ " Cycle contains function entry block!" );
175
+
176
+ VisitedBBs.insert (BB);
177
+ }
178
+
179
+ if (VisitedBBs.size () != getNumBlocks ()) {
180
+ dbgs () << " The following blocks are unreachable in the cycle: " ;
181
+ for (auto *BB : Blocks) {
182
+ if (!VisitedBBs.count (BB)) {
183
+ dbgs () << *BB << " \n " ;
184
+ }
185
+ }
186
+ assert (false && " Unreachable block in cycle" );
187
+ }
188
+
189
+ verifyCycleNest ();
190
+ #endif
191
+ }
192
+
193
+ // / \brief Verify the parent-child relations of this cycle.
194
+ // /
195
+ // / Note that this does \em not check that cycle is really a cycle in the CFG.
196
+ template <typename ContextT>
197
+ void GenericCycle<ContextT>::verifyCycleNest() const {
198
+ #ifndef NDEBUG
199
+ // Check the subcycles.
200
+ for (GenericCycle *Child : children ()) {
201
+ // Each block in each subcycle should be contained within this cycle.
202
+ for (BlockT *BB : Child->blocks ()) {
203
+ assert (contains (BB) &&
204
+ " Cycle does not contain all the blocks of a subcycle!" );
205
+ }
206
+ assert (Child->Depth == Depth + 1 );
207
+ }
208
+
209
+ // Check the parent cycle pointer.
210
+ if (ParentCycle) {
211
+ assert (is_contained (ParentCycle->children (), this ) &&
212
+ " Cycle is not a subcycle of its parent!" );
213
+ }
214
+ #endif
215
+ }
216
+
122
217
// / \brief Helper class for computing cycle information.
123
218
template <typename ContextT> class GenericCycleInfoCompute {
124
219
using BlockT = typename ContextT::BlockT;
@@ -400,8 +495,6 @@ void GenericCycleInfo<ContextT>::compute(FunctionT &F) {
400
495
LLVM_DEBUG (errs () << " Computing cycles for function: " << F.getName ()
401
496
<< " \n " );
402
497
Compute.run (&F.front ());
403
-
404
- assert (validateTree ());
405
498
}
406
499
407
500
template <typename ContextT>
@@ -414,7 +507,7 @@ void GenericCycleInfo<ContextT>::splitCriticalEdge(BlockT *Pred, BlockT *Succ,
414
507
return ;
415
508
416
509
addBlockToCycle (NewBlock, Cycle);
417
- assert ( validateTree () );
510
+ verifyCycleNest ( );
418
511
}
419
512
420
513
// / \brief Find the innermost cycle containing a given block.
@@ -468,73 +561,63 @@ unsigned GenericCycleInfo<ContextT>::getCycleDepth(const BlockT *Block) const {
468
561
return Cycle->getDepth ();
469
562
}
470
563
471
- #ifndef NDEBUG
472
- // / \brief Validate the internal consistency of the cycle tree.
564
+ // / \brief Verify the internal consistency of the cycle tree.
473
565
// /
474
566
// / Note that this does \em not check that cycles are really cycles in the CFG,
475
567
// / or that the right set of cycles in the CFG were found.
568
+ // /
569
+ // / Every natural loop has a corresponding cycle (possibly irreducible) with the
570
+ // / same header, and every reducible cycle is a natural loop with the same
571
+ // / header. We check this by comparing headers encountered in the two forests.
476
572
template <typename ContextT>
477
- bool GenericCycleInfo<ContextT>::validateTree() const {
478
- DenseSet<BlockT *> Blocks;
479
- DenseSet<BlockT *> Entries;
480
-
481
- auto reportError = [](const char *File, int Line, const char *Cond) {
482
- errs () << File << ' :' << Line
483
- << " : GenericCycleInfo::validateTree: " << Cond << ' \n ' ;
484
- };
485
- #define check (cond ) \
486
- do { \
487
- if (!(cond)) { \
488
- reportError (__FILE__, __LINE__, #cond); \
489
- return false ; \
490
- } \
491
- } while (false )
573
+ void GenericCycleInfo<ContextT>::verifyCycleNest(bool VerifyFull,
574
+ LoopInfoT *LI) const {
575
+ #ifndef NDEBUG
576
+ DenseSet<BlockT *> LoopHeaders;
577
+ DenseSet<BlockT *> CycleHeaders;
492
578
493
- for (const auto *TLC : toplevel_cycles ()) {
494
- for (const CycleT *Cycle : depth_first (TLC)) {
495
- if (Cycle->ParentCycle )
496
- check (is_contained (Cycle->ParentCycle ->children (), Cycle));
497
-
498
- for (BlockT *Block : Cycle->Blocks ) {
499
- auto MapIt = BlockMap.find (Block);
500
- check (MapIt != BlockMap.end ());
501
- check (Cycle->contains (MapIt->second ));
502
- check (Blocks.insert (Block).second ); // duplicates in block list?
579
+ if (LI) {
580
+ for (LoopT *TopLoop : *LI) {
581
+ for (LoopT *Loop : depth_first (TopLoop)) {
582
+ LoopHeaders.insert (Loop->getHeader ());
503
583
}
504
- Blocks.clear ();
584
+ }
585
+ }
505
586
506
- check (!Cycle->Entries .empty ());
507
- for (BlockT *Entry : Cycle->Entries ) {
508
- check (Entries.insert (Entry).second ); // duplicate entry?
509
- check (is_contained (Cycle->Blocks , Entry));
587
+ for (CycleT *TopCycle : toplevel_cycles ()) {
588
+ for (CycleT *Cycle : depth_first (TopCycle)) {
589
+ if (VerifyFull)
590
+ Cycle->verifyCycle ();
591
+ else
592
+ Cycle->verifyCycleNest ();
593
+ // Check the block map entries for blocks contained in this cycle.
594
+ for (BlockT *BB : Cycle->blocks ()) {
595
+ auto MapIt = BlockMap.find (BB);
596
+ assert (MapIt != BlockMap.end ());
597
+ assert (Cycle->contains (MapIt->second ));
510
598
}
511
- Entries.clear ();
512
-
513
- unsigned ChildDepth = 0 ;
514
- for (const CycleT *Child : Cycle->children ()) {
515
- check (Child->Depth > Cycle->Depth );
516
- if (!ChildDepth) {
517
- ChildDepth = Child->Depth ;
518
- } else {
519
- check (ChildDepth == Child->Depth );
520
- }
599
+ if (LI) {
600
+ BlockT *Header = Cycle->getHeader ();
601
+ assert (CycleHeaders.insert (Header).second );
602
+ if (Cycle->isReducible ())
603
+ assert (LoopHeaders.contains (Header));
521
604
}
522
605
}
523
606
}
524
607
525
- for (const auto &Entry : BlockMap) {
526
- BlockT *Block = Entry.first ;
527
- for (const CycleT *Cycle = Entry.second ; Cycle;
528
- Cycle = Cycle->ParentCycle ) {
529
- check (is_contained (Cycle->Blocks , Block));
608
+ if (LI) {
609
+ for (BlockT *Header : LoopHeaders) {
610
+ assert (CycleHeaders.contains (Header));
530
611
}
531
612
}
613
+ #endif
614
+ }
532
615
533
- #undef check
534
-
535
- return true ;
616
+ // / \brief Verify that the entire cycle tree well-formed.
617
+ template <typename ContextT>
618
+ void GenericCycleInfo<ContextT>::verify(LoopInfoT *LI) const {
619
+ verifyCycleNest (/* VerifyFull=*/ true , LI);
536
620
}
537
- #endif
538
621
539
622
// / \brief Print the cycle info.
540
623
template <typename ContextT>
0 commit comments