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"
30
29
31
30
#define DEBUG_TYPE " generic-cycle-impl"
32
31
@@ -120,104 +119,6 @@ auto GenericCycle<ContextT>::getCyclePredecessor() const -> BlockT * {
120
119
return Out;
121
120
}
122
121
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
-
221
122
// / \brief Helper class for computing cycle information.
222
123
template <typename ContextT> class GenericCycleInfoCompute {
223
124
using BlockT = typename ContextT::BlockT;
@@ -499,6 +400,8 @@ void GenericCycleInfo<ContextT>::compute(FunctionT &F) {
499
400
LLVM_DEBUG (errs () << " Computing cycles for function: " << F.getName ()
500
401
<< " \n " );
501
402
Compute.run (&F.front ());
403
+
404
+ assert (validateTree ());
502
405
}
503
406
504
407
template <typename ContextT>
@@ -511,7 +414,7 @@ void GenericCycleInfo<ContextT>::splitCriticalEdge(BlockT *Pred, BlockT *Succ,
511
414
return ;
512
415
513
416
addBlockToCycle (NewBlock, Cycle);
514
- verifyCycleNest ( );
417
+ assert ( validateTree () );
515
418
}
516
419
517
420
// / \brief Find the innermost cycle containing a given block.
@@ -565,63 +468,73 @@ unsigned GenericCycleInfo<ContextT>::getCycleDepth(const BlockT *Block) const {
565
468
return Cycle->getDepth ();
566
469
}
567
470
568
- // / \brief Verify the internal consistency of the cycle tree.
471
+ #ifndef NDEBUG
472
+ // / \brief Validate the internal consistency of the cycle tree.
569
473
// /
570
474
// / Note that this does \em not check that cycles are really cycles in the CFG,
571
475
// / 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.
576
476
template <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 )
582
492
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?
587
503
}
588
- }
589
- }
504
+ Blocks.clear ();
590
505
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));
602
510
}
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
+ }
608
521
}
609
522
}
610
523
}
611
524
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));
615
530
}
616
531
}
617
- #endif
618
- }
619
532
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 ;
624
536
}
537
+ #endif
625
538
626
539
// / \brief Print the cycle info.
627
540
template <typename ContextT>
0 commit comments