1 //===- llvm/unittest/IR/PassManager.cpp - PassManager 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 "llvm/IR/PassManager.h"
10 #include "llvm/AsmParser/Parser.h"
11 #include "llvm/IR/Function.h"
12 #include "llvm/IR/LLVMContext.h"
13 #include "llvm/IR/Module.h"
14 #include "llvm/IR/PassManagerImpl.h"
15 #include "llvm/Support/SourceMgr.h"
16 #include "gtest/gtest.h"
17
18 using namespace llvm;
19
20 namespace {
21
22 class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> {
23 public:
24 struct Result {
Result__anone9858d360111::TestFunctionAnalysis::Result25 Result(int Count) : InstructionCount(Count) {}
26 int InstructionCount;
invalidate__anone9858d360111::TestFunctionAnalysis::Result27 bool invalidate(Function &, const PreservedAnalyses &PA,
28 FunctionAnalysisManager::Invalidator &) {
29 // Check whether the analysis or all analyses on functions have been
30 // preserved.
31 auto PAC = PA.getChecker<TestFunctionAnalysis>();
32 return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>());
33 }
34 };
35
TestFunctionAnalysis(int & Runs)36 TestFunctionAnalysis(int &Runs) : Runs(Runs) {}
37
38 /// Run the analysis pass over the function and return a result.
run(Function & F,FunctionAnalysisManager & AM)39 Result run(Function &F, FunctionAnalysisManager &AM) {
40 ++Runs;
41 int Count = 0;
42 for (Function::iterator BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI)
43 for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE;
44 ++II)
45 ++Count;
46 return Result(Count);
47 }
48
49 private:
50 friend AnalysisInfoMixin<TestFunctionAnalysis>;
51 static AnalysisKey Key;
52
53 int &Runs;
54 };
55
56 AnalysisKey TestFunctionAnalysis::Key;
57
58 class TestModuleAnalysis : public AnalysisInfoMixin<TestModuleAnalysis> {
59 public:
60 struct Result {
Result__anone9858d360111::TestModuleAnalysis::Result61 Result(int Count) : FunctionCount(Count) {}
62 int FunctionCount;
invalidate__anone9858d360111::TestModuleAnalysis::Result63 bool invalidate(Module &, const PreservedAnalyses &PA,
64 ModuleAnalysisManager::Invalidator &) {
65 // Check whether the analysis or all analyses on modules have been
66 // preserved.
67 auto PAC = PA.getChecker<TestModuleAnalysis>();
68 return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Module>>());
69 }
70 };
71
TestModuleAnalysis(int & Runs)72 TestModuleAnalysis(int &Runs) : Runs(Runs) {}
73
run(Module & M,ModuleAnalysisManager & AM)74 Result run(Module &M, ModuleAnalysisManager &AM) {
75 ++Runs;
76 int Count = 0;
77 for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
78 ++Count;
79 return Result(Count);
80 }
81
82 private:
83 friend AnalysisInfoMixin<TestModuleAnalysis>;
84 static AnalysisKey Key;
85
86 int &Runs;
87 };
88
89 AnalysisKey TestModuleAnalysis::Key;
90
91 struct TestModulePass : PassInfoMixin<TestModulePass> {
TestModulePass__anone9858d360111::TestModulePass92 TestModulePass(int &RunCount) : RunCount(RunCount) {}
93
run__anone9858d360111::TestModulePass94 PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
95 ++RunCount;
96 return PreservedAnalyses::none();
97 }
98
99 int &RunCount;
100 };
101
102 struct TestPreservingModulePass : PassInfoMixin<TestPreservingModulePass> {
run__anone9858d360111::TestPreservingModulePass103 PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
104 return PreservedAnalyses::all();
105 }
106 };
107
108 struct TestFunctionPass : PassInfoMixin<TestFunctionPass> {
TestFunctionPass__anone9858d360111::TestFunctionPass109 TestFunctionPass(int &RunCount, int &AnalyzedInstrCount,
110 int &AnalyzedFunctionCount, ModuleAnalysisManager &MAM,
111 bool OnlyUseCachedResults = false)
112 : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount),
113 AnalyzedFunctionCount(AnalyzedFunctionCount), MAM(MAM),
114 OnlyUseCachedResults(OnlyUseCachedResults) {}
115
run__anone9858d360111::TestFunctionPass116 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
117 ++RunCount;
118
119 // Getting a cached result that isn't stateless through the proxy will
120 // trigger an assert:
121 // auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
122 // Use MAM, for the purposes of this unittest.
123 if (TestModuleAnalysis::Result *TMA =
124 MAM.getCachedResult<TestModuleAnalysis>(*F.getParent())) {
125 AnalyzedFunctionCount += TMA->FunctionCount;
126 }
127
128 if (OnlyUseCachedResults) {
129 // Hack to force the use of the cached interface.
130 if (TestFunctionAnalysis::Result *AR =
131 AM.getCachedResult<TestFunctionAnalysis>(F))
132 AnalyzedInstrCount += AR->InstructionCount;
133 } else {
134 // Typical path just runs the analysis as needed.
135 TestFunctionAnalysis::Result &AR = AM.getResult<TestFunctionAnalysis>(F);
136 AnalyzedInstrCount += AR.InstructionCount;
137 }
138
139 return PreservedAnalyses::all();
140 }
141
142 int &RunCount;
143 int &AnalyzedInstrCount;
144 int &AnalyzedFunctionCount;
145 ModuleAnalysisManager &MAM;
146 bool OnlyUseCachedResults;
147 };
148
149 // A test function pass that invalidates all function analyses for a function
150 // with a specific name.
151 struct TestInvalidationFunctionPass
152 : PassInfoMixin<TestInvalidationFunctionPass> {
TestInvalidationFunctionPass__anone9858d360111::TestInvalidationFunctionPass153 TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {}
154
run__anone9858d360111::TestInvalidationFunctionPass155 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
156 return F.getName() == Name ? PreservedAnalyses::none()
157 : PreservedAnalyses::all();
158 }
159
160 StringRef Name;
161 };
162
parseIR(LLVMContext & Context,const char * IR)163 std::unique_ptr<Module> parseIR(LLVMContext &Context, const char *IR) {
164 SMDiagnostic Err;
165 return parseAssemblyString(IR, Err, Context);
166 }
167
168 class PassManagerTest : public ::testing::Test {
169 protected:
170 LLVMContext Context;
171 std::unique_ptr<Module> M;
172
173 public:
PassManagerTest()174 PassManagerTest()
175 : M(parseIR(Context, "define void @f() {\n"
176 "entry:\n"
177 " call void @g()\n"
178 " call void @h()\n"
179 " ret void\n"
180 "}\n"
181 "define void @g() {\n"
182 " ret void\n"
183 "}\n"
184 "define void @h() {\n"
185 " ret void\n"
186 "}\n")) {}
187 };
188
TEST(PreservedAnalysesTest,Basic)189 TEST(PreservedAnalysesTest, Basic) {
190 PreservedAnalyses PA1 = PreservedAnalyses();
191 {
192 auto PAC = PA1.getChecker<TestFunctionAnalysis>();
193 EXPECT_FALSE(PAC.preserved());
194 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>());
195 }
196 {
197 auto PAC = PA1.getChecker<TestModuleAnalysis>();
198 EXPECT_FALSE(PAC.preserved());
199 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Module>>());
200 }
201 auto PA2 = PreservedAnalyses::none();
202 {
203 auto PAC = PA2.getChecker<TestFunctionAnalysis>();
204 EXPECT_FALSE(PAC.preserved());
205 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>());
206 }
207 auto PA3 = PreservedAnalyses::all();
208 {
209 auto PAC = PA3.getChecker<TestFunctionAnalysis>();
210 EXPECT_TRUE(PAC.preserved());
211 EXPECT_TRUE(PAC.preservedSet<AllAnalysesOn<Function>>());
212 }
213 PreservedAnalyses PA4 = PA1;
214 {
215 auto PAC = PA4.getChecker<TestFunctionAnalysis>();
216 EXPECT_FALSE(PAC.preserved());
217 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>());
218 }
219 PA4 = PA3;
220 {
221 auto PAC = PA4.getChecker<TestFunctionAnalysis>();
222 EXPECT_TRUE(PAC.preserved());
223 EXPECT_TRUE(PAC.preservedSet<AllAnalysesOn<Function>>());
224 }
225 PA4 = std::move(PA2);
226 {
227 auto PAC = PA4.getChecker<TestFunctionAnalysis>();
228 EXPECT_FALSE(PAC.preserved());
229 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>());
230 }
231 auto PA5 = PreservedAnalyses::allInSet<AllAnalysesOn<Function>>();
232 {
233 auto PAC = PA5.getChecker<TestFunctionAnalysis>();
234 EXPECT_FALSE(PAC.preserved());
235 EXPECT_TRUE(PAC.preservedSet<AllAnalysesOn<Function>>());
236 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Module>>());
237 }
238 }
239
TEST(PreservedAnalysesTest,Preserve)240 TEST(PreservedAnalysesTest, Preserve) {
241 auto PA = PreservedAnalyses::none();
242 PA.preserve<TestFunctionAnalysis>();
243 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>().preserved());
244 EXPECT_FALSE(PA.getChecker<TestModuleAnalysis>().preserved());
245 PA.preserve<TestModuleAnalysis>();
246 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>().preserved());
247 EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>().preserved());
248
249 // Redundant calls are fine.
250 PA.preserve<TestFunctionAnalysis>();
251 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>().preserved());
252 EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>().preserved());
253 }
254
TEST(PreservedAnalysesTest,PreserveSets)255 TEST(PreservedAnalysesTest, PreserveSets) {
256 auto PA = PreservedAnalyses::none();
257 PA.preserveSet<AllAnalysesOn<Function>>();
258 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>()
259 .preservedSet<AllAnalysesOn<Function>>());
260 EXPECT_FALSE(PA.getChecker<TestModuleAnalysis>()
261 .preservedSet<AllAnalysesOn<Module>>());
262 PA.preserveSet<AllAnalysesOn<Module>>();
263 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>()
264 .preservedSet<AllAnalysesOn<Function>>());
265 EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>()
266 .preservedSet<AllAnalysesOn<Module>>());
267
268 // Mixing is fine.
269 PA.preserve<TestFunctionAnalysis>();
270 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>()
271 .preservedSet<AllAnalysesOn<Function>>());
272 EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>()
273 .preservedSet<AllAnalysesOn<Module>>());
274
275 // Redundant calls are fine.
276 PA.preserveSet<AllAnalysesOn<Module>>();
277 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>()
278 .preservedSet<AllAnalysesOn<Function>>());
279 EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>()
280 .preservedSet<AllAnalysesOn<Module>>());
281 }
282
TEST(PreservedAnalysisTest,Intersect)283 TEST(PreservedAnalysisTest, Intersect) {
284 // Setup the initial sets.
285 auto PA1 = PreservedAnalyses::none();
286 PA1.preserve<TestFunctionAnalysis>();
287 PA1.preserveSet<AllAnalysesOn<Module>>();
288 auto PA2 = PreservedAnalyses::none();
289 PA2.preserve<TestFunctionAnalysis>();
290 PA2.preserveSet<AllAnalysesOn<Function>>();
291 PA2.preserve<TestModuleAnalysis>();
292 PA2.preserveSet<AllAnalysesOn<Module>>();
293 auto PA3 = PreservedAnalyses::none();
294 PA3.preserve<TestModuleAnalysis>();
295 PA3.preserveSet<AllAnalysesOn<Function>>();
296
297 // Self intersection is a no-op.
298 auto Intersected = PA1;
299 Intersected.intersect(PA1);
300 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
301 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
302 .preservedSet<AllAnalysesOn<Function>>());
303 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
304 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>()
305 .preservedSet<AllAnalysesOn<Module>>());
306
307 // Intersecting with all is a no-op.
308 Intersected.intersect(PreservedAnalyses::all());
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 a narrow set with a more broad set is the narrow set.
317 Intersected.intersect(PA2);
318 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
319 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
320 .preservedSet<AllAnalysesOn<Function>>());
321 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
322 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>()
323 .preservedSet<AllAnalysesOn<Module>>());
324
325 // Intersecting a broad set with a more narrow set is the narrow set.
326 Intersected = PA2;
327 Intersected.intersect(PA1);
328 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
329 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
330 .preservedSet<AllAnalysesOn<Function>>());
331 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
332 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>()
333 .preservedSet<AllAnalysesOn<Module>>());
334
335 // Intersecting with empty clears.
336 Intersected.intersect(PreservedAnalyses::none());
337 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
338 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
339 .preservedSet<AllAnalysesOn<Function>>());
340 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
341 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>()
342 .preservedSet<AllAnalysesOn<Module>>());
343
344 // Intersecting non-overlapping clears.
345 Intersected = PA1;
346 Intersected.intersect(PA3);
347 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
348 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
349 .preservedSet<AllAnalysesOn<Function>>());
350 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
351 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>()
352 .preservedSet<AllAnalysesOn<Module>>());
353
354 // Intersecting with moves works in when there is storage on both sides.
355 Intersected = PA1;
356 auto Tmp = PA2;
357 Intersected.intersect(std::move(Tmp));
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 // Intersecting with move works for incoming all and existing all.
366 auto Tmp2 = PreservedAnalyses::all();
367 Intersected.intersect(std::move(Tmp2));
368 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
369 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
370 .preservedSet<AllAnalysesOn<Function>>());
371 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
372 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>()
373 .preservedSet<AllAnalysesOn<Module>>());
374 Intersected = PreservedAnalyses::all();
375 auto Tmp3 = PA1;
376 Intersected.intersect(std::move(Tmp3));
377 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
378 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
379 .preservedSet<AllAnalysesOn<Function>>());
380 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
381 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>()
382 .preservedSet<AllAnalysesOn<Module>>());
383 }
384
TEST(PreservedAnalysisTest,Abandon)385 TEST(PreservedAnalysisTest, Abandon) {
386 auto PA = PreservedAnalyses::none();
387
388 // We can abandon things after they are preserved.
389 PA.preserve<TestFunctionAnalysis>();
390 PA.abandon<TestFunctionAnalysis>();
391 EXPECT_FALSE(PA.getChecker<TestFunctionAnalysis>().preserved());
392
393 // Repeated is fine, and abandoning if they were never preserved is fine.
394 PA.abandon<TestFunctionAnalysis>();
395 EXPECT_FALSE(PA.getChecker<TestFunctionAnalysis>().preserved());
396 PA.abandon<TestModuleAnalysis>();
397 EXPECT_FALSE(PA.getChecker<TestModuleAnalysis>().preserved());
398
399 // Even if the sets are preserved, the abandoned analyses' checker won't
400 // return true for those sets.
401 PA.preserveSet<AllAnalysesOn<Function>>();
402 PA.preserveSet<AllAnalysesOn<Module>>();
403 EXPECT_FALSE(PA.getChecker<TestFunctionAnalysis>()
404 .preservedSet<AllAnalysesOn<Function>>());
405 EXPECT_FALSE(PA.getChecker<TestModuleAnalysis>()
406 .preservedSet<AllAnalysesOn<Module>>());
407
408 // But an arbitrary (opaque) analysis will still observe the sets as
409 // preserved. This also checks that we can use an explicit ID rather than
410 // a type.
411 AnalysisKey FakeKey, *FakeID = &FakeKey;
412 EXPECT_TRUE(PA.getChecker(FakeID).preservedSet<AllAnalysesOn<Function>>());
413 EXPECT_TRUE(PA.getChecker(FakeID).preservedSet<AllAnalysesOn<Module>>());
414 }
415
TEST_F(PassManagerTest,Basic)416 TEST_F(PassManagerTest, Basic) {
417 FunctionAnalysisManager FAM(/*DebugLogging*/ true);
418 int FunctionAnalysisRuns = 0;
419 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
420
421 ModuleAnalysisManager MAM(/*DebugLogging*/ true);
422 int ModuleAnalysisRuns = 0;
423 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
424 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
425 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
426
427 MAM.registerPass([&] { return PassInstrumentationAnalysis(); });
428 FAM.registerPass([&] { return PassInstrumentationAnalysis(); });
429
430 ModulePassManager MPM;
431
432 // Count the runs over a Function.
433 int FunctionPassRunCount1 = 0;
434 int AnalyzedInstrCount1 = 0;
435 int AnalyzedFunctionCount1 = 0;
436 {
437 // Pointless scoped copy to test move assignment.
438 ModulePassManager NestedMPM(/*DebugLogging*/ true);
439 FunctionPassManager FPM;
440 {
441 // Pointless scope to test move assignment.
442 FunctionPassManager NestedFPM(/*DebugLogging*/ true);
443 NestedFPM.addPass(TestFunctionPass(FunctionPassRunCount1,
444 AnalyzedInstrCount1,
445 AnalyzedFunctionCount1, MAM));
446 FPM = std::move(NestedFPM);
447 }
448 NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
449 MPM = std::move(NestedMPM);
450 }
451
452 // Count the runs over a module.
453 int ModulePassRunCount = 0;
454 MPM.addPass(TestModulePass(ModulePassRunCount));
455
456 // Count the runs over a Function in a separate manager.
457 int FunctionPassRunCount2 = 0;
458 int AnalyzedInstrCount2 = 0;
459 int AnalyzedFunctionCount2 = 0;
460 {
461 FunctionPassManager FPM(/*DebugLogging*/ true);
462 FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2,
463 AnalyzedFunctionCount2, MAM));
464 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
465 }
466
467 // A third function pass manager but with only preserving intervening passes
468 // and with a function pass that invalidates exactly one analysis.
469 MPM.addPass(TestPreservingModulePass());
470 int FunctionPassRunCount3 = 0;
471 int AnalyzedInstrCount3 = 0;
472 int AnalyzedFunctionCount3 = 0;
473 {
474 FunctionPassManager FPM(/*DebugLogging*/ true);
475 FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3,
476 AnalyzedFunctionCount3, MAM));
477 FPM.addPass(TestInvalidationFunctionPass("f"));
478 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
479 }
480
481 // A fourth function pass manager but with only preserving intervening
482 // passes but triggering the module analysis.
483 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
484 int FunctionPassRunCount4 = 0;
485 int AnalyzedInstrCount4 = 0;
486 int AnalyzedFunctionCount4 = 0;
487 {
488 FunctionPassManager FPM;
489 FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4,
490 AnalyzedFunctionCount4, MAM));
491 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
492 }
493
494 // A fifth function pass manager which invalidates one function first but
495 // uses only cached results.
496 int FunctionPassRunCount5 = 0;
497 int AnalyzedInstrCount5 = 0;
498 int AnalyzedFunctionCount5 = 0;
499 {
500 FunctionPassManager FPM(/*DebugLogging*/ true);
501 FPM.addPass(TestInvalidationFunctionPass("f"));
502 FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5,
503 AnalyzedFunctionCount5, MAM,
504 /*OnlyUseCachedResults=*/true));
505 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
506 }
507
508 MPM.run(*M, MAM);
509
510 // Validate module pass counters.
511 EXPECT_EQ(1, ModulePassRunCount);
512
513 // Validate all function pass counter sets are the same.
514 EXPECT_EQ(3, FunctionPassRunCount1);
515 EXPECT_EQ(5, AnalyzedInstrCount1);
516 EXPECT_EQ(0, AnalyzedFunctionCount1);
517 EXPECT_EQ(3, FunctionPassRunCount2);
518 EXPECT_EQ(5, AnalyzedInstrCount2);
519 EXPECT_EQ(0, AnalyzedFunctionCount2);
520 EXPECT_EQ(3, FunctionPassRunCount3);
521 EXPECT_EQ(5, AnalyzedInstrCount3);
522 EXPECT_EQ(0, AnalyzedFunctionCount3);
523 EXPECT_EQ(3, FunctionPassRunCount4);
524 EXPECT_EQ(5, AnalyzedInstrCount4);
525 EXPECT_EQ(9, AnalyzedFunctionCount4);
526 EXPECT_EQ(3, FunctionPassRunCount5);
527 EXPECT_EQ(2, AnalyzedInstrCount5); // Only 'g' and 'h' were cached.
528 EXPECT_EQ(9, AnalyzedFunctionCount5);
529
530 // Validate the analysis counters:
531 // first run over 3 functions, then module pass invalidates
532 // second run over 3 functions, nothing invalidates
533 // third run over 0 functions, but 1 function invalidated
534 // fourth run over 1 function
535 // fifth run invalidates 1 function first, but runs over 0 functions
536 EXPECT_EQ(7, FunctionAnalysisRuns);
537
538 EXPECT_EQ(1, ModuleAnalysisRuns);
539 }
540
541 // A customized pass manager that passes extra arguments through the
542 // infrastructure.
543 typedef AnalysisManager<Function, int> CustomizedAnalysisManager;
544 typedef PassManager<Function, CustomizedAnalysisManager, int, int &>
545 CustomizedPassManager;
546
547 class CustomizedAnalysis : public AnalysisInfoMixin<CustomizedAnalysis> {
548 public:
549 struct Result {
Result__anone9858d360111::CustomizedAnalysis::Result550 Result(int I) : I(I) {}
551 int I;
552 };
553
run(Function & F,CustomizedAnalysisManager & AM,int I)554 Result run(Function &F, CustomizedAnalysisManager &AM, int I) {
555 return Result(I);
556 }
557
558 private:
559 friend AnalysisInfoMixin<CustomizedAnalysis>;
560 static AnalysisKey Key;
561 };
562
563 AnalysisKey CustomizedAnalysis::Key;
564
565 struct CustomizedPass : PassInfoMixin<CustomizedPass> {
566 std::function<void(CustomizedAnalysis::Result &, int &)> Callback;
567
568 template <typename CallbackT>
CustomizedPass__anone9858d360111::CustomizedPass569 CustomizedPass(CallbackT Callback) : Callback(Callback) {}
570
run__anone9858d360111::CustomizedPass571 PreservedAnalyses run(Function &F, CustomizedAnalysisManager &AM, int I,
572 int &O) {
573 Callback(AM.getResult<CustomizedAnalysis>(F, I), O);
574 return PreservedAnalyses::none();
575 }
576 };
577
TEST_F(PassManagerTest,CustomizedPassManagerArgs)578 TEST_F(PassManagerTest, CustomizedPassManagerArgs) {
579 CustomizedAnalysisManager AM;
580 AM.registerPass([&] { return CustomizedAnalysis(); });
581 PassInstrumentationCallbacks PIC;
582 AM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); });
583
584 CustomizedPassManager PM;
585
586 // Add an instance of the customized pass that just accumulates the input
587 // after it is round-tripped through the analysis.
588 int Result = 0;
589 PM.addPass(
590 CustomizedPass([](CustomizedAnalysis::Result &R, int &O) { O += R.I; }));
591
592 // Run this over every function with the input of 42.
593 for (Function &F : *M)
594 PM.run(F, AM, 42, Result);
595
596 // And ensure that we accumulated the correct result.
597 EXPECT_EQ(42 * (int)M->size(), Result);
598 }
599
600 /// A test analysis pass which caches in its result another analysis pass and
601 /// uses it to serve queries. This requires the result to invalidate itself
602 /// when its dependency is invalidated.
603 struct TestIndirectFunctionAnalysis
604 : public AnalysisInfoMixin<TestIndirectFunctionAnalysis> {
605 struct Result {
Result__anone9858d360111::TestIndirectFunctionAnalysis::Result606 Result(TestFunctionAnalysis::Result &FDep, TestModuleAnalysis::Result &MDep)
607 : FDep(FDep), MDep(MDep) {}
608 TestFunctionAnalysis::Result &FDep;
609 TestModuleAnalysis::Result &MDep;
610
invalidate__anone9858d360111::TestIndirectFunctionAnalysis::Result611 bool invalidate(Function &F, const PreservedAnalyses &PA,
612 FunctionAnalysisManager::Invalidator &Inv) {
613 auto PAC = PA.getChecker<TestIndirectFunctionAnalysis>();
614 return !(PAC.preserved() ||
615 PAC.preservedSet<AllAnalysesOn<Function>>()) ||
616 Inv.invalidate<TestFunctionAnalysis>(F, PA);
617 }
618 };
619
TestIndirectFunctionAnalysis__anone9858d360111::TestIndirectFunctionAnalysis620 TestIndirectFunctionAnalysis(int &Runs, ModuleAnalysisManager &MAM)
621 : Runs(Runs), MAM(MAM) {}
622
623 /// Run the analysis pass over the function and return a result.
run__anone9858d360111::TestIndirectFunctionAnalysis624 Result run(Function &F, FunctionAnalysisManager &AM) {
625 ++Runs;
626 auto &FDep = AM.getResult<TestFunctionAnalysis>(F);
627 auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
628 // For the test, we insist that the module analysis starts off in the
629 // cache. Getting a cached result that isn't stateless trigger an assert.
630 // Use MAM, for the purposes of this unittest.
631 auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
632 // And register the dependency as module analysis dependencies have to be
633 // pre-registered on the proxy.
634 MAMProxy.registerOuterAnalysisInvalidation<TestModuleAnalysis,
635 TestIndirectFunctionAnalysis>();
636 return Result(FDep, MDep);
637 }
638
639 private:
640 friend AnalysisInfoMixin<TestIndirectFunctionAnalysis>;
641 static AnalysisKey Key;
642
643 int &Runs;
644 ModuleAnalysisManager &MAM;
645 };
646
647 AnalysisKey TestIndirectFunctionAnalysis::Key;
648
649 /// A test analysis pass which chaches in its result the result from the above
650 /// indirect analysis pass.
651 ///
652 /// This allows us to ensure that whenever an analysis pass is invalidated due
653 /// to dependencies (especially dependencies across IR units that trigger
654 /// asynchronous invalidation) we correctly detect that this may in turn cause
655 /// other analysis to be invalidated.
656 struct TestDoublyIndirectFunctionAnalysis
657 : public AnalysisInfoMixin<TestDoublyIndirectFunctionAnalysis> {
658 struct Result {
Result__anone9858d360111::TestDoublyIndirectFunctionAnalysis::Result659 Result(TestIndirectFunctionAnalysis::Result &IDep) : IDep(IDep) {}
660 TestIndirectFunctionAnalysis::Result &IDep;
661
invalidate__anone9858d360111::TestDoublyIndirectFunctionAnalysis::Result662 bool invalidate(Function &F, const PreservedAnalyses &PA,
663 FunctionAnalysisManager::Invalidator &Inv) {
664 auto PAC = PA.getChecker<TestDoublyIndirectFunctionAnalysis>();
665 return !(PAC.preserved() ||
666 PAC.preservedSet<AllAnalysesOn<Function>>()) ||
667 Inv.invalidate<TestIndirectFunctionAnalysis>(F, PA);
668 }
669 };
670
TestDoublyIndirectFunctionAnalysis__anone9858d360111::TestDoublyIndirectFunctionAnalysis671 TestDoublyIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {}
672
673 /// Run the analysis pass over the function and return a result.
run__anone9858d360111::TestDoublyIndirectFunctionAnalysis674 Result run(Function &F, FunctionAnalysisManager &AM) {
675 ++Runs;
676 auto &IDep = AM.getResult<TestIndirectFunctionAnalysis>(F);
677 return Result(IDep);
678 }
679
680 private:
681 friend AnalysisInfoMixin<TestDoublyIndirectFunctionAnalysis>;
682 static AnalysisKey Key;
683
684 int &Runs;
685 };
686
687 AnalysisKey TestDoublyIndirectFunctionAnalysis::Key;
688
689 struct LambdaPass : public PassInfoMixin<LambdaPass> {
690 using FuncT = std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)>;
691
LambdaPass__anone9858d360111::LambdaPass692 LambdaPass(FuncT Func) : Func(std::move(Func)) {}
693
run__anone9858d360111::LambdaPass694 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
695 return Func(F, AM);
696 }
697
698 FuncT Func;
699 };
700
TEST_F(PassManagerTest,IndirectAnalysisInvalidation)701 TEST_F(PassManagerTest, IndirectAnalysisInvalidation) {
702 FunctionAnalysisManager FAM(/*DebugLogging*/ true);
703 ModuleAnalysisManager MAM(/*DebugLogging*/ true);
704 int FunctionAnalysisRuns = 0, ModuleAnalysisRuns = 0,
705 IndirectAnalysisRuns = 0, DoublyIndirectAnalysisRuns = 0;
706 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
707 FAM.registerPass(
708 [&] { return TestIndirectFunctionAnalysis(IndirectAnalysisRuns, MAM); });
709 FAM.registerPass([&] {
710 return TestDoublyIndirectFunctionAnalysis(DoublyIndirectAnalysisRuns);
711 });
712
713 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
714 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
715 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
716
717 PassInstrumentationCallbacks PIC;
718 MAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); });
719 FAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); });
720
721 int InstrCount = 0, FunctionCount = 0;
722 ModulePassManager MPM(/*DebugLogging*/ true);
723 FunctionPassManager FPM(/*DebugLogging*/ true);
724 // First just use the analysis to get the instruction count, and preserve
725 // everything.
726 FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) {
727 auto &DoublyIndirectResult =
728 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F);
729 auto &IndirectResult = DoublyIndirectResult.IDep;
730 InstrCount += IndirectResult.FDep.InstructionCount;
731 FunctionCount += IndirectResult.MDep.FunctionCount;
732 return PreservedAnalyses::all();
733 }));
734 // Next, invalidate
735 // - both analyses for "f",
736 // - just the underlying (indirect) analysis for "g", and
737 // - just the direct analysis for "h".
738 FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) {
739 auto &DoublyIndirectResult =
740 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F);
741 auto &IndirectResult = DoublyIndirectResult.IDep;
742 InstrCount += IndirectResult.FDep.InstructionCount;
743 FunctionCount += IndirectResult.MDep.FunctionCount;
744 auto PA = PreservedAnalyses::none();
745 if (F.getName() == "g")
746 PA.preserve<TestFunctionAnalysis>();
747 else if (F.getName() == "h")
748 PA.preserve<TestIndirectFunctionAnalysis>();
749 return PA;
750 }));
751 // Finally, use the analysis again on each function, forcing re-computation
752 // for all of them.
753 FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) {
754 auto &DoublyIndirectResult =
755 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F);
756 auto &IndirectResult = DoublyIndirectResult.IDep;
757 InstrCount += IndirectResult.FDep.InstructionCount;
758 FunctionCount += IndirectResult.MDep.FunctionCount;
759 return PreservedAnalyses::all();
760 }));
761
762 // Create a second function pass manager. This will cause the module-level
763 // invalidation to occur, which will force yet another invalidation of the
764 // indirect function-level analysis as the module analysis it depends on gets
765 // invalidated.
766 FunctionPassManager FPM2(/*DebugLogging*/ true);
767 FPM2.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) {
768 auto &DoublyIndirectResult =
769 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F);
770 auto &IndirectResult = DoublyIndirectResult.IDep;
771 InstrCount += IndirectResult.FDep.InstructionCount;
772 FunctionCount += IndirectResult.MDep.FunctionCount;
773 return PreservedAnalyses::all();
774 }));
775
776 // Add a requires pass to populate the module analysis and then our function
777 // pass pipeline.
778 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
779 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
780 // Now require the module analysis again (it will have been invalidated once)
781 // and then use it again from a function pass manager.
782 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
783 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM2)));
784 MPM.run(*M, MAM);
785
786 // There are generally two possible runs for each of the three functions. But
787 // for one function, we only invalidate the indirect analysis so the base one
788 // only gets run five times.
789 EXPECT_EQ(5, FunctionAnalysisRuns);
790 // The module analysis pass should be run twice here.
791 EXPECT_EQ(2, ModuleAnalysisRuns);
792 // The indirect analysis is invalidated for each function (either directly or
793 // indirectly) and run twice for each.
794 EXPECT_EQ(9, IndirectAnalysisRuns);
795 EXPECT_EQ(9, DoublyIndirectAnalysisRuns);
796
797 // There are five instructions in the module and we add the count four
798 // times.
799 EXPECT_EQ(5 * 4, InstrCount);
800
801 // There are three functions and we count them four times for each of the
802 // three functions.
803 EXPECT_EQ(3 * 4 * 3, FunctionCount);
804 }
805 }
806