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/BuiltinOps.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 {
MyAnalysis__anon1e6749e10111::MyAnalysis22 MyAnalysis(Operation *) {}
23 };
24 struct OtherAnalysis {
OtherAnalysis__anon1e6749e10111::OtherAnalysis25 OtherAnalysis(Operation *) {}
26 };
27 struct OpSpecificAnalysis {
OpSpecificAnalysis__anon1e6749e10111::OpSpecificAnalysis28 OpSpecificAnalysis(ModuleOp) {}
29 };
30
TEST(AnalysisManagerTest,FineGrainModuleAnalysisPreservation)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
TEST(AnalysisManagerTest,FineGrainFunctionAnalysisPreservation)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 func1.setPrivate();
62 module->push_back(func1);
63
64 // Test fine grain invalidation of the function analysis manager.
65 ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr);
66 AnalysisManager am = mam;
67 AnalysisManager fam = am.nest(func1);
68
69 // Query two different analyses, but only preserve one before invalidating.
70 fam.getAnalysis<MyAnalysis>();
71 fam.getAnalysis<OtherAnalysis>();
72
73 detail::PreservedAnalyses pa;
74 pa.preserve<MyAnalysis>();
75 fam.invalidate(pa);
76
77 // Check that only MyAnalysis is preserved.
78 EXPECT_TRUE(fam.getCachedAnalysis<MyAnalysis>().hasValue());
79 EXPECT_FALSE(fam.getCachedAnalysis<OtherAnalysis>().hasValue());
80 }
81
TEST(AnalysisManagerTest,FineGrainChildFunctionAnalysisPreservation)82 TEST(AnalysisManagerTest, FineGrainChildFunctionAnalysisPreservation) {
83 MLIRContext context;
84 Builder builder(&context);
85
86 // Create a function and a module.
87 OwningModuleRef module(ModuleOp::create(UnknownLoc::get(&context)));
88 FuncOp func1 =
89 FuncOp::create(builder.getUnknownLoc(), "foo",
90 builder.getFunctionType(llvm::None, llvm::None));
91 func1.setPrivate();
92 module->push_back(func1);
93
94 // Test fine grain invalidation of a function analysis from within a module
95 // analysis manager.
96 ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr);
97 AnalysisManager am = mam;
98
99 // Check that the analysis cache is initially empty.
100 EXPECT_FALSE(am.getCachedChildAnalysis<MyAnalysis>(func1).hasValue());
101
102 // Query two different analyses, but only preserve one before invalidating.
103 am.getChildAnalysis<MyAnalysis>(func1);
104 am.getChildAnalysis<OtherAnalysis>(func1);
105
106 detail::PreservedAnalyses pa;
107 pa.preserve<MyAnalysis>();
108 am.invalidate(pa);
109
110 // Check that only MyAnalysis is preserved.
111 EXPECT_TRUE(am.getCachedChildAnalysis<MyAnalysis>(func1).hasValue());
112 EXPECT_FALSE(am.getCachedChildAnalysis<OtherAnalysis>(func1).hasValue());
113 }
114
115 /// Test analyses with custom invalidation logic.
116 struct TestAnalysisSet {};
117
118 struct CustomInvalidatingAnalysis {
CustomInvalidatingAnalysis__anon1e6749e10111::CustomInvalidatingAnalysis119 CustomInvalidatingAnalysis(Operation *) {}
120
isInvalidated__anon1e6749e10111::CustomInvalidatingAnalysis121 bool isInvalidated(const AnalysisManager::PreservedAnalyses &pa) {
122 return !pa.isPreserved<TestAnalysisSet>();
123 }
124 };
125
TEST(AnalysisManagerTest,CustomInvalidation)126 TEST(AnalysisManagerTest, CustomInvalidation) {
127 MLIRContext context;
128 Builder builder(&context);
129
130 // Create a function and a module.
131 OwningModuleRef module(ModuleOp::create(UnknownLoc::get(&context)));
132 ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr);
133 AnalysisManager am = mam;
134
135 detail::PreservedAnalyses pa;
136
137 // Check that the analysis is invalidated properly.
138 am.getAnalysis<CustomInvalidatingAnalysis>();
139 am.invalidate(pa);
140 EXPECT_FALSE(am.getCachedAnalysis<CustomInvalidatingAnalysis>().hasValue());
141
142 // Check that the analysis is preserved properly.
143 am.getAnalysis<CustomInvalidatingAnalysis>();
144 pa.preserve<TestAnalysisSet>();
145 am.invalidate(pa);
146 EXPECT_TRUE(am.getCachedAnalysis<CustomInvalidatingAnalysis>().hasValue());
147 }
148
TEST(AnalysisManagerTest,OpSpecificAnalysis)149 TEST(AnalysisManagerTest, OpSpecificAnalysis) {
150 MLIRContext context;
151
152 // Create a module.
153 OwningModuleRef module(ModuleOp::create(UnknownLoc::get(&context)));
154 ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr);
155 AnalysisManager am = mam;
156
157 // Query the op specific analysis for the module and verify that its cached.
158 am.getAnalysis<OpSpecificAnalysis, ModuleOp>();
159 EXPECT_TRUE(am.getCachedAnalysis<OpSpecificAnalysis>().hasValue());
160 }
161
162 } // end namespace
163