1 //===- AnalysisManagerTest.cpp - AnalysisManager unit 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "mlir/Pass/AnalysisManager.h" 10 #include "mlir/IR/Builders.h" 11 #include "mlir/IR/Function.h" 12 #include "mlir/Pass/Pass.h" 13 #include "mlir/Pass/PassManager.h" 14 #include "gtest/gtest.h" 15 16 using namespace mlir; 17 using namespace mlir::detail; 18 19 namespace { 20 /// Minimal class definitions for two analyses. 21 struct MyAnalysis { 22 MyAnalysis(Operation *) {} 23 }; 24 struct OtherAnalysis { 25 OtherAnalysis(Operation *) {} 26 }; 27 struct OpSpecificAnalysis { 28 OpSpecificAnalysis(ModuleOp) {} 29 }; 30 31 TEST(AnalysisManagerTest, FineGrainModuleAnalysisPreservation) { 32 MLIRContext context; 33 34 // Test fine grain invalidation of the module analysis manager. 35 OwningModuleRef module(ModuleOp::create(UnknownLoc::get(&context))); 36 ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr); 37 AnalysisManager am = mam; 38 39 // Query two different analyses, but only preserve one before invalidating. 40 am.getAnalysis<MyAnalysis>(); 41 am.getAnalysis<OtherAnalysis>(); 42 43 detail::PreservedAnalyses pa; 44 pa.preserve<MyAnalysis>(); 45 am.invalidate(pa); 46 47 // Check that only MyAnalysis is preserved. 48 EXPECT_TRUE(am.getCachedAnalysis<MyAnalysis>().hasValue()); 49 EXPECT_FALSE(am.getCachedAnalysis<OtherAnalysis>().hasValue()); 50 } 51 52 TEST(AnalysisManagerTest, FineGrainFunctionAnalysisPreservation) { 53 MLIRContext context; 54 Builder builder(&context); 55 56 // Create a function and a module. 57 OwningModuleRef module(ModuleOp::create(UnknownLoc::get(&context))); 58 FuncOp func1 = 59 FuncOp::create(builder.getUnknownLoc(), "foo", 60 builder.getFunctionType(llvm::None, llvm::None)); 61 module->push_back(func1); 62 63 // Test fine grain invalidation of the function analysis manager. 64 ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr); 65 AnalysisManager am = mam; 66 AnalysisManager fam = am.nest(func1); 67 68 // Query two different analyses, but only preserve one before invalidating. 69 fam.getAnalysis<MyAnalysis>(); 70 fam.getAnalysis<OtherAnalysis>(); 71 72 detail::PreservedAnalyses pa; 73 pa.preserve<MyAnalysis>(); 74 fam.invalidate(pa); 75 76 // Check that only MyAnalysis is preserved. 77 EXPECT_TRUE(fam.getCachedAnalysis<MyAnalysis>().hasValue()); 78 EXPECT_FALSE(fam.getCachedAnalysis<OtherAnalysis>().hasValue()); 79 } 80 81 TEST(AnalysisManagerTest, FineGrainChildFunctionAnalysisPreservation) { 82 MLIRContext context; 83 Builder builder(&context); 84 85 // Create a function and a module. 86 OwningModuleRef module(ModuleOp::create(UnknownLoc::get(&context))); 87 FuncOp func1 = 88 FuncOp::create(builder.getUnknownLoc(), "foo", 89 builder.getFunctionType(llvm::None, llvm::None)); 90 module->push_back(func1); 91 92 // Test fine grain invalidation of a function analysis from within a module 93 // analysis manager. 94 ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr); 95 AnalysisManager am = mam; 96 97 // Check that the analysis cache is initially empty. 98 EXPECT_FALSE(am.getCachedChildAnalysis<MyAnalysis>(func1).hasValue()); 99 100 // Query two different analyses, but only preserve one before invalidating. 101 am.getChildAnalysis<MyAnalysis>(func1); 102 am.getChildAnalysis<OtherAnalysis>(func1); 103 104 detail::PreservedAnalyses pa; 105 pa.preserve<MyAnalysis>(); 106 am.invalidate(pa); 107 108 // Check that only MyAnalysis is preserved. 109 EXPECT_TRUE(am.getCachedChildAnalysis<MyAnalysis>(func1).hasValue()); 110 EXPECT_FALSE(am.getCachedChildAnalysis<OtherAnalysis>(func1).hasValue()); 111 } 112 113 /// Test analyses with custom invalidation logic. 114 struct TestAnalysisSet {}; 115 116 struct CustomInvalidatingAnalysis { 117 CustomInvalidatingAnalysis(Operation *) {} 118 119 bool isInvalidated(const AnalysisManager::PreservedAnalyses &pa) { 120 return !pa.isPreserved<TestAnalysisSet>(); 121 } 122 }; 123 124 TEST(AnalysisManagerTest, CustomInvalidation) { 125 MLIRContext context; 126 Builder builder(&context); 127 128 // Create a function and a module. 129 OwningModuleRef module(ModuleOp::create(UnknownLoc::get(&context))); 130 ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr); 131 AnalysisManager am = mam; 132 133 detail::PreservedAnalyses pa; 134 135 // Check that the analysis is invalidated properly. 136 am.getAnalysis<CustomInvalidatingAnalysis>(); 137 am.invalidate(pa); 138 EXPECT_FALSE(am.getCachedAnalysis<CustomInvalidatingAnalysis>().hasValue()); 139 140 // Check that the analysis is preserved properly. 141 am.getAnalysis<CustomInvalidatingAnalysis>(); 142 pa.preserve<TestAnalysisSet>(); 143 am.invalidate(pa); 144 EXPECT_TRUE(am.getCachedAnalysis<CustomInvalidatingAnalysis>().hasValue()); 145 } 146 147 TEST(AnalysisManagerTest, OpSpecificAnalysis) { 148 MLIRContext context; 149 150 // Create a module. 151 OwningModuleRef module(ModuleOp::create(UnknownLoc::get(&context))); 152 ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr); 153 AnalysisManager am = mam; 154 155 // Query the op specific analysis for the module and verify that its cached. 156 am.getAnalysis<OpSpecificAnalysis, ModuleOp>(); 157 EXPECT_TRUE(am.getCachedAnalysis<OpSpecificAnalysis>().hasValue()); 158 } 159 160 } // end namespace 161