LazyCallGraphTest.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  1. //===- LazyCallGraphTest.cpp - Unit tests for the lazy CG analysis --------===//
  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. #include "llvm/Analysis/LazyCallGraph.h"
  10. #include "llvm/AsmParser/Parser.h"
  11. #include "llvm/IR/Function.h"
  12. #include "llvm/IR/LLVMContext.h"
  13. #include "llvm/IR/Module.h"
  14. #include "llvm/Support/ErrorHandling.h"
  15. #include "llvm/Support/SourceMgr.h"
  16. #include "gtest/gtest.h"
  17. #include <memory>
  18. using namespace llvm;
  19. namespace {
  20. std::unique_ptr<Module> parseAssembly(const char *Assembly) {
  21. SMDiagnostic Error;
  22. std::unique_ptr<Module> M =
  23. parseAssemblyString(Assembly, Error, getGlobalContext());
  24. std::string ErrMsg;
  25. raw_string_ostream OS(ErrMsg);
  26. Error.print("", OS);
  27. // A failure here means that the test itself is buggy.
  28. if (!M)
  29. report_fatal_error(OS.str().c_str());
  30. return M;
  31. }
  32. /*
  33. IR forming a call graph with a diamond of triangle-shaped SCCs:
  34. d1
  35. / \
  36. d3--d2
  37. / \
  38. b1 c1
  39. / \ / \
  40. b3--b2 c3--c2
  41. \ /
  42. a1
  43. / \
  44. a3--a2
  45. All call edges go up between SCCs, and clockwise around the SCC.
  46. */
  47. static const char DiamondOfTriangles[] =
  48. "define void @a1() {\n"
  49. "entry:\n"
  50. " call void @a2()\n"
  51. " call void @b2()\n"
  52. " call void @c3()\n"
  53. " ret void\n"
  54. "}\n"
  55. "define void @a2() {\n"
  56. "entry:\n"
  57. " call void @a3()\n"
  58. " ret void\n"
  59. "}\n"
  60. "define void @a3() {\n"
  61. "entry:\n"
  62. " call void @a1()\n"
  63. " ret void\n"
  64. "}\n"
  65. "define void @b1() {\n"
  66. "entry:\n"
  67. " call void @b2()\n"
  68. " call void @d3()\n"
  69. " ret void\n"
  70. "}\n"
  71. "define void @b2() {\n"
  72. "entry:\n"
  73. " call void @b3()\n"
  74. " ret void\n"
  75. "}\n"
  76. "define void @b3() {\n"
  77. "entry:\n"
  78. " call void @b1()\n"
  79. " ret void\n"
  80. "}\n"
  81. "define void @c1() {\n"
  82. "entry:\n"
  83. " call void @c2()\n"
  84. " call void @d2()\n"
  85. " ret void\n"
  86. "}\n"
  87. "define void @c2() {\n"
  88. "entry:\n"
  89. " call void @c3()\n"
  90. " ret void\n"
  91. "}\n"
  92. "define void @c3() {\n"
  93. "entry:\n"
  94. " call void @c1()\n"
  95. " ret void\n"
  96. "}\n"
  97. "define void @d1() {\n"
  98. "entry:\n"
  99. " call void @d2()\n"
  100. " ret void\n"
  101. "}\n"
  102. "define void @d2() {\n"
  103. "entry:\n"
  104. " call void @d3()\n"
  105. " ret void\n"
  106. "}\n"
  107. "define void @d3() {\n"
  108. "entry:\n"
  109. " call void @d1()\n"
  110. " ret void\n"
  111. "}\n";
  112. TEST(LazyCallGraphTest, BasicGraphFormation) {
  113. std::unique_ptr<Module> M = parseAssembly(DiamondOfTriangles);
  114. LazyCallGraph CG(*M);
  115. // The order of the entry nodes should be stable w.r.t. the source order of
  116. // the IR, and everything in our module is an entry node, so just directly
  117. // build variables for each node.
  118. auto I = CG.begin();
  119. LazyCallGraph::Node &A1 = *I++;
  120. EXPECT_EQ("a1", A1.getFunction().getName());
  121. LazyCallGraph::Node &A2 = *I++;
  122. EXPECT_EQ("a2", A2.getFunction().getName());
  123. LazyCallGraph::Node &A3 = *I++;
  124. EXPECT_EQ("a3", A3.getFunction().getName());
  125. LazyCallGraph::Node &B1 = *I++;
  126. EXPECT_EQ("b1", B1.getFunction().getName());
  127. LazyCallGraph::Node &B2 = *I++;
  128. EXPECT_EQ("b2", B2.getFunction().getName());
  129. LazyCallGraph::Node &B3 = *I++;
  130. EXPECT_EQ("b3", B3.getFunction().getName());
  131. LazyCallGraph::Node &C1 = *I++;
  132. EXPECT_EQ("c1", C1.getFunction().getName());
  133. LazyCallGraph::Node &C2 = *I++;
  134. EXPECT_EQ("c2", C2.getFunction().getName());
  135. LazyCallGraph::Node &C3 = *I++;
  136. EXPECT_EQ("c3", C3.getFunction().getName());
  137. LazyCallGraph::Node &D1 = *I++;
  138. EXPECT_EQ("d1", D1.getFunction().getName());
  139. LazyCallGraph::Node &D2 = *I++;
  140. EXPECT_EQ("d2", D2.getFunction().getName());
  141. LazyCallGraph::Node &D3 = *I++;
  142. EXPECT_EQ("d3", D3.getFunction().getName());
  143. EXPECT_EQ(CG.end(), I);
  144. // Build vectors and sort them for the rest of the assertions to make them
  145. // independent of order.
  146. std::vector<std::string> Nodes;
  147. for (LazyCallGraph::Node &N : A1)
  148. Nodes.push_back(N.getFunction().getName());
  149. std::sort(Nodes.begin(), Nodes.end());
  150. EXPECT_EQ("a2", Nodes[0]);
  151. EXPECT_EQ("b2", Nodes[1]);
  152. EXPECT_EQ("c3", Nodes[2]);
  153. Nodes.clear();
  154. EXPECT_EQ(A2.end(), std::next(A2.begin()));
  155. EXPECT_EQ("a3", A2.begin()->getFunction().getName());
  156. EXPECT_EQ(A3.end(), std::next(A3.begin()));
  157. EXPECT_EQ("a1", A3.begin()->getFunction().getName());
  158. for (LazyCallGraph::Node &N : B1)
  159. Nodes.push_back(N.getFunction().getName());
  160. std::sort(Nodes.begin(), Nodes.end());
  161. EXPECT_EQ("b2", Nodes[0]);
  162. EXPECT_EQ("d3", Nodes[1]);
  163. Nodes.clear();
  164. EXPECT_EQ(B2.end(), std::next(B2.begin()));
  165. EXPECT_EQ("b3", B2.begin()->getFunction().getName());
  166. EXPECT_EQ(B3.end(), std::next(B3.begin()));
  167. EXPECT_EQ("b1", B3.begin()->getFunction().getName());
  168. for (LazyCallGraph::Node &N : C1)
  169. Nodes.push_back(N.getFunction().getName());
  170. std::sort(Nodes.begin(), Nodes.end());
  171. EXPECT_EQ("c2", Nodes[0]);
  172. EXPECT_EQ("d2", Nodes[1]);
  173. Nodes.clear();
  174. EXPECT_EQ(C2.end(), std::next(C2.begin()));
  175. EXPECT_EQ("c3", C2.begin()->getFunction().getName());
  176. EXPECT_EQ(C3.end(), std::next(C3.begin()));
  177. EXPECT_EQ("c1", C3.begin()->getFunction().getName());
  178. EXPECT_EQ(D1.end(), std::next(D1.begin()));
  179. EXPECT_EQ("d2", D1.begin()->getFunction().getName());
  180. EXPECT_EQ(D2.end(), std::next(D2.begin()));
  181. EXPECT_EQ("d3", D2.begin()->getFunction().getName());
  182. EXPECT_EQ(D3.end(), std::next(D3.begin()));
  183. EXPECT_EQ("d1", D3.begin()->getFunction().getName());
  184. // Now lets look at the SCCs.
  185. auto SCCI = CG.postorder_scc_begin();
  186. LazyCallGraph::SCC &D = *SCCI++;
  187. for (LazyCallGraph::Node *N : D)
  188. Nodes.push_back(N->getFunction().getName());
  189. std::sort(Nodes.begin(), Nodes.end());
  190. EXPECT_EQ(3u, Nodes.size());
  191. EXPECT_EQ("d1", Nodes[0]);
  192. EXPECT_EQ("d2", Nodes[1]);
  193. EXPECT_EQ("d3", Nodes[2]);
  194. Nodes.clear();
  195. EXPECT_FALSE(D.isParentOf(D));
  196. EXPECT_FALSE(D.isChildOf(D));
  197. EXPECT_FALSE(D.isAncestorOf(D));
  198. EXPECT_FALSE(D.isDescendantOf(D));
  199. LazyCallGraph::SCC &C = *SCCI++;
  200. for (LazyCallGraph::Node *N : C)
  201. Nodes.push_back(N->getFunction().getName());
  202. std::sort(Nodes.begin(), Nodes.end());
  203. EXPECT_EQ(3u, Nodes.size());
  204. EXPECT_EQ("c1", Nodes[0]);
  205. EXPECT_EQ("c2", Nodes[1]);
  206. EXPECT_EQ("c3", Nodes[2]);
  207. Nodes.clear();
  208. EXPECT_TRUE(C.isParentOf(D));
  209. EXPECT_FALSE(C.isChildOf(D));
  210. EXPECT_TRUE(C.isAncestorOf(D));
  211. EXPECT_FALSE(C.isDescendantOf(D));
  212. LazyCallGraph::SCC &B = *SCCI++;
  213. for (LazyCallGraph::Node *N : B)
  214. Nodes.push_back(N->getFunction().getName());
  215. std::sort(Nodes.begin(), Nodes.end());
  216. EXPECT_EQ(3u, Nodes.size());
  217. EXPECT_EQ("b1", Nodes[0]);
  218. EXPECT_EQ("b2", Nodes[1]);
  219. EXPECT_EQ("b3", Nodes[2]);
  220. Nodes.clear();
  221. EXPECT_TRUE(B.isParentOf(D));
  222. EXPECT_FALSE(B.isChildOf(D));
  223. EXPECT_TRUE(B.isAncestorOf(D));
  224. EXPECT_FALSE(B.isDescendantOf(D));
  225. EXPECT_FALSE(B.isAncestorOf(C));
  226. EXPECT_FALSE(C.isAncestorOf(B));
  227. LazyCallGraph::SCC &A = *SCCI++;
  228. for (LazyCallGraph::Node *N : A)
  229. Nodes.push_back(N->getFunction().getName());
  230. std::sort(Nodes.begin(), Nodes.end());
  231. EXPECT_EQ(3u, Nodes.size());
  232. EXPECT_EQ("a1", Nodes[0]);
  233. EXPECT_EQ("a2", Nodes[1]);
  234. EXPECT_EQ("a3", Nodes[2]);
  235. Nodes.clear();
  236. EXPECT_TRUE(A.isParentOf(B));
  237. EXPECT_TRUE(A.isParentOf(C));
  238. EXPECT_FALSE(A.isParentOf(D));
  239. EXPECT_TRUE(A.isAncestorOf(B));
  240. EXPECT_TRUE(A.isAncestorOf(C));
  241. EXPECT_TRUE(A.isAncestorOf(D));
  242. EXPECT_EQ(CG.postorder_scc_end(), SCCI);
  243. }
  244. static Function &lookupFunction(Module &M, StringRef Name) {
  245. for (Function &F : M)
  246. if (F.getName() == Name)
  247. return F;
  248. report_fatal_error("Couldn't find function!");
  249. }
  250. TEST(LazyCallGraphTest, BasicGraphMutation) {
  251. std::unique_ptr<Module> M = parseAssembly(
  252. "define void @a() {\n"
  253. "entry:\n"
  254. " call void @b()\n"
  255. " call void @c()\n"
  256. " ret void\n"
  257. "}\n"
  258. "define void @b() {\n"
  259. "entry:\n"
  260. " ret void\n"
  261. "}\n"
  262. "define void @c() {\n"
  263. "entry:\n"
  264. " ret void\n"
  265. "}\n");
  266. LazyCallGraph CG(*M);
  267. LazyCallGraph::Node &A = CG.get(lookupFunction(*M, "a"));
  268. LazyCallGraph::Node &B = CG.get(lookupFunction(*M, "b"));
  269. EXPECT_EQ(2, std::distance(A.begin(), A.end()));
  270. EXPECT_EQ(0, std::distance(B.begin(), B.end()));
  271. CG.insertEdge(B, lookupFunction(*M, "c"));
  272. EXPECT_EQ(1, std::distance(B.begin(), B.end()));
  273. LazyCallGraph::Node &C = *B.begin();
  274. EXPECT_EQ(0, std::distance(C.begin(), C.end()));
  275. CG.insertEdge(C, B.getFunction());
  276. EXPECT_EQ(1, std::distance(C.begin(), C.end()));
  277. EXPECT_EQ(&B, &*C.begin());
  278. CG.insertEdge(C, C.getFunction());
  279. EXPECT_EQ(2, std::distance(C.begin(), C.end()));
  280. EXPECT_EQ(&B, &*C.begin());
  281. EXPECT_EQ(&C, &*std::next(C.begin()));
  282. CG.removeEdge(C, B.getFunction());
  283. EXPECT_EQ(1, std::distance(C.begin(), C.end()));
  284. EXPECT_EQ(&C, &*C.begin());
  285. CG.removeEdge(C, C.getFunction());
  286. EXPECT_EQ(0, std::distance(C.begin(), C.end()));
  287. CG.removeEdge(B, C.getFunction());
  288. EXPECT_EQ(0, std::distance(B.begin(), B.end()));
  289. }
  290. TEST(LazyCallGraphTest, MultiArmSCC) {
  291. // Two interlocking cycles. The really useful thing about this SCC is that it
  292. // will require Tarjan's DFS to backtrack and finish processing all of the
  293. // children of each node in the SCC.
  294. std::unique_ptr<Module> M = parseAssembly(
  295. "define void @a() {\n"
  296. "entry:\n"
  297. " call void @b()\n"
  298. " call void @d()\n"
  299. " ret void\n"
  300. "}\n"
  301. "define void @b() {\n"
  302. "entry:\n"
  303. " call void @c()\n"
  304. " ret void\n"
  305. "}\n"
  306. "define void @c() {\n"
  307. "entry:\n"
  308. " call void @a()\n"
  309. " ret void\n"
  310. "}\n"
  311. "define void @d() {\n"
  312. "entry:\n"
  313. " call void @e()\n"
  314. " ret void\n"
  315. "}\n"
  316. "define void @e() {\n"
  317. "entry:\n"
  318. " call void @a()\n"
  319. " ret void\n"
  320. "}\n");
  321. LazyCallGraph CG(*M);
  322. // Force the graph to be fully expanded.
  323. auto SCCI = CG.postorder_scc_begin();
  324. LazyCallGraph::SCC &SCC = *SCCI++;
  325. EXPECT_EQ(CG.postorder_scc_end(), SCCI);
  326. LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
  327. LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
  328. LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
  329. LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
  330. LazyCallGraph::Node &E = *CG.lookup(lookupFunction(*M, "e"));
  331. EXPECT_EQ(&SCC, CG.lookupSCC(A));
  332. EXPECT_EQ(&SCC, CG.lookupSCC(B));
  333. EXPECT_EQ(&SCC, CG.lookupSCC(C));
  334. EXPECT_EQ(&SCC, CG.lookupSCC(D));
  335. EXPECT_EQ(&SCC, CG.lookupSCC(E));
  336. }
  337. TEST(LazyCallGraphTest, OutgoingSCCEdgeInsertion) {
  338. std::unique_ptr<Module> M = parseAssembly(
  339. "define void @a() {\n"
  340. "entry:\n"
  341. " call void @b()\n"
  342. " call void @c()\n"
  343. " ret void\n"
  344. "}\n"
  345. "define void @b() {\n"
  346. "entry:\n"
  347. " call void @d()\n"
  348. " ret void\n"
  349. "}\n"
  350. "define void @c() {\n"
  351. "entry:\n"
  352. " call void @d()\n"
  353. " ret void\n"
  354. "}\n"
  355. "define void @d() {\n"
  356. "entry:\n"
  357. " ret void\n"
  358. "}\n");
  359. LazyCallGraph CG(*M);
  360. // Force the graph to be fully expanded.
  361. for (LazyCallGraph::SCC &C : CG.postorder_sccs())
  362. (void)C;
  363. LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
  364. LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
  365. LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
  366. LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
  367. LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
  368. LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
  369. LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
  370. LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
  371. EXPECT_TRUE(AC.isAncestorOf(BC));
  372. EXPECT_TRUE(AC.isAncestorOf(CC));
  373. EXPECT_TRUE(AC.isAncestorOf(DC));
  374. EXPECT_TRUE(DC.isDescendantOf(AC));
  375. EXPECT_TRUE(DC.isDescendantOf(BC));
  376. EXPECT_TRUE(DC.isDescendantOf(CC));
  377. EXPECT_EQ(2, std::distance(A.begin(), A.end()));
  378. AC.insertOutgoingEdge(A, D);
  379. EXPECT_EQ(3, std::distance(A.begin(), A.end()));
  380. EXPECT_TRUE(AC.isParentOf(DC));
  381. EXPECT_EQ(&AC, CG.lookupSCC(A));
  382. EXPECT_EQ(&BC, CG.lookupSCC(B));
  383. EXPECT_EQ(&CC, CG.lookupSCC(C));
  384. EXPECT_EQ(&DC, CG.lookupSCC(D));
  385. }
  386. TEST(LazyCallGraphTest, IncomingSCCEdgeInsertion) {
  387. // We want to ensure we can add edges even across complex diamond graphs, so
  388. // we use the diamond of triangles graph defined above. The ascii diagram is
  389. // repeated here for easy reference.
  390. //
  391. // d1 |
  392. // / \ |
  393. // d3--d2 |
  394. // / \ |
  395. // b1 c1 |
  396. // / \ / \ |
  397. // b3--b2 c3--c2 |
  398. // \ / |
  399. // a1 |
  400. // / \ |
  401. // a3--a2 |
  402. //
  403. std::unique_ptr<Module> M = parseAssembly(DiamondOfTriangles);
  404. LazyCallGraph CG(*M);
  405. // Force the graph to be fully expanded.
  406. for (LazyCallGraph::SCC &C : CG.postorder_sccs())
  407. (void)C;
  408. LazyCallGraph::Node &A1 = *CG.lookup(lookupFunction(*M, "a1"));
  409. LazyCallGraph::Node &A2 = *CG.lookup(lookupFunction(*M, "a2"));
  410. LazyCallGraph::Node &A3 = *CG.lookup(lookupFunction(*M, "a3"));
  411. LazyCallGraph::Node &B1 = *CG.lookup(lookupFunction(*M, "b1"));
  412. LazyCallGraph::Node &B2 = *CG.lookup(lookupFunction(*M, "b2"));
  413. LazyCallGraph::Node &B3 = *CG.lookup(lookupFunction(*M, "b3"));
  414. LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
  415. LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
  416. LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
  417. LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
  418. LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
  419. LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
  420. LazyCallGraph::SCC &AC = *CG.lookupSCC(A1);
  421. LazyCallGraph::SCC &BC = *CG.lookupSCC(B1);
  422. LazyCallGraph::SCC &CC = *CG.lookupSCC(C1);
  423. LazyCallGraph::SCC &DC = *CG.lookupSCC(D1);
  424. ASSERT_EQ(&AC, CG.lookupSCC(A2));
  425. ASSERT_EQ(&AC, CG.lookupSCC(A3));
  426. ASSERT_EQ(&BC, CG.lookupSCC(B2));
  427. ASSERT_EQ(&BC, CG.lookupSCC(B3));
  428. ASSERT_EQ(&CC, CG.lookupSCC(C2));
  429. ASSERT_EQ(&CC, CG.lookupSCC(C3));
  430. ASSERT_EQ(&DC, CG.lookupSCC(D2));
  431. ASSERT_EQ(&DC, CG.lookupSCC(D3));
  432. ASSERT_EQ(1, std::distance(D2.begin(), D2.end()));
  433. // Add an edge to make the graph:
  434. //
  435. // d1 |
  436. // / \ |
  437. // d3--d2---. |
  438. // / \ | |
  439. // b1 c1 | |
  440. // / \ / \ / |
  441. // b3--b2 c3--c2 |
  442. // \ / |
  443. // a1 |
  444. // / \ |
  445. // a3--a2 |
  446. CC.insertIncomingEdge(D2, C2);
  447. // Make sure we connected the nodes.
  448. EXPECT_EQ(2, std::distance(D2.begin(), D2.end()));
  449. // Make sure we have the correct nodes in the SCC sets.
  450. EXPECT_EQ(&AC, CG.lookupSCC(A1));
  451. EXPECT_EQ(&AC, CG.lookupSCC(A2));
  452. EXPECT_EQ(&AC, CG.lookupSCC(A3));
  453. EXPECT_EQ(&BC, CG.lookupSCC(B1));
  454. EXPECT_EQ(&BC, CG.lookupSCC(B2));
  455. EXPECT_EQ(&BC, CG.lookupSCC(B3));
  456. EXPECT_EQ(&CC, CG.lookupSCC(C1));
  457. EXPECT_EQ(&CC, CG.lookupSCC(C2));
  458. EXPECT_EQ(&CC, CG.lookupSCC(C3));
  459. EXPECT_EQ(&CC, CG.lookupSCC(D1));
  460. EXPECT_EQ(&CC, CG.lookupSCC(D2));
  461. EXPECT_EQ(&CC, CG.lookupSCC(D3));
  462. // And that ancestry tests have been updated.
  463. EXPECT_TRUE(AC.isParentOf(BC));
  464. EXPECT_TRUE(AC.isParentOf(CC));
  465. EXPECT_FALSE(AC.isAncestorOf(DC));
  466. EXPECT_FALSE(BC.isAncestorOf(DC));
  467. EXPECT_FALSE(CC.isAncestorOf(DC));
  468. }
  469. TEST(LazyCallGraphTest, IncomingSCCEdgeInsertionMidTraversal) {
  470. // This is the same fundamental test as the previous, but we perform it
  471. // having only partially walked the SCCs of the graph.
  472. std::unique_ptr<Module> M = parseAssembly(DiamondOfTriangles);
  473. LazyCallGraph CG(*M);
  474. // Walk the SCCs until we find the one containing 'c1'.
  475. auto SCCI = CG.postorder_scc_begin(), SCCE = CG.postorder_scc_end();
  476. ASSERT_NE(SCCI, SCCE);
  477. LazyCallGraph::SCC &DC = *SCCI;
  478. ASSERT_NE(&DC, nullptr);
  479. ++SCCI;
  480. ASSERT_NE(SCCI, SCCE);
  481. LazyCallGraph::SCC &CC = *SCCI;
  482. ASSERT_NE(&CC, nullptr);
  483. ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a1")));
  484. ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a2")));
  485. ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a3")));
  486. ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b1")));
  487. ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b2")));
  488. ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b3")));
  489. LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
  490. LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
  491. LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
  492. LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
  493. LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
  494. LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
  495. ASSERT_EQ(&CC, CG.lookupSCC(C1));
  496. ASSERT_EQ(&CC, CG.lookupSCC(C2));
  497. ASSERT_EQ(&CC, CG.lookupSCC(C3));
  498. ASSERT_EQ(&DC, CG.lookupSCC(D1));
  499. ASSERT_EQ(&DC, CG.lookupSCC(D2));
  500. ASSERT_EQ(&DC, CG.lookupSCC(D3));
  501. ASSERT_EQ(1, std::distance(D2.begin(), D2.end()));
  502. CC.insertIncomingEdge(D2, C2);
  503. EXPECT_EQ(2, std::distance(D2.begin(), D2.end()));
  504. // Make sure we have the correct nodes in the SCC sets.
  505. EXPECT_EQ(&CC, CG.lookupSCC(C1));
  506. EXPECT_EQ(&CC, CG.lookupSCC(C2));
  507. EXPECT_EQ(&CC, CG.lookupSCC(C3));
  508. EXPECT_EQ(&CC, CG.lookupSCC(D1));
  509. EXPECT_EQ(&CC, CG.lookupSCC(D2));
  510. EXPECT_EQ(&CC, CG.lookupSCC(D3));
  511. // Check that we can form the last two SCCs now in a coherent way.
  512. ++SCCI;
  513. EXPECT_NE(SCCI, SCCE);
  514. LazyCallGraph::SCC &BC = *SCCI;
  515. EXPECT_NE(&BC, nullptr);
  516. EXPECT_EQ(&BC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "b1"))));
  517. EXPECT_EQ(&BC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "b2"))));
  518. EXPECT_EQ(&BC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "b3"))));
  519. ++SCCI;
  520. EXPECT_NE(SCCI, SCCE);
  521. LazyCallGraph::SCC &AC = *SCCI;
  522. EXPECT_NE(&AC, nullptr);
  523. EXPECT_EQ(&AC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "a1"))));
  524. EXPECT_EQ(&AC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "a2"))));
  525. EXPECT_EQ(&AC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "a3"))));
  526. ++SCCI;
  527. EXPECT_EQ(SCCI, SCCE);
  528. }
  529. TEST(LazyCallGraphTest, InterSCCEdgeRemoval) {
  530. std::unique_ptr<Module> M = parseAssembly(
  531. "define void @a() {\n"
  532. "entry:\n"
  533. " call void @b()\n"
  534. " ret void\n"
  535. "}\n"
  536. "define void @b() {\n"
  537. "entry:\n"
  538. " ret void\n"
  539. "}\n");
  540. LazyCallGraph CG(*M);
  541. // Force the graph to be fully expanded.
  542. for (LazyCallGraph::SCC &C : CG.postorder_sccs())
  543. (void)C;
  544. LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
  545. LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
  546. LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
  547. LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
  548. EXPECT_EQ("b", A.begin()->getFunction().getName());
  549. EXPECT_EQ(B.end(), B.begin());
  550. EXPECT_EQ(&AC, &*BC.parent_begin());
  551. AC.removeInterSCCEdge(A, B);
  552. EXPECT_EQ(A.end(), A.begin());
  553. EXPECT_EQ(B.end(), B.begin());
  554. EXPECT_EQ(BC.parent_end(), BC.parent_begin());
  555. }
  556. TEST(LazyCallGraphTest, IntraSCCEdgeInsertion) {
  557. std::unique_ptr<Module> M1 = parseAssembly(
  558. "define void @a() {\n"
  559. "entry:\n"
  560. " call void @b()\n"
  561. " ret void\n"
  562. "}\n"
  563. "define void @b() {\n"
  564. "entry:\n"
  565. " call void @c()\n"
  566. " ret void\n"
  567. "}\n"
  568. "define void @c() {\n"
  569. "entry:\n"
  570. " call void @a()\n"
  571. " ret void\n"
  572. "}\n");
  573. LazyCallGraph CG1(*M1);
  574. // Force the graph to be fully expanded.
  575. auto SCCI = CG1.postorder_scc_begin();
  576. LazyCallGraph::SCC &SCC = *SCCI++;
  577. EXPECT_EQ(CG1.postorder_scc_end(), SCCI);
  578. LazyCallGraph::Node &A = *CG1.lookup(lookupFunction(*M1, "a"));
  579. LazyCallGraph::Node &B = *CG1.lookup(lookupFunction(*M1, "b"));
  580. LazyCallGraph::Node &C = *CG1.lookup(lookupFunction(*M1, "c"));
  581. EXPECT_EQ(&SCC, CG1.lookupSCC(A));
  582. EXPECT_EQ(&SCC, CG1.lookupSCC(B));
  583. EXPECT_EQ(&SCC, CG1.lookupSCC(C));
  584. // Insert an edge from 'a' to 'c'. Nothing changes about the SCCs.
  585. SCC.insertIntraSCCEdge(A, C);
  586. EXPECT_EQ(2, std::distance(A.begin(), A.end()));
  587. EXPECT_EQ(&SCC, CG1.lookupSCC(A));
  588. EXPECT_EQ(&SCC, CG1.lookupSCC(B));
  589. EXPECT_EQ(&SCC, CG1.lookupSCC(C));
  590. // Insert a self edge from 'a' back to 'a'.
  591. SCC.insertIntraSCCEdge(A, A);
  592. EXPECT_EQ(3, std::distance(A.begin(), A.end()));
  593. EXPECT_EQ(&SCC, CG1.lookupSCC(A));
  594. EXPECT_EQ(&SCC, CG1.lookupSCC(B));
  595. EXPECT_EQ(&SCC, CG1.lookupSCC(C));
  596. }
  597. TEST(LazyCallGraphTest, IntraSCCEdgeRemoval) {
  598. // A nice fully connected (including self-edges) SCC.
  599. std::unique_ptr<Module> M1 = parseAssembly(
  600. "define void @a() {\n"
  601. "entry:\n"
  602. " call void @a()\n"
  603. " call void @b()\n"
  604. " call void @c()\n"
  605. " ret void\n"
  606. "}\n"
  607. "define void @b() {\n"
  608. "entry:\n"
  609. " call void @a()\n"
  610. " call void @b()\n"
  611. " call void @c()\n"
  612. " ret void\n"
  613. "}\n"
  614. "define void @c() {\n"
  615. "entry:\n"
  616. " call void @a()\n"
  617. " call void @b()\n"
  618. " call void @c()\n"
  619. " ret void\n"
  620. "}\n");
  621. LazyCallGraph CG1(*M1);
  622. // Force the graph to be fully expanded.
  623. auto SCCI = CG1.postorder_scc_begin();
  624. LazyCallGraph::SCC &SCC = *SCCI++;
  625. EXPECT_EQ(CG1.postorder_scc_end(), SCCI);
  626. LazyCallGraph::Node &A = *CG1.lookup(lookupFunction(*M1, "a"));
  627. LazyCallGraph::Node &B = *CG1.lookup(lookupFunction(*M1, "b"));
  628. LazyCallGraph::Node &C = *CG1.lookup(lookupFunction(*M1, "c"));
  629. EXPECT_EQ(&SCC, CG1.lookupSCC(A));
  630. EXPECT_EQ(&SCC, CG1.lookupSCC(B));
  631. EXPECT_EQ(&SCC, CG1.lookupSCC(C));
  632. // Remove the edge from b -> a, which should leave the 3 functions still in
  633. // a single connected component because of a -> b -> c -> a.
  634. SmallVector<LazyCallGraph::SCC *, 1> NewSCCs = SCC.removeIntraSCCEdge(B, A);
  635. EXPECT_EQ(0u, NewSCCs.size());
  636. EXPECT_EQ(&SCC, CG1.lookupSCC(A));
  637. EXPECT_EQ(&SCC, CG1.lookupSCC(B));
  638. EXPECT_EQ(&SCC, CG1.lookupSCC(C));
  639. // Remove the edge from c -> a, which should leave 'a' in the original SCC
  640. // and form a new SCC for 'b' and 'c'.
  641. NewSCCs = SCC.removeIntraSCCEdge(C, A);
  642. EXPECT_EQ(1u, NewSCCs.size());
  643. EXPECT_EQ(&SCC, CG1.lookupSCC(A));
  644. EXPECT_EQ(1, std::distance(SCC.begin(), SCC.end()));
  645. LazyCallGraph::SCC *SCC2 = CG1.lookupSCC(B);
  646. EXPECT_EQ(SCC2, CG1.lookupSCC(C));
  647. EXPECT_EQ(SCC2, NewSCCs[0]);
  648. }
  649. }