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