Fix buildbot failures with the newly added test case (triple was missing).
[llvm-core.git] / unittests / IR / PassManagerTest.cpp
blob13b87f1022e5c853b8c6e8e28b527d89744988f7
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 //===----------------------------------------------------------------------===//
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"
18 using namespace llvm;
20 namespace {
22 class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> {
23 public:
24 struct Result {
25 Result(int Count) : InstructionCount(Count) {}
26 int InstructionCount;
29 TestFunctionAnalysis(int &Runs) : Runs(Runs) {}
31 /// Run the analysis pass over the function and return a result.
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);
42 private:
43 friend AnalysisInfoMixin<TestFunctionAnalysis>;
44 static AnalysisKey Key;
46 int &Runs;
49 AnalysisKey TestFunctionAnalysis::Key;
51 class TestModuleAnalysis : public AnalysisInfoMixin<TestModuleAnalysis> {
52 public:
53 struct Result {
54 Result(int Count) : FunctionCount(Count) {}
55 int FunctionCount;
58 TestModuleAnalysis(int &Runs) : Runs(Runs) {}
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);
68 private:
69 friend AnalysisInfoMixin<TestModuleAnalysis>;
70 static AnalysisKey Key;
72 int &Runs;
75 AnalysisKey TestModuleAnalysis::Key;
77 struct TestModulePass : PassInfoMixin<TestModulePass> {
78 TestModulePass(int &RunCount) : RunCount(RunCount) {}
80 PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
81 ++RunCount;
82 return PreservedAnalyses::none();
85 int &RunCount;
88 struct TestPreservingModulePass : PassInfoMixin<TestPreservingModulePass> {
89 PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
90 return PreservedAnalyses::all();
94 struct TestFunctionPass : PassInfoMixin<TestFunctionPass> {
95 TestFunctionPass(int &RunCount, int &AnalyzedInstrCount,
96 int &AnalyzedFunctionCount,
97 bool OnlyUseCachedResults = false)
98 : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount),
99 AnalyzedFunctionCount(AnalyzedFunctionCount),
100 OnlyUseCachedResults(OnlyUseCachedResults) {}
102 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
103 ++RunCount;
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;
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;
122 return PreservedAnalyses::all();
125 int &RunCount;
126 int &AnalyzedInstrCount;
127 int &AnalyzedFunctionCount;
128 bool OnlyUseCachedResults;
131 // A test function pass that invalidates all function analyses for a function
132 // with a specific name.
133 struct TestInvalidationFunctionPass
134 : PassInfoMixin<TestInvalidationFunctionPass> {
135 TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {}
137 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
138 return F.getName() == Name ? PreservedAnalyses::none()
139 : PreservedAnalyses::all();
142 StringRef Name;
145 std::unique_ptr<Module> parseIR(LLVMContext &Context, const char *IR) {
146 SMDiagnostic Err;
147 return parseAssemblyString(IR, Err, Context);
150 class PassManagerTest : public ::testing::Test {
151 protected:
152 LLVMContext Context;
153 std::unique_ptr<Module> M;
155 public:
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")) {}
171 TEST(PreservedAnalysesTest, Basic) {
172 PreservedAnalyses PA1 = PreservedAnalyses();
174 auto PAC = PA1.getChecker<TestFunctionAnalysis>();
175 EXPECT_FALSE(PAC.preserved());
176 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>());
179 auto PAC = PA1.getChecker<TestModuleAnalysis>();
180 EXPECT_FALSE(PAC.preserved());
181 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Module>>());
183 auto PA2 = PreservedAnalyses::none();
185 auto PAC = PA2.getChecker<TestFunctionAnalysis>();
186 EXPECT_FALSE(PAC.preserved());
187 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>());
189 auto PA3 = PreservedAnalyses::all();
191 auto PAC = PA3.getChecker<TestFunctionAnalysis>();
192 EXPECT_TRUE(PAC.preserved());
193 EXPECT_TRUE(PAC.preservedSet<AllAnalysesOn<Function>>());
195 PreservedAnalyses PA4 = PA1;
197 auto PAC = PA4.getChecker<TestFunctionAnalysis>();
198 EXPECT_FALSE(PAC.preserved());
199 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>());
201 PA4 = PA3;
203 auto PAC = PA4.getChecker<TestFunctionAnalysis>();
204 EXPECT_TRUE(PAC.preserved());
205 EXPECT_TRUE(PAC.preservedSet<AllAnalysesOn<Function>>());
207 PA4 = std::move(PA2);
209 auto PAC = PA4.getChecker<TestFunctionAnalysis>();
210 EXPECT_FALSE(PAC.preserved());
211 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>());
213 auto PA5 = PreservedAnalyses::allInSet<AllAnalysesOn<Function>>();
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>>());
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());
231 // Redundant calls are fine.
232 PA.preserve<TestFunctionAnalysis>();
233 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>().preserved());
234 EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>().preserved());
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>>());
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>>());
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>>());
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>>();
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>>());
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>>());
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>>());
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>>());
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>>());
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>>());
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>>());
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>>());
367 TEST(PreservedAnalysisTest, Abandon) {
368 auto PA = PreservedAnalyses::none();
370 // We can abandon things after they are preserved.
371 PA.preserve<TestFunctionAnalysis>();
372 PA.abandon<TestFunctionAnalysis>();
373 EXPECT_FALSE(PA.getChecker<TestFunctionAnalysis>().preserved());
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());
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>>());
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>>());
398 TEST_F(PassManagerTest, Basic) {
399 FunctionAnalysisManager FAM(/*DebugLogging*/ true);
400 int FunctionAnalysisRuns = 0;
401 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
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); });
409 MAM.registerPass([&] { return PassInstrumentationAnalysis(); });
410 FAM.registerPass([&] { return PassInstrumentationAnalysis(); });
412 ModulePassManager MPM;
414 // Count the runs over a Function.
415 int FunctionPassRunCount1 = 0;
416 int AnalyzedInstrCount1 = 0;
417 int AnalyzedFunctionCount1 = 0;
419 // Pointless scoped copy to test move assignment.
420 ModulePassManager NestedMPM(/*DebugLogging*/ true);
421 FunctionPassManager FPM;
423 // Pointless scope to test move assignment.
424 FunctionPassManager NestedFPM(/*DebugLogging*/ true);
425 NestedFPM.addPass(TestFunctionPass(
426 FunctionPassRunCount1, AnalyzedInstrCount1, AnalyzedFunctionCount1));
427 FPM = std::move(NestedFPM);
429 NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
430 MPM = std::move(NestedMPM);
433 // Count the runs over a module.
434 int ModulePassRunCount = 0;
435 MPM.addPass(TestModulePass(ModulePassRunCount));
437 // Count the runs over a Function in a separate manager.
438 int FunctionPassRunCount2 = 0;
439 int AnalyzedInstrCount2 = 0;
440 int AnalyzedFunctionCount2 = 0;
442 FunctionPassManager FPM(/*DebugLogging*/ true);
443 FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2,
444 AnalyzedFunctionCount2));
445 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
448 // A third function pass manager but with only preserving intervening passes
449 // and with a function pass that invalidates exactly one analysis.
450 MPM.addPass(TestPreservingModulePass());
451 int FunctionPassRunCount3 = 0;
452 int AnalyzedInstrCount3 = 0;
453 int AnalyzedFunctionCount3 = 0;
455 FunctionPassManager FPM(/*DebugLogging*/ true);
456 FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3,
457 AnalyzedFunctionCount3));
458 FPM.addPass(TestInvalidationFunctionPass("f"));
459 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
462 // A fourth function pass manager but with only preserving intervening
463 // passes but triggering the module analysis.
464 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
465 int FunctionPassRunCount4 = 0;
466 int AnalyzedInstrCount4 = 0;
467 int AnalyzedFunctionCount4 = 0;
469 FunctionPassManager FPM;
470 FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4,
471 AnalyzedFunctionCount4));
472 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
475 // A fifth function pass manager which invalidates one function first but
476 // uses only cached results.
477 int FunctionPassRunCount5 = 0;
478 int AnalyzedInstrCount5 = 0;
479 int AnalyzedFunctionCount5 = 0;
481 FunctionPassManager FPM(/*DebugLogging*/ true);
482 FPM.addPass(TestInvalidationFunctionPass("f"));
483 FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5,
484 AnalyzedFunctionCount5,
485 /*OnlyUseCachedResults=*/true));
486 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
489 MPM.run(*M, MAM);
491 // Validate module pass counters.
492 EXPECT_EQ(1, ModulePassRunCount);
494 // Validate all function pass counter sets are the same.
495 EXPECT_EQ(3, FunctionPassRunCount1);
496 EXPECT_EQ(5, AnalyzedInstrCount1);
497 EXPECT_EQ(0, AnalyzedFunctionCount1);
498 EXPECT_EQ(3, FunctionPassRunCount2);
499 EXPECT_EQ(5, AnalyzedInstrCount2);
500 EXPECT_EQ(0, AnalyzedFunctionCount2);
501 EXPECT_EQ(3, FunctionPassRunCount3);
502 EXPECT_EQ(5, AnalyzedInstrCount3);
503 EXPECT_EQ(0, AnalyzedFunctionCount3);
504 EXPECT_EQ(3, FunctionPassRunCount4);
505 EXPECT_EQ(5, AnalyzedInstrCount4);
506 EXPECT_EQ(9, AnalyzedFunctionCount4);
507 EXPECT_EQ(3, FunctionPassRunCount5);
508 EXPECT_EQ(2, AnalyzedInstrCount5); // Only 'g' and 'h' were cached.
509 EXPECT_EQ(9, AnalyzedFunctionCount5);
511 // Validate the analysis counters:
512 // first run over 3 functions, then module pass invalidates
513 // second run over 3 functions, nothing invalidates
514 // third run over 0 functions, but 1 function invalidated
515 // fourth run over 1 function
516 // fifth run invalidates 1 function first, but runs over 0 functions
517 EXPECT_EQ(7, FunctionAnalysisRuns);
519 EXPECT_EQ(1, ModuleAnalysisRuns);
522 // A customized pass manager that passes extra arguments through the
523 // infrastructure.
524 typedef AnalysisManager<Function, int> CustomizedAnalysisManager;
525 typedef PassManager<Function, CustomizedAnalysisManager, int, int &>
526 CustomizedPassManager;
528 class CustomizedAnalysis : public AnalysisInfoMixin<CustomizedAnalysis> {
529 public:
530 struct Result {
531 Result(int I) : I(I) {}
532 int I;
535 Result run(Function &F, CustomizedAnalysisManager &AM, int I) {
536 return Result(I);
539 private:
540 friend AnalysisInfoMixin<CustomizedAnalysis>;
541 static AnalysisKey Key;
544 AnalysisKey CustomizedAnalysis::Key;
546 struct CustomizedPass : PassInfoMixin<CustomizedPass> {
547 std::function<void(CustomizedAnalysis::Result &, int &)> Callback;
549 template <typename CallbackT>
550 CustomizedPass(CallbackT Callback) : Callback(Callback) {}
552 PreservedAnalyses run(Function &F, CustomizedAnalysisManager &AM, int I,
553 int &O) {
554 Callback(AM.getResult<CustomizedAnalysis>(F, I), O);
555 return PreservedAnalyses::none();
559 TEST_F(PassManagerTest, CustomizedPassManagerArgs) {
560 CustomizedAnalysisManager AM;
561 AM.registerPass([&] { return CustomizedAnalysis(); });
562 PassInstrumentationCallbacks PIC;
563 AM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); });
565 CustomizedPassManager PM;
567 // Add an instance of the customized pass that just accumulates the input
568 // after it is round-tripped through the analysis.
569 int Result = 0;
570 PM.addPass(
571 CustomizedPass([](CustomizedAnalysis::Result &R, int &O) { O += R.I; }));
573 // Run this over every function with the input of 42.
574 for (Function &F : *M)
575 PM.run(F, AM, 42, Result);
577 // And ensure that we accumulated the correct result.
578 EXPECT_EQ(42 * (int)M->size(), Result);
581 /// A test analysis pass which caches in its result another analysis pass and
582 /// uses it to serve queries. This requires the result to invalidate itself
583 /// when its dependency is invalidated.
584 struct TestIndirectFunctionAnalysis
585 : public AnalysisInfoMixin<TestIndirectFunctionAnalysis> {
586 struct Result {
587 Result(TestFunctionAnalysis::Result &FDep, TestModuleAnalysis::Result &MDep)
588 : FDep(FDep), MDep(MDep) {}
589 TestFunctionAnalysis::Result &FDep;
590 TestModuleAnalysis::Result &MDep;
592 bool invalidate(Function &F, const PreservedAnalyses &PA,
593 FunctionAnalysisManager::Invalidator &Inv) {
594 auto PAC = PA.getChecker<TestIndirectFunctionAnalysis>();
595 return !(PAC.preserved() ||
596 PAC.preservedSet<AllAnalysesOn<Function>>()) ||
597 Inv.invalidate<TestFunctionAnalysis>(F, PA);
601 TestIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {}
603 /// Run the analysis pass over the function and return a result.
604 Result run(Function &F, FunctionAnalysisManager &AM) {
605 ++Runs;
606 auto &FDep = AM.getResult<TestFunctionAnalysis>(F);
607 auto &Proxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
608 const ModuleAnalysisManager &MAM = Proxy.getManager();
609 // For the test, we insist that the module analysis starts off in the
610 // cache.
611 auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
612 // And register the dependency as module analysis dependencies have to be
613 // pre-registered on the proxy.
614 Proxy.registerOuterAnalysisInvalidation<TestModuleAnalysis,
615 TestIndirectFunctionAnalysis>();
616 return Result(FDep, MDep);
619 private:
620 friend AnalysisInfoMixin<TestIndirectFunctionAnalysis>;
621 static AnalysisKey Key;
623 int &Runs;
626 AnalysisKey TestIndirectFunctionAnalysis::Key;
628 /// A test analysis pass which chaches in its result the result from the above
629 /// indirect analysis pass.
631 /// This allows us to ensure that whenever an analysis pass is invalidated due
632 /// to dependencies (especially dependencies across IR units that trigger
633 /// asynchronous invalidation) we correctly detect that this may in turn cause
634 /// other analysis to be invalidated.
635 struct TestDoublyIndirectFunctionAnalysis
636 : public AnalysisInfoMixin<TestDoublyIndirectFunctionAnalysis> {
637 struct Result {
638 Result(TestIndirectFunctionAnalysis::Result &IDep) : IDep(IDep) {}
639 TestIndirectFunctionAnalysis::Result &IDep;
641 bool invalidate(Function &F, const PreservedAnalyses &PA,
642 FunctionAnalysisManager::Invalidator &Inv) {
643 auto PAC = PA.getChecker<TestDoublyIndirectFunctionAnalysis>();
644 return !(PAC.preserved() ||
645 PAC.preservedSet<AllAnalysesOn<Function>>()) ||
646 Inv.invalidate<TestIndirectFunctionAnalysis>(F, PA);
650 TestDoublyIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {}
652 /// Run the analysis pass over the function and return a result.
653 Result run(Function &F, FunctionAnalysisManager &AM) {
654 ++Runs;
655 auto &IDep = AM.getResult<TestIndirectFunctionAnalysis>(F);
656 return Result(IDep);
659 private:
660 friend AnalysisInfoMixin<TestDoublyIndirectFunctionAnalysis>;
661 static AnalysisKey Key;
663 int &Runs;
666 AnalysisKey TestDoublyIndirectFunctionAnalysis::Key;
668 struct LambdaPass : public PassInfoMixin<LambdaPass> {
669 using FuncT = std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)>;
671 LambdaPass(FuncT Func) : Func(std::move(Func)) {}
673 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
674 return Func(F, AM);
677 FuncT Func;
680 TEST_F(PassManagerTest, IndirectAnalysisInvalidation) {
681 FunctionAnalysisManager FAM(/*DebugLogging*/ true);
682 int FunctionAnalysisRuns = 0, ModuleAnalysisRuns = 0,
683 IndirectAnalysisRuns = 0, DoublyIndirectAnalysisRuns = 0;
684 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
685 FAM.registerPass(
686 [&] { return TestIndirectFunctionAnalysis(IndirectAnalysisRuns); });
687 FAM.registerPass([&] {
688 return TestDoublyIndirectFunctionAnalysis(DoublyIndirectAnalysisRuns);
691 ModuleAnalysisManager MAM(/*DebugLogging*/ true);
692 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
693 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
694 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
696 PassInstrumentationCallbacks PIC;
697 MAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); });
698 FAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); });
700 int InstrCount = 0, FunctionCount = 0;
701 ModulePassManager MPM(/*DebugLogging*/ true);
702 FunctionPassManager FPM(/*DebugLogging*/ true);
703 // First just use the analysis to get the instruction count, and preserve
704 // everything.
705 FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) {
706 auto &DoublyIndirectResult =
707 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F);
708 auto &IndirectResult = DoublyIndirectResult.IDep;
709 InstrCount += IndirectResult.FDep.InstructionCount;
710 FunctionCount += IndirectResult.MDep.FunctionCount;
711 return PreservedAnalyses::all();
712 }));
713 // Next, invalidate
714 // - both analyses for "f",
715 // - just the underlying (indirect) analysis for "g", and
716 // - just the direct analysis for "h".
717 FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) {
718 auto &DoublyIndirectResult =
719 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F);
720 auto &IndirectResult = DoublyIndirectResult.IDep;
721 InstrCount += IndirectResult.FDep.InstructionCount;
722 FunctionCount += IndirectResult.MDep.FunctionCount;
723 auto PA = PreservedAnalyses::none();
724 if (F.getName() == "g")
725 PA.preserve<TestFunctionAnalysis>();
726 else if (F.getName() == "h")
727 PA.preserve<TestIndirectFunctionAnalysis>();
728 return PA;
729 }));
730 // Finally, use the analysis again on each function, forcing re-computation
731 // for all of them.
732 FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) {
733 auto &DoublyIndirectResult =
734 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F);
735 auto &IndirectResult = DoublyIndirectResult.IDep;
736 InstrCount += IndirectResult.FDep.InstructionCount;
737 FunctionCount += IndirectResult.MDep.FunctionCount;
738 return PreservedAnalyses::all();
739 }));
741 // Create a second function pass manager. This will cause the module-level
742 // invalidation to occur, which will force yet another invalidation of the
743 // indirect function-level analysis as the module analysis it depends on gets
744 // invalidated.
745 FunctionPassManager FPM2(/*DebugLogging*/ true);
746 FPM2.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) {
747 auto &DoublyIndirectResult =
748 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F);
749 auto &IndirectResult = DoublyIndirectResult.IDep;
750 InstrCount += IndirectResult.FDep.InstructionCount;
751 FunctionCount += IndirectResult.MDep.FunctionCount;
752 return PreservedAnalyses::all();
753 }));
755 // Add a requires pass to populate the module analysis and then our function
756 // pass pipeline.
757 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
758 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
759 // Now require the module analysis again (it will have been invalidated once)
760 // and then use it again from a function pass manager.
761 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
762 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM2)));
763 MPM.run(*M, MAM);
765 // There are generally two possible runs for each of the three functions. But
766 // for one function, we only invalidate the indirect analysis so the base one
767 // only gets run five times.
768 EXPECT_EQ(5, FunctionAnalysisRuns);
769 // The module analysis pass should be run twice here.
770 EXPECT_EQ(2, ModuleAnalysisRuns);
771 // The indirect analysis is invalidated for each function (either directly or
772 // indirectly) and run twice for each.
773 EXPECT_EQ(9, IndirectAnalysisRuns);
774 EXPECT_EQ(9, DoublyIndirectAnalysisRuns);
776 // There are five instructions in the module and we add the count four
777 // times.
778 EXPECT_EQ(5 * 4, InstrCount);
780 // There are three functions and we count them four times for each of the
781 // three functions.
782 EXPECT_EQ(3 * 4 * 3, FunctionCount);