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/CFG.h" 31 #include "llvm/IR/Module.h" 32 #include "llvm/Pass.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) override; 41 42 void print(raw_ostream &O, const Module* = nullptr) const override { } 43 44 void getAnalysisUsage(AnalysisUsage &AU) const override { 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) override; 55 56 void print(raw_ostream &O, const Module* = nullptr) const override { } 57 58 // getAnalysisUsage - This pass requires the CallGraph. 59 void getAnalysisUsage(AnalysisUsage &AU) const override { 60 AU.setPreservesAll(); 61 AU.addRequired<CallGraphWrapperPass>(); 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); !SCCI.isAtEnd(); ++SCCI) { 78 const std::vector<BasicBlock *> &nextSCC = *SCCI; 79 errs() << "\nSCC #" << ++sccNum << " : "; 80 for (std::vector<BasicBlock*>::const_iterator I = nextSCC.begin(), 81 E = nextSCC.end(); I != E; ++I) 82 errs() << (*I)->getName() << ", "; 83 if (nextSCC.size() == 1 && SCCI.hasLoop()) 84 errs() << " (Has self-loop)."; 85 } 86 errs() << "\n"; 87 88 return true; 89 } 90 91 92 // run - Print out SCCs in the call graph for the specified module. 93 bool CallGraphSCC::runOnModule(Module &M) { 94 CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph(); 95 unsigned sccNum = 0; 96 errs() << "SCCs for the program in PostOrder:"; 97 for (scc_iterator<CallGraph*> SCCI = scc_begin(&CG); !SCCI.isAtEnd(); 98 ++SCCI) { 99 const std::vector<CallGraphNode*> &nextSCC = *SCCI; 100 errs() << "\nSCC #" << ++sccNum << " : "; 101 for (std::vector<CallGraphNode*>::const_iterator I = nextSCC.begin(), 102 E = nextSCC.end(); I != E; ++I) 103 errs() << ((*I)->getFunction() ? (*I)->getFunction()->getName() 104 : "external node") << ", "; 105 if (nextSCC.size() == 1 && SCCI.hasLoop()) 106 errs() << " (Has self-loop)."; 107 } 108 errs() << "\n"; 109 110 return true; 111 } 112