blob: f314baaba937c086f9b09a06205e3fcef07c50f1 [file] [log] [blame]
Dan Gohmanf17a25c2007-07-18 16:29:46 +00001//===- PrintSCC.cpp - Enumerate SCCs in some key graphs -------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner5f5a5732007-12-29 20:44:31 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Dan Gohmanf17a25c2007-07-18 16:29:46 +00007//
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:
Duncan Sandsd10d6f72008-09-23 12:47:39 +000017// 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.
Dan Gohmanf17a25c2007-07-18 16:29:46 +000020//
21// and similarly:
Duncan Sandsd10d6f72008-09-23 12:47:39 +000022// analyze -print-callgraph-sccs [-stats] [-debug] to print SCCs in the CallGraph
Dan Gohmanf17a25c2007-07-18 16:29:46 +000023//
24// (3) To test the scc_iterator.
25//
26//===----------------------------------------------------------------------===//
27
28#include "llvm/Pass.h"
29#include "llvm/Module.h"
30#include "llvm/Analysis/CallGraph.h"
31#include "llvm/Support/CFG.h"
32#include "llvm/ADT/SCCIterator.h"
33#include <iostream>
34using namespace llvm;
35
36namespace {
37 struct CFGSCC : public FunctionPass {
38 static char ID; // Pass identification, replacement for typeid
39 CFGSCC() : FunctionPass((intptr_t)&ID) {}
40 bool runOnFunction(Function& func);
41
42 void print(std::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((intptr_t)&ID) {}
52
53 // run - Print out SCCs in the call graph for the specified module.
54 bool runOnModule(Module &M);
55
56 void print(std::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 char CFGSCC::ID = 0;
66 RegisterPass<CFGSCC>
Duncan Sandsd10d6f72008-09-23 12:47:39 +000067 Y("print-cfg-sccs", "Print SCCs of each function CFG");
Dan Gohmanf17a25c2007-07-18 16:29:46 +000068
69 char CallGraphSCC::ID = 0;
70 RegisterPass<CallGraphSCC>
Duncan Sandsd10d6f72008-09-23 12:47:39 +000071 Z("print-callgraph-sccs", "Print SCCs of the Call Graph");
Dan Gohmanf17a25c2007-07-18 16:29:46 +000072}
73
74bool CFGSCC::runOnFunction(Function &F) {
75 unsigned sccNum = 0;
76 std::cout << "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 std::cout << "\nSCC #" << ++sccNum << " : ";
81 for (std::vector<BasicBlock*>::const_iterator I = nextSCC.begin(),
82 E = nextSCC.end(); I != E; ++I)
83 std::cout << (*I)->getName() << ", ";
84 if (nextSCC.size() == 1 && SCCI.hasLoop())
85 std::cout << " (Has self-loop).";
86 }
87 std::cout << "\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 std::cout << "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 std::cout << "\nSCC #" << ++sccNum << " : ";
102 for (std::vector<CallGraphNode*>::const_iterator I = nextSCC.begin(),
103 E = nextSCC.end(); I != E; ++I)
104 std::cout << ((*I)->getFunction() ? (*I)->getFunction()->getName()
105 : std::string("Indirect CallGraph node")) << ", ";
106 if (nextSCC.size() == 1 && SCCI.hasLoop())
107 std::cout << " (Has self-loop).";
108 }
109 std::cout << "\n";
110
111 return true;
112}