blob: 70049d20c9d299d849d4199cf714ed37f8ab4aa6 [file] [log] [blame]
Vikram S. Advec405daf2002-11-04 14:20:22 +00001//===- PrintSCC.cpp - Enumerate SCCs in some key graphs ---------*- C++ -*-===//
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.
17//===----------------------------------------------------------------------===//
18
19#include "llvm/Pass.h"
20#include "llvm/Module.h"
21#include "llvm/Function.h"
22#include "llvm/BasicBlock.h"
23#include "llvm/Analysis/CallGraph.h"
24#include "llvm/Support/CFG.h"
25#include "Support/TarjanSCCIterator.h"
26
27namespace {
28
29class CFGSCC: public FunctionPass {
30public:
31 bool runOnFunction(Function& func) {
32 unsigned long sccNum = 0;
33 const SCC<Function*>* nextSCC;
34 std::cout << "SCCs for Function " << func.getName() << " in PostOrder:";
35 for (TarjanSCC_iterator<Function*> tarjSCCiter = tarj_begin(&func);
36 (nextSCC = *tarjSCCiter); ++tarjSCCiter)
37 {
38 std::cout << "\nSCC #" << ++sccNum << " : ";
39 for (SCC<Function*>::const_iterator I=nextSCC->begin(),E=nextSCC->end();
40 I != E; ++I)
41 std::cout << (*I)->getName() << ", ";
42 if (nextSCC->size() == 1 && nextSCC->HasLoop())
43 std::cout << " (Has self-loop).";
44 }
45 std::cout << "\n";
46
47 return true;
48 }
49 void print(std::ostream &O) const { }
50};
51
52
53class CallGraphSCC: public Pass {
54public:
55 // run - Print out SCCs in the call graph for the specified module.
56 bool run(Module& M) {
57 CallGraphNode* rootNode = getAnalysis<CallGraph>().getRoot();
58 unsigned long sccNum = 0;
59 const SCC<CallGraphNode*>* nextSCC;
60 std::cout << "SCCs for the program in PostOrder:";
61 for (TarjanSCC_iterator<CallGraphNode*> tarjSCCiter = tarj_begin(rootNode);
62 (nextSCC = *tarjSCCiter); ++tarjSCCiter)
63 {
64 std::cout << "\nSCC #" << ++sccNum << " : ";
65 for (SCC<CallGraphNode*>::const_iterator I=nextSCC->begin(),
66 E=nextSCC->end(); I != E; ++I)
67 std::cout << ((*I)->getFunction()? (*I)->getFunction()->getName()
68 : std::string("Null CallGraph node"))
69 << ", ";
70 if (nextSCC->size() == 1 && nextSCC->HasLoop())
71 std::cout << " (Has self-loop).";
72 }
73 std::cout << "\n";
74
75 return true;
76 }
77
78 void print(std::ostream &O) const { }
79
80 // getAnalysisUsage - This pass requires the CallGraph.
81 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
82 AU.setPreservesAll();
83 AU.addRequired<CallGraph>();
84 }
85};
86
87static RegisterAnalysis<CFGSCC>
88Y("cfgscc", "Print SCCs of each function CFG");
89
90static RegisterAnalysis<CallGraphSCC>
91Z("callscc", "Print SCCs of the Call Graph");
92
93}