1414#include " llvm/Analysis/ReducibilityAnalysis.h"
1515
1616#include " llvm/ADT/BitVector.h"
17+ #include " llvm/ADT/SmallVector.h"
1718#include " llvm/Analysis/CFG.h"
1819#include " llvm/Analysis/LoopPass.h"
1920#include " llvm/IR/CFG.h"
@@ -140,16 +141,14 @@ class ScopeNestedCFG : public FunctionPass {
140141 // Preliminary CFG transformations and related utilities.
141142 //
142143 void SanitizeBranches ();
143- void SanitizeBranchesRec (BasicBlock *pBB,
144- unordered_set<BasicBlock *> &VisitedBB);
145144 void CollectUniqueSuccessors (const BasicBlock *pBB,
146145 const BasicBlock *pSuccessorToExclude,
147146 vector<BasicBlock *> &Successors);
148147
149148 //
150149 // Loop region transformations.
151150 //
152- void CollectLoopsRec (Loop *pLoop);
151+ void CollectLoops (Loop *pLoop);
153152
154153 void AnnotateBranch (BasicBlock *pBB, BranchKind Kind);
155154 BranchKind GetBranchAnnotation (const BasicBlock *pBB);
@@ -203,9 +202,6 @@ class ScopeNestedCFG : public FunctionPass {
203202 };
204203 void ComputeBlockTopologicalOrderAndReachability (
205204 BasicBlock *pEntry, BlockTopologicalOrderAndReachability &BTO);
206- void ComputeBlockTopologicalOrderAndReachabilityRec (
207- BasicBlock *pNode, BlockTopologicalOrderAndReachability &BTO,
208- unordered_map<BasicBlock *, unsigned > &Marks);
209205
210206 //
211207 // Recovery of scope end points.
@@ -337,7 +333,7 @@ bool ScopeNestedCFG::runOnFunction(Function &F) {
337333 for (auto itLoop = m_pLI->begin (), endLoop = m_pLI->end (); itLoop != endLoop;
338334 ++itLoop) {
339335 Loop *pLoop = *itLoop;
340- CollectLoopsRec (pLoop);
336+ CollectLoops (pLoop);
341337 }
342338
343339 //
@@ -428,91 +424,90 @@ void ScopeNestedCFG::Clear() {
428424// Preliminary CFG transformations and related utilities.
429425// -----------------------------------------------------------------------------
430426void ScopeNestedCFG::SanitizeBranches () {
431- unordered_set <BasicBlock *> VisitedBB;
432- SanitizeBranchesRec (m_pFunc-> begin (), VisitedBB) ;
433- }
427+ SmallPtrSet <BasicBlock *, 32 > VisitedBB;
428+ SmallVector<BasicBlock *, 32 > Worklist ;
429+ Worklist. push_back (m_pFunc-> begin ());
434430
435- void ScopeNestedCFG::SanitizeBranchesRec (
436- BasicBlock *pBB, unordered_set<BasicBlock *> &VisitedBB) {
437- // Mark pBB as visited, and return if pBB already has been visited.
438- if (!VisitedBB.emplace (pBB).second )
439- return ;
431+ while (!Worklist.empty ()) {
432+ BasicBlock *pBB = Worklist.pop_back_val ();
440433
441- // Sanitize branch.
442- if (BranchInst *I = dyn_cast<BranchInst>(pBB->getTerminator ())) {
443- // a. Convert a conditional branch to unconditional, if successors are the
444- // same.
445- if (I->isConditional ()) {
446- BasicBlock *pSucc1 = I->getSuccessor (0 );
447- BasicBlock *pSucc2 = I->getSuccessor (1 );
448- if (pSucc1 == pSucc2) {
449- BranchInst::Create (pSucc1, I);
450- I->eraseFromParent ();
434+ // Mark pBB as visited, and skip if pBB already has been visited.
435+ if (!VisitedBB.insert (pBB).second )
436+ continue ;
437+
438+ // Sanitize branch.
439+ if (BranchInst *I = dyn_cast<BranchInst>(pBB->getTerminator ())) {
440+ // a. Convert a conditional branch to unconditional, if successors are the
441+ // same.
442+ if (I->isConditional ()) {
443+ BasicBlock *pSucc1 = I->getSuccessor (0 );
444+ BasicBlock *pSucc2 = I->getSuccessor (1 );
445+ if (pSucc1 == pSucc2) {
446+ BranchInst::Create (pSucc1, I);
447+ I->eraseFromParent ();
448+ }
451449 }
452- }
453- } else if (SwitchInst *I = dyn_cast<SwitchInst>(pBB->getTerminator ())) {
454- // b. Group switch successors.
455- struct SwitchCaseGroup {
456- BasicBlock *pSuccBB;
457- vector<ConstantInt *> CaseValue;
458- };
459- vector<SwitchCaseGroup> SwitchCaseGroups;
460- unordered_map<BasicBlock *, unsigned > BB2GroupIdMap;
461- BasicBlock *pDefaultBB = I->getDefaultDest ();
450+ } else if (SwitchInst *I = dyn_cast<SwitchInst>(pBB->getTerminator ())) {
451+ // b. Group switch successors.
452+ struct SwitchCaseGroup {
453+ BasicBlock *pSuccBB;
454+ SmallVector<ConstantInt *, 8 > CaseValue;
455+ };
456+ SmallVector<SwitchCaseGroup, 8 > SwitchCaseGroups;
457+ DenseMap<BasicBlock *, unsigned > BB2GroupIdMap;
458+ BasicBlock *pDefaultBB = I->getDefaultDest ();
462459
463- for (SwitchInst::CaseIt itCase = I->case_begin (), endCase = I->case_end ();
464- itCase != endCase; ++itCase) {
465- BasicBlock *pSuccBB = itCase.getCaseSuccessor ();
466- ConstantInt *pCaseValue = itCase.getCaseValue ();
460+ for (SwitchInst::CaseIt itCase = I->case_begin (), endCase = I->case_end ();
461+ itCase != endCase; ++itCase) {
462+ BasicBlock *pSuccBB = itCase.getCaseSuccessor ();
463+ ConstantInt *pCaseValue = itCase.getCaseValue ();
467464
468- if (pSuccBB == pDefaultBB) {
469465 // Assimilate this case label into default label.
470- continue ;
471- }
466+ if (pSuccBB == pDefaultBB)
467+ continue ;
472468
473- auto itGroup = BB2GroupIdMap.insert ({pSuccBB, SwitchCaseGroups.size ()});
474- if (itGroup.second ) {
475- SwitchCaseGroups.emplace_back (SwitchCaseGroup{});
476- }
469+ auto itGroup = BB2GroupIdMap.insert ({pSuccBB, SwitchCaseGroups.size ()});
470+ if (itGroup.second )
471+ SwitchCaseGroups.emplace_back (SwitchCaseGroup{});
477472
478- SwitchCaseGroup &G = SwitchCaseGroups[itGroup.first ->second ];
479- G.pSuccBB = pSuccBB;
480- G.CaseValue .emplace_back (pCaseValue);
481- }
473+ SwitchCaseGroup &G = SwitchCaseGroups[itGroup.first ->second ];
474+ G.pSuccBB = pSuccBB;
475+ G.CaseValue .emplace_back (pCaseValue);
476+ }
482477
483- if (SwitchCaseGroups.size () == 0 ) {
484- // All case labels were assimilated into the default label.
485- // Replace switch with an unconditional branch.
486- BranchInst::Create (pDefaultBB, I);
487- I->eraseFromParent ();
488- } else {
489- // Rewrite switch instruction such that case labels are grouped by the
490- // successor.
491- unsigned CaseIdx = 0 ;
492- for (const SwitchCaseGroup &G : SwitchCaseGroups) {
493- for (ConstantInt *pCaseValue : G.CaseValue ) {
494- SwitchInst::CaseIt itCase (I, CaseIdx++);
495- itCase.setSuccessor (G.pSuccBB );
496- itCase.setValue (pCaseValue);
478+ if (SwitchCaseGroups.size () == 0 ) {
479+ // All case labels were assimilated into the default label.
480+ // Replace switch with an unconditional branch.
481+ BranchInst::Create (pDefaultBB, I);
482+ I->eraseFromParent ();
483+ } else {
484+ // Rewrite switch instruction such that case labels are grouped by the
485+ // successor.
486+ unsigned CaseIdx = 0 ;
487+ for (const SwitchCaseGroup &G : SwitchCaseGroups) {
488+ for (ConstantInt *pCaseValue : G.CaseValue ) {
489+ SwitchInst::CaseIt itCase (I, CaseIdx++);
490+ itCase.setSuccessor (G.pSuccBB );
491+ itCase.setValue (pCaseValue);
492+ }
493+ }
494+ // Remove unused case labels.
495+ for (unsigned NumCases = I->getNumCases (); CaseIdx < NumCases;
496+ NumCases--) {
497+ I->removeCase (SwitchInst::CaseIt{I, NumCases - 1 });
497498 }
498- }
499- // Remove unused case labels.
500- for (unsigned NumCases = I->getNumCases (); CaseIdx < NumCases;
501- NumCases--) {
502- I->removeCase (SwitchInst::CaseIt{I, NumCases - 1 });
503499 }
504500 }
505- }
506501
507- // Recurse, visiting each successor group once.
508- TerminatorInst *pTI = pBB->getTerminator ();
509- BasicBlock *pPrevSuccBB = nullptr ;
510- for (unsigned i = 0 ; i < pTI->getNumSuccessors (); i++) {
511- BasicBlock *pSuccBB = pTI->getSuccessor (i);
512- if (pSuccBB != pPrevSuccBB) {
513- SanitizeBranchesRec (pSuccBB, VisitedBB);
502+ // Push successors onto worklist, visiting each successor group once.
503+ TerminatorInst *pTI = pBB->getTerminator ();
504+ BasicBlock *pPrevSuccBB = nullptr ;
505+ for (unsigned i = 0 ; i < pTI->getNumSuccessors (); i++) {
506+ BasicBlock *pSuccBB = pTI->getSuccessor (i);
507+ if (pSuccBB != pPrevSuccBB)
508+ Worklist.push_back (pSuccBB);
509+ pPrevSuccBB = pSuccBB;
514510 }
515- pPrevSuccBB = pSuccBB;
516511 }
517512}
518513
@@ -537,14 +532,24 @@ void ScopeNestedCFG::CollectUniqueSuccessors(
537532// -----------------------------------------------------------------------------
538533// Loop region transformations.
539534// -----------------------------------------------------------------------------
540- void ScopeNestedCFG::CollectLoopsRec (Loop *pLoop) {
541- for (auto itLoop = pLoop->begin (), endLoop = pLoop->end (); itLoop != endLoop;
542- ++itLoop) {
543- Loop *pNestedLoop = *itLoop;
544- CollectLoopsRec (pNestedLoop);
535+ void ScopeNestedCFG::CollectLoops (Loop *pLoop) {
536+ // Iterative post-order: collect in reverse pre-order, then reverse.
537+ SmallVector<Loop *, 16 > Stack;
538+ SmallVector<Loop *, 16 > ReversePostOrder;
539+ Stack.push_back (pLoop);
540+
541+ while (!Stack.empty ()) {
542+ Loop *pCurrent = Stack.pop_back_val ();
543+ ReversePostOrder.push_back (pCurrent);
544+ for (auto it = pCurrent->begin (), end = pCurrent->end (); it != end; ++it) {
545+ Stack.push_back (*it);
546+ }
545547 }
546548
547- m_Loops.emplace_back (pLoop);
549+ for (auto it = ReversePostOrder.rbegin (), end = ReversePostOrder.rend ();
550+ it != end; ++it) {
551+ m_Loops.emplace_back (*it);
552+ }
548553}
549554
550555void ScopeNestedCFG::AnnotateBranch (BasicBlock *pBB, BranchKind Kind) {
@@ -988,60 +993,102 @@ void ScopeNestedCFG::BlockTopologicalOrderAndReachability::dump(
988993
989994void ScopeNestedCFG::ComputeBlockTopologicalOrderAndReachability (
990995 BasicBlock *pEntry, BlockTopologicalOrderAndReachability &BTO) {
991- unordered_map<BasicBlock *, unsigned > WaterMarks;
992- ComputeBlockTopologicalOrderAndReachabilityRec (pEntry, BTO, WaterMarks);
996+ DenseMap<BasicBlock *, unsigned > Marks;
997+ unsigned NumBBs = (unsigned )pEntry->getParent ()->getBasicBlockList ().size ();
998+
999+ struct StackFrame {
1000+ BasicBlock *pNode;
1001+ BasicBlock *pEffective;
1002+ unique_ptr<BitVector> ReachableBBs;
1003+ succ_iterator CurrentSucc;
1004+ succ_iterator EndSucc;
1005+ bool Initialized;
1006+
1007+ StackFrame (BasicBlock *Node)
1008+ : pNode(Node), pEffective(nullptr ), CurrentSucc(succ_begin(Node)),
1009+ EndSucc (succ_end(Node)), Initialized(false ) {}
1010+ };
9931011
994- #if SNCFG_DBG
995- dbgs () << " \n BB topological order and reachable BBs rooted at "
996- << pEntry->getName () << " :\n " ;
997- BTO.dump (dbgs ());
998- #endif
999- }
1012+ SmallVector<StackFrame, 32 > Stack;
1013+ Stack.emplace_back(pEntry);
10001014
1001- void ScopeNestedCFG::ComputeBlockTopologicalOrderAndReachabilityRec (
1002- BasicBlock *pNode, BlockTopologicalOrderAndReachability &BTO,
1003- unordered_map<BasicBlock *, unsigned > &Marks) {
1004- auto itMarkBB = Marks.find (pNode);
1005- if (Marks.find (pNode) != Marks.end ()) {
1006- DXASSERT (itMarkBB->second == 2 , " acyclic component has a cycle" );
1007- return ;
1008- }
1015+ while (!Stack.empty()) {
1016+ StackFrame &Frame = Stack.back ();
10091017
1010- unsigned NumBBs = (unsigned )pNode->getParent ()->getBasicBlockList ().size ();
1018+ if (!Frame.Initialized ) {
1019+ auto itMark = Marks.find (Frame.pNode );
1020+ if (itMark != Marks.end ()) {
1021+ DXASSERT (itMark->second == 2 , " acyclic component has a cycle" );
1022+ Stack.pop_back ();
1023+ continue ;
1024+ }
10111025
1012- // Region terminator.
1013- if (IsAcyclicRegionTerminator (pNode)) {
1014- Marks[pNode] = 2 ; // late watermark
1015- BTO.AppendBlock (pNode, std::make_unique<BitVector>(NumBBs, false ));
1016- return ;
1017- }
1026+ // Region terminator.
1027+ if (IsAcyclicRegionTerminator (Frame.pNode )) {
1028+ Marks[Frame.pNode ] = 2 ; // late watermark
1029+ BTO.AppendBlock (Frame.pNode ,
1030+ std::make_unique<BitVector>(NumBBs, false ));
1031+ Stack.pop_back ();
1032+ continue ;
1033+ }
10181034
1019- BasicBlock *pNodeToFollowSuccessors =
1020- GetEffectiveNodeToFollowSuccessor (pNode);
1035+ BasicBlock *pEffective = GetEffectiveNodeToFollowSuccessor (Frame.pNode );
10211036
1022- // Loop with no exit.
1023- if (pNodeToFollowSuccessors == nullptr ) {
1024- Marks[pNode] = 2 ; // late watermark
1025- BTO.AppendBlock (pNode, std::make_unique<BitVector>(NumBBs, false ));
1026- return ;
1027- }
1037+ // Loop with no exit.
1038+ if (pEffective == nullptr ) {
1039+ Marks[Frame.pNode ] = 2 ; // late watermark
1040+ BTO.AppendBlock (Frame.pNode ,
1041+ std::make_unique<BitVector>(NumBBs, false ));
1042+ Stack.pop_back ();
1043+ continue ;
1044+ }
10281045
1029- Marks[pNode] = 1 ; // early watermark
1046+ Frame.Initialized = true ;
1047+ Frame.pEffective = pEffective;
1048+ Marks[Frame.pNode ] = 1 ; // early watermark
1049+ Frame.ReachableBBs = std::make_unique<BitVector>(NumBBs, false );
1050+ Frame.CurrentSucc = succ_begin (pEffective);
1051+ Frame.EndSucc = succ_end (pEffective);
1052+ }
10301053
1031- auto ReachableBBs = std::make_unique<BitVector>(NumBBs, false );
1032- for (auto itSucc = succ_begin (pNodeToFollowSuccessors),
1033- endSucc = succ_end (pNodeToFollowSuccessors);
1034- itSucc != endSucc; ++itSucc) {
1035- BasicBlock *pSuccBB = *itSucc;
1054+ // Process successors one at a time. When an unvisited successor is found,
1055+ // push it and revisit this frame later (without advancing the iterator so
1056+ // the now-visited successor will be unioned on the next visit).
1057+ bool PushedChild = false ;
1058+ while (Frame.CurrentSucc != Frame.EndSucc ) {
1059+ BasicBlock *pSuccBB = *Frame.CurrentSucc ;
1060+ auto itMark = Marks.find (pSuccBB);
1061+ if (itMark != Marks.end ()) {
1062+ DXASSERT (itMark->second == 2 , " acyclic component has a cycle" );
1063+ // Already processed, union reachable BBs and advance.
1064+ (*Frame.ReachableBBs ) |= (*BTO.GetReachableBBs (pSuccBB));
1065+ ++Frame.CurrentSucc ;
1066+ } else {
1067+ // Successor not yet visited; push it for processing.
1068+ // Don't advance the iterator: when we return here the successor
1069+ // will be marked and we will union its reachability above.
1070+ Stack.emplace_back (pSuccBB);
1071+ PushedChild = true ;
1072+ break ;
1073+ }
1074+ }
10361075
1037- ComputeBlockTopologicalOrderAndReachabilityRec (pSuccBB, BTO, Marks);
1038- // Union reachable BBs.
1039- (*ReachableBBs) |= (*BTO.GetReachableBBs (pSuccBB));
1040- }
1076+ if (PushedChild)
1077+ continue ;
10411078
1042- Marks[pNode] = 2 ; // late watermark
1079+ // All successors processed.
1080+ BasicBlock *pNode = Frame.pNode ;
1081+ auto ReachableBBs = std::move (Frame.ReachableBBs );
1082+ Marks[pNode] = 2 ; // late watermark
1083+ BTO.AppendBlock (pNode, std::move (ReachableBBs));
1084+ Stack.pop_back ();
1085+ }
10431086
1044- BTO.AppendBlock (pNode, std::move (ReachableBBs));
1087+ #if SNCFG_DBG
1088+ dbgs () << "\nBB topological order and reachable BBs rooted at "
1089+ << pEntry->getName() << ":\n";
1090+ BTO.dump(dbgs());
1091+ #endif
10451092}
10461093
10471094// -----------------------------------------------------------------------------
0 commit comments