1 //===--- LastRunTrackingAnalysisTest.cpp - LastRunTrackingAnalysis 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/Analysis/LastRunTrackingAnalysis.h"
10 #include "llvm/IR/LLVMContext.h"
11 #include "llvm/IR/Module.h"
12 #include "llvm/Passes/PassBuilder.h"
13 #include "gtest/gtest.h"
19 class LastRunTrackingAnalysisTest
: public testing::Test
{
25 LoopAnalysisManager LAM
;
26 FunctionAnalysisManager FAM
;
27 CGSCCAnalysisManager CGAM
;
28 ModulePassManager MPM
;
29 ModuleAnalysisManager MAM
;
31 LastRunTrackingAnalysisTest() : M("LastRunTrackingAnalysisTest", C
) {
32 PB
.registerModuleAnalyses(MAM
);
33 PB
.registerCGSCCAnalyses(CGAM
);
34 PB
.registerFunctionAnalyses(FAM
);
35 PB
.registerLoopAnalyses(LAM
);
36 PB
.crossRegisterProxies(LAM
, FAM
, CGAM
, MAM
);
40 struct PassOption final
{
43 /// Assume that this pass doesn't make changes with threshold A if we already
44 /// know it doesn't make changes with a larger threshold B.
45 bool isCompatibleWith(const PassOption
&LastOpt
) const {
46 return Threshold
<= LastOpt
.Threshold
;
50 class ModuleNoopPass
: public PassInfoMixin
<ModuleNoopPass
> {
51 uint32_t &ExecutedBitMap
;
55 std::optional
<PassOption
> Option
;
57 bool shouldSkip(LastRunTrackingInfo
&LRT
) {
58 if (Option
.has_value())
59 return LRT
.shouldSkip(PassID
, *Option
);
60 return LRT
.shouldSkip(PassID
);
63 void update(LastRunTrackingInfo
&LRT
) {
64 if (Option
.has_value())
65 return LRT
.update(PassID
, ShouldChange
, *Option
);
66 return LRT
.update(PassID
, ShouldChange
);
70 explicit ModuleNoopPass(uint32_t &ExecutedBitMapRef
, uint32_t RunIDVal
,
71 void *PassIDVal
, bool ShouldChangeVal
,
72 std::optional
<PassOption
> OptionVal
= std::nullopt
)
73 : ExecutedBitMap(ExecutedBitMapRef
), RunID(RunIDVal
), PassID(PassIDVal
),
74 ShouldChange(ShouldChangeVal
), Option(OptionVal
) {}
76 PreservedAnalyses
run(Module
&F
, ModuleAnalysisManager
&AM
) {
77 auto &LRT
= AM
.getResult
<LastRunTrackingAnalysis
>(F
);
78 if (shouldSkip(LRT
)) {
79 EXPECT_FALSE(ShouldChange
) << "This pass is incorrectly skipped.";
80 return PreservedAnalyses::all();
82 ExecutedBitMap
|= 1U << RunID
;
85 PA
.preserve
<LastRunTrackingAnalysis
>();
90 static char PassA
, PassB
;
92 TEST_F(LastRunTrackingAnalysisTest
, SkipTest
) {
94 // Executed. This is first run of PassA.
95 MPM
.addPass(ModuleNoopPass(BitMap
, 0, &PassA
, true));
96 // Skipped since PassA has just been executed.
97 MPM
.addPass(ModuleNoopPass(BitMap
, 1, &PassA
, false));
98 // Skipped since PassA has just been executed.
99 MPM
.addPass(ModuleNoopPass(BitMap
, 2, &PassA
, false));
100 // Executed. This is first run of PassB.
101 MPM
.addPass(ModuleNoopPass(BitMap
, 3, &PassB
, false, PassOption
{2}));
102 // Skipped. PassB doesn't make changes with lower threshold.
103 MPM
.addPass(ModuleNoopPass(BitMap
, 4, &PassB
, false, PassOption
{1}));
104 // Executed. PassB may make changes with higher threshold.
105 MPM
.addPass(ModuleNoopPass(BitMap
, 5, &PassB
, false, PassOption
{3}));
106 // Skipped. We don't make changes since last run of PassA.
107 MPM
.addPass(ModuleNoopPass(BitMap
, 6, &PassA
, false));
108 // Executed. PassB may make changes with higher threshold.
109 MPM
.addPass(ModuleNoopPass(BitMap
, 7, &PassB
, true, PassOption
{4}));
110 // Executed. This module has been modified by PassB.
111 MPM
.addPass(ModuleNoopPass(BitMap
, 8, &PassA
, false));
114 ASSERT_EQ(BitMap
, 0b110101001U
);