blob: dfb7420542c93d5ea712a9d64cf1c4225c96605e [file] [log] [blame]
Chris Lattner23ebd752003-08-31 19:23:41 +00001//===- PrintSCC.cpp - Enumerate SCCs in some key graphs -------------------===//
Vikram S. Advec405daf2002-11-04 14:20:22 +00002//
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
Chris Lattner55b2eb32003-08-31 20:01:57 +00005// scc_iterator directly to enumerate SCCs and process them in some way. These
6// passes serve three purposes:
7//
8// (1) As a reference for how to use the scc_iterator.
Vikram S. Advec405daf2002-11-04 14:20:22 +00009// (2) To print out the SCCs for a CFG or a CallGraph:
10// analyze -cfgscc to print the SCCs in each CFG of a module.
11// analyze -cfgscc -stats to print the #SCCs and the maximum SCC size.
12// analyze -cfgscc -debug > /dev/null to watch the algorithm in action.
13//
14// and similarly:
15// analyze -callscc [-stats] [-debug] to print SCCs in the CallGraph
16//
Chris Lattner55b2eb32003-08-31 20:01:57 +000017// (3) To test the scc_iterator.
Chris Lattner23ebd752003-08-31 19:23:41 +000018//
Vikram S. Advec405daf2002-11-04 14:20:22 +000019//===----------------------------------------------------------------------===//
20
21#include "llvm/Pass.h"
22#include "llvm/Module.h"
Vikram S. Advec405daf2002-11-04 14:20:22 +000023#include "llvm/Analysis/CallGraph.h"
24#include "llvm/Support/CFG.h"
Chris Lattner55b2eb32003-08-31 20:01:57 +000025#include "Support/SCCIterator.h"
Vikram S. Advec405daf2002-11-04 14:20:22 +000026
27namespace {
Chris Lattner8d0a23a2003-08-31 19:27:11 +000028 struct CFGSCC : public FunctionPass {
29 bool runOnFunction(Function& func);
30
31 void print(std::ostream &O) const { }
32
33 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
34 AU.setPreservesAll();
Chris Lattner23ebd752003-08-31 19:23:41 +000035 }
Chris Lattner8d0a23a2003-08-31 19:27:11 +000036 };
Vikram S. Advec405daf2002-11-04 14:20:22 +000037
Chris Lattner8d0a23a2003-08-31 19:27:11 +000038 struct CallGraphSCC : public Pass {
39 // run - Print out SCCs in the call graph for the specified module.
40 bool run(Module &M);
Vikram S. Advec405daf2002-11-04 14:20:22 +000041
Chris Lattner8d0a23a2003-08-31 19:27:11 +000042 void print(std::ostream &O) const { }
Vikram S. Advec405daf2002-11-04 14:20:22 +000043
Chris Lattner8d0a23a2003-08-31 19:27:11 +000044 // getAnalysisUsage - This pass requires the CallGraph.
45 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
46 AU.setPreservesAll();
47 AU.addRequired<CallGraph>();
Chris Lattner23ebd752003-08-31 19:23:41 +000048 }
Chris Lattner8d0a23a2003-08-31 19:27:11 +000049 };
Vikram S. Advec405daf2002-11-04 14:20:22 +000050
Chris Lattner23ebd752003-08-31 19:23:41 +000051 RegisterAnalysis<CFGSCC>
52 Y("cfgscc", "Print SCCs of each function CFG");
Vikram S. Advec405daf2002-11-04 14:20:22 +000053
Chris Lattner23ebd752003-08-31 19:23:41 +000054 RegisterAnalysis<CallGraphSCC>
55 Z("callscc", "Print SCCs of the Call Graph");
Vikram S. Advec405daf2002-11-04 14:20:22 +000056}
Chris Lattner8d0a23a2003-08-31 19:27:11 +000057
58bool CFGSCC::runOnFunction(Function &F) {
59 unsigned sccNum = 0;
60 std::cout << "SCCs for Function " << F.getName() << " in PostOrder:";
Chris Lattner55b2eb32003-08-31 20:01:57 +000061 for (scc_iterator<Function*> SCCI = scc_begin(&F),
62 E = scc_end(&F); SCCI != E; ++SCCI) {
Chris Lattner729d73d2003-08-31 19:55:06 +000063 std::vector<BasicBlock*> &nextSCC = *SCCI;
Chris Lattner8d0a23a2003-08-31 19:27:11 +000064 std::cout << "\nSCC #" << ++sccNum << " : ";
Chris Lattner9f2a06e2003-08-31 19:51:38 +000065 for (std::vector<BasicBlock*>::const_iterator I = nextSCC.begin(),
Chris Lattner8d0a23a2003-08-31 19:27:11 +000066 E = nextSCC.end(); I != E; ++I)
67 std::cout << (*I)->getName() << ", ";
Chris Lattner9f2a06e2003-08-31 19:51:38 +000068 if (nextSCC.size() == 1 && SCCI.hasLoop())
Chris Lattner8d0a23a2003-08-31 19:27:11 +000069 std::cout << " (Has self-loop).";
70 }
71 std::cout << "\n";
72
73 return true;
74}
75
76
77// run - Print out SCCs in the call graph for the specified module.
78bool CallGraphSCC::run(Module &M) {
79 CallGraphNode* rootNode = getAnalysis<CallGraph>().getRoot();
80 unsigned sccNum = 0;
81 std::cout << "SCCs for the program in PostOrder:";
Chris Lattner55b2eb32003-08-31 20:01:57 +000082 for (scc_iterator<CallGraphNode*> SCCI = scc_begin(rootNode),
83 E = scc_end(rootNode); SCCI != E; ++SCCI) {
Chris Lattner729d73d2003-08-31 19:55:06 +000084 const std::vector<CallGraphNode*> &nextSCC = *SCCI;
Chris Lattner8d0a23a2003-08-31 19:27:11 +000085 std::cout << "\nSCC #" << ++sccNum << " : ";
Chris Lattner9f2a06e2003-08-31 19:51:38 +000086 for (std::vector<CallGraphNode*>::const_iterator I = nextSCC.begin(),
Chris Lattner8d0a23a2003-08-31 19:27:11 +000087 E = nextSCC.end(); I != E; ++I)
88 std::cout << ((*I)->getFunction() ? (*I)->getFunction()->getName()
89 : std::string("Indirect CallGraph node")) << ", ";
Chris Lattner9f2a06e2003-08-31 19:51:38 +000090 if (nextSCC.size() == 1 && SCCI.hasLoop())
Chris Lattner8d0a23a2003-08-31 19:27:11 +000091 std::cout << " (Has self-loop).";
92 }
93 std::cout << "\n";
94
95 return true;
96}