1//===- LazyCallGraphTest.cpp - Unit tests for the lazy CG analysis --------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/Analysis/LazyCallGraph.h"
10#include "llvm/AsmParser/Parser.h"
11#include "llvm/IR/Function.h"
12#include "llvm/IR/Instructions.h"
13#include "llvm/IR/LLVMContext.h"
14#include "llvm/IR/Module.h"
15#include "llvm/IR/Verifier.h"
16#include "llvm/Support/ErrorHandling.h"
17#include "llvm/Support/SourceMgr.h"
18#include "llvm/TargetParser/Triple.h"
19#include "gtest/gtest.h"
20#include <memory>
21
22using namespace llvm;
23
24namespace {
25
26std::unique_ptr<Module> parseAssembly(LLVMContext &Context,
27 const char *Assembly) {
28 SMDiagnostic Error;
29 std::unique_ptr<Module> M = parseAssemblyString(AsmString: Assembly, Err&: Error, Context);
30
31 std::string ErrMsg;
32 raw_string_ostream OS(ErrMsg);
33 Error.print(ProgName: "", S&: OS);
34
35 // A failure here means that the test itself is buggy.
36 if (!M)
37 report_fatal_error(reason: OS.str().c_str());
38
39 return M;
40}
41
42/*
43 IR forming a call graph with a diamond of triangle-shaped SCCs:
44
45 d1
46 / \
47 d3--d2
48 / \
49 b1 c1
50 / \ / \
51 b3--b2 c3--c2
52 \ /
53 a1
54 / \
55 a3--a2
56
57 All call edges go up between SCCs, and clockwise around the SCC.
58 */
59static const char DiamondOfTriangles[] =
60 "define void @a1() {\n"
61 "entry:\n"
62 " call void @a2()\n"
63 " call void @b2()\n"
64 " call void @c3()\n"
65 " ret void\n"
66 "}\n"
67 "define void @a2() {\n"
68 "entry:\n"
69 " call void @a3()\n"
70 " ret void\n"
71 "}\n"
72 "define void @a3() {\n"
73 "entry:\n"
74 " call void @a1()\n"
75 " ret void\n"
76 "}\n"
77 "define void @b1() {\n"
78 "entry:\n"
79 " call void @b2()\n"
80 " call void @d3()\n"
81 " ret void\n"
82 "}\n"
83 "define void @b2() {\n"
84 "entry:\n"
85 " call void @b3()\n"
86 " ret void\n"
87 "}\n"
88 "define void @b3() {\n"
89 "entry:\n"
90 " call void @b1()\n"
91 " ret void\n"
92 "}\n"
93 "define void @c1() {\n"
94 "entry:\n"
95 " call void @c2()\n"
96 " call void @d2()\n"
97 " ret void\n"
98 "}\n"
99 "define void @c2() {\n"
100 "entry:\n"
101 " call void @c3()\n"
102 " ret void\n"
103 "}\n"
104 "define void @c3() {\n"
105 "entry:\n"
106 " call void @c1()\n"
107 " ret void\n"
108 "}\n"
109 "define void @d1() {\n"
110 "entry:\n"
111 " call void @d2()\n"
112 " ret void\n"
113 "}\n"
114 "define void @d2() {\n"
115 "entry:\n"
116 " call void @d3()\n"
117 " ret void\n"
118 "}\n"
119 "define void @d3() {\n"
120 "entry:\n"
121 " call void @d1()\n"
122 " ret void\n"
123 "}\n";
124
125/*
126 IR forming a reference graph with a diamond of triangle-shaped RefSCCs
127
128 d1
129 / \
130 d3--d2
131 / \
132 b1 c1
133 / \ / \
134 b3--b2 c3--c2
135 \ /
136 a1
137 / \
138 a3--a2
139
140 All call edges go up between RefSCCs, and clockwise around the RefSCC.
141 */
142static const char DiamondOfTrianglesRefGraph[] =
143 "define void @a1() {\n"
144 "entry:\n"
145 " %a = alloca void ()*\n"
146 " store void ()* @a2, void ()** %a\n"
147 " store void ()* @b2, void ()** %a\n"
148 " store void ()* @c3, void ()** %a\n"
149 " ret void\n"
150 "}\n"
151 "define void @a2() {\n"
152 "entry:\n"
153 " %a = alloca void ()*\n"
154 " store void ()* @a3, void ()** %a\n"
155 " ret void\n"
156 "}\n"
157 "define void @a3() {\n"
158 "entry:\n"
159 " %a = alloca void ()*\n"
160 " store void ()* @a1, void ()** %a\n"
161 " ret void\n"
162 "}\n"
163 "define void @b1() {\n"
164 "entry:\n"
165 " %a = alloca void ()*\n"
166 " store void ()* @b2, void ()** %a\n"
167 " store void ()* @d3, void ()** %a\n"
168 " ret void\n"
169 "}\n"
170 "define void @b2() {\n"
171 "entry:\n"
172 " %a = alloca void ()*\n"
173 " store void ()* @b3, void ()** %a\n"
174 " ret void\n"
175 "}\n"
176 "define void @b3() {\n"
177 "entry:\n"
178 " %a = alloca void ()*\n"
179 " store void ()* @b1, void ()** %a\n"
180 " ret void\n"
181 "}\n"
182 "define void @c1() {\n"
183 "entry:\n"
184 " %a = alloca void ()*\n"
185 " store void ()* @c2, void ()** %a\n"
186 " store void ()* @d2, void ()** %a\n"
187 " ret void\n"
188 "}\n"
189 "define void @c2() {\n"
190 "entry:\n"
191 " %a = alloca void ()*\n"
192 " store void ()* @c3, void ()** %a\n"
193 " ret void\n"
194 "}\n"
195 "define void @c3() {\n"
196 "entry:\n"
197 " %a = alloca void ()*\n"
198 " store void ()* @c1, void ()** %a\n"
199 " ret void\n"
200 "}\n"
201 "define void @d1() {\n"
202 "entry:\n"
203 " %a = alloca void ()*\n"
204 " store void ()* @d2, void ()** %a\n"
205 " ret void\n"
206 "}\n"
207 "define void @d2() {\n"
208 "entry:\n"
209 " %a = alloca void ()*\n"
210 " store void ()* @d3, void ()** %a\n"
211 " ret void\n"
212 "}\n"
213 "define void @d3() {\n"
214 "entry:\n"
215 " %a = alloca void ()*\n"
216 " store void ()* @d1, void ()** %a\n"
217 " ret void\n"
218 "}\n";
219
220static LazyCallGraph buildCG(Module &M) {
221 TargetLibraryInfoImpl TLII(Triple(M.getTargetTriple()));
222 TargetLibraryInfo TLI(TLII);
223 auto GetTLI = [&TLI](Function &F) -> TargetLibraryInfo & { return TLI; };
224
225 LazyCallGraph CG(M, GetTLI);
226 return CG;
227}
228
229TEST(LazyCallGraphTest, BasicGraphFormation) {
230 LLVMContext Context;
231 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: DiamondOfTriangles);
232 LazyCallGraph CG = buildCG(M&: *M);
233
234 // The order of the entry nodes should be stable w.r.t. the source order of
235 // the IR, and everything in our module is an entry node, so just directly
236 // build variables for each node.
237 auto I = CG.begin();
238 LazyCallGraph::Node &A1 = (I++)->getNode();
239 EXPECT_EQ("a1", A1.getFunction().getName());
240 LazyCallGraph::Node &A2 = (I++)->getNode();
241 EXPECT_EQ("a2", A2.getFunction().getName());
242 LazyCallGraph::Node &A3 = (I++)->getNode();
243 EXPECT_EQ("a3", A3.getFunction().getName());
244 LazyCallGraph::Node &B1 = (I++)->getNode();
245 EXPECT_EQ("b1", B1.getFunction().getName());
246 LazyCallGraph::Node &B2 = (I++)->getNode();
247 EXPECT_EQ("b2", B2.getFunction().getName());
248 LazyCallGraph::Node &B3 = (I++)->getNode();
249 EXPECT_EQ("b3", B3.getFunction().getName());
250 LazyCallGraph::Node &C1 = (I++)->getNode();
251 EXPECT_EQ("c1", C1.getFunction().getName());
252 LazyCallGraph::Node &C2 = (I++)->getNode();
253 EXPECT_EQ("c2", C2.getFunction().getName());
254 LazyCallGraph::Node &C3 = (I++)->getNode();
255 EXPECT_EQ("c3", C3.getFunction().getName());
256 LazyCallGraph::Node &D1 = (I++)->getNode();
257 EXPECT_EQ("d1", D1.getFunction().getName());
258 LazyCallGraph::Node &D2 = (I++)->getNode();
259 EXPECT_EQ("d2", D2.getFunction().getName());
260 LazyCallGraph::Node &D3 = (I++)->getNode();
261 EXPECT_EQ("d3", D3.getFunction().getName());
262 EXPECT_EQ(CG.end(), I);
263
264 // Build vectors and sort them for the rest of the assertions to make them
265 // independent of order.
266 std::vector<std::string> Nodes;
267
268 for (LazyCallGraph::Edge &E : A1.populate())
269 Nodes.push_back(x: std::string(E.getFunction().getName()));
270 llvm::sort(C&: Nodes);
271 EXPECT_EQ("a2", Nodes[0]);
272 EXPECT_EQ("b2", Nodes[1]);
273 EXPECT_EQ("c3", Nodes[2]);
274 Nodes.clear();
275
276 A2.populate();
277 EXPECT_EQ(A2->end(), std::next(A2->begin()));
278 EXPECT_EQ("a3", A2->begin()->getFunction().getName());
279 A3.populate();
280 EXPECT_EQ(A3->end(), std::next(A3->begin()));
281 EXPECT_EQ("a1", A3->begin()->getFunction().getName());
282
283 for (LazyCallGraph::Edge &E : B1.populate())
284 Nodes.push_back(x: std::string(E.getFunction().getName()));
285 llvm::sort(C&: Nodes);
286 EXPECT_EQ("b2", Nodes[0]);
287 EXPECT_EQ("d3", Nodes[1]);
288 Nodes.clear();
289
290 B2.populate();
291 EXPECT_EQ(B2->end(), std::next(B2->begin()));
292 EXPECT_EQ("b3", B2->begin()->getFunction().getName());
293 B3.populate();
294 EXPECT_EQ(B3->end(), std::next(B3->begin()));
295 EXPECT_EQ("b1", B3->begin()->getFunction().getName());
296
297 for (LazyCallGraph::Edge &E : C1.populate())
298 Nodes.push_back(x: std::string(E.getFunction().getName()));
299 llvm::sort(C&: Nodes);
300 EXPECT_EQ("c2", Nodes[0]);
301 EXPECT_EQ("d2", Nodes[1]);
302 Nodes.clear();
303
304 C2.populate();
305 EXPECT_EQ(C2->end(), std::next(C2->begin()));
306 EXPECT_EQ("c3", C2->begin()->getFunction().getName());
307 C3.populate();
308 EXPECT_EQ(C3->end(), std::next(C3->begin()));
309 EXPECT_EQ("c1", C3->begin()->getFunction().getName());
310
311 D1.populate();
312 EXPECT_EQ(D1->end(), std::next(D1->begin()));
313 EXPECT_EQ("d2", D1->begin()->getFunction().getName());
314 D2.populate();
315 EXPECT_EQ(D2->end(), std::next(D2->begin()));
316 EXPECT_EQ("d3", D2->begin()->getFunction().getName());
317 D3.populate();
318 EXPECT_EQ(D3->end(), std::next(D3->begin()));
319 EXPECT_EQ("d1", D3->begin()->getFunction().getName());
320
321 // Now lets look at the RefSCCs and SCCs.
322 CG.buildRefSCCs();
323 auto J = CG.postorder_ref_scc_begin();
324
325 LazyCallGraph::RefSCC &D = *J++;
326 ASSERT_EQ(1, D.size());
327 for (LazyCallGraph::Node &N : *D.begin())
328 Nodes.push_back(x: std::string(N.getFunction().getName()));
329 llvm::sort(C&: Nodes);
330 EXPECT_EQ(3u, Nodes.size());
331 EXPECT_EQ("d1", Nodes[0]);
332 EXPECT_EQ("d2", Nodes[1]);
333 EXPECT_EQ("d3", Nodes[2]);
334 Nodes.clear();
335 EXPECT_FALSE(D.isParentOf(D));
336 EXPECT_FALSE(D.isChildOf(D));
337 EXPECT_FALSE(D.isAncestorOf(D));
338 EXPECT_FALSE(D.isDescendantOf(D));
339 EXPECT_EQ(&D, &*CG.postorder_ref_scc_begin());
340
341 LazyCallGraph::RefSCC &B = *J++;
342 ASSERT_EQ(1, B.size());
343 for (LazyCallGraph::Node &N : *B.begin())
344 Nodes.push_back(x: std::string(N.getFunction().getName()));
345 llvm::sort(C&: Nodes);
346 EXPECT_EQ(3u, Nodes.size());
347 EXPECT_EQ("b1", Nodes[0]);
348 EXPECT_EQ("b2", Nodes[1]);
349 EXPECT_EQ("b3", Nodes[2]);
350 Nodes.clear();
351 EXPECT_TRUE(B.isParentOf(D));
352 EXPECT_FALSE(B.isChildOf(D));
353 EXPECT_TRUE(B.isAncestorOf(D));
354 EXPECT_FALSE(B.isDescendantOf(D));
355 EXPECT_EQ(&B, &*std::next(CG.postorder_ref_scc_begin()));
356
357 LazyCallGraph::RefSCC &C = *J++;
358 ASSERT_EQ(1, C.size());
359 for (LazyCallGraph::Node &N : *C.begin())
360 Nodes.push_back(x: std::string(N.getFunction().getName()));
361 llvm::sort(C&: Nodes);
362 EXPECT_EQ(3u, Nodes.size());
363 EXPECT_EQ("c1", Nodes[0]);
364 EXPECT_EQ("c2", Nodes[1]);
365 EXPECT_EQ("c3", Nodes[2]);
366 Nodes.clear();
367 EXPECT_FALSE(B.isAncestorOf(C));
368 EXPECT_FALSE(C.isAncestorOf(B));
369 EXPECT_TRUE(C.isParentOf(D));
370 EXPECT_FALSE(C.isChildOf(D));
371 EXPECT_TRUE(C.isAncestorOf(D));
372 EXPECT_FALSE(C.isDescendantOf(D));
373 EXPECT_EQ(&C, &*std::next(CG.postorder_ref_scc_begin(), 2));
374
375 LazyCallGraph::RefSCC &A = *J++;
376 ASSERT_EQ(1, A.size());
377 for (LazyCallGraph::Node &N : *A.begin())
378 Nodes.push_back(x: std::string(N.getFunction().getName()));
379 llvm::sort(C&: Nodes);
380 EXPECT_EQ(3u, Nodes.size());
381 EXPECT_EQ("a1", Nodes[0]);
382 EXPECT_EQ("a2", Nodes[1]);
383 EXPECT_EQ("a3", Nodes[2]);
384 Nodes.clear();
385 EXPECT_TRUE(A.isParentOf(B));
386 EXPECT_TRUE(A.isParentOf(C));
387 EXPECT_FALSE(A.isParentOf(D));
388 EXPECT_TRUE(A.isAncestorOf(B));
389 EXPECT_TRUE(A.isAncestorOf(C));
390 EXPECT_TRUE(A.isAncestorOf(D));
391 EXPECT_EQ(&A, &*std::next(CG.postorder_ref_scc_begin(), 3));
392
393 EXPECT_EQ(CG.postorder_ref_scc_end(), J);
394 EXPECT_EQ(J, std::next(CG.postorder_ref_scc_begin(), 4));
395}
396
397static Function &lookupFunction(Module &M, StringRef Name) {
398 for (Function &F : M)
399 if (F.getName() == Name)
400 return F;
401 report_fatal_error(reason: "Couldn't find function!");
402}
403
404TEST(LazyCallGraphTest, BasicGraphMutation) {
405 LLVMContext Context;
406 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: "define void @a() {\n"
407 "entry:\n"
408 " call void @b()\n"
409 " call void @c()\n"
410 " ret void\n"
411 "}\n"
412 "define void @b() {\n"
413 "entry:\n"
414 " ret void\n"
415 "}\n"
416 "define void @c() {\n"
417 "entry:\n"
418 " ret void\n"
419 "}\n");
420 LazyCallGraph CG = buildCG(M&: *M);
421
422 LazyCallGraph::Node &A = CG.get(F&: lookupFunction(M&: *M, Name: "a"));
423 LazyCallGraph::Node &B = CG.get(F&: lookupFunction(M&: *M, Name: "b"));
424 A.populate();
425 EXPECT_EQ(2, std::distance(A->begin(), A->end()));
426 B.populate();
427 EXPECT_EQ(0, std::distance(B->begin(), B->end()));
428
429 LazyCallGraph::Node &C = CG.get(F&: lookupFunction(M&: *M, Name: "c"));
430 C.populate();
431 CG.insertEdge(SourceN&: B, TargetN&: C, EK: LazyCallGraph::Edge::Call);
432 EXPECT_EQ(1, std::distance(B->begin(), B->end()));
433 EXPECT_EQ(0, std::distance(C->begin(), C->end()));
434
435 CG.insertEdge(SourceN&: C, TargetN&: B, EK: LazyCallGraph::Edge::Call);
436 EXPECT_EQ(1, std::distance(C->begin(), C->end()));
437 EXPECT_EQ(&B, &C->begin()->getNode());
438
439 CG.insertEdge(SourceN&: C, TargetN&: C, EK: LazyCallGraph::Edge::Call);
440 EXPECT_EQ(2, std::distance(C->begin(), C->end()));
441 EXPECT_EQ(&B, &C->begin()->getNode());
442 EXPECT_EQ(&C, &std::next(C->begin())->getNode());
443
444 CG.removeEdge(SourceN&: C, TargetN&: B);
445 EXPECT_EQ(1, std::distance(C->begin(), C->end()));
446 EXPECT_EQ(&C, &C->begin()->getNode());
447
448 CG.removeEdge(SourceN&: C, TargetN&: C);
449 EXPECT_EQ(0, std::distance(C->begin(), C->end()));
450
451 CG.removeEdge(SourceN&: B, TargetN&: C);
452 EXPECT_EQ(0, std::distance(B->begin(), B->end()));
453}
454
455TEST(LazyCallGraphTest, InnerSCCFormation) {
456 LLVMContext Context;
457 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: DiamondOfTriangles);
458 LazyCallGraph CG = buildCG(M&: *M);
459
460 // Now mutate the graph to connect every node into a single RefSCC to ensure
461 // that our inner SCC formation handles the rest.
462 LazyCallGraph::Node &D1 = CG.get(F&: lookupFunction(M&: *M, Name: "d1"));
463 LazyCallGraph::Node &A1 = CG.get(F&: lookupFunction(M&: *M, Name: "a1"));
464 A1.populate();
465 D1.populate();
466 CG.insertEdge(SourceN&: D1, TargetN&: A1, EK: LazyCallGraph::Edge::Ref);
467
468 // Build vectors and sort them for the rest of the assertions to make them
469 // independent of order.
470 std::vector<std::string> Nodes;
471
472 // We should build a single RefSCC for the entire graph.
473 CG.buildRefSCCs();
474 auto I = CG.postorder_ref_scc_begin();
475 LazyCallGraph::RefSCC &RC = *I++;
476 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
477
478 // Now walk the four SCCs which should be in post-order.
479 auto J = RC.begin();
480 LazyCallGraph::SCC &D = *J++;
481 for (LazyCallGraph::Node &N : D)
482 Nodes.push_back(x: std::string(N.getFunction().getName()));
483 llvm::sort(C&: Nodes);
484 EXPECT_EQ(3u, Nodes.size());
485 EXPECT_EQ("d1", Nodes[0]);
486 EXPECT_EQ("d2", Nodes[1]);
487 EXPECT_EQ("d3", Nodes[2]);
488 Nodes.clear();
489
490 LazyCallGraph::SCC &B = *J++;
491 for (LazyCallGraph::Node &N : B)
492 Nodes.push_back(x: std::string(N.getFunction().getName()));
493 llvm::sort(C&: Nodes);
494 EXPECT_EQ(3u, Nodes.size());
495 EXPECT_EQ("b1", Nodes[0]);
496 EXPECT_EQ("b2", Nodes[1]);
497 EXPECT_EQ("b3", Nodes[2]);
498 Nodes.clear();
499
500 LazyCallGraph::SCC &C = *J++;
501 for (LazyCallGraph::Node &N : C)
502 Nodes.push_back(x: std::string(N.getFunction().getName()));
503 llvm::sort(C&: Nodes);
504 EXPECT_EQ(3u, Nodes.size());
505 EXPECT_EQ("c1", Nodes[0]);
506 EXPECT_EQ("c2", Nodes[1]);
507 EXPECT_EQ("c3", Nodes[2]);
508 Nodes.clear();
509
510 LazyCallGraph::SCC &A = *J++;
511 for (LazyCallGraph::Node &N : A)
512 Nodes.push_back(x: std::string(N.getFunction().getName()));
513 llvm::sort(C&: Nodes);
514 EXPECT_EQ(3u, Nodes.size());
515 EXPECT_EQ("a1", Nodes[0]);
516 EXPECT_EQ("a2", Nodes[1]);
517 EXPECT_EQ("a3", Nodes[2]);
518 Nodes.clear();
519
520 EXPECT_EQ(RC.end(), J);
521}
522
523TEST(LazyCallGraphTest, MultiArmSCC) {
524 LLVMContext Context;
525 // Two interlocking cycles. The really useful thing about this SCC is that it
526 // will require Tarjan's DFS to backtrack and finish processing all of the
527 // children of each node in the SCC. Since this involves call edges, both
528 // Tarjan implementations will have to successfully navigate the structure.
529 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: "define void @f1() {\n"
530 "entry:\n"
531 " call void @f2()\n"
532 " call void @f4()\n"
533 " ret void\n"
534 "}\n"
535 "define void @f2() {\n"
536 "entry:\n"
537 " call void @f3()\n"
538 " ret void\n"
539 "}\n"
540 "define void @f3() {\n"
541 "entry:\n"
542 " call void @f1()\n"
543 " ret void\n"
544 "}\n"
545 "define void @f4() {\n"
546 "entry:\n"
547 " call void @f5()\n"
548 " ret void\n"
549 "}\n"
550 "define void @f5() {\n"
551 "entry:\n"
552 " call void @f1()\n"
553 " ret void\n"
554 "}\n");
555 LazyCallGraph CG = buildCG(M&: *M);
556
557 // Force the graph to be fully expanded.
558 CG.buildRefSCCs();
559 auto I = CG.postorder_ref_scc_begin();
560 LazyCallGraph::RefSCC &RC = *I++;
561 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
562
563 LazyCallGraph::Node &N1 = *CG.lookup(F: lookupFunction(M&: *M, Name: "f1"));
564 LazyCallGraph::Node &N2 = *CG.lookup(F: lookupFunction(M&: *M, Name: "f2"));
565 LazyCallGraph::Node &N3 = *CG.lookup(F: lookupFunction(M&: *M, Name: "f3"));
566 LazyCallGraph::Node &N4 = *CG.lookup(F: lookupFunction(M&: *M, Name: "f4"));
567 LazyCallGraph::Node &N5 = *CG.lookup(F: lookupFunction(M&: *M, Name: "f4"));
568 EXPECT_EQ(&RC, CG.lookupRefSCC(N1));
569 EXPECT_EQ(&RC, CG.lookupRefSCC(N2));
570 EXPECT_EQ(&RC, CG.lookupRefSCC(N3));
571 EXPECT_EQ(&RC, CG.lookupRefSCC(N4));
572 EXPECT_EQ(&RC, CG.lookupRefSCC(N5));
573
574 ASSERT_EQ(1, RC.size());
575
576 LazyCallGraph::SCC &C = *RC.begin();
577 EXPECT_EQ(&C, CG.lookupSCC(N1));
578 EXPECT_EQ(&C, CG.lookupSCC(N2));
579 EXPECT_EQ(&C, CG.lookupSCC(N3));
580 EXPECT_EQ(&C, CG.lookupSCC(N4));
581 EXPECT_EQ(&C, CG.lookupSCC(N5));
582}
583
584TEST(LazyCallGraphTest, OutgoingEdgeMutation) {
585 LLVMContext Context;
586 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: "define void @a() {\n"
587 "entry:\n"
588 " call void @b()\n"
589 " call void @c()\n"
590 " ret void\n"
591 "}\n"
592 "define void @b() {\n"
593 "entry:\n"
594 " call void @d()\n"
595 " ret void\n"
596 "}\n"
597 "define void @c() {\n"
598 "entry:\n"
599 " call void @d()\n"
600 " ret void\n"
601 "}\n"
602 "define void @d() {\n"
603 "entry:\n"
604 " ret void\n"
605 "}\n");
606 LazyCallGraph CG = buildCG(M&: *M);
607
608 // Force the graph to be fully expanded.
609 CG.buildRefSCCs();
610 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
611 dbgs() << "Formed RefSCC: " << RC << "\n";
612
613 LazyCallGraph::Node &A = *CG.lookup(F: lookupFunction(M&: *M, Name: "a"));
614 LazyCallGraph::Node &B = *CG.lookup(F: lookupFunction(M&: *M, Name: "b"));
615 LazyCallGraph::Node &C = *CG.lookup(F: lookupFunction(M&: *M, Name: "c"));
616 LazyCallGraph::Node &D = *CG.lookup(F: lookupFunction(M&: *M, Name: "d"));
617 LazyCallGraph::SCC &AC = *CG.lookupSCC(N&: A);
618 LazyCallGraph::SCC &BC = *CG.lookupSCC(N&: B);
619 LazyCallGraph::SCC &CC = *CG.lookupSCC(N&: C);
620 LazyCallGraph::SCC &DC = *CG.lookupSCC(N&: D);
621 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(N&: A);
622 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(N&: B);
623 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(N&: C);
624 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(N&: D);
625 EXPECT_TRUE(ARC.isParentOf(BRC));
626 EXPECT_TRUE(AC.isParentOf(BC));
627 EXPECT_TRUE(ARC.isParentOf(CRC));
628 EXPECT_TRUE(AC.isParentOf(CC));
629 EXPECT_FALSE(ARC.isParentOf(DRC));
630 EXPECT_FALSE(AC.isParentOf(DC));
631 EXPECT_TRUE(ARC.isAncestorOf(DRC));
632 EXPECT_TRUE(AC.isAncestorOf(DC));
633 EXPECT_FALSE(DRC.isChildOf(ARC));
634 EXPECT_FALSE(DC.isChildOf(AC));
635 EXPECT_TRUE(DRC.isDescendantOf(ARC));
636 EXPECT_TRUE(DC.isDescendantOf(AC));
637 EXPECT_TRUE(DRC.isChildOf(BRC));
638 EXPECT_TRUE(DC.isChildOf(BC));
639 EXPECT_TRUE(DRC.isChildOf(CRC));
640 EXPECT_TRUE(DC.isChildOf(CC));
641
642 EXPECT_EQ(2, std::distance(A->begin(), A->end()));
643 ARC.insertOutgoingEdge(SourceN&: A, TargetN&: D, EK: LazyCallGraph::Edge::Call);
644 EXPECT_EQ(3, std::distance(A->begin(), A->end()));
645 const LazyCallGraph::Edge &NewE = (*A)[D];
646 EXPECT_TRUE(NewE);
647 EXPECT_TRUE(NewE.isCall());
648 EXPECT_EQ(&D, &NewE.getNode());
649
650 // Only the parent and child tests sholud have changed. The rest of the graph
651 // remains the same.
652 EXPECT_TRUE(ARC.isParentOf(DRC));
653 EXPECT_TRUE(AC.isParentOf(DC));
654 EXPECT_TRUE(ARC.isAncestorOf(DRC));
655 EXPECT_TRUE(AC.isAncestorOf(DC));
656 EXPECT_TRUE(DRC.isChildOf(ARC));
657 EXPECT_TRUE(DC.isChildOf(AC));
658 EXPECT_TRUE(DRC.isDescendantOf(ARC));
659 EXPECT_TRUE(DC.isDescendantOf(AC));
660 EXPECT_EQ(&AC, CG.lookupSCC(A));
661 EXPECT_EQ(&BC, CG.lookupSCC(B));
662 EXPECT_EQ(&CC, CG.lookupSCC(C));
663 EXPECT_EQ(&DC, CG.lookupSCC(D));
664 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
665 EXPECT_EQ(&BRC, CG.lookupRefSCC(B));
666 EXPECT_EQ(&CRC, CG.lookupRefSCC(C));
667 EXPECT_EQ(&DRC, CG.lookupRefSCC(D));
668
669 ARC.switchOutgoingEdgeToRef(SourceN&: A, TargetN&: D);
670 EXPECT_FALSE(NewE.isCall());
671
672 // Verify the reference graph remains the same but the SCC graph is updated.
673 EXPECT_TRUE(ARC.isParentOf(DRC));
674 EXPECT_FALSE(AC.isParentOf(DC));
675 EXPECT_TRUE(ARC.isAncestorOf(DRC));
676 EXPECT_TRUE(AC.isAncestorOf(DC));
677 EXPECT_TRUE(DRC.isChildOf(ARC));
678 EXPECT_FALSE(DC.isChildOf(AC));
679 EXPECT_TRUE(DRC.isDescendantOf(ARC));
680 EXPECT_TRUE(DC.isDescendantOf(AC));
681 EXPECT_EQ(&AC, CG.lookupSCC(A));
682 EXPECT_EQ(&BC, CG.lookupSCC(B));
683 EXPECT_EQ(&CC, CG.lookupSCC(C));
684 EXPECT_EQ(&DC, CG.lookupSCC(D));
685 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
686 EXPECT_EQ(&BRC, CG.lookupRefSCC(B));
687 EXPECT_EQ(&CRC, CG.lookupRefSCC(C));
688 EXPECT_EQ(&DRC, CG.lookupRefSCC(D));
689
690 ARC.switchOutgoingEdgeToCall(SourceN&: A, TargetN&: D);
691 EXPECT_TRUE(NewE.isCall());
692
693 // Verify the reference graph remains the same but the SCC graph is updated.
694 EXPECT_TRUE(ARC.isParentOf(DRC));
695 EXPECT_TRUE(AC.isParentOf(DC));
696 EXPECT_TRUE(ARC.isAncestorOf(DRC));
697 EXPECT_TRUE(AC.isAncestorOf(DC));
698 EXPECT_TRUE(DRC.isChildOf(ARC));
699 EXPECT_TRUE(DC.isChildOf(AC));
700 EXPECT_TRUE(DRC.isDescendantOf(ARC));
701 EXPECT_TRUE(DC.isDescendantOf(AC));
702 EXPECT_EQ(&AC, CG.lookupSCC(A));
703 EXPECT_EQ(&BC, CG.lookupSCC(B));
704 EXPECT_EQ(&CC, CG.lookupSCC(C));
705 EXPECT_EQ(&DC, CG.lookupSCC(D));
706 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
707 EXPECT_EQ(&BRC, CG.lookupRefSCC(B));
708 EXPECT_EQ(&CRC, CG.lookupRefSCC(C));
709 EXPECT_EQ(&DRC, CG.lookupRefSCC(D));
710
711 ARC.removeOutgoingEdge(SourceN&: A, TargetN&: D);
712 EXPECT_EQ(2, std::distance(A->begin(), A->end()));
713
714 // Now the parent and child tests fail again but the rest remains the same.
715 EXPECT_FALSE(ARC.isParentOf(DRC));
716 EXPECT_FALSE(AC.isParentOf(DC));
717 EXPECT_TRUE(ARC.isAncestorOf(DRC));
718 EXPECT_TRUE(AC.isAncestorOf(DC));
719 EXPECT_FALSE(DRC.isChildOf(ARC));
720 EXPECT_FALSE(DC.isChildOf(AC));
721 EXPECT_TRUE(DRC.isDescendantOf(ARC));
722 EXPECT_TRUE(DC.isDescendantOf(AC));
723 EXPECT_EQ(&AC, CG.lookupSCC(A));
724 EXPECT_EQ(&BC, CG.lookupSCC(B));
725 EXPECT_EQ(&CC, CG.lookupSCC(C));
726 EXPECT_EQ(&DC, CG.lookupSCC(D));
727 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
728 EXPECT_EQ(&BRC, CG.lookupRefSCC(B));
729 EXPECT_EQ(&CRC, CG.lookupRefSCC(C));
730 EXPECT_EQ(&DRC, CG.lookupRefSCC(D));
731}
732
733TEST(LazyCallGraphTest, IncomingEdgeInsertion) {
734 LLVMContext Context;
735 // We want to ensure we can add edges even across complex diamond graphs, so
736 // we use the diamond of triangles graph defined above. The ascii diagram is
737 // repeated here for easy reference.
738 //
739 // d1 |
740 // / \ |
741 // d3--d2 |
742 // / \ |
743 // b1 c1 |
744 // / \ / \ |
745 // b3--b2 c3--c2 |
746 // \ / |
747 // a1 |
748 // / \ |
749 // a3--a2 |
750 //
751 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: DiamondOfTriangles);
752 LazyCallGraph CG = buildCG(M&: *M);
753
754 // Force the graph to be fully expanded.
755 CG.buildRefSCCs();
756 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
757 dbgs() << "Formed RefSCC: " << RC << "\n";
758
759 LazyCallGraph::Node &A1 = *CG.lookup(F: lookupFunction(M&: *M, Name: "a1"));
760 LazyCallGraph::Node &A2 = *CG.lookup(F: lookupFunction(M&: *M, Name: "a2"));
761 LazyCallGraph::Node &A3 = *CG.lookup(F: lookupFunction(M&: *M, Name: "a3"));
762 LazyCallGraph::Node &B1 = *CG.lookup(F: lookupFunction(M&: *M, Name: "b1"));
763 LazyCallGraph::Node &B2 = *CG.lookup(F: lookupFunction(M&: *M, Name: "b2"));
764 LazyCallGraph::Node &B3 = *CG.lookup(F: lookupFunction(M&: *M, Name: "b3"));
765 LazyCallGraph::Node &C1 = *CG.lookup(F: lookupFunction(M&: *M, Name: "c1"));
766 LazyCallGraph::Node &C2 = *CG.lookup(F: lookupFunction(M&: *M, Name: "c2"));
767 LazyCallGraph::Node &C3 = *CG.lookup(F: lookupFunction(M&: *M, Name: "c3"));
768 LazyCallGraph::Node &D1 = *CG.lookup(F: lookupFunction(M&: *M, Name: "d1"));
769 LazyCallGraph::Node &D2 = *CG.lookup(F: lookupFunction(M&: *M, Name: "d2"));
770 LazyCallGraph::Node &D3 = *CG.lookup(F: lookupFunction(M&: *M, Name: "d3"));
771 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(N&: A1);
772 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(N&: B1);
773 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(N&: C1);
774 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(N&: D1);
775 ASSERT_EQ(&ARC, CG.lookupRefSCC(A2));
776 ASSERT_EQ(&ARC, CG.lookupRefSCC(A3));
777 ASSERT_EQ(&BRC, CG.lookupRefSCC(B2));
778 ASSERT_EQ(&BRC, CG.lookupRefSCC(B3));
779 ASSERT_EQ(&CRC, CG.lookupRefSCC(C2));
780 ASSERT_EQ(&CRC, CG.lookupRefSCC(C3));
781 ASSERT_EQ(&DRC, CG.lookupRefSCC(D2));
782 ASSERT_EQ(&DRC, CG.lookupRefSCC(D3));
783 ASSERT_EQ(1, std::distance(D2->begin(), D2->end()));
784
785 // Add an edge to make the graph:
786 //
787 // d1 |
788 // / \ |
789 // d3--d2---. |
790 // / \ | |
791 // b1 c1 | |
792 // / \ / \ / |
793 // b3--b2 c3--c2 |
794 // \ / |
795 // a1 |
796 // / \ |
797 // a3--a2 |
798 auto MergedRCs = CRC.insertIncomingRefEdge(SourceN&: D2, TargetN&: C2);
799 // Make sure we connected the nodes.
800 for (LazyCallGraph::Edge E : *D2) {
801 if (&E.getNode() == &D3)
802 continue;
803 EXPECT_EQ(&C2, &E.getNode());
804 }
805 // And marked the D ref-SCC as no longer valid.
806 EXPECT_EQ(1u, MergedRCs.size());
807 EXPECT_EQ(&DRC, MergedRCs[0]);
808
809 // Make sure we have the correct nodes in the SCC sets.
810 EXPECT_EQ(&ARC, CG.lookupRefSCC(A1));
811 EXPECT_EQ(&ARC, CG.lookupRefSCC(A2));
812 EXPECT_EQ(&ARC, CG.lookupRefSCC(A3));
813 EXPECT_EQ(&BRC, CG.lookupRefSCC(B1));
814 EXPECT_EQ(&BRC, CG.lookupRefSCC(B2));
815 EXPECT_EQ(&BRC, CG.lookupRefSCC(B3));
816 EXPECT_EQ(&CRC, CG.lookupRefSCC(C1));
817 EXPECT_EQ(&CRC, CG.lookupRefSCC(C2));
818 EXPECT_EQ(&CRC, CG.lookupRefSCC(C3));
819 EXPECT_EQ(&CRC, CG.lookupRefSCC(D1));
820 EXPECT_EQ(&CRC, CG.lookupRefSCC(D2));
821 EXPECT_EQ(&CRC, CG.lookupRefSCC(D3));
822
823 // And that ancestry tests have been updated.
824 EXPECT_TRUE(ARC.isParentOf(CRC));
825 EXPECT_TRUE(BRC.isParentOf(CRC));
826
827 // And verify the post-order walk reflects the updated structure.
828 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
829 ASSERT_NE(I, E);
830 EXPECT_EQ(&CRC, &*I) << "Actual RefSCC: " << *I;
831 ASSERT_NE(++I, E);
832 EXPECT_EQ(&BRC, &*I) << "Actual RefSCC: " << *I;
833 ASSERT_NE(++I, E);
834 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
835 EXPECT_EQ(++I, E);
836}
837
838TEST(LazyCallGraphTest, IncomingEdgeInsertionRefGraph) {
839 LLVMContext Context;
840 // Another variation of the above test but with all the edges switched to
841 // references rather than calls.
842 std::unique_ptr<Module> M =
843 parseAssembly(Context, Assembly: DiamondOfTrianglesRefGraph);
844 LazyCallGraph CG = buildCG(M&: *M);
845
846 // Force the graph to be fully expanded.
847 CG.buildRefSCCs();
848 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
849 dbgs() << "Formed RefSCC: " << RC << "\n";
850
851 LazyCallGraph::Node &A1 = *CG.lookup(F: lookupFunction(M&: *M, Name: "a1"));
852 LazyCallGraph::Node &A2 = *CG.lookup(F: lookupFunction(M&: *M, Name: "a2"));
853 LazyCallGraph::Node &A3 = *CG.lookup(F: lookupFunction(M&: *M, Name: "a3"));
854 LazyCallGraph::Node &B1 = *CG.lookup(F: lookupFunction(M&: *M, Name: "b1"));
855 LazyCallGraph::Node &B2 = *CG.lookup(F: lookupFunction(M&: *M, Name: "b2"));
856 LazyCallGraph::Node &B3 = *CG.lookup(F: lookupFunction(M&: *M, Name: "b3"));
857 LazyCallGraph::Node &C1 = *CG.lookup(F: lookupFunction(M&: *M, Name: "c1"));
858 LazyCallGraph::Node &C2 = *CG.lookup(F: lookupFunction(M&: *M, Name: "c2"));
859 LazyCallGraph::Node &C3 = *CG.lookup(F: lookupFunction(M&: *M, Name: "c3"));
860 LazyCallGraph::Node &D1 = *CG.lookup(F: lookupFunction(M&: *M, Name: "d1"));
861 LazyCallGraph::Node &D2 = *CG.lookup(F: lookupFunction(M&: *M, Name: "d2"));
862 LazyCallGraph::Node &D3 = *CG.lookup(F: lookupFunction(M&: *M, Name: "d3"));
863 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(N&: A1);
864 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(N&: B1);
865 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(N&: C1);
866 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(N&: D1);
867 ASSERT_EQ(&ARC, CG.lookupRefSCC(A2));
868 ASSERT_EQ(&ARC, CG.lookupRefSCC(A3));
869 ASSERT_EQ(&BRC, CG.lookupRefSCC(B2));
870 ASSERT_EQ(&BRC, CG.lookupRefSCC(B3));
871 ASSERT_EQ(&CRC, CG.lookupRefSCC(C2));
872 ASSERT_EQ(&CRC, CG.lookupRefSCC(C3));
873 ASSERT_EQ(&DRC, CG.lookupRefSCC(D2));
874 ASSERT_EQ(&DRC, CG.lookupRefSCC(D3));
875 ASSERT_EQ(1, std::distance(D2->begin(), D2->end()));
876
877 // Add an edge to make the graph:
878 //
879 // d1 |
880 // / \ |
881 // d3--d2---. |
882 // / \ | |
883 // b1 c1 | |
884 // / \ / \ / |
885 // b3--b2 c3--c2 |
886 // \ / |
887 // a1 |
888 // / \ |
889 // a3--a2 |
890 auto MergedRCs = CRC.insertIncomingRefEdge(SourceN&: D2, TargetN&: C2);
891 // Make sure we connected the nodes.
892 for (LazyCallGraph::Edge E : *D2) {
893 if (&E.getNode() == &D3)
894 continue;
895 EXPECT_EQ(&C2, &E.getNode());
896 }
897 // And marked the D ref-SCC as no longer valid.
898 EXPECT_EQ(1u, MergedRCs.size());
899 EXPECT_EQ(&DRC, MergedRCs[0]);
900
901 // Make sure we have the correct nodes in the SCC sets.
902 EXPECT_EQ(&ARC, CG.lookupRefSCC(A1));
903 EXPECT_EQ(&ARC, CG.lookupRefSCC(A2));
904 EXPECT_EQ(&ARC, CG.lookupRefSCC(A3));
905 EXPECT_EQ(&BRC, CG.lookupRefSCC(B1));
906 EXPECT_EQ(&BRC, CG.lookupRefSCC(B2));
907 EXPECT_EQ(&BRC, CG.lookupRefSCC(B3));
908 EXPECT_EQ(&CRC, CG.lookupRefSCC(C1));
909 EXPECT_EQ(&CRC, CG.lookupRefSCC(C2));
910 EXPECT_EQ(&CRC, CG.lookupRefSCC(C3));
911 EXPECT_EQ(&CRC, CG.lookupRefSCC(D1));
912 EXPECT_EQ(&CRC, CG.lookupRefSCC(D2));
913 EXPECT_EQ(&CRC, CG.lookupRefSCC(D3));
914
915 // And that ancestry tests have been updated.
916 EXPECT_TRUE(ARC.isParentOf(CRC));
917 EXPECT_TRUE(BRC.isParentOf(CRC));
918
919 // And verify the post-order walk reflects the updated structure.
920 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
921 ASSERT_NE(I, E);
922 EXPECT_EQ(&CRC, &*I) << "Actual RefSCC: " << *I;
923 ASSERT_NE(++I, E);
924 EXPECT_EQ(&BRC, &*I) << "Actual RefSCC: " << *I;
925 ASSERT_NE(++I, E);
926 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
927 EXPECT_EQ(++I, E);
928}
929
930TEST(LazyCallGraphTest, IncomingEdgeInsertionLargeCallCycle) {
931 LLVMContext Context;
932 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: "define void @a() {\n"
933 "entry:\n"
934 " call void @b()\n"
935 " ret void\n"
936 "}\n"
937 "define void @b() {\n"
938 "entry:\n"
939 " call void @c()\n"
940 " ret void\n"
941 "}\n"
942 "define void @c() {\n"
943 "entry:\n"
944 " call void @d()\n"
945 " ret void\n"
946 "}\n"
947 "define void @d() {\n"
948 "entry:\n"
949 " ret void\n"
950 "}\n");
951 LazyCallGraph CG = buildCG(M&: *M);
952
953 // Force the graph to be fully expanded.
954 CG.buildRefSCCs();
955 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
956 dbgs() << "Formed RefSCC: " << RC << "\n";
957
958 LazyCallGraph::Node &A = *CG.lookup(F: lookupFunction(M&: *M, Name: "a"));
959 LazyCallGraph::Node &B = *CG.lookup(F: lookupFunction(M&: *M, Name: "b"));
960 LazyCallGraph::Node &C = *CG.lookup(F: lookupFunction(M&: *M, Name: "c"));
961 LazyCallGraph::Node &D = *CG.lookup(F: lookupFunction(M&: *M, Name: "d"));
962 LazyCallGraph::SCC &AC = *CG.lookupSCC(N&: A);
963 LazyCallGraph::SCC &BC = *CG.lookupSCC(N&: B);
964 LazyCallGraph::SCC &CC = *CG.lookupSCC(N&: C);
965 LazyCallGraph::SCC &DC = *CG.lookupSCC(N&: D);
966 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(N&: A);
967 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(N&: B);
968 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(N&: C);
969 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(N&: D);
970
971 // Connect the top to the bottom forming a large RefSCC made up mostly of calls.
972 auto MergedRCs = ARC.insertIncomingRefEdge(SourceN&: D, TargetN&: A);
973 // Make sure we connected the nodes.
974 EXPECT_NE(D->begin(), D->end());
975 EXPECT_EQ(&A, &D->begin()->getNode());
976
977 // Check that we have the dead RCs, but ignore the order.
978 EXPECT_EQ(3u, MergedRCs.size());
979 EXPECT_NE(find(MergedRCs, &BRC), MergedRCs.end());
980 EXPECT_NE(find(MergedRCs, &CRC), MergedRCs.end());
981 EXPECT_NE(find(MergedRCs, &DRC), MergedRCs.end());
982
983 // Make sure the nodes point to the right place now.
984 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
985 EXPECT_EQ(&ARC, CG.lookupRefSCC(B));
986 EXPECT_EQ(&ARC, CG.lookupRefSCC(C));
987 EXPECT_EQ(&ARC, CG.lookupRefSCC(D));
988
989 // Check that the SCCs are in postorder.
990 EXPECT_EQ(4, ARC.size());
991 EXPECT_EQ(&DC, &ARC[0]);
992 EXPECT_EQ(&CC, &ARC[1]);
993 EXPECT_EQ(&BC, &ARC[2]);
994 EXPECT_EQ(&AC, &ARC[3]);
995
996 // And verify the post-order walk reflects the updated structure.
997 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
998 ASSERT_NE(I, E);
999 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
1000 EXPECT_EQ(++I, E);
1001}
1002
1003TEST(LazyCallGraphTest, IncomingEdgeInsertionLargeRefCycle) {
1004 LLVMContext Context;
1005 std::unique_ptr<Module> M =
1006 parseAssembly(Context, Assembly: "define void @a() {\n"
1007 "entry:\n"
1008 " %p = alloca void ()*\n"
1009 " store void ()* @b, void ()** %p\n"
1010 " ret void\n"
1011 "}\n"
1012 "define void @b() {\n"
1013 "entry:\n"
1014 " %p = alloca void ()*\n"
1015 " store void ()* @c, void ()** %p\n"
1016 " ret void\n"
1017 "}\n"
1018 "define void @c() {\n"
1019 "entry:\n"
1020 " %p = alloca void ()*\n"
1021 " store void ()* @d, void ()** %p\n"
1022 " ret void\n"
1023 "}\n"
1024 "define void @d() {\n"
1025 "entry:\n"
1026 " ret void\n"
1027 "}\n");
1028 LazyCallGraph CG = buildCG(M&: *M);
1029
1030 // Force the graph to be fully expanded.
1031 CG.buildRefSCCs();
1032 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
1033 dbgs() << "Formed RefSCC: " << RC << "\n";
1034
1035 LazyCallGraph::Node &A = *CG.lookup(F: lookupFunction(M&: *M, Name: "a"));
1036 LazyCallGraph::Node &B = *CG.lookup(F: lookupFunction(M&: *M, Name: "b"));
1037 LazyCallGraph::Node &C = *CG.lookup(F: lookupFunction(M&: *M, Name: "c"));
1038 LazyCallGraph::Node &D = *CG.lookup(F: lookupFunction(M&: *M, Name: "d"));
1039 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(N&: A);
1040 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(N&: B);
1041 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(N&: C);
1042 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(N&: D);
1043
1044 // Connect the top to the bottom forming a large RefSCC made up just of
1045 // references.
1046 auto MergedRCs = ARC.insertIncomingRefEdge(SourceN&: D, TargetN&: A);
1047 // Make sure we connected the nodes.
1048 EXPECT_NE(D->begin(), D->end());
1049 EXPECT_EQ(&A, &D->begin()->getNode());
1050
1051 // Check that we have the dead RCs, but ignore the order.
1052 EXPECT_EQ(3u, MergedRCs.size());
1053 EXPECT_NE(find(MergedRCs, &BRC), MergedRCs.end());
1054 EXPECT_NE(find(MergedRCs, &CRC), MergedRCs.end());
1055 EXPECT_NE(find(MergedRCs, &DRC), MergedRCs.end());
1056
1057 // Make sure the nodes point to the right place now.
1058 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
1059 EXPECT_EQ(&ARC, CG.lookupRefSCC(B));
1060 EXPECT_EQ(&ARC, CG.lookupRefSCC(C));
1061 EXPECT_EQ(&ARC, CG.lookupRefSCC(D));
1062
1063 // And verify the post-order walk reflects the updated structure.
1064 auto I = CG.postorder_ref_scc_begin(), End = CG.postorder_ref_scc_end();
1065 ASSERT_NE(I, End);
1066 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
1067 EXPECT_EQ(++I, End);
1068}
1069
1070TEST(LazyCallGraphTest, InlineAndDeleteFunction) {
1071 LLVMContext Context;
1072 // We want to ensure we can delete nodes from relatively complex graphs and
1073 // so use the diamond of triangles graph defined above.
1074 //
1075 // The ascii diagram is repeated here for easy reference.
1076 //
1077 // d1 |
1078 // / \ |
1079 // d3--d2 |
1080 // / \ |
1081 // b1 c1 |
1082 // / \ / \ |
1083 // b3--b2 c3--c2 |
1084 // \ / |
1085 // a1 |
1086 // / \ |
1087 // a3--a2 |
1088 //
1089 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: DiamondOfTriangles);
1090 LazyCallGraph CG = buildCG(M&: *M);
1091
1092 // Force the graph to be fully expanded.
1093 CG.buildRefSCCs();
1094 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
1095 dbgs() << "Formed RefSCC: " << RC << "\n";
1096
1097 LazyCallGraph::Node &A1 = *CG.lookup(F: lookupFunction(M&: *M, Name: "a1"));
1098 LazyCallGraph::Node &A2 = *CG.lookup(F: lookupFunction(M&: *M, Name: "a2"));
1099 LazyCallGraph::Node &A3 = *CG.lookup(F: lookupFunction(M&: *M, Name: "a3"));
1100 LazyCallGraph::Node &B1 = *CG.lookup(F: lookupFunction(M&: *M, Name: "b1"));
1101 LazyCallGraph::Node &B2 = *CG.lookup(F: lookupFunction(M&: *M, Name: "b2"));
1102 LazyCallGraph::Node &B3 = *CG.lookup(F: lookupFunction(M&: *M, Name: "b3"));
1103 LazyCallGraph::Node &C1 = *CG.lookup(F: lookupFunction(M&: *M, Name: "c1"));
1104 LazyCallGraph::Node &C2 = *CG.lookup(F: lookupFunction(M&: *M, Name: "c2"));
1105 LazyCallGraph::Node &C3 = *CG.lookup(F: lookupFunction(M&: *M, Name: "c3"));
1106 LazyCallGraph::Node &D1 = *CG.lookup(F: lookupFunction(M&: *M, Name: "d1"));
1107 LazyCallGraph::Node &D2 = *CG.lookup(F: lookupFunction(M&: *M, Name: "d2"));
1108 LazyCallGraph::Node &D3 = *CG.lookup(F: lookupFunction(M&: *M, Name: "d3"));
1109 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(N&: A1);
1110 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(N&: B1);
1111 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(N&: C1);
1112 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(N&: D1);
1113 ASSERT_EQ(&ARC, CG.lookupRefSCC(A2));
1114 ASSERT_EQ(&ARC, CG.lookupRefSCC(A3));
1115 ASSERT_EQ(&BRC, CG.lookupRefSCC(B2));
1116 ASSERT_EQ(&BRC, CG.lookupRefSCC(B3));
1117 ASSERT_EQ(&CRC, CG.lookupRefSCC(C2));
1118 ASSERT_EQ(&CRC, CG.lookupRefSCC(C3));
1119 ASSERT_EQ(&DRC, CG.lookupRefSCC(D2));
1120 ASSERT_EQ(&DRC, CG.lookupRefSCC(D3));
1121 ASSERT_EQ(1, std::distance(D2->begin(), D2->end()));
1122
1123 // Delete d2 from the graph, as if it had been inlined.
1124 //
1125 // d1 |
1126 // / / |
1127 // d3--. |
1128 // / \ |
1129 // b1 c1 |
1130 // / \ / \ |
1131 // b3--b2 c3--c2 |
1132 // \ / |
1133 // a1 |
1134 // / \ |
1135 // a3--a2 |
1136
1137 Function &D2F = D2.getFunction();
1138 CallInst *C1Call = nullptr, *D1Call = nullptr;
1139 for (User *U : D2F.users()) {
1140 CallInst *CI = dyn_cast<CallInst>(Val: U);
1141 ASSERT_TRUE(CI) << "Expected a call: " << *U;
1142 if (CI->getParent()->getParent() == &C1.getFunction()) {
1143 ASSERT_EQ(nullptr, C1Call) << "Found too many C1 calls: " << *CI;
1144 C1Call = CI;
1145 } else if (CI->getParent()->getParent() == &D1.getFunction()) {
1146 ASSERT_EQ(nullptr, D1Call) << "Found too many D1 calls: " << *CI;
1147 D1Call = CI;
1148 } else {
1149 FAIL() << "Found an unexpected call instruction: " << *CI;
1150 }
1151 }
1152 ASSERT_NE(C1Call, nullptr);
1153 ASSERT_NE(D1Call, nullptr);
1154 ASSERT_EQ(&D2F, C1Call->getCalledFunction());
1155 ASSERT_EQ(&D2F, D1Call->getCalledFunction());
1156 C1Call->setCalledFunction(&D3.getFunction());
1157 D1Call->setCalledFunction(&D3.getFunction());
1158 ASSERT_EQ(0u, D2F.getNumUses());
1159
1160 // Insert new edges first.
1161 CRC.insertTrivialCallEdge(SourceN&: C1, TargetN&: D3);
1162 DRC.insertTrivialCallEdge(SourceN&: D1, TargetN&: D3);
1163
1164 // Then remove the old ones.
1165 LazyCallGraph::SCC &DC = *CG.lookupSCC(N&: D2);
1166 auto NewCs = DRC.switchInternalEdgeToRef(SourceN&: D1, TargetN&: D2);
1167 EXPECT_EQ(&DC, CG.lookupSCC(D2));
1168 EXPECT_EQ(NewCs.end(), std::next(NewCs.begin()));
1169 LazyCallGraph::SCC &NewDC = *NewCs.begin();
1170 EXPECT_EQ(&NewDC, CG.lookupSCC(D1));
1171 EXPECT_EQ(&NewDC, CG.lookupSCC(D3));
1172 auto NewRCs = DRC.removeInternalRefEdge(SourceN&: D1, TargetNs: {&D2});
1173 ASSERT_EQ(2u, NewRCs.size());
1174 LazyCallGraph::RefSCC &NewDRC = *NewRCs[0];
1175 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D1));
1176 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D3));
1177 LazyCallGraph::RefSCC &D2RC = *NewRCs[1];
1178 EXPECT_EQ(&D2RC, CG.lookupRefSCC(D2));
1179 EXPECT_FALSE(NewDRC.isParentOf(D2RC));
1180 EXPECT_TRUE(CRC.isParentOf(D2RC));
1181 EXPECT_TRUE(CRC.isParentOf(NewDRC));
1182 EXPECT_TRUE(D2RC.isParentOf(NewDRC));
1183 CRC.removeOutgoingEdge(SourceN&: C1, TargetN&: D2);
1184 EXPECT_FALSE(CRC.isParentOf(D2RC));
1185 EXPECT_TRUE(CRC.isParentOf(NewDRC));
1186 EXPECT_TRUE(D2RC.isParentOf(NewDRC));
1187
1188 // Now that we've updated the call graph, D2 is dead, so remove it.
1189 CG.removeDeadFunction(F&: D2F);
1190
1191 // Check that the graph still looks the same.
1192 EXPECT_EQ(&ARC, CG.lookupRefSCC(A1));
1193 EXPECT_EQ(&ARC, CG.lookupRefSCC(A2));
1194 EXPECT_EQ(&ARC, CG.lookupRefSCC(A3));
1195 EXPECT_EQ(&BRC, CG.lookupRefSCC(B1));
1196 EXPECT_EQ(&BRC, CG.lookupRefSCC(B2));
1197 EXPECT_EQ(&BRC, CG.lookupRefSCC(B3));
1198 EXPECT_EQ(&CRC, CG.lookupRefSCC(C1));
1199 EXPECT_EQ(&CRC, CG.lookupRefSCC(C2));
1200 EXPECT_EQ(&CRC, CG.lookupRefSCC(C3));
1201 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D1));
1202 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D3));
1203 EXPECT_TRUE(CRC.isParentOf(NewDRC));
1204
1205 // Verify the post-order walk hasn't changed.
1206 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
1207 ASSERT_NE(I, E);
1208 EXPECT_EQ(&NewDRC, &*I) << "Actual RefSCC: " << *I;
1209 ASSERT_NE(++I, E);
1210 EXPECT_EQ(&BRC, &*I) << "Actual RefSCC: " << *I;
1211 ASSERT_NE(++I, E);
1212 EXPECT_EQ(&CRC, &*I) << "Actual RefSCC: " << *I;
1213 ASSERT_NE(++I, E);
1214 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
1215 EXPECT_EQ(++I, E);
1216}
1217
1218TEST(LazyCallGraphTest, InternalEdgeMutation) {
1219 LLVMContext Context;
1220 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: "define void @a() {\n"
1221 "entry:\n"
1222 " call void @b()\n"
1223 " ret void\n"
1224 "}\n"
1225 "define void @b() {\n"
1226 "entry:\n"
1227 " call void @c()\n"
1228 " ret void\n"
1229 "}\n"
1230 "define void @c() {\n"
1231 "entry:\n"
1232 " call void @a()\n"
1233 " ret void\n"
1234 "}\n");
1235 LazyCallGraph CG = buildCG(M&: *M);
1236
1237 // Force the graph to be fully expanded.
1238 CG.buildRefSCCs();
1239 auto I = CG.postorder_ref_scc_begin();
1240 LazyCallGraph::RefSCC &RC = *I++;
1241 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1242
1243 LazyCallGraph::Node &A = *CG.lookup(F: lookupFunction(M&: *M, Name: "a"));
1244 LazyCallGraph::Node &B = *CG.lookup(F: lookupFunction(M&: *M, Name: "b"));
1245 LazyCallGraph::Node &C = *CG.lookup(F: lookupFunction(M&: *M, Name: "c"));
1246 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1247 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1248 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
1249 EXPECT_EQ(1, RC.size());
1250 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(A));
1251 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(B));
1252 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(C));
1253
1254 // Insert an edge from 'a' to 'c'. Nothing changes about the graph.
1255 RC.insertInternalRefEdge(SourceN&: A, TargetN&: C);
1256 EXPECT_EQ(2, std::distance(A->begin(), A->end()));
1257 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1258 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1259 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
1260 EXPECT_EQ(1, RC.size());
1261 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(A));
1262 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(B));
1263 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(C));
1264
1265 // Switch the call edge from 'b' to 'c' to a ref edge. This will break the
1266 // call cycle and cause us to form more SCCs. The RefSCC will remain the same
1267 // though.
1268 auto NewCs = RC.switchInternalEdgeToRef(SourceN&: B, TargetN&: C);
1269 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1270 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1271 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
1272 auto J = RC.begin();
1273 // The SCCs must be in *post-order* which means successors before
1274 // predecessors. At this point we have call edges from C to A and from A to
1275 // B. The only valid postorder is B, A, C.
1276 EXPECT_EQ(&*J++, CG.lookupSCC(B));
1277 EXPECT_EQ(&*J++, CG.lookupSCC(A));
1278 EXPECT_EQ(&*J++, CG.lookupSCC(C));
1279 EXPECT_EQ(RC.end(), J);
1280 // And the returned range must be the slice of this sequence containing new
1281 // SCCs.
1282 EXPECT_EQ(RC.begin(), NewCs.begin());
1283 EXPECT_EQ(std::prev(RC.end()), NewCs.end());
1284
1285 // Test turning the ref edge from A to C into a call edge. This will form an
1286 // SCC out of A and C. Since we previously had a call edge from C to A, the
1287 // C SCC should be preserved and have A merged into it while the A SCC should
1288 // be invalidated.
1289 LazyCallGraph::SCC &AC = *CG.lookupSCC(N&: A);
1290 LazyCallGraph::SCC &CC = *CG.lookupSCC(N&: C);
1291 EXPECT_TRUE(RC.switchInternalEdgeToCall(A, C, [&](ArrayRef<LazyCallGraph::SCC *> MergedCs) {
1292 ASSERT_EQ(1u, MergedCs.size());
1293 EXPECT_EQ(&AC, MergedCs[0]);
1294 }));
1295 EXPECT_EQ(2, CC.size());
1296 EXPECT_EQ(&CC, CG.lookupSCC(A));
1297 EXPECT_EQ(&CC, CG.lookupSCC(C));
1298 J = RC.begin();
1299 EXPECT_EQ(&*J++, CG.lookupSCC(B));
1300 EXPECT_EQ(&*J++, CG.lookupSCC(C));
1301 EXPECT_EQ(RC.end(), J);
1302}
1303
1304TEST(LazyCallGraphTest, InternalEdgeRemoval) {
1305 LLVMContext Context;
1306 // A nice fully connected (including self-edges) RefSCC.
1307 std::unique_ptr<Module> M = parseAssembly(
1308 Context, Assembly: "define void @a(i8** %ptr) {\n"
1309 "entry:\n"
1310 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1311 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1312 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1313 " ret void\n"
1314 "}\n"
1315 "define void @b(i8** %ptr) {\n"
1316 "entry:\n"
1317 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1318 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1319 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1320 " ret void\n"
1321 "}\n"
1322 "define void @c(i8** %ptr) {\n"
1323 "entry:\n"
1324 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1325 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1326 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1327 " ret void\n"
1328 "}\n");
1329 LazyCallGraph CG = buildCG(M&: *M);
1330
1331 // Force the graph to be fully expanded.
1332 CG.buildRefSCCs();
1333 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
1334 LazyCallGraph::RefSCC &RC = *I;
1335 EXPECT_EQ(E, std::next(I));
1336
1337 LazyCallGraph::Node &A = *CG.lookup(F: lookupFunction(M&: *M, Name: "a"));
1338 LazyCallGraph::Node &B = *CG.lookup(F: lookupFunction(M&: *M, Name: "b"));
1339 LazyCallGraph::Node &C = *CG.lookup(F: lookupFunction(M&: *M, Name: "c"));
1340 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1341 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1342 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
1343
1344 // Remove the edge from b -> a, which should leave the 3 functions still in
1345 // a single connected component because of a -> b -> c -> a.
1346 SmallVector<LazyCallGraph::RefSCC *, 1> NewRCs =
1347 RC.removeInternalRefEdge(SourceN&: B, TargetNs: {&A});
1348 EXPECT_EQ(0u, NewRCs.size());
1349 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1350 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1351 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
1352 auto J = CG.postorder_ref_scc_begin();
1353 EXPECT_EQ(I, J);
1354 EXPECT_EQ(&RC, &*J);
1355 EXPECT_EQ(E, std::next(J));
1356
1357 // Increment I before we actually mutate the structure so that it remains
1358 // a valid iterator.
1359 ++I;
1360
1361 // Remove the edge from c -> a, which should leave 'a' in the original RefSCC
1362 // and form a new RefSCC for 'b' and 'c'.
1363 NewRCs = RC.removeInternalRefEdge(SourceN&: C, TargetNs: {&A});
1364 ASSERT_EQ(2u, NewRCs.size());
1365 LazyCallGraph::RefSCC &BCRC = *NewRCs[0];
1366 LazyCallGraph::RefSCC &ARC = *NewRCs[1];
1367 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
1368 EXPECT_EQ(1, std::distance(ARC.begin(), ARC.end()));
1369 EXPECT_EQ(&BCRC, CG.lookupRefSCC(B));
1370 EXPECT_EQ(&BCRC, CG.lookupRefSCC(C));
1371 J = CG.postorder_ref_scc_begin();
1372 EXPECT_NE(I, J);
1373 EXPECT_EQ(&BCRC, &*J);
1374 ++J;
1375 EXPECT_NE(I, J);
1376 EXPECT_EQ(&ARC, &*J);
1377 ++J;
1378 EXPECT_EQ(I, J);
1379 EXPECT_EQ(E, J);
1380}
1381
1382TEST(LazyCallGraphTest, InternalMultiEdgeRemoval) {
1383 LLVMContext Context;
1384 // A nice fully connected (including self-edges) RefSCC.
1385 std::unique_ptr<Module> M = parseAssembly(
1386 Context, Assembly: "define void @a(i8** %ptr) {\n"
1387 "entry:\n"
1388 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1389 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1390 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1391 " ret void\n"
1392 "}\n"
1393 "define void @b(i8** %ptr) {\n"
1394 "entry:\n"
1395 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1396 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1397 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1398 " ret void\n"
1399 "}\n"
1400 "define void @c(i8** %ptr) {\n"
1401 "entry:\n"
1402 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1403 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1404 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1405 " ret void\n"
1406 "}\n");
1407 LazyCallGraph CG = buildCG(M&: *M);
1408
1409 // Force the graph to be fully expanded.
1410 CG.buildRefSCCs();
1411 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
1412 LazyCallGraph::RefSCC &RC = *I;
1413 EXPECT_EQ(E, std::next(I));
1414
1415 LazyCallGraph::Node &A = *CG.lookup(F: lookupFunction(M&: *M, Name: "a"));
1416 LazyCallGraph::Node &B = *CG.lookup(F: lookupFunction(M&: *M, Name: "b"));
1417 LazyCallGraph::Node &C = *CG.lookup(F: lookupFunction(M&: *M, Name: "c"));
1418 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1419 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1420 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
1421
1422 // Increment I before we actually mutate the structure so that it remains
1423 // a valid iterator.
1424 ++I;
1425
1426 // Remove the edges from b -> a and b -> c, leaving b in its own RefSCC.
1427 SmallVector<LazyCallGraph::RefSCC *, 1> NewRCs =
1428 RC.removeInternalRefEdge(SourceN&: B, TargetNs: {&A, &C});
1429
1430 ASSERT_EQ(2u, NewRCs.size());
1431 LazyCallGraph::RefSCC &BRC = *NewRCs[0];
1432 LazyCallGraph::RefSCC &ACRC = *NewRCs[1];
1433 EXPECT_EQ(&BRC, CG.lookupRefSCC(B));
1434 EXPECT_EQ(1, std::distance(BRC.begin(), BRC.end()));
1435 EXPECT_EQ(&ACRC, CG.lookupRefSCC(A));
1436 EXPECT_EQ(&ACRC, CG.lookupRefSCC(C));
1437 auto J = CG.postorder_ref_scc_begin();
1438 EXPECT_NE(I, J);
1439 EXPECT_EQ(&BRC, &*J);
1440 ++J;
1441 EXPECT_NE(I, J);
1442 EXPECT_EQ(&ACRC, &*J);
1443 ++J;
1444 EXPECT_EQ(I, J);
1445 EXPECT_EQ(E, J);
1446}
1447
1448TEST(LazyCallGraphTest, InternalNoOpEdgeRemoval) {
1449 LLVMContext Context;
1450 // A graph with a single cycle formed both from call and reference edges
1451 // which makes the reference edges trivial to delete. The graph looks like:
1452 //
1453 // Reference edges: a -> b -> c -> a
1454 // Call edges: a -> c -> b -> a
1455 std::unique_ptr<Module> M = parseAssembly(
1456 Context, Assembly: "define void @a(i8** %ptr) {\n"
1457 "entry:\n"
1458 " call void @b(i8** %ptr)\n"
1459 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1460 " ret void\n"
1461 "}\n"
1462 "define void @b(i8** %ptr) {\n"
1463 "entry:\n"
1464 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1465 " call void @c(i8** %ptr)\n"
1466 " ret void\n"
1467 "}\n"
1468 "define void @c(i8** %ptr) {\n"
1469 "entry:\n"
1470 " call void @a(i8** %ptr)\n"
1471 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1472 " ret void\n"
1473 "}\n");
1474 LazyCallGraph CG = buildCG(M&: *M);
1475
1476 // Force the graph to be fully expanded.
1477 CG.buildRefSCCs();
1478 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
1479 LazyCallGraph::RefSCC &RC = *I;
1480 EXPECT_EQ(E, std::next(I));
1481
1482 LazyCallGraph::SCC &C = *RC.begin();
1483 EXPECT_EQ(RC.end(), std::next(RC.begin()));
1484
1485 LazyCallGraph::Node &AN = *CG.lookup(F: lookupFunction(M&: *M, Name: "a"));
1486 LazyCallGraph::Node &BN = *CG.lookup(F: lookupFunction(M&: *M, Name: "b"));
1487 LazyCallGraph::Node &CN = *CG.lookup(F: lookupFunction(M&: *M, Name: "c"));
1488 EXPECT_EQ(&RC, CG.lookupRefSCC(AN));
1489 EXPECT_EQ(&RC, CG.lookupRefSCC(BN));
1490 EXPECT_EQ(&RC, CG.lookupRefSCC(CN));
1491 EXPECT_EQ(&C, CG.lookupSCC(AN));
1492 EXPECT_EQ(&C, CG.lookupSCC(BN));
1493 EXPECT_EQ(&C, CG.lookupSCC(CN));
1494
1495 // Remove the edge from a -> c which doesn't change anything.
1496 SmallVector<LazyCallGraph::RefSCC *, 1> NewRCs =
1497 RC.removeInternalRefEdge(SourceN&: AN, TargetNs: {&CN});
1498 EXPECT_EQ(0u, NewRCs.size());
1499 EXPECT_EQ(&RC, CG.lookupRefSCC(AN));
1500 EXPECT_EQ(&RC, CG.lookupRefSCC(BN));
1501 EXPECT_EQ(&RC, CG.lookupRefSCC(CN));
1502 EXPECT_EQ(&C, CG.lookupSCC(AN));
1503 EXPECT_EQ(&C, CG.lookupSCC(BN));
1504 EXPECT_EQ(&C, CG.lookupSCC(CN));
1505 auto J = CG.postorder_ref_scc_begin();
1506 EXPECT_EQ(I, J);
1507 EXPECT_EQ(&RC, &*J);
1508 EXPECT_EQ(E, std::next(J));
1509
1510 // Remove the edge from b -> a and c -> b; again this doesn't change
1511 // anything.
1512 NewRCs = RC.removeInternalRefEdge(SourceN&: BN, TargetNs: {&AN});
1513 NewRCs = RC.removeInternalRefEdge(SourceN&: CN, TargetNs: {&BN});
1514 EXPECT_EQ(0u, NewRCs.size());
1515 EXPECT_EQ(&RC, CG.lookupRefSCC(AN));
1516 EXPECT_EQ(&RC, CG.lookupRefSCC(BN));
1517 EXPECT_EQ(&RC, CG.lookupRefSCC(CN));
1518 EXPECT_EQ(&C, CG.lookupSCC(AN));
1519 EXPECT_EQ(&C, CG.lookupSCC(BN));
1520 EXPECT_EQ(&C, CG.lookupSCC(CN));
1521 J = CG.postorder_ref_scc_begin();
1522 EXPECT_EQ(I, J);
1523 EXPECT_EQ(&RC, &*J);
1524 EXPECT_EQ(E, std::next(J));
1525}
1526
1527TEST(LazyCallGraphTest, InternalCallEdgeToRef) {
1528 LLVMContext Context;
1529 // A nice fully connected (including self-edges) SCC (and RefSCC)
1530 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: "define void @a() {\n"
1531 "entry:\n"
1532 " call void @a()\n"
1533 " call void @b()\n"
1534 " call void @c()\n"
1535 " ret void\n"
1536 "}\n"
1537 "define void @b() {\n"
1538 "entry:\n"
1539 " call void @a()\n"
1540 " call void @b()\n"
1541 " call void @c()\n"
1542 " ret void\n"
1543 "}\n"
1544 "define void @c() {\n"
1545 "entry:\n"
1546 " call void @a()\n"
1547 " call void @b()\n"
1548 " call void @c()\n"
1549 " ret void\n"
1550 "}\n");
1551 LazyCallGraph CG = buildCG(M&: *M);
1552
1553 // Force the graph to be fully expanded.
1554 CG.buildRefSCCs();
1555 auto I = CG.postorder_ref_scc_begin();
1556 LazyCallGraph::RefSCC &RC = *I++;
1557 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1558
1559 EXPECT_EQ(1, RC.size());
1560 LazyCallGraph::SCC &AC = *RC.begin();
1561
1562 LazyCallGraph::Node &AN = *CG.lookup(F: lookupFunction(M&: *M, Name: "a"));
1563 LazyCallGraph::Node &BN = *CG.lookup(F: lookupFunction(M&: *M, Name: "b"));
1564 LazyCallGraph::Node &CN = *CG.lookup(F: lookupFunction(M&: *M, Name: "c"));
1565 EXPECT_EQ(&AC, CG.lookupSCC(AN));
1566 EXPECT_EQ(&AC, CG.lookupSCC(BN));
1567 EXPECT_EQ(&AC, CG.lookupSCC(CN));
1568
1569 // Remove the call edge from b -> a to a ref edge, which should leave the
1570 // 3 functions still in a single connected component because of a -> b ->
1571 // c -> a.
1572 auto NewCs = RC.switchInternalEdgeToRef(SourceN&: BN, TargetN&: AN);
1573 EXPECT_EQ(NewCs.begin(), NewCs.end());
1574 EXPECT_EQ(1, RC.size());
1575 EXPECT_EQ(&AC, CG.lookupSCC(AN));
1576 EXPECT_EQ(&AC, CG.lookupSCC(BN));
1577 EXPECT_EQ(&AC, CG.lookupSCC(CN));
1578
1579 // Remove the edge from c -> a, which should leave 'a' in the original SCC
1580 // and form a new SCC for 'b' and 'c'.
1581 NewCs = RC.switchInternalEdgeToRef(SourceN&: CN, TargetN&: AN);
1582 EXPECT_EQ(1, std::distance(NewCs.begin(), NewCs.end()));
1583 EXPECT_EQ(2, RC.size());
1584 EXPECT_EQ(&AC, CG.lookupSCC(AN));
1585 LazyCallGraph::SCC &BC = *CG.lookupSCC(N&: BN);
1586 EXPECT_NE(&BC, &AC);
1587 EXPECT_EQ(&BC, CG.lookupSCC(CN));
1588 auto J = RC.find(C&: AC);
1589 EXPECT_EQ(&AC, &*J);
1590 --J;
1591 EXPECT_EQ(&BC, &*J);
1592 EXPECT_EQ(RC.begin(), J);
1593 EXPECT_EQ(J, NewCs.begin());
1594
1595 // Remove the edge from c -> b, which should leave 'b' in the original SCC
1596 // and form a new SCC for 'c'. It shouldn't change 'a's SCC.
1597 NewCs = RC.switchInternalEdgeToRef(SourceN&: CN, TargetN&: BN);
1598 EXPECT_EQ(1, std::distance(NewCs.begin(), NewCs.end()));
1599 EXPECT_EQ(3, RC.size());
1600 EXPECT_EQ(&AC, CG.lookupSCC(AN));
1601 EXPECT_EQ(&BC, CG.lookupSCC(BN));
1602 LazyCallGraph::SCC &CC = *CG.lookupSCC(N&: CN);
1603 EXPECT_NE(&CC, &AC);
1604 EXPECT_NE(&CC, &BC);
1605 J = RC.find(C&: AC);
1606 EXPECT_EQ(&AC, &*J);
1607 --J;
1608 EXPECT_EQ(&BC, &*J);
1609 --J;
1610 EXPECT_EQ(&CC, &*J);
1611 EXPECT_EQ(RC.begin(), J);
1612 EXPECT_EQ(J, NewCs.begin());
1613}
1614
1615TEST(LazyCallGraphTest, InternalRefEdgeToCall) {
1616 LLVMContext Context;
1617 // Basic tests for making a ref edge a call. This hits the basics of the
1618 // process only.
1619 std::unique_ptr<Module> M =
1620 parseAssembly(Context, Assembly: "define void @a() {\n"
1621 "entry:\n"
1622 " call void @b()\n"
1623 " call void @c()\n"
1624 " store void()* @d, void()** undef\n"
1625 " ret void\n"
1626 "}\n"
1627 "define void @b() {\n"
1628 "entry:\n"
1629 " store void()* @c, void()** undef\n"
1630 " call void @d()\n"
1631 " ret void\n"
1632 "}\n"
1633 "define void @c() {\n"
1634 "entry:\n"
1635 " store void()* @b, void()** undef\n"
1636 " call void @d()\n"
1637 " ret void\n"
1638 "}\n"
1639 "define void @d() {\n"
1640 "entry:\n"
1641 " store void()* @a, void()** undef\n"
1642 " ret void\n"
1643 "}\n");
1644 LazyCallGraph CG = buildCG(M&: *M);
1645
1646 // Force the graph to be fully expanded.
1647 CG.buildRefSCCs();
1648 auto I = CG.postorder_ref_scc_begin();
1649 LazyCallGraph::RefSCC &RC = *I++;
1650 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1651
1652 LazyCallGraph::Node &A = *CG.lookup(F: lookupFunction(M&: *M, Name: "a"));
1653 LazyCallGraph::Node &B = *CG.lookup(F: lookupFunction(M&: *M, Name: "b"));
1654 LazyCallGraph::Node &C = *CG.lookup(F: lookupFunction(M&: *M, Name: "c"));
1655 LazyCallGraph::Node &D = *CG.lookup(F: lookupFunction(M&: *M, Name: "d"));
1656 LazyCallGraph::SCC &AC = *CG.lookupSCC(N&: A);
1657 LazyCallGraph::SCC &BC = *CG.lookupSCC(N&: B);
1658 LazyCallGraph::SCC &CC = *CG.lookupSCC(N&: C);
1659 LazyCallGraph::SCC &DC = *CG.lookupSCC(N&: D);
1660
1661 // Check the initial post-order. Note that B and C could be flipped here (and
1662 // in our mutation) without changing the nature of this test.
1663 ASSERT_EQ(4, RC.size());
1664 EXPECT_EQ(&DC, &RC[0]);
1665 EXPECT_EQ(&BC, &RC[1]);
1666 EXPECT_EQ(&CC, &RC[2]);
1667 EXPECT_EQ(&AC, &RC[3]);
1668
1669 // Switch the ref edge from A -> D to a call edge. This should have no
1670 // effect as it is already in postorder and no new cycles are formed.
1671 EXPECT_FALSE(RC.switchInternalEdgeToCall(A, D));
1672 ASSERT_EQ(4, RC.size());
1673 EXPECT_EQ(&DC, &RC[0]);
1674 EXPECT_EQ(&BC, &RC[1]);
1675 EXPECT_EQ(&CC, &RC[2]);
1676 EXPECT_EQ(&AC, &RC[3]);
1677
1678 // Switch B -> C to a call edge. This doesn't form any new cycles but does
1679 // require reordering the SCCs.
1680 EXPECT_FALSE(RC.switchInternalEdgeToCall(B, C));
1681 ASSERT_EQ(4, RC.size());
1682 EXPECT_EQ(&DC, &RC[0]);
1683 EXPECT_EQ(&CC, &RC[1]);
1684 EXPECT_EQ(&BC, &RC[2]);
1685 EXPECT_EQ(&AC, &RC[3]);
1686
1687 // Switch C -> B to a call edge. This forms a cycle and forces merging SCCs.
1688 EXPECT_TRUE(RC.switchInternalEdgeToCall(C, B, [&](ArrayRef<LazyCallGraph::SCC *> MergedCs) {
1689 ASSERT_EQ(1u, MergedCs.size());
1690 EXPECT_EQ(&CC, MergedCs[0]);
1691 }));
1692 ASSERT_EQ(3, RC.size());
1693 EXPECT_EQ(&DC, &RC[0]);
1694 EXPECT_EQ(&BC, &RC[1]);
1695 EXPECT_EQ(&AC, &RC[2]);
1696 EXPECT_EQ(2, BC.size());
1697 EXPECT_EQ(&BC, CG.lookupSCC(B));
1698 EXPECT_EQ(&BC, CG.lookupSCC(C));
1699}
1700
1701TEST(LazyCallGraphTest, InternalRefEdgeToCallNoCycleInterleaved) {
1702 LLVMContext Context;
1703 // Test for having a post-order prior to changing a ref edge to a call edge
1704 // with SCCs connecting to the source and connecting to the target, but not
1705 // connecting to both, interleaved between the source and target. This
1706 // ensures we correctly partition the range rather than simply moving one or
1707 // the other.
1708 std::unique_ptr<Module> M =
1709 parseAssembly(Context, Assembly: "define void @a() {\n"
1710 "entry:\n"
1711 " call void @b1()\n"
1712 " call void @c1()\n"
1713 " ret void\n"
1714 "}\n"
1715 "define void @b1() {\n"
1716 "entry:\n"
1717 " call void @c1()\n"
1718 " call void @b2()\n"
1719 " ret void\n"
1720 "}\n"
1721 "define void @c1() {\n"
1722 "entry:\n"
1723 " call void @b2()\n"
1724 " call void @c2()\n"
1725 " ret void\n"
1726 "}\n"
1727 "define void @b2() {\n"
1728 "entry:\n"
1729 " call void @c2()\n"
1730 " call void @b3()\n"
1731 " ret void\n"
1732 "}\n"
1733 "define void @c2() {\n"
1734 "entry:\n"
1735 " call void @b3()\n"
1736 " call void @c3()\n"
1737 " ret void\n"
1738 "}\n"
1739 "define void @b3() {\n"
1740 "entry:\n"
1741 " call void @c3()\n"
1742 " call void @d()\n"
1743 " ret void\n"
1744 "}\n"
1745 "define void @c3() {\n"
1746 "entry:\n"
1747 " store void()* @b1, void()** undef\n"
1748 " call void @d()\n"
1749 " ret void\n"
1750 "}\n"
1751 "define void @d() {\n"
1752 "entry:\n"
1753 " store void()* @a, void()** undef\n"
1754 " ret void\n"
1755 "}\n");
1756 LazyCallGraph CG = buildCG(M&: *M);
1757
1758 // Force the graph to be fully expanded.
1759 CG.buildRefSCCs();
1760 auto I = CG.postorder_ref_scc_begin();
1761 LazyCallGraph::RefSCC &RC = *I++;
1762 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1763
1764 LazyCallGraph::Node &A = *CG.lookup(F: lookupFunction(M&: *M, Name: "a"));
1765 LazyCallGraph::Node &B1 = *CG.lookup(F: lookupFunction(M&: *M, Name: "b1"));
1766 LazyCallGraph::Node &B2 = *CG.lookup(F: lookupFunction(M&: *M, Name: "b2"));
1767 LazyCallGraph::Node &B3 = *CG.lookup(F: lookupFunction(M&: *M, Name: "b3"));
1768 LazyCallGraph::Node &C1 = *CG.lookup(F: lookupFunction(M&: *M, Name: "c1"));
1769 LazyCallGraph::Node &C2 = *CG.lookup(F: lookupFunction(M&: *M, Name: "c2"));
1770 LazyCallGraph::Node &C3 = *CG.lookup(F: lookupFunction(M&: *M, Name: "c3"));
1771 LazyCallGraph::Node &D = *CG.lookup(F: lookupFunction(M&: *M, Name: "d"));
1772 LazyCallGraph::SCC &AC = *CG.lookupSCC(N&: A);
1773 LazyCallGraph::SCC &B1C = *CG.lookupSCC(N&: B1);
1774 LazyCallGraph::SCC &B2C = *CG.lookupSCC(N&: B2);
1775 LazyCallGraph::SCC &B3C = *CG.lookupSCC(N&: B3);
1776 LazyCallGraph::SCC &C1C = *CG.lookupSCC(N&: C1);
1777 LazyCallGraph::SCC &C2C = *CG.lookupSCC(N&: C2);
1778 LazyCallGraph::SCC &C3C = *CG.lookupSCC(N&: C3);
1779 LazyCallGraph::SCC &DC = *CG.lookupSCC(N&: D);
1780
1781 // Several call edges are initially present to force a particual post-order.
1782 // Remove them now, leaving an interleaved post-order pattern.
1783 RC.switchTrivialInternalEdgeToRef(SourceN&: B3, TargetN&: C3);
1784 RC.switchTrivialInternalEdgeToRef(SourceN&: C2, TargetN&: B3);
1785 RC.switchTrivialInternalEdgeToRef(SourceN&: B2, TargetN&: C2);
1786 RC.switchTrivialInternalEdgeToRef(SourceN&: C1, TargetN&: B2);
1787 RC.switchTrivialInternalEdgeToRef(SourceN&: B1, TargetN&: C1);
1788
1789 // Check the initial post-order. We ensure this order with the extra edges
1790 // that are nuked above.
1791 ASSERT_EQ(8, RC.size());
1792 EXPECT_EQ(&DC, &RC[0]);
1793 EXPECT_EQ(&C3C, &RC[1]);
1794 EXPECT_EQ(&B3C, &RC[2]);
1795 EXPECT_EQ(&C2C, &RC[3]);
1796 EXPECT_EQ(&B2C, &RC[4]);
1797 EXPECT_EQ(&C1C, &RC[5]);
1798 EXPECT_EQ(&B1C, &RC[6]);
1799 EXPECT_EQ(&AC, &RC[7]);
1800
1801 // Switch C3 -> B1 to a call edge. This doesn't form any new cycles but does
1802 // require reordering the SCCs in the face of tricky internal node
1803 // structures.
1804 EXPECT_FALSE(RC.switchInternalEdgeToCall(C3, B1));
1805 ASSERT_EQ(8, RC.size());
1806 EXPECT_EQ(&DC, &RC[0]);
1807 EXPECT_EQ(&B3C, &RC[1]);
1808 EXPECT_EQ(&B2C, &RC[2]);
1809 EXPECT_EQ(&B1C, &RC[3]);
1810 EXPECT_EQ(&C3C, &RC[4]);
1811 EXPECT_EQ(&C2C, &RC[5]);
1812 EXPECT_EQ(&C1C, &RC[6]);
1813 EXPECT_EQ(&AC, &RC[7]);
1814}
1815
1816TEST(LazyCallGraphTest, InternalRefEdgeToCallBothPartitionAndMerge) {
1817 LLVMContext Context;
1818 // Test for having a postorder where between the source and target are all
1819 // three kinds of other SCCs:
1820 // 1) One connected to the target only that have to be shifted below the
1821 // source.
1822 // 2) One connected to the source only that have to be shifted below the
1823 // target.
1824 // 3) One connected to both source and target that has to remain and get
1825 // merged away.
1826 //
1827 // To achieve this we construct a heavily connected graph to force
1828 // a particular post-order. Then we remove the forcing edges and connect
1829 // a cycle.
1830 //
1831 // Diagram for the graph we want on the left and the graph we use to force
1832 // the ordering on the right. Edges point down or right.
1833 //
1834 // A | A |
1835 // / \ | / \ |
1836 // B E | B \ |
1837 // |\ | | |\ | |
1838 // | D | | C-D-E |
1839 // | \| | | \| |
1840 // C F | \ F |
1841 // \ / | \ / |
1842 // G | G |
1843 //
1844 // And we form a cycle by connecting F to B.
1845 std::unique_ptr<Module> M =
1846 parseAssembly(Context, Assembly: "define void @a() {\n"
1847 "entry:\n"
1848 " call void @b()\n"
1849 " call void @e()\n"
1850 " ret void\n"
1851 "}\n"
1852 "define void @b() {\n"
1853 "entry:\n"
1854 " call void @c()\n"
1855 " call void @d()\n"
1856 " ret void\n"
1857 "}\n"
1858 "define void @c() {\n"
1859 "entry:\n"
1860 " call void @d()\n"
1861 " call void @g()\n"
1862 " ret void\n"
1863 "}\n"
1864 "define void @d() {\n"
1865 "entry:\n"
1866 " call void @e()\n"
1867 " call void @f()\n"
1868 " ret void\n"
1869 "}\n"
1870 "define void @e() {\n"
1871 "entry:\n"
1872 " call void @f()\n"
1873 " ret void\n"
1874 "}\n"
1875 "define void @f() {\n"
1876 "entry:\n"
1877 " store void()* @b, void()** undef\n"
1878 " call void @g()\n"
1879 " ret void\n"
1880 "}\n"
1881 "define void @g() {\n"
1882 "entry:\n"
1883 " store void()* @a, void()** undef\n"
1884 " ret void\n"
1885 "}\n");
1886 LazyCallGraph CG = buildCG(M&: *M);
1887
1888 // Force the graph to be fully expanded.
1889 CG.buildRefSCCs();
1890 auto I = CG.postorder_ref_scc_begin();
1891 LazyCallGraph::RefSCC &RC = *I++;
1892 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1893
1894 LazyCallGraph::Node &A = *CG.lookup(F: lookupFunction(M&: *M, Name: "a"));
1895 LazyCallGraph::Node &B = *CG.lookup(F: lookupFunction(M&: *M, Name: "b"));
1896 LazyCallGraph::Node &C = *CG.lookup(F: lookupFunction(M&: *M, Name: "c"));
1897 LazyCallGraph::Node &D = *CG.lookup(F: lookupFunction(M&: *M, Name: "d"));
1898 LazyCallGraph::Node &E = *CG.lookup(F: lookupFunction(M&: *M, Name: "e"));
1899 LazyCallGraph::Node &F = *CG.lookup(F: lookupFunction(M&: *M, Name: "f"));
1900 LazyCallGraph::Node &G = *CG.lookup(F: lookupFunction(M&: *M, Name: "g"));
1901 LazyCallGraph::SCC &AC = *CG.lookupSCC(N&: A);
1902 LazyCallGraph::SCC &BC = *CG.lookupSCC(N&: B);
1903 LazyCallGraph::SCC &CC = *CG.lookupSCC(N&: C);
1904 LazyCallGraph::SCC &DC = *CG.lookupSCC(N&: D);
1905 LazyCallGraph::SCC &EC = *CG.lookupSCC(N&: E);
1906 LazyCallGraph::SCC &FC = *CG.lookupSCC(N&: F);
1907 LazyCallGraph::SCC &GC = *CG.lookupSCC(N&: G);
1908
1909 // Remove the extra edges that were used to force a particular post-order.
1910 RC.switchTrivialInternalEdgeToRef(SourceN&: C, TargetN&: D);
1911 RC.switchTrivialInternalEdgeToRef(SourceN&: D, TargetN&: E);
1912
1913 // Check the initial post-order. We ensure this order with the extra edges
1914 // that are nuked above.
1915 ASSERT_EQ(7, RC.size());
1916 EXPECT_EQ(&GC, &RC[0]);
1917 EXPECT_EQ(&FC, &RC[1]);
1918 EXPECT_EQ(&EC, &RC[2]);
1919 EXPECT_EQ(&DC, &RC[3]);
1920 EXPECT_EQ(&CC, &RC[4]);
1921 EXPECT_EQ(&BC, &RC[5]);
1922 EXPECT_EQ(&AC, &RC[6]);
1923
1924 // Switch F -> B to a call edge. This merges B, D, and F into a single SCC,
1925 // and has to place the C and E SCCs on either side of it:
1926 // A A |
1927 // / \ / \ |
1928 // B E | E |
1929 // |\ | \ / |
1930 // | D | -> B |
1931 // | \| / \ |
1932 // C F C | |
1933 // \ / \ / |
1934 // G G |
1935 EXPECT_TRUE(RC.switchInternalEdgeToCall(
1936 F, B, [&](ArrayRef<LazyCallGraph::SCC *> MergedCs) {
1937 ASSERT_EQ(2u, MergedCs.size());
1938 EXPECT_EQ(&FC, MergedCs[0]);
1939 EXPECT_EQ(&DC, MergedCs[1]);
1940 }));
1941 EXPECT_EQ(3, BC.size());
1942
1943 // And make sure the postorder was updated.
1944 ASSERT_EQ(5, RC.size());
1945 EXPECT_EQ(&GC, &RC[0]);
1946 EXPECT_EQ(&CC, &RC[1]);
1947 EXPECT_EQ(&BC, &RC[2]);
1948 EXPECT_EQ(&EC, &RC[3]);
1949 EXPECT_EQ(&AC, &RC[4]);
1950}
1951
1952// Test for IR containing constants using blockaddress constant expressions.
1953// These are truly unique constructs: constant expressions with non-constant
1954// operands.
1955TEST(LazyCallGraphTest, HandleBlockAddress) {
1956 LLVMContext Context;
1957 std::unique_ptr<Module> M =
1958 parseAssembly(Context, Assembly: "define void @f() {\n"
1959 "entry:\n"
1960 " ret void\n"
1961 "bb:\n"
1962 " unreachable\n"
1963 "}\n"
1964 "define void @g(i8** %ptr) {\n"
1965 "entry:\n"
1966 " store i8* blockaddress(@f, %bb), i8** %ptr\n"
1967 " ret void\n"
1968 "}\n");
1969 LazyCallGraph CG = buildCG(M&: *M);
1970
1971 CG.buildRefSCCs();
1972 auto I = CG.postorder_ref_scc_begin();
1973 LazyCallGraph::RefSCC &FRC = *I++;
1974 LazyCallGraph::RefSCC &GRC = *I++;
1975 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1976
1977 LazyCallGraph::Node &F = *CG.lookup(F: lookupFunction(M&: *M, Name: "f"));
1978 LazyCallGraph::Node &G = *CG.lookup(F: lookupFunction(M&: *M, Name: "g"));
1979 EXPECT_EQ(&FRC, CG.lookupRefSCC(F));
1980 EXPECT_EQ(&GRC, CG.lookupRefSCC(G));
1981 EXPECT_FALSE(GRC.isParentOf(FRC));
1982 EXPECT_FALSE(FRC.isParentOf(GRC));
1983}
1984
1985// Test that a blockaddress that refers to itself creates no new RefSCC
1986// connections. https://bugs.llvm.org/show_bug.cgi?id=40722
1987TEST(LazyCallGraphTest, HandleBlockAddress2) {
1988 LLVMContext Context;
1989 std::unique_ptr<Module> M =
1990 parseAssembly(Context, Assembly: "define void @f() {\n"
1991 " ret void\n"
1992 "}\n"
1993 "define void @g(i8** %ptr) {\n"
1994 "bb:\n"
1995 " store i8* blockaddress(@g, %bb), i8** %ptr\n"
1996 " ret void\n"
1997 "}\n");
1998 LazyCallGraph CG = buildCG(M&: *M);
1999
2000 CG.buildRefSCCs();
2001 auto I = CG.postorder_ref_scc_begin();
2002 LazyCallGraph::RefSCC &FRC = *I++;
2003 LazyCallGraph::RefSCC &GRC = *I++;
2004 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2005
2006 LazyCallGraph::Node &F = *CG.lookup(F: lookupFunction(M&: *M, Name: "f"));
2007 LazyCallGraph::Node &G = *CG.lookup(F: lookupFunction(M&: *M, Name: "g"));
2008 EXPECT_EQ(&FRC, CG.lookupRefSCC(F));
2009 EXPECT_EQ(&GRC, CG.lookupRefSCC(G));
2010 EXPECT_FALSE(GRC.isParentOf(FRC));
2011 EXPECT_FALSE(FRC.isParentOf(GRC));
2012}
2013
2014TEST(LazyCallGraphTest, ReplaceNodeFunction) {
2015 LLVMContext Context;
2016 // A graph with several different kinds of edges pointing at a particular
2017 // function.
2018 std::unique_ptr<Module> M =
2019 parseAssembly(Context,
2020 Assembly: "define void @a(i8** %ptr) {\n"
2021 "entry:\n"
2022 " store i8* bitcast (void(i8**)* @d to i8*), i8** %ptr\n"
2023 " ret void\n"
2024 "}\n"
2025 "define void @b(i8** %ptr) {\n"
2026 "entry:\n"
2027 " store i8* bitcast (void(i8**)* @d to i8*), i8** %ptr\n"
2028 " store i8* bitcast (void(i8**)* @d to i8*), i8** %ptr\n"
2029 " call void @d(i8** %ptr)"
2030 " ret void\n"
2031 "}\n"
2032 "define void @c(i8** %ptr) {\n"
2033 "entry:\n"
2034 " call void @d(i8** %ptr)"
2035 " call void @d(i8** %ptr)"
2036 " store i8* bitcast (void(i8**)* @d to i8*), i8** %ptr\n"
2037 " ret void\n"
2038 "}\n"
2039 "define void @d(i8** %ptr) {\n"
2040 "entry:\n"
2041 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
2042 " call void @c(i8** %ptr)"
2043 " call void @d(i8** %ptr)"
2044 " store i8* bitcast (void(i8**)* @d to i8*), i8** %ptr\n"
2045 " ret void\n"
2046 "}\n");
2047 LazyCallGraph CG = buildCG(M&: *M);
2048
2049 // Force the graph to be fully expanded.
2050 CG.buildRefSCCs();
2051 auto I = CG.postorder_ref_scc_begin();
2052 LazyCallGraph::RefSCC &RC1 = *I++;
2053 LazyCallGraph::RefSCC &RC2 = *I++;
2054 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2055
2056 ASSERT_EQ(2, RC1.size());
2057 LazyCallGraph::SCC &C1 = RC1[0];
2058 LazyCallGraph::SCC &C2 = RC1[1];
2059
2060 LazyCallGraph::Node &AN = *CG.lookup(F: lookupFunction(M&: *M, Name: "a"));
2061 LazyCallGraph::Node &BN = *CG.lookup(F: lookupFunction(M&: *M, Name: "b"));
2062 LazyCallGraph::Node &CN = *CG.lookup(F: lookupFunction(M&: *M, Name: "c"));
2063 LazyCallGraph::Node &DN = *CG.lookup(F: lookupFunction(M&: *M, Name: "d"));
2064 EXPECT_EQ(&C1, CG.lookupSCC(DN));
2065 EXPECT_EQ(&C1, CG.lookupSCC(CN));
2066 EXPECT_EQ(&C2, CG.lookupSCC(BN));
2067 EXPECT_EQ(&RC1, CG.lookupRefSCC(DN));
2068 EXPECT_EQ(&RC1, CG.lookupRefSCC(CN));
2069 EXPECT_EQ(&RC1, CG.lookupRefSCC(BN));
2070 EXPECT_EQ(&RC2, CG.lookupRefSCC(AN));
2071
2072 // Now we need to build a new function 'e' with the same signature as 'd'.
2073 Function &D = DN.getFunction();
2074 Function &E = *Function::Create(Ty: D.getFunctionType(), Linkage: D.getLinkage(), N: "e");
2075 D.getParent()->getFunctionList().insert(where: D.getIterator(), New: &E);
2076
2077 // Change each use of 'd' to use 'e'. This is particularly easy as they have
2078 // the same type.
2079 D.replaceAllUsesWith(V: &E);
2080
2081 // Splice the body of the old function into the new one.
2082 E.splice(ToIt: E.begin(), FromF: &D);
2083 // And fix up the one argument.
2084 D.arg_begin()->replaceAllUsesWith(V: &*E.arg_begin());
2085 E.arg_begin()->takeName(V: &*D.arg_begin());
2086
2087 // Now replace the function in the graph.
2088 RC1.replaceNodeFunction(N&: DN, NewF&: E);
2089
2090 EXPECT_EQ(&E, &DN.getFunction());
2091 EXPECT_EQ(&DN, &(*CN)[DN].getNode());
2092 EXPECT_EQ(&DN, &(*BN)[DN].getNode());
2093}
2094
2095TEST(LazyCallGraphTest, RemoveFunctionWithSpuriousRef) {
2096 LLVMContext Context;
2097 // A graph with a couple of RefSCCs.
2098 std::unique_ptr<Module> M =
2099 parseAssembly(Context,
2100 Assembly: "define void @a(i8** %ptr) {\n"
2101 "entry:\n"
2102 " store i8* bitcast (void(i8**)* @d to i8*), i8** %ptr\n"
2103 " ret void\n"
2104 "}\n"
2105 "define void @b(i8** %ptr) {\n"
2106 "entry:\n"
2107 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
2108 " ret void\n"
2109 "}\n"
2110 "define void @c(i8** %ptr) {\n"
2111 "entry:\n"
2112 " call void @d(i8** %ptr)"
2113 " ret void\n"
2114 "}\n"
2115 "define void @d(i8** %ptr) {\n"
2116 "entry:\n"
2117 " call void @c(i8** %ptr)"
2118 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
2119 " ret void\n"
2120 "}\n"
2121 "define void @dead() {\n"
2122 "entry:\n"
2123 " ret void\n"
2124 "}\n");
2125 LazyCallGraph CG = buildCG(M&: *M);
2126
2127 // Insert spurious ref edges.
2128 LazyCallGraph::Node &AN = CG.get(F&: lookupFunction(M&: *M, Name: "a"));
2129 LazyCallGraph::Node &BN = CG.get(F&: lookupFunction(M&: *M, Name: "b"));
2130 LazyCallGraph::Node &CN = CG.get(F&: lookupFunction(M&: *M, Name: "c"));
2131 LazyCallGraph::Node &DN = CG.get(F&: lookupFunction(M&: *M, Name: "d"));
2132 LazyCallGraph::Node &DeadN = CG.get(F&: lookupFunction(M&: *M, Name: "dead"));
2133 AN.populate();
2134 BN.populate();
2135 CN.populate();
2136 DN.populate();
2137 DeadN.populate();
2138 CG.insertEdge(SourceN&: AN, TargetN&: DeadN, EK: LazyCallGraph::Edge::Ref);
2139 CG.insertEdge(SourceN&: BN, TargetN&: DeadN, EK: LazyCallGraph::Edge::Ref);
2140 CG.insertEdge(SourceN&: CN, TargetN&: DeadN, EK: LazyCallGraph::Edge::Ref);
2141 CG.insertEdge(SourceN&: DN, TargetN&: DeadN, EK: LazyCallGraph::Edge::Ref);
2142
2143 // Force the graph to be fully expanded.
2144 CG.buildRefSCCs();
2145 auto I = CG.postorder_ref_scc_begin();
2146 LazyCallGraph::RefSCC &DeadRC = *I++;
2147 LazyCallGraph::RefSCC &RC1 = *I++;
2148 LazyCallGraph::RefSCC &RC2 = *I++;
2149 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2150
2151 ASSERT_EQ(2, RC1.size());
2152 LazyCallGraph::SCC &C1 = RC1[0];
2153 LazyCallGraph::SCC &C2 = RC1[1];
2154
2155 EXPECT_EQ(&DeadRC, CG.lookupRefSCC(DeadN));
2156 EXPECT_EQ(&C1, CG.lookupSCC(DN));
2157 EXPECT_EQ(&C1, CG.lookupSCC(CN));
2158 EXPECT_EQ(&C2, CG.lookupSCC(BN));
2159 EXPECT_EQ(&RC1, CG.lookupRefSCC(DN));
2160 EXPECT_EQ(&RC1, CG.lookupRefSCC(CN));
2161 EXPECT_EQ(&RC1, CG.lookupRefSCC(BN));
2162 EXPECT_EQ(&RC2, CG.lookupRefSCC(AN));
2163
2164 // Now delete 'dead'. There are no uses of this function but there are
2165 // spurious references.
2166 CG.removeDeadFunction(F&: DeadN.getFunction());
2167
2168 // The only observable change should be that the RefSCC is gone from the
2169 // postorder sequence.
2170 I = CG.postorder_ref_scc_begin();
2171 EXPECT_EQ(&RC1, &*I++);
2172 EXPECT_EQ(&RC2, &*I++);
2173 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2174}
2175
2176TEST(LazyCallGraphTest, RemoveFunctionWithSpuriousRefRecursive) {
2177 LLVMContext Context;
2178 std::unique_ptr<Module> M =
2179 parseAssembly(Context, Assembly: "define void @a(ptr %p) {\n"
2180 " store ptr @b, ptr %p\n"
2181 " ret void\n"
2182 "}\n"
2183 "define void @b(ptr %p) {\n"
2184 " store ptr @c, ptr %p\n"
2185 " ret void\n"
2186 "}\n"
2187 "define void @c(ptr %p) {\n"
2188 " ret void\n"
2189 "}\n");
2190 LazyCallGraph CG = buildCG(M&: *M);
2191
2192 LazyCallGraph::Node &AN = CG.get(F&: lookupFunction(M&: *M, Name: "a"));
2193 LazyCallGraph::Node &BN = CG.get(F&: lookupFunction(M&: *M, Name: "b"));
2194 LazyCallGraph::Node &CN = CG.get(F&: lookupFunction(M&: *M, Name: "c"));
2195 AN.populate();
2196 BN.populate();
2197 CN.populate();
2198 // Insert spurious ref edge.
2199 CG.insertEdge(SourceN&: CN, TargetN&: AN, EK: LazyCallGraph::Edge::Ref);
2200
2201 // Force the graph to be fully expanded.
2202 CG.buildRefSCCs();
2203 auto I = CG.postorder_ref_scc_begin();
2204 LazyCallGraph::RefSCC &RC = *I++;
2205 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2206
2207 ASSERT_EQ(RC.size(), 3);
2208
2209 EXPECT_EQ(&RC, CG.lookupRefSCC(AN));
2210 EXPECT_EQ(&RC, CG.lookupRefSCC(BN));
2211 EXPECT_EQ(&RC, CG.lookupRefSCC(CN));
2212
2213 // Now delete 'a'. There are no uses of this function but there are
2214 // spurious references.
2215 CG.removeDeadFunction(F&: AN.getFunction());
2216
2217 // The only observable change should be that the RefSCC is gone from the
2218 // postorder sequence.
2219 I = CG.postorder_ref_scc_begin();
2220 EXPECT_EQ(CG.lookupRefSCC(CN), &*I++);
2221 EXPECT_EQ(CG.lookupRefSCC(BN), &*I++);
2222 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2223}
2224
2225TEST(LazyCallGraphTest, RemoveFunctionWithSpuriousRefRecursive2) {
2226 LLVMContext Context;
2227 std::unique_ptr<Module> M =
2228 parseAssembly(Context, Assembly: "define void @a(ptr %p) {\n"
2229 " store ptr @b, ptr %p\n"
2230 " ret void\n"
2231 "}\n"
2232 "define void @b(ptr %p) {\n"
2233 " store ptr @c, ptr %p\n"
2234 " ret void\n"
2235 "}\n"
2236 "define void @c(ptr %p) {\n"
2237 " store ptr @b, ptr %p\n"
2238 " store ptr @d, ptr %p\n"
2239 " ret void\n"
2240 "}\n"
2241 "define void @d(ptr %p) {\n"
2242 " ret void\n"
2243 "}\n");
2244 LazyCallGraph CG = buildCG(M&: *M);
2245
2246 LazyCallGraph::Node &AN = CG.get(F&: lookupFunction(M&: *M, Name: "a"));
2247 LazyCallGraph::Node &BN = CG.get(F&: lookupFunction(M&: *M, Name: "b"));
2248 LazyCallGraph::Node &CN = CG.get(F&: lookupFunction(M&: *M, Name: "c"));
2249 LazyCallGraph::Node &DN = CG.get(F&: lookupFunction(M&: *M, Name: "d"));
2250 AN.populate();
2251 BN.populate();
2252 CN.populate();
2253 DN.populate();
2254 // Insert spurious ref edge.
2255 CG.insertEdge(SourceN&: DN, TargetN&: AN, EK: LazyCallGraph::Edge::Ref);
2256
2257 // Force the graph to be fully expanded.
2258 CG.buildRefSCCs();
2259 auto I = CG.postorder_ref_scc_begin();
2260 LazyCallGraph::RefSCC &RC = *I++;
2261 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2262
2263 ASSERT_EQ(4, RC.size());
2264
2265 EXPECT_EQ(&RC, CG.lookupRefSCC(AN));
2266 EXPECT_EQ(&RC, CG.lookupRefSCC(BN));
2267 EXPECT_EQ(&RC, CG.lookupRefSCC(CN));
2268 EXPECT_EQ(&RC, CG.lookupRefSCC(DN));
2269
2270 // Now delete 'a'. There are no uses of this function but there are
2271 // spurious references.
2272 CG.removeDeadFunction(F&: AN.getFunction());
2273
2274 // The only observable change should be that the RefSCC is gone from the
2275 // postorder sequence.
2276 I = CG.postorder_ref_scc_begin();
2277 EXPECT_EQ(CG.lookupRefSCC(DN), &*I++);
2278 EXPECT_EQ(CG.lookupRefSCC(CN), &*I);
2279 EXPECT_EQ(CG.lookupRefSCC(BN), &*I++);
2280 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2281}
2282
2283TEST(LazyCallGraphTest, RemoveFunctionWithSpuriousRefRecursive3) {
2284 LLVMContext Context;
2285 std::unique_ptr<Module> M =
2286 parseAssembly(Context, Assembly: "define void @a(ptr %p) {\n"
2287 " store ptr @b, ptr %p\n"
2288 " ret void\n"
2289 "}\n"
2290 "define void @b(ptr %p) {\n"
2291 " store ptr @c, ptr %p\n"
2292 " ret void\n"
2293 "}\n"
2294 "define void @c(ptr %p) {\n"
2295 " ret void\n"
2296 "}\n");
2297 LazyCallGraph CG = buildCG(M&: *M);
2298
2299 LazyCallGraph::Node &AN = CG.get(F&: lookupFunction(M&: *M, Name: "a"));
2300 LazyCallGraph::Node &BN = CG.get(F&: lookupFunction(M&: *M, Name: "b"));
2301 LazyCallGraph::Node &CN = CG.get(F&: lookupFunction(M&: *M, Name: "c"));
2302 AN.populate();
2303 BN.populate();
2304 CN.populate();
2305 // Insert spurious ref edges.
2306 CG.insertEdge(SourceN&: CN, TargetN&: AN, EK: LazyCallGraph::Edge::Ref);
2307 CG.insertEdge(SourceN&: BN, TargetN&: AN, EK: LazyCallGraph::Edge::Ref);
2308
2309 // Force the graph to be fully expanded.
2310 CG.buildRefSCCs();
2311 auto I = CG.postorder_ref_scc_begin();
2312 LazyCallGraph::RefSCC &RC = *I++;
2313 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2314
2315 ASSERT_EQ(RC.size(), 3);
2316
2317 EXPECT_EQ(&RC, CG.lookupRefSCC(AN));
2318 EXPECT_EQ(&RC, CG.lookupRefSCC(BN));
2319 EXPECT_EQ(&RC, CG.lookupRefSCC(CN));
2320
2321 // Now delete 'a'. There are no uses of this function but there are
2322 // spurious references.
2323 CG.removeDeadFunction(F&: AN.getFunction());
2324
2325 // The only observable change should be that the RefSCC is gone from the
2326 // postorder sequence.
2327 I = CG.postorder_ref_scc_begin();
2328 EXPECT_EQ(CG.lookupRefSCC(CN), &*I++);
2329 EXPECT_EQ(CG.lookupRefSCC(BN), &*I++);
2330 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2331}
2332
2333TEST(LazyCallGraphTest, AddSplitFunction1) {
2334 LLVMContext Context;
2335 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: "define void @f() {\n"
2336 " ret void\n"
2337 "}\n");
2338 LazyCallGraph CG = buildCG(M&: *M);
2339
2340 Function &F = lookupFunction(M&: *M, Name: "f");
2341 LazyCallGraph::Node &FN = CG.get(F);
2342
2343 // Force the graph to be fully expanded.
2344 CG.buildRefSCCs();
2345 auto I = CG.postorder_ref_scc_begin();
2346 LazyCallGraph::RefSCC *ORC = &*I++;
2347 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2348
2349 auto *G = Function::Create(Ty: F.getFunctionType(), Linkage: F.getLinkage(),
2350 AddrSpace: F.getAddressSpace(), N: "g", M: F.getParent());
2351 BasicBlock *GBB = BasicBlock::Create(Context, Name: "", Parent: G);
2352 (void)ReturnInst::Create(C&: Context, InsertAtEnd: GBB);
2353
2354 // Create f -call-> g.
2355 (void)CallInst::Create(Func: G, Args: {}, NameStr: "", InsertBefore: &*F.getEntryBlock().begin());
2356
2357 EXPECT_FALSE(verifyModule(*M, &errs()));
2358
2359 CG.addSplitFunction(OriginalFunction&: F, NewFunction&: *G);
2360
2361 LazyCallGraph::Node *GN = CG.lookup(F: *G);
2362 EXPECT_TRUE(GN);
2363
2364 I = CG.postorder_ref_scc_begin();
2365 LazyCallGraph::RefSCC *RC1 = &*I++;
2366 EXPECT_EQ(RC1, CG.lookupRefSCC(*GN));
2367 LazyCallGraph::RefSCC *RC2 = &*I++;
2368 EXPECT_EQ(RC2, ORC);
2369 EXPECT_EQ(RC2, CG.lookupRefSCC(FN));
2370 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2371}
2372
2373TEST(LazyCallGraphTest, AddSplitFunction2) {
2374 LLVMContext Context;
2375 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: "define void @f() {\n"
2376 " ret void\n"
2377 "}\n");
2378 LazyCallGraph CG = buildCG(M&: *M);
2379
2380 Function &F = lookupFunction(M&: *M, Name: "f");
2381 LazyCallGraph::Node &FN = CG.get(F);
2382
2383 // Force the graph to be fully expanded.
2384 CG.buildRefSCCs();
2385 auto I = CG.postorder_ref_scc_begin();
2386 LazyCallGraph::RefSCC *ORC = &*I++;
2387 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2388
2389 auto *G = Function::Create(Ty: F.getFunctionType(), Linkage: F.getLinkage(),
2390 AddrSpace: F.getAddressSpace(), N: "g", M: F.getParent());
2391 BasicBlock *GBB = BasicBlock::Create(Context, Name: "", Parent: G);
2392 (void)ReturnInst::Create(C&: Context, InsertAtEnd: GBB);
2393
2394 // Create f -ref-> g.
2395 (void)CastInst::CreatePointerCast(S: G, Ty: PointerType::getUnqual(C&: Context), Name: "",
2396 InsertBefore: &*F.getEntryBlock().begin());
2397
2398 EXPECT_FALSE(verifyModule(*M, &errs()));
2399
2400 CG.addSplitFunction(OriginalFunction&: F, NewFunction&: *G);
2401
2402 LazyCallGraph::Node *GN = CG.lookup(F: *G);
2403 EXPECT_TRUE(GN);
2404
2405 I = CG.postorder_ref_scc_begin();
2406 LazyCallGraph::RefSCC *RC1 = &*I++;
2407 EXPECT_EQ(RC1, CG.lookupRefSCC(*GN));
2408 LazyCallGraph::RefSCC *RC2 = &*I++;
2409 EXPECT_EQ(RC2, ORC);
2410 EXPECT_EQ(RC2, CG.lookupRefSCC(FN));
2411 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2412}
2413
2414TEST(LazyCallGraphTest, AddSplitFunction3) {
2415 LLVMContext Context;
2416 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: "define void @f() {\n"
2417 " ret void\n"
2418 "}\n");
2419 LazyCallGraph CG = buildCG(M&: *M);
2420
2421 Function &F = lookupFunction(M&: *M, Name: "f");
2422 LazyCallGraph::Node &FN = CG.get(F);
2423
2424 // Force the graph to be fully expanded.
2425 CG.buildRefSCCs();
2426 auto I = CG.postorder_ref_scc_begin();
2427 LazyCallGraph::RefSCC *ORC = &*I++;
2428 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2429
2430 auto *G = Function::Create(Ty: F.getFunctionType(), Linkage: F.getLinkage(),
2431 AddrSpace: F.getAddressSpace(), N: "g", M: F.getParent());
2432 BasicBlock *GBB = BasicBlock::Create(Context, Name: "", Parent: G);
2433 // Create g -ref-> f.
2434 (void)CastInst::CreatePointerCast(S: &F, Ty: PointerType::getUnqual(C&: Context), Name: "",
2435 InsertAtEnd: GBB);
2436 (void)ReturnInst::Create(C&: Context, InsertAtEnd: GBB);
2437
2438 // Create f -call-> g.
2439 (void)CallInst::Create(Func: G, Args: {}, NameStr: "", InsertBefore: &*F.getEntryBlock().begin());
2440
2441 EXPECT_FALSE(verifyModule(*M, &errs()));
2442
2443 CG.addSplitFunction(OriginalFunction&: F, NewFunction&: *G);
2444
2445 LazyCallGraph::Node *GN = CG.lookup(F: *G);
2446 EXPECT_TRUE(GN);
2447
2448 I = CG.postorder_ref_scc_begin();
2449 LazyCallGraph::RefSCC *RC = &*I++;
2450 EXPECT_EQ(RC, CG.lookupRefSCC(*GN));
2451 EXPECT_EQ(RC, ORC);
2452 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2453
2454 EXPECT_EQ(2, RC->size());
2455 EXPECT_EQ(CG.lookupSCC(*GN), &(*RC)[0]);
2456 EXPECT_EQ(CG.lookupSCC(FN), &(*RC)[1]);
2457}
2458
2459TEST(LazyCallGraphTest, AddSplitFunction4) {
2460 LLVMContext Context;
2461 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: "define void @f() {\n"
2462 " ret void\n"
2463 "}\n");
2464 LazyCallGraph CG = buildCG(M&: *M);
2465
2466 Function &F = lookupFunction(M&: *M, Name: "f");
2467 LazyCallGraph::Node &FN = CG.get(F);
2468
2469 // Force the graph to be fully expanded.
2470 CG.buildRefSCCs();
2471 auto I = CG.postorder_ref_scc_begin();
2472 LazyCallGraph::RefSCC *ORC = &*I++;
2473 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2474
2475 auto *G = Function::Create(Ty: F.getFunctionType(), Linkage: F.getLinkage(),
2476 AddrSpace: F.getAddressSpace(), N: "g", M: F.getParent());
2477 BasicBlock *GBB = BasicBlock::Create(Context, Name: "", Parent: G);
2478 // Create g -ref-> f.
2479 (void)CastInst::CreatePointerCast(S: &F, Ty: PointerType::getUnqual(C&: Context), Name: "",
2480 InsertAtEnd: GBB);
2481 (void)ReturnInst::Create(C&: Context, InsertAtEnd: GBB);
2482
2483 // Create f -ref-> g.
2484 (void)CastInst::CreatePointerCast(S: G, Ty: PointerType::getUnqual(C&: Context), Name: "",
2485 InsertBefore: &*F.getEntryBlock().begin());
2486
2487 EXPECT_FALSE(verifyModule(*M, &errs()));
2488
2489 CG.addSplitFunction(OriginalFunction&: F, NewFunction&: *G);
2490
2491 LazyCallGraph::Node *GN = CG.lookup(F: *G);
2492 EXPECT_TRUE(GN);
2493
2494 I = CG.postorder_ref_scc_begin();
2495 LazyCallGraph::RefSCC *RC = &*I++;
2496 EXPECT_EQ(RC, CG.lookupRefSCC(*GN));
2497 EXPECT_EQ(RC, ORC);
2498 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2499
2500 // Order doesn't matter for sibling SCCs.
2501 EXPECT_EQ(2, RC->size());
2502 EXPECT_EQ(&CG.lookupSCC(*GN)->getOuterRefSCC(), RC);
2503 EXPECT_EQ(&CG.lookupSCC(FN)->getOuterRefSCC(), RC);
2504}
2505
2506TEST(LazyCallGraphTest, AddSplitFunction5) {
2507 LLVMContext Context;
2508 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: "define void @f() {\n"
2509 " ret void\n"
2510 "}\n");
2511 LazyCallGraph CG = buildCG(M&: *M);
2512
2513 Function &F = lookupFunction(M&: *M, Name: "f");
2514 LazyCallGraph::Node &FN = CG.get(F);
2515
2516 // Force the graph to be fully expanded.
2517 CG.buildRefSCCs();
2518 auto I = CG.postorder_ref_scc_begin();
2519 LazyCallGraph::RefSCC *ORC = &*I++;
2520 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2521
2522 auto *G = Function::Create(Ty: F.getFunctionType(), Linkage: F.getLinkage(),
2523 AddrSpace: F.getAddressSpace(), N: "g", M: F.getParent());
2524 BasicBlock *GBB = BasicBlock::Create(Context, Name: "", Parent: G);
2525 // Create g -call-> f.
2526 (void)CallInst::Create(Func: &F, Args: {}, NameStr: "", InsertAtEnd: GBB);
2527 (void)ReturnInst::Create(C&: Context, InsertAtEnd: GBB);
2528
2529 // Create f -ref-> g.
2530 (void)CastInst::CreatePointerCast(S: G, Ty: PointerType::getUnqual(C&: Context), Name: "",
2531 InsertBefore: &*F.getEntryBlock().begin());
2532
2533 EXPECT_FALSE(verifyModule(*M, &errs()));
2534
2535 CG.addSplitFunction(OriginalFunction&: F, NewFunction&: *G);
2536
2537 LazyCallGraph::Node *GN = CG.lookup(F: *G);
2538 EXPECT_TRUE(GN);
2539
2540 I = CG.postorder_ref_scc_begin();
2541 LazyCallGraph::RefSCC *RC = &*I++;
2542 EXPECT_EQ(RC, CG.lookupRefSCC(*GN));
2543 EXPECT_EQ(RC, ORC);
2544 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2545
2546 EXPECT_EQ(2, RC->size());
2547 EXPECT_EQ(CG.lookupSCC(FN), &(*RC)[0]);
2548 EXPECT_EQ(CG.lookupSCC(*GN), &(*RC)[1]);
2549}
2550
2551TEST(LazyCallGraphTest, AddSplitFunction6) {
2552 LLVMContext Context;
2553 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: "define void @f() {\n"
2554 " ret void\n"
2555 "}\n");
2556 LazyCallGraph CG = buildCG(M&: *M);
2557
2558 Function &F = lookupFunction(M&: *M, Name: "f");
2559 LazyCallGraph::Node &FN = CG.get(F);
2560
2561 // Force the graph to be fully expanded.
2562 CG.buildRefSCCs();
2563 auto I = CG.postorder_ref_scc_begin();
2564 LazyCallGraph::RefSCC *ORC = &*I++;
2565 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2566
2567 auto *G = Function::Create(Ty: F.getFunctionType(), Linkage: F.getLinkage(),
2568 AddrSpace: F.getAddressSpace(), N: "g", M: F.getParent());
2569 BasicBlock *GBB = BasicBlock::Create(Context, Name: "", Parent: G);
2570 // Create g -call-> f.
2571 (void)CallInst::Create(Func: &F, Args: {}, NameStr: "", InsertAtEnd: GBB);
2572 (void)ReturnInst::Create(C&: Context, InsertAtEnd: GBB);
2573
2574 // Create f -call-> g.
2575 (void)CallInst::Create(Func: G, Args: {}, NameStr: "", InsertBefore: &*F.getEntryBlock().begin());
2576
2577 EXPECT_FALSE(verifyModule(*M, &errs()));
2578
2579 CG.addSplitFunction(OriginalFunction&: F, NewFunction&: *G);
2580
2581 LazyCallGraph::Node *GN = CG.lookup(F: *G);
2582 EXPECT_TRUE(GN);
2583
2584 I = CG.postorder_ref_scc_begin();
2585 LazyCallGraph::RefSCC *RC = &*I++;
2586 EXPECT_EQ(RC, CG.lookupRefSCC(*GN));
2587 EXPECT_EQ(RC, ORC);
2588 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2589
2590 EXPECT_EQ(1, RC->size());
2591 EXPECT_EQ(CG.lookupSCC(FN), &(*RC)[0]);
2592 EXPECT_EQ(CG.lookupSCC(*GN), &(*RC)[0]);
2593}
2594
2595TEST(LazyCallGraphTest, AddSplitFunction7) {
2596 LLVMContext Context;
2597 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: "define void @f() {\n"
2598 " call void @f2()\n"
2599 " ret void\n"
2600 "}\n"
2601 "define void @f2() {\n"
2602 " call void @f()\n"
2603 " ret void\n"
2604 "}\n");
2605 LazyCallGraph CG = buildCG(M&: *M);
2606
2607 Function &F = lookupFunction(M&: *M, Name: "f");
2608 LazyCallGraph::Node &FN = CG.get(F);
2609 Function &F2 = lookupFunction(M&: *M, Name: "f2");
2610 LazyCallGraph::Node &F2N = CG.get(F&: F2);
2611
2612 // Force the graph to be fully expanded.
2613 CG.buildRefSCCs();
2614 auto I = CG.postorder_ref_scc_begin();
2615 LazyCallGraph::RefSCC *ORC = &*I++;
2616 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2617
2618 auto *G = Function::Create(Ty: F.getFunctionType(), Linkage: F.getLinkage(),
2619 AddrSpace: F.getAddressSpace(), N: "g", M: F.getParent());
2620 BasicBlock *GBB = BasicBlock::Create(Context, Name: "", Parent: G);
2621 // Create g -call-> f2.
2622 (void)CallInst::Create(Func: &F2, Args: {}, NameStr: "", InsertAtEnd: GBB);
2623 (void)ReturnInst::Create(C&: Context, InsertAtEnd: GBB);
2624
2625 // Create f -call-> g.
2626 (void)CallInst::Create(Func: G, Args: {}, NameStr: "", InsertBefore: &*F.getEntryBlock().begin());
2627
2628 EXPECT_FALSE(verifyModule(*M, &errs()));
2629
2630 CG.addSplitFunction(OriginalFunction&: F, NewFunction&: *G);
2631
2632 LazyCallGraph::Node *GN = CG.lookup(F: *G);
2633 EXPECT_TRUE(GN);
2634
2635 I = CG.postorder_ref_scc_begin();
2636 LazyCallGraph::RefSCC *RC = &*I++;
2637 EXPECT_EQ(RC, CG.lookupRefSCC(*GN));
2638 EXPECT_EQ(RC, ORC);
2639 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2640
2641 EXPECT_EQ(1, RC->size());
2642 EXPECT_EQ(CG.lookupSCC(FN), &(*RC)[0]);
2643 EXPECT_EQ(CG.lookupSCC(F2N), &(*RC)[0]);
2644 EXPECT_EQ(CG.lookupSCC(*GN), &(*RC)[0]);
2645}
2646
2647TEST(LazyCallGraphTest, AddSplitFunction8) {
2648 LLVMContext Context;
2649 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: "define void @f() {\n"
2650 " call void @f2()\n"
2651 " ret void\n"
2652 "}\n"
2653 "define void @f2() {\n"
2654 " call void @f()\n"
2655 " ret void\n"
2656 "}\n");
2657 LazyCallGraph CG = buildCG(M&: *M);
2658
2659 Function &F = lookupFunction(M&: *M, Name: "f");
2660 LazyCallGraph::Node &FN = CG.get(F);
2661 Function &F2 = lookupFunction(M&: *M, Name: "f2");
2662 LazyCallGraph::Node &F2N = CG.get(F&: F2);
2663
2664 // Force the graph to be fully expanded.
2665 CG.buildRefSCCs();
2666 auto I = CG.postorder_ref_scc_begin();
2667 LazyCallGraph::RefSCC *ORC = &*I++;
2668 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2669
2670 auto *G = Function::Create(Ty: F.getFunctionType(), Linkage: F.getLinkage(),
2671 AddrSpace: F.getAddressSpace(), N: "g", M: F.getParent());
2672 BasicBlock *GBB = BasicBlock::Create(Context, Name: "", Parent: G);
2673 // Create g -call-> f2.
2674 (void)CallInst::Create(Func: &F2, Args: {}, NameStr: "", InsertAtEnd: GBB);
2675 (void)ReturnInst::Create(C&: Context, InsertAtEnd: GBB);
2676
2677 // Create f -ref-> g.
2678 (void)CastInst::CreatePointerCast(S: G, Ty: PointerType::getUnqual(C&: Context), Name: "",
2679 InsertBefore: &*F.getEntryBlock().begin());
2680
2681 EXPECT_FALSE(verifyModule(*M, &errs()));
2682
2683 CG.addSplitFunction(OriginalFunction&: F, NewFunction&: *G);
2684
2685 LazyCallGraph::Node *GN = CG.lookup(F: *G);
2686 EXPECT_TRUE(GN);
2687
2688 I = CG.postorder_ref_scc_begin();
2689 LazyCallGraph::RefSCC *RC = &*I++;
2690 EXPECT_EQ(RC, CG.lookupRefSCC(*GN));
2691 EXPECT_EQ(RC, ORC);
2692 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2693
2694 EXPECT_EQ(2, RC->size());
2695 EXPECT_EQ(CG.lookupSCC(FN), &(*RC)[0]);
2696 EXPECT_EQ(CG.lookupSCC(F2N), &(*RC)[0]);
2697 EXPECT_EQ(CG.lookupSCC(*GN), &(*RC)[1]);
2698}
2699
2700TEST(LazyCallGraphTest, AddSplitFunction9) {
2701 LLVMContext Context;
2702 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: "define void @f() {\n"
2703 " call void @f2()\n"
2704 " ret void\n"
2705 "}\n"
2706 "define void @f2() {\n"
2707 " call void @f()\n"
2708 " ret void\n"
2709 "}\n");
2710 LazyCallGraph CG = buildCG(M&: *M);
2711
2712 Function &F = lookupFunction(M&: *M, Name: "f");
2713 LazyCallGraph::Node &FN = CG.get(F);
2714 Function &F2 = lookupFunction(M&: *M, Name: "f2");
2715 LazyCallGraph::Node &F2N = CG.get(F&: F2);
2716
2717 // Force the graph to be fully expanded.
2718 CG.buildRefSCCs();
2719 auto I = CG.postorder_ref_scc_begin();
2720 LazyCallGraph::RefSCC *ORC = &*I++;
2721 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2722
2723 auto *G = Function::Create(Ty: F.getFunctionType(), Linkage: F.getLinkage(),
2724 AddrSpace: F.getAddressSpace(), N: "g", M: F.getParent());
2725 BasicBlock *GBB = BasicBlock::Create(Context, Name: "", Parent: G);
2726 // Create g -ref-> f2.
2727 (void)CastInst::CreatePointerCast(S: &F2, Ty: PointerType::getUnqual(C&: Context), Name: "",
2728 InsertAtEnd: GBB);
2729 (void)ReturnInst::Create(C&: Context, InsertAtEnd: GBB);
2730
2731 // Create f -call-> g.
2732 (void)CallInst::Create(Func: G, Args: {}, NameStr: "", InsertBefore: &*F.getEntryBlock().begin());
2733
2734 EXPECT_FALSE(verifyModule(*M, &errs()));
2735
2736 CG.addSplitFunction(OriginalFunction&: F, NewFunction&: *G);
2737
2738 LazyCallGraph::Node *GN = CG.lookup(F: *G);
2739 EXPECT_TRUE(GN);
2740
2741 I = CG.postorder_ref_scc_begin();
2742 LazyCallGraph::RefSCC *RC = &*I++;
2743 EXPECT_EQ(RC, CG.lookupRefSCC(*GN));
2744 EXPECT_EQ(RC, ORC);
2745 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2746
2747 EXPECT_EQ(2, RC->size());
2748 EXPECT_EQ(CG.lookupSCC(*GN), &(*RC)[0]);
2749 EXPECT_EQ(CG.lookupSCC(FN), &(*RC)[1]);
2750 EXPECT_EQ(CG.lookupSCC(F2N), &(*RC)[1]);
2751}
2752
2753TEST(LazyCallGraphTest, AddSplitFunctions1) {
2754 LLVMContext Context;
2755 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: "define void @f() {\n"
2756 " ret void\n"
2757 "}\n");
2758 LazyCallGraph CG = buildCG(M&: *M);
2759
2760 Function &F = lookupFunction(M&: *M, Name: "f");
2761 LazyCallGraph::Node &FN = CG.get(F);
2762
2763 // Force the graph to be fully expanded.
2764 CG.buildRefSCCs();
2765 auto I = CG.postorder_ref_scc_begin();
2766 LazyCallGraph::RefSCC *ORC = &*I++;
2767 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2768
2769 auto *G = Function::Create(Ty: F.getFunctionType(), Linkage: F.getLinkage(),
2770 AddrSpace: F.getAddressSpace(), N: "g", M: F.getParent());
2771 BasicBlock *GBB = BasicBlock::Create(Context, Name: "", Parent: G);
2772 (void)ReturnInst::Create(C&: Context, InsertAtEnd: GBB);
2773
2774 // Create f -ref-> g.
2775 (void)CastInst::CreatePointerCast(S: G, Ty: PointerType::getUnqual(C&: Context), Name: "",
2776 InsertBefore: &*F.getEntryBlock().begin());
2777
2778 EXPECT_FALSE(verifyModule(*M, &errs()));
2779
2780 CG.addSplitRefRecursiveFunctions(OriginalFunction&: F, NewFunctions: SmallVector<Function *, 1>({G}));
2781
2782 LazyCallGraph::Node *GN = CG.lookup(F: *G);
2783 EXPECT_TRUE(GN);
2784
2785 I = CG.postorder_ref_scc_begin();
2786 LazyCallGraph::RefSCC *RC1 = &*I++;
2787 EXPECT_EQ(RC1, CG.lookupRefSCC(*GN));
2788 LazyCallGraph::RefSCC *RC2 = &*I++;
2789 EXPECT_EQ(RC2, ORC);
2790 EXPECT_EQ(RC2, CG.lookupRefSCC(FN));
2791 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2792}
2793
2794TEST(LazyCallGraphTest, AddSplitFunctions2) {
2795 LLVMContext Context;
2796 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: "define void @f() {\n"
2797 " ret void\n"
2798 "}\n");
2799 LazyCallGraph CG = buildCG(M&: *M);
2800
2801 Function &F = lookupFunction(M&: *M, Name: "f");
2802 LazyCallGraph::Node &FN = CG.get(F);
2803
2804 // Force the graph to be fully expanded.
2805 CG.buildRefSCCs();
2806 auto I = CG.postorder_ref_scc_begin();
2807 LazyCallGraph::RefSCC *ORC = &*I++;
2808 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2809
2810 auto *G = Function::Create(Ty: F.getFunctionType(), Linkage: F.getLinkage(),
2811 AddrSpace: F.getAddressSpace(), N: "g", M: F.getParent());
2812 BasicBlock *GBB = BasicBlock::Create(Context, Name: "", Parent: G);
2813 // Create g -ref-> f.
2814 (void)CastInst::CreatePointerCast(S: &F, Ty: PointerType::getUnqual(C&: Context), Name: "",
2815 InsertAtEnd: GBB);
2816 (void)ReturnInst::Create(C&: Context, InsertAtEnd: GBB);
2817
2818 // Create f -ref-> g.
2819 (void)CastInst::CreatePointerCast(S: G, Ty: PointerType::getUnqual(C&: Context), Name: "",
2820 InsertBefore: &*F.getEntryBlock().begin());
2821
2822 EXPECT_FALSE(verifyModule(*M, &errs()));
2823
2824 CG.addSplitRefRecursiveFunctions(OriginalFunction&: F, NewFunctions: SmallVector<Function *, 1>({G}));
2825
2826 LazyCallGraph::Node *GN = CG.lookup(F: *G);
2827 EXPECT_TRUE(GN);
2828
2829 I = CG.postorder_ref_scc_begin();
2830 LazyCallGraph::RefSCC *RC = &*I++;
2831 EXPECT_EQ(RC, CG.lookupRefSCC(*GN));
2832 EXPECT_EQ(RC, ORC);
2833 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2834
2835 // Order doesn't matter for sibling SCCs.
2836 EXPECT_EQ(2, RC->size());
2837 EXPECT_EQ(&CG.lookupSCC(*GN)->getOuterRefSCC(), RC);
2838 EXPECT_EQ(&CG.lookupSCC(FN)->getOuterRefSCC(), RC);
2839}
2840
2841TEST(LazyCallGraphTest, AddSplitFunctions3) {
2842 LLVMContext Context;
2843 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: "define void @f() {\n"
2844 " ret void\n"
2845 "}\n");
2846 LazyCallGraph CG = buildCG(M&: *M);
2847
2848 Function &F = lookupFunction(M&: *M, Name: "f");
2849 LazyCallGraph::Node &FN = CG.get(F);
2850
2851 // Force the graph to be fully expanded.
2852 CG.buildRefSCCs();
2853 auto I = CG.postorder_ref_scc_begin();
2854 LazyCallGraph::RefSCC *ORC = &*I++;
2855 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2856
2857 auto *G1 = Function::Create(Ty: F.getFunctionType(), Linkage: F.getLinkage(),
2858 AddrSpace: F.getAddressSpace(), N: "g1", M: F.getParent());
2859 auto *G2 = Function::Create(Ty: F.getFunctionType(), Linkage: F.getLinkage(),
2860 AddrSpace: F.getAddressSpace(), N: "g2", M: F.getParent());
2861 BasicBlock *G1BB = BasicBlock::Create(Context, Name: "", Parent: G1);
2862 BasicBlock *G2BB = BasicBlock::Create(Context, Name: "", Parent: G2);
2863 // Create g1 -ref-> g2 and g2 -ref-> g1.
2864 (void)CastInst::CreatePointerCast(S: G2, Ty: PointerType::getUnqual(C&: Context), Name: "",
2865 InsertAtEnd: G1BB);
2866 (void)CastInst::CreatePointerCast(S: G1, Ty: PointerType::getUnqual(C&: Context), Name: "",
2867 InsertAtEnd: G2BB);
2868 (void)ReturnInst::Create(C&: Context, InsertAtEnd: G1BB);
2869 (void)ReturnInst::Create(C&: Context, InsertAtEnd: G2BB);
2870
2871 // Create f -ref-> g1 and f -ref-> g2.
2872 (void)CastInst::CreatePointerCast(S: G1, Ty: PointerType::getUnqual(C&: Context), Name: "",
2873 InsertBefore: &*F.getEntryBlock().begin());
2874 (void)CastInst::CreatePointerCast(S: G2, Ty: PointerType::getUnqual(C&: Context), Name: "",
2875 InsertBefore: &*F.getEntryBlock().begin());
2876
2877 EXPECT_FALSE(verifyModule(*M, &errs()));
2878
2879 CG.addSplitRefRecursiveFunctions(OriginalFunction&: F, NewFunctions: SmallVector<Function *, 1>({G1, G2}));
2880
2881 LazyCallGraph::Node *G1N = CG.lookup(F: *G1);
2882 EXPECT_TRUE(G1N);
2883 LazyCallGraph::Node *G2N = CG.lookup(F: *G2);
2884 EXPECT_TRUE(G2N);
2885
2886 I = CG.postorder_ref_scc_begin();
2887 LazyCallGraph::RefSCC *RC1 = &*I++;
2888 EXPECT_EQ(2, RC1->size());
2889 EXPECT_EQ(RC1, CG.lookupRefSCC(*G1N));
2890 EXPECT_EQ(RC1, CG.lookupRefSCC(*G2N));
2891 LazyCallGraph::RefSCC *RC2 = &*I++;
2892 EXPECT_EQ(RC2, ORC);
2893 EXPECT_EQ(RC2, CG.lookupRefSCC(FN));
2894 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2895}
2896
2897TEST(LazyCallGraphTest, AddSplitFunctions4) {
2898 LLVMContext Context;
2899 std::unique_ptr<Module> M = parseAssembly(Context, Assembly: "define void @f() {\n"
2900 " ret void\n"
2901 "}\n");
2902 LazyCallGraph CG = buildCG(M&: *M);
2903
2904 Function &F = lookupFunction(M&: *M, Name: "f");
2905 LazyCallGraph::Node &FN = CG.get(F);
2906
2907 // Force the graph to be fully expanded.
2908 CG.buildRefSCCs();
2909 auto I = CG.postorder_ref_scc_begin();
2910 LazyCallGraph::RefSCC *ORC = &*I++;
2911 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2912
2913 auto *G1 = Function::Create(Ty: F.getFunctionType(), Linkage: F.getLinkage(),
2914 AddrSpace: F.getAddressSpace(), N: "g1", M: F.getParent());
2915 auto *G2 = Function::Create(Ty: F.getFunctionType(), Linkage: F.getLinkage(),
2916 AddrSpace: F.getAddressSpace(), N: "g2", M: F.getParent());
2917 BasicBlock *G1BB = BasicBlock::Create(Context, Name: "", Parent: G1);
2918 BasicBlock *G2BB = BasicBlock::Create(Context, Name: "", Parent: G2);
2919 // Create g1 -ref-> g2 and g2 -ref-> g1.
2920 (void)CastInst::CreatePointerCast(S: G2, Ty: PointerType::getUnqual(C&: Context), Name: "",
2921 InsertAtEnd: G1BB);
2922 (void)CastInst::CreatePointerCast(S: G1, Ty: PointerType::getUnqual(C&: Context), Name: "",
2923 InsertAtEnd: G2BB);
2924 // Create g2 -ref-> f.
2925 (void)CastInst::CreatePointerCast(S: &F, Ty: PointerType::getUnqual(C&: Context), Name: "",
2926 InsertAtEnd: G2BB);
2927 (void)ReturnInst::Create(C&: Context, InsertAtEnd: G1BB);
2928 (void)ReturnInst::Create(C&: Context, InsertAtEnd: G2BB);
2929
2930 // Create f -ref-> g1 and f -ref-> g2.
2931 (void)CastInst::CreatePointerCast(S: G1, Ty: PointerType::getUnqual(C&: Context), Name: "",
2932 InsertBefore: &*F.getEntryBlock().begin());
2933 (void)CastInst::CreatePointerCast(S: G2, Ty: PointerType::getUnqual(C&: Context), Name: "",
2934 InsertBefore: &*F.getEntryBlock().begin());
2935
2936 EXPECT_FALSE(verifyModule(*M, &errs()));
2937
2938 CG.addSplitRefRecursiveFunctions(OriginalFunction&: F, NewFunctions: SmallVector<Function *, 1>({G1, G2}));
2939
2940 LazyCallGraph::Node *G1N = CG.lookup(F: *G1);
2941 EXPECT_TRUE(G1N);
2942 LazyCallGraph::Node *G2N = CG.lookup(F: *G2);
2943 EXPECT_TRUE(G2N);
2944
2945 I = CG.postorder_ref_scc_begin();
2946 LazyCallGraph::RefSCC *RC = &*I++;
2947 EXPECT_EQ(RC, ORC);
2948 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2949
2950 // Order doesn't matter for sibling SCCs.
2951 EXPECT_EQ(3, RC->size());
2952 EXPECT_EQ(&CG.lookupSCC(FN)->getOuterRefSCC(), RC);
2953 EXPECT_EQ(&CG.lookupSCC(*G1N)->getOuterRefSCC(), RC);
2954 EXPECT_EQ(&CG.lookupSCC(*G2N)->getOuterRefSCC(), RC);
2955 EXPECT_EQ(RC, CG.lookupRefSCC(*G1N));
2956 EXPECT_EQ(RC, CG.lookupRefSCC(*G2N));
2957}
2958
2959TEST(LazyCallGraphTest, AddSplitFunctions5) {
2960 LLVMContext Context;
2961 std::unique_ptr<Module> M =
2962 parseAssembly(Context, Assembly: "define void @f() {\n"
2963 " %1 = bitcast void ()* @f2 to i8*\n"
2964 " ret void\n"
2965 "}\n"
2966 "define void @f2() {\n"
2967 " call void @f()\n"
2968 " ret void\n"
2969 "}\n");
2970 LazyCallGraph CG = buildCG(M&: *M);
2971
2972 Function &F = lookupFunction(M&: *M, Name: "f");
2973 LazyCallGraph::Node &FN = CG.get(F);
2974 Function &F2 = lookupFunction(M&: *M, Name: "f2");
2975 LazyCallGraph::Node &F2N = CG.get(F);
2976
2977 // Force the graph to be fully expanded.
2978 CG.buildRefSCCs();
2979 auto I = CG.postorder_ref_scc_begin();
2980 LazyCallGraph::RefSCC *ORC = &*I++;
2981 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2982
2983 auto *G1 = Function::Create(Ty: F.getFunctionType(), Linkage: F.getLinkage(),
2984 AddrSpace: F.getAddressSpace(), N: "g1", M: F.getParent());
2985 auto *G2 = Function::Create(Ty: F.getFunctionType(), Linkage: F.getLinkage(),
2986 AddrSpace: F.getAddressSpace(), N: "g2", M: F.getParent());
2987 BasicBlock *G1BB = BasicBlock::Create(Context, Name: "", Parent: G1);
2988 BasicBlock *G2BB = BasicBlock::Create(Context, Name: "", Parent: G2);
2989 // Create g1 -ref-> g2 and g2 -ref-> g1.
2990 (void)CastInst::CreatePointerCast(S: G2, Ty: PointerType::getUnqual(C&: Context), Name: "",
2991 InsertAtEnd: G1BB);
2992 (void)CastInst::CreatePointerCast(S: G1, Ty: PointerType::getUnqual(C&: Context), Name: "",
2993 InsertAtEnd: G2BB);
2994 // Create g2 -ref-> f2.
2995 (void)CastInst::CreatePointerCast(S: &F2, Ty: PointerType::getUnqual(C&: Context), Name: "",
2996 InsertAtEnd: G2BB);
2997 (void)ReturnInst::Create(C&: Context, InsertAtEnd: G1BB);
2998 (void)ReturnInst::Create(C&: Context, InsertAtEnd: G2BB);
2999
3000 // Create f -ref-> g1 and f -ref-> g2.
3001 (void)CastInst::CreatePointerCast(S: G1, Ty: PointerType::getUnqual(C&: Context), Name: "",
3002 InsertBefore: &*F.getEntryBlock().begin());
3003 (void)CastInst::CreatePointerCast(S: G2, Ty: PointerType::getUnqual(C&: Context), Name: "",
3004 InsertBefore: &*F.getEntryBlock().begin());
3005
3006 EXPECT_FALSE(verifyModule(*M, &errs()));
3007
3008 CG.addSplitRefRecursiveFunctions(OriginalFunction&: F, NewFunctions: SmallVector<Function *, 1>({G1, G2}));
3009
3010 LazyCallGraph::Node *G1N = CG.lookup(F: *G1);
3011 EXPECT_TRUE(G1N);
3012 LazyCallGraph::Node *G2N = CG.lookup(F: *G2);
3013 EXPECT_TRUE(G2N);
3014
3015 I = CG.postorder_ref_scc_begin();
3016 LazyCallGraph::RefSCC *RC = &*I++;
3017 EXPECT_EQ(4, RC->size());
3018 EXPECT_EQ(RC, ORC);
3019 EXPECT_EQ(RC, CG.lookupRefSCC(*G1N));
3020 EXPECT_EQ(RC, CG.lookupRefSCC(*G2N));
3021 EXPECT_EQ(RC, CG.lookupRefSCC(FN));
3022 EXPECT_EQ(RC, CG.lookupRefSCC(F2N));
3023 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
3024}
3025}
3026

source code of llvm/unittests/Analysis/LazyCallGraphTest.cpp