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 | 23ebd75 | 2003-08-31 19:23:41 +0000 | [diff] [blame^] | 27 | struct CFGSCC: public FunctionPass { |
Vikram S. Adve | c405daf | 2002-11-04 14:20:22 +0000 | [diff] [blame] | 28 | bool runOnFunction(Function& func) { |
| 29 | unsigned long sccNum = 0; |
Vikram S. Adve | c405daf | 2002-11-04 14:20:22 +0000 | [diff] [blame] | 30 | std::cout << "SCCs for Function " << func.getName() << " in PostOrder:"; |
Chris Lattner | 23ebd75 | 2003-08-31 19:23:41 +0000 | [diff] [blame^] | 31 | for (TarjanSCC_iterator<Function*> I = tarj_begin(&func), |
| 32 | E = tarj_end(&func); I != E; ++I) { |
| 33 | SCC<Function*> &nextSCC = **I; |
| 34 | std::cout << "\nSCC #" << ++sccNum << " : "; |
| 35 | for (SCC<Function*>::const_iterator I = nextSCC.begin(),E = nextSCC.end(); |
| 36 | I != E; ++I) |
| 37 | std::cout << (*I)->getName() << ", "; |
| 38 | if (nextSCC.size() == 1 && nextSCC.HasLoop()) |
| 39 | std::cout << " (Has self-loop)."; |
| 40 | } |
Vikram S. Adve | c405daf | 2002-11-04 14:20:22 +0000 | [diff] [blame] | 41 | std::cout << "\n"; |
| 42 | |
| 43 | return true; |
| 44 | } |
| 45 | void print(std::ostream &O) const { } |
| 46 | }; |
| 47 | |
| 48 | |
Chris Lattner | 23ebd75 | 2003-08-31 19:23:41 +0000 | [diff] [blame^] | 49 | struct CallGraphSCC : public Pass { |
Vikram S. Adve | c405daf | 2002-11-04 14:20:22 +0000 | [diff] [blame] | 50 | // run - Print out SCCs in the call graph for the specified module. |
Chris Lattner | 23ebd75 | 2003-08-31 19:23:41 +0000 | [diff] [blame^] | 51 | bool run(Module &M) { |
Vikram S. Adve | c405daf | 2002-11-04 14:20:22 +0000 | [diff] [blame] | 52 | CallGraphNode* rootNode = getAnalysis<CallGraph>().getRoot(); |
| 53 | unsigned long sccNum = 0; |
Vikram S. Adve | c405daf | 2002-11-04 14:20:22 +0000 | [diff] [blame] | 54 | std::cout << "SCCs for the program in PostOrder:"; |
Chris Lattner | 23ebd75 | 2003-08-31 19:23:41 +0000 | [diff] [blame^] | 55 | for (TarjanSCC_iterator<CallGraphNode*> SCCI = tarj_begin(rootNode), |
| 56 | E = tarj_end(rootNode); SCCI != E; ++SCCI) { |
| 57 | const SCC<CallGraphNode*> &nextSCC = **SCCI; |
| 58 | std::cout << "\nSCC #" << ++sccNum << " : "; |
| 59 | for (SCC<CallGraphNode*>::const_iterator I = nextSCC.begin(), |
| 60 | E = nextSCC.end(); I != E; ++I) |
| 61 | std::cout << ((*I)->getFunction() ? (*I)->getFunction()->getName() |
| 62 | : std::string("Indirect CallGraph node")) << ", "; |
| 63 | if (nextSCC.size() == 1 && nextSCC.HasLoop()) |
| 64 | std::cout << " (Has self-loop)."; |
| 65 | } |
Vikram S. Adve | c405daf | 2002-11-04 14:20:22 +0000 | [diff] [blame] | 66 | std::cout << "\n"; |
| 67 | |
| 68 | return true; |
| 69 | } |
| 70 | |
| 71 | void print(std::ostream &O) const { } |
| 72 | |
| 73 | // getAnalysisUsage - This pass requires the CallGraph. |
| 74 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { |
| 75 | AU.setPreservesAll(); |
| 76 | AU.addRequired<CallGraph>(); |
| 77 | } |
| 78 | }; |
| 79 | |
Chris Lattner | 23ebd75 | 2003-08-31 19:23:41 +0000 | [diff] [blame^] | 80 | RegisterAnalysis<CFGSCC> |
| 81 | Y("cfgscc", "Print SCCs of each function CFG"); |
Vikram S. Adve | c405daf | 2002-11-04 14:20:22 +0000 | [diff] [blame] | 82 | |
Chris Lattner | 23ebd75 | 2003-08-31 19:23:41 +0000 | [diff] [blame^] | 83 | RegisterAnalysis<CallGraphSCC> |
| 84 | Z("callscc", "Print SCCs of the Call Graph"); |
Vikram S. Adve | c405daf | 2002-11-04 14:20:22 +0000 | [diff] [blame] | 85 | } |