175 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 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>20 21using namespace llvm;22 23//===----------------------------------------------------------------------===//24// Define dummy passes for legacy pass manager run.25 26namespace llvm {27 28void initializePass1Pass(PassRegistry &);29void initializePass2Pass(PassRegistry &);30 31namespace {32struct Pass1 : public ModulePass {33 static char ID;34 35public:36 Pass1() : ModulePass(ID) {}37 bool runOnModule(Module &M) override { return false; }38 void getAnalysisUsage(AnalysisUsage &AU) const override {39 AU.setPreservesAll();40 }41 StringRef getPassName() const override { return "Pass1"; }42};43char Pass1::ID;44 45struct Pass2 : public ModulePass {46 static char ID;47 48public:49 Pass2() : ModulePass(ID) {}50 bool runOnModule(Module &M) override { return false; }51 void getAnalysisUsage(AnalysisUsage &AU) const override {52 AU.setPreservesAll();53 }54 StringRef getPassName() const override { return "Pass2"; }55};56char Pass2::ID;57} // namespace58} // namespace llvm59 60INITIALIZE_PASS(Pass1, "Pass1", "Pass1", false, false)61INITIALIZE_PASS(Pass2, "Pass2", "Pass2", false, false)62 63namespace {64 65TEST(TimePassesTest, LegacyCustomOut) {66 PassInstrumentationCallbacks PIC;67 PassInstrumentation PI(&PIC);68 69 LLVMContext Context;70 Module M("TestModule", Context);71 72 SmallString<0> TimePassesStr;73 raw_svector_ostream ReportStream(TimePassesStr);74 75 // Setup pass manager76 legacy::PassManager PM1;77 PM1.add(new llvm::Pass1());78 PM1.add(new llvm::Pass2());79 80 // Enable time-passes and run passes.81 TimePassesIsEnabled = true;82 PM1.run(M);83 84 // Generating report.85 reportAndResetTimings(&ReportStream);86 87 // There should be Pass1 and Pass2 in the report88 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"));92 93 // Clear and generate report again.94 TimePassesStr.clear();95 reportAndResetTimings(&ReportStream);96 97 // Since we did not run any passes since last print, report should be empty.98 EXPECT_TRUE(TimePassesStr.empty());99 100 // Now run just a single pass to populate timers again.101 legacy::PassManager PM2;102 PM2.add(new llvm::Pass2());103 PM2.run(M);104 105 // Generate report again.106 reportAndResetTimings(&ReportStream);107 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"));113 114 // Reset flag to not affect other tests.115 TimePassesIsEnabled = false;116}117 118class MyPass1 : public PassInfoMixin<MyPass1> {};119class MyPass2 : public PassInfoMixin<MyPass2> {};120 121TEST(TimePassesTest, CustomOut) {122 PassInstrumentationCallbacks PIC;123 PassInstrumentation PI(&PIC);124 125 LLVMContext Context;126 Module M("TestModule", Context);127 MyPass1 Pass1;128 MyPass2 Pass2;129 130 SmallString<0> TimePassesStr;131 raw_svector_ostream ReportStream(TimePassesStr);132 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);138 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());144 145 // Generating report.146 TimePasses->print();147 148 // There should be Pass1 and Pass2 in the report149 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"));153 154 // Clear and generate report again.155 TimePassesStr.clear();156 TimePasses->print();157 // Since we did not run any passes since last print, report should be empty.158 EXPECT_TRUE(TimePassesStr.empty());159 160 // Now trigger just a single pass to populate timers again.161 PI.runBeforePass(Pass2, M);162 PI.runAfterPass(Pass2, M, PreservedAnalyses::all());163 164 // Clear and generate report again.165 TimePasses->print();166 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"));172}173 174} // end anonymous namespace175