Chris Lattner | 23ebd75 | 2003-08-31 19:23:41 +0000 | [diff] [blame] | 1 | //===- PrintSCC.cpp - Enumerate SCCs in some key graphs -------------------===// |
Vikram S. Adve | c405daf | 2002-11-04 14:20:22 +0000 | [diff] [blame] | 2 | // |
| 3 | // This file provides passes to print out SCCs in a CFG or a CallGraph. |
| 4 | // Normally, you would not use these passes; instead, you would use the |
| 5 | // TarjanSCCIterator directly to enumerate SCCs and process them in some way. |
| 6 | // These passes serve three purposes: |
| 7 | // (1) As a reference for how to use the TarjanSCCIterator. |
| 8 | // (2) To print out the SCCs for a CFG or a CallGraph: |
| 9 | // analyze -cfgscc to print the SCCs in each CFG of a module. |
| 10 | // analyze -cfgscc -stats to print the #SCCs and the maximum SCC size. |
| 11 | // analyze -cfgscc -debug > /dev/null to watch the algorithm in action. |
| 12 | // |
| 13 | // and similarly: |
| 14 | // analyze -callscc [-stats] [-debug] to print SCCs in the CallGraph |
| 15 | // |
| 16 | // (3) To test the TarjanSCCIterator. |
Chris Lattner | 23ebd75 | 2003-08-31 19:23:41 +0000 | [diff] [blame] | 17 | // |
Vikram S. Adve | c405daf | 2002-11-04 14:20:22 +0000 | [diff] [blame] | 18 | //===----------------------------------------------------------------------===// |
| 19 | |
| 20 | #include "llvm/Pass.h" |
| 21 | #include "llvm/Module.h" |
Vikram S. Adve | c405daf | 2002-11-04 14:20:22 +0000 | [diff] [blame] | 22 | #include "llvm/Analysis/CallGraph.h" |
| 23 | #include "llvm/Support/CFG.h" |
| 24 | #include "Support/TarjanSCCIterator.h" |
| 25 | |
| 26 | namespace { |
Chris Lattner | 8d0a23a | 2003-08-31 19:27:11 +0000 | [diff] [blame^] | 27 | struct CFGSCC : public FunctionPass { |
| 28 | bool runOnFunction(Function& func); |
| 29 | |
| 30 | void print(std::ostream &O) const { } |
| 31 | |
| 32 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { |
| 33 | AU.setPreservesAll(); |
Chris Lattner | 23ebd75 | 2003-08-31 19:23:41 +0000 | [diff] [blame] | 34 | } |
Chris Lattner | 8d0a23a | 2003-08-31 19:27:11 +0000 | [diff] [blame^] | 35 | }; |
Vikram S. Adve | c405daf | 2002-11-04 14:20:22 +0000 | [diff] [blame] | 36 | |
Chris Lattner | 8d0a23a | 2003-08-31 19:27:11 +0000 | [diff] [blame^] | 37 | struct CallGraphSCC : public Pass { |
| 38 | // run - Print out SCCs in the call graph for the specified module. |
| 39 | bool run(Module &M); |
Vikram S. Adve | c405daf | 2002-11-04 14:20:22 +0000 | [diff] [blame] | 40 | |
Chris Lattner | 8d0a23a | 2003-08-31 19:27:11 +0000 | [diff] [blame^] | 41 | void print(std::ostream &O) const { } |
Vikram S. Adve | c405daf | 2002-11-04 14:20:22 +0000 | [diff] [blame] | 42 | |
Chris Lattner | 8d0a23a | 2003-08-31 19:27:11 +0000 | [diff] [blame^] | 43 | // getAnalysisUsage - This pass requires the CallGraph. |
| 44 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { |
| 45 | AU.setPreservesAll(); |
| 46 | AU.addRequired<CallGraph>(); |
Chris Lattner | 23ebd75 | 2003-08-31 19:23:41 +0000 | [diff] [blame] | 47 | } |
Chris Lattner | 8d0a23a | 2003-08-31 19:27:11 +0000 | [diff] [blame^] | 48 | }; |
Vikram S. Adve | c405daf | 2002-11-04 14:20:22 +0000 | [diff] [blame] | 49 | |
Chris Lattner | 23ebd75 | 2003-08-31 19:23:41 +0000 | [diff] [blame] | 50 | RegisterAnalysis<CFGSCC> |
| 51 | Y("cfgscc", "Print SCCs of each function CFG"); |
Vikram S. Adve | c405daf | 2002-11-04 14:20:22 +0000 | [diff] [blame] | 52 | |
Chris Lattner | 23ebd75 | 2003-08-31 19:23:41 +0000 | [diff] [blame] | 53 | RegisterAnalysis<CallGraphSCC> |
| 54 | Z("callscc", "Print SCCs of the Call Graph"); |
Vikram S. Adve | c405daf | 2002-11-04 14:20:22 +0000 | [diff] [blame] | 55 | } |
Chris Lattner | 8d0a23a | 2003-08-31 19:27:11 +0000 | [diff] [blame^] | 56 | |
| 57 | bool CFGSCC::runOnFunction(Function &F) { |
| 58 | unsigned sccNum = 0; |
| 59 | std::cout << "SCCs for Function " << F.getName() << " in PostOrder:"; |
| 60 | for (TarjanSCC_iterator<Function*> I = tarj_begin(&F), |
| 61 | E = tarj_end(&F); I != E; ++I) { |
| 62 | SCC<Function*> &nextSCC = **I; |
| 63 | std::cout << "\nSCC #" << ++sccNum << " : "; |
| 64 | for (SCC<Function*>::const_iterator I = nextSCC.begin(), |
| 65 | E = nextSCC.end(); I != E; ++I) |
| 66 | std::cout << (*I)->getName() << ", "; |
| 67 | if (nextSCC.size() == 1 && nextSCC.HasLoop()) |
| 68 | std::cout << " (Has self-loop)."; |
| 69 | } |
| 70 | std::cout << "\n"; |
| 71 | |
| 72 | return true; |
| 73 | } |
| 74 | |
| 75 | |
| 76 | // run - Print out SCCs in the call graph for the specified module. |
| 77 | bool CallGraphSCC::run(Module &M) { |
| 78 | CallGraphNode* rootNode = getAnalysis<CallGraph>().getRoot(); |
| 79 | unsigned sccNum = 0; |
| 80 | std::cout << "SCCs for the program in PostOrder:"; |
| 81 | for (TarjanSCC_iterator<CallGraphNode*> SCCI = tarj_begin(rootNode), |
| 82 | E = tarj_end(rootNode); SCCI != E; ++SCCI) { |
| 83 | const SCC<CallGraphNode*> &nextSCC = **SCCI; |
| 84 | std::cout << "\nSCC #" << ++sccNum << " : "; |
| 85 | for (SCC<CallGraphNode*>::const_iterator I = nextSCC.begin(), |
| 86 | E = nextSCC.end(); I != E; ++I) |
| 87 | std::cout << ((*I)->getFunction() ? (*I)->getFunction()->getName() |
| 88 | : std::string("Indirect CallGraph node")) << ", "; |
| 89 | if (nextSCC.size() == 1 && nextSCC.HasLoop()) |
| 90 | std::cout << " (Has self-loop)."; |
| 91 | } |
| 92 | std::cout << "\n"; |
| 93 | |
| 94 | return true; |
| 95 | } |