1 //===- PrintSCC.cpp - Enumerate SCCs in some key graphs -------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file provides passes to print out SCCs in a CFG or a CallGraph. 11 // Normally, you would not use these passes; instead, you would use the 12 // scc_iterator directly to enumerate SCCs and process them in some way. These 13 // passes serve three purposes: 14 // 15 // (1) As a reference for how to use the scc_iterator. 16 // (2) To print out the SCCs for a CFG or a CallGraph: 17 // analyze -print-cfg-sccs to print the SCCs in each CFG of a module. 18 // analyze -print-cfg-sccs -stats to print the #SCCs and the maximum SCC size. 19 // analyze -print-cfg-sccs -debug > /dev/null to watch the algorithm in action. 20 // 21 // and similarly: 22 // analyze -print-callgraph-sccs [-stats] [-debug] to print SCCs in the CallGraph 23 // 24 // (3) To test the scc_iterator. 25 // 26 //===----------------------------------------------------------------------===// 27 28 #include "llvm/ADT/SCCIterator.h" 29 #include "llvm/Analysis/CallGraph.h" 30 #include "llvm/IR/Module.h" 31 #include "llvm/Pass.h" 32 #include "llvm/Support/CFG.h" 33 #include "llvm/Support/raw_ostream.h" 34 using namespace llvm; 35 36 namespace { 37 struct CFGSCC : public FunctionPass { 38 static char ID; // Pass identification, replacement for typeid 39 CFGSCC() : FunctionPass(ID) {} 40 bool runOnFunction(Function& func); 41 42 void print(raw_ostream &O, const Module* = 0) const { } 43 44 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 45 AU.setPreservesAll(); 46 } 47 }; 48 49 struct CallGraphSCC : public ModulePass { 50 static char ID; // Pass identification, replacement for typeid 51 CallGraphSCC() : ModulePass(ID) {} 52 53 // run - Print out SCCs in the call graph for the specified module. 54 bool runOnModule(Module &M); 55 56 void print(raw_ostream &O, const Module* = 0) const { } 57 58 // getAnalysisUsage - This pass requires the CallGraph. 59 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 60 AU.setPreservesAll(); 61 AU.addRequired<CallGraph>(); 62 } 63 }; 64 } 65 66 char CFGSCC::ID = 0; 67 static RegisterPass<CFGSCC> 68 Y("print-cfg-sccs", "Print SCCs of each function CFG"); 69 70 char CallGraphSCC::ID = 0; 71 static RegisterPass<CallGraphSCC> 72 Z("print-callgraph-sccs", "Print SCCs of the Call Graph"); 73 74 bool CFGSCC::runOnFunction(Function &F) { 75 unsigned sccNum = 0; 76 errs() << "SCCs for Function " << F.getName() << " in PostOrder:"; 77 for (scc_iterator<Function*> SCCI = scc_begin(&F), 78 E = scc_end(&F); SCCI != E; ++SCCI) { 79 std::vector<BasicBlock*> &nextSCC = *SCCI; 80 errs() << "\nSCC #" << ++sccNum << " : "; 81 for (std::vector<BasicBlock*>::const_iterator I = nextSCC.begin(), 82 E = nextSCC.end(); I != E; ++I) 83 errs() << (*I)->getName() << ", "; 84 if (nextSCC.size() == 1 && SCCI.hasLoop()) 85 errs() << " (Has self-loop)."; 86 } 87 errs() << "\n"; 88 89 return true; 90 } 91 92 93 // run - Print out SCCs in the call graph for the specified module. 94 bool CallGraphSCC::runOnModule(Module &M) { 95 CallGraphNode* rootNode = getAnalysis<CallGraph>().getRoot(); 96 unsigned sccNum = 0; 97 errs() << "SCCs for the program in PostOrder:"; 98 for (scc_iterator<CallGraphNode*> SCCI = scc_begin(rootNode), 99 E = scc_end(rootNode); SCCI != E; ++SCCI) { 100 const std::vector<CallGraphNode*> &nextSCC = *SCCI; 101 errs() << "\nSCC #" << ++sccNum << " : "; 102 for (std::vector<CallGraphNode*>::const_iterator I = nextSCC.begin(), 103 E = nextSCC.end(); I != E; ++I) 104 errs() << ((*I)->getFunction() ? (*I)->getFunction()->getName() 105 : "external node") << ", "; 106 if (nextSCC.size() == 1 && SCCI.hasLoop()) 107 errs() << " (Has self-loop)."; 108 } 109 errs() << "\n"; 110 111 return true; 112 } 113