PrintSCC.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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. #include "llvm/ADT/SCCIterator.h"
  28. #include "llvm/Analysis/CallGraph.h"
  29. #include "llvm/IR/CFG.h"
  30. #include "llvm/IR/Module.h"
  31. #include "llvm/Pass.h"
  32. #include "llvm/Support/raw_ostream.h"
  33. using namespace llvm;
  34. namespace {
  35. struct CFGSCC : public FunctionPass {
  36. static char ID; // Pass identification, replacement for typeid
  37. CFGSCC() : FunctionPass(ID) {}
  38. bool runOnFunction(Function& func) override;
  39. void print(raw_ostream &O, const Module* = nullptr) const override { }
  40. void getAnalysisUsage(AnalysisUsage &AU) const override {
  41. AU.setPreservesAll();
  42. }
  43. };
  44. struct CallGraphSCC : public ModulePass {
  45. static char ID; // Pass identification, replacement for typeid
  46. CallGraphSCC() : ModulePass(ID) {}
  47. // run - Print out SCCs in the call graph for the specified module.
  48. bool runOnModule(Module &M) override;
  49. void print(raw_ostream &O, const Module* = nullptr) const override { }
  50. // getAnalysisUsage - This pass requires the CallGraph.
  51. void getAnalysisUsage(AnalysisUsage &AU) const override {
  52. AU.setPreservesAll();
  53. AU.addRequired<CallGraphWrapperPass>();
  54. }
  55. };
  56. }
  57. char CFGSCC::ID = 0;
  58. static RegisterPass<CFGSCC>
  59. Y("print-cfg-sccs", "Print SCCs of each function CFG");
  60. char CallGraphSCC::ID = 0;
  61. static RegisterPass<CallGraphSCC>
  62. Z("print-callgraph-sccs", "Print SCCs of the Call Graph");
  63. bool CFGSCC::runOnFunction(Function &F) {
  64. unsigned sccNum = 0;
  65. errs() << "SCCs for Function " << F.getName() << " in PostOrder:";
  66. for (scc_iterator<Function*> SCCI = scc_begin(&F); !SCCI.isAtEnd(); ++SCCI) {
  67. const std::vector<BasicBlock *> &nextSCC = *SCCI;
  68. errs() << "\nSCC #" << ++sccNum << " : ";
  69. for (std::vector<BasicBlock*>::const_iterator I = nextSCC.begin(),
  70. E = nextSCC.end(); I != E; ++I)
  71. errs() << (*I)->getName() << ", ";
  72. if (nextSCC.size() == 1 && SCCI.hasLoop())
  73. errs() << " (Has self-loop).";
  74. }
  75. errs() << "\n";
  76. return true;
  77. }
  78. // run - Print out SCCs in the call graph for the specified module.
  79. bool CallGraphSCC::runOnModule(Module &M) {
  80. CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
  81. unsigned sccNum = 0;
  82. errs() << "SCCs for the program in PostOrder:";
  83. for (scc_iterator<CallGraph*> SCCI = scc_begin(&CG); !SCCI.isAtEnd();
  84. ++SCCI) {
  85. const std::vector<CallGraphNode*> &nextSCC = *SCCI;
  86. errs() << "\nSCC #" << ++sccNum << " : ";
  87. for (std::vector<CallGraphNode*>::const_iterator I = nextSCC.begin(),
  88. E = nextSCC.end(); I != E; ++I)
  89. errs() << ((*I)->getFunction() ? (*I)->getFunction()->getName()
  90. : "external node") << ", ";
  91. if (nextSCC.size() == 1 && SCCI.hasLoop())
  92. errs() << " (Has self-loop).";
  93. }
  94. errs() << "\n";
  95. return true;
  96. }