PrintSCC.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. //===- PrintSCC.cpp - Enumerate SCCs in some key graphs -------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file provides passes to print out SCCs in a CFG or a CallGraph.
  10. // Normally, you would not use these passes; instead, you would use the
  11. // scc_iterator directly to enumerate SCCs and process them in some way. These
  12. // passes serve three purposes:
  13. //
  14. // (1) As a reference for how to use the scc_iterator.
  15. // (2) To print out the SCCs for a CFG or a CallGraph:
  16. // analyze -print-cfg-sccs to print the SCCs in each CFG of a module.
  17. // analyze -print-cfg-sccs -stats to print the #SCCs and the maximum SCC size.
  18. // analyze -print-cfg-sccs -debug > /dev/null to watch the algorithm in action.
  19. //
  20. // and similarly:
  21. // analyze -print-callgraph-sccs [-stats] [-debug] to print SCCs in the CallGraph
  22. //
  23. // (3) To test the scc_iterator.
  24. //
  25. //===----------------------------------------------------------------------===//
  26. #include "llvm/ADT/SCCIterator.h"
  27. #include "llvm/Analysis/CallGraph.h"
  28. #include "llvm/IR/CFG.h"
  29. #include "llvm/IR/Module.h"
  30. #include "llvm/Pass.h"
  31. #include "llvm/Support/raw_ostream.h"
  32. using namespace llvm;
  33. namespace {
  34. struct CFGSCC : public FunctionPass {
  35. static char ID; // Pass identification, replacement for typeid
  36. CFGSCC() : FunctionPass(ID) {}
  37. bool runOnFunction(Function& func) override;
  38. void print(raw_ostream &O, const Module* = nullptr) const override { }
  39. void getAnalysisUsage(AnalysisUsage &AU) const override {
  40. AU.setPreservesAll();
  41. }
  42. };
  43. struct CallGraphSCC : public ModulePass {
  44. static char ID; // Pass identification, replacement for typeid
  45. CallGraphSCC() : ModulePass(ID) {}
  46. // run - Print out SCCs in the call graph for the specified module.
  47. bool runOnModule(Module &M) override;
  48. void print(raw_ostream &O, const Module* = nullptr) const override { }
  49. // getAnalysisUsage - This pass requires the CallGraph.
  50. void getAnalysisUsage(AnalysisUsage &AU) const override {
  51. AU.setPreservesAll();
  52. AU.addRequired<CallGraphWrapperPass>();
  53. }
  54. };
  55. }
  56. char CFGSCC::ID = 0;
  57. static RegisterPass<CFGSCC>
  58. Y("print-cfg-sccs", "Print SCCs of each function CFG");
  59. char CallGraphSCC::ID = 0;
  60. static RegisterPass<CallGraphSCC>
  61. Z("print-callgraph-sccs", "Print SCCs of the Call Graph");
  62. bool CFGSCC::runOnFunction(Function &F) {
  63. unsigned sccNum = 0;
  64. errs() << "SCCs for Function " << F.getName() << " in PostOrder:";
  65. for (scc_iterator<Function*> SCCI = scc_begin(&F); !SCCI.isAtEnd(); ++SCCI) {
  66. const std::vector<BasicBlock *> &nextSCC = *SCCI;
  67. errs() << "\nSCC #" << ++sccNum << " : ";
  68. for (BasicBlock *BB : nextSCC) {
  69. BB->printAsOperand(errs(), false);
  70. errs() << ", ";
  71. }
  72. if (nextSCC.size() == 1 && SCCI.hasCycle())
  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.hasCycle())
  92. errs() << " (Has self-loop).";
  93. }
  94. errs() << "\n";
  95. return true;
  96. }