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
10 #include "llvm/Analysis/LazyCallGraph.h"
11 #include "llvm/AsmParser/Parser.h"
12 #include "llvm/IR/Function.h"
13 #include "llvm/IR/Instructions.h"
14 #include "llvm/IR/LLVMContext.h"
15 #include "llvm/IR/Module.h"
16 #include "llvm/Support/ErrorHandling.h"
17 #include "llvm/Support/SourceMgr.h"
18 #include "gtest/gtest.h"
19 #include <memory>
20
21 using namespace llvm;
22
23 namespace {
24
parseAssembly(LLVMContext & Context,const char * Assembly)25 std::unique_ptr<Module> parseAssembly(LLVMContext &Context,
26 const char *Assembly) {
27 SMDiagnostic Error;
28 std::unique_ptr<Module> M = parseAssemblyString(Assembly, Error, Context);
29
30 std::string ErrMsg;
31 raw_string_ostream OS(ErrMsg);
32 Error.print("", OS);
33
34 // A failure here means that the test itself is buggy.
35 if (!M)
36 report_fatal_error(OS.str().c_str());
37
38 return M;
39 }
40
41 /*
42 IR forming a call graph with a diamond of triangle-shaped SCCs:
43
44 d1
45 / \
46 d3--d2
47 / \
48 b1 c1
49 / \ / \
50 b3--b2 c3--c2
51 \ /
52 a1
53 / \
54 a3--a2
55
56 All call edges go up between SCCs, and clockwise around the SCC.
57 */
58 static const char DiamondOfTriangles[] =
59 "define void @a1() {\n"
60 "entry:\n"
61 " call void @a2()\n"
62 " call void @b2()\n"
63 " call void @c3()\n"
64 " ret void\n"
65 "}\n"
66 "define void @a2() {\n"
67 "entry:\n"
68 " call void @a3()\n"
69 " ret void\n"
70 "}\n"
71 "define void @a3() {\n"
72 "entry:\n"
73 " call void @a1()\n"
74 " ret void\n"
75 "}\n"
76 "define void @b1() {\n"
77 "entry:\n"
78 " call void @b2()\n"
79 " call void @d3()\n"
80 " ret void\n"
81 "}\n"
82 "define void @b2() {\n"
83 "entry:\n"
84 " call void @b3()\n"
85 " ret void\n"
86 "}\n"
87 "define void @b3() {\n"
88 "entry:\n"
89 " call void @b1()\n"
90 " ret void\n"
91 "}\n"
92 "define void @c1() {\n"
93 "entry:\n"
94 " call void @c2()\n"
95 " call void @d2()\n"
96 " ret void\n"
97 "}\n"
98 "define void @c2() {\n"
99 "entry:\n"
100 " call void @c3()\n"
101 " ret void\n"
102 "}\n"
103 "define void @c3() {\n"
104 "entry:\n"
105 " call void @c1()\n"
106 " ret void\n"
107 "}\n"
108 "define void @d1() {\n"
109 "entry:\n"
110 " call void @d2()\n"
111 " ret void\n"
112 "}\n"
113 "define void @d2() {\n"
114 "entry:\n"
115 " call void @d3()\n"
116 " ret void\n"
117 "}\n"
118 "define void @d3() {\n"
119 "entry:\n"
120 " call void @d1()\n"
121 " ret void\n"
122 "}\n";
123
124 /*
125 IR forming a reference graph with a diamond of triangle-shaped RefSCCs
126
127 d1
128 / \
129 d3--d2
130 / \
131 b1 c1
132 / \ / \
133 b3--b2 c3--c2
134 \ /
135 a1
136 / \
137 a3--a2
138
139 All call edges go up between RefSCCs, and clockwise around the RefSCC.
140 */
141 static const char DiamondOfTrianglesRefGraph[] =
142 "define void @a1() {\n"
143 "entry:\n"
144 " %a = alloca void ()*\n"
145 " store void ()* @a2, void ()** %a\n"
146 " store void ()* @b2, void ()** %a\n"
147 " store void ()* @c3, void ()** %a\n"
148 " ret void\n"
149 "}\n"
150 "define void @a2() {\n"
151 "entry:\n"
152 " %a = alloca void ()*\n"
153 " store void ()* @a3, void ()** %a\n"
154 " ret void\n"
155 "}\n"
156 "define void @a3() {\n"
157 "entry:\n"
158 " %a = alloca void ()*\n"
159 " store void ()* @a1, void ()** %a\n"
160 " ret void\n"
161 "}\n"
162 "define void @b1() {\n"
163 "entry:\n"
164 " %a = alloca void ()*\n"
165 " store void ()* @b2, void ()** %a\n"
166 " store void ()* @d3, void ()** %a\n"
167 " ret void\n"
168 "}\n"
169 "define void @b2() {\n"
170 "entry:\n"
171 " %a = alloca void ()*\n"
172 " store void ()* @b3, void ()** %a\n"
173 " ret void\n"
174 "}\n"
175 "define void @b3() {\n"
176 "entry:\n"
177 " %a = alloca void ()*\n"
178 " store void ()* @b1, void ()** %a\n"
179 " ret void\n"
180 "}\n"
181 "define void @c1() {\n"
182 "entry:\n"
183 " %a = alloca void ()*\n"
184 " store void ()* @c2, void ()** %a\n"
185 " store void ()* @d2, void ()** %a\n"
186 " ret void\n"
187 "}\n"
188 "define void @c2() {\n"
189 "entry:\n"
190 " %a = alloca void ()*\n"
191 " store void ()* @c3, void ()** %a\n"
192 " ret void\n"
193 "}\n"
194 "define void @c3() {\n"
195 "entry:\n"
196 " %a = alloca void ()*\n"
197 " store void ()* @c1, void ()** %a\n"
198 " ret void\n"
199 "}\n"
200 "define void @d1() {\n"
201 "entry:\n"
202 " %a = alloca void ()*\n"
203 " store void ()* @d2, void ()** %a\n"
204 " ret void\n"
205 "}\n"
206 "define void @d2() {\n"
207 "entry:\n"
208 " %a = alloca void ()*\n"
209 " store void ()* @d3, void ()** %a\n"
210 " ret void\n"
211 "}\n"
212 "define void @d3() {\n"
213 "entry:\n"
214 " %a = alloca void ()*\n"
215 " store void ()* @d1, void ()** %a\n"
216 " ret void\n"
217 "}\n";
218
buildCG(Module & M)219 static LazyCallGraph buildCG(Module &M) {
220 TargetLibraryInfoImpl TLII(Triple(M.getTargetTriple()));
221 TargetLibraryInfo TLI(TLII);
222 LazyCallGraph CG(M, TLI);
223 return CG;
224 }
225
TEST(LazyCallGraphTest,BasicGraphFormation)226 TEST(LazyCallGraphTest, BasicGraphFormation) {
227 LLVMContext Context;
228 std::unique_ptr<Module> M = parseAssembly(Context, DiamondOfTriangles);
229 LazyCallGraph CG = buildCG(*M);
230
231 // The order of the entry nodes should be stable w.r.t. the source order of
232 // the IR, and everything in our module is an entry node, so just directly
233 // build variables for each node.
234 auto I = CG.begin();
235 LazyCallGraph::Node &A1 = (I++)->getNode();
236 EXPECT_EQ("a1", A1.getFunction().getName());
237 LazyCallGraph::Node &A2 = (I++)->getNode();
238 EXPECT_EQ("a2", A2.getFunction().getName());
239 LazyCallGraph::Node &A3 = (I++)->getNode();
240 EXPECT_EQ("a3", A3.getFunction().getName());
241 LazyCallGraph::Node &B1 = (I++)->getNode();
242 EXPECT_EQ("b1", B1.getFunction().getName());
243 LazyCallGraph::Node &B2 = (I++)->getNode();
244 EXPECT_EQ("b2", B2.getFunction().getName());
245 LazyCallGraph::Node &B3 = (I++)->getNode();
246 EXPECT_EQ("b3", B3.getFunction().getName());
247 LazyCallGraph::Node &C1 = (I++)->getNode();
248 EXPECT_EQ("c1", C1.getFunction().getName());
249 LazyCallGraph::Node &C2 = (I++)->getNode();
250 EXPECT_EQ("c2", C2.getFunction().getName());
251 LazyCallGraph::Node &C3 = (I++)->getNode();
252 EXPECT_EQ("c3", C3.getFunction().getName());
253 LazyCallGraph::Node &D1 = (I++)->getNode();
254 EXPECT_EQ("d1", D1.getFunction().getName());
255 LazyCallGraph::Node &D2 = (I++)->getNode();
256 EXPECT_EQ("d2", D2.getFunction().getName());
257 LazyCallGraph::Node &D3 = (I++)->getNode();
258 EXPECT_EQ("d3", D3.getFunction().getName());
259 EXPECT_EQ(CG.end(), I);
260
261 // Build vectors and sort them for the rest of the assertions to make them
262 // independent of order.
263 std::vector<std::string> Nodes;
264
265 for (LazyCallGraph::Edge &E : A1.populate())
266 Nodes.push_back(E.getFunction().getName());
267 llvm::sort(Nodes.begin(), Nodes.end());
268 EXPECT_EQ("a2", Nodes[0]);
269 EXPECT_EQ("b2", Nodes[1]);
270 EXPECT_EQ("c3", Nodes[2]);
271 Nodes.clear();
272
273 A2.populate();
274 EXPECT_EQ(A2->end(), std::next(A2->begin()));
275 EXPECT_EQ("a3", A2->begin()->getFunction().getName());
276 A3.populate();
277 EXPECT_EQ(A3->end(), std::next(A3->begin()));
278 EXPECT_EQ("a1", A3->begin()->getFunction().getName());
279
280 for (LazyCallGraph::Edge &E : B1.populate())
281 Nodes.push_back(E.getFunction().getName());
282 llvm::sort(Nodes.begin(), Nodes.end());
283 EXPECT_EQ("b2", Nodes[0]);
284 EXPECT_EQ("d3", Nodes[1]);
285 Nodes.clear();
286
287 B2.populate();
288 EXPECT_EQ(B2->end(), std::next(B2->begin()));
289 EXPECT_EQ("b3", B2->begin()->getFunction().getName());
290 B3.populate();
291 EXPECT_EQ(B3->end(), std::next(B3->begin()));
292 EXPECT_EQ("b1", B3->begin()->getFunction().getName());
293
294 for (LazyCallGraph::Edge &E : C1.populate())
295 Nodes.push_back(E.getFunction().getName());
296 llvm::sort(Nodes.begin(), Nodes.end());
297 EXPECT_EQ("c2", Nodes[0]);
298 EXPECT_EQ("d2", Nodes[1]);
299 Nodes.clear();
300
301 C2.populate();
302 EXPECT_EQ(C2->end(), std::next(C2->begin()));
303 EXPECT_EQ("c3", C2->begin()->getFunction().getName());
304 C3.populate();
305 EXPECT_EQ(C3->end(), std::next(C3->begin()));
306 EXPECT_EQ("c1", C3->begin()->getFunction().getName());
307
308 D1.populate();
309 EXPECT_EQ(D1->end(), std::next(D1->begin()));
310 EXPECT_EQ("d2", D1->begin()->getFunction().getName());
311 D2.populate();
312 EXPECT_EQ(D2->end(), std::next(D2->begin()));
313 EXPECT_EQ("d3", D2->begin()->getFunction().getName());
314 D3.populate();
315 EXPECT_EQ(D3->end(), std::next(D3->begin()));
316 EXPECT_EQ("d1", D3->begin()->getFunction().getName());
317
318 // Now lets look at the RefSCCs and SCCs.
319 CG.buildRefSCCs();
320 auto J = CG.postorder_ref_scc_begin();
321
322 LazyCallGraph::RefSCC &D = *J++;
323 ASSERT_EQ(1, D.size());
324 for (LazyCallGraph::Node &N : *D.begin())
325 Nodes.push_back(N.getFunction().getName());
326 llvm::sort(Nodes.begin(), Nodes.end());
327 EXPECT_EQ(3u, Nodes.size());
328 EXPECT_EQ("d1", Nodes[0]);
329 EXPECT_EQ("d2", Nodes[1]);
330 EXPECT_EQ("d3", Nodes[2]);
331 Nodes.clear();
332 EXPECT_FALSE(D.isParentOf(D));
333 EXPECT_FALSE(D.isChildOf(D));
334 EXPECT_FALSE(D.isAncestorOf(D));
335 EXPECT_FALSE(D.isDescendantOf(D));
336 EXPECT_EQ(&D, &*CG.postorder_ref_scc_begin());
337
338 LazyCallGraph::RefSCC &C = *J++;
339 ASSERT_EQ(1, C.size());
340 for (LazyCallGraph::Node &N : *C.begin())
341 Nodes.push_back(N.getFunction().getName());
342 llvm::sort(Nodes.begin(), Nodes.end());
343 EXPECT_EQ(3u, Nodes.size());
344 EXPECT_EQ("c1", Nodes[0]);
345 EXPECT_EQ("c2", Nodes[1]);
346 EXPECT_EQ("c3", Nodes[2]);
347 Nodes.clear();
348 EXPECT_TRUE(C.isParentOf(D));
349 EXPECT_FALSE(C.isChildOf(D));
350 EXPECT_TRUE(C.isAncestorOf(D));
351 EXPECT_FALSE(C.isDescendantOf(D));
352 EXPECT_EQ(&C, &*std::next(CG.postorder_ref_scc_begin()));
353
354 LazyCallGraph::RefSCC &B = *J++;
355 ASSERT_EQ(1, B.size());
356 for (LazyCallGraph::Node &N : *B.begin())
357 Nodes.push_back(N.getFunction().getName());
358 llvm::sort(Nodes.begin(), Nodes.end());
359 EXPECT_EQ(3u, Nodes.size());
360 EXPECT_EQ("b1", Nodes[0]);
361 EXPECT_EQ("b2", Nodes[1]);
362 EXPECT_EQ("b3", Nodes[2]);
363 Nodes.clear();
364 EXPECT_TRUE(B.isParentOf(D));
365 EXPECT_FALSE(B.isChildOf(D));
366 EXPECT_TRUE(B.isAncestorOf(D));
367 EXPECT_FALSE(B.isDescendantOf(D));
368 EXPECT_FALSE(B.isAncestorOf(C));
369 EXPECT_FALSE(C.isAncestorOf(B));
370 EXPECT_EQ(&B, &*std::next(CG.postorder_ref_scc_begin(), 2));
371
372 LazyCallGraph::RefSCC &A = *J++;
373 ASSERT_EQ(1, A.size());
374 for (LazyCallGraph::Node &N : *A.begin())
375 Nodes.push_back(N.getFunction().getName());
376 llvm::sort(Nodes.begin(), Nodes.end());
377 EXPECT_EQ(3u, Nodes.size());
378 EXPECT_EQ("a1", Nodes[0]);
379 EXPECT_EQ("a2", Nodes[1]);
380 EXPECT_EQ("a3", Nodes[2]);
381 Nodes.clear();
382 EXPECT_TRUE(A.isParentOf(B));
383 EXPECT_TRUE(A.isParentOf(C));
384 EXPECT_FALSE(A.isParentOf(D));
385 EXPECT_TRUE(A.isAncestorOf(B));
386 EXPECT_TRUE(A.isAncestorOf(C));
387 EXPECT_TRUE(A.isAncestorOf(D));
388 EXPECT_EQ(&A, &*std::next(CG.postorder_ref_scc_begin(), 3));
389
390 EXPECT_EQ(CG.postorder_ref_scc_end(), J);
391 EXPECT_EQ(J, std::next(CG.postorder_ref_scc_begin(), 4));
392 }
393
lookupFunction(Module & M,StringRef Name)394 static Function &lookupFunction(Module &M, StringRef Name) {
395 for (Function &F : M)
396 if (F.getName() == Name)
397 return F;
398 report_fatal_error("Couldn't find function!");
399 }
400
TEST(LazyCallGraphTest,BasicGraphMutation)401 TEST(LazyCallGraphTest, BasicGraphMutation) {
402 LLVMContext Context;
403 std::unique_ptr<Module> M = parseAssembly(Context, "define void @a() {\n"
404 "entry:\n"
405 " call void @b()\n"
406 " call void @c()\n"
407 " ret void\n"
408 "}\n"
409 "define void @b() {\n"
410 "entry:\n"
411 " ret void\n"
412 "}\n"
413 "define void @c() {\n"
414 "entry:\n"
415 " ret void\n"
416 "}\n");
417 LazyCallGraph CG = buildCG(*M);
418
419 LazyCallGraph::Node &A = CG.get(lookupFunction(*M, "a"));
420 LazyCallGraph::Node &B = CG.get(lookupFunction(*M, "b"));
421 A.populate();
422 EXPECT_EQ(2, std::distance(A->begin(), A->end()));
423 B.populate();
424 EXPECT_EQ(0, std::distance(B->begin(), B->end()));
425
426 LazyCallGraph::Node &C = CG.get(lookupFunction(*M, "c"));
427 C.populate();
428 CG.insertEdge(B, C, LazyCallGraph::Edge::Call);
429 EXPECT_EQ(1, std::distance(B->begin(), B->end()));
430 EXPECT_EQ(0, std::distance(C->begin(), C->end()));
431
432 CG.insertEdge(C, B, LazyCallGraph::Edge::Call);
433 EXPECT_EQ(1, std::distance(C->begin(), C->end()));
434 EXPECT_EQ(&B, &C->begin()->getNode());
435
436 CG.insertEdge(C, C, LazyCallGraph::Edge::Call);
437 EXPECT_EQ(2, std::distance(C->begin(), C->end()));
438 EXPECT_EQ(&B, &C->begin()->getNode());
439 EXPECT_EQ(&C, &std::next(C->begin())->getNode());
440
441 CG.removeEdge(C, B);
442 EXPECT_EQ(1, std::distance(C->begin(), C->end()));
443 EXPECT_EQ(&C, &C->begin()->getNode());
444
445 CG.removeEdge(C, C);
446 EXPECT_EQ(0, std::distance(C->begin(), C->end()));
447
448 CG.removeEdge(B, C);
449 EXPECT_EQ(0, std::distance(B->begin(), B->end()));
450 }
451
TEST(LazyCallGraphTest,InnerSCCFormation)452 TEST(LazyCallGraphTest, InnerSCCFormation) {
453 LLVMContext Context;
454 std::unique_ptr<Module> M = parseAssembly(Context, DiamondOfTriangles);
455 LazyCallGraph CG = buildCG(*M);
456
457 // Now mutate the graph to connect every node into a single RefSCC to ensure
458 // that our inner SCC formation handles the rest.
459 LazyCallGraph::Node &D1 = CG.get(lookupFunction(*M, "d1"));
460 LazyCallGraph::Node &A1 = CG.get(lookupFunction(*M, "a1"));
461 A1.populate();
462 D1.populate();
463 CG.insertEdge(D1, A1, LazyCallGraph::Edge::Ref);
464
465 // Build vectors and sort them for the rest of the assertions to make them
466 // independent of order.
467 std::vector<std::string> Nodes;
468
469 // We should build a single RefSCC for the entire graph.
470 CG.buildRefSCCs();
471 auto I = CG.postorder_ref_scc_begin();
472 LazyCallGraph::RefSCC &RC = *I++;
473 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
474
475 // Now walk the four SCCs which should be in post-order.
476 auto J = RC.begin();
477 LazyCallGraph::SCC &D = *J++;
478 for (LazyCallGraph::Node &N : D)
479 Nodes.push_back(N.getFunction().getName());
480 llvm::sort(Nodes.begin(), Nodes.end());
481 EXPECT_EQ(3u, Nodes.size());
482 EXPECT_EQ("d1", Nodes[0]);
483 EXPECT_EQ("d2", Nodes[1]);
484 EXPECT_EQ("d3", Nodes[2]);
485 Nodes.clear();
486
487 LazyCallGraph::SCC &B = *J++;
488 for (LazyCallGraph::Node &N : B)
489 Nodes.push_back(N.getFunction().getName());
490 llvm::sort(Nodes.begin(), Nodes.end());
491 EXPECT_EQ(3u, Nodes.size());
492 EXPECT_EQ("b1", Nodes[0]);
493 EXPECT_EQ("b2", Nodes[1]);
494 EXPECT_EQ("b3", Nodes[2]);
495 Nodes.clear();
496
497 LazyCallGraph::SCC &C = *J++;
498 for (LazyCallGraph::Node &N : C)
499 Nodes.push_back(N.getFunction().getName());
500 llvm::sort(Nodes.begin(), Nodes.end());
501 EXPECT_EQ(3u, Nodes.size());
502 EXPECT_EQ("c1", Nodes[0]);
503 EXPECT_EQ("c2", Nodes[1]);
504 EXPECT_EQ("c3", Nodes[2]);
505 Nodes.clear();
506
507 LazyCallGraph::SCC &A = *J++;
508 for (LazyCallGraph::Node &N : A)
509 Nodes.push_back(N.getFunction().getName());
510 llvm::sort(Nodes.begin(), Nodes.end());
511 EXPECT_EQ(3u, Nodes.size());
512 EXPECT_EQ("a1", Nodes[0]);
513 EXPECT_EQ("a2", Nodes[1]);
514 EXPECT_EQ("a3", Nodes[2]);
515 Nodes.clear();
516
517 EXPECT_EQ(RC.end(), J);
518 }
519
TEST(LazyCallGraphTest,MultiArmSCC)520 TEST(LazyCallGraphTest, MultiArmSCC) {
521 LLVMContext Context;
522 // Two interlocking cycles. The really useful thing about this SCC is that it
523 // will require Tarjan's DFS to backtrack and finish processing all of the
524 // children of each node in the SCC. Since this involves call edges, both
525 // Tarjan implementations will have to successfully navigate the structure.
526 std::unique_ptr<Module> M = parseAssembly(Context, "define void @f1() {\n"
527 "entry:\n"
528 " call void @f2()\n"
529 " call void @f4()\n"
530 " ret void\n"
531 "}\n"
532 "define void @f2() {\n"
533 "entry:\n"
534 " call void @f3()\n"
535 " ret void\n"
536 "}\n"
537 "define void @f3() {\n"
538 "entry:\n"
539 " call void @f1()\n"
540 " ret void\n"
541 "}\n"
542 "define void @f4() {\n"
543 "entry:\n"
544 " call void @f5()\n"
545 " ret void\n"
546 "}\n"
547 "define void @f5() {\n"
548 "entry:\n"
549 " call void @f1()\n"
550 " ret void\n"
551 "}\n");
552 LazyCallGraph CG = buildCG(*M);
553
554 // Force the graph to be fully expanded.
555 CG.buildRefSCCs();
556 auto I = CG.postorder_ref_scc_begin();
557 LazyCallGraph::RefSCC &RC = *I++;
558 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
559
560 LazyCallGraph::Node &N1 = *CG.lookup(lookupFunction(*M, "f1"));
561 LazyCallGraph::Node &N2 = *CG.lookup(lookupFunction(*M, "f2"));
562 LazyCallGraph::Node &N3 = *CG.lookup(lookupFunction(*M, "f3"));
563 LazyCallGraph::Node &N4 = *CG.lookup(lookupFunction(*M, "f4"));
564 LazyCallGraph::Node &N5 = *CG.lookup(lookupFunction(*M, "f4"));
565 EXPECT_EQ(&RC, CG.lookupRefSCC(N1));
566 EXPECT_EQ(&RC, CG.lookupRefSCC(N2));
567 EXPECT_EQ(&RC, CG.lookupRefSCC(N3));
568 EXPECT_EQ(&RC, CG.lookupRefSCC(N4));
569 EXPECT_EQ(&RC, CG.lookupRefSCC(N5));
570
571 ASSERT_EQ(1, RC.size());
572
573 LazyCallGraph::SCC &C = *RC.begin();
574 EXPECT_EQ(&C, CG.lookupSCC(N1));
575 EXPECT_EQ(&C, CG.lookupSCC(N2));
576 EXPECT_EQ(&C, CG.lookupSCC(N3));
577 EXPECT_EQ(&C, CG.lookupSCC(N4));
578 EXPECT_EQ(&C, CG.lookupSCC(N5));
579 }
580
TEST(LazyCallGraphTest,OutgoingEdgeMutation)581 TEST(LazyCallGraphTest, OutgoingEdgeMutation) {
582 LLVMContext Context;
583 std::unique_ptr<Module> M = parseAssembly(Context, "define void @a() {\n"
584 "entry:\n"
585 " call void @b()\n"
586 " call void @c()\n"
587 " ret void\n"
588 "}\n"
589 "define void @b() {\n"
590 "entry:\n"
591 " call void @d()\n"
592 " ret void\n"
593 "}\n"
594 "define void @c() {\n"
595 "entry:\n"
596 " call void @d()\n"
597 " ret void\n"
598 "}\n"
599 "define void @d() {\n"
600 "entry:\n"
601 " ret void\n"
602 "}\n");
603 LazyCallGraph CG = buildCG(*M);
604
605 // Force the graph to be fully expanded.
606 CG.buildRefSCCs();
607 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
608 dbgs() << "Formed RefSCC: " << RC << "\n";
609
610 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
611 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
612 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
613 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
614 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
615 LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
616 LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
617 LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
618 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(A);
619 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(B);
620 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(C);
621 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(D);
622 EXPECT_TRUE(ARC.isParentOf(BRC));
623 EXPECT_TRUE(AC.isParentOf(BC));
624 EXPECT_TRUE(ARC.isParentOf(CRC));
625 EXPECT_TRUE(AC.isParentOf(CC));
626 EXPECT_FALSE(ARC.isParentOf(DRC));
627 EXPECT_FALSE(AC.isParentOf(DC));
628 EXPECT_TRUE(ARC.isAncestorOf(DRC));
629 EXPECT_TRUE(AC.isAncestorOf(DC));
630 EXPECT_FALSE(DRC.isChildOf(ARC));
631 EXPECT_FALSE(DC.isChildOf(AC));
632 EXPECT_TRUE(DRC.isDescendantOf(ARC));
633 EXPECT_TRUE(DC.isDescendantOf(AC));
634 EXPECT_TRUE(DRC.isChildOf(BRC));
635 EXPECT_TRUE(DC.isChildOf(BC));
636 EXPECT_TRUE(DRC.isChildOf(CRC));
637 EXPECT_TRUE(DC.isChildOf(CC));
638
639 EXPECT_EQ(2, std::distance(A->begin(), A->end()));
640 ARC.insertOutgoingEdge(A, D, LazyCallGraph::Edge::Call);
641 EXPECT_EQ(3, std::distance(A->begin(), A->end()));
642 const LazyCallGraph::Edge &NewE = (*A)[D];
643 EXPECT_TRUE(NewE);
644 EXPECT_TRUE(NewE.isCall());
645 EXPECT_EQ(&D, &NewE.getNode());
646
647 // Only the parent and child tests sholud have changed. The rest of the graph
648 // remains the same.
649 EXPECT_TRUE(ARC.isParentOf(DRC));
650 EXPECT_TRUE(AC.isParentOf(DC));
651 EXPECT_TRUE(ARC.isAncestorOf(DRC));
652 EXPECT_TRUE(AC.isAncestorOf(DC));
653 EXPECT_TRUE(DRC.isChildOf(ARC));
654 EXPECT_TRUE(DC.isChildOf(AC));
655 EXPECT_TRUE(DRC.isDescendantOf(ARC));
656 EXPECT_TRUE(DC.isDescendantOf(AC));
657 EXPECT_EQ(&AC, CG.lookupSCC(A));
658 EXPECT_EQ(&BC, CG.lookupSCC(B));
659 EXPECT_EQ(&CC, CG.lookupSCC(C));
660 EXPECT_EQ(&DC, CG.lookupSCC(D));
661 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
662 EXPECT_EQ(&BRC, CG.lookupRefSCC(B));
663 EXPECT_EQ(&CRC, CG.lookupRefSCC(C));
664 EXPECT_EQ(&DRC, CG.lookupRefSCC(D));
665
666 ARC.switchOutgoingEdgeToRef(A, D);
667 EXPECT_FALSE(NewE.isCall());
668
669 // Verify the reference graph remains the same but the SCC graph is updated.
670 EXPECT_TRUE(ARC.isParentOf(DRC));
671 EXPECT_FALSE(AC.isParentOf(DC));
672 EXPECT_TRUE(ARC.isAncestorOf(DRC));
673 EXPECT_TRUE(AC.isAncestorOf(DC));
674 EXPECT_TRUE(DRC.isChildOf(ARC));
675 EXPECT_FALSE(DC.isChildOf(AC));
676 EXPECT_TRUE(DRC.isDescendantOf(ARC));
677 EXPECT_TRUE(DC.isDescendantOf(AC));
678 EXPECT_EQ(&AC, CG.lookupSCC(A));
679 EXPECT_EQ(&BC, CG.lookupSCC(B));
680 EXPECT_EQ(&CC, CG.lookupSCC(C));
681 EXPECT_EQ(&DC, CG.lookupSCC(D));
682 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
683 EXPECT_EQ(&BRC, CG.lookupRefSCC(B));
684 EXPECT_EQ(&CRC, CG.lookupRefSCC(C));
685 EXPECT_EQ(&DRC, CG.lookupRefSCC(D));
686
687 ARC.switchOutgoingEdgeToCall(A, D);
688 EXPECT_TRUE(NewE.isCall());
689
690 // Verify the reference graph remains the same but the SCC graph is updated.
691 EXPECT_TRUE(ARC.isParentOf(DRC));
692 EXPECT_TRUE(AC.isParentOf(DC));
693 EXPECT_TRUE(ARC.isAncestorOf(DRC));
694 EXPECT_TRUE(AC.isAncestorOf(DC));
695 EXPECT_TRUE(DRC.isChildOf(ARC));
696 EXPECT_TRUE(DC.isChildOf(AC));
697 EXPECT_TRUE(DRC.isDescendantOf(ARC));
698 EXPECT_TRUE(DC.isDescendantOf(AC));
699 EXPECT_EQ(&AC, CG.lookupSCC(A));
700 EXPECT_EQ(&BC, CG.lookupSCC(B));
701 EXPECT_EQ(&CC, CG.lookupSCC(C));
702 EXPECT_EQ(&DC, CG.lookupSCC(D));
703 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
704 EXPECT_EQ(&BRC, CG.lookupRefSCC(B));
705 EXPECT_EQ(&CRC, CG.lookupRefSCC(C));
706 EXPECT_EQ(&DRC, CG.lookupRefSCC(D));
707
708 ARC.removeOutgoingEdge(A, D);
709 EXPECT_EQ(2, std::distance(A->begin(), A->end()));
710
711 // Now the parent and child tests fail again but the rest remains the same.
712 EXPECT_FALSE(ARC.isParentOf(DRC));
713 EXPECT_FALSE(AC.isParentOf(DC));
714 EXPECT_TRUE(ARC.isAncestorOf(DRC));
715 EXPECT_TRUE(AC.isAncestorOf(DC));
716 EXPECT_FALSE(DRC.isChildOf(ARC));
717 EXPECT_FALSE(DC.isChildOf(AC));
718 EXPECT_TRUE(DRC.isDescendantOf(ARC));
719 EXPECT_TRUE(DC.isDescendantOf(AC));
720 EXPECT_EQ(&AC, CG.lookupSCC(A));
721 EXPECT_EQ(&BC, CG.lookupSCC(B));
722 EXPECT_EQ(&CC, CG.lookupSCC(C));
723 EXPECT_EQ(&DC, CG.lookupSCC(D));
724 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
725 EXPECT_EQ(&BRC, CG.lookupRefSCC(B));
726 EXPECT_EQ(&CRC, CG.lookupRefSCC(C));
727 EXPECT_EQ(&DRC, CG.lookupRefSCC(D));
728 }
729
TEST(LazyCallGraphTest,IncomingEdgeInsertion)730 TEST(LazyCallGraphTest, IncomingEdgeInsertion) {
731 LLVMContext Context;
732 // We want to ensure we can add edges even across complex diamond graphs, so
733 // we use the diamond of triangles graph defined above. The ascii diagram is
734 // repeated here for easy reference.
735 //
736 // d1 |
737 // / \ |
738 // d3--d2 |
739 // / \ |
740 // b1 c1 |
741 // / \ / \ |
742 // b3--b2 c3--c2 |
743 // \ / |
744 // a1 |
745 // / \ |
746 // a3--a2 |
747 //
748 std::unique_ptr<Module> M = parseAssembly(Context, DiamondOfTriangles);
749 LazyCallGraph CG = buildCG(*M);
750
751 // Force the graph to be fully expanded.
752 CG.buildRefSCCs();
753 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
754 dbgs() << "Formed RefSCC: " << RC << "\n";
755
756 LazyCallGraph::Node &A1 = *CG.lookup(lookupFunction(*M, "a1"));
757 LazyCallGraph::Node &A2 = *CG.lookup(lookupFunction(*M, "a2"));
758 LazyCallGraph::Node &A3 = *CG.lookup(lookupFunction(*M, "a3"));
759 LazyCallGraph::Node &B1 = *CG.lookup(lookupFunction(*M, "b1"));
760 LazyCallGraph::Node &B2 = *CG.lookup(lookupFunction(*M, "b2"));
761 LazyCallGraph::Node &B3 = *CG.lookup(lookupFunction(*M, "b3"));
762 LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
763 LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
764 LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
765 LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
766 LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
767 LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
768 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(A1);
769 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(B1);
770 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(C1);
771 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(D1);
772 ASSERT_EQ(&ARC, CG.lookupRefSCC(A2));
773 ASSERT_EQ(&ARC, CG.lookupRefSCC(A3));
774 ASSERT_EQ(&BRC, CG.lookupRefSCC(B2));
775 ASSERT_EQ(&BRC, CG.lookupRefSCC(B3));
776 ASSERT_EQ(&CRC, CG.lookupRefSCC(C2));
777 ASSERT_EQ(&CRC, CG.lookupRefSCC(C3));
778 ASSERT_EQ(&DRC, CG.lookupRefSCC(D2));
779 ASSERT_EQ(&DRC, CG.lookupRefSCC(D3));
780 ASSERT_EQ(1, std::distance(D2->begin(), D2->end()));
781
782 // Add an edge to make the graph:
783 //
784 // d1 |
785 // / \ |
786 // d3--d2---. |
787 // / \ | |
788 // b1 c1 | |
789 // / \ / \ / |
790 // b3--b2 c3--c2 |
791 // \ / |
792 // a1 |
793 // / \ |
794 // a3--a2 |
795 auto MergedRCs = CRC.insertIncomingRefEdge(D2, C2);
796 // Make sure we connected the nodes.
797 for (LazyCallGraph::Edge E : *D2) {
798 if (&E.getNode() == &D3)
799 continue;
800 EXPECT_EQ(&C2, &E.getNode());
801 }
802 // And marked the D ref-SCC as no longer valid.
803 EXPECT_EQ(1u, MergedRCs.size());
804 EXPECT_EQ(&DRC, MergedRCs[0]);
805
806 // Make sure we have the correct nodes in the SCC sets.
807 EXPECT_EQ(&ARC, CG.lookupRefSCC(A1));
808 EXPECT_EQ(&ARC, CG.lookupRefSCC(A2));
809 EXPECT_EQ(&ARC, CG.lookupRefSCC(A3));
810 EXPECT_EQ(&BRC, CG.lookupRefSCC(B1));
811 EXPECT_EQ(&BRC, CG.lookupRefSCC(B2));
812 EXPECT_EQ(&BRC, CG.lookupRefSCC(B3));
813 EXPECT_EQ(&CRC, CG.lookupRefSCC(C1));
814 EXPECT_EQ(&CRC, CG.lookupRefSCC(C2));
815 EXPECT_EQ(&CRC, CG.lookupRefSCC(C3));
816 EXPECT_EQ(&CRC, CG.lookupRefSCC(D1));
817 EXPECT_EQ(&CRC, CG.lookupRefSCC(D2));
818 EXPECT_EQ(&CRC, CG.lookupRefSCC(D3));
819
820 // And that ancestry tests have been updated.
821 EXPECT_TRUE(ARC.isParentOf(CRC));
822 EXPECT_TRUE(BRC.isParentOf(CRC));
823
824 // And verify the post-order walk reflects the updated structure.
825 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
826 ASSERT_NE(I, E);
827 EXPECT_EQ(&CRC, &*I) << "Actual RefSCC: " << *I;
828 ASSERT_NE(++I, E);
829 EXPECT_EQ(&BRC, &*I) << "Actual RefSCC: " << *I;
830 ASSERT_NE(++I, E);
831 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
832 EXPECT_EQ(++I, E);
833 }
834
TEST(LazyCallGraphTest,IncomingEdgeInsertionRefGraph)835 TEST(LazyCallGraphTest, IncomingEdgeInsertionRefGraph) {
836 LLVMContext Context;
837 // Another variation of the above test but with all the edges switched to
838 // references rather than calls.
839 std::unique_ptr<Module> M =
840 parseAssembly(Context, DiamondOfTrianglesRefGraph);
841 LazyCallGraph CG = buildCG(*M);
842
843 // Force the graph to be fully expanded.
844 CG.buildRefSCCs();
845 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
846 dbgs() << "Formed RefSCC: " << RC << "\n";
847
848 LazyCallGraph::Node &A1 = *CG.lookup(lookupFunction(*M, "a1"));
849 LazyCallGraph::Node &A2 = *CG.lookup(lookupFunction(*M, "a2"));
850 LazyCallGraph::Node &A3 = *CG.lookup(lookupFunction(*M, "a3"));
851 LazyCallGraph::Node &B1 = *CG.lookup(lookupFunction(*M, "b1"));
852 LazyCallGraph::Node &B2 = *CG.lookup(lookupFunction(*M, "b2"));
853 LazyCallGraph::Node &B3 = *CG.lookup(lookupFunction(*M, "b3"));
854 LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
855 LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
856 LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
857 LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
858 LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
859 LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
860 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(A1);
861 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(B1);
862 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(C1);
863 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(D1);
864 ASSERT_EQ(&ARC, CG.lookupRefSCC(A2));
865 ASSERT_EQ(&ARC, CG.lookupRefSCC(A3));
866 ASSERT_EQ(&BRC, CG.lookupRefSCC(B2));
867 ASSERT_EQ(&BRC, CG.lookupRefSCC(B3));
868 ASSERT_EQ(&CRC, CG.lookupRefSCC(C2));
869 ASSERT_EQ(&CRC, CG.lookupRefSCC(C3));
870 ASSERT_EQ(&DRC, CG.lookupRefSCC(D2));
871 ASSERT_EQ(&DRC, CG.lookupRefSCC(D3));
872 ASSERT_EQ(1, std::distance(D2->begin(), D2->end()));
873
874 // Add an edge to make the graph:
875 //
876 // d1 |
877 // / \ |
878 // d3--d2---. |
879 // / \ | |
880 // b1 c1 | |
881 // / \ / \ / |
882 // b3--b2 c3--c2 |
883 // \ / |
884 // a1 |
885 // / \ |
886 // a3--a2 |
887 auto MergedRCs = CRC.insertIncomingRefEdge(D2, C2);
888 // Make sure we connected the nodes.
889 for (LazyCallGraph::Edge E : *D2) {
890 if (&E.getNode() == &D3)
891 continue;
892 EXPECT_EQ(&C2, &E.getNode());
893 }
894 // And marked the D ref-SCC as no longer valid.
895 EXPECT_EQ(1u, MergedRCs.size());
896 EXPECT_EQ(&DRC, MergedRCs[0]);
897
898 // Make sure we have the correct nodes in the SCC sets.
899 EXPECT_EQ(&ARC, CG.lookupRefSCC(A1));
900 EXPECT_EQ(&ARC, CG.lookupRefSCC(A2));
901 EXPECT_EQ(&ARC, CG.lookupRefSCC(A3));
902 EXPECT_EQ(&BRC, CG.lookupRefSCC(B1));
903 EXPECT_EQ(&BRC, CG.lookupRefSCC(B2));
904 EXPECT_EQ(&BRC, CG.lookupRefSCC(B3));
905 EXPECT_EQ(&CRC, CG.lookupRefSCC(C1));
906 EXPECT_EQ(&CRC, CG.lookupRefSCC(C2));
907 EXPECT_EQ(&CRC, CG.lookupRefSCC(C3));
908 EXPECT_EQ(&CRC, CG.lookupRefSCC(D1));
909 EXPECT_EQ(&CRC, CG.lookupRefSCC(D2));
910 EXPECT_EQ(&CRC, CG.lookupRefSCC(D3));
911
912 // And that ancestry tests have been updated.
913 EXPECT_TRUE(ARC.isParentOf(CRC));
914 EXPECT_TRUE(BRC.isParentOf(CRC));
915
916 // And verify the post-order walk reflects the updated structure.
917 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
918 ASSERT_NE(I, E);
919 EXPECT_EQ(&CRC, &*I) << "Actual RefSCC: " << *I;
920 ASSERT_NE(++I, E);
921 EXPECT_EQ(&BRC, &*I) << "Actual RefSCC: " << *I;
922 ASSERT_NE(++I, E);
923 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
924 EXPECT_EQ(++I, E);
925 }
926
TEST(LazyCallGraphTest,IncomingEdgeInsertionLargeCallCycle)927 TEST(LazyCallGraphTest, IncomingEdgeInsertionLargeCallCycle) {
928 LLVMContext Context;
929 std::unique_ptr<Module> M = parseAssembly(Context, "define void @a() {\n"
930 "entry:\n"
931 " call void @b()\n"
932 " ret void\n"
933 "}\n"
934 "define void @b() {\n"
935 "entry:\n"
936 " call void @c()\n"
937 " ret void\n"
938 "}\n"
939 "define void @c() {\n"
940 "entry:\n"
941 " call void @d()\n"
942 " ret void\n"
943 "}\n"
944 "define void @d() {\n"
945 "entry:\n"
946 " ret void\n"
947 "}\n");
948 LazyCallGraph CG = buildCG(*M);
949
950 // Force the graph to be fully expanded.
951 CG.buildRefSCCs();
952 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
953 dbgs() << "Formed RefSCC: " << RC << "\n";
954
955 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
956 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
957 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
958 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
959 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
960 LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
961 LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
962 LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
963 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(A);
964 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(B);
965 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(C);
966 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(D);
967
968 // Connect the top to the bottom forming a large RefSCC made up mostly of calls.
969 auto MergedRCs = ARC.insertIncomingRefEdge(D, A);
970 // Make sure we connected the nodes.
971 EXPECT_NE(D->begin(), D->end());
972 EXPECT_EQ(&A, &D->begin()->getNode());
973
974 // Check that we have the dead RCs, but ignore the order.
975 EXPECT_EQ(3u, MergedRCs.size());
976 EXPECT_NE(find(MergedRCs, &BRC), MergedRCs.end());
977 EXPECT_NE(find(MergedRCs, &CRC), MergedRCs.end());
978 EXPECT_NE(find(MergedRCs, &DRC), MergedRCs.end());
979
980 // Make sure the nodes point to the right place now.
981 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
982 EXPECT_EQ(&ARC, CG.lookupRefSCC(B));
983 EXPECT_EQ(&ARC, CG.lookupRefSCC(C));
984 EXPECT_EQ(&ARC, CG.lookupRefSCC(D));
985
986 // Check that the SCCs are in postorder.
987 EXPECT_EQ(4, ARC.size());
988 EXPECT_EQ(&DC, &ARC[0]);
989 EXPECT_EQ(&CC, &ARC[1]);
990 EXPECT_EQ(&BC, &ARC[2]);
991 EXPECT_EQ(&AC, &ARC[3]);
992
993 // And verify the post-order walk reflects the updated structure.
994 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
995 ASSERT_NE(I, E);
996 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
997 EXPECT_EQ(++I, E);
998 }
999
TEST(LazyCallGraphTest,IncomingEdgeInsertionLargeRefCycle)1000 TEST(LazyCallGraphTest, IncomingEdgeInsertionLargeRefCycle) {
1001 LLVMContext Context;
1002 std::unique_ptr<Module> M =
1003 parseAssembly(Context, "define void @a() {\n"
1004 "entry:\n"
1005 " %p = alloca void ()*\n"
1006 " store void ()* @b, void ()** %p\n"
1007 " ret void\n"
1008 "}\n"
1009 "define void @b() {\n"
1010 "entry:\n"
1011 " %p = alloca void ()*\n"
1012 " store void ()* @c, void ()** %p\n"
1013 " ret void\n"
1014 "}\n"
1015 "define void @c() {\n"
1016 "entry:\n"
1017 " %p = alloca void ()*\n"
1018 " store void ()* @d, void ()** %p\n"
1019 " ret void\n"
1020 "}\n"
1021 "define void @d() {\n"
1022 "entry:\n"
1023 " ret void\n"
1024 "}\n");
1025 LazyCallGraph CG = buildCG(*M);
1026
1027 // Force the graph to be fully expanded.
1028 CG.buildRefSCCs();
1029 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
1030 dbgs() << "Formed RefSCC: " << RC << "\n";
1031
1032 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1033 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1034 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1035 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
1036 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(A);
1037 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(B);
1038 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(C);
1039 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(D);
1040
1041 // Connect the top to the bottom forming a large RefSCC made up just of
1042 // references.
1043 auto MergedRCs = ARC.insertIncomingRefEdge(D, A);
1044 // Make sure we connected the nodes.
1045 EXPECT_NE(D->begin(), D->end());
1046 EXPECT_EQ(&A, &D->begin()->getNode());
1047
1048 // Check that we have the dead RCs, but ignore the order.
1049 EXPECT_EQ(3u, MergedRCs.size());
1050 EXPECT_NE(find(MergedRCs, &BRC), MergedRCs.end());
1051 EXPECT_NE(find(MergedRCs, &CRC), MergedRCs.end());
1052 EXPECT_NE(find(MergedRCs, &DRC), MergedRCs.end());
1053
1054 // Make sure the nodes point to the right place now.
1055 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
1056 EXPECT_EQ(&ARC, CG.lookupRefSCC(B));
1057 EXPECT_EQ(&ARC, CG.lookupRefSCC(C));
1058 EXPECT_EQ(&ARC, CG.lookupRefSCC(D));
1059
1060 // And verify the post-order walk reflects the updated structure.
1061 auto I = CG.postorder_ref_scc_begin(), End = CG.postorder_ref_scc_end();
1062 ASSERT_NE(I, End);
1063 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
1064 EXPECT_EQ(++I, End);
1065 }
1066
TEST(LazyCallGraphTest,InlineAndDeleteFunction)1067 TEST(LazyCallGraphTest, InlineAndDeleteFunction) {
1068 LLVMContext Context;
1069 // We want to ensure we can delete nodes from relatively complex graphs and
1070 // so use the diamond of triangles graph defined above.
1071 //
1072 // The ascii diagram is repeated here for easy reference.
1073 //
1074 // d1 |
1075 // / \ |
1076 // d3--d2 |
1077 // / \ |
1078 // b1 c1 |
1079 // / \ / \ |
1080 // b3--b2 c3--c2 |
1081 // \ / |
1082 // a1 |
1083 // / \ |
1084 // a3--a2 |
1085 //
1086 std::unique_ptr<Module> M = parseAssembly(Context, DiamondOfTriangles);
1087 LazyCallGraph CG = buildCG(*M);
1088
1089 // Force the graph to be fully expanded.
1090 CG.buildRefSCCs();
1091 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
1092 dbgs() << "Formed RefSCC: " << RC << "\n";
1093
1094 LazyCallGraph::Node &A1 = *CG.lookup(lookupFunction(*M, "a1"));
1095 LazyCallGraph::Node &A2 = *CG.lookup(lookupFunction(*M, "a2"));
1096 LazyCallGraph::Node &A3 = *CG.lookup(lookupFunction(*M, "a3"));
1097 LazyCallGraph::Node &B1 = *CG.lookup(lookupFunction(*M, "b1"));
1098 LazyCallGraph::Node &B2 = *CG.lookup(lookupFunction(*M, "b2"));
1099 LazyCallGraph::Node &B3 = *CG.lookup(lookupFunction(*M, "b3"));
1100 LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
1101 LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
1102 LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
1103 LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
1104 LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
1105 LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
1106 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(A1);
1107 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(B1);
1108 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(C1);
1109 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(D1);
1110 ASSERT_EQ(&ARC, CG.lookupRefSCC(A2));
1111 ASSERT_EQ(&ARC, CG.lookupRefSCC(A3));
1112 ASSERT_EQ(&BRC, CG.lookupRefSCC(B2));
1113 ASSERT_EQ(&BRC, CG.lookupRefSCC(B3));
1114 ASSERT_EQ(&CRC, CG.lookupRefSCC(C2));
1115 ASSERT_EQ(&CRC, CG.lookupRefSCC(C3));
1116 ASSERT_EQ(&DRC, CG.lookupRefSCC(D2));
1117 ASSERT_EQ(&DRC, CG.lookupRefSCC(D3));
1118 ASSERT_EQ(1, std::distance(D2->begin(), D2->end()));
1119
1120 // Delete d2 from the graph, as if it had been inlined.
1121 //
1122 // d1 |
1123 // / / |
1124 // d3--. |
1125 // / \ |
1126 // b1 c1 |
1127 // / \ / \ |
1128 // b3--b2 c3--c2 |
1129 // \ / |
1130 // a1 |
1131 // / \ |
1132 // a3--a2 |
1133
1134 Function &D2F = D2.getFunction();
1135 CallInst *C1Call = nullptr, *D1Call = nullptr;
1136 for (User *U : D2F.users()) {
1137 CallInst *CI = dyn_cast<CallInst>(U);
1138 ASSERT_TRUE(CI) << "Expected a call: " << *U;
1139 if (CI->getParent()->getParent() == &C1.getFunction()) {
1140 ASSERT_EQ(nullptr, C1Call) << "Found too many C1 calls: " << *CI;
1141 C1Call = CI;
1142 } else if (CI->getParent()->getParent() == &D1.getFunction()) {
1143 ASSERT_EQ(nullptr, D1Call) << "Found too many D1 calls: " << *CI;
1144 D1Call = CI;
1145 } else {
1146 FAIL() << "Found an unexpected call instruction: " << *CI;
1147 }
1148 }
1149 ASSERT_NE(C1Call, nullptr);
1150 ASSERT_NE(D1Call, nullptr);
1151 ASSERT_EQ(&D2F, C1Call->getCalledFunction());
1152 ASSERT_EQ(&D2F, D1Call->getCalledFunction());
1153 C1Call->setCalledFunction(&D3.getFunction());
1154 D1Call->setCalledFunction(&D3.getFunction());
1155 ASSERT_EQ(0u, D2F.getNumUses());
1156
1157 // Insert new edges first.
1158 CRC.insertTrivialCallEdge(C1, D3);
1159 DRC.insertTrivialCallEdge(D1, D3);
1160
1161 // Then remove the old ones.
1162 LazyCallGraph::SCC &DC = *CG.lookupSCC(D2);
1163 auto NewCs = DRC.switchInternalEdgeToRef(D1, D2);
1164 EXPECT_EQ(&DC, CG.lookupSCC(D2));
1165 EXPECT_EQ(NewCs.end(), std::next(NewCs.begin()));
1166 LazyCallGraph::SCC &NewDC = *NewCs.begin();
1167 EXPECT_EQ(&NewDC, CG.lookupSCC(D1));
1168 EXPECT_EQ(&NewDC, CG.lookupSCC(D3));
1169 auto NewRCs = DRC.removeInternalRefEdge(D1, {&D2});
1170 ASSERT_EQ(2u, NewRCs.size());
1171 LazyCallGraph::RefSCC &NewDRC = *NewRCs[0];
1172 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D1));
1173 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D3));
1174 LazyCallGraph::RefSCC &D2RC = *NewRCs[1];
1175 EXPECT_EQ(&D2RC, CG.lookupRefSCC(D2));
1176 EXPECT_FALSE(NewDRC.isParentOf(D2RC));
1177 EXPECT_TRUE(CRC.isParentOf(D2RC));
1178 EXPECT_TRUE(CRC.isParentOf(NewDRC));
1179 EXPECT_TRUE(D2RC.isParentOf(NewDRC));
1180 CRC.removeOutgoingEdge(C1, D2);
1181 EXPECT_FALSE(CRC.isParentOf(D2RC));
1182 EXPECT_TRUE(CRC.isParentOf(NewDRC));
1183 EXPECT_TRUE(D2RC.isParentOf(NewDRC));
1184
1185 // Now that we've updated the call graph, D2 is dead, so remove it.
1186 CG.removeDeadFunction(D2F);
1187
1188 // Check that the graph still looks the same.
1189 EXPECT_EQ(&ARC, CG.lookupRefSCC(A1));
1190 EXPECT_EQ(&ARC, CG.lookupRefSCC(A2));
1191 EXPECT_EQ(&ARC, CG.lookupRefSCC(A3));
1192 EXPECT_EQ(&BRC, CG.lookupRefSCC(B1));
1193 EXPECT_EQ(&BRC, CG.lookupRefSCC(B2));
1194 EXPECT_EQ(&BRC, CG.lookupRefSCC(B3));
1195 EXPECT_EQ(&CRC, CG.lookupRefSCC(C1));
1196 EXPECT_EQ(&CRC, CG.lookupRefSCC(C2));
1197 EXPECT_EQ(&CRC, CG.lookupRefSCC(C3));
1198 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D1));
1199 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D3));
1200 EXPECT_TRUE(CRC.isParentOf(NewDRC));
1201
1202 // Verify the post-order walk hasn't changed.
1203 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
1204 ASSERT_NE(I, E);
1205 EXPECT_EQ(&NewDRC, &*I) << "Actual RefSCC: " << *I;
1206 ASSERT_NE(++I, E);
1207 EXPECT_EQ(&CRC, &*I) << "Actual RefSCC: " << *I;
1208 ASSERT_NE(++I, E);
1209 EXPECT_EQ(&BRC, &*I) << "Actual RefSCC: " << *I;
1210 ASSERT_NE(++I, E);
1211 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
1212 EXPECT_EQ(++I, E);
1213 }
1214
TEST(LazyCallGraphTest,InternalEdgeMutation)1215 TEST(LazyCallGraphTest, InternalEdgeMutation) {
1216 LLVMContext Context;
1217 std::unique_ptr<Module> M = parseAssembly(Context, "define void @a() {\n"
1218 "entry:\n"
1219 " call void @b()\n"
1220 " ret void\n"
1221 "}\n"
1222 "define void @b() {\n"
1223 "entry:\n"
1224 " call void @c()\n"
1225 " ret void\n"
1226 "}\n"
1227 "define void @c() {\n"
1228 "entry:\n"
1229 " call void @a()\n"
1230 " ret void\n"
1231 "}\n");
1232 LazyCallGraph CG = buildCG(*M);
1233
1234 // Force the graph to be fully expanded.
1235 CG.buildRefSCCs();
1236 auto I = CG.postorder_ref_scc_begin();
1237 LazyCallGraph::RefSCC &RC = *I++;
1238 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1239
1240 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1241 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1242 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1243 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1244 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1245 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
1246 EXPECT_EQ(1, RC.size());
1247 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(A));
1248 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(B));
1249 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(C));
1250
1251 // Insert an edge from 'a' to 'c'. Nothing changes about the graph.
1252 RC.insertInternalRefEdge(A, C);
1253 EXPECT_EQ(2, std::distance(A->begin(), A->end()));
1254 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1255 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1256 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
1257 EXPECT_EQ(1, RC.size());
1258 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(A));
1259 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(B));
1260 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(C));
1261
1262 // Switch the call edge from 'b' to 'c' to a ref edge. This will break the
1263 // call cycle and cause us to form more SCCs. The RefSCC will remain the same
1264 // though.
1265 auto NewCs = RC.switchInternalEdgeToRef(B, C);
1266 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1267 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1268 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
1269 auto J = RC.begin();
1270 // The SCCs must be in *post-order* which means successors before
1271 // predecessors. At this point we have call edges from C to A and from A to
1272 // B. The only valid postorder is B, A, C.
1273 EXPECT_EQ(&*J++, CG.lookupSCC(B));
1274 EXPECT_EQ(&*J++, CG.lookupSCC(A));
1275 EXPECT_EQ(&*J++, CG.lookupSCC(C));
1276 EXPECT_EQ(RC.end(), J);
1277 // And the returned range must be the slice of this sequence containing new
1278 // SCCs.
1279 EXPECT_EQ(RC.begin(), NewCs.begin());
1280 EXPECT_EQ(std::prev(RC.end()), NewCs.end());
1281
1282 // Test turning the ref edge from A to C into a call edge. This will form an
1283 // SCC out of A and C. Since we previously had a call edge from C to A, the
1284 // C SCC should be preserved and have A merged into it while the A SCC should
1285 // be invalidated.
1286 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
1287 LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
1288 EXPECT_TRUE(RC.switchInternalEdgeToCall(A, C, [&](ArrayRef<LazyCallGraph::SCC *> MergedCs) {
1289 ASSERT_EQ(1u, MergedCs.size());
1290 EXPECT_EQ(&AC, MergedCs[0]);
1291 }));
1292 EXPECT_EQ(2, CC.size());
1293 EXPECT_EQ(&CC, CG.lookupSCC(A));
1294 EXPECT_EQ(&CC, CG.lookupSCC(C));
1295 J = RC.begin();
1296 EXPECT_EQ(&*J++, CG.lookupSCC(B));
1297 EXPECT_EQ(&*J++, CG.lookupSCC(C));
1298 EXPECT_EQ(RC.end(), J);
1299 }
1300
TEST(LazyCallGraphTest,InternalEdgeRemoval)1301 TEST(LazyCallGraphTest, InternalEdgeRemoval) {
1302 LLVMContext Context;
1303 // A nice fully connected (including self-edges) RefSCC.
1304 std::unique_ptr<Module> M = parseAssembly(
1305 Context, "define void @a(i8** %ptr) {\n"
1306 "entry:\n"
1307 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1308 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1309 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1310 " ret void\n"
1311 "}\n"
1312 "define void @b(i8** %ptr) {\n"
1313 "entry:\n"
1314 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1315 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1316 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1317 " ret void\n"
1318 "}\n"
1319 "define void @c(i8** %ptr) {\n"
1320 "entry:\n"
1321 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1322 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1323 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1324 " ret void\n"
1325 "}\n");
1326 LazyCallGraph CG = buildCG(*M);
1327
1328 // Force the graph to be fully expanded.
1329 CG.buildRefSCCs();
1330 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
1331 LazyCallGraph::RefSCC &RC = *I;
1332 EXPECT_EQ(E, std::next(I));
1333
1334 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1335 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1336 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1337 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1338 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1339 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
1340
1341 // Remove the edge from b -> a, which should leave the 3 functions still in
1342 // a single connected component because of a -> b -> c -> a.
1343 SmallVector<LazyCallGraph::RefSCC *, 1> NewRCs =
1344 RC.removeInternalRefEdge(B, {&A});
1345 EXPECT_EQ(0u, NewRCs.size());
1346 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1347 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1348 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
1349 auto J = CG.postorder_ref_scc_begin();
1350 EXPECT_EQ(I, J);
1351 EXPECT_EQ(&RC, &*J);
1352 EXPECT_EQ(E, std::next(J));
1353
1354 // Increment I before we actually mutate the structure so that it remains
1355 // a valid iterator.
1356 ++I;
1357
1358 // Remove the edge from c -> a, which should leave 'a' in the original RefSCC
1359 // and form a new RefSCC for 'b' and 'c'.
1360 NewRCs = RC.removeInternalRefEdge(C, {&A});
1361 ASSERT_EQ(2u, NewRCs.size());
1362 LazyCallGraph::RefSCC &BCRC = *NewRCs[0];
1363 LazyCallGraph::RefSCC &ARC = *NewRCs[1];
1364 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
1365 EXPECT_EQ(1, std::distance(ARC.begin(), ARC.end()));
1366 EXPECT_EQ(&BCRC, CG.lookupRefSCC(B));
1367 EXPECT_EQ(&BCRC, CG.lookupRefSCC(C));
1368 J = CG.postorder_ref_scc_begin();
1369 EXPECT_NE(I, J);
1370 EXPECT_EQ(&BCRC, &*J);
1371 ++J;
1372 EXPECT_NE(I, J);
1373 EXPECT_EQ(&ARC, &*J);
1374 ++J;
1375 EXPECT_EQ(I, J);
1376 EXPECT_EQ(E, J);
1377 }
1378
TEST(LazyCallGraphTest,InternalMultiEdgeRemoval)1379 TEST(LazyCallGraphTest, InternalMultiEdgeRemoval) {
1380 LLVMContext Context;
1381 // A nice fully connected (including self-edges) RefSCC.
1382 std::unique_ptr<Module> M = parseAssembly(
1383 Context, "define void @a(i8** %ptr) {\n"
1384 "entry:\n"
1385 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1386 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1387 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1388 " ret void\n"
1389 "}\n"
1390 "define void @b(i8** %ptr) {\n"
1391 "entry:\n"
1392 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1393 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1394 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1395 " ret void\n"
1396 "}\n"
1397 "define void @c(i8** %ptr) {\n"
1398 "entry:\n"
1399 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1400 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1401 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1402 " ret void\n"
1403 "}\n");
1404 LazyCallGraph CG = buildCG(*M);
1405
1406 // Force the graph to be fully expanded.
1407 CG.buildRefSCCs();
1408 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
1409 LazyCallGraph::RefSCC &RC = *I;
1410 EXPECT_EQ(E, std::next(I));
1411
1412 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1413 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1414 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1415 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1416 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1417 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
1418
1419 // Increment I before we actually mutate the structure so that it remains
1420 // a valid iterator.
1421 ++I;
1422
1423 // Remove the edges from b -> a and b -> c, leaving b in its own RefSCC.
1424 SmallVector<LazyCallGraph::RefSCC *, 1> NewRCs =
1425 RC.removeInternalRefEdge(B, {&A, &C});
1426
1427 ASSERT_EQ(2u, NewRCs.size());
1428 LazyCallGraph::RefSCC &BRC = *NewRCs[0];
1429 LazyCallGraph::RefSCC &ACRC = *NewRCs[1];
1430 EXPECT_EQ(&BRC, CG.lookupRefSCC(B));
1431 EXPECT_EQ(1, std::distance(BRC.begin(), BRC.end()));
1432 EXPECT_EQ(&ACRC, CG.lookupRefSCC(A));
1433 EXPECT_EQ(&ACRC, CG.lookupRefSCC(C));
1434 auto J = CG.postorder_ref_scc_begin();
1435 EXPECT_NE(I, J);
1436 EXPECT_EQ(&BRC, &*J);
1437 ++J;
1438 EXPECT_NE(I, J);
1439 EXPECT_EQ(&ACRC, &*J);
1440 ++J;
1441 EXPECT_EQ(I, J);
1442 EXPECT_EQ(E, J);
1443 }
1444
TEST(LazyCallGraphTest,InternalNoOpEdgeRemoval)1445 TEST(LazyCallGraphTest, InternalNoOpEdgeRemoval) {
1446 LLVMContext Context;
1447 // A graph with a single cycle formed both from call and reference edges
1448 // which makes the reference edges trivial to delete. The graph looks like:
1449 //
1450 // Reference edges: a -> b -> c -> a
1451 // Call edges: a -> c -> b -> a
1452 std::unique_ptr<Module> M = parseAssembly(
1453 Context, "define void @a(i8** %ptr) {\n"
1454 "entry:\n"
1455 " call void @b(i8** %ptr)\n"
1456 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1457 " ret void\n"
1458 "}\n"
1459 "define void @b(i8** %ptr) {\n"
1460 "entry:\n"
1461 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1462 " call void @c(i8** %ptr)\n"
1463 " ret void\n"
1464 "}\n"
1465 "define void @c(i8** %ptr) {\n"
1466 "entry:\n"
1467 " call void @a(i8** %ptr)\n"
1468 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1469 " ret void\n"
1470 "}\n");
1471 LazyCallGraph CG = buildCG(*M);
1472
1473 // Force the graph to be fully expanded.
1474 CG.buildRefSCCs();
1475 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
1476 LazyCallGraph::RefSCC &RC = *I;
1477 EXPECT_EQ(E, std::next(I));
1478
1479 LazyCallGraph::SCC &C = *RC.begin();
1480 EXPECT_EQ(RC.end(), std::next(RC.begin()));
1481
1482 LazyCallGraph::Node &AN = *CG.lookup(lookupFunction(*M, "a"));
1483 LazyCallGraph::Node &BN = *CG.lookup(lookupFunction(*M, "b"));
1484 LazyCallGraph::Node &CN = *CG.lookup(lookupFunction(*M, "c"));
1485 EXPECT_EQ(&RC, CG.lookupRefSCC(AN));
1486 EXPECT_EQ(&RC, CG.lookupRefSCC(BN));
1487 EXPECT_EQ(&RC, CG.lookupRefSCC(CN));
1488 EXPECT_EQ(&C, CG.lookupSCC(AN));
1489 EXPECT_EQ(&C, CG.lookupSCC(BN));
1490 EXPECT_EQ(&C, CG.lookupSCC(CN));
1491
1492 // Remove the edge from a -> c which doesn't change anything.
1493 SmallVector<LazyCallGraph::RefSCC *, 1> NewRCs =
1494 RC.removeInternalRefEdge(AN, {&CN});
1495 EXPECT_EQ(0u, NewRCs.size());
1496 EXPECT_EQ(&RC, CG.lookupRefSCC(AN));
1497 EXPECT_EQ(&RC, CG.lookupRefSCC(BN));
1498 EXPECT_EQ(&RC, CG.lookupRefSCC(CN));
1499 EXPECT_EQ(&C, CG.lookupSCC(AN));
1500 EXPECT_EQ(&C, CG.lookupSCC(BN));
1501 EXPECT_EQ(&C, CG.lookupSCC(CN));
1502 auto J = CG.postorder_ref_scc_begin();
1503 EXPECT_EQ(I, J);
1504 EXPECT_EQ(&RC, &*J);
1505 EXPECT_EQ(E, std::next(J));
1506
1507 // Remove the edge from b -> a and c -> b; again this doesn't change
1508 // anything.
1509 NewRCs = RC.removeInternalRefEdge(BN, {&AN});
1510 NewRCs = RC.removeInternalRefEdge(CN, {&BN});
1511 EXPECT_EQ(0u, NewRCs.size());
1512 EXPECT_EQ(&RC, CG.lookupRefSCC(AN));
1513 EXPECT_EQ(&RC, CG.lookupRefSCC(BN));
1514 EXPECT_EQ(&RC, CG.lookupRefSCC(CN));
1515 EXPECT_EQ(&C, CG.lookupSCC(AN));
1516 EXPECT_EQ(&C, CG.lookupSCC(BN));
1517 EXPECT_EQ(&C, CG.lookupSCC(CN));
1518 J = CG.postorder_ref_scc_begin();
1519 EXPECT_EQ(I, J);
1520 EXPECT_EQ(&RC, &*J);
1521 EXPECT_EQ(E, std::next(J));
1522 }
1523
TEST(LazyCallGraphTest,InternalCallEdgeToRef)1524 TEST(LazyCallGraphTest, InternalCallEdgeToRef) {
1525 LLVMContext Context;
1526 // A nice fully connected (including self-edges) SCC (and RefSCC)
1527 std::unique_ptr<Module> M = parseAssembly(Context, "define void @a() {\n"
1528 "entry:\n"
1529 " call void @a()\n"
1530 " call void @b()\n"
1531 " call void @c()\n"
1532 " ret void\n"
1533 "}\n"
1534 "define void @b() {\n"
1535 "entry:\n"
1536 " call void @a()\n"
1537 " call void @b()\n"
1538 " call void @c()\n"
1539 " ret void\n"
1540 "}\n"
1541 "define void @c() {\n"
1542 "entry:\n"
1543 " call void @a()\n"
1544 " call void @b()\n"
1545 " call void @c()\n"
1546 " ret void\n"
1547 "}\n");
1548 LazyCallGraph CG = buildCG(*M);
1549
1550 // Force the graph to be fully expanded.
1551 CG.buildRefSCCs();
1552 auto I = CG.postorder_ref_scc_begin();
1553 LazyCallGraph::RefSCC &RC = *I++;
1554 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1555
1556 EXPECT_EQ(1, RC.size());
1557 LazyCallGraph::SCC &AC = *RC.begin();
1558
1559 LazyCallGraph::Node &AN = *CG.lookup(lookupFunction(*M, "a"));
1560 LazyCallGraph::Node &BN = *CG.lookup(lookupFunction(*M, "b"));
1561 LazyCallGraph::Node &CN = *CG.lookup(lookupFunction(*M, "c"));
1562 EXPECT_EQ(&AC, CG.lookupSCC(AN));
1563 EXPECT_EQ(&AC, CG.lookupSCC(BN));
1564 EXPECT_EQ(&AC, CG.lookupSCC(CN));
1565
1566 // Remove the call edge from b -> a to a ref edge, which should leave the
1567 // 3 functions still in a single connected component because of a -> b ->
1568 // c -> a.
1569 auto NewCs = RC.switchInternalEdgeToRef(BN, AN);
1570 EXPECT_EQ(NewCs.begin(), NewCs.end());
1571 EXPECT_EQ(1, RC.size());
1572 EXPECT_EQ(&AC, CG.lookupSCC(AN));
1573 EXPECT_EQ(&AC, CG.lookupSCC(BN));
1574 EXPECT_EQ(&AC, CG.lookupSCC(CN));
1575
1576 // Remove the edge from c -> a, which should leave 'a' in the original SCC
1577 // and form a new SCC for 'b' and 'c'.
1578 NewCs = RC.switchInternalEdgeToRef(CN, AN);
1579 EXPECT_EQ(1, std::distance(NewCs.begin(), NewCs.end()));
1580 EXPECT_EQ(2, RC.size());
1581 EXPECT_EQ(&AC, CG.lookupSCC(AN));
1582 LazyCallGraph::SCC &BC = *CG.lookupSCC(BN);
1583 EXPECT_NE(&BC, &AC);
1584 EXPECT_EQ(&BC, CG.lookupSCC(CN));
1585 auto J = RC.find(AC);
1586 EXPECT_EQ(&AC, &*J);
1587 --J;
1588 EXPECT_EQ(&BC, &*J);
1589 EXPECT_EQ(RC.begin(), J);
1590 EXPECT_EQ(J, NewCs.begin());
1591
1592 // Remove the edge from c -> b, which should leave 'b' in the original SCC
1593 // and form a new SCC for 'c'. It shouldn't change 'a's SCC.
1594 NewCs = RC.switchInternalEdgeToRef(CN, BN);
1595 EXPECT_EQ(1, std::distance(NewCs.begin(), NewCs.end()));
1596 EXPECT_EQ(3, RC.size());
1597 EXPECT_EQ(&AC, CG.lookupSCC(AN));
1598 EXPECT_EQ(&BC, CG.lookupSCC(BN));
1599 LazyCallGraph::SCC &CC = *CG.lookupSCC(CN);
1600 EXPECT_NE(&CC, &AC);
1601 EXPECT_NE(&CC, &BC);
1602 J = RC.find(AC);
1603 EXPECT_EQ(&AC, &*J);
1604 --J;
1605 EXPECT_EQ(&BC, &*J);
1606 --J;
1607 EXPECT_EQ(&CC, &*J);
1608 EXPECT_EQ(RC.begin(), J);
1609 EXPECT_EQ(J, NewCs.begin());
1610 }
1611
TEST(LazyCallGraphTest,InternalRefEdgeToCall)1612 TEST(LazyCallGraphTest, InternalRefEdgeToCall) {
1613 LLVMContext Context;
1614 // Basic tests for making a ref edge a call. This hits the basics of the
1615 // process only.
1616 std::unique_ptr<Module> M =
1617 parseAssembly(Context, "define void @a() {\n"
1618 "entry:\n"
1619 " call void @b()\n"
1620 " call void @c()\n"
1621 " store void()* @d, void()** undef\n"
1622 " ret void\n"
1623 "}\n"
1624 "define void @b() {\n"
1625 "entry:\n"
1626 " store void()* @c, void()** undef\n"
1627 " call void @d()\n"
1628 " ret void\n"
1629 "}\n"
1630 "define void @c() {\n"
1631 "entry:\n"
1632 " store void()* @b, void()** undef\n"
1633 " call void @d()\n"
1634 " ret void\n"
1635 "}\n"
1636 "define void @d() {\n"
1637 "entry:\n"
1638 " store void()* @a, void()** undef\n"
1639 " ret void\n"
1640 "}\n");
1641 LazyCallGraph CG = buildCG(*M);
1642
1643 // Force the graph to be fully expanded.
1644 CG.buildRefSCCs();
1645 auto I = CG.postorder_ref_scc_begin();
1646 LazyCallGraph::RefSCC &RC = *I++;
1647 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1648
1649 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1650 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1651 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1652 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
1653 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
1654 LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
1655 LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
1656 LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
1657
1658 // Check the initial post-order. Note that B and C could be flipped here (and
1659 // in our mutation) without changing the nature of this test.
1660 ASSERT_EQ(4, RC.size());
1661 EXPECT_EQ(&DC, &RC[0]);
1662 EXPECT_EQ(&BC, &RC[1]);
1663 EXPECT_EQ(&CC, &RC[2]);
1664 EXPECT_EQ(&AC, &RC[3]);
1665
1666 // Switch the ref edge from A -> D to a call edge. This should have no
1667 // effect as it is already in postorder and no new cycles are formed.
1668 EXPECT_FALSE(RC.switchInternalEdgeToCall(A, D));
1669 ASSERT_EQ(4, RC.size());
1670 EXPECT_EQ(&DC, &RC[0]);
1671 EXPECT_EQ(&BC, &RC[1]);
1672 EXPECT_EQ(&CC, &RC[2]);
1673 EXPECT_EQ(&AC, &RC[3]);
1674
1675 // Switch B -> C to a call edge. This doesn't form any new cycles but does
1676 // require reordering the SCCs.
1677 EXPECT_FALSE(RC.switchInternalEdgeToCall(B, C));
1678 ASSERT_EQ(4, RC.size());
1679 EXPECT_EQ(&DC, &RC[0]);
1680 EXPECT_EQ(&CC, &RC[1]);
1681 EXPECT_EQ(&BC, &RC[2]);
1682 EXPECT_EQ(&AC, &RC[3]);
1683
1684 // Switch C -> B to a call edge. This forms a cycle and forces merging SCCs.
1685 EXPECT_TRUE(RC.switchInternalEdgeToCall(C, B, [&](ArrayRef<LazyCallGraph::SCC *> MergedCs) {
1686 ASSERT_EQ(1u, MergedCs.size());
1687 EXPECT_EQ(&CC, MergedCs[0]);
1688 }));
1689 ASSERT_EQ(3, RC.size());
1690 EXPECT_EQ(&DC, &RC[0]);
1691 EXPECT_EQ(&BC, &RC[1]);
1692 EXPECT_EQ(&AC, &RC[2]);
1693 EXPECT_EQ(2, BC.size());
1694 EXPECT_EQ(&BC, CG.lookupSCC(B));
1695 EXPECT_EQ(&BC, CG.lookupSCC(C));
1696 }
1697
TEST(LazyCallGraphTest,InternalRefEdgeToCallNoCycleInterleaved)1698 TEST(LazyCallGraphTest, InternalRefEdgeToCallNoCycleInterleaved) {
1699 LLVMContext Context;
1700 // Test for having a post-order prior to changing a ref edge to a call edge
1701 // with SCCs connecting to the source and connecting to the target, but not
1702 // connecting to both, interleaved between the source and target. This
1703 // ensures we correctly partition the range rather than simply moving one or
1704 // the other.
1705 std::unique_ptr<Module> M =
1706 parseAssembly(Context, "define void @a() {\n"
1707 "entry:\n"
1708 " call void @b1()\n"
1709 " call void @c1()\n"
1710 " ret void\n"
1711 "}\n"
1712 "define void @b1() {\n"
1713 "entry:\n"
1714 " call void @c1()\n"
1715 " call void @b2()\n"
1716 " ret void\n"
1717 "}\n"
1718 "define void @c1() {\n"
1719 "entry:\n"
1720 " call void @b2()\n"
1721 " call void @c2()\n"
1722 " ret void\n"
1723 "}\n"
1724 "define void @b2() {\n"
1725 "entry:\n"
1726 " call void @c2()\n"
1727 " call void @b3()\n"
1728 " ret void\n"
1729 "}\n"
1730 "define void @c2() {\n"
1731 "entry:\n"
1732 " call void @b3()\n"
1733 " call void @c3()\n"
1734 " ret void\n"
1735 "}\n"
1736 "define void @b3() {\n"
1737 "entry:\n"
1738 " call void @c3()\n"
1739 " call void @d()\n"
1740 " ret void\n"
1741 "}\n"
1742 "define void @c3() {\n"
1743 "entry:\n"
1744 " store void()* @b1, void()** undef\n"
1745 " call void @d()\n"
1746 " ret void\n"
1747 "}\n"
1748 "define void @d() {\n"
1749 "entry:\n"
1750 " store void()* @a, void()** undef\n"
1751 " ret void\n"
1752 "}\n");
1753 LazyCallGraph CG = buildCG(*M);
1754
1755 // Force the graph to be fully expanded.
1756 CG.buildRefSCCs();
1757 auto I = CG.postorder_ref_scc_begin();
1758 LazyCallGraph::RefSCC &RC = *I++;
1759 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1760
1761 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1762 LazyCallGraph::Node &B1 = *CG.lookup(lookupFunction(*M, "b1"));
1763 LazyCallGraph::Node &B2 = *CG.lookup(lookupFunction(*M, "b2"));
1764 LazyCallGraph::Node &B3 = *CG.lookup(lookupFunction(*M, "b3"));
1765 LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
1766 LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
1767 LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
1768 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
1769 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
1770 LazyCallGraph::SCC &B1C = *CG.lookupSCC(B1);
1771 LazyCallGraph::SCC &B2C = *CG.lookupSCC(B2);
1772 LazyCallGraph::SCC &B3C = *CG.lookupSCC(B3);
1773 LazyCallGraph::SCC &C1C = *CG.lookupSCC(C1);
1774 LazyCallGraph::SCC &C2C = *CG.lookupSCC(C2);
1775 LazyCallGraph::SCC &C3C = *CG.lookupSCC(C3);
1776 LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
1777
1778 // Several call edges are initially present to force a particual post-order.
1779 // Remove them now, leaving an interleaved post-order pattern.
1780 RC.switchTrivialInternalEdgeToRef(B3, C3);
1781 RC.switchTrivialInternalEdgeToRef(C2, B3);
1782 RC.switchTrivialInternalEdgeToRef(B2, C2);
1783 RC.switchTrivialInternalEdgeToRef(C1, B2);
1784 RC.switchTrivialInternalEdgeToRef(B1, C1);
1785
1786 // Check the initial post-order. We ensure this order with the extra edges
1787 // that are nuked above.
1788 ASSERT_EQ(8, RC.size());
1789 EXPECT_EQ(&DC, &RC[0]);
1790 EXPECT_EQ(&C3C, &RC[1]);
1791 EXPECT_EQ(&B3C, &RC[2]);
1792 EXPECT_EQ(&C2C, &RC[3]);
1793 EXPECT_EQ(&B2C, &RC[4]);
1794 EXPECT_EQ(&C1C, &RC[5]);
1795 EXPECT_EQ(&B1C, &RC[6]);
1796 EXPECT_EQ(&AC, &RC[7]);
1797
1798 // Switch C3 -> B1 to a call edge. This doesn't form any new cycles but does
1799 // require reordering the SCCs in the face of tricky internal node
1800 // structures.
1801 EXPECT_FALSE(RC.switchInternalEdgeToCall(C3, B1));
1802 ASSERT_EQ(8, RC.size());
1803 EXPECT_EQ(&DC, &RC[0]);
1804 EXPECT_EQ(&B3C, &RC[1]);
1805 EXPECT_EQ(&B2C, &RC[2]);
1806 EXPECT_EQ(&B1C, &RC[3]);
1807 EXPECT_EQ(&C3C, &RC[4]);
1808 EXPECT_EQ(&C2C, &RC[5]);
1809 EXPECT_EQ(&C1C, &RC[6]);
1810 EXPECT_EQ(&AC, &RC[7]);
1811 }
1812
TEST(LazyCallGraphTest,InternalRefEdgeToCallBothPartitionAndMerge)1813 TEST(LazyCallGraphTest, InternalRefEdgeToCallBothPartitionAndMerge) {
1814 LLVMContext Context;
1815 // Test for having a postorder where between the source and target are all
1816 // three kinds of other SCCs:
1817 // 1) One connected to the target only that have to be shifted below the
1818 // source.
1819 // 2) One connected to the source only that have to be shifted below the
1820 // target.
1821 // 3) One connected to both source and target that has to remain and get
1822 // merged away.
1823 //
1824 // To achieve this we construct a heavily connected graph to force
1825 // a particular post-order. Then we remove the forcing edges and connect
1826 // a cycle.
1827 //
1828 // Diagram for the graph we want on the left and the graph we use to force
1829 // the ordering on the right. Edges ponit down or right.
1830 //
1831 // A | A |
1832 // / \ | / \ |
1833 // B E | B \ |
1834 // |\ | | |\ | |
1835 // | D | | C-D-E |
1836 // | \| | | \| |
1837 // C F | \ F |
1838 // \ / | \ / |
1839 // G | G |
1840 //
1841 // And we form a cycle by connecting F to B.
1842 std::unique_ptr<Module> M =
1843 parseAssembly(Context, "define void @a() {\n"
1844 "entry:\n"
1845 " call void @b()\n"
1846 " call void @e()\n"
1847 " ret void\n"
1848 "}\n"
1849 "define void @b() {\n"
1850 "entry:\n"
1851 " call void @c()\n"
1852 " call void @d()\n"
1853 " ret void\n"
1854 "}\n"
1855 "define void @c() {\n"
1856 "entry:\n"
1857 " call void @d()\n"
1858 " call void @g()\n"
1859 " ret void\n"
1860 "}\n"
1861 "define void @d() {\n"
1862 "entry:\n"
1863 " call void @e()\n"
1864 " call void @f()\n"
1865 " ret void\n"
1866 "}\n"
1867 "define void @e() {\n"
1868 "entry:\n"
1869 " call void @f()\n"
1870 " ret void\n"
1871 "}\n"
1872 "define void @f() {\n"
1873 "entry:\n"
1874 " store void()* @b, void()** undef\n"
1875 " call void @g()\n"
1876 " ret void\n"
1877 "}\n"
1878 "define void @g() {\n"
1879 "entry:\n"
1880 " store void()* @a, void()** undef\n"
1881 " ret void\n"
1882 "}\n");
1883 LazyCallGraph CG = buildCG(*M);
1884
1885 // Force the graph to be fully expanded.
1886 CG.buildRefSCCs();
1887 auto I = CG.postorder_ref_scc_begin();
1888 LazyCallGraph::RefSCC &RC = *I++;
1889 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1890
1891 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1892 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1893 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1894 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
1895 LazyCallGraph::Node &E = *CG.lookup(lookupFunction(*M, "e"));
1896 LazyCallGraph::Node &F = *CG.lookup(lookupFunction(*M, "f"));
1897 LazyCallGraph::Node &G = *CG.lookup(lookupFunction(*M, "g"));
1898 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
1899 LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
1900 LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
1901 LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
1902 LazyCallGraph::SCC &EC = *CG.lookupSCC(E);
1903 LazyCallGraph::SCC &FC = *CG.lookupSCC(F);
1904 LazyCallGraph::SCC &GC = *CG.lookupSCC(G);
1905
1906 // Remove the extra edges that were used to force a particular post-order.
1907 RC.switchTrivialInternalEdgeToRef(C, D);
1908 RC.switchTrivialInternalEdgeToRef(D, E);
1909
1910 // Check the initial post-order. We ensure this order with the extra edges
1911 // that are nuked above.
1912 ASSERT_EQ(7, RC.size());
1913 EXPECT_EQ(&GC, &RC[0]);
1914 EXPECT_EQ(&FC, &RC[1]);
1915 EXPECT_EQ(&EC, &RC[2]);
1916 EXPECT_EQ(&DC, &RC[3]);
1917 EXPECT_EQ(&CC, &RC[4]);
1918 EXPECT_EQ(&BC, &RC[5]);
1919 EXPECT_EQ(&AC, &RC[6]);
1920
1921 // Switch F -> B to a call edge. This merges B, D, and F into a single SCC,
1922 // and has to place the C and E SCCs on either side of it:
1923 // A A |
1924 // / \ / \ |
1925 // B E | E |
1926 // |\ | \ / |
1927 // | D | -> B |
1928 // | \| / \ |
1929 // C F C | |
1930 // \ / \ / |
1931 // G G |
1932 EXPECT_TRUE(RC.switchInternalEdgeToCall(
1933 F, B, [&](ArrayRef<LazyCallGraph::SCC *> MergedCs) {
1934 ASSERT_EQ(2u, MergedCs.size());
1935 EXPECT_EQ(&FC, MergedCs[0]);
1936 EXPECT_EQ(&DC, MergedCs[1]);
1937 }));
1938 EXPECT_EQ(3, BC.size());
1939
1940 // And make sure the postorder was updated.
1941 ASSERT_EQ(5, RC.size());
1942 EXPECT_EQ(&GC, &RC[0]);
1943 EXPECT_EQ(&CC, &RC[1]);
1944 EXPECT_EQ(&BC, &RC[2]);
1945 EXPECT_EQ(&EC, &RC[3]);
1946 EXPECT_EQ(&AC, &RC[4]);
1947 }
1948
1949 // Test for IR containing constants using blockaddress constant expressions.
1950 // These are truly unique constructs: constant expressions with non-constant
1951 // operands.
TEST(LazyCallGraphTest,HandleBlockAddress)1952 TEST(LazyCallGraphTest, HandleBlockAddress) {
1953 LLVMContext Context;
1954 std::unique_ptr<Module> M =
1955 parseAssembly(Context, "define void @f() {\n"
1956 "entry:\n"
1957 " ret void\n"
1958 "bb:\n"
1959 " unreachable\n"
1960 "}\n"
1961 "define void @g(i8** %ptr) {\n"
1962 "entry:\n"
1963 " store i8* blockaddress(@f, %bb), i8** %ptr\n"
1964 " ret void\n"
1965 "}\n");
1966 LazyCallGraph CG = buildCG(*M);
1967
1968 CG.buildRefSCCs();
1969 auto I = CG.postorder_ref_scc_begin();
1970 LazyCallGraph::RefSCC &FRC = *I++;
1971 LazyCallGraph::RefSCC &GRC = *I++;
1972 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1973
1974 LazyCallGraph::Node &F = *CG.lookup(lookupFunction(*M, "f"));
1975 LazyCallGraph::Node &G = *CG.lookup(lookupFunction(*M, "g"));
1976 EXPECT_EQ(&FRC, CG.lookupRefSCC(F));
1977 EXPECT_EQ(&GRC, CG.lookupRefSCC(G));
1978 EXPECT_TRUE(GRC.isParentOf(FRC));
1979 }
1980
TEST(LazyCallGraphTest,ReplaceNodeFunction)1981 TEST(LazyCallGraphTest, ReplaceNodeFunction) {
1982 LLVMContext Context;
1983 // A graph with several different kinds of edges pointing at a particular
1984 // function.
1985 std::unique_ptr<Module> M =
1986 parseAssembly(Context,
1987 "define void @a(i8** %ptr) {\n"
1988 "entry:\n"
1989 " store i8* bitcast (void(i8**)* @d to i8*), i8** %ptr\n"
1990 " ret void\n"
1991 "}\n"
1992 "define void @b(i8** %ptr) {\n"
1993 "entry:\n"
1994 " store i8* bitcast (void(i8**)* @d to i8*), i8** %ptr\n"
1995 " store i8* bitcast (void(i8**)* @d to i8*), i8** %ptr\n"
1996 " call void @d(i8** %ptr)"
1997 " ret void\n"
1998 "}\n"
1999 "define void @c(i8** %ptr) {\n"
2000 "entry:\n"
2001 " call void @d(i8** %ptr)"
2002 " call void @d(i8** %ptr)"
2003 " store i8* bitcast (void(i8**)* @d to i8*), i8** %ptr\n"
2004 " ret void\n"
2005 "}\n"
2006 "define void @d(i8** %ptr) {\n"
2007 "entry:\n"
2008 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
2009 " call void @c(i8** %ptr)"
2010 " call void @d(i8** %ptr)"
2011 " store i8* bitcast (void(i8**)* @d to i8*), i8** %ptr\n"
2012 " ret void\n"
2013 "}\n");
2014 LazyCallGraph CG = buildCG(*M);
2015
2016 // Force the graph to be fully expanded.
2017 CG.buildRefSCCs();
2018 auto I = CG.postorder_ref_scc_begin();
2019 LazyCallGraph::RefSCC &RC1 = *I++;
2020 LazyCallGraph::RefSCC &RC2 = *I++;
2021 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2022
2023 ASSERT_EQ(2, RC1.size());
2024 LazyCallGraph::SCC &C1 = RC1[0];
2025 LazyCallGraph::SCC &C2 = RC1[1];
2026
2027 LazyCallGraph::Node &AN = *CG.lookup(lookupFunction(*M, "a"));
2028 LazyCallGraph::Node &BN = *CG.lookup(lookupFunction(*M, "b"));
2029 LazyCallGraph::Node &CN = *CG.lookup(lookupFunction(*M, "c"));
2030 LazyCallGraph::Node &DN = *CG.lookup(lookupFunction(*M, "d"));
2031 EXPECT_EQ(&C1, CG.lookupSCC(DN));
2032 EXPECT_EQ(&C1, CG.lookupSCC(CN));
2033 EXPECT_EQ(&C2, CG.lookupSCC(BN));
2034 EXPECT_EQ(&RC1, CG.lookupRefSCC(DN));
2035 EXPECT_EQ(&RC1, CG.lookupRefSCC(CN));
2036 EXPECT_EQ(&RC1, CG.lookupRefSCC(BN));
2037 EXPECT_EQ(&RC2, CG.lookupRefSCC(AN));
2038
2039 // Now we need to build a new function 'e' with the same signature as 'd'.
2040 Function &D = DN.getFunction();
2041 Function &E = *Function::Create(D.getFunctionType(), D.getLinkage(), "e");
2042 D.getParent()->getFunctionList().insert(D.getIterator(), &E);
2043
2044 // Change each use of 'd' to use 'e'. This is particularly easy as they have
2045 // the same type.
2046 D.replaceAllUsesWith(&E);
2047
2048 // Splice the body of the old function into the new one.
2049 E.getBasicBlockList().splice(E.begin(), D.getBasicBlockList());
2050 // And fix up the one argument.
2051 D.arg_begin()->replaceAllUsesWith(&*E.arg_begin());
2052 E.arg_begin()->takeName(&*D.arg_begin());
2053
2054 // Now replace the function in the graph.
2055 RC1.replaceNodeFunction(DN, E);
2056
2057 EXPECT_EQ(&E, &DN.getFunction());
2058 EXPECT_EQ(&DN, &(*CN)[DN].getNode());
2059 EXPECT_EQ(&DN, &(*BN)[DN].getNode());
2060 }
2061
TEST(LazyCallGraphTest,RemoveFunctionWithSpurriousRef)2062 TEST(LazyCallGraphTest, RemoveFunctionWithSpurriousRef) {
2063 LLVMContext Context;
2064 // A graph with a couple of RefSCCs.
2065 std::unique_ptr<Module> M =
2066 parseAssembly(Context,
2067 "define void @a(i8** %ptr) {\n"
2068 "entry:\n"
2069 " store i8* bitcast (void(i8**)* @d to i8*), i8** %ptr\n"
2070 " ret void\n"
2071 "}\n"
2072 "define void @b(i8** %ptr) {\n"
2073 "entry:\n"
2074 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
2075 " ret void\n"
2076 "}\n"
2077 "define void @c(i8** %ptr) {\n"
2078 "entry:\n"
2079 " call void @d(i8** %ptr)"
2080 " ret void\n"
2081 "}\n"
2082 "define void @d(i8** %ptr) {\n"
2083 "entry:\n"
2084 " call void @c(i8** %ptr)"
2085 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
2086 " ret void\n"
2087 "}\n"
2088 "define void @dead() {\n"
2089 "entry:\n"
2090 " ret void\n"
2091 "}\n");
2092 LazyCallGraph CG = buildCG(*M);
2093
2094 // Insert spurious ref edges.
2095 LazyCallGraph::Node &AN = CG.get(lookupFunction(*M, "a"));
2096 LazyCallGraph::Node &BN = CG.get(lookupFunction(*M, "b"));
2097 LazyCallGraph::Node &CN = CG.get(lookupFunction(*M, "c"));
2098 LazyCallGraph::Node &DN = CG.get(lookupFunction(*M, "d"));
2099 LazyCallGraph::Node &DeadN = CG.get(lookupFunction(*M, "dead"));
2100 AN.populate();
2101 BN.populate();
2102 CN.populate();
2103 DN.populate();
2104 DeadN.populate();
2105 CG.insertEdge(AN, DeadN, LazyCallGraph::Edge::Ref);
2106 CG.insertEdge(BN, DeadN, LazyCallGraph::Edge::Ref);
2107 CG.insertEdge(CN, DeadN, LazyCallGraph::Edge::Ref);
2108 CG.insertEdge(DN, DeadN, LazyCallGraph::Edge::Ref);
2109
2110 // Force the graph to be fully expanded.
2111 CG.buildRefSCCs();
2112 auto I = CG.postorder_ref_scc_begin();
2113 LazyCallGraph::RefSCC &DeadRC = *I++;
2114 LazyCallGraph::RefSCC &RC1 = *I++;
2115 LazyCallGraph::RefSCC &RC2 = *I++;
2116 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2117
2118 ASSERT_EQ(2, RC1.size());
2119 LazyCallGraph::SCC &C1 = RC1[0];
2120 LazyCallGraph::SCC &C2 = RC1[1];
2121
2122 EXPECT_EQ(&DeadRC, CG.lookupRefSCC(DeadN));
2123 EXPECT_EQ(&C1, CG.lookupSCC(DN));
2124 EXPECT_EQ(&C1, CG.lookupSCC(CN));
2125 EXPECT_EQ(&C2, CG.lookupSCC(BN));
2126 EXPECT_EQ(&RC1, CG.lookupRefSCC(DN));
2127 EXPECT_EQ(&RC1, CG.lookupRefSCC(CN));
2128 EXPECT_EQ(&RC1, CG.lookupRefSCC(BN));
2129 EXPECT_EQ(&RC2, CG.lookupRefSCC(AN));
2130
2131 // Now delete 'dead'. There are no uses of this function but there are
2132 // spurious references.
2133 CG.removeDeadFunction(DeadN.getFunction());
2134
2135 // The only observable change should be that the RefSCC is gone from the
2136 // postorder sequence.
2137 I = CG.postorder_ref_scc_begin();
2138 EXPECT_EQ(&RC1, &*I++);
2139 EXPECT_EQ(&RC2, &*I++);
2140 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2141 }
2142 }
2143