PrintSCC.cpp revision 267654
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" 34using namespace llvm; 35 36namespace { 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 66char CFGSCC::ID = 0; 67static RegisterPass<CFGSCC> 68Y("print-cfg-sccs", "Print SCCs of each function CFG"); 69 70char CallGraphSCC::ID = 0; 71static RegisterPass<CallGraphSCC> 72Z("print-callgraph-sccs", "Print SCCs of the Call Graph"); 73 74bool 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. 94bool 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