TimePassesTest.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. //===- unittests/IR/TimePassesTest.cpp - TimePassesHandler tests ----------===//
  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. #include <gtest/gtest.h>
  9. #include <llvm/ADT/SmallString.h>
  10. #include "llvm/IR/LegacyPassManager.h"
  11. #include <llvm/IR/LLVMContext.h>
  12. #include <llvm/IR/Module.h>
  13. #include <llvm/IR/PassInstrumentation.h>
  14. #include <llvm/IR/PassManager.h>
  15. #include <llvm/IR/PassTimingInfo.h>
  16. #include <llvm/Support/raw_ostream.h>
  17. using namespace llvm;
  18. //===----------------------------------------------------------------------===//
  19. // Define dummy passes for legacy pass manager run.
  20. namespace llvm {
  21. void initializePass1Pass(PassRegistry &);
  22. void initializePass2Pass(PassRegistry &);
  23. namespace {
  24. struct Pass1 : public ModulePass {
  25. static char ID;
  26. public:
  27. Pass1() : ModulePass(ID) {}
  28. bool runOnModule(Module &M) override { return false; }
  29. void getAnalysisUsage(AnalysisUsage &AU) const override {
  30. AU.setPreservesAll();
  31. }
  32. StringRef getPassName() const override { return "Pass1"; }
  33. };
  34. char Pass1::ID;
  35. struct Pass2 : public ModulePass {
  36. static char ID;
  37. public:
  38. Pass2() : ModulePass(ID) {}
  39. bool runOnModule(Module &M) override { return false; }
  40. void getAnalysisUsage(AnalysisUsage &AU) const override {
  41. AU.setPreservesAll();
  42. }
  43. StringRef getPassName() const override { return "Pass2"; }
  44. };
  45. char Pass2::ID;
  46. } // namespace
  47. } // namespace llvm
  48. INITIALIZE_PASS(Pass1, "Pass1", "Pass1", false, false)
  49. INITIALIZE_PASS(Pass2, "Pass2", "Pass2", false, false)
  50. namespace {
  51. TEST(TimePassesTest, LegacyCustomOut) {
  52. PassInstrumentationCallbacks PIC;
  53. PassInstrumentation PI(&PIC);
  54. LLVMContext Context;
  55. Module M("TestModule", Context);
  56. SmallString<0> TimePassesStr;
  57. raw_svector_ostream ReportStream(TimePassesStr);
  58. // Setup pass manager
  59. legacy::PassManager PM1;
  60. PM1.add(new llvm::Pass1());
  61. PM1.add(new llvm::Pass2());
  62. // Enable time-passes and run passes.
  63. TimePassesIsEnabled = true;
  64. PM1.run(M);
  65. // Generating report.
  66. reportAndResetTimings(&ReportStream);
  67. // There should be Pass1 and Pass2 in the report
  68. EXPECT_FALSE(TimePassesStr.empty());
  69. EXPECT_TRUE(TimePassesStr.str().contains("report"));
  70. EXPECT_TRUE(TimePassesStr.str().contains("Pass1"));
  71. EXPECT_TRUE(TimePassesStr.str().contains("Pass2"));
  72. // Clear and generate report again.
  73. TimePassesStr.clear();
  74. reportAndResetTimings(&ReportStream);
  75. // Since we did not run any passes since last print, report should be empty.
  76. EXPECT_TRUE(TimePassesStr.empty());
  77. // Now run just a single pass to populate timers again.
  78. legacy::PassManager PM2;
  79. PM2.add(new llvm::Pass2());
  80. PM2.run(M);
  81. // Generate report again.
  82. reportAndResetTimings(&ReportStream);
  83. // There should be Pass2 in this report and no Pass1.
  84. EXPECT_FALSE(TimePassesStr.str().empty());
  85. EXPECT_TRUE(TimePassesStr.str().contains("report"));
  86. EXPECT_FALSE(TimePassesStr.str().contains("Pass1"));
  87. EXPECT_TRUE(TimePassesStr.str().contains("Pass2"));
  88. }
  89. class MyPass1 : public PassInfoMixin<MyPass1> {};
  90. class MyPass2 : public PassInfoMixin<MyPass2> {};
  91. TEST(TimePassesTest, CustomOut) {
  92. PassInstrumentationCallbacks PIC;
  93. PassInstrumentation PI(&PIC);
  94. LLVMContext Context;
  95. Module M("TestModule", Context);
  96. MyPass1 Pass1;
  97. MyPass2 Pass2;
  98. SmallString<0> TimePassesStr;
  99. raw_svector_ostream ReportStream(TimePassesStr);
  100. // Setup time-passes handler and redirect output to the stream.
  101. std::unique_ptr<TimePassesHandler> TimePasses =
  102. std::make_unique<TimePassesHandler>(true);
  103. TimePasses->setOutStream(ReportStream);
  104. TimePasses->registerCallbacks(PIC);
  105. // Pretending that passes are running to trigger the timers.
  106. PI.runBeforePass(Pass1, M);
  107. PI.runBeforePass(Pass2, M);
  108. PI.runAfterPass(Pass2, M);
  109. PI.runAfterPass(Pass1, M);
  110. // Generating report.
  111. TimePasses->print();
  112. // There should be Pass1 and Pass2 in the report
  113. EXPECT_FALSE(TimePassesStr.empty());
  114. EXPECT_TRUE(TimePassesStr.str().contains("report"));
  115. EXPECT_TRUE(TimePassesStr.str().contains("Pass1"));
  116. EXPECT_TRUE(TimePassesStr.str().contains("Pass2"));
  117. // Clear and generate report again.
  118. TimePassesStr.clear();
  119. TimePasses->print();
  120. // Since we did not run any passes since last print, report should be empty.
  121. EXPECT_TRUE(TimePassesStr.empty());
  122. // Now trigger just a single pass to populate timers again.
  123. PI.runBeforePass(Pass2, M);
  124. PI.runAfterPass(Pass2, M);
  125. // Generate report by deleting the handler.
  126. TimePasses.reset();
  127. // There should be Pass2 in this report and no Pass1.
  128. EXPECT_FALSE(TimePassesStr.str().empty());
  129. EXPECT_TRUE(TimePassesStr.str().contains("report"));
  130. EXPECT_FALSE(TimePassesStr.str().contains("Pass1"));
  131. EXPECT_TRUE(TimePassesStr.str().contains("Pass2"));
  132. }
  133. } // end anonymous namespace