1 //===- unittests/IR/TimePassesTest.cpp - TimePassesHandler tests ----------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/IR/LegacyPassManager.h"
10 #include "llvm/Pass.h"
11 #include "llvm/PassRegistry.h"
12 #include <gtest/gtest.h>
13 #include <llvm/ADT/SmallString.h>
14 #include <llvm/IR/LLVMContext.h>
15 #include <llvm/IR/Module.h>
16 #include <llvm/IR/PassInstrumentation.h>
17 #include <llvm/IR/PassManager.h>
18 #include <llvm/IR/PassTimingInfo.h>
19 #include <llvm/Support/raw_ostream.h>
23 //===----------------------------------------------------------------------===//
24 // Define dummy passes for legacy pass manager run.
28 void initializePass1Pass(PassRegistry
&);
29 void initializePass2Pass(PassRegistry
&);
32 struct Pass1
: public ModulePass
{
36 Pass1() : ModulePass(ID
) {}
37 bool runOnModule(Module
&M
) override
{ return false; }
38 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
41 StringRef
getPassName() const override
{ return "Pass1"; }
45 struct Pass2
: public ModulePass
{
49 Pass2() : ModulePass(ID
) {}
50 bool runOnModule(Module
&M
) override
{ return false; }
51 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
54 StringRef
getPassName() const override
{ return "Pass2"; }
60 INITIALIZE_PASS(Pass1
, "Pass1", "Pass1", false, false)
61 INITIALIZE_PASS(Pass2
, "Pass2", "Pass2", false, false)
65 TEST(TimePassesTest
, LegacyCustomOut
) {
66 PassInstrumentationCallbacks PIC
;
67 PassInstrumentation
PI(&PIC
);
70 Module
M("TestModule", Context
);
72 SmallString
<0> TimePassesStr
;
73 raw_svector_ostream
ReportStream(TimePassesStr
);
76 legacy::PassManager PM1
;
77 PM1
.add(new llvm::Pass1());
78 PM1
.add(new llvm::Pass2());
80 // Enable time-passes and run passes.
81 TimePassesIsEnabled
= true;
85 reportAndResetTimings(&ReportStream
);
87 // There should be Pass1 and Pass2 in the report
88 EXPECT_FALSE(TimePassesStr
.empty());
89 EXPECT_TRUE(TimePassesStr
.str().contains("report"));
90 EXPECT_TRUE(TimePassesStr
.str().contains("Pass1"));
91 EXPECT_TRUE(TimePassesStr
.str().contains("Pass2"));
93 // Clear and generate report again.
94 TimePassesStr
.clear();
95 reportAndResetTimings(&ReportStream
);
97 // Since we did not run any passes since last print, report should be empty.
98 EXPECT_TRUE(TimePassesStr
.empty());
100 // Now run just a single pass to populate timers again.
101 legacy::PassManager PM2
;
102 PM2
.add(new llvm::Pass2());
105 // Generate report again.
106 reportAndResetTimings(&ReportStream
);
108 // There should be Pass2 in this report and no Pass1.
109 EXPECT_FALSE(TimePassesStr
.str().empty());
110 EXPECT_TRUE(TimePassesStr
.str().contains("report"));
111 EXPECT_FALSE(TimePassesStr
.str().contains("Pass1"));
112 EXPECT_TRUE(TimePassesStr
.str().contains("Pass2"));
114 // Reset flag to not affect other tests.
115 TimePassesIsEnabled
= false;
118 class MyPass1
: public PassInfoMixin
<MyPass1
> {};
119 class MyPass2
: public PassInfoMixin
<MyPass2
> {};
121 TEST(TimePassesTest
, CustomOut
) {
122 PassInstrumentationCallbacks PIC
;
123 PassInstrumentation
PI(&PIC
);
126 Module
M("TestModule", Context
);
130 SmallString
<0> TimePassesStr
;
131 raw_svector_ostream
ReportStream(TimePassesStr
);
133 // Setup time-passes handler and redirect output to the stream.
134 std::unique_ptr
<TimePassesHandler
> TimePasses
=
135 std::make_unique
<TimePassesHandler
>(true);
136 TimePasses
->setOutStream(ReportStream
);
137 TimePasses
->registerCallbacks(PIC
);
139 // Pretending that passes are running to trigger the timers.
140 PI
.runBeforePass(Pass1
, M
);
141 PI
.runAfterPass(Pass1
, M
, PreservedAnalyses::all());
142 PI
.runBeforePass(Pass2
, M
);
143 PI
.runAfterPass(Pass2
, M
, PreservedAnalyses::all());
145 // Generating report.
148 // There should be Pass1 and Pass2 in the report
149 EXPECT_FALSE(TimePassesStr
.empty());
150 EXPECT_TRUE(TimePassesStr
.str().contains("report"));
151 EXPECT_TRUE(TimePassesStr
.str().contains("Pass1"));
152 EXPECT_TRUE(TimePassesStr
.str().contains("Pass2"));
154 // Clear and generate report again.
155 TimePassesStr
.clear();
157 // Since we did not run any passes since last print, report should be empty.
158 EXPECT_TRUE(TimePassesStr
.empty());
160 // Now trigger just a single pass to populate timers again.
161 PI
.runBeforePass(Pass2
, M
);
162 PI
.runAfterPass(Pass2
, M
, PreservedAnalyses::all());
164 // Generate report by deleting the handler.
167 // There should be Pass2 in this report and no Pass1.
168 EXPECT_FALSE(TimePassesStr
.str().empty());
169 EXPECT_TRUE(TimePassesStr
.str().contains("report"));
170 EXPECT_FALSE(TimePassesStr
.str().contains("Pass1"));
171 EXPECT_TRUE(TimePassesStr
.str().contains("Pass2"));
174 } // end anonymous namespace