xref: /llvm-project/llvm/unittests/Analysis/LastRunTrackingAnalysisTest.cpp (revision 84745da74c8aa2749510c26cf0e3a35bececfa30)
1cacbe71aSYingwei Zheng //===--- LastRunTrackingAnalysisTest.cpp - LastRunTrackingAnalysis tests---===//
2cacbe71aSYingwei Zheng //
3cacbe71aSYingwei Zheng // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4cacbe71aSYingwei Zheng // See https://llvm.org/LICENSE.txt for license information.
5cacbe71aSYingwei Zheng // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6cacbe71aSYingwei Zheng //
7cacbe71aSYingwei Zheng //===----------------------------------------------------------------------===//
8cacbe71aSYingwei Zheng 
9cacbe71aSYingwei Zheng #include "llvm/Analysis/LastRunTrackingAnalysis.h"
10cacbe71aSYingwei Zheng #include "llvm/IR/LLVMContext.h"
11cacbe71aSYingwei Zheng #include "llvm/IR/Module.h"
12cacbe71aSYingwei Zheng #include "llvm/Passes/PassBuilder.h"
13cacbe71aSYingwei Zheng #include "gtest/gtest.h"
14cacbe71aSYingwei Zheng 
15cacbe71aSYingwei Zheng namespace {
16cacbe71aSYingwei Zheng 
17cacbe71aSYingwei Zheng using namespace llvm;
18cacbe71aSYingwei Zheng 
19cacbe71aSYingwei Zheng class LastRunTrackingAnalysisTest : public testing::Test {
20cacbe71aSYingwei Zheng protected:
21cacbe71aSYingwei Zheng   LLVMContext C;
22cacbe71aSYingwei Zheng   Module M;
23cacbe71aSYingwei Zheng   PassBuilder PB;
24cacbe71aSYingwei Zheng 
25cacbe71aSYingwei Zheng   LoopAnalysisManager LAM;
26cacbe71aSYingwei Zheng   FunctionAnalysisManager FAM;
27cacbe71aSYingwei Zheng   CGSCCAnalysisManager CGAM;
28cacbe71aSYingwei Zheng   ModulePassManager MPM;
29cacbe71aSYingwei Zheng   ModuleAnalysisManager MAM;
30cacbe71aSYingwei Zheng 
31cacbe71aSYingwei Zheng   LastRunTrackingAnalysisTest() : M("LastRunTrackingAnalysisTest", C) {
32cacbe71aSYingwei Zheng     PB.registerModuleAnalyses(MAM);
33cacbe71aSYingwei Zheng     PB.registerCGSCCAnalyses(CGAM);
34cacbe71aSYingwei Zheng     PB.registerFunctionAnalyses(FAM);
35cacbe71aSYingwei Zheng     PB.registerLoopAnalyses(LAM);
36cacbe71aSYingwei Zheng     PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
37cacbe71aSYingwei Zheng   }
38cacbe71aSYingwei Zheng };
39cacbe71aSYingwei Zheng 
40cacbe71aSYingwei Zheng struct PassOption final {
41cacbe71aSYingwei Zheng   uint32_t Threshold;
42cacbe71aSYingwei Zheng 
43cacbe71aSYingwei Zheng   /// Assume that this pass doesn't make changes with threshold A if we already
44cacbe71aSYingwei Zheng   /// know it doesn't make changes with a larger threshold B.
45cacbe71aSYingwei Zheng   bool isCompatibleWith(const PassOption &LastOpt) const {
46cacbe71aSYingwei Zheng     return Threshold <= LastOpt.Threshold;
47cacbe71aSYingwei Zheng   }
48cacbe71aSYingwei Zheng };
49cacbe71aSYingwei Zheng 
50cacbe71aSYingwei Zheng class ModuleNoopPass : public PassInfoMixin<ModuleNoopPass> {
51cacbe71aSYingwei Zheng   uint32_t &ExecutedBitMap;
52cacbe71aSYingwei Zheng   uint32_t RunID;
53cacbe71aSYingwei Zheng   void *PassID;
54cacbe71aSYingwei Zheng   bool ShouldChange;
55cacbe71aSYingwei Zheng   std::optional<PassOption> Option;
56cacbe71aSYingwei Zheng 
57cacbe71aSYingwei Zheng   bool shouldSkip(LastRunTrackingInfo &LRT) {
58cacbe71aSYingwei Zheng     if (Option.has_value())
59cacbe71aSYingwei Zheng       return LRT.shouldSkip(PassID, *Option);
60cacbe71aSYingwei Zheng     return LRT.shouldSkip(PassID);
61cacbe71aSYingwei Zheng   }
62cacbe71aSYingwei Zheng 
63cacbe71aSYingwei Zheng   void update(LastRunTrackingInfo &LRT) {
64cacbe71aSYingwei Zheng     if (Option.has_value())
65cacbe71aSYingwei Zheng       return LRT.update(PassID, ShouldChange, *Option);
66cacbe71aSYingwei Zheng     return LRT.update(PassID, ShouldChange);
67cacbe71aSYingwei Zheng   }
68cacbe71aSYingwei Zheng 
69cacbe71aSYingwei Zheng public:
70cacbe71aSYingwei Zheng   explicit ModuleNoopPass(uint32_t &ExecutedBitMapRef, uint32_t RunIDVal,
71cacbe71aSYingwei Zheng                           void *PassIDVal, bool ShouldChangeVal,
72cacbe71aSYingwei Zheng                           std::optional<PassOption> OptionVal = std::nullopt)
73cacbe71aSYingwei Zheng       : ExecutedBitMap(ExecutedBitMapRef), RunID(RunIDVal), PassID(PassIDVal),
74cacbe71aSYingwei Zheng         ShouldChange(ShouldChangeVal), Option(OptionVal) {}
75cacbe71aSYingwei Zheng 
76cacbe71aSYingwei Zheng   PreservedAnalyses run(Module &F, ModuleAnalysisManager &AM) {
77cacbe71aSYingwei Zheng     auto &LRT = AM.getResult<LastRunTrackingAnalysis>(F);
78cacbe71aSYingwei Zheng     if (shouldSkip(LRT)) {
79cacbe71aSYingwei Zheng       EXPECT_FALSE(ShouldChange) << "This pass is incorrectly skipped.";
80cacbe71aSYingwei Zheng       return PreservedAnalyses::all();
81cacbe71aSYingwei Zheng     }
82cacbe71aSYingwei Zheng     ExecutedBitMap |= 1U << RunID;
83cacbe71aSYingwei Zheng     update(LRT);
84cacbe71aSYingwei Zheng     PreservedAnalyses PA;
85cacbe71aSYingwei Zheng     PA.preserve<LastRunTrackingAnalysis>();
86cacbe71aSYingwei Zheng     return PA;
87cacbe71aSYingwei Zheng   }
88cacbe71aSYingwei Zheng };
89cacbe71aSYingwei Zheng 
90cacbe71aSYingwei Zheng static char PassA, PassB;
91cacbe71aSYingwei Zheng 
92cacbe71aSYingwei Zheng TEST_F(LastRunTrackingAnalysisTest, SkipTest) {
93cacbe71aSYingwei Zheng   uint32_t BitMap = 0;
94cacbe71aSYingwei Zheng   // Executed. This is first run of PassA.
95cacbe71aSYingwei Zheng   MPM.addPass(ModuleNoopPass(BitMap, 0, &PassA, true));
96cacbe71aSYingwei Zheng   // Skipped since PassA has just been executed.
97cacbe71aSYingwei Zheng   MPM.addPass(ModuleNoopPass(BitMap, 1, &PassA, false));
98cacbe71aSYingwei Zheng   // Skipped since PassA has just been executed.
99cacbe71aSYingwei Zheng   MPM.addPass(ModuleNoopPass(BitMap, 2, &PassA, false));
100cacbe71aSYingwei Zheng   // Executed. This is first run of PassB.
101cacbe71aSYingwei Zheng   MPM.addPass(ModuleNoopPass(BitMap, 3, &PassB, false, PassOption{2}));
102cacbe71aSYingwei Zheng   // Skipped. PassB doesn't make changes with lower threshold.
103cacbe71aSYingwei Zheng   MPM.addPass(ModuleNoopPass(BitMap, 4, &PassB, false, PassOption{1}));
104cacbe71aSYingwei Zheng   // Executed. PassB may make changes with higher threshold.
105cacbe71aSYingwei Zheng   MPM.addPass(ModuleNoopPass(BitMap, 5, &PassB, false, PassOption{3}));
106cacbe71aSYingwei Zheng   // Skipped. We don't make changes since last run of PassA.
107cacbe71aSYingwei Zheng   MPM.addPass(ModuleNoopPass(BitMap, 6, &PassA, false));
108cacbe71aSYingwei Zheng   // Executed. PassB may make changes with higher threshold.
109cacbe71aSYingwei Zheng   MPM.addPass(ModuleNoopPass(BitMap, 7, &PassB, true, PassOption{4}));
110cacbe71aSYingwei Zheng   // Executed. This module has been modified by PassB.
111cacbe71aSYingwei Zheng   MPM.addPass(ModuleNoopPass(BitMap, 8, &PassA, false));
112cacbe71aSYingwei Zheng   MPM.run(M, MAM);
113cacbe71aSYingwei Zheng 
114*84745da7SKazu Hirata   ASSERT_EQ(BitMap, 0b110101001U);
115cacbe71aSYingwei Zheng }
116cacbe71aSYingwei Zheng 
117cacbe71aSYingwei Zheng } // namespace
118