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