xref: /llvm-project/mlir/unittests/Pass/AnalysisManagerTest.cpp (revision 3a77eb669894f77ef30f61d3a4f9767596fd0fcd)
11d87b62aSRiver Riddle //===- AnalysisManagerTest.cpp - AnalysisManager unit tests ---------------===//
21d87b62aSRiver Riddle //
330857107SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
456222a06SMehdi Amini // See https://llvm.org/LICENSE.txt for license information.
556222a06SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61d87b62aSRiver Riddle //
756222a06SMehdi Amini //===----------------------------------------------------------------------===//
81d87b62aSRiver Riddle 
91d87b62aSRiver Riddle #include "mlir/Pass/AnalysisManager.h"
1036550692SRiver Riddle #include "mlir/Dialect/Func/IR/FuncOps.h"
111d87b62aSRiver Riddle #include "mlir/IR/Builders.h"
1265fcddffSRiver Riddle #include "mlir/IR/BuiltinOps.h"
139a4b30cfSRahul Joshi #include "mlir/Pass/Pass.h"
149a4b30cfSRahul Joshi #include "mlir/Pass/PassManager.h"
151d87b62aSRiver Riddle #include "gtest/gtest.h"
161d87b62aSRiver Riddle 
171d87b62aSRiver Riddle using namespace mlir;
181d87b62aSRiver Riddle using namespace mlir::detail;
191d87b62aSRiver Riddle 
201d87b62aSRiver Riddle namespace {
211d87b62aSRiver Riddle /// Minimal class definitions for two analyses.
221d87b62aSRiver Riddle struct MyAnalysis {
235e50dd04SRiver Riddle   MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(MyAnalysis)
245e50dd04SRiver Riddle 
MyAnalysis__anon7c676c9d0111::MyAnalysis2529099e03SRiver Riddle   MyAnalysis(Operation *) {}
261d87b62aSRiver Riddle };
271d87b62aSRiver Riddle struct OtherAnalysis {
285e50dd04SRiver Riddle   MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(OtherAnalysis)
295e50dd04SRiver Riddle 
OtherAnalysis__anon7c676c9d0111::OtherAnalysis3029099e03SRiver Riddle   OtherAnalysis(Operation *) {}
311d87b62aSRiver Riddle };
329a4b30cfSRahul Joshi struct OpSpecificAnalysis {
335e50dd04SRiver Riddle   MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(OpSpecificAnalysis)
345e50dd04SRiver Riddle 
OpSpecificAnalysis__anon7c676c9d0111::OpSpecificAnalysis359a4b30cfSRahul Joshi   OpSpecificAnalysis(ModuleOp) {}
369a4b30cfSRahul Joshi };
371d87b62aSRiver Riddle 
TEST(AnalysisManagerTest,FineGrainModuleAnalysisPreservation)381d87b62aSRiver Riddle TEST(AnalysisManagerTest, FineGrainModuleAnalysisPreservation) {
39e7021232SMehdi Amini   MLIRContext context;
401d87b62aSRiver Riddle 
411d87b62aSRiver Riddle   // Test fine grain invalidation of the module analysis manager.
428f66ab1cSSanjoy Das   OwningOpRef<ModuleOp> module(ModuleOp::create(UnknownLoc::get(&context)));
43206e55ccSRiver Riddle   ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr);
4429099e03SRiver Riddle   AnalysisManager am = mam;
451d87b62aSRiver Riddle 
461d87b62aSRiver Riddle   // Query two different analyses, but only preserve one before invalidating.
4729099e03SRiver Riddle   am.getAnalysis<MyAnalysis>();
4829099e03SRiver Riddle   am.getAnalysis<OtherAnalysis>();
491d87b62aSRiver Riddle 
501d87b62aSRiver Riddle   detail::PreservedAnalyses pa;
511d87b62aSRiver Riddle   pa.preserve<MyAnalysis>();
5229099e03SRiver Riddle   am.invalidate(pa);
531d87b62aSRiver Riddle 
541d87b62aSRiver Riddle   // Check that only MyAnalysis is preserved.
55491d2701SKazu Hirata   EXPECT_TRUE(am.getCachedAnalysis<MyAnalysis>().has_value());
56491d2701SKazu Hirata   EXPECT_FALSE(am.getCachedAnalysis<OtherAnalysis>().has_value());
571d87b62aSRiver Riddle }
581d87b62aSRiver Riddle 
TEST(AnalysisManagerTest,FineGrainFunctionAnalysisPreservation)591d87b62aSRiver Riddle TEST(AnalysisManagerTest, FineGrainFunctionAnalysisPreservation) {
60e7021232SMehdi Amini   MLIRContext context;
6136550692SRiver Riddle   context.loadDialect<func::FuncDialect>();
621d87b62aSRiver Riddle   Builder builder(&context);
631d87b62aSRiver Riddle 
641d87b62aSRiver Riddle   // Create a function and a module.
658f66ab1cSSanjoy Das   OwningOpRef<ModuleOp> module(ModuleOp::create(UnknownLoc::get(&context)));
6658ceae95SRiver Riddle   func::FuncOp func1 =
6758ceae95SRiver Riddle       func::FuncOp::create(builder.getUnknownLoc(), "foo",
68*3a77eb66SKazu Hirata                            builder.getFunctionType(std::nullopt, std::nullopt));
69b7382ed3SRahul Joshi   func1.setPrivate();
7054cd6a7eSRiver Riddle   module->push_back(func1);
711d87b62aSRiver Riddle 
721d87b62aSRiver Riddle   // Test fine grain invalidation of the function analysis manager.
73206e55ccSRiver Riddle   ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr);
7429099e03SRiver Riddle   AnalysisManager am = mam;
75c39c2161SMehdi Amini   AnalysisManager fam = am.nest(func1);
761d87b62aSRiver Riddle 
771d87b62aSRiver Riddle   // Query two different analyses, but only preserve one before invalidating.
78d43f630dSRiver Riddle   fam.getAnalysis<MyAnalysis>();
79d43f630dSRiver Riddle   fam.getAnalysis<OtherAnalysis>();
801d87b62aSRiver Riddle 
811d87b62aSRiver Riddle   detail::PreservedAnalyses pa;
821d87b62aSRiver Riddle   pa.preserve<MyAnalysis>();
831d87b62aSRiver Riddle   fam.invalidate(pa);
841d87b62aSRiver Riddle 
851d87b62aSRiver Riddle   // Check that only MyAnalysis is preserved.
86491d2701SKazu Hirata   EXPECT_TRUE(fam.getCachedAnalysis<MyAnalysis>().has_value());
87491d2701SKazu Hirata   EXPECT_FALSE(fam.getCachedAnalysis<OtherAnalysis>().has_value());
881d87b62aSRiver Riddle }
891d87b62aSRiver Riddle 
TEST(AnalysisManagerTest,FineGrainChildFunctionAnalysisPreservation)901d87b62aSRiver Riddle TEST(AnalysisManagerTest, FineGrainChildFunctionAnalysisPreservation) {
91e7021232SMehdi Amini   MLIRContext context;
9236550692SRiver Riddle   context.loadDialect<func::FuncDialect>();
931d87b62aSRiver Riddle   Builder builder(&context);
941d87b62aSRiver Riddle 
951d87b62aSRiver Riddle   // Create a function and a module.
968f66ab1cSSanjoy Das   OwningOpRef<ModuleOp> module(ModuleOp::create(UnknownLoc::get(&context)));
9758ceae95SRiver Riddle   func::FuncOp func1 =
9858ceae95SRiver Riddle       func::FuncOp::create(builder.getUnknownLoc(), "foo",
99*3a77eb66SKazu Hirata                            builder.getFunctionType(std::nullopt, std::nullopt));
100b7382ed3SRahul Joshi   func1.setPrivate();
10154cd6a7eSRiver Riddle   module->push_back(func1);
1021d87b62aSRiver Riddle 
1031d87b62aSRiver Riddle   // Test fine grain invalidation of a function analysis from within a module
1041d87b62aSRiver Riddle   // analysis manager.
105206e55ccSRiver Riddle   ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr);
10629099e03SRiver Riddle   AnalysisManager am = mam;
10729099e03SRiver Riddle 
10829099e03SRiver Riddle   // Check that the analysis cache is initially empty.
109491d2701SKazu Hirata   EXPECT_FALSE(am.getCachedChildAnalysis<MyAnalysis>(func1).has_value());
1101d87b62aSRiver Riddle 
1111d87b62aSRiver Riddle   // Query two different analyses, but only preserve one before invalidating.
11229099e03SRiver Riddle   am.getChildAnalysis<MyAnalysis>(func1);
11329099e03SRiver Riddle   am.getChildAnalysis<OtherAnalysis>(func1);
1141d87b62aSRiver Riddle 
1151d87b62aSRiver Riddle   detail::PreservedAnalyses pa;
1161d87b62aSRiver Riddle   pa.preserve<MyAnalysis>();
11729099e03SRiver Riddle   am.invalidate(pa);
1181d87b62aSRiver Riddle 
1191d87b62aSRiver Riddle   // Check that only MyAnalysis is preserved.
120491d2701SKazu Hirata   EXPECT_TRUE(am.getCachedChildAnalysis<MyAnalysis>(func1).has_value());
121491d2701SKazu Hirata   EXPECT_FALSE(am.getCachedChildAnalysis<OtherAnalysis>(func1).has_value());
1221d87b62aSRiver Riddle }
1231d87b62aSRiver Riddle 
1244741ec6aSRiver Riddle /// Test analyses with custom invalidation logic.
1255e50dd04SRiver Riddle struct TestAnalysisSet {
1265e50dd04SRiver Riddle   MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestAnalysisSet)
1275e50dd04SRiver Riddle };
1284741ec6aSRiver Riddle 
1294741ec6aSRiver Riddle struct CustomInvalidatingAnalysis {
1305e50dd04SRiver Riddle   MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(CustomInvalidatingAnalysis)
1315e50dd04SRiver Riddle 
CustomInvalidatingAnalysis__anon7c676c9d0111::CustomInvalidatingAnalysis1324741ec6aSRiver Riddle   CustomInvalidatingAnalysis(Operation *) {}
1334741ec6aSRiver Riddle 
isInvalidated__anon7c676c9d0111::CustomInvalidatingAnalysis1344741ec6aSRiver Riddle   bool isInvalidated(const AnalysisManager::PreservedAnalyses &pa) {
1354741ec6aSRiver Riddle     return !pa.isPreserved<TestAnalysisSet>();
1364741ec6aSRiver Riddle   }
1374741ec6aSRiver Riddle };
1384741ec6aSRiver Riddle 
TEST(AnalysisManagerTest,CustomInvalidation)1394741ec6aSRiver Riddle TEST(AnalysisManagerTest, CustomInvalidation) {
140e7021232SMehdi Amini   MLIRContext context;
1414741ec6aSRiver Riddle   Builder builder(&context);
1424741ec6aSRiver Riddle 
1434741ec6aSRiver Riddle   // Create a function and a module.
1448f66ab1cSSanjoy Das   OwningOpRef<ModuleOp> module(ModuleOp::create(UnknownLoc::get(&context)));
1454741ec6aSRiver Riddle   ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr);
1464741ec6aSRiver Riddle   AnalysisManager am = mam;
1474741ec6aSRiver Riddle 
1484741ec6aSRiver Riddle   detail::PreservedAnalyses pa;
1494741ec6aSRiver Riddle 
1504741ec6aSRiver Riddle   // Check that the analysis is invalidated properly.
1514741ec6aSRiver Riddle   am.getAnalysis<CustomInvalidatingAnalysis>();
1524741ec6aSRiver Riddle   am.invalidate(pa);
153491d2701SKazu Hirata   EXPECT_FALSE(am.getCachedAnalysis<CustomInvalidatingAnalysis>().has_value());
1544741ec6aSRiver Riddle 
1554741ec6aSRiver Riddle   // Check that the analysis is preserved properly.
1564741ec6aSRiver Riddle   am.getAnalysis<CustomInvalidatingAnalysis>();
1574741ec6aSRiver Riddle   pa.preserve<TestAnalysisSet>();
1584741ec6aSRiver Riddle   am.invalidate(pa);
159491d2701SKazu Hirata   EXPECT_TRUE(am.getCachedAnalysis<CustomInvalidatingAnalysis>().has_value());
1604741ec6aSRiver Riddle }
1619a4b30cfSRahul Joshi 
TEST(AnalysisManagerTest,OpSpecificAnalysis)1629a4b30cfSRahul Joshi TEST(AnalysisManagerTest, OpSpecificAnalysis) {
1639a4b30cfSRahul Joshi   MLIRContext context;
1649a4b30cfSRahul Joshi 
1659a4b30cfSRahul Joshi   // Create a module.
1668f66ab1cSSanjoy Das   OwningOpRef<ModuleOp> module(ModuleOp::create(UnknownLoc::get(&context)));
1679a4b30cfSRahul Joshi   ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr);
1689a4b30cfSRahul Joshi   AnalysisManager am = mam;
1699a4b30cfSRahul Joshi 
1709a4b30cfSRahul Joshi   // Query the op specific analysis for the module and verify that its cached.
1719a4b30cfSRahul Joshi   am.getAnalysis<OpSpecificAnalysis, ModuleOp>();
172491d2701SKazu Hirata   EXPECT_TRUE(am.getCachedAnalysis<OpSpecificAnalysis>().has_value());
1739a4b30cfSRahul Joshi }
1749a4b30cfSRahul Joshi 
175cd94f18eSButygin struct AnalysisWithDependency {
1765e50dd04SRiver Riddle   MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(AnalysisWithDependency)
1775e50dd04SRiver Riddle 
AnalysisWithDependency__anon7c676c9d0111::AnalysisWithDependency178cd94f18eSButygin   AnalysisWithDependency(Operation *, AnalysisManager &am) {
179cd94f18eSButygin     am.getAnalysis<MyAnalysis>();
180cd94f18eSButygin   }
181cd94f18eSButygin 
isInvalidated__anon7c676c9d0111::AnalysisWithDependency182cd94f18eSButygin   bool isInvalidated(const AnalysisManager::PreservedAnalyses &pa) {
183cd94f18eSButygin     return !pa.isPreserved<AnalysisWithDependency>() ||
184cd94f18eSButygin            !pa.isPreserved<MyAnalysis>();
185cd94f18eSButygin   }
186cd94f18eSButygin };
187cd94f18eSButygin 
TEST(AnalysisManagerTest,DependentAnalysis)188cd94f18eSButygin TEST(AnalysisManagerTest, DependentAnalysis) {
189cd94f18eSButygin   MLIRContext context;
190cd94f18eSButygin 
191cd94f18eSButygin   // Create a module.
1928f66ab1cSSanjoy Das   OwningOpRef<ModuleOp> module(ModuleOp::create(UnknownLoc::get(&context)));
193cd94f18eSButygin   ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr);
194cd94f18eSButygin   AnalysisManager am = mam;
195cd94f18eSButygin 
196cd94f18eSButygin   am.getAnalysis<AnalysisWithDependency>();
197491d2701SKazu Hirata   EXPECT_TRUE(am.getCachedAnalysis<AnalysisWithDependency>().has_value());
198491d2701SKazu Hirata   EXPECT_TRUE(am.getCachedAnalysis<MyAnalysis>().has_value());
199cd94f18eSButygin 
200cd94f18eSButygin   detail::PreservedAnalyses pa;
201cd94f18eSButygin   pa.preserve<AnalysisWithDependency>();
202cd94f18eSButygin   am.invalidate(pa);
203cd94f18eSButygin 
204491d2701SKazu Hirata   EXPECT_FALSE(am.getCachedAnalysis<AnalysisWithDependency>().has_value());
205491d2701SKazu Hirata   EXPECT_FALSE(am.getCachedAnalysis<MyAnalysis>().has_value());
206cd94f18eSButygin }
207cd94f18eSButygin 
208cd94f18eSButygin struct AnalysisWithNestedDependency {
2095e50dd04SRiver Riddle   MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(AnalysisWithNestedDependency)
2105e50dd04SRiver Riddle 
AnalysisWithNestedDependency__anon7c676c9d0111::AnalysisWithNestedDependency211cd94f18eSButygin   AnalysisWithNestedDependency(Operation *, AnalysisManager &am) {
212cd94f18eSButygin     am.getAnalysis<AnalysisWithDependency>();
213cd94f18eSButygin   }
214cd94f18eSButygin 
isInvalidated__anon7c676c9d0111::AnalysisWithNestedDependency215cd94f18eSButygin   bool isInvalidated(const AnalysisManager::PreservedAnalyses &pa) {
216cd94f18eSButygin     return !pa.isPreserved<AnalysisWithNestedDependency>() ||
217cd94f18eSButygin            !pa.isPreserved<AnalysisWithDependency>();
218cd94f18eSButygin   }
219cd94f18eSButygin };
220cd94f18eSButygin 
TEST(AnalysisManagerTest,NestedDependentAnalysis)221cd94f18eSButygin TEST(AnalysisManagerTest, NestedDependentAnalysis) {
222cd94f18eSButygin   MLIRContext context;
223cd94f18eSButygin 
224cd94f18eSButygin   // Create a module.
2258f66ab1cSSanjoy Das   OwningOpRef<ModuleOp> module(ModuleOp::create(UnknownLoc::get(&context)));
226cd94f18eSButygin   ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr);
227cd94f18eSButygin   AnalysisManager am = mam;
228cd94f18eSButygin 
229cd94f18eSButygin   am.getAnalysis<AnalysisWithNestedDependency>();
230491d2701SKazu Hirata   EXPECT_TRUE(am.getCachedAnalysis<AnalysisWithNestedDependency>().has_value());
231491d2701SKazu Hirata   EXPECT_TRUE(am.getCachedAnalysis<AnalysisWithDependency>().has_value());
232491d2701SKazu Hirata   EXPECT_TRUE(am.getCachedAnalysis<MyAnalysis>().has_value());
233cd94f18eSButygin 
234cd94f18eSButygin   detail::PreservedAnalyses pa;
235cd94f18eSButygin   pa.preserve<AnalysisWithDependency>();
236cd94f18eSButygin   pa.preserve<AnalysisWithNestedDependency>();
237cd94f18eSButygin   am.invalidate(pa);
238cd94f18eSButygin 
239491d2701SKazu Hirata   EXPECT_FALSE(
240491d2701SKazu Hirata       am.getCachedAnalysis<AnalysisWithNestedDependency>().has_value());
241491d2701SKazu Hirata   EXPECT_FALSE(am.getCachedAnalysis<AnalysisWithDependency>().has_value());
242491d2701SKazu Hirata   EXPECT_FALSE(am.getCachedAnalysis<MyAnalysis>().has_value());
243cd94f18eSButygin }
244cd94f18eSButygin 
245cd94f18eSButygin struct AnalysisWith2Ctors {
2465e50dd04SRiver Riddle   MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(AnalysisWith2Ctors)
2475e50dd04SRiver Riddle 
AnalysisWith2Ctors__anon7c676c9d0111::AnalysisWith2Ctors248cd94f18eSButygin   AnalysisWith2Ctors(Operation *) { ctor1called = true; }
249cd94f18eSButygin 
AnalysisWith2Ctors__anon7c676c9d0111::AnalysisWith2Ctors250cd94f18eSButygin   AnalysisWith2Ctors(Operation *, AnalysisManager &) { ctor2called = true; }
251cd94f18eSButygin 
252cd94f18eSButygin   bool ctor1called = false;
253cd94f18eSButygin   bool ctor2called = false;
254cd94f18eSButygin };
255cd94f18eSButygin 
TEST(AnalysisManagerTest,DependentAnalysis2Ctors)256cd94f18eSButygin TEST(AnalysisManagerTest, DependentAnalysis2Ctors) {
257cd94f18eSButygin   MLIRContext context;
258cd94f18eSButygin 
259cd94f18eSButygin   // Create a module.
2608f66ab1cSSanjoy Das   OwningOpRef<ModuleOp> module(ModuleOp::create(UnknownLoc::get(&context)));
261cd94f18eSButygin   ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr);
262cd94f18eSButygin   AnalysisManager am = mam;
263cd94f18eSButygin 
264cd94f18eSButygin   auto &an = am.getAnalysis<AnalysisWith2Ctors>();
265cd94f18eSButygin   EXPECT_FALSE(an.ctor1called);
266cd94f18eSButygin   EXPECT_TRUE(an.ctor2called);
267cd94f18eSButygin }
268cd94f18eSButygin 
269be0a7e9fSMehdi Amini } // namespace
270