2626#include " llvm/ADT/DenseSet.h"
2727#include " llvm/ADT/DepthFirstIterator.h"
2828#include " llvm/ADT/GenericCycleInfo.h"
29- #include " llvm/ADT/StringExtras.h"
3029
3130#define DEBUG_TYPE " generic-cycle-impl"
3231
@@ -120,104 +119,6 @@ auto GenericCycle<ContextT>::getCyclePredecessor() const -> BlockT * {
120119 return Out;
121120}
122121
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-
221122// / \brief Helper class for computing cycle information.
222123template <typename ContextT> class GenericCycleInfoCompute {
223124 using BlockT = typename ContextT::BlockT;
@@ -499,6 +400,8 @@ void GenericCycleInfo<ContextT>::compute(FunctionT &F) {
499400 LLVM_DEBUG (errs () << " Computing cycles for function: " << F.getName ()
500401 << " \n " );
501402 Compute.run (&F.front ());
403+
404+ assert (validateTree ());
502405}
503406
504407template <typename ContextT>
@@ -511,7 +414,7 @@ void GenericCycleInfo<ContextT>::splitCriticalEdge(BlockT *Pred, BlockT *Succ,
511414 return ;
512415
513416 addBlockToCycle (NewBlock, Cycle);
514- verifyCycleNest ( );
417+ assert ( validateTree () );
515418}
516419
517420// / \brief Find the innermost cycle containing a given block.
@@ -565,63 +468,73 @@ unsigned GenericCycleInfo<ContextT>::getCycleDepth(const BlockT *Block) const {
565468 return Cycle->getDepth ();
566469}
567470
568- // / \brief Verify the internal consistency of the cycle tree.
471+ #ifndef NDEBUG
472+ // / \brief Validate the internal consistency of the cycle tree.
569473// /
570474// / Note that this does \em not check that cycles are really cycles in the CFG,
571475// / 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.
576476template <typename ContextT>
577- void GenericCycleInfo<ContextT>::verifyCycleNest(bool VerifyFull,
578- LoopInfoT *LI) const {
579- #ifndef NDEBUG
580- DenseSet<BlockT *> LoopHeaders;
581- DenseSet<BlockT *> CycleHeaders;
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 )
582492
583- if (LI) {
584- for (LoopT *TopLoop : *LI) {
585- for (LoopT *Loop : depth_first (TopLoop)) {
586- LoopHeaders.insert (Loop->getHeader ());
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?
587503 }
588- }
589- }
504+ Blocks.clear ();
590505
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 ));
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));
602510 }
603- if (LI) {
604- BlockT *Header = Cycle->getHeader ();
605- assert (CycleHeaders.insert (Header).second );
606- if (Cycle->isReducible ())
607- assert (LoopHeaders.contains (Header));
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+ }
608521 }
609522 }
610523 }
611524
612- if (LI) {
613- for (BlockT *Header : LoopHeaders) {
614- assert (CycleHeaders.contains (Header));
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));
615530 }
616531 }
617- #endif
618- }
619532
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);
533+ #undef check
534+
535+ return true ;
624536}
537+ #endif
625538
626539// / \brief Print the cycle info.
627540template <typename ContextT>
0 commit comments