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,89 @@ 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+ }
497493 }
498- }
499- // Remove unused case labels.
500- for (unsigned NumCases = I->getNumCases (); CaseIdx < NumCases;
501- NumCases--) {
502- I->removeCase (SwitchInst::CaseIt{I, NumCases - 1 });
494+ // Remove unused case labels.
495+ for (unsigned NumCases = I->getNumCases (); CaseIdx < NumCases;
496+ --NumCases)
497+ I->removeCase (SwitchInst::CaseIt{I, NumCases - 1 });
503498 }
504499 }
505- }
506500
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);
501+ // Push successors onto worklist, visiting each successor group once.
502+ TerminatorInst *pTI = pBB->getTerminator ();
503+ BasicBlock *pPrevSuccBB = nullptr ;
504+ for (unsigned i = 0 ; i < pTI->getNumSuccessors (); i++) {
505+ BasicBlock *pSuccBB = pTI->getSuccessor (i);
506+ if (pSuccBB != pPrevSuccBB)
507+ Worklist.push_back (pSuccBB);
508+ pPrevSuccBB = pSuccBB;
514509 }
515- pPrevSuccBB = pSuccBB;
516510 }
517511}
518512
@@ -537,14 +531,22 @@ void ScopeNestedCFG::CollectUniqueSuccessors(
537531// -----------------------------------------------------------------------------
538532// Loop region transformations.
539533// -----------------------------------------------------------------------------
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);
534+ void ScopeNestedCFG::CollectLoops (Loop *pLoop) {
535+ // Iterative post-order: collect in reverse pre-order, then reverse.
536+ SmallVector<Loop *, 16 > Stack;
537+ SmallVector<Loop *, 16 > ReversePostOrder;
538+ Stack.push_back (pLoop);
539+
540+ while (!Stack.empty ()) {
541+ Loop *pCurrent = Stack.pop_back_val ();
542+ ReversePostOrder.push_back (pCurrent);
543+ for (auto it = pCurrent->begin (), end = pCurrent->end (); it != end; ++it)
544+ Stack.push_back (*it);
545545 }
546546
547- m_Loops.emplace_back (pLoop);
547+ for (auto it = ReversePostOrder.rbegin (), end = ReversePostOrder.rend ();
548+ it != end; ++it)
549+ m_Loops.emplace_back (*it);
548550}
549551
550552void ScopeNestedCFG::AnnotateBranch (BasicBlock *pBB, BranchKind Kind) {
@@ -988,60 +990,102 @@ void ScopeNestedCFG::BlockTopologicalOrderAndReachability::dump(
988990
989991void ScopeNestedCFG::ComputeBlockTopologicalOrderAndReachability (
990992 BasicBlock *pEntry, BlockTopologicalOrderAndReachability &BTO) {
991- unordered_map<BasicBlock *, unsigned > WaterMarks;
992- ComputeBlockTopologicalOrderAndReachabilityRec (pEntry, BTO, WaterMarks);
993+ DenseMap<BasicBlock *, unsigned > Marks;
994+ unsigned NumBBs = (unsigned )pEntry->getParent ()->getBasicBlockList ().size ();
995+
996+ struct StackFrame {
997+ BasicBlock *pNode;
998+ BasicBlock *pEffective;
999+ unique_ptr<BitVector> ReachableBBs;
1000+ succ_iterator CurrentSucc;
1001+ succ_iterator EndSucc;
1002+ bool Initialized;
1003+
1004+ StackFrame (BasicBlock *Node)
1005+ : pNode(Node), pEffective(nullptr ), CurrentSucc(succ_begin(Node)),
1006+ EndSucc (succ_end(Node)), Initialized(false ) {}
1007+ };
9931008
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- }
1009+ SmallVector<StackFrame, 32 > Stack;
1010+ Stack.emplace_back(pEntry);
10001011
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- }
1012+ while (!Stack.empty()) {
1013+ StackFrame &Frame = Stack.back ();
10091014
1010- unsigned NumBBs = (unsigned )pNode->getParent ()->getBasicBlockList ().size ();
1015+ if (!Frame.Initialized ) {
1016+ auto itMark = Marks.find (Frame.pNode );
1017+ if (itMark != Marks.end ()) {
1018+ DXASSERT (itMark->second == 2 , " acyclic component has a cycle" );
1019+ Stack.pop_back ();
1020+ continue ;
1021+ }
10111022
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- }
1023+ // Region terminator.
1024+ if (IsAcyclicRegionTerminator (Frame.pNode )) {
1025+ Marks[Frame.pNode ] = 2 ; // late watermark
1026+ BTO.AppendBlock (Frame.pNode ,
1027+ std::make_unique<BitVector>(NumBBs, false ));
1028+ Stack.pop_back ();
1029+ continue ;
1030+ }
10181031
1019- BasicBlock *pNodeToFollowSuccessors =
1020- GetEffectiveNodeToFollowSuccessor (pNode);
1032+ BasicBlock *pEffective = GetEffectiveNodeToFollowSuccessor (Frame.pNode );
10211033
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- }
1034+ // Loop with no exit.
1035+ if (pEffective == nullptr ) {
1036+ Marks[Frame.pNode ] = 2 ; // late watermark
1037+ BTO.AppendBlock (Frame.pNode ,
1038+ std::make_unique<BitVector>(NumBBs, false ));
1039+ Stack.pop_back ();
1040+ continue ;
1041+ }
10281042
1029- Marks[pNode] = 1 ; // early watermark
1043+ Frame.Initialized = true ;
1044+ Frame.pEffective = pEffective;
1045+ Marks[Frame.pNode ] = 1 ; // early watermark
1046+ Frame.ReachableBBs = std::make_unique<BitVector>(NumBBs, false );
1047+ Frame.CurrentSucc = succ_begin (pEffective);
1048+ Frame.EndSucc = succ_end (pEffective);
1049+ }
10301050
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;
1051+ // Process successors one at a time. When an unvisited successor is found,
1052+ // push it and revisit this frame later (without advancing the iterator so
1053+ // the now-visited successor will be unioned on the next visit).
1054+ bool PushedChild = false ;
1055+ while (Frame.CurrentSucc != Frame.EndSucc ) {
1056+ BasicBlock *pSuccBB = *Frame.CurrentSucc ;
1057+ auto itMark = Marks.find (pSuccBB);
1058+ if (itMark != Marks.end ()) {
1059+ DXASSERT (itMark->second == 2 , " acyclic component has a cycle" );
1060+ // Already processed, union reachable BBs and advance.
1061+ (*Frame.ReachableBBs ) |= (*BTO.GetReachableBBs (pSuccBB));
1062+ ++Frame.CurrentSucc ;
1063+ } else {
1064+ // Successor not yet visited; push it for processing.
1065+ // Don't advance the iterator: when we return here the successor
1066+ // will be marked and we will union its reachability above.
1067+ Stack.emplace_back (pSuccBB);
1068+ PushedChild = true ;
1069+ break ;
1070+ }
1071+ }
10361072
1037- ComputeBlockTopologicalOrderAndReachabilityRec (pSuccBB, BTO, Marks);
1038- // Union reachable BBs.
1039- (*ReachableBBs) |= (*BTO.GetReachableBBs (pSuccBB));
1040- }
1073+ if (PushedChild)
1074+ continue ;
10411075
1042- Marks[pNode] = 2 ; // late watermark
1076+ // All successors processed.
1077+ BasicBlock *pNode = Frame.pNode ;
1078+ unique_ptr<BitVector> ReachableBBs = std::move (Frame.ReachableBBs );
1079+ Marks[pNode] = 2 ; // late watermark
1080+ BTO.AppendBlock (pNode, std::move (ReachableBBs));
1081+ Stack.pop_back ();
1082+ }
10431083
1044- BTO.AppendBlock (pNode, std::move (ReachableBBs));
1084+ #if SNCFG_DBG
1085+ dbgs () << "\nBB topological order and reachable BBs rooted at "
1086+ << pEntry->getName() << ":\n";
1087+ BTO.dump(dbgs());
1088+ #endif
10451089}
10461090
10471091// -----------------------------------------------------------------------------
0 commit comments