118 lines · cpp
1//===--- LastRunTrackingAnalysisTest.cpp - LastRunTrackingAnalysis 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/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"14 15namespace {16 17using namespace llvm;18 19class LastRunTrackingAnalysisTest : public testing::Test {20protected:21 LLVMContext C;22 Module M;23 PassBuilder PB;24 25 LoopAnalysisManager LAM;26 FunctionAnalysisManager FAM;27 CGSCCAnalysisManager CGAM;28 ModulePassManager MPM;29 ModuleAnalysisManager MAM;30 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);37 }38};39 40struct PassOption final {41 uint32_t Threshold;42 43 /// Assume that this pass doesn't make changes with threshold A if we already44 /// know it doesn't make changes with a larger threshold B.45 bool isCompatibleWith(const PassOption &LastOpt) const {46 return Threshold <= LastOpt.Threshold;47 }48};49 50class ModuleNoopPass : public PassInfoMixin<ModuleNoopPass> {51 uint32_t &ExecutedBitMap;52 uint32_t RunID;53 void *PassID;54 bool ShouldChange;55 std::optional<PassOption> Option;56 57 bool shouldSkip(LastRunTrackingInfo &LRT) {58 if (Option.has_value())59 return LRT.shouldSkip(PassID, *Option);60 return LRT.shouldSkip(PassID);61 }62 63 void update(LastRunTrackingInfo &LRT) {64 if (Option.has_value())65 return LRT.update(PassID, ShouldChange, *Option);66 return LRT.update(PassID, ShouldChange);67 }68 69public: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) {}75 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();81 }82 ExecutedBitMap |= 1U << RunID;83 update(LRT);84 PreservedAnalyses PA;85 PA.preserve<LastRunTrackingAnalysis>();86 return PA;87 }88};89 90static char PassA, PassB;91 92TEST_F(LastRunTrackingAnalysisTest, SkipTest) {93 uint32_t BitMap = 0;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));112 MPM.run(M, MAM);113 114 ASSERT_EQ(BitMap, 0b110101001U);115}116 117} // namespace118