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