blob: 643af94674e736919017dbc3e8cf1b4b761755ad [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 {
103 bool invalidate(Function &, const PreservedAnalyses &) { return false; }
104 };
105
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000106 TestImmutableFunctionAnalysis(int &Runs) : Runs(Runs) {}
107
Chandler Carruthb47f8012016-03-11 11:05:24 +0000108 Result run(Function &F, FunctionAnalysisManager &AM) {
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000109 ++Runs;
110 return Result();
111 }
112
113private:
Chandler Carruthdab4eae2016-11-23 17:53:26 +0000114 friend AnalysisInfoMixin<TestImmutableFunctionAnalysis>;
115 static AnalysisKey Key;
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000116
117 int &Runs;
118};
119
Chandler Carruthdab4eae2016-11-23 17:53:26 +0000120AnalysisKey TestImmutableFunctionAnalysis::Key;
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000121
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000122struct LambdaSCCPass : public PassInfoMixin<LambdaSCCPass> {
123 template <typename T> LambdaSCCPass(T &&Arg) : Func(std::forward<T>(Arg)) {}
Chandler Carruth0f0ef132016-09-02 10:49:58 +0000124 // We have to explicitly define all the special member functions because MSVC
125 // refuses to generate them.
126 LambdaSCCPass(LambdaSCCPass &&Arg) : Func(std::move(Arg.Func)) {}
127 LambdaSCCPass &operator=(LambdaSCCPass &&RHS) {
128 Func = std::move(RHS.Func);
129 return *this;
130 }
Chandler Carruth74319922016-02-23 10:02:02 +0000131
Chandler Carruth88823462016-08-24 09:37:14 +0000132 PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
133 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000134 return Func(C, AM, CG, UR);
Chandler Carruth74319922016-02-23 10:02:02 +0000135 }
136
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000137 std::function<PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
138 LazyCallGraph &, CGSCCUpdateResult &)>
139 Func;
Chandler Carruth74319922016-02-23 10:02:02 +0000140};
141
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000142struct LambdaFunctionPass : public PassInfoMixin<LambdaFunctionPass> {
143 template <typename T> LambdaFunctionPass(T &&Arg) : Func(std::forward<T>(Arg)) {}
Chandler Carruth0f0ef132016-09-02 10:49:58 +0000144 // We have to explicitly define all the special member functions because MSVC
145 // refuses to generate them.
146 LambdaFunctionPass(LambdaFunctionPass &&Arg) : Func(std::move(Arg.Func)) {}
147 LambdaFunctionPass &operator=(LambdaFunctionPass &&RHS) {
148 Func = std::move(RHS.Func);
149 return *this;
150 }
Chandler Carruth74319922016-02-23 10:02:02 +0000151
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000152 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
153 return Func(F, AM);
Chandler Carruth74319922016-02-23 10:02:02 +0000154 }
155
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000156 std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)> Func;
Chandler Carruth74319922016-02-23 10:02:02 +0000157};
158
Chandler Carruth6c138ce2016-06-28 00:38:42 +0000159std::unique_ptr<Module> parseIR(const char *IR) {
160 // We just use a static context here. This is never called from multiple
161 // threads so it is harmless no matter how it is implemented. We just need
162 // the context to outlive the module which it does.
163 static LLVMContext C;
Chandler Carruth74319922016-02-23 10:02:02 +0000164 SMDiagnostic Err;
165 return parseAssemblyString(IR, Err, C);
166}
167
Chandler Carruth4f837422016-09-02 01:14:05 +0000168class CGSCCPassManagerTest : public ::testing::Test {
169protected:
170 LLVMContext Context;
Chandler Carruthdc288a82016-09-26 06:29:21 +0000171 FunctionAnalysisManager FAM;
172 CGSCCAnalysisManager CGAM;
173 ModuleAnalysisManager MAM;
174
Chandler Carruth4f837422016-09-02 01:14:05 +0000175 std::unique_ptr<Module> M;
176
177public:
178 CGSCCPassManagerTest()
Chandler Carruthdc288a82016-09-26 06:29:21 +0000179 : FAM(/*DebugLogging*/ true), CGAM(/*DebugLogging*/ true),
Chandler Carruth4cf2c892016-11-28 03:40:33 +0000180 MAM(/*DebugLogging*/ true),
181 M(parseIR(
182 // Define a module with the following call graph, where calls go
183 // out the bottom of nodes and enter the top:
184 //
185 // f
186 // |\ _
187 // | \ / |
188 // g h1 |
189 // | | |
190 // | h2 |
191 // | | |
192 // | h3 |
193 // | / \_/
194 // |/
195 // x
196 //
197 "define void @f() {\n"
198 "entry:\n"
199 " call void @g()\n"
200 " call void @h1()\n"
201 " ret void\n"
202 "}\n"
203 "define void @g() {\n"
204 "entry:\n"
205 " call void @g()\n"
206 " call void @x()\n"
207 " ret void\n"
208 "}\n"
209 "define void @h1() {\n"
210 "entry:\n"
211 " call void @h2()\n"
212 " ret void\n"
213 "}\n"
214 "define void @h2() {\n"
215 "entry:\n"
216 " call void @h3()\n"
217 " call void @x()\n"
218 " ret void\n"
219 "}\n"
220 "define void @h3() {\n"
221 "entry:\n"
222 " call void @h1()\n"
223 " ret void\n"
224 "}\n"
225 "define void @x() {\n"
226 "entry:\n"
227 " ret void\n"
228 "}\n")) {
Chandler Carruthdc288a82016-09-26 06:29:21 +0000229 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
230 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
231 MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });
232 CGAM.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(FAM); });
233 CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); });
234 FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); });
235 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
236 }
Chandler Carruth4f837422016-09-02 01:14:05 +0000237};
238
239TEST_F(CGSCCPassManagerTest, Basic) {
Chandler Carruth74319922016-02-23 10:02:02 +0000240 int FunctionAnalysisRuns = 0;
241 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000242 int ImmutableFunctionAnalysisRuns = 0;
243 FAM.registerPass([&] {
244 return TestImmutableFunctionAnalysis(ImmutableFunctionAnalysisRuns);
245 });
Chandler Carruth74319922016-02-23 10:02:02 +0000246
Chandler Carruth74319922016-02-23 10:02:02 +0000247 int SCCAnalysisRuns = 0;
248 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
249
Chandler Carruth74319922016-02-23 10:02:02 +0000250 int ModuleAnalysisRuns = 0;
Chandler Carruth74319922016-02-23 10:02:02 +0000251 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
252
Chandler Carruth74319922016-02-23 10:02:02 +0000253 ModulePassManager MPM(/*DebugLogging*/ true);
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000254 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
Chandler Carruth74319922016-02-23 10:02:02 +0000255
256 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
257 int SCCPassRunCount1 = 0;
258 int AnalyzedInstrCount1 = 0;
259 int AnalyzedSCCFunctionCount1 = 0;
260 int AnalyzedModuleFunctionCount1 = 0;
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000261 CGPM1.addPass(
262 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
263 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
264 ++SCCPassRunCount1;
265
266 const ModuleAnalysisManager &MAM =
267 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
268 FunctionAnalysisManager &FAM =
269 AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
270 if (TestModuleAnalysis::Result *TMA =
271 MAM.getCachedResult<TestModuleAnalysis>(
272 *C.begin()->getFunction().getParent()))
273 AnalyzedModuleFunctionCount1 += TMA->FunctionCount;
274
275 TestSCCAnalysis::Result &AR = AM.getResult<TestSCCAnalysis>(C, CG);
276 AnalyzedSCCFunctionCount1 += AR.FunctionCount;
277 for (LazyCallGraph::Node &N : C) {
278 TestFunctionAnalysis::Result &FAR =
279 FAM.getResult<TestFunctionAnalysis>(N.getFunction());
280 AnalyzedInstrCount1 += FAR.InstructionCount;
281
282 // Just ensure we get the immutable results.
283 (void)FAM.getResult<TestImmutableFunctionAnalysis>(N.getFunction());
284 }
285
286 return PreservedAnalyses::all();
287 }));
Chandler Carruth74319922016-02-23 10:02:02 +0000288
289 FunctionPassManager FPM1(/*DebugLogging*/ true);
290 int FunctionPassRunCount1 = 0;
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000291 FPM1.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
292 ++FunctionPassRunCount1;
293 return PreservedAnalyses::all();
294 }));
Chandler Carruth74319922016-02-23 10:02:02 +0000295 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
296 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
297
Chandler Carruthb47f8012016-03-11 11:05:24 +0000298 MPM.run(*M, MAM);
Chandler Carruth74319922016-02-23 10:02:02 +0000299
Chandler Carruth74319922016-02-23 10:02:02 +0000300 EXPECT_EQ(1, ModuleAnalysisRuns);
301 EXPECT_EQ(4, SCCAnalysisRuns);
302 EXPECT_EQ(6, FunctionAnalysisRuns);
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000303 EXPECT_EQ(6, ImmutableFunctionAnalysisRuns);
Chandler Carruth74319922016-02-23 10:02:02 +0000304
305 EXPECT_EQ(4, SCCPassRunCount1);
306 EXPECT_EQ(14, AnalyzedInstrCount1);
307 EXPECT_EQ(6, AnalyzedSCCFunctionCount1);
308 EXPECT_EQ(4 * 6, AnalyzedModuleFunctionCount1);
309}
310
Chandler Carruthb52b5732016-09-26 04:01:55 +0000311// Test that an SCC pass which fails to preserve a module analysis does in fact
312// invalidate that module analysis.
313TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesModuleAnalysis) {
Chandler Carruthb52b5732016-09-26 04:01:55 +0000314 int ModuleAnalysisRuns = 0;
315 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
316
317 ModulePassManager MPM(/*DebugLogging*/ true);
318 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
319
320 // The first CGSCC run we preserve everything and make sure that works and
321 // the module analysis is available in the second CGSCC run from the one
322 // required module pass above.
323 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
324 int CountFoundModuleAnalysis1 = 0;
325 CGPM1.addPass(
326 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
327 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
328 const auto &MAM =
329 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
330 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
331 *C.begin()->getFunction().getParent());
332
333 if (TMA)
334 ++CountFoundModuleAnalysis1;
335
336 return PreservedAnalyses::all();
337 }));
338 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
339
340 // The second CGSCC run checks that the module analysis got preserved the
341 // previous time and in one SCC fails to preserve it.
342 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
343 int CountFoundModuleAnalysis2 = 0;
344 CGPM2.addPass(
345 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
346 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
347 const auto &MAM =
348 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
349 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
350 *C.begin()->getFunction().getParent());
351
352 if (TMA)
353 ++CountFoundModuleAnalysis2;
354
355 // Only fail to preserve analyses on one SCC and make sure that gets
356 // propagated.
357 return C.getName() == "(g)" ? PreservedAnalyses::none()
358 : PreservedAnalyses::all();
359 }));
360 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
361
362 // The third CGSCC run should fail to find a cached module analysis as it
363 // should have been invalidated by the above CGSCC run.
364 CGSCCPassManager CGPM3(/*DebugLogging*/ true);
365 int CountFoundModuleAnalysis3 = 0;
366 CGPM3.addPass(
367 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
368 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
369 const auto &MAM =
370 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
371 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
372 *C.begin()->getFunction().getParent());
373
374 if (TMA)
375 ++CountFoundModuleAnalysis3;
376
377 return PreservedAnalyses::none();
378 }));
379 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
380
381 MPM.run(*M, MAM);
382
383 EXPECT_EQ(1, ModuleAnalysisRuns);
384 EXPECT_EQ(4, CountFoundModuleAnalysis1);
385 EXPECT_EQ(4, CountFoundModuleAnalysis2);
386 EXPECT_EQ(0, CountFoundModuleAnalysis3);
387}
388
Chandler Carruthe35f84a2016-09-26 04:17:12 +0000389// Similar to the above, but test that this works for function passes embedded
390// *within* a CGSCC layer.
391TEST_F(CGSCCPassManagerTest, TestFunctionPassInsideCGSCCInvalidatesModuleAnalysis) {
Chandler Carruthe35f84a2016-09-26 04:17:12 +0000392 int ModuleAnalysisRuns = 0;
393 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
394
395 ModulePassManager MPM(/*DebugLogging*/ true);
396 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
397
398 // The first run we preserve everything and make sure that works and the
399 // module analysis is available in the second run from the one required
400 // module pass above.
401 FunctionPassManager FPM1(/*DebugLogging*/ true);
402 // Start true and mark false if we ever failed to find a module analysis
403 // because we expect this to succeed for each SCC.
404 bool FoundModuleAnalysis1 = true;
405 FPM1.addPass(
406 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
407 const auto &MAM =
408 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
409 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
410
411 if (!TMA)
412 FoundModuleAnalysis1 = false;
413
414 return PreservedAnalyses::all();
415 }));
416 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
417 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
418 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
419
420 // The second run checks that the module analysis got preserved the previous
421 // time and in one function fails to preserve it.
422 FunctionPassManager FPM2(/*DebugLogging*/ true);
423 // Again, start true and mark false if we ever failed to find a module analysis
424 // because we expect this to succeed for each SCC.
425 bool FoundModuleAnalysis2 = true;
426 FPM2.addPass(
427 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
428 const auto &MAM =
429 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
430 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
431
432 if (!TMA)
433 FoundModuleAnalysis2 = false;
434
435 // Only fail to preserve analyses on one SCC and make sure that gets
436 // propagated.
437 return F.getName() == "h2" ? PreservedAnalyses::none()
438 : PreservedAnalyses::all();
439 }));
440 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
441 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
442 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
443
444 // The third run should fail to find a cached module analysis as it should
445 // have been invalidated by the above run.
446 FunctionPassManager FPM3(/*DebugLogging*/ true);
447 // Start false and mark true if we ever *succeeded* to find a module
448 // analysis, as we expect this to fail for every function.
449 bool FoundModuleAnalysis3 = false;
450 FPM3.addPass(
451 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
452 const auto &MAM =
453 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
454 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
455
456 if (TMA)
457 FoundModuleAnalysis3 = true;
458
459 return PreservedAnalyses::none();
460 }));
461 CGSCCPassManager CGPM3(/*DebugLogging*/ true);
462 CGPM3.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM3)));
463 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
464
465 MPM.run(*M, MAM);
466
467 EXPECT_EQ(1, ModuleAnalysisRuns);
468 EXPECT_TRUE(FoundModuleAnalysis1);
469 EXPECT_TRUE(FoundModuleAnalysis2);
470 EXPECT_FALSE(FoundModuleAnalysis3);
471}
472
Chandler Carruth74319922016-02-23 10:02:02 +0000473}