@@ -789,6 +789,20 @@ void Compiler::fgDfsReversePostorder()
789
789
}
790
790
}
791
791
792
+ // If there are still unvisited blocks (say isolated cycles), visit them too.
793
+ //
794
+ if (preorderIndex != fgBBcount + 1 )
795
+ {
796
+ JITDUMP (" DFS: flow graph has some isolated cycles, doing extra traversals\n " );
797
+ for (BasicBlock* const block : Blocks ())
798
+ {
799
+ if (!BlockSetOps::IsMember (this , visited, block->bbNum ))
800
+ {
801
+ fgDfsReversePostorderHelper (block, visited, preorderIndex, postorderIndex);
802
+ }
803
+ }
804
+ }
805
+
792
806
// After the DFS reverse postorder is completed, we must have visited all the basic blocks.
793
807
noway_assert (preorderIndex == fgBBcount + 1 );
794
808
noway_assert (postorderIndex == fgBBcount + 1 );
@@ -866,64 +880,91 @@ void Compiler::fgDfsReversePostorderHelper(BasicBlock* block,
866
880
// Assume we haven't visited this node yet (callers ensure this).
867
881
assert (!BlockSetOps::IsMember (this , visited, block->bbNum ));
868
882
883
+ struct DfsBlockEntry
884
+ {
885
+ public:
886
+ DfsBlockEntry (Compiler* comp, BasicBlock* block) : m_block(block), m_nSucc(block->NumSucc (comp)), m_iter(0 )
887
+ {
888
+ }
889
+
890
+ BasicBlock* getBlock ()
891
+ {
892
+ return m_block;
893
+ }
894
+
895
+ bool atStart ()
896
+ {
897
+ return m_iter == 0 ;
898
+ }
899
+
900
+ BasicBlock* getNextSucc (Compiler* comp)
901
+ {
902
+ if (m_iter >= m_nSucc)
903
+ {
904
+ return nullptr ;
905
+ }
906
+ return m_block->GetSucc (m_iter++, comp);
907
+ }
908
+
909
+ private:
910
+ BasicBlock* m_block;
911
+ unsigned m_nSucc;
912
+ unsigned m_iter;
913
+ };
914
+
869
915
// Allocate a local stack to hold the DFS traversal actions necessary
870
916
// to compute pre/post-ordering of the control flowgraph.
871
917
ArrayStack<DfsBlockEntry> stack (getAllocator(CMK_ArrayStack));
872
918
873
919
// Push the first block on the stack to seed the traversal.
874
- stack.Push ( DfsBlockEntry (DSS_Pre , block) );
920
+ stack.Emplace( this , block);
875
921
876
922
// Flag the node we just visited to avoid backtracking.
877
923
BlockSetOps::AddElemD (this , visited, block->bbNum);
878
924
879
925
// The search is terminated once all the actions have been processed.
880
926
while (!stack.Empty())
881
927
{
882
- DfsBlockEntry current = stack.Pop ();
883
- BasicBlock* currentBlock = current.dfsBlock ;
928
+ DfsBlockEntry& current = stack.TopRef ();
929
+ BasicBlock* const block = current.getBlock () ;
884
930
885
- if (current.dfsStackState == DSS_Pre )
931
+ if (current.atStart () )
886
932
{
887
- // This is a pre-visit that corresponds to the first time the
888
- // node is encountered in the spanning tree and receives pre-order
889
- // numberings. By pushing the post-action on the stack here we
890
- // are guaranteed to only process it after all of its successors
891
- // pre and post actions are processed.
892
- stack.Push (DfsBlockEntry (DSS_Post, currentBlock));
893
- currentBlock->bbPreorderNum = preorderIndex;
933
+ // Initial visit to this node
934
+ //
935
+ block->bbPreorderNum = preorderIndex;
894
936
preorderIndex++;
895
-
896
- for (BasicBlock* const succ : currentBlock->Succs (this ))
897
- {
898
- // If this is a node we haven't seen before, go ahead and process
899
- if (!BlockSetOps::IsMember (this , visited, succ->bbNum ))
900
- {
901
- // Push a pre-visit action for this successor onto the stack and
902
- // mark it as visited in case this block has multiple successors
903
- // to the same node (multi-graph).
904
- stack.Push (DfsBlockEntry (DSS_Pre, succ));
905
- BlockSetOps::AddElemD (this , visited, succ->bbNum );
906
- }
907
- }
908
937
}
909
- else
910
- {
911
- // This is a post-visit that corresponds to the last time the
912
- // node is visited in the spanning tree and only happens after
913
- // all descendents in the spanning tree have had pre and post
914
- // actions applied.
915
938
916
- assert (current.dfsStackState == DSS_Post);
917
- currentBlock->bbPostorderNum = postorderIndex;
939
+ BasicBlock* const succ = current.getNextSucc (this );
918
940
919
- // Compute the index of this in the reverse postorder and
941
+ if (succ == nullptr )
942
+ {
943
+ // Final visit to this node
944
+ //
945
+ block->bbPostorderNum = postorderIndex;
946
+
947
+ // Compute the index of block in the reverse postorder and
920
948
// update the reverse postorder accordingly.
921
949
//
922
950
assert (postorderIndex <= fgBBcount);
923
951
unsigned reversePostorderIndex = fgBBcount - postorderIndex + 1 ;
924
- fgBBReversePostorder[reversePostorderIndex] = currentBlock ;
952
+ fgBBReversePostorder[reversePostorderIndex] = block ;
925
953
postorderIndex++;
954
+
955
+ stack.Pop ();
956
+ continue ;
926
957
}
958
+
959
+ if (BlockSetOps::IsMember (this , visited, succ->bbNum ))
960
+ {
961
+ // Already visited this succ
962
+ //
963
+ continue ;
964
+ }
965
+
966
+ BlockSetOps::AddElemD (this , visited, succ->bbNum );
967
+ stack.Emplace (this , succ);
927
968
}
928
969
}
929
970
0 commit comments