xref: /llvm-project/llvm/unittests/IR/TimePassesTest.cpp (revision aa5bc41b765694696ff05c3448247f7525577657)
16a9c2f4fSFedor Sergeev //===- unittests/IR/TimePassesTest.cpp - TimePassesHandler tests ----------===//
26a9c2f4fSFedor Sergeev //
36a9c2f4fSFedor Sergeev // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
46a9c2f4fSFedor Sergeev // See https://llvm.org/LICENSE.txt for license information.
56a9c2f4fSFedor Sergeev // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66a9c2f4fSFedor Sergeev //
76a9c2f4fSFedor Sergeev //===----------------------------------------------------------------------===//
86a9c2f4fSFedor Sergeev 
9e188aae4Sserge-sans-paille #include "llvm/IR/LegacyPassManager.h"
10e188aae4Sserge-sans-paille #include "llvm/Pass.h"
11e188aae4Sserge-sans-paille #include "llvm/PassRegistry.h"
126a9c2f4fSFedor Sergeev #include <gtest/gtest.h>
136a9c2f4fSFedor Sergeev #include <llvm/ADT/SmallString.h>
146a9c2f4fSFedor Sergeev #include <llvm/IR/LLVMContext.h>
156a9c2f4fSFedor Sergeev #include <llvm/IR/Module.h>
166a9c2f4fSFedor Sergeev #include <llvm/IR/PassInstrumentation.h>
176a9c2f4fSFedor Sergeev #include <llvm/IR/PassManager.h>
186a9c2f4fSFedor Sergeev #include <llvm/IR/PassTimingInfo.h>
196a9c2f4fSFedor Sergeev #include <llvm/Support/raw_ostream.h>
206a9c2f4fSFedor Sergeev 
216a9c2f4fSFedor Sergeev using namespace llvm;
226a9c2f4fSFedor Sergeev 
23ec74378eSFedor Sergeev //===----------------------------------------------------------------------===//
24ec74378eSFedor Sergeev // Define dummy passes for legacy pass manager run.
25ec74378eSFedor Sergeev 
26ec74378eSFedor Sergeev namespace llvm {
27ec74378eSFedor Sergeev 
28ec74378eSFedor Sergeev void initializePass1Pass(PassRegistry &);
29ec74378eSFedor Sergeev void initializePass2Pass(PassRegistry &);
30ec74378eSFedor Sergeev 
316a9c2f4fSFedor Sergeev namespace {
32ec74378eSFedor Sergeev struct Pass1 : public ModulePass {
33ec74378eSFedor Sergeev   static char ID;
34ec74378eSFedor Sergeev 
35ec74378eSFedor Sergeev public:
Pass1llvm::__anon13a3aac70111::Pass136ec74378eSFedor Sergeev   Pass1() : ModulePass(ID) {}
runOnModulellvm::__anon13a3aac70111::Pass137ec74378eSFedor Sergeev   bool runOnModule(Module &M) override { return false; }
getAnalysisUsagellvm::__anon13a3aac70111::Pass138ec74378eSFedor Sergeev   void getAnalysisUsage(AnalysisUsage &AU) const override {
39ec74378eSFedor Sergeev     AU.setPreservesAll();
40ec74378eSFedor Sergeev   }
getPassNamellvm::__anon13a3aac70111::Pass141ec74378eSFedor Sergeev   StringRef getPassName() const override { return "Pass1"; }
42ec74378eSFedor Sergeev };
43ec74378eSFedor Sergeev char Pass1::ID;
44ec74378eSFedor Sergeev 
45ec74378eSFedor Sergeev struct Pass2 : public ModulePass {
46ec74378eSFedor Sergeev   static char ID;
47ec74378eSFedor Sergeev 
48ec74378eSFedor Sergeev public:
Pass2llvm::__anon13a3aac70111::Pass249ec74378eSFedor Sergeev   Pass2() : ModulePass(ID) {}
runOnModulellvm::__anon13a3aac70111::Pass250ec74378eSFedor Sergeev   bool runOnModule(Module &M) override { return false; }
getAnalysisUsagellvm::__anon13a3aac70111::Pass251ec74378eSFedor Sergeev   void getAnalysisUsage(AnalysisUsage &AU) const override {
52ec74378eSFedor Sergeev     AU.setPreservesAll();
53ec74378eSFedor Sergeev   }
getPassNamellvm::__anon13a3aac70111::Pass254ec74378eSFedor Sergeev   StringRef getPassName() const override { return "Pass2"; }
55ec74378eSFedor Sergeev };
56ec74378eSFedor Sergeev char Pass2::ID;
57ec74378eSFedor Sergeev } // namespace
58ec74378eSFedor Sergeev } // namespace llvm
59ec74378eSFedor Sergeev 
60ec74378eSFedor Sergeev INITIALIZE_PASS(Pass1, "Pass1", "Pass1", false, false)
61ec74378eSFedor Sergeev INITIALIZE_PASS(Pass2, "Pass2", "Pass2", false, false)
62ec74378eSFedor Sergeev 
63ec74378eSFedor Sergeev namespace {
64ec74378eSFedor Sergeev 
TEST(TimePassesTest,LegacyCustomOut)65ec74378eSFedor Sergeev TEST(TimePassesTest, LegacyCustomOut) {
66ec74378eSFedor Sergeev   PassInstrumentationCallbacks PIC;
67ec74378eSFedor Sergeev   PassInstrumentation PI(&PIC);
68ec74378eSFedor Sergeev 
69ec74378eSFedor Sergeev   LLVMContext Context;
70ec74378eSFedor Sergeev   Module M("TestModule", Context);
71ec74378eSFedor Sergeev 
72ec74378eSFedor Sergeev   SmallString<0> TimePassesStr;
73ec74378eSFedor Sergeev   raw_svector_ostream ReportStream(TimePassesStr);
74ec74378eSFedor Sergeev 
75ec74378eSFedor Sergeev   // Setup pass manager
76ec74378eSFedor Sergeev   legacy::PassManager PM1;
77ec74378eSFedor Sergeev   PM1.add(new llvm::Pass1());
78ec74378eSFedor Sergeev   PM1.add(new llvm::Pass2());
79ec74378eSFedor Sergeev 
80ec74378eSFedor Sergeev   // Enable time-passes and run passes.
81ec74378eSFedor Sergeev   TimePassesIsEnabled = true;
82ec74378eSFedor Sergeev   PM1.run(M);
83ec74378eSFedor Sergeev 
84ec74378eSFedor Sergeev   // Generating report.
85ec74378eSFedor Sergeev   reportAndResetTimings(&ReportStream);
86ec74378eSFedor Sergeev 
87ec74378eSFedor Sergeev   // There should be Pass1 and Pass2 in the report
88ec74378eSFedor Sergeev   EXPECT_FALSE(TimePassesStr.empty());
89ec74378eSFedor Sergeev   EXPECT_TRUE(TimePassesStr.str().contains("report"));
90ec74378eSFedor Sergeev   EXPECT_TRUE(TimePassesStr.str().contains("Pass1"));
91ec74378eSFedor Sergeev   EXPECT_TRUE(TimePassesStr.str().contains("Pass2"));
92ec74378eSFedor Sergeev 
93ec74378eSFedor Sergeev   // Clear and generate report again.
94ec74378eSFedor Sergeev   TimePassesStr.clear();
95ec74378eSFedor Sergeev   reportAndResetTimings(&ReportStream);
96ec74378eSFedor Sergeev 
97ec74378eSFedor Sergeev   // Since we did not run any passes since last print, report should be empty.
98ec74378eSFedor Sergeev   EXPECT_TRUE(TimePassesStr.empty());
99ec74378eSFedor Sergeev 
100ec74378eSFedor Sergeev   // Now run just a single pass to populate timers again.
101ec74378eSFedor Sergeev   legacy::PassManager PM2;
102ec74378eSFedor Sergeev   PM2.add(new llvm::Pass2());
103ec74378eSFedor Sergeev   PM2.run(M);
104ec74378eSFedor Sergeev 
105ec74378eSFedor Sergeev   // Generate report again.
106ec74378eSFedor Sergeev   reportAndResetTimings(&ReportStream);
107ec74378eSFedor Sergeev 
108ec74378eSFedor Sergeev   // There should be Pass2 in this report and no Pass1.
109ec74378eSFedor Sergeev   EXPECT_FALSE(TimePassesStr.str().empty());
110ec74378eSFedor Sergeev   EXPECT_TRUE(TimePassesStr.str().contains("report"));
111ec74378eSFedor Sergeev   EXPECT_FALSE(TimePassesStr.str().contains("Pass1"));
112ec74378eSFedor Sergeev   EXPECT_TRUE(TimePassesStr.str().contains("Pass2"));
113*aa5bc41bSArthur Eubanks 
114*aa5bc41bSArthur Eubanks   // Reset flag to not affect other tests.
115*aa5bc41bSArthur Eubanks   TimePassesIsEnabled = false;
116ec74378eSFedor Sergeev }
1176a9c2f4fSFedor Sergeev 
1186a9c2f4fSFedor Sergeev class MyPass1 : public PassInfoMixin<MyPass1> {};
1196a9c2f4fSFedor Sergeev class MyPass2 : public PassInfoMixin<MyPass2> {};
1206a9c2f4fSFedor Sergeev 
TEST(TimePassesTest,CustomOut)1216a9c2f4fSFedor Sergeev TEST(TimePassesTest, CustomOut) {
1226a9c2f4fSFedor Sergeev   PassInstrumentationCallbacks PIC;
1236a9c2f4fSFedor Sergeev   PassInstrumentation PI(&PIC);
1246a9c2f4fSFedor Sergeev 
1256a9c2f4fSFedor Sergeev   LLVMContext Context;
1266a9c2f4fSFedor Sergeev   Module M("TestModule", Context);
1276a9c2f4fSFedor Sergeev   MyPass1 Pass1;
1286a9c2f4fSFedor Sergeev   MyPass2 Pass2;
1296a9c2f4fSFedor Sergeev 
1306a9c2f4fSFedor Sergeev   SmallString<0> TimePassesStr;
1316a9c2f4fSFedor Sergeev   raw_svector_ostream ReportStream(TimePassesStr);
1326a9c2f4fSFedor Sergeev 
1336a9c2f4fSFedor Sergeev   // Setup time-passes handler and redirect output to the stream.
1346a9c2f4fSFedor Sergeev   std::unique_ptr<TimePassesHandler> TimePasses =
1350eaee545SJonas Devlieghere       std::make_unique<TimePassesHandler>(true);
1366a9c2f4fSFedor Sergeev   TimePasses->setOutStream(ReportStream);
1376a9c2f4fSFedor Sergeev   TimePasses->registerCallbacks(PIC);
1386a9c2f4fSFedor Sergeev 
139ec74378eSFedor Sergeev   // Pretending that passes are running to trigger the timers.
1406a9c2f4fSFedor Sergeev   PI.runBeforePass(Pass1, M);
1410cd27cdcSArthur Eubanks   PI.runAfterPass(Pass1, M, PreservedAnalyses::all());
1426a9c2f4fSFedor Sergeev   PI.runBeforePass(Pass2, M);
14318bc400fSYevgeny Rouban   PI.runAfterPass(Pass2, M, PreservedAnalyses::all());
1446a9c2f4fSFedor Sergeev 
1456a9c2f4fSFedor Sergeev   // Generating report.
1466a9c2f4fSFedor Sergeev   TimePasses->print();
1476a9c2f4fSFedor Sergeev 
1486a9c2f4fSFedor Sergeev   // There should be Pass1 and Pass2 in the report
1496a9c2f4fSFedor Sergeev   EXPECT_FALSE(TimePassesStr.empty());
1506a9c2f4fSFedor Sergeev   EXPECT_TRUE(TimePassesStr.str().contains("report"));
1516a9c2f4fSFedor Sergeev   EXPECT_TRUE(TimePassesStr.str().contains("Pass1"));
1526a9c2f4fSFedor Sergeev   EXPECT_TRUE(TimePassesStr.str().contains("Pass2"));
1536a9c2f4fSFedor Sergeev 
1546a9c2f4fSFedor Sergeev   // Clear and generate report again.
1556a9c2f4fSFedor Sergeev   TimePassesStr.clear();
1566a9c2f4fSFedor Sergeev   TimePasses->print();
1576a9c2f4fSFedor Sergeev   // Since we did not run any passes since last print, report should be empty.
1586a9c2f4fSFedor Sergeev   EXPECT_TRUE(TimePassesStr.empty());
1596a9c2f4fSFedor Sergeev 
160ec74378eSFedor Sergeev   // Now trigger just a single pass to populate timers again.
1616a9c2f4fSFedor Sergeev   PI.runBeforePass(Pass2, M);
16218bc400fSYevgeny Rouban   PI.runAfterPass(Pass2, M, PreservedAnalyses::all());
1636a9c2f4fSFedor Sergeev 
1646a9c2f4fSFedor Sergeev   // Generate report by deleting the handler.
1656a9c2f4fSFedor Sergeev   TimePasses.reset();
1666a9c2f4fSFedor Sergeev 
1676a9c2f4fSFedor Sergeev   // There should be Pass2 in this report and no Pass1.
1686a9c2f4fSFedor Sergeev   EXPECT_FALSE(TimePassesStr.str().empty());
1696a9c2f4fSFedor Sergeev   EXPECT_TRUE(TimePassesStr.str().contains("report"));
1706a9c2f4fSFedor Sergeev   EXPECT_FALSE(TimePassesStr.str().contains("Pass1"));
1716a9c2f4fSFedor Sergeev   EXPECT_TRUE(TimePassesStr.str().contains("Pass2"));
1726a9c2f4fSFedor Sergeev }
1736a9c2f4fSFedor Sergeev 
1746a9c2f4fSFedor Sergeev } // end anonymous namespace
175