blob: 55c8ff9439822f407e5f4463eb8049384f8aa8c3 [file] [log] [blame]
Chandler Carruth74319922016-02-23 10:02:02 +00001//===- CGSCCPassManagerTest.cpp -------------------------------------------===//
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/Analysis/CGSCCPassManager.h"
11#include "llvm/Analysis/LazyCallGraph.h"
12#include "llvm/AsmParser/Parser.h"
13#include "llvm/IR/Function.h"
14#include "llvm/IR/InstIterator.h"
15#include "llvm/IR/LLVMContext.h"
16#include "llvm/IR/Module.h"
17#include "llvm/IR/PassManager.h"
18#include "llvm/Support/SourceMgr.h"
19#include "gtest/gtest.h"
20
21using namespace llvm;
22
23namespace {
24
Chandler Carruthdab4eae2016-11-23 17:53:26 +000025class TestModuleAnalysis : public AnalysisInfoMixin<TestModuleAnalysis> {
Chandler Carruth74319922016-02-23 10:02:02 +000026public:
27 struct Result {
28 Result(int Count) : FunctionCount(Count) {}
29 int FunctionCount;
30 };
31
Chandler Carruth74319922016-02-23 10:02:02 +000032 TestModuleAnalysis(int &Runs) : Runs(Runs) {}
33
Chandler Carruthb47f8012016-03-11 11:05:24 +000034 Result run(Module &M, ModuleAnalysisManager &AM) {
Chandler Carruth74319922016-02-23 10:02:02 +000035 ++Runs;
36 return Result(M.size());
37 }
38
39private:
Chandler Carruthdab4eae2016-11-23 17:53:26 +000040 friend AnalysisInfoMixin<TestModuleAnalysis>;
41 static AnalysisKey Key;
Chandler Carruth74319922016-02-23 10:02:02 +000042
43 int &Runs;
44};
45
Chandler Carruthdab4eae2016-11-23 17:53:26 +000046AnalysisKey TestModuleAnalysis::Key;
Chandler Carruth74319922016-02-23 10:02:02 +000047
Chandler Carruthdab4eae2016-11-23 17:53:26 +000048class TestSCCAnalysis : public AnalysisInfoMixin<TestSCCAnalysis> {
Chandler Carruth74319922016-02-23 10:02:02 +000049public:
50 struct Result {
51 Result(int Count) : FunctionCount(Count) {}
52 int FunctionCount;
53 };
54
Chandler Carruth74319922016-02-23 10:02:02 +000055 TestSCCAnalysis(int &Runs) : Runs(Runs) {}
56
Chandler Carruth88823462016-08-24 09:37:14 +000057 Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &) {
Chandler Carruth74319922016-02-23 10:02:02 +000058 ++Runs;
59 return Result(C.size());
60 }
61
62private:
Chandler Carruthdab4eae2016-11-23 17:53:26 +000063 friend AnalysisInfoMixin<TestSCCAnalysis>;
64 static AnalysisKey Key;
Chandler Carruth74319922016-02-23 10:02:02 +000065
66 int &Runs;
67};
68
Chandler Carruthdab4eae2016-11-23 17:53:26 +000069AnalysisKey TestSCCAnalysis::Key;
Chandler Carruth74319922016-02-23 10:02:02 +000070
Chandler Carruthdab4eae2016-11-23 17:53:26 +000071class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> {
Chandler Carruth74319922016-02-23 10:02:02 +000072public:
73 struct Result {
74 Result(int Count) : InstructionCount(Count) {}
75 int InstructionCount;
76 };
77
Chandler Carruth74319922016-02-23 10:02:02 +000078 TestFunctionAnalysis(int &Runs) : Runs(Runs) {}
79
Chandler Carruthb47f8012016-03-11 11:05:24 +000080 Result run(Function &F, FunctionAnalysisManager &AM) {
Chandler Carruth74319922016-02-23 10:02:02 +000081 ++Runs;
82 int Count = 0;
83 for (Instruction &I : instructions(F)) {
84 (void)I;
85 ++Count;
86 }
87 return Result(Count);
88 }
89
90private:
Chandler Carruthdab4eae2016-11-23 17:53:26 +000091 friend AnalysisInfoMixin<TestFunctionAnalysis>;
92 static AnalysisKey Key;
Chandler Carruth74319922016-02-23 10:02:02 +000093
94 int &Runs;
95};
96
Chandler Carruthdab4eae2016-11-23 17:53:26 +000097AnalysisKey TestFunctionAnalysis::Key;
Chandler Carruth74319922016-02-23 10:02:02 +000098
Chandler Carruthdab4eae2016-11-23 17:53:26 +000099class TestImmutableFunctionAnalysis
100 : public AnalysisInfoMixin<TestImmutableFunctionAnalysis> {
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000101public:
102 struct Result {
Chandler Carruth3ab2a5a2016-11-28 22:04:31 +0000103 bool invalidate(Function &, const PreservedAnalyses &,
104 FunctionAnalysisManager::Invalidator &) {
105 return false;
106 }
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000107 };
108
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000109 TestImmutableFunctionAnalysis(int &Runs) : Runs(Runs) {}
110
Chandler Carruthb47f8012016-03-11 11:05:24 +0000111 Result run(Function &F, FunctionAnalysisManager &AM) {
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000112 ++Runs;
113 return Result();
114 }
115
116private:
Chandler Carruthdab4eae2016-11-23 17:53:26 +0000117 friend AnalysisInfoMixin<TestImmutableFunctionAnalysis>;
118 static AnalysisKey Key;
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000119
120 int &Runs;
121};
122
Chandler Carruthdab4eae2016-11-23 17:53:26 +0000123AnalysisKey TestImmutableFunctionAnalysis::Key;
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000124
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000125struct LambdaSCCPass : public PassInfoMixin<LambdaSCCPass> {
126 template <typename T> LambdaSCCPass(T &&Arg) : Func(std::forward<T>(Arg)) {}
Chandler Carruth0f0ef132016-09-02 10:49:58 +0000127 // We have to explicitly define all the special member functions because MSVC
128 // refuses to generate them.
129 LambdaSCCPass(LambdaSCCPass &&Arg) : Func(std::move(Arg.Func)) {}
130 LambdaSCCPass &operator=(LambdaSCCPass &&RHS) {
131 Func = std::move(RHS.Func);
132 return *this;
133 }
Chandler Carruth74319922016-02-23 10:02:02 +0000134
Chandler Carruth88823462016-08-24 09:37:14 +0000135 PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
136 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000137 return Func(C, AM, CG, UR);
Chandler Carruth74319922016-02-23 10:02:02 +0000138 }
139
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000140 std::function<PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
141 LazyCallGraph &, CGSCCUpdateResult &)>
142 Func;
Chandler Carruth74319922016-02-23 10:02:02 +0000143};
144
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000145struct LambdaFunctionPass : public PassInfoMixin<LambdaFunctionPass> {
146 template <typename T> LambdaFunctionPass(T &&Arg) : Func(std::forward<T>(Arg)) {}
Chandler Carruth0f0ef132016-09-02 10:49:58 +0000147 // We have to explicitly define all the special member functions because MSVC
148 // refuses to generate them.
149 LambdaFunctionPass(LambdaFunctionPass &&Arg) : Func(std::move(Arg.Func)) {}
150 LambdaFunctionPass &operator=(LambdaFunctionPass &&RHS) {
151 Func = std::move(RHS.Func);
152 return *this;
153 }
Chandler Carruth74319922016-02-23 10:02:02 +0000154
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000155 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
156 return Func(F, AM);
Chandler Carruth74319922016-02-23 10:02:02 +0000157 }
158
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000159 std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)> Func;
Chandler Carruth74319922016-02-23 10:02:02 +0000160};
161
Chandler Carruth6c138ce2016-06-28 00:38:42 +0000162std::unique_ptr<Module> parseIR(const char *IR) {
163 // We just use a static context here. This is never called from multiple
164 // threads so it is harmless no matter how it is implemented. We just need
165 // the context to outlive the module which it does.
166 static LLVMContext C;
Chandler Carruth74319922016-02-23 10:02:02 +0000167 SMDiagnostic Err;
168 return parseAssemblyString(IR, Err, C);
169}
170
Chandler Carruth4f837422016-09-02 01:14:05 +0000171class CGSCCPassManagerTest : public ::testing::Test {
172protected:
173 LLVMContext Context;
Chandler Carruthdc288a82016-09-26 06:29:21 +0000174 FunctionAnalysisManager FAM;
175 CGSCCAnalysisManager CGAM;
176 ModuleAnalysisManager MAM;
177
Chandler Carruth4f837422016-09-02 01:14:05 +0000178 std::unique_ptr<Module> M;
179
180public:
181 CGSCCPassManagerTest()
Chandler Carruthdc288a82016-09-26 06:29:21 +0000182 : FAM(/*DebugLogging*/ true), CGAM(/*DebugLogging*/ true),
Chandler Carruth4cf2c892016-11-28 03:40:33 +0000183 MAM(/*DebugLogging*/ true),
184 M(parseIR(
185 // Define a module with the following call graph, where calls go
186 // out the bottom of nodes and enter the top:
187 //
188 // f
189 // |\ _
190 // | \ / |
191 // g h1 |
192 // | | |
193 // | h2 |
194 // | | |
195 // | h3 |
196 // | / \_/
197 // |/
198 // x
199 //
200 "define void @f() {\n"
201 "entry:\n"
202 " call void @g()\n"
203 " call void @h1()\n"
204 " ret void\n"
205 "}\n"
206 "define void @g() {\n"
207 "entry:\n"
208 " call void @g()\n"
209 " call void @x()\n"
210 " ret void\n"
211 "}\n"
212 "define void @h1() {\n"
213 "entry:\n"
214 " call void @h2()\n"
215 " ret void\n"
216 "}\n"
217 "define void @h2() {\n"
218 "entry:\n"
219 " call void @h3()\n"
220 " call void @x()\n"
221 " ret void\n"
222 "}\n"
223 "define void @h3() {\n"
224 "entry:\n"
225 " call void @h1()\n"
226 " ret void\n"
227 "}\n"
228 "define void @x() {\n"
229 "entry:\n"
230 " ret void\n"
231 "}\n")) {
Chandler Carruthdc288a82016-09-26 06:29:21 +0000232 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
233 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
234 MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });
235 CGAM.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(FAM); });
236 CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); });
237 FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); });
238 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
239 }
Chandler Carruth4f837422016-09-02 01:14:05 +0000240};
241
242TEST_F(CGSCCPassManagerTest, Basic) {
Chandler Carruth74319922016-02-23 10:02:02 +0000243 int FunctionAnalysisRuns = 0;
244 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000245 int ImmutableFunctionAnalysisRuns = 0;
246 FAM.registerPass([&] {
247 return TestImmutableFunctionAnalysis(ImmutableFunctionAnalysisRuns);
248 });
Chandler Carruth74319922016-02-23 10:02:02 +0000249
Chandler Carruth74319922016-02-23 10:02:02 +0000250 int SCCAnalysisRuns = 0;
251 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
252
Chandler Carruth74319922016-02-23 10:02:02 +0000253 int ModuleAnalysisRuns = 0;
Chandler Carruth74319922016-02-23 10:02:02 +0000254 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
255
Chandler Carruth74319922016-02-23 10:02:02 +0000256 ModulePassManager MPM(/*DebugLogging*/ true);
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000257 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
Chandler Carruth74319922016-02-23 10:02:02 +0000258
259 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
260 int SCCPassRunCount1 = 0;
261 int AnalyzedInstrCount1 = 0;
262 int AnalyzedSCCFunctionCount1 = 0;
263 int AnalyzedModuleFunctionCount1 = 0;
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000264 CGPM1.addPass(
265 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
266 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
267 ++SCCPassRunCount1;
268
269 const ModuleAnalysisManager &MAM =
270 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
271 FunctionAnalysisManager &FAM =
272 AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
273 if (TestModuleAnalysis::Result *TMA =
274 MAM.getCachedResult<TestModuleAnalysis>(
275 *C.begin()->getFunction().getParent()))
276 AnalyzedModuleFunctionCount1 += TMA->FunctionCount;
277
278 TestSCCAnalysis::Result &AR = AM.getResult<TestSCCAnalysis>(C, CG);
279 AnalyzedSCCFunctionCount1 += AR.FunctionCount;
280 for (LazyCallGraph::Node &N : C) {
281 TestFunctionAnalysis::Result &FAR =
282 FAM.getResult<TestFunctionAnalysis>(N.getFunction());
283 AnalyzedInstrCount1 += FAR.InstructionCount;
284
285 // Just ensure we get the immutable results.
286 (void)FAM.getResult<TestImmutableFunctionAnalysis>(N.getFunction());
287 }
288
289 return PreservedAnalyses::all();
290 }));
Chandler Carruth74319922016-02-23 10:02:02 +0000291
292 FunctionPassManager FPM1(/*DebugLogging*/ true);
293 int FunctionPassRunCount1 = 0;
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000294 FPM1.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
295 ++FunctionPassRunCount1;
296 return PreservedAnalyses::all();
297 }));
Chandler Carruth74319922016-02-23 10:02:02 +0000298 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
299 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
300
Chandler Carruthb47f8012016-03-11 11:05:24 +0000301 MPM.run(*M, MAM);
Chandler Carruth74319922016-02-23 10:02:02 +0000302
Chandler Carruth74319922016-02-23 10:02:02 +0000303 EXPECT_EQ(1, ModuleAnalysisRuns);
304 EXPECT_EQ(4, SCCAnalysisRuns);
305 EXPECT_EQ(6, FunctionAnalysisRuns);
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000306 EXPECT_EQ(6, ImmutableFunctionAnalysisRuns);
Chandler Carruth74319922016-02-23 10:02:02 +0000307
308 EXPECT_EQ(4, SCCPassRunCount1);
309 EXPECT_EQ(14, AnalyzedInstrCount1);
310 EXPECT_EQ(6, AnalyzedSCCFunctionCount1);
311 EXPECT_EQ(4 * 6, AnalyzedModuleFunctionCount1);
312}
313
Chandler Carruthb52b5732016-09-26 04:01:55 +0000314// Test that an SCC pass which fails to preserve a module analysis does in fact
315// invalidate that module analysis.
316TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesModuleAnalysis) {
Chandler Carruthb52b5732016-09-26 04:01:55 +0000317 int ModuleAnalysisRuns = 0;
318 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
319
320 ModulePassManager MPM(/*DebugLogging*/ true);
321 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
322
323 // The first CGSCC run we preserve everything and make sure that works and
324 // the module analysis is available in the second CGSCC run from the one
325 // required module pass above.
326 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
327 int CountFoundModuleAnalysis1 = 0;
328 CGPM1.addPass(
329 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
330 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
331 const auto &MAM =
332 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
333 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
334 *C.begin()->getFunction().getParent());
335
336 if (TMA)
337 ++CountFoundModuleAnalysis1;
338
339 return PreservedAnalyses::all();
340 }));
341 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
342
343 // The second CGSCC run checks that the module analysis got preserved the
344 // previous time and in one SCC fails to preserve it.
345 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
346 int CountFoundModuleAnalysis2 = 0;
347 CGPM2.addPass(
348 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
349 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
350 const auto &MAM =
351 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
352 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
353 *C.begin()->getFunction().getParent());
354
355 if (TMA)
356 ++CountFoundModuleAnalysis2;
357
358 // Only fail to preserve analyses on one SCC and make sure that gets
359 // propagated.
360 return C.getName() == "(g)" ? PreservedAnalyses::none()
361 : PreservedAnalyses::all();
362 }));
363 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
364
365 // The third CGSCC run should fail to find a cached module analysis as it
366 // should have been invalidated by the above CGSCC run.
367 CGSCCPassManager CGPM3(/*DebugLogging*/ true);
368 int CountFoundModuleAnalysis3 = 0;
369 CGPM3.addPass(
370 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
371 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
372 const auto &MAM =
373 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
374 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
375 *C.begin()->getFunction().getParent());
376
377 if (TMA)
378 ++CountFoundModuleAnalysis3;
379
380 return PreservedAnalyses::none();
381 }));
382 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
383
384 MPM.run(*M, MAM);
385
386 EXPECT_EQ(1, ModuleAnalysisRuns);
387 EXPECT_EQ(4, CountFoundModuleAnalysis1);
388 EXPECT_EQ(4, CountFoundModuleAnalysis2);
389 EXPECT_EQ(0, CountFoundModuleAnalysis3);
390}
391
Chandler Carruthe35f84a2016-09-26 04:17:12 +0000392// Similar to the above, but test that this works for function passes embedded
393// *within* a CGSCC layer.
394TEST_F(CGSCCPassManagerTest, TestFunctionPassInsideCGSCCInvalidatesModuleAnalysis) {
Chandler Carruthe35f84a2016-09-26 04:17:12 +0000395 int ModuleAnalysisRuns = 0;
396 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
397
398 ModulePassManager MPM(/*DebugLogging*/ true);
399 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
400
401 // The first run we preserve everything and make sure that works and the
402 // module analysis is available in the second run from the one required
403 // module pass above.
404 FunctionPassManager FPM1(/*DebugLogging*/ true);
405 // Start true and mark false if we ever failed to find a module analysis
406 // because we expect this to succeed for each SCC.
407 bool FoundModuleAnalysis1 = true;
408 FPM1.addPass(
409 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
410 const auto &MAM =
411 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
412 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
413
414 if (!TMA)
415 FoundModuleAnalysis1 = false;
416
417 return PreservedAnalyses::all();
418 }));
419 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
420 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
421 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
422
423 // The second run checks that the module analysis got preserved the previous
424 // time and in one function fails to preserve it.
425 FunctionPassManager FPM2(/*DebugLogging*/ true);
426 // Again, start true and mark false if we ever failed to find a module analysis
427 // because we expect this to succeed for each SCC.
428 bool FoundModuleAnalysis2 = true;
429 FPM2.addPass(
430 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
431 const auto &MAM =
432 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
433 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
434
435 if (!TMA)
436 FoundModuleAnalysis2 = false;
437
438 // Only fail to preserve analyses on one SCC and make sure that gets
439 // propagated.
440 return F.getName() == "h2" ? PreservedAnalyses::none()
441 : PreservedAnalyses::all();
442 }));
443 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
444 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
445 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
446
447 // The third run should fail to find a cached module analysis as it should
448 // have been invalidated by the above run.
449 FunctionPassManager FPM3(/*DebugLogging*/ true);
450 // Start false and mark true if we ever *succeeded* to find a module
451 // analysis, as we expect this to fail for every function.
452 bool FoundModuleAnalysis3 = false;
453 FPM3.addPass(
454 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
455 const auto &MAM =
456 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
457 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
458
459 if (TMA)
460 FoundModuleAnalysis3 = true;
461
462 return PreservedAnalyses::none();
463 }));
464 CGSCCPassManager CGPM3(/*DebugLogging*/ true);
465 CGPM3.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM3)));
466 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
467
468 MPM.run(*M, MAM);
469
470 EXPECT_EQ(1, ModuleAnalysisRuns);
471 EXPECT_TRUE(FoundModuleAnalysis1);
472 EXPECT_TRUE(FoundModuleAnalysis2);
473 EXPECT_FALSE(FoundModuleAnalysis3);
474}
475
Chandler Carruth74319922016-02-23 10:02:02 +0000476}