blob: a76652202b815f529a9d1dc36e36bf646574cb45 [file] [log] [blame]
Fedor Sergeev6a9c2f42019-03-15 22:15:23 +00001//===- 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>
Fedor Sergeevec743782019-03-22 23:11:08 +000011#include "llvm/IR/LegacyPassManager.h"
Fedor Sergeev6a9c2f42019-03-15 22:15:23 +000012#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
19using namespace llvm;
20
Fedor Sergeevec743782019-03-22 23:11:08 +000021//===----------------------------------------------------------------------===//
22// Define dummy passes for legacy pass manager run.
23
24namespace llvm {
25
26void initializePass1Pass(PassRegistry &);
27void initializePass2Pass(PassRegistry &);
28
Fedor Sergeev6a9c2f42019-03-15 22:15:23 +000029namespace {
Fedor Sergeevec743782019-03-22 23:11:08 +000030struct Pass1 : public ModulePass {
31 static char ID;
32
33public:
34 Pass1() : ModulePass(ID) {}
35 bool runOnModule(Module &M) override { return false; }
36 void getAnalysisUsage(AnalysisUsage &AU) const override {
37 AU.setPreservesAll();
38 }
39 StringRef getPassName() const override { return "Pass1"; }
40};
41char Pass1::ID;
42
43struct Pass2 : public ModulePass {
44 static char ID;
45
46public:
47 Pass2() : ModulePass(ID) {}
48 bool runOnModule(Module &M) override { return false; }
49 void getAnalysisUsage(AnalysisUsage &AU) const override {
50 AU.setPreservesAll();
51 }
52 StringRef getPassName() const override { return "Pass2"; }
53};
54char Pass2::ID;
55} // namespace
56} // namespace llvm
57
58INITIALIZE_PASS(Pass1, "Pass1", "Pass1", false, false)
59INITIALIZE_PASS(Pass2, "Pass2", "Pass2", false, false)
60
61namespace {
62
63TEST(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}
Fedor Sergeev6a9c2f42019-03-15 22:15:23 +0000112
113class MyPass1 : public PassInfoMixin<MyPass1> {};
114class MyPass2 : public PassInfoMixin<MyPass2> {};
115
116TEST(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 llvm::make_unique<TimePassesHandler>(true);
131 TimePasses->setOutStream(ReportStream);
132 TimePasses->registerCallbacks(PIC);
133
Fedor Sergeevec743782019-03-22 23:11:08 +0000134 // Pretending that passes are running to trigger the timers.
Fedor Sergeev6a9c2f42019-03-15 22:15:23 +0000135 PI.runBeforePass(Pass1, M);
136 PI.runBeforePass(Pass2, M);
137 PI.runAfterPass(Pass2, M);
138 PI.runAfterPass(Pass1, M);
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
Fedor Sergeevec743782019-03-22 23:11:08 +0000155 // Now trigger just a single pass to populate timers again.
Fedor Sergeev6a9c2f42019-03-15 22:15:23 +0000156 PI.runBeforePass(Pass2, M);
157 PI.runAfterPass(Pass2, M);
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