CGSCCPassManagerTest.cpp 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284
  1. //===- CGSCCPassManagerTest.cpp -------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/Analysis/CGSCCPassManager.h"
  9. #include "llvm/Analysis/LazyCallGraph.h"
  10. #include "llvm/Analysis/TargetLibraryInfo.h"
  11. #include "llvm/AsmParser/Parser.h"
  12. #include "llvm/IR/Function.h"
  13. #include "llvm/IR/InstIterator.h"
  14. #include "llvm/IR/LLVMContext.h"
  15. #include "llvm/IR/Module.h"
  16. #include "llvm/IR/PassManager.h"
  17. #include "llvm/Support/SourceMgr.h"
  18. #include "gtest/gtest.h"
  19. using namespace llvm;
  20. namespace {
  21. class TestModuleAnalysis : public AnalysisInfoMixin<TestModuleAnalysis> {
  22. public:
  23. struct Result {
  24. Result(int Count) : FunctionCount(Count) {}
  25. int FunctionCount;
  26. };
  27. TestModuleAnalysis(int &Runs) : Runs(Runs) {}
  28. Result run(Module &M, ModuleAnalysisManager &AM) {
  29. ++Runs;
  30. return Result(M.size());
  31. }
  32. private:
  33. friend AnalysisInfoMixin<TestModuleAnalysis>;
  34. static AnalysisKey Key;
  35. int &Runs;
  36. };
  37. AnalysisKey TestModuleAnalysis::Key;
  38. class TestSCCAnalysis : public AnalysisInfoMixin<TestSCCAnalysis> {
  39. public:
  40. struct Result {
  41. Result(int Count) : FunctionCount(Count) {}
  42. int FunctionCount;
  43. };
  44. TestSCCAnalysis(int &Runs) : Runs(Runs) {}
  45. Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &) {
  46. ++Runs;
  47. return Result(C.size());
  48. }
  49. private:
  50. friend AnalysisInfoMixin<TestSCCAnalysis>;
  51. static AnalysisKey Key;
  52. int &Runs;
  53. };
  54. AnalysisKey TestSCCAnalysis::Key;
  55. class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> {
  56. public:
  57. struct Result {
  58. Result(int Count) : InstructionCount(Count) {}
  59. int InstructionCount;
  60. };
  61. TestFunctionAnalysis(int &Runs) : Runs(Runs) {}
  62. Result run(Function &F, FunctionAnalysisManager &AM) {
  63. ++Runs;
  64. int Count = 0;
  65. for (Instruction &I : instructions(F)) {
  66. (void)I;
  67. ++Count;
  68. }
  69. return Result(Count);
  70. }
  71. private:
  72. friend AnalysisInfoMixin<TestFunctionAnalysis>;
  73. static AnalysisKey Key;
  74. int &Runs;
  75. };
  76. AnalysisKey TestFunctionAnalysis::Key;
  77. class TestImmutableFunctionAnalysis
  78. : public AnalysisInfoMixin<TestImmutableFunctionAnalysis> {
  79. public:
  80. struct Result {
  81. bool invalidate(Function &, const PreservedAnalyses &,
  82. FunctionAnalysisManager::Invalidator &) {
  83. return false;
  84. }
  85. };
  86. TestImmutableFunctionAnalysis(int &Runs) : Runs(Runs) {}
  87. Result run(Function &F, FunctionAnalysisManager &AM) {
  88. ++Runs;
  89. return Result();
  90. }
  91. private:
  92. friend AnalysisInfoMixin<TestImmutableFunctionAnalysis>;
  93. static AnalysisKey Key;
  94. int &Runs;
  95. };
  96. AnalysisKey TestImmutableFunctionAnalysis::Key;
  97. struct LambdaModulePass : public PassInfoMixin<LambdaModulePass> {
  98. template <typename T>
  99. LambdaModulePass(T &&Arg) : Func(std::forward<T>(Arg)) {}
  100. PreservedAnalyses run(Module &F, ModuleAnalysisManager &AM) {
  101. return Func(F, AM);
  102. }
  103. std::function<PreservedAnalyses(Module &, ModuleAnalysisManager &)> Func;
  104. };
  105. struct LambdaSCCPass : public PassInfoMixin<LambdaSCCPass> {
  106. template <typename T> LambdaSCCPass(T &&Arg) : Func(std::forward<T>(Arg)) {}
  107. PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
  108. LazyCallGraph &CG, CGSCCUpdateResult &UR) {
  109. return Func(C, AM, CG, UR);
  110. }
  111. std::function<PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
  112. LazyCallGraph &, CGSCCUpdateResult &)>
  113. Func;
  114. };
  115. struct LambdaFunctionPass : public PassInfoMixin<LambdaFunctionPass> {
  116. template <typename T>
  117. LambdaFunctionPass(T &&Arg) : Func(std::forward<T>(Arg)) {}
  118. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
  119. return Func(F, AM);
  120. }
  121. std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)> Func;
  122. };
  123. std::unique_ptr<Module> parseIR(const char *IR) {
  124. // We just use a static context here. This is never called from multiple
  125. // threads so it is harmless no matter how it is implemented. We just need
  126. // the context to outlive the module which it does.
  127. static LLVMContext C;
  128. SMDiagnostic Err;
  129. return parseAssemblyString(IR, Err, C);
  130. }
  131. class CGSCCPassManagerTest : public ::testing::Test {
  132. protected:
  133. LLVMContext Context;
  134. FunctionAnalysisManager FAM;
  135. CGSCCAnalysisManager CGAM;
  136. ModuleAnalysisManager MAM;
  137. std::unique_ptr<Module> M;
  138. public:
  139. CGSCCPassManagerTest()
  140. : FAM(/*DebugLogging*/ true), CGAM(/*DebugLogging*/ true),
  141. MAM(/*DebugLogging*/ true),
  142. M(parseIR(
  143. // Define a module with the following call graph, where calls go
  144. // out the bottom of nodes and enter the top:
  145. //
  146. // f
  147. // |\ _
  148. // | \ / |
  149. // g h1 |
  150. // | | |
  151. // | h2 |
  152. // | | |
  153. // | h3 |
  154. // | / \_/
  155. // |/
  156. // x
  157. //
  158. "define void @f() {\n"
  159. "entry:\n"
  160. " call void @g()\n"
  161. " call void @h1()\n"
  162. " ret void\n"
  163. "}\n"
  164. "define void @g() {\n"
  165. "entry:\n"
  166. " call void @g()\n"
  167. " call void @x()\n"
  168. " ret void\n"
  169. "}\n"
  170. "define void @h1() {\n"
  171. "entry:\n"
  172. " call void @h2()\n"
  173. " ret void\n"
  174. "}\n"
  175. "define void @h2() {\n"
  176. "entry:\n"
  177. " call void @h3()\n"
  178. " call void @x()\n"
  179. " ret void\n"
  180. "}\n"
  181. "define void @h3() {\n"
  182. "entry:\n"
  183. " call void @h1()\n"
  184. " ret void\n"
  185. "}\n"
  186. "define void @x() {\n"
  187. "entry:\n"
  188. " ret void\n"
  189. "}\n")) {
  190. FAM.registerPass([&] { return TargetLibraryAnalysis(); });
  191. MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
  192. MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
  193. // Register required pass instrumentation analysis.
  194. MAM.registerPass([&] { return PassInstrumentationAnalysis(); });
  195. CGAM.registerPass([&] { return PassInstrumentationAnalysis(); });
  196. FAM.registerPass([&] { return PassInstrumentationAnalysis(); });
  197. // Cross-register proxies.
  198. MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });
  199. CGAM.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(); });
  200. CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); });
  201. FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); });
  202. FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
  203. }
  204. };
  205. TEST_F(CGSCCPassManagerTest, Basic) {
  206. int FunctionAnalysisRuns = 0;
  207. FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
  208. int ImmutableFunctionAnalysisRuns = 0;
  209. FAM.registerPass([&] {
  210. return TestImmutableFunctionAnalysis(ImmutableFunctionAnalysisRuns);
  211. });
  212. int SCCAnalysisRuns = 0;
  213. CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
  214. int ModuleAnalysisRuns = 0;
  215. MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
  216. ModulePassManager MPM(/*DebugLogging*/ true);
  217. MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
  218. CGSCCPassManager CGPM1(/*DebugLogging*/ true);
  219. FunctionPassManager FPM1(/*DebugLogging*/ true);
  220. int FunctionPassRunCount1 = 0;
  221. FPM1.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
  222. ++FunctionPassRunCount1;
  223. return PreservedAnalyses::none();
  224. }));
  225. CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
  226. int SCCPassRunCount1 = 0;
  227. int AnalyzedInstrCount1 = 0;
  228. int AnalyzedSCCFunctionCount1 = 0;
  229. int AnalyzedModuleFunctionCount1 = 0;
  230. CGPM1.addPass(
  231. LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
  232. LazyCallGraph &CG, CGSCCUpdateResult &UR) {
  233. ++SCCPassRunCount1;
  234. const ModuleAnalysisManager &MAM =
  235. AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
  236. FunctionAnalysisManager &FAM =
  237. AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
  238. if (TestModuleAnalysis::Result *TMA =
  239. MAM.getCachedResult<TestModuleAnalysis>(
  240. *C.begin()->getFunction().getParent()))
  241. AnalyzedModuleFunctionCount1 += TMA->FunctionCount;
  242. TestSCCAnalysis::Result &AR = AM.getResult<TestSCCAnalysis>(C, CG);
  243. AnalyzedSCCFunctionCount1 += AR.FunctionCount;
  244. for (LazyCallGraph::Node &N : C) {
  245. TestFunctionAnalysis::Result &FAR =
  246. FAM.getResult<TestFunctionAnalysis>(N.getFunction());
  247. AnalyzedInstrCount1 += FAR.InstructionCount;
  248. // Just ensure we get the immutable results.
  249. (void)FAM.getResult<TestImmutableFunctionAnalysis>(N.getFunction());
  250. }
  251. return PreservedAnalyses::all();
  252. }));
  253. FunctionPassManager FPM2(/*DebugLogging*/ true);
  254. int FunctionPassRunCount2 = 0;
  255. FPM2.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
  256. ++FunctionPassRunCount2;
  257. return PreservedAnalyses::none();
  258. }));
  259. CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
  260. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
  261. FunctionPassManager FPM3(/*DebugLogging*/ true);
  262. int FunctionPassRunCount3 = 0;
  263. FPM3.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
  264. ++FunctionPassRunCount3;
  265. return PreservedAnalyses::none();
  266. }));
  267. MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM3)));
  268. MPM.run(*M, MAM);
  269. EXPECT_EQ(4, SCCPassRunCount1);
  270. EXPECT_EQ(6, FunctionPassRunCount1);
  271. EXPECT_EQ(6, FunctionPassRunCount2);
  272. EXPECT_EQ(6, FunctionPassRunCount3);
  273. EXPECT_EQ(1, ModuleAnalysisRuns);
  274. EXPECT_EQ(4, SCCAnalysisRuns);
  275. EXPECT_EQ(6, FunctionAnalysisRuns);
  276. EXPECT_EQ(6, ImmutableFunctionAnalysisRuns);
  277. EXPECT_EQ(14, AnalyzedInstrCount1);
  278. EXPECT_EQ(6, AnalyzedSCCFunctionCount1);
  279. EXPECT_EQ(4 * 6, AnalyzedModuleFunctionCount1);
  280. }
  281. // Test that an SCC pass which fails to preserve a module analysis does in fact
  282. // invalidate that module analysis.
  283. TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesModuleAnalysis) {
  284. int ModuleAnalysisRuns = 0;
  285. MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
  286. ModulePassManager MPM(/*DebugLogging*/ true);
  287. MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
  288. // The first CGSCC run we preserve everything and make sure that works and
  289. // the module analysis is available in the second CGSCC run from the one
  290. // required module pass above.
  291. CGSCCPassManager CGPM1(/*DebugLogging*/ true);
  292. int CountFoundModuleAnalysis1 = 0;
  293. CGPM1.addPass(
  294. LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
  295. LazyCallGraph &CG, CGSCCUpdateResult &UR) {
  296. const auto &MAM =
  297. AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
  298. auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
  299. *C.begin()->getFunction().getParent());
  300. if (TMA)
  301. ++CountFoundModuleAnalysis1;
  302. return PreservedAnalyses::all();
  303. }));
  304. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
  305. // The second CGSCC run checks that the module analysis got preserved the
  306. // previous time and in one SCC fails to preserve it.
  307. CGSCCPassManager CGPM2(/*DebugLogging*/ true);
  308. int CountFoundModuleAnalysis2 = 0;
  309. CGPM2.addPass(
  310. LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
  311. LazyCallGraph &CG, CGSCCUpdateResult &UR) {
  312. const auto &MAM =
  313. AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
  314. auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
  315. *C.begin()->getFunction().getParent());
  316. if (TMA)
  317. ++CountFoundModuleAnalysis2;
  318. // Only fail to preserve analyses on one SCC and make sure that gets
  319. // propagated.
  320. return C.getName() == "(g)" ? PreservedAnalyses::none()
  321. : PreservedAnalyses::all();
  322. }));
  323. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
  324. // The third CGSCC run should fail to find a cached module analysis as it
  325. // should have been invalidated by the above CGSCC run.
  326. CGSCCPassManager CGPM3(/*DebugLogging*/ true);
  327. int CountFoundModuleAnalysis3 = 0;
  328. CGPM3.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. if (TMA)
  336. ++CountFoundModuleAnalysis3;
  337. return PreservedAnalyses::none();
  338. }));
  339. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
  340. MPM.run(*M, MAM);
  341. EXPECT_EQ(1, ModuleAnalysisRuns);
  342. EXPECT_EQ(4, CountFoundModuleAnalysis1);
  343. EXPECT_EQ(4, CountFoundModuleAnalysis2);
  344. EXPECT_EQ(0, CountFoundModuleAnalysis3);
  345. }
  346. // Similar to the above, but test that this works for function passes embedded
  347. // *within* a CGSCC layer.
  348. TEST_F(CGSCCPassManagerTest, TestFunctionPassInsideCGSCCInvalidatesModuleAnalysis) {
  349. int ModuleAnalysisRuns = 0;
  350. MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
  351. ModulePassManager MPM(/*DebugLogging*/ true);
  352. MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
  353. // The first run we preserve everything and make sure that works and the
  354. // module analysis is available in the second run from the one required
  355. // module pass above.
  356. FunctionPassManager FPM1(/*DebugLogging*/ true);
  357. // Start true and mark false if we ever failed to find a module analysis
  358. // because we expect this to succeed for each SCC.
  359. bool FoundModuleAnalysis1 = true;
  360. FPM1.addPass(
  361. LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
  362. const auto &MAM =
  363. AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
  364. auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
  365. if (!TMA)
  366. FoundModuleAnalysis1 = false;
  367. return PreservedAnalyses::all();
  368. }));
  369. CGSCCPassManager CGPM1(/*DebugLogging*/ true);
  370. CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
  371. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
  372. // The second run checks that the module analysis got preserved the previous
  373. // time and in one function fails to preserve it.
  374. FunctionPassManager FPM2(/*DebugLogging*/ true);
  375. // Again, start true and mark false if we ever failed to find a module analysis
  376. // because we expect this to succeed for each SCC.
  377. bool FoundModuleAnalysis2 = true;
  378. FPM2.addPass(
  379. LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
  380. const auto &MAM =
  381. AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
  382. auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
  383. if (!TMA)
  384. FoundModuleAnalysis2 = false;
  385. // Only fail to preserve analyses on one SCC and make sure that gets
  386. // propagated.
  387. return F.getName() == "h2" ? PreservedAnalyses::none()
  388. : PreservedAnalyses::all();
  389. }));
  390. CGSCCPassManager CGPM2(/*DebugLogging*/ true);
  391. CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
  392. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
  393. // The third run should fail to find a cached module analysis as it should
  394. // have been invalidated by the above run.
  395. FunctionPassManager FPM3(/*DebugLogging*/ true);
  396. // Start false and mark true if we ever *succeeded* to find a module
  397. // analysis, as we expect this to fail for every function.
  398. bool FoundModuleAnalysis3 = false;
  399. FPM3.addPass(
  400. LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
  401. const auto &MAM =
  402. AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
  403. auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
  404. if (TMA)
  405. FoundModuleAnalysis3 = true;
  406. return PreservedAnalyses::none();
  407. }));
  408. CGSCCPassManager CGPM3(/*DebugLogging*/ true);
  409. CGPM3.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM3)));
  410. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
  411. MPM.run(*M, MAM);
  412. EXPECT_EQ(1, ModuleAnalysisRuns);
  413. EXPECT_TRUE(FoundModuleAnalysis1);
  414. EXPECT_TRUE(FoundModuleAnalysis2);
  415. EXPECT_FALSE(FoundModuleAnalysis3);
  416. }
  417. // Test that a Module pass which fails to preserve an SCC analysis in fact
  418. // invalidates that analysis.
  419. TEST_F(CGSCCPassManagerTest, TestModulePassInvalidatesSCCAnalysis) {
  420. int SCCAnalysisRuns = 0;
  421. CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
  422. ModulePassManager MPM(/*DebugLogging*/ true);
  423. // First force the analysis to be run.
  424. CGSCCPassManager CGPM1(/*DebugLogging*/ true);
  425. CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
  426. CGSCCAnalysisManager, LazyCallGraph &,
  427. CGSCCUpdateResult &>());
  428. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
  429. // Now run a module pass that preserves the LazyCallGraph and the proxy but
  430. // not the SCC analysis.
  431. MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
  432. PreservedAnalyses PA;
  433. PA.preserve<LazyCallGraphAnalysis>();
  434. PA.preserve<CGSCCAnalysisManagerModuleProxy>();
  435. PA.preserve<FunctionAnalysisManagerModuleProxy>();
  436. return PA;
  437. }));
  438. // And now a second CGSCC run which requires the SCC analysis again. This
  439. // will trigger re-running it.
  440. CGSCCPassManager CGPM2(/*DebugLogging*/ true);
  441. CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
  442. CGSCCAnalysisManager, LazyCallGraph &,
  443. CGSCCUpdateResult &>());
  444. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
  445. MPM.run(*M, MAM);
  446. // Two runs and four SCCs.
  447. EXPECT_EQ(2 * 4, SCCAnalysisRuns);
  448. }
  449. // Check that marking the SCC analysis preserved is sufficient to avoid
  450. // invaliadtion. This should only run the analysis once for each SCC.
  451. TEST_F(CGSCCPassManagerTest, TestModulePassCanPreserveSCCAnalysis) {
  452. int SCCAnalysisRuns = 0;
  453. CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
  454. ModulePassManager MPM(/*DebugLogging*/ true);
  455. // First force the analysis to be run.
  456. CGSCCPassManager CGPM1(/*DebugLogging*/ true);
  457. CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
  458. CGSCCAnalysisManager, LazyCallGraph &,
  459. CGSCCUpdateResult &>());
  460. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
  461. // Now run a module pass that preserves each of the necessary components
  462. // (but not everything).
  463. MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
  464. PreservedAnalyses PA;
  465. PA.preserve<LazyCallGraphAnalysis>();
  466. PA.preserve<CGSCCAnalysisManagerModuleProxy>();
  467. PA.preserve<FunctionAnalysisManagerModuleProxy>();
  468. PA.preserve<TestSCCAnalysis>();
  469. return PA;
  470. }));
  471. // And now a second CGSCC run which requires the SCC analysis again but find
  472. // it in the cache.
  473. CGSCCPassManager CGPM2(/*DebugLogging*/ true);
  474. CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
  475. CGSCCAnalysisManager, LazyCallGraph &,
  476. CGSCCUpdateResult &>());
  477. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
  478. MPM.run(*M, MAM);
  479. // Four SCCs
  480. EXPECT_EQ(4, SCCAnalysisRuns);
  481. }
  482. // Check that even when the analysis is preserved, if the SCC information isn't
  483. // we still nuke things because the SCC keys could change.
  484. TEST_F(CGSCCPassManagerTest, TestModulePassInvalidatesSCCAnalysisOnCGChange) {
  485. int SCCAnalysisRuns = 0;
  486. CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
  487. ModulePassManager MPM(/*DebugLogging*/ true);
  488. // First force the analysis to be run.
  489. CGSCCPassManager CGPM1(/*DebugLogging*/ true);
  490. CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
  491. CGSCCAnalysisManager, LazyCallGraph &,
  492. CGSCCUpdateResult &>());
  493. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
  494. // Now run a module pass that preserves the analysis but not the call
  495. // graph or proxy.
  496. MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
  497. PreservedAnalyses PA;
  498. PA.preserve<TestSCCAnalysis>();
  499. return PA;
  500. }));
  501. // And now a second CGSCC run which requires the SCC analysis again.
  502. CGSCCPassManager CGPM2(/*DebugLogging*/ true);
  503. CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
  504. CGSCCAnalysisManager, LazyCallGraph &,
  505. CGSCCUpdateResult &>());
  506. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
  507. MPM.run(*M, MAM);
  508. // Two runs and four SCCs.
  509. EXPECT_EQ(2 * 4, SCCAnalysisRuns);
  510. }
  511. // Test that an SCC pass which fails to preserve a Function analysis in fact
  512. // invalidates that analysis.
  513. TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesFunctionAnalysis) {
  514. int FunctionAnalysisRuns = 0;
  515. FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
  516. // Create a very simple module with a single function and SCC to make testing
  517. // these issues much easier.
  518. std::unique_ptr<Module> M = parseIR("declare void @g()\n"
  519. "declare void @h()\n"
  520. "define void @f() {\n"
  521. "entry:\n"
  522. " call void @g()\n"
  523. " call void @h()\n"
  524. " ret void\n"
  525. "}\n");
  526. CGSCCPassManager CGPM(/*DebugLogging*/ true);
  527. // First force the analysis to be run.
  528. FunctionPassManager FPM1(/*DebugLogging*/ true);
  529. FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
  530. CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
  531. // Now run a module pass that preserves the LazyCallGraph and proxy but not
  532. // the SCC analysis.
  533. CGPM.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
  534. LazyCallGraph &, CGSCCUpdateResult &) {
  535. PreservedAnalyses PA;
  536. PA.preserve<LazyCallGraphAnalysis>();
  537. return PA;
  538. }));
  539. // And now a second CGSCC run which requires the SCC analysis again. This
  540. // will trigger re-running it.
  541. FunctionPassManager FPM2(/*DebugLogging*/ true);
  542. FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
  543. CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
  544. ModulePassManager MPM(/*DebugLogging*/ true);
  545. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
  546. MPM.run(*M, MAM);
  547. EXPECT_EQ(2, FunctionAnalysisRuns);
  548. }
  549. // Check that marking the SCC analysis preserved is sufficient. This should
  550. // only run the analysis once the SCC.
  551. TEST_F(CGSCCPassManagerTest, TestSCCPassCanPreserveFunctionAnalysis) {
  552. int FunctionAnalysisRuns = 0;
  553. FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
  554. // Create a very simple module with a single function and SCC to make testing
  555. // these issues much easier.
  556. std::unique_ptr<Module> M = parseIR("declare void @g()\n"
  557. "declare void @h()\n"
  558. "define void @f() {\n"
  559. "entry:\n"
  560. " call void @g()\n"
  561. " call void @h()\n"
  562. " ret void\n"
  563. "}\n");
  564. CGSCCPassManager CGPM(/*DebugLogging*/ true);
  565. // First force the analysis to be run.
  566. FunctionPassManager FPM1(/*DebugLogging*/ true);
  567. FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
  568. CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
  569. // Now run a module pass that preserves each of the necessary components
  570. // (but
  571. // not everything).
  572. CGPM.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
  573. LazyCallGraph &, CGSCCUpdateResult &) {
  574. PreservedAnalyses PA;
  575. PA.preserve<LazyCallGraphAnalysis>();
  576. PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
  577. PA.preserve<TestFunctionAnalysis>();
  578. return PA;
  579. }));
  580. // And now a second CGSCC run which requires the SCC analysis again but find
  581. // it in the cache.
  582. FunctionPassManager FPM2(/*DebugLogging*/ true);
  583. FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
  584. CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
  585. ModulePassManager MPM(/*DebugLogging*/ true);
  586. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
  587. MPM.run(*M, MAM);
  588. EXPECT_EQ(1, FunctionAnalysisRuns);
  589. }
  590. // Note that there is no test for invalidating the call graph or other
  591. // structure with an SCC pass because there is no mechanism to do that from
  592. // withinsuch a pass. Instead, such a pass has to directly update the call
  593. // graph structure.
  594. // Test that a madule pass invalidates function analyses when the CGSCC proxies
  595. // and pass manager.
  596. TEST_F(CGSCCPassManagerTest,
  597. TestModulePassInvalidatesFunctionAnalysisNestedInCGSCC) {
  598. MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
  599. int FunctionAnalysisRuns = 0;
  600. FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
  601. ModulePassManager MPM(/*DebugLogging*/ true);
  602. // First force the analysis to be run.
  603. FunctionPassManager FPM1(/*DebugLogging*/ true);
  604. FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
  605. CGSCCPassManager CGPM1(/*DebugLogging*/ true);
  606. CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
  607. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
  608. // Now run a module pass that preserves the LazyCallGraph and proxies but not
  609. // the Function analysis.
  610. MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
  611. PreservedAnalyses PA;
  612. PA.preserve<LazyCallGraphAnalysis>();
  613. PA.preserve<CGSCCAnalysisManagerModuleProxy>();
  614. PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
  615. PA.preserve<FunctionAnalysisManagerModuleProxy>();
  616. return PA;
  617. }));
  618. // And now a second CGSCC run which requires the SCC analysis again. This
  619. // will trigger re-running it.
  620. FunctionPassManager FPM2(/*DebugLogging*/ true);
  621. FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
  622. CGSCCPassManager CGPM2(/*DebugLogging*/ true);
  623. CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
  624. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
  625. MPM.run(*M, MAM);
  626. // Two runs and 6 functions.
  627. EXPECT_EQ(2 * 6, FunctionAnalysisRuns);
  628. }
  629. // Check that by marking the function pass and proxies as preserved, this
  630. // propagates all the way through.
  631. TEST_F(CGSCCPassManagerTest,
  632. TestModulePassCanPreserveFunctionAnalysisNestedInCGSCC) {
  633. MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
  634. int FunctionAnalysisRuns = 0;
  635. FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
  636. ModulePassManager MPM(/*DebugLogging*/ true);
  637. // First force the analysis to be run.
  638. FunctionPassManager FPM1(/*DebugLogging*/ true);
  639. FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
  640. CGSCCPassManager CGPM1(/*DebugLogging*/ true);
  641. CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
  642. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
  643. // Now run a module pass that preserves the LazyCallGraph, the proxy, and
  644. // the Function analysis.
  645. MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
  646. PreservedAnalyses PA;
  647. PA.preserve<LazyCallGraphAnalysis>();
  648. PA.preserve<CGSCCAnalysisManagerModuleProxy>();
  649. PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
  650. PA.preserve<FunctionAnalysisManagerModuleProxy>();
  651. PA.preserve<TestFunctionAnalysis>();
  652. return PA;
  653. }));
  654. // And now a second CGSCC run which requires the SCC analysis again. This
  655. // will trigger re-running it.
  656. FunctionPassManager FPM2(/*DebugLogging*/ true);
  657. FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
  658. CGSCCPassManager CGPM2(/*DebugLogging*/ true);
  659. CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
  660. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
  661. MPM.run(*M, MAM);
  662. // One run and 6 functions.
  663. EXPECT_EQ(6, FunctionAnalysisRuns);
  664. }
  665. // Check that if the lazy call graph itself isn't preserved we still manage to
  666. // invalidate everything.
  667. TEST_F(CGSCCPassManagerTest,
  668. TestModulePassInvalidatesFunctionAnalysisNestedInCGSCCOnCGChange) {
  669. MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
  670. int FunctionAnalysisRuns = 0;
  671. FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
  672. ModulePassManager MPM(/*DebugLogging*/ true);
  673. // First force the analysis to be run.
  674. FunctionPassManager FPM1(/*DebugLogging*/ true);
  675. FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
  676. CGSCCPassManager CGPM1(/*DebugLogging*/ true);
  677. CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
  678. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
  679. // Now run a module pass that preserves the LazyCallGraph but not the
  680. // Function analysis.
  681. MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
  682. PreservedAnalyses PA;
  683. return PA;
  684. }));
  685. // And now a second CGSCC run which requires the SCC analysis again. This
  686. // will trigger re-running it.
  687. FunctionPassManager FPM2(/*DebugLogging*/ true);
  688. FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
  689. CGSCCPassManager CGPM2(/*DebugLogging*/ true);
  690. CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
  691. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
  692. MPM.run(*M, MAM);
  693. // Two runs and 6 functions.
  694. EXPECT_EQ(2 * 6, FunctionAnalysisRuns);
  695. }
  696. /// A test CGSCC-level analysis pass which caches in its result another
  697. /// analysis pass and uses it to serve queries. This requires the result to
  698. /// invalidate itself when its dependency is invalidated.
  699. ///
  700. /// FIXME: Currently this doesn't also depend on a function analysis, and if it
  701. /// did we would fail to invalidate it correctly.
  702. struct TestIndirectSCCAnalysis
  703. : public AnalysisInfoMixin<TestIndirectSCCAnalysis> {
  704. struct Result {
  705. Result(TestSCCAnalysis::Result &SCCDep, TestModuleAnalysis::Result &MDep)
  706. : SCCDep(SCCDep), MDep(MDep) {}
  707. TestSCCAnalysis::Result &SCCDep;
  708. TestModuleAnalysis::Result &MDep;
  709. bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
  710. CGSCCAnalysisManager::Invalidator &Inv) {
  711. auto PAC = PA.getChecker<TestIndirectSCCAnalysis>();
  712. return !(PAC.preserved() ||
  713. PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>()) ||
  714. Inv.invalidate<TestSCCAnalysis>(C, PA);
  715. }
  716. };
  717. TestIndirectSCCAnalysis(int &Runs) : Runs(Runs) {}
  718. /// Run the analysis pass over the function and return a result.
  719. Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
  720. LazyCallGraph &CG) {
  721. ++Runs;
  722. auto &SCCDep = AM.getResult<TestSCCAnalysis>(C, CG);
  723. auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
  724. const ModuleAnalysisManager &MAM = ModuleProxy.getManager();
  725. // For the test, we insist that the module analysis starts off in the
  726. // cache.
  727. auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(
  728. *C.begin()->getFunction().getParent());
  729. // Register the dependency as module analysis dependencies have to be
  730. // pre-registered on the proxy.
  731. ModuleProxy.registerOuterAnalysisInvalidation<TestModuleAnalysis,
  732. TestIndirectSCCAnalysis>();
  733. return Result(SCCDep, MDep);
  734. }
  735. private:
  736. friend AnalysisInfoMixin<TestIndirectSCCAnalysis>;
  737. static AnalysisKey Key;
  738. int &Runs;
  739. };
  740. AnalysisKey TestIndirectSCCAnalysis::Key;
  741. /// A test analysis pass which caches in its result the result from the above
  742. /// indirect analysis pass.
  743. ///
  744. /// This allows us to ensure that whenever an analysis pass is invalidated due
  745. /// to dependencies (especially dependencies across IR units that trigger
  746. /// asynchronous invalidation) we correctly detect that this may in turn cause
  747. /// other analysis to be invalidated.
  748. struct TestDoublyIndirectSCCAnalysis
  749. : public AnalysisInfoMixin<TestDoublyIndirectSCCAnalysis> {
  750. struct Result {
  751. Result(TestIndirectSCCAnalysis::Result &IDep) : IDep(IDep) {}
  752. TestIndirectSCCAnalysis::Result &IDep;
  753. bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
  754. CGSCCAnalysisManager::Invalidator &Inv) {
  755. auto PAC = PA.getChecker<TestDoublyIndirectSCCAnalysis>();
  756. return !(PAC.preserved() ||
  757. PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>()) ||
  758. Inv.invalidate<TestIndirectSCCAnalysis>(C, PA);
  759. }
  760. };
  761. TestDoublyIndirectSCCAnalysis(int &Runs) : Runs(Runs) {}
  762. /// Run the analysis pass over the function and return a result.
  763. Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
  764. LazyCallGraph &CG) {
  765. ++Runs;
  766. auto &IDep = AM.getResult<TestIndirectSCCAnalysis>(C, CG);
  767. return Result(IDep);
  768. }
  769. private:
  770. friend AnalysisInfoMixin<TestDoublyIndirectSCCAnalysis>;
  771. static AnalysisKey Key;
  772. int &Runs;
  773. };
  774. AnalysisKey TestDoublyIndirectSCCAnalysis::Key;
  775. /// A test analysis pass which caches results from three different IR unit
  776. /// layers and requires intermediate layers to correctly propagate the entire
  777. /// distance.
  778. struct TestIndirectFunctionAnalysis
  779. : public AnalysisInfoMixin<TestIndirectFunctionAnalysis> {
  780. struct Result {
  781. Result(TestFunctionAnalysis::Result &FDep, TestModuleAnalysis::Result &MDep,
  782. TestSCCAnalysis::Result &SCCDep)
  783. : FDep(FDep), MDep(MDep), SCCDep(SCCDep) {}
  784. TestFunctionAnalysis::Result &FDep;
  785. TestModuleAnalysis::Result &MDep;
  786. TestSCCAnalysis::Result &SCCDep;
  787. bool invalidate(Function &F, const PreservedAnalyses &PA,
  788. FunctionAnalysisManager::Invalidator &Inv) {
  789. auto PAC = PA.getChecker<TestIndirectFunctionAnalysis>();
  790. return !(PAC.preserved() ||
  791. PAC.preservedSet<AllAnalysesOn<Function>>()) ||
  792. Inv.invalidate<TestFunctionAnalysis>(F, PA);
  793. }
  794. };
  795. TestIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {}
  796. /// Run the analysis pass over the function and return a result.
  797. Result run(Function &F, FunctionAnalysisManager &AM) {
  798. ++Runs;
  799. auto &FDep = AM.getResult<TestFunctionAnalysis>(F);
  800. auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
  801. const ModuleAnalysisManager &MAM = ModuleProxy.getManager();
  802. // For the test, we insist that the module analysis starts off in the
  803. // cache.
  804. auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
  805. // Register the dependency as module analysis dependencies have to be
  806. // pre-registered on the proxy.
  807. ModuleProxy.registerOuterAnalysisInvalidation<
  808. TestModuleAnalysis, TestIndirectFunctionAnalysis>();
  809. // For thet test we assume this is run inside a CGSCC pass manager.
  810. const LazyCallGraph &CG =
  811. *MAM.getCachedResult<LazyCallGraphAnalysis>(*F.getParent());
  812. auto &CGSCCProxy = AM.getResult<CGSCCAnalysisManagerFunctionProxy>(F);
  813. const CGSCCAnalysisManager &CGAM = CGSCCProxy.getManager();
  814. // For the test, we insist that the CGSCC analysis starts off in the cache.
  815. auto &SCCDep =
  816. *CGAM.getCachedResult<TestSCCAnalysis>(*CG.lookupSCC(*CG.lookup(F)));
  817. // Register the dependency as CGSCC analysis dependencies have to be
  818. // pre-registered on the proxy.
  819. CGSCCProxy.registerOuterAnalysisInvalidation<
  820. TestSCCAnalysis, TestIndirectFunctionAnalysis>();
  821. return Result(FDep, MDep, SCCDep);
  822. }
  823. private:
  824. friend AnalysisInfoMixin<TestIndirectFunctionAnalysis>;
  825. static AnalysisKey Key;
  826. int &Runs;
  827. };
  828. AnalysisKey TestIndirectFunctionAnalysis::Key;
  829. TEST_F(CGSCCPassManagerTest, TestIndirectAnalysisInvalidation) {
  830. int ModuleAnalysisRuns = 0;
  831. MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
  832. int SCCAnalysisRuns = 0, IndirectSCCAnalysisRuns = 0,
  833. DoublyIndirectSCCAnalysisRuns = 0;
  834. CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
  835. CGAM.registerPass(
  836. [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns); });
  837. CGAM.registerPass([&] {
  838. return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns);
  839. });
  840. int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0;
  841. FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
  842. FAM.registerPass([&] {
  843. return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns);
  844. });
  845. ModulePassManager MPM(/*DebugLogging*/ true);
  846. int FunctionCount = 0;
  847. CGSCCPassManager CGPM(/*DebugLogging*/ true);
  848. // First just use the analysis to get the function count and preserve
  849. // everything.
  850. CGPM.addPass(
  851. LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
  852. LazyCallGraph &CG, CGSCCUpdateResult &) {
  853. auto &DoublyIndirectResult =
  854. AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
  855. auto &IndirectResult = DoublyIndirectResult.IDep;
  856. FunctionCount += IndirectResult.SCCDep.FunctionCount;
  857. return PreservedAnalyses::all();
  858. }));
  859. CGPM.addPass(createCGSCCToFunctionPassAdaptor(
  860. RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>()));
  861. // Next, invalidate
  862. // - both analyses for the (f) and (x) SCCs,
  863. // - just the underlying (indirect) analysis for (g) SCC, and
  864. // - just the direct analysis for (h1,h2,h3) SCC.
  865. CGPM.addPass(
  866. LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
  867. LazyCallGraph &CG, CGSCCUpdateResult &) {
  868. auto &DoublyIndirectResult =
  869. AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
  870. auto &IndirectResult = DoublyIndirectResult.IDep;
  871. FunctionCount += IndirectResult.SCCDep.FunctionCount;
  872. auto PA = PreservedAnalyses::none();
  873. PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
  874. PA.preserveSet<AllAnalysesOn<Function>>();
  875. if (C.getName() == "(g)")
  876. PA.preserve<TestSCCAnalysis>();
  877. else if (C.getName() == "(h3, h1, h2)")
  878. PA.preserve<TestIndirectSCCAnalysis>();
  879. return PA;
  880. }));
  881. // Finally, use the analysis again on each SCC (and function), forcing
  882. // re-computation for all of them.
  883. CGPM.addPass(
  884. LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
  885. LazyCallGraph &CG, CGSCCUpdateResult &) {
  886. auto &DoublyIndirectResult =
  887. AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
  888. auto &IndirectResult = DoublyIndirectResult.IDep;
  889. FunctionCount += IndirectResult.SCCDep.FunctionCount;
  890. return PreservedAnalyses::all();
  891. }));
  892. CGPM.addPass(createCGSCCToFunctionPassAdaptor(
  893. RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>()));
  894. // Create a second CGSCC pass manager. This will cause the module-level
  895. // invalidation to occur, which will force yet another invalidation of the
  896. // indirect SCC-level analysis as the module analysis it depends on gets
  897. // invalidated.
  898. CGSCCPassManager CGPM2(/*DebugLogging*/ true);
  899. CGPM2.addPass(
  900. LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
  901. LazyCallGraph &CG, CGSCCUpdateResult &) {
  902. auto &DoublyIndirectResult =
  903. AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
  904. auto &IndirectResult = DoublyIndirectResult.IDep;
  905. FunctionCount += IndirectResult.SCCDep.FunctionCount;
  906. return PreservedAnalyses::all();
  907. }));
  908. CGPM2.addPass(createCGSCCToFunctionPassAdaptor(
  909. RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>()));
  910. // Add a requires pass to populate the module analysis and then our CGSCC
  911. // pass pipeline.
  912. MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
  913. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
  914. // Now require the module analysis again (it will have been invalidated once)
  915. // and then use it again from our second CGSCC pipeline..
  916. MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
  917. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
  918. MPM.run(*M, MAM);
  919. // There are generally two possible runs for each of the four SCCs. But
  920. // for one SCC, we only invalidate the indirect analysis so the base one
  921. // only gets run seven times.
  922. EXPECT_EQ(7, SCCAnalysisRuns);
  923. // The module analysis pass should be run twice here.
  924. EXPECT_EQ(2, ModuleAnalysisRuns);
  925. // The indirect analysis is invalidated (either directly or indirectly) three
  926. // times for each of four SCCs.
  927. EXPECT_EQ(3 * 4, IndirectSCCAnalysisRuns);
  928. EXPECT_EQ(3 * 4, DoublyIndirectSCCAnalysisRuns);
  929. // We run the indirect function analysis once per function the first time.
  930. // Then we re-run it for every SCC but "(g)". Then we re-run it for every
  931. // function again.
  932. EXPECT_EQ(6 + 5 + 6, IndirectFunctionAnalysisRuns);
  933. // Four passes count each of six functions once (via SCCs).
  934. EXPECT_EQ(4 * 6, FunctionCount);
  935. }
  936. TEST_F(CGSCCPassManagerTest, TestAnalysisInvalidationCGSCCUpdate) {
  937. int ModuleAnalysisRuns = 0;
  938. MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
  939. int SCCAnalysisRuns = 0, IndirectSCCAnalysisRuns = 0,
  940. DoublyIndirectSCCAnalysisRuns = 0;
  941. CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
  942. CGAM.registerPass(
  943. [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns); });
  944. CGAM.registerPass([&] {
  945. return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns);
  946. });
  947. int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0;
  948. FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
  949. FAM.registerPass([&] {
  950. return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns);
  951. });
  952. ModulePassManager MPM(/*DebugLogging*/ true);
  953. CGSCCPassManager CGPM(/*DebugLogging*/ true);
  954. // First just use the analysis to get the function count and preserve
  955. // everything.
  956. using RequireTestIndirectFunctionAnalysisPass =
  957. RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>;
  958. using RequireTestDoublyIndirectSCCAnalysisPass =
  959. RequireAnalysisPass<TestDoublyIndirectSCCAnalysis, LazyCallGraph::SCC,
  960. CGSCCAnalysisManager, LazyCallGraph &,
  961. CGSCCUpdateResult &>;
  962. CGPM.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
  963. CGPM.addPass(createCGSCCToFunctionPassAdaptor(
  964. RequireTestIndirectFunctionAnalysisPass()));
  965. // Next, we inject an SCC pass that invalidates everything for the `(h3, h1,
  966. // h2)` SCC but also deletes the call edge from `h2` to `h3` and updates the
  967. // CG. This should successfully invalidate (and force to be re-run) all the
  968. // analyses for that SCC and for the functions.
  969. CGPM.addPass(
  970. LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
  971. LazyCallGraph &CG, CGSCCUpdateResult &UR) {
  972. (void)AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
  973. if (C.getName() != "(h3, h1, h2)")
  974. return PreservedAnalyses::all();
  975. // Build the preserved set.
  976. auto PA = PreservedAnalyses::none();
  977. PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
  978. PA.preserve<TestIndirectSCCAnalysis>();
  979. PA.preserve<TestDoublyIndirectSCCAnalysis>();
  980. // Delete the call from `h2` to `h3`.
  981. auto &H2N = *llvm::find_if(
  982. C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; });
  983. auto &H2F = H2N.getFunction();
  984. auto &H3F = *cast<CallInst>(H2F.begin()->begin())->getCalledFunction();
  985. assert(H3F.getName() == "h3" && "Wrong called function!");
  986. H2F.begin()->begin()->eraseFromParent();
  987. // Insert a bitcast of `h3` so that we retain a ref edge to it.
  988. (void)CastInst::CreatePointerCast(&H3F,
  989. Type::getInt8PtrTy(H2F.getContext()),
  990. "dummy", &*H2F.begin()->begin());
  991. // Now update the call graph.
  992. auto &NewC =
  993. updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR);
  994. assert(&NewC != &C && "Should get a new SCC due to update!");
  995. (void)&NewC;
  996. return PA;
  997. }));
  998. // Now use the analysis again on each SCC and function, forcing
  999. // re-computation for all of them.
  1000. CGPM.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
  1001. CGPM.addPass(createCGSCCToFunctionPassAdaptor(
  1002. RequireTestIndirectFunctionAnalysisPass()));
  1003. // Create another CGSCC pipeline that requires all the analyses again.
  1004. CGSCCPassManager CGPM2(/*DebugLogging*/ true);
  1005. CGPM2.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
  1006. CGPM2.addPass(createCGSCCToFunctionPassAdaptor(
  1007. RequireTestIndirectFunctionAnalysisPass()));
  1008. // Next we inject an SCC pass that finds the `(h2)` SCC, adds a call to `h3`
  1009. // back to `h2`, and then invalidates everything for what will then be the
  1010. // `(h3, h1, h2)` SCC again.
  1011. CGSCCPassManager CGPM3(/*DebugLogging*/ true);
  1012. CGPM3.addPass(
  1013. LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
  1014. LazyCallGraph &CG, CGSCCUpdateResult &UR) {
  1015. (void)AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
  1016. if (C.getName() != "(h2)")
  1017. return PreservedAnalyses::all();
  1018. // Build the preserved set.
  1019. auto PA = PreservedAnalyses::none();
  1020. PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
  1021. PA.preserve<TestIndirectSCCAnalysis>();
  1022. PA.preserve<TestDoublyIndirectSCCAnalysis>();
  1023. // Delete the bitcast of `h3` that we added earlier.
  1024. auto &H2N = *C.begin();
  1025. auto &H2F = H2N.getFunction();
  1026. auto &H3F = *cast<Function>(cast<BitCastInst>(H2F.begin()->begin())->getOperand(0));
  1027. assert(H3F.getName() == "h3" && "Wrong called function!");
  1028. H2F.begin()->begin()->eraseFromParent();
  1029. // And insert a call to `h3`.
  1030. (void)CallInst::Create(&H3F, {}, "", &*H2F.begin()->begin());
  1031. // Now update the call graph.
  1032. auto &NewC =
  1033. updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR);
  1034. assert(&NewC != &C && "Should get a new SCC due to update!");
  1035. (void)&NewC;
  1036. return PA;
  1037. }));
  1038. // Now use the analysis again on each SCC and function, forcing
  1039. // re-computation for all of them.
  1040. CGPM3.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
  1041. CGPM3.addPass(createCGSCCToFunctionPassAdaptor(
  1042. RequireTestIndirectFunctionAnalysisPass()));
  1043. // Create a second CGSCC pass manager. This will cause the module-level
  1044. // invalidation to occur, which will force yet another invalidation of the
  1045. // indirect SCC-level analysis as the module analysis it depends on gets
  1046. // invalidated.
  1047. CGSCCPassManager CGPM4(/*DebugLogging*/ true);
  1048. CGPM4.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
  1049. CGPM4.addPass(createCGSCCToFunctionPassAdaptor(
  1050. RequireTestIndirectFunctionAnalysisPass()));
  1051. // Add a requires pass to populate the module analysis and then one of our
  1052. // CGSCC pipelines. Repeat for all four CGSCC pipelines.
  1053. MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
  1054. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
  1055. MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
  1056. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
  1057. MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
  1058. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
  1059. MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
  1060. MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM4)));
  1061. MPM.run(*M, MAM);
  1062. // We run over four SCCs the first time. But then we split an SCC into three.
  1063. // And then we merge those three back into one. However, this also
  1064. // invalidates all three SCCs further down in the PO walk.
  1065. EXPECT_EQ(4 + 3 + 1 + 3, SCCAnalysisRuns);
  1066. // The module analysis pass should be run three times.
  1067. EXPECT_EQ(3, ModuleAnalysisRuns);
  1068. // We run over four SCCs the first time. Then over the two new ones. Then the
  1069. // entire module is invalidated causing a full run over all seven. Then we
  1070. // fold three SCCs back to one, re-compute for it and the two SCCs above it
  1071. // in the graph, and then run over the whole module again.
  1072. EXPECT_EQ(4 + 2 + 7 + 1 + 3 + 4, IndirectSCCAnalysisRuns);
  1073. EXPECT_EQ(4 + 2 + 7 + 1 + 3 + 4, DoublyIndirectSCCAnalysisRuns);
  1074. // First we run over all six functions. Then we re-run it over three when we
  1075. // split their SCCs. Then we re-run over the whole module. Then we re-run
  1076. // over three functions merged back into a single SCC, then those three
  1077. // functions again, the two functions in SCCs above it in the graph, and then
  1078. // over the whole module again.
  1079. EXPECT_EQ(6 + 3 + 6 + 3 + 3 + 2 + 6, FunctionAnalysisRuns);
  1080. // Re run the function analysis over the entire module, and then re-run it
  1081. // over the `(h3, h1, h2)` SCC due to invalidation. Then we re-run it over
  1082. // the entire module, then the three functions merged back into a single SCC,
  1083. // those three functions again, then the two functions in SCCs above it in
  1084. // the graph, and then over the whole module.
  1085. EXPECT_EQ(6 + 3 + 6 + 3 + 3 + 2 + 6, IndirectFunctionAnalysisRuns);
  1086. }
  1087. }