blob: 304803d40814a38e5f19dc405a317faf5c548a82 [file] [log] [blame]
Chandler Carruth90a835d2013-11-09 13:09:08 +00001//===- llvm/unittest/IR/PassManager.cpp - PassManager tests ---------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Chandler Carruth90a835d2013-11-09 13:09:08 +00006//
7//===----------------------------------------------------------------------===//
8
Chandler Carruth9a67b072017-06-06 11:06:56 +00009#include "llvm/IR/PassManager.h"
Chandler Carruth9aca9182014-01-07 12:34:26 +000010#include "llvm/AsmParser/Parser.h"
Chandler Carruth90a835d2013-11-09 13:09:08 +000011#include "llvm/IR/Function.h"
12#include "llvm/IR/LLVMContext.h"
13#include "llvm/IR/Module.h"
Chandler Carruth90a835d2013-11-09 13:09:08 +000014#include "llvm/Support/SourceMgr.h"
15#include "gtest/gtest.h"
16
17using namespace llvm;
18
19namespace {
20
Chandler Carruth30a07302016-03-11 10:33:22 +000021class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> {
Chandler Carruth74015a72013-11-13 01:12:08 +000022public:
Chandler Carruth74015a72013-11-13 01:12:08 +000023 struct Result {
24 Result(int Count) : InstructionCount(Count) {}
Chandler Carruth74015a72013-11-13 01:12:08 +000025 int InstructionCount;
26 };
27
Chandler Carruth2ad18582013-11-23 01:25:02 +000028 TestFunctionAnalysis(int &Runs) : Runs(Runs) {}
Chandler Carruth851a2aa2013-11-21 02:11:31 +000029
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000030 /// Run the analysis pass over the function and return a result.
Chandler Carruthb47f8012016-03-11 11:05:24 +000031 Result run(Function &F, FunctionAnalysisManager &AM) {
Chandler Carruth851a2aa2013-11-21 02:11:31 +000032 ++Runs;
Chandler Carruth74015a72013-11-13 01:12:08 +000033 int Count = 0;
Chandler Carruthd174ce42015-01-05 02:47:05 +000034 for (Function::iterator BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI)
Chandler Carruth74015a72013-11-13 01:12:08 +000035 for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE;
36 ++II)
37 ++Count;
38 return Result(Count);
39 }
40
41private:
Chandler Carruth30a07302016-03-11 10:33:22 +000042 friend AnalysisInfoMixin<TestFunctionAnalysis>;
Chandler Carruthdab4eae2016-11-23 17:53:26 +000043 static AnalysisKey Key;
Chandler Carruthb4faf132016-03-11 10:22:49 +000044
Chandler Carruth851a2aa2013-11-21 02:11:31 +000045 int &Runs;
Chandler Carruth74015a72013-11-13 01:12:08 +000046};
47
Chandler Carruthdab4eae2016-11-23 17:53:26 +000048AnalysisKey TestFunctionAnalysis::Key;
Chandler Carruthb4faf132016-03-11 10:22:49 +000049
Chandler Carruth30a07302016-03-11 10:33:22 +000050class TestModuleAnalysis : public AnalysisInfoMixin<TestModuleAnalysis> {
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +000051public:
52 struct Result {
53 Result(int Count) : FunctionCount(Count) {}
54 int FunctionCount;
55 };
56
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +000057 TestModuleAnalysis(int &Runs) : Runs(Runs) {}
58
Chandler Carruthb47f8012016-03-11 11:05:24 +000059 Result run(Module &M, ModuleAnalysisManager &AM) {
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +000060 ++Runs;
61 int Count = 0;
Chandler Carruthd174ce42015-01-05 02:47:05 +000062 for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +000063 ++Count;
64 return Result(Count);
65 }
66
67private:
Chandler Carruth30a07302016-03-11 10:33:22 +000068 friend AnalysisInfoMixin<TestModuleAnalysis>;
Chandler Carruthdab4eae2016-11-23 17:53:26 +000069 static AnalysisKey Key;
Chandler Carruthb4faf132016-03-11 10:22:49 +000070
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +000071 int &Runs;
72};
73
Chandler Carruthdab4eae2016-11-23 17:53:26 +000074AnalysisKey TestModuleAnalysis::Key;
Chandler Carruthb4faf132016-03-11 10:22:49 +000075
Chandler Carruth30a07302016-03-11 10:33:22 +000076struct TestModulePass : PassInfoMixin<TestModulePass> {
Chandler Carruth90a835d2013-11-09 13:09:08 +000077 TestModulePass(int &RunCount) : RunCount(RunCount) {}
78
Chandler Carruth164a2aa62016-06-17 00:11:01 +000079 PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
Chandler Carruth90a835d2013-11-09 13:09:08 +000080 ++RunCount;
Chandler Carruthc0bfa8c2013-11-20 11:31:50 +000081 return PreservedAnalyses::none();
Chandler Carruth90a835d2013-11-09 13:09:08 +000082 }
83
84 int &RunCount;
85};
86
Chandler Carruth30a07302016-03-11 10:33:22 +000087struct TestPreservingModulePass : PassInfoMixin<TestPreservingModulePass> {
Chandler Carruth164a2aa62016-06-17 00:11:01 +000088 PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
89 return PreservedAnalyses::all();
90 }
Chandler Carruth2846e9e2013-11-21 10:53:05 +000091};
92
Chandler Carruth30a07302016-03-11 10:33:22 +000093struct TestFunctionPass : PassInfoMixin<TestFunctionPass> {
Chandler Carruthde9afd82013-11-23 00:38:42 +000094 TestFunctionPass(int &RunCount, int &AnalyzedInstrCount,
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +000095 int &AnalyzedFunctionCount,
Chandler Carruthde9afd82013-11-23 00:38:42 +000096 bool OnlyUseCachedResults = false)
97 : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount),
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +000098 AnalyzedFunctionCount(AnalyzedFunctionCount),
Chandler Carruthde9afd82013-11-23 00:38:42 +000099 OnlyUseCachedResults(OnlyUseCachedResults) {}
Chandler Carruth90a835d2013-11-09 13:09:08 +0000100
Chandler Carruthb47f8012016-03-11 11:05:24 +0000101 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
Chandler Carruth90a835d2013-11-09 13:09:08 +0000102 ++RunCount;
Chandler Carruth74015a72013-11-13 01:12:08 +0000103
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000104 const ModuleAnalysisManager &MAM =
Chandler Carruthb47f8012016-03-11 11:05:24 +0000105 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
Chandler Carrutheedf9fc2014-02-05 21:41:42 +0000106 if (TestModuleAnalysis::Result *TMA =
Chandler Carruthd174ce42015-01-05 02:47:05 +0000107 MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()))
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000108 AnalyzedFunctionCount += TMA->FunctionCount;
109
Chandler Carruthde9afd82013-11-23 00:38:42 +0000110 if (OnlyUseCachedResults) {
111 // Hack to force the use of the cached interface.
Chandler Carrutheedf9fc2014-02-05 21:41:42 +0000112 if (TestFunctionAnalysis::Result *AR =
Chandler Carruthb47f8012016-03-11 11:05:24 +0000113 AM.getCachedResult<TestFunctionAnalysis>(F))
Chandler Carruthde9afd82013-11-23 00:38:42 +0000114 AnalyzedInstrCount += AR->InstructionCount;
115 } else {
116 // Typical path just runs the analysis as needed.
Chandler Carruthb47f8012016-03-11 11:05:24 +0000117 TestFunctionAnalysis::Result &AR = AM.getResult<TestFunctionAnalysis>(F);
Chandler Carruthde9afd82013-11-23 00:38:42 +0000118 AnalyzedInstrCount += AR.InstructionCount;
119 }
Chandler Carruth74015a72013-11-13 01:12:08 +0000120
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000121 return PreservedAnalyses::all();
Chandler Carruth90a835d2013-11-09 13:09:08 +0000122 }
123
124 int &RunCount;
Chandler Carruth74015a72013-11-13 01:12:08 +0000125 int &AnalyzedInstrCount;
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000126 int &AnalyzedFunctionCount;
Chandler Carruthde9afd82013-11-23 00:38:42 +0000127 bool OnlyUseCachedResults;
Chandler Carruth90a835d2013-11-09 13:09:08 +0000128};
129
Chandler Carruthbceeb222013-11-22 23:38:07 +0000130// A test function pass that invalidates all function analyses for a function
131// with a specific name.
Chandler Carruth30a07302016-03-11 10:33:22 +0000132struct TestInvalidationFunctionPass
133 : PassInfoMixin<TestInvalidationFunctionPass> {
Chandler Carruthbceeb222013-11-22 23:38:07 +0000134 TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {}
135
Chandler Carruth164a2aa62016-06-17 00:11:01 +0000136 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
Chandler Carruthd174ce42015-01-05 02:47:05 +0000137 return F.getName() == Name ? PreservedAnalyses::none()
138 : PreservedAnalyses::all();
Chandler Carruthbceeb222013-11-22 23:38:07 +0000139 }
140
141 StringRef Name;
142};
143
Mehdi Amini03b42e42016-04-14 21:59:01 +0000144std::unique_ptr<Module> parseIR(LLVMContext &Context, const char *IR) {
Chandler Carruth90a835d2013-11-09 13:09:08 +0000145 SMDiagnostic Err;
Mehdi Amini03b42e42016-04-14 21:59:01 +0000146 return parseAssemblyString(IR, Err, Context);
Chandler Carruth90a835d2013-11-09 13:09:08 +0000147}
148
149class PassManagerTest : public ::testing::Test {
150protected:
Mehdi Amini03b42e42016-04-14 21:59:01 +0000151 LLVMContext Context;
Ahmed Charles56440fd2014-03-06 05:51:42 +0000152 std::unique_ptr<Module> M;
Chandler Carruth90a835d2013-11-09 13:09:08 +0000153
154public:
155 PassManagerTest()
Mehdi Amini03b42e42016-04-14 21:59:01 +0000156 : M(parseIR(Context, "define void @f() {\n"
157 "entry:\n"
158 " call void @g()\n"
159 " call void @h()\n"
160 " ret void\n"
161 "}\n"
162 "define void @g() {\n"
163 " ret void\n"
164 "}\n"
165 "define void @h() {\n"
166 " ret void\n"
167 "}\n")) {}
Chandler Carruth90a835d2013-11-09 13:09:08 +0000168};
169
Chandler Carruthba90ae92016-12-27 08:40:39 +0000170TEST(PreservedAnalysesTest, Basic) {
Chandler Carruth999b92d2014-03-13 10:42:18 +0000171 PreservedAnalyses PA1 = PreservedAnalyses();
Chandler Carruthba90ae92016-12-27 08:40:39 +0000172 {
173 auto PAC = PA1.getChecker<TestFunctionAnalysis>();
174 EXPECT_FALSE(PAC.preserved());
175 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>());
176 }
177 {
178 auto PAC = PA1.getChecker<TestModuleAnalysis>();
179 EXPECT_FALSE(PAC.preserved());
180 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Module>>());
181 }
182 auto PA2 = PreservedAnalyses::none();
183 {
184 auto PAC = PA2.getChecker<TestFunctionAnalysis>();
185 EXPECT_FALSE(PAC.preserved());
186 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>());
187 }
188 auto PA3 = PreservedAnalyses::all();
189 {
190 auto PAC = PA3.getChecker<TestFunctionAnalysis>();
191 EXPECT_TRUE(PAC.preserved());
192 EXPECT_TRUE(PAC.preservedSet<AllAnalysesOn<Function>>());
193 }
Chandler Carruth999b92d2014-03-13 10:42:18 +0000194 PreservedAnalyses PA4 = PA1;
Chandler Carruthba90ae92016-12-27 08:40:39 +0000195 {
196 auto PAC = PA4.getChecker<TestFunctionAnalysis>();
197 EXPECT_FALSE(PAC.preserved());
198 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>());
199 }
Chandler Carruth999b92d2014-03-13 10:42:18 +0000200 PA4 = PA3;
Chandler Carruthba90ae92016-12-27 08:40:39 +0000201 {
202 auto PAC = PA4.getChecker<TestFunctionAnalysis>();
203 EXPECT_TRUE(PAC.preserved());
204 EXPECT_TRUE(PAC.preservedSet<AllAnalysesOn<Function>>());
205 }
Chandler Carruth999b92d2014-03-13 10:42:18 +0000206 PA4 = std::move(PA2);
Chandler Carruthba90ae92016-12-27 08:40:39 +0000207 {
208 auto PAC = PA4.getChecker<TestFunctionAnalysis>();
209 EXPECT_FALSE(PAC.preserved());
210 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>());
211 }
Chandler Carruth9c350652017-07-09 07:23:27 +0000212 auto PA5 = PreservedAnalyses::allInSet<AllAnalysesOn<Function>>();
213 {
214 auto PAC = PA5.getChecker<TestFunctionAnalysis>();
215 EXPECT_FALSE(PAC.preserved());
216 EXPECT_TRUE(PAC.preservedSet<AllAnalysesOn<Function>>());
217 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Module>>());
218 }
Chandler Carruthba90ae92016-12-27 08:40:39 +0000219}
220
221TEST(PreservedAnalysesTest, Preserve) {
222 auto PA = PreservedAnalyses::none();
223 PA.preserve<TestFunctionAnalysis>();
224 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>().preserved());
225 EXPECT_FALSE(PA.getChecker<TestModuleAnalysis>().preserved());
226 PA.preserve<TestModuleAnalysis>();
227 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>().preserved());
228 EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>().preserved());
229
230 // Redundant calls are fine.
231 PA.preserve<TestFunctionAnalysis>();
232 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>().preserved());
233 EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>().preserved());
234}
235
236TEST(PreservedAnalysesTest, PreserveSets) {
237 auto PA = PreservedAnalyses::none();
238 PA.preserveSet<AllAnalysesOn<Function>>();
239 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>()
240 .preservedSet<AllAnalysesOn<Function>>());
241 EXPECT_FALSE(PA.getChecker<TestModuleAnalysis>()
242 .preservedSet<AllAnalysesOn<Module>>());
243 PA.preserveSet<AllAnalysesOn<Module>>();
244 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>()
245 .preservedSet<AllAnalysesOn<Function>>());
246 EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>()
247 .preservedSet<AllAnalysesOn<Module>>());
248
249 // Mixing is fine.
250 PA.preserve<TestFunctionAnalysis>();
251 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>()
252 .preservedSet<AllAnalysesOn<Function>>());
253 EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>()
254 .preservedSet<AllAnalysesOn<Module>>());
255
256 // Redundant calls are fine.
257 PA.preserveSet<AllAnalysesOn<Module>>();
258 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>()
259 .preservedSet<AllAnalysesOn<Function>>());
260 EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>()
261 .preservedSet<AllAnalysesOn<Module>>());
262}
263
264TEST(PreservedAnalysisTest, Intersect) {
265 // Setup the initial sets.
266 auto PA1 = PreservedAnalyses::none();
Chandler Carruth999b92d2014-03-13 10:42:18 +0000267 PA1.preserve<TestFunctionAnalysis>();
Chandler Carruthba90ae92016-12-27 08:40:39 +0000268 PA1.preserveSet<AllAnalysesOn<Module>>();
269 auto PA2 = PreservedAnalyses::none();
270 PA2.preserve<TestFunctionAnalysis>();
271 PA2.preserveSet<AllAnalysesOn<Function>>();
272 PA2.preserve<TestModuleAnalysis>();
273 PA2.preserveSet<AllAnalysesOn<Module>>();
274 auto PA3 = PreservedAnalyses::none();
275 PA3.preserve<TestModuleAnalysis>();
276 PA3.preserveSet<AllAnalysesOn<Function>>();
277
278 // Self intersection is a no-op.
279 auto Intersected = PA1;
280 Intersected.intersect(PA1);
281 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
282 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
283 .preservedSet<AllAnalysesOn<Function>>());
284 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
285 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>()
286 .preservedSet<AllAnalysesOn<Module>>());
287
288 // Intersecting with all is a no-op.
289 Intersected.intersect(PreservedAnalyses::all());
290 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
291 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
292 .preservedSet<AllAnalysesOn<Function>>());
293 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
294 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>()
295 .preservedSet<AllAnalysesOn<Module>>());
296
297 // Intersecting a narrow set with a more broad set is the narrow set.
298 Intersected.intersect(PA2);
299 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
300 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
301 .preservedSet<AllAnalysesOn<Function>>());
302 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
303 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>()
304 .preservedSet<AllAnalysesOn<Module>>());
305
306 // Intersecting a broad set with a more narrow set is the narrow set.
307 Intersected = PA2;
308 Intersected.intersect(PA1);
309 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
310 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
311 .preservedSet<AllAnalysesOn<Function>>());
312 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
313 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>()
314 .preservedSet<AllAnalysesOn<Module>>());
315
316 // Intersecting with empty clears.
317 Intersected.intersect(PreservedAnalyses::none());
318 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
319 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
320 .preservedSet<AllAnalysesOn<Function>>());
321 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
322 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>()
323 .preservedSet<AllAnalysesOn<Module>>());
324
325 // Intersecting non-overlapping clears.
326 Intersected = PA1;
327 Intersected.intersect(PA3);
328 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
329 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
330 .preservedSet<AllAnalysesOn<Function>>());
331 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
332 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>()
333 .preservedSet<AllAnalysesOn<Module>>());
334
335 // Intersecting with moves works in when there is storage on both sides.
336 Intersected = PA1;
337 auto Tmp = PA2;
338 Intersected.intersect(std::move(Tmp));
339 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
340 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
341 .preservedSet<AllAnalysesOn<Function>>());
342 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
343 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>()
344 .preservedSet<AllAnalysesOn<Module>>());
345
346 // Intersecting with move works for incoming all and existing all.
347 auto Tmp2 = PreservedAnalyses::all();
348 Intersected.intersect(std::move(Tmp2));
349 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
350 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
351 .preservedSet<AllAnalysesOn<Function>>());
352 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
353 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>()
354 .preservedSet<AllAnalysesOn<Module>>());
355 Intersected = PreservedAnalyses::all();
356 auto Tmp3 = PA1;
357 Intersected.intersect(std::move(Tmp3));
358 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
359 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
360 .preservedSet<AllAnalysesOn<Function>>());
361 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
362 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>()
363 .preservedSet<AllAnalysesOn<Module>>());
364}
365
366TEST(PreservedAnalysisTest, Abandon) {
367 auto PA = PreservedAnalyses::none();
368
369 // We can abandon things after they are preserved.
370 PA.preserve<TestFunctionAnalysis>();
371 PA.abandon<TestFunctionAnalysis>();
372 EXPECT_FALSE(PA.getChecker<TestFunctionAnalysis>().preserved());
373
374 // Repeated is fine, and abandoning if they were never preserved is fine.
375 PA.abandon<TestFunctionAnalysis>();
376 EXPECT_FALSE(PA.getChecker<TestFunctionAnalysis>().preserved());
377 PA.abandon<TestModuleAnalysis>();
378 EXPECT_FALSE(PA.getChecker<TestModuleAnalysis>().preserved());
379
380 // Even if the sets are preserved, the abandoned analyses' checker won't
381 // return true for those sets.
382 PA.preserveSet<AllAnalysesOn<Function>>();
383 PA.preserveSet<AllAnalysesOn<Module>>();
384 EXPECT_FALSE(PA.getChecker<TestFunctionAnalysis>()
385 .preservedSet<AllAnalysesOn<Function>>());
386 EXPECT_FALSE(PA.getChecker<TestModuleAnalysis>()
387 .preservedSet<AllAnalysesOn<Module>>());
388
389 // But an arbitrary (opaque) analysis will still observe the sets as
390 // preserved. This also checks that we can use an explicit ID rather than
391 // a type.
392 AnalysisKey FakeKey, *FakeID = &FakeKey;
393 EXPECT_TRUE(PA.getChecker(FakeID).preservedSet<AllAnalysesOn<Function>>());
394 EXPECT_TRUE(PA.getChecker(FakeID).preservedSet<AllAnalysesOn<Module>>());
Chandler Carruth999b92d2014-03-13 10:42:18 +0000395}
396
Chandler Carruth90a835d2013-11-09 13:09:08 +0000397TEST_F(PassManagerTest, Basic) {
Chandler Carruth6b981642016-12-10 06:34:44 +0000398 FunctionAnalysisManager FAM(/*DebugLogging*/ true);
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000399 int FunctionAnalysisRuns = 0;
Chandler Carruthedf59962016-02-18 09:45:17 +0000400 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
Chandler Carruth74015a72013-11-13 01:12:08 +0000401
Chandler Carruth6b981642016-12-10 06:34:44 +0000402 ModuleAnalysisManager MAM(/*DebugLogging*/ true);
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000403 int ModuleAnalysisRuns = 0;
Chandler Carruthedf59962016-02-18 09:45:17 +0000404 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
405 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
406 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000407
Fedor Sergeevee8d31c2018-09-20 17:08:45 +0000408 MAM.registerPass([&] { return PassInstrumentationAnalysis(); });
409 FAM.registerPass([&] { return PassInstrumentationAnalysis(); });
410
Chandler Carruthb3e72192013-11-22 00:43:29 +0000411 ModulePassManager MPM;
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000412
413 // Count the runs over a Function.
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000414 int FunctionPassRunCount1 = 0;
415 int AnalyzedInstrCount1 = 0;
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000416 int AnalyzedFunctionCount1 = 0;
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000417 {
Chandler Carruth999b92d2014-03-13 10:42:18 +0000418 // Pointless scoped copy to test move assignment.
Chandler Carruth6b981642016-12-10 06:34:44 +0000419 ModulePassManager NestedMPM(/*DebugLogging*/ true);
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000420 FunctionPassManager FPM;
Chandler Carruth999b92d2014-03-13 10:42:18 +0000421 {
422 // Pointless scope to test move assignment.
Chandler Carruth6b981642016-12-10 06:34:44 +0000423 FunctionPassManager NestedFPM(/*DebugLogging*/ true);
Chandler Carruth74a8a222016-06-17 07:15:29 +0000424 NestedFPM.addPass(TestFunctionPass(
425 FunctionPassRunCount1, AnalyzedInstrCount1, AnalyzedFunctionCount1));
Chandler Carruth999b92d2014-03-13 10:42:18 +0000426 FPM = std::move(NestedFPM);
427 }
428 NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
429 MPM = std::move(NestedMPM);
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000430 }
Chandler Carruth90a835d2013-11-09 13:09:08 +0000431
432 // Count the runs over a module.
433 int ModulePassRunCount = 0;
434 MPM.addPass(TestModulePass(ModulePassRunCount));
435
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000436 // Count the runs over a Function in a separate manager.
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000437 int FunctionPassRunCount2 = 0;
438 int AnalyzedInstrCount2 = 0;
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000439 int AnalyzedFunctionCount2 = 0;
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000440 {
Chandler Carruth6b981642016-12-10 06:34:44 +0000441 FunctionPassManager FPM(/*DebugLogging*/ true);
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000442 FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2,
443 AnalyzedFunctionCount2));
444 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
445 }
Chandler Carruth90a835d2013-11-09 13:09:08 +0000446
Chandler Carruthbceeb222013-11-22 23:38:07 +0000447 // A third function pass manager but with only preserving intervening passes
448 // and with a function pass that invalidates exactly one analysis.
Chandler Carruth2846e9e2013-11-21 10:53:05 +0000449 MPM.addPass(TestPreservingModulePass());
Chandler Carruth2846e9e2013-11-21 10:53:05 +0000450 int FunctionPassRunCount3 = 0;
451 int AnalyzedInstrCount3 = 0;
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000452 int AnalyzedFunctionCount3 = 0;
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000453 {
Chandler Carruth6b981642016-12-10 06:34:44 +0000454 FunctionPassManager FPM(/*DebugLogging*/ true);
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000455 FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3,
456 AnalyzedFunctionCount3));
457 FPM.addPass(TestInvalidationFunctionPass("f"));
458 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
459 }
Chandler Carruth2846e9e2013-11-21 10:53:05 +0000460
Chandler Carruth6b981642016-12-10 06:34:44 +0000461 // A fourth function pass manager but with only preserving intervening
462 // passes but triggering the module analysis.
463 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
Chandler Carruth2846e9e2013-11-21 10:53:05 +0000464 int FunctionPassRunCount4 = 0;
465 int AnalyzedInstrCount4 = 0;
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000466 int AnalyzedFunctionCount4 = 0;
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000467 {
468 FunctionPassManager FPM;
469 FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4,
470 AnalyzedFunctionCount4));
471 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
472 }
Chandler Carruth2846e9e2013-11-21 10:53:05 +0000473
Chandler Carruth6b981642016-12-10 06:34:44 +0000474 // A fifth function pass manager which invalidates one function first but
475 // uses only cached results.
Chandler Carruthde9afd82013-11-23 00:38:42 +0000476 int FunctionPassRunCount5 = 0;
477 int AnalyzedInstrCount5 = 0;
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000478 int AnalyzedFunctionCount5 = 0;
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000479 {
Chandler Carruth6b981642016-12-10 06:34:44 +0000480 FunctionPassManager FPM(/*DebugLogging*/ true);
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000481 FPM.addPass(TestInvalidationFunctionPass("f"));
482 FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5,
483 AnalyzedFunctionCount5,
484 /*OnlyUseCachedResults=*/true));
485 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
486 }
Chandler Carruthde9afd82013-11-23 00:38:42 +0000487
Chandler Carruthb47f8012016-03-11 11:05:24 +0000488 MPM.run(*M, MAM);
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000489
490 // Validate module pass counters.
Chandler Carruth90a835d2013-11-09 13:09:08 +0000491 EXPECT_EQ(1, ModulePassRunCount);
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000492
Chandler Carruthbceeb222013-11-22 23:38:07 +0000493 // Validate all function pass counter sets are the same.
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000494 EXPECT_EQ(3, FunctionPassRunCount1);
495 EXPECT_EQ(5, AnalyzedInstrCount1);
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000496 EXPECT_EQ(0, AnalyzedFunctionCount1);
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000497 EXPECT_EQ(3, FunctionPassRunCount2);
498 EXPECT_EQ(5, AnalyzedInstrCount2);
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000499 EXPECT_EQ(0, AnalyzedFunctionCount2);
Chandler Carruth2846e9e2013-11-21 10:53:05 +0000500 EXPECT_EQ(3, FunctionPassRunCount3);
501 EXPECT_EQ(5, AnalyzedInstrCount3);
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000502 EXPECT_EQ(0, AnalyzedFunctionCount3);
Chandler Carruth2846e9e2013-11-21 10:53:05 +0000503 EXPECT_EQ(3, FunctionPassRunCount4);
504 EXPECT_EQ(5, AnalyzedInstrCount4);
Chandler Carruth6b981642016-12-10 06:34:44 +0000505 EXPECT_EQ(9, AnalyzedFunctionCount4);
Chandler Carruthde9afd82013-11-23 00:38:42 +0000506 EXPECT_EQ(3, FunctionPassRunCount5);
507 EXPECT_EQ(2, AnalyzedInstrCount5); // Only 'g' and 'h' were cached.
Chandler Carruth6b981642016-12-10 06:34:44 +0000508 EXPECT_EQ(9, AnalyzedFunctionCount5);
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000509
Chandler Carruthbceeb222013-11-22 23:38:07 +0000510 // Validate the analysis counters:
511 // first run over 3 functions, then module pass invalidates
512 // second run over 3 functions, nothing invalidates
513 // third run over 0 functions, but 1 function invalidated
514 // fourth run over 1 function
Chandler Carruth6b981642016-12-10 06:34:44 +0000515 // fifth run invalidates 1 function first, but runs over 0 functions
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000516 EXPECT_EQ(7, FunctionAnalysisRuns);
517
518 EXPECT_EQ(1, ModuleAnalysisRuns);
Chandler Carruth90a835d2013-11-09 13:09:08 +0000519}
Chandler Carruth9b35e6d2016-08-19 18:36:06 +0000520
521// A customized pass manager that passes extra arguments through the
522// infrastructure.
523typedef AnalysisManager<Function, int> CustomizedAnalysisManager;
524typedef PassManager<Function, CustomizedAnalysisManager, int, int &>
525 CustomizedPassManager;
526
527class CustomizedAnalysis : public AnalysisInfoMixin<CustomizedAnalysis> {
528public:
529 struct Result {
530 Result(int I) : I(I) {}
531 int I;
532 };
533
534 Result run(Function &F, CustomizedAnalysisManager &AM, int I) {
535 return Result(I);
536 }
537
538private:
539 friend AnalysisInfoMixin<CustomizedAnalysis>;
Chandler Carruthdab4eae2016-11-23 17:53:26 +0000540 static AnalysisKey Key;
Chandler Carruth9b35e6d2016-08-19 18:36:06 +0000541};
542
Chandler Carruthdab4eae2016-11-23 17:53:26 +0000543AnalysisKey CustomizedAnalysis::Key;
Chandler Carruth9b35e6d2016-08-19 18:36:06 +0000544
545struct CustomizedPass : PassInfoMixin<CustomizedPass> {
546 std::function<void(CustomizedAnalysis::Result &, int &)> Callback;
547
548 template <typename CallbackT>
549 CustomizedPass(CallbackT Callback) : Callback(Callback) {}
550
551 PreservedAnalyses run(Function &F, CustomizedAnalysisManager &AM, int I,
552 int &O) {
553 Callback(AM.getResult<CustomizedAnalysis>(F, I), O);
554 return PreservedAnalyses::none();
555 }
556};
557
558TEST_F(PassManagerTest, CustomizedPassManagerArgs) {
559 CustomizedAnalysisManager AM;
560 AM.registerPass([&] { return CustomizedAnalysis(); });
Fedor Sergeevee8d31c2018-09-20 17:08:45 +0000561 PassInstrumentationCallbacks PIC;
562 AM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); });
Chandler Carruth9b35e6d2016-08-19 18:36:06 +0000563
564 CustomizedPassManager PM;
565
566 // Add an instance of the customized pass that just accumulates the input
567 // after it is round-tripped through the analysis.
568 int Result = 0;
569 PM.addPass(
570 CustomizedPass([](CustomizedAnalysis::Result &R, int &O) { O += R.I; }));
571
572 // Run this over every function with the input of 42.
573 for (Function &F : *M)
574 PM.run(F, AM, 42, Result);
575
576 // And ensure that we accumulated the correct result.
577 EXPECT_EQ(42 * (int)M->size(), Result);
578}
Chandler Carruth3ab2a5a2016-11-28 22:04:31 +0000579
580/// A test analysis pass which caches in its result another analysis pass and
581/// uses it to serve queries. This requires the result to invalidate itself
582/// when its dependency is invalidated.
583struct TestIndirectFunctionAnalysis
584 : public AnalysisInfoMixin<TestIndirectFunctionAnalysis> {
585 struct Result {
Chandler Carruthba90ae92016-12-27 08:40:39 +0000586 Result(TestFunctionAnalysis::Result &FDep, TestModuleAnalysis::Result &MDep)
587 : FDep(FDep), MDep(MDep) {}
588 TestFunctionAnalysis::Result &FDep;
589 TestModuleAnalysis::Result &MDep;
Chandler Carruth3ab2a5a2016-11-28 22:04:31 +0000590
591 bool invalidate(Function &F, const PreservedAnalyses &PA,
592 FunctionAnalysisManager::Invalidator &Inv) {
Chandler Carruthba90ae92016-12-27 08:40:39 +0000593 auto PAC = PA.getChecker<TestIndirectFunctionAnalysis>();
594 return !(PAC.preserved() ||
595 PAC.preservedSet<AllAnalysesOn<Function>>()) ||
Chandler Carruth3ab2a5a2016-11-28 22:04:31 +0000596 Inv.invalidate<TestFunctionAnalysis>(F, PA);
597 }
598 };
599
600 TestIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {}
601
602 /// Run the analysis pass over the function and return a result.
603 Result run(Function &F, FunctionAnalysisManager &AM) {
604 ++Runs;
Chandler Carruthba90ae92016-12-27 08:40:39 +0000605 auto &FDep = AM.getResult<TestFunctionAnalysis>(F);
606 auto &Proxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
607 const ModuleAnalysisManager &MAM = Proxy.getManager();
608 // For the test, we insist that the module analysis starts off in the
609 // cache.
610 auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
611 // And register the dependency as module analysis dependencies have to be
612 // pre-registered on the proxy.
613 Proxy.registerOuterAnalysisInvalidation<TestModuleAnalysis,
614 TestIndirectFunctionAnalysis>();
615 return Result(FDep, MDep);
Chandler Carruth3ab2a5a2016-11-28 22:04:31 +0000616 }
617
618private:
619 friend AnalysisInfoMixin<TestIndirectFunctionAnalysis>;
620 static AnalysisKey Key;
621
622 int &Runs;
623};
624
625AnalysisKey TestIndirectFunctionAnalysis::Key;
626
Chandler Carruthba90ae92016-12-27 08:40:39 +0000627/// A test analysis pass which chaches in its result the result from the above
628/// indirect analysis pass.
629///
630/// This allows us to ensure that whenever an analysis pass is invalidated due
631/// to dependencies (especially dependencies across IR units that trigger
632/// asynchronous invalidation) we correctly detect that this may in turn cause
633/// other analysis to be invalidated.
634struct TestDoublyIndirectFunctionAnalysis
635 : public AnalysisInfoMixin<TestDoublyIndirectFunctionAnalysis> {
636 struct Result {
637 Result(TestIndirectFunctionAnalysis::Result &IDep) : IDep(IDep) {}
638 TestIndirectFunctionAnalysis::Result &IDep;
639
640 bool invalidate(Function &F, const PreservedAnalyses &PA,
641 FunctionAnalysisManager::Invalidator &Inv) {
642 auto PAC = PA.getChecker<TestDoublyIndirectFunctionAnalysis>();
643 return !(PAC.preserved() ||
644 PAC.preservedSet<AllAnalysesOn<Function>>()) ||
645 Inv.invalidate<TestIndirectFunctionAnalysis>(F, PA);
646 }
647 };
648
649 TestDoublyIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {}
650
651 /// Run the analysis pass over the function and return a result.
652 Result run(Function &F, FunctionAnalysisManager &AM) {
653 ++Runs;
654 auto &IDep = AM.getResult<TestIndirectFunctionAnalysis>(F);
655 return Result(IDep);
656 }
657
658private:
659 friend AnalysisInfoMixin<TestDoublyIndirectFunctionAnalysis>;
660 static AnalysisKey Key;
661
662 int &Runs;
663};
664
665AnalysisKey TestDoublyIndirectFunctionAnalysis::Key;
666
Chandler Carruth3ab2a5a2016-11-28 22:04:31 +0000667struct LambdaPass : public PassInfoMixin<LambdaPass> {
668 using FuncT = std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)>;
669
670 LambdaPass(FuncT Func) : Func(std::move(Func)) {}
671
672 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
673 return Func(F, AM);
674 }
675
676 FuncT Func;
677};
678
679TEST_F(PassManagerTest, IndirectAnalysisInvalidation) {
680 FunctionAnalysisManager FAM(/*DebugLogging*/ true);
Chandler Carruthba90ae92016-12-27 08:40:39 +0000681 int FunctionAnalysisRuns = 0, ModuleAnalysisRuns = 0,
682 IndirectAnalysisRuns = 0, DoublyIndirectAnalysisRuns = 0;
683 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
Chandler Carruth3ab2a5a2016-11-28 22:04:31 +0000684 FAM.registerPass(
685 [&] { return TestIndirectFunctionAnalysis(IndirectAnalysisRuns); });
Chandler Carruthba90ae92016-12-27 08:40:39 +0000686 FAM.registerPass([&] {
687 return TestDoublyIndirectFunctionAnalysis(DoublyIndirectAnalysisRuns);
688 });
Chandler Carruth3ab2a5a2016-11-28 22:04:31 +0000689
690 ModuleAnalysisManager MAM(/*DebugLogging*/ true);
Chandler Carruthba90ae92016-12-27 08:40:39 +0000691 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
Chandler Carruth3ab2a5a2016-11-28 22:04:31 +0000692 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
693 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
694
Fedor Sergeevee8d31c2018-09-20 17:08:45 +0000695 PassInstrumentationCallbacks PIC;
696 MAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); });
697 FAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); });
698
Chandler Carruthba90ae92016-12-27 08:40:39 +0000699 int InstrCount = 0, FunctionCount = 0;
Chandler Carruth3ab2a5a2016-11-28 22:04:31 +0000700 ModulePassManager MPM(/*DebugLogging*/ true);
701 FunctionPassManager FPM(/*DebugLogging*/ true);
702 // First just use the analysis to get the instruction count, and preserve
703 // everything.
704 FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) {
Chandler Carruthba90ae92016-12-27 08:40:39 +0000705 auto &DoublyIndirectResult =
706 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F);
707 auto &IndirectResult = DoublyIndirectResult.IDep;
708 InstrCount += IndirectResult.FDep.InstructionCount;
709 FunctionCount += IndirectResult.MDep.FunctionCount;
Chandler Carruth3ab2a5a2016-11-28 22:04:31 +0000710 return PreservedAnalyses::all();
711 }));
712 // Next, invalidate
713 // - both analyses for "f",
714 // - just the underlying (indirect) analysis for "g", and
715 // - just the direct analysis for "h".
716 FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) {
Chandler Carruthba90ae92016-12-27 08:40:39 +0000717 auto &DoublyIndirectResult =
718 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F);
719 auto &IndirectResult = DoublyIndirectResult.IDep;
720 InstrCount += IndirectResult.FDep.InstructionCount;
721 FunctionCount += IndirectResult.MDep.FunctionCount;
Chandler Carruth3ab2a5a2016-11-28 22:04:31 +0000722 auto PA = PreservedAnalyses::none();
723 if (F.getName() == "g")
724 PA.preserve<TestFunctionAnalysis>();
725 else if (F.getName() == "h")
726 PA.preserve<TestIndirectFunctionAnalysis>();
727 return PA;
728 }));
729 // Finally, use the analysis again on each function, forcing re-computation
730 // for all of them.
731 FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) {
Chandler Carruthba90ae92016-12-27 08:40:39 +0000732 auto &DoublyIndirectResult =
733 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F);
734 auto &IndirectResult = DoublyIndirectResult.IDep;
735 InstrCount += IndirectResult.FDep.InstructionCount;
736 FunctionCount += IndirectResult.MDep.FunctionCount;
Chandler Carruth3ab2a5a2016-11-28 22:04:31 +0000737 return PreservedAnalyses::all();
738 }));
Chandler Carruthba90ae92016-12-27 08:40:39 +0000739
740 // Create a second function pass manager. This will cause the module-level
741 // invalidation to occur, which will force yet another invalidation of the
742 // indirect function-level analysis as the module analysis it depends on gets
743 // invalidated.
744 FunctionPassManager FPM2(/*DebugLogging*/ true);
745 FPM2.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) {
746 auto &DoublyIndirectResult =
747 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F);
748 auto &IndirectResult = DoublyIndirectResult.IDep;
749 InstrCount += IndirectResult.FDep.InstructionCount;
750 FunctionCount += IndirectResult.MDep.FunctionCount;
751 return PreservedAnalyses::all();
752 }));
753
754 // Add a requires pass to populate the module analysis and then our function
755 // pass pipeline.
756 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
Chandler Carruth3ab2a5a2016-11-28 22:04:31 +0000757 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
Chandler Carruthba90ae92016-12-27 08:40:39 +0000758 // Now require the module analysis again (it will have been invalidated once)
759 // and then use it again from a function pass manager.
760 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
761 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM2)));
Chandler Carruth3ab2a5a2016-11-28 22:04:31 +0000762 MPM.run(*M, MAM);
763
764 // There are generally two possible runs for each of the three functions. But
765 // for one function, we only invalidate the indirect analysis so the base one
766 // only gets run five times.
Chandler Carruthba90ae92016-12-27 08:40:39 +0000767 EXPECT_EQ(5, FunctionAnalysisRuns);
768 // The module analysis pass should be run twice here.
769 EXPECT_EQ(2, ModuleAnalysisRuns);
Chandler Carruth3ab2a5a2016-11-28 22:04:31 +0000770 // The indirect analysis is invalidated for each function (either directly or
771 // indirectly) and run twice for each.
Chandler Carruthba90ae92016-12-27 08:40:39 +0000772 EXPECT_EQ(9, IndirectAnalysisRuns);
773 EXPECT_EQ(9, DoublyIndirectAnalysisRuns);
Chandler Carruth3ab2a5a2016-11-28 22:04:31 +0000774
Chandler Carruthba90ae92016-12-27 08:40:39 +0000775 // There are five instructions in the module and we add the count four
Chandler Carruth3ab2a5a2016-11-28 22:04:31 +0000776 // times.
Chandler Carruthba90ae92016-12-27 08:40:39 +0000777 EXPECT_EQ(5 * 4, InstrCount);
778
779 // There are three functions and we count them four times for each of the
780 // three functions.
781 EXPECT_EQ(3 * 4 * 3, FunctionCount);
Chandler Carruth3ab2a5a2016-11-28 22:04:31 +0000782}
Chandler Carruth90a835d2013-11-09 13:09:08 +0000783}