• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
9 #include <gtest/gtest.h>
10 #include <llvm/ADT/SmallString.h>
11 #include "llvm/IR/LegacyPassManager.h"
12 #include <llvm/IR/LLVMContext.h>
13 #include <llvm/IR/Module.h>
14 #include <llvm/IR/PassInstrumentation.h>
15 #include <llvm/IR/PassManager.h>
16 #include <llvm/IR/PassTimingInfo.h>
17 #include <llvm/Support/raw_ostream.h>
18 
19 using namespace llvm;
20 
21 //===----------------------------------------------------------------------===//
22 // Define dummy passes for legacy pass manager run.
23 
24 namespace llvm {
25 
26 void initializePass1Pass(PassRegistry &);
27 void initializePass2Pass(PassRegistry &);
28 
29 namespace {
30 struct Pass1 : public ModulePass {
31   static char ID;
32 
33 public:
Pass1llvm::__anon45e7ac8b0111::Pass134   Pass1() : ModulePass(ID) {}
runOnModulellvm::__anon45e7ac8b0111::Pass135   bool runOnModule(Module &M) override { return false; }
getAnalysisUsagellvm::__anon45e7ac8b0111::Pass136   void getAnalysisUsage(AnalysisUsage &AU) const override {
37     AU.setPreservesAll();
38   }
getPassNamellvm::__anon45e7ac8b0111::Pass139   StringRef getPassName() const override { return "Pass1"; }
40 };
41 char Pass1::ID;
42 
43 struct Pass2 : public ModulePass {
44   static char ID;
45 
46 public:
Pass2llvm::__anon45e7ac8b0111::Pass247   Pass2() : ModulePass(ID) {}
runOnModulellvm::__anon45e7ac8b0111::Pass248   bool runOnModule(Module &M) override { return false; }
getAnalysisUsagellvm::__anon45e7ac8b0111::Pass249   void getAnalysisUsage(AnalysisUsage &AU) const override {
50     AU.setPreservesAll();
51   }
getPassNamellvm::__anon45e7ac8b0111::Pass252   StringRef getPassName() const override { return "Pass2"; }
53 };
54 char Pass2::ID;
55 } // namespace
56 } // namespace llvm
57 
58 INITIALIZE_PASS(Pass1, "Pass1", "Pass1", false, false)
59 INITIALIZE_PASS(Pass2, "Pass2", "Pass2", false, false)
60 
61 namespace {
62 
TEST(TimePassesTest,LegacyCustomOut)63 TEST(TimePassesTest, LegacyCustomOut) {
64   PassInstrumentationCallbacks PIC;
65   PassInstrumentation PI(&PIC);
66 
67   LLVMContext Context;
68   Module M("TestModule", Context);
69 
70   SmallString<0> TimePassesStr;
71   raw_svector_ostream ReportStream(TimePassesStr);
72 
73   // Setup pass manager
74   legacy::PassManager PM1;
75   PM1.add(new llvm::Pass1());
76   PM1.add(new llvm::Pass2());
77 
78   // Enable time-passes and run passes.
79   TimePassesIsEnabled = true;
80   PM1.run(M);
81 
82   // Generating report.
83   reportAndResetTimings(&ReportStream);
84 
85   // There should be Pass1 and Pass2 in the report
86   EXPECT_FALSE(TimePassesStr.empty());
87   EXPECT_TRUE(TimePassesStr.str().contains("report"));
88   EXPECT_TRUE(TimePassesStr.str().contains("Pass1"));
89   EXPECT_TRUE(TimePassesStr.str().contains("Pass2"));
90 
91   // Clear and generate report again.
92   TimePassesStr.clear();
93   reportAndResetTimings(&ReportStream);
94 
95   // Since we did not run any passes since last print, report should be empty.
96   EXPECT_TRUE(TimePassesStr.empty());
97 
98   // Now run just a single pass to populate timers again.
99   legacy::PassManager PM2;
100   PM2.add(new llvm::Pass2());
101   PM2.run(M);
102 
103   // Generate report again.
104   reportAndResetTimings(&ReportStream);
105 
106   // There should be Pass2 in this report and no Pass1.
107   EXPECT_FALSE(TimePassesStr.str().empty());
108   EXPECT_TRUE(TimePassesStr.str().contains("report"));
109   EXPECT_FALSE(TimePassesStr.str().contains("Pass1"));
110   EXPECT_TRUE(TimePassesStr.str().contains("Pass2"));
111 }
112 
113 class MyPass1 : public PassInfoMixin<MyPass1> {};
114 class MyPass2 : public PassInfoMixin<MyPass2> {};
115 
TEST(TimePassesTest,CustomOut)116 TEST(TimePassesTest, CustomOut) {
117   PassInstrumentationCallbacks PIC;
118   PassInstrumentation PI(&PIC);
119 
120   LLVMContext Context;
121   Module M("TestModule", Context);
122   MyPass1 Pass1;
123   MyPass2 Pass2;
124 
125   SmallString<0> TimePassesStr;
126   raw_svector_ostream ReportStream(TimePassesStr);
127 
128   // Setup time-passes handler and redirect output to the stream.
129   std::unique_ptr<TimePassesHandler> TimePasses =
130       std::make_unique<TimePassesHandler>(true);
131   TimePasses->setOutStream(ReportStream);
132   TimePasses->registerCallbacks(PIC);
133 
134   // Pretending that passes are running to trigger the timers.
135   PI.runBeforePass(Pass1, M);
136   PI.runBeforePass(Pass2, M);
137   PI.runAfterPass(Pass2, M, PreservedAnalyses::all());
138   PI.runAfterPass(Pass1, M, PreservedAnalyses::all());
139 
140   // Generating report.
141   TimePasses->print();
142 
143   // There should be Pass1 and Pass2 in the report
144   EXPECT_FALSE(TimePassesStr.empty());
145   EXPECT_TRUE(TimePassesStr.str().contains("report"));
146   EXPECT_TRUE(TimePassesStr.str().contains("Pass1"));
147   EXPECT_TRUE(TimePassesStr.str().contains("Pass2"));
148 
149   // Clear and generate report again.
150   TimePassesStr.clear();
151   TimePasses->print();
152   // Since we did not run any passes since last print, report should be empty.
153   EXPECT_TRUE(TimePassesStr.empty());
154 
155   // Now trigger just a single pass to populate timers again.
156   PI.runBeforePass(Pass2, M);
157   PI.runAfterPass(Pass2, M, PreservedAnalyses::all());
158 
159   // Generate report by deleting the handler.
160   TimePasses.reset();
161 
162   // There should be Pass2 in this report and no Pass1.
163   EXPECT_FALSE(TimePassesStr.str().empty());
164   EXPECT_TRUE(TimePassesStr.str().contains("report"));
165   EXPECT_FALSE(TimePassesStr.str().contains("Pass1"));
166   EXPECT_TRUE(TimePassesStr.str().contains("Pass2"));
167 }
168 
169 } // end anonymous namespace
170