From c405daf3923a9b32fced0b75b937e3d27fb7b349 Mon Sep 17 00:00:00 2001 From: "Vikram S. Adve" Date: Mon, 4 Nov 2002 14:20:22 +0000 Subject: Simple passes that print out SCCs in the CFGs or in the CallGraph of a module. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4532 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/opt/PrintSCC.cpp | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 tools/opt/PrintSCC.cpp (limited to 'tools/opt') diff --git a/tools/opt/PrintSCC.cpp b/tools/opt/PrintSCC.cpp new file mode 100644 index 0000000000..70049d20c9 --- /dev/null +++ b/tools/opt/PrintSCC.cpp @@ -0,0 +1,93 @@ +//===- PrintSCC.cpp - Enumerate SCCs in some key graphs ---------*- C++ -*-===// +// +// This file provides passes to print out SCCs in a CFG or a CallGraph. +// Normally, you would not use these passes; instead, you would use the +// TarjanSCCIterator directly to enumerate SCCs and process them in some way. +// These passes serve three purposes: +// (1) As a reference for how to use the TarjanSCCIterator. +// (2) To print out the SCCs for a CFG or a CallGraph: +// analyze -cfgscc to print the SCCs in each CFG of a module. +// analyze -cfgscc -stats to print the #SCCs and the maximum SCC size. +// analyze -cfgscc -debug > /dev/null to watch the algorithm in action. +// +// and similarly: +// analyze -callscc [-stats] [-debug] to print SCCs in the CallGraph +// +// (3) To test the TarjanSCCIterator. +//===----------------------------------------------------------------------===// + +#include "llvm/Pass.h" +#include "llvm/Module.h" +#include "llvm/Function.h" +#include "llvm/BasicBlock.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Support/CFG.h" +#include "Support/TarjanSCCIterator.h" + +namespace { + +class CFGSCC: public FunctionPass { +public: + bool runOnFunction(Function& func) { + unsigned long sccNum = 0; + const SCC* nextSCC; + std::cout << "SCCs for Function " << func.getName() << " in PostOrder:"; + for (TarjanSCC_iterator tarjSCCiter = tarj_begin(&func); + (nextSCC = *tarjSCCiter); ++tarjSCCiter) + { + std::cout << "\nSCC #" << ++sccNum << " : "; + for (SCC::const_iterator I=nextSCC->begin(),E=nextSCC->end(); + I != E; ++I) + std::cout << (*I)->getName() << ", "; + if (nextSCC->size() == 1 && nextSCC->HasLoop()) + std::cout << " (Has self-loop)."; + } + std::cout << "\n"; + + return true; + } + void print(std::ostream &O) const { } +}; + + +class CallGraphSCC: public Pass { +public: + // run - Print out SCCs in the call graph for the specified module. + bool run(Module& M) { + CallGraphNode* rootNode = getAnalysis().getRoot(); + unsigned long sccNum = 0; + const SCC* nextSCC; + std::cout << "SCCs for the program in PostOrder:"; + for (TarjanSCC_iterator tarjSCCiter = tarj_begin(rootNode); + (nextSCC = *tarjSCCiter); ++tarjSCCiter) + { + std::cout << "\nSCC #" << ++sccNum << " : "; + for (SCC::const_iterator I=nextSCC->begin(), + E=nextSCC->end(); I != E; ++I) + std::cout << ((*I)->getFunction()? (*I)->getFunction()->getName() + : std::string("Null CallGraph node")) + << ", "; + if (nextSCC->size() == 1 && nextSCC->HasLoop()) + std::cout << " (Has self-loop)."; + } + std::cout << "\n"; + + return true; + } + + void print(std::ostream &O) const { } + + // getAnalysisUsage - This pass requires the CallGraph. + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + } +}; + +static RegisterAnalysis +Y("cfgscc", "Print SCCs of each function CFG"); + +static RegisterAnalysis +Z("callscc", "Print SCCs of the Call Graph"); + +} -- cgit v1.2.3