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