一、思路
使用llvm/ADT/SCCIterator.h中定义的scc_iterator迭代器获得。
但是scc_iterator获得是逆拓扑排序的。它的注释如下:
// The SCC iterator has the important property that if a node in SCC S1 has an
// edge to a node in SCC S2, then it visits S1 *after* S2.
/// scc_iterator – Enumerate the SCCs of a directed graph, in
/// reverse topological order of the SCC DAG
所以我们使用栈进行获得SCC正序的拓扑排序(因为scc_iterator不支持自减)
二、获得SCC拓扑排序的代码:
代码如下,其中F是Function*类型的,是待分析的函数
132 std::stack<scc_iterator<Function*> > sccs;
133 for(scc_iterator<Function*> SCCI=scc_begin(F),SCCE=scc_end(F);SCCI!=SCCE;++SCCI)
134 sccs.push(SCCI);
135
136 //按照顺序遍历强连通分量(SCC)
137 unsigned sccNum=0;
138 while(!sccs.empty()){
139 scc_iterator<Function*> SCCI=sccs.top();
140 sccs.pop();
141 std::vector<BasicBlock*> & nextSCC=*SCCI;
142 errs()<<"\n SCC#"<<++sccNum<<":";
143 //遍历SCC中的块(DFS顺序 )
144 std::vector<BasicBlock*>::const_iterator I=nextSCC.begin(),E=nextSCC.end();
145 for(--E,--I;E!=I;--E){
146 errs()<<(*E)->getName()<<",";
147 }
148 }
需要特别指出的,我们打印出SCC内部的基本块(Basic Block)是按照DFS(深度优先)打印出的。
三、参考代码
本代码参考LLVM的
tools/opt/PrintSCC.cpp
include/llvm/ADT/SCCIterator.h
四、参考
http://stackoverflow.com/questions/18650999/topological-sorting-of-basic-blocks-in-llvm