2626#include " llvm/ADT/DenseSet.h"
2727#include " llvm/ADT/DepthFirstIterator.h"
2828#include " llvm/ADT/GenericCycleInfo.h"
29+ #include " llvm/ADT/StringExtras.h"
2930
3031#define DEBUG_TYPE " generic-cycle-impl"
3132
@@ -119,6 +120,104 @@ auto GenericCycle<ContextT>::getCyclePredecessor() const -> BlockT * {
119120 return Out;
120121}
121122
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+ llvm_unreachable (" 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+
122221// / \brief Helper class for computing cycle information.
123222template <typename ContextT> class GenericCycleInfoCompute {
124223 using BlockT = typename ContextT::BlockT;
@@ -400,8 +499,6 @@ void GenericCycleInfo<ContextT>::compute(FunctionT &F) {
400499 LLVM_DEBUG (errs () << " Computing cycles for function: " << F.getName ()
401500 << " \n " );
402501 Compute.run (&F.front ());
403-
404- assert (validateTree ());
405502}
406503
407504template <typename ContextT>
@@ -414,7 +511,7 @@ void GenericCycleInfo<ContextT>::splitCriticalEdge(BlockT *Pred, BlockT *Succ,
414511 return ;
415512
416513 addBlockToCycle (NewBlock, Cycle);
417- assert ( validateTree () );
514+ verifyCycleNest ( );
418515}
419516
420517// / \brief Find the innermost cycle containing a given block.
@@ -468,73 +565,38 @@ unsigned GenericCycleInfo<ContextT>::getCycleDepth(const BlockT *Block) const {
468565 return Cycle->getDepth ();
469566}
470567
471- #ifndef NDEBUG
472- // / \brief Validate the internal consistency of the cycle tree.
568+ // / \brief Verify the internal consistency of the cycle tree.
473569// /
474570// / Note that this does \em not check that cycles are really cycles in the CFG,
475571// / or that the right set of cycles in the CFG were found.
476572template <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 )
492-
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?
503- }
504- Blocks.clear ();
505-
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));
510- }
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- }
573+ void GenericCycleInfo<ContextT>::verifyCycleNest(bool VerifyFull) const {
574+ #ifndef NDEBUG
575+ DenseSet<BlockT *> CycleHeaders;
576+
577+ for (CycleT *TopCycle : toplevel_cycles ()) {
578+ for (CycleT *Cycle : depth_first (TopCycle)) {
579+ BlockT *Header = Cycle->getHeader ();
580+ assert (CycleHeaders.insert (Header).second );
581+ if (VerifyFull)
582+ Cycle->verifyCycle ();
583+ else
584+ Cycle->verifyCycleNest ();
585+ // Check the block map entries for blocks contained in this cycle.
586+ for (BlockT *BB : Cycle->blocks ()) {
587+ auto MapIt = BlockMap.find (BB);
588+ assert (MapIt != BlockMap.end ());
589+ assert (Cycle->contains (MapIt->second ));
521590 }
522591 }
523592 }
593+ #endif
594+ }
524595
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));
530- }
531- }
532-
533- #undef check
534-
535- return true ;
596+ // / \brief Verify that the entire cycle tree well-formed.
597+ template <typename ContextT> void GenericCycleInfo<ContextT>::verify() const {
598+ verifyCycleNest (/* VerifyFull=*/ true );
536599}
537- #endif
538600
539601// / \brief Print the cycle info.
540602template <typename ContextT>
0 commit comments