[LCG] Add some basic methods for querying the parent/child relationships
[oota-llvm.git] / unittests / Analysis / LazyCallGraphTest.cpp
1 //===- LazyCallGraphTest.cpp - Unit tests for the lazy CG analysis --------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/Analysis/LazyCallGraph.h"
11 #include "llvm/AsmParser/Parser.h"
12 #include "llvm/IR/Function.h"
13 #include "llvm/IR/LLVMContext.h"
14 #include "llvm/IR/Module.h"
15 #include "llvm/Support/ErrorHandling.h"
16 #include "llvm/Support/SourceMgr.h"
17 #include "gtest/gtest.h"
18 #include <memory>
19
20 using namespace llvm;
21
22 namespace {
23
24 std::unique_ptr<Module> parseAssembly(const char *Assembly) {
25   auto M = make_unique<Module>("Module", getGlobalContext());
26
27   SMDiagnostic Error;
28   bool Parsed =
29       ParseAssemblyString(Assembly, M.get(), Error, M->getContext()) == M.get();
30
31   std::string ErrMsg;
32   raw_string_ostream OS(ErrMsg);
33   Error.print("", OS);
34
35   // A failure here means that the test itself is buggy.
36   if (!Parsed)
37     report_fatal_error(OS.str().c_str());
38
39   return M;
40 }
41
42 // IR forming a call graph with a diamond of triangle-shaped SCCs:
43 //
44 //         d1       |
45 //        /  \      |
46 //       d3--d2     |
47 //      /     \     |
48 //     b1     c1    |
49 //   /  \    /  \   |
50 //  b3--b2  c3--c2  |
51 //       \  /       |
52 //        a1        |
53 //       /  \       |
54 //      a3--a2      |
55 //
56 // All call edges go up between SCCs, and clockwise around the SCC.
57 static const char DiamondOfTriangles[] =
58      "define void @a1() {\n"
59      "entry:\n"
60      "  call void @a2()\n"
61      "  call void @b2()\n"
62      "  call void @c3()\n"
63      "  ret void\n"
64      "}\n"
65      "define void @a2() {\n"
66      "entry:\n"
67      "  call void @a3()\n"
68      "  ret void\n"
69      "}\n"
70      "define void @a3() {\n"
71      "entry:\n"
72      "  call void @a1()\n"
73      "  ret void\n"
74      "}\n"
75      "define void @b1() {\n"
76      "entry:\n"
77      "  call void @b2()\n"
78      "  call void @d3()\n"
79      "  ret void\n"
80      "}\n"
81      "define void @b2() {\n"
82      "entry:\n"
83      "  call void @b3()\n"
84      "  ret void\n"
85      "}\n"
86      "define void @b3() {\n"
87      "entry:\n"
88      "  call void @b1()\n"
89      "  ret void\n"
90      "}\n"
91      "define void @c1() {\n"
92      "entry:\n"
93      "  call void @c2()\n"
94      "  call void @d2()\n"
95      "  ret void\n"
96      "}\n"
97      "define void @c2() {\n"
98      "entry:\n"
99      "  call void @c3()\n"
100      "  ret void\n"
101      "}\n"
102      "define void @c3() {\n"
103      "entry:\n"
104      "  call void @c1()\n"
105      "  ret void\n"
106      "}\n"
107      "define void @d1() {\n"
108      "entry:\n"
109      "  call void @d2()\n"
110      "  ret void\n"
111      "}\n"
112      "define void @d2() {\n"
113      "entry:\n"
114      "  call void @d3()\n"
115      "  ret void\n"
116      "}\n"
117      "define void @d3() {\n"
118      "entry:\n"
119      "  call void @d1()\n"
120      "  ret void\n"
121      "}\n";
122
123 TEST(LazyCallGraphTest, BasicGraphFormation) {
124   std::unique_ptr<Module> M = parseAssembly(DiamondOfTriangles);
125   LazyCallGraph CG(*M);
126
127   // The order of the entry nodes should be stable w.r.t. the source order of
128   // the IR, and everything in our module is an entry node, so just directly
129   // build variables for each node.
130   auto I = CG.begin();
131   LazyCallGraph::Node &A1 = *I++;
132   EXPECT_EQ("a1", A1.getFunction().getName());
133   LazyCallGraph::Node &A2 = *I++;
134   EXPECT_EQ("a2", A2.getFunction().getName());
135   LazyCallGraph::Node &A3 = *I++;
136   EXPECT_EQ("a3", A3.getFunction().getName());
137   LazyCallGraph::Node &B1 = *I++;
138   EXPECT_EQ("b1", B1.getFunction().getName());
139   LazyCallGraph::Node &B2 = *I++;
140   EXPECT_EQ("b2", B2.getFunction().getName());
141   LazyCallGraph::Node &B3 = *I++;
142   EXPECT_EQ("b3", B3.getFunction().getName());
143   LazyCallGraph::Node &C1 = *I++;
144   EXPECT_EQ("c1", C1.getFunction().getName());
145   LazyCallGraph::Node &C2 = *I++;
146   EXPECT_EQ("c2", C2.getFunction().getName());
147   LazyCallGraph::Node &C3 = *I++;
148   EXPECT_EQ("c3", C3.getFunction().getName());
149   LazyCallGraph::Node &D1 = *I++;
150   EXPECT_EQ("d1", D1.getFunction().getName());
151   LazyCallGraph::Node &D2 = *I++;
152   EXPECT_EQ("d2", D2.getFunction().getName());
153   LazyCallGraph::Node &D3 = *I++;
154   EXPECT_EQ("d3", D3.getFunction().getName());
155   EXPECT_EQ(CG.end(), I);
156
157   // Build vectors and sort them for the rest of the assertions to make them
158   // independent of order.
159   std::vector<std::string> Nodes;
160
161   for (LazyCallGraph::Node &N : A1)
162     Nodes.push_back(N.getFunction().getName());
163   std::sort(Nodes.begin(), Nodes.end());
164   EXPECT_EQ("a2", Nodes[0]);
165   EXPECT_EQ("b2", Nodes[1]);
166   EXPECT_EQ("c3", Nodes[2]);
167   Nodes.clear();
168
169   EXPECT_EQ(A2.end(), std::next(A2.begin()));
170   EXPECT_EQ("a3", A2.begin()->getFunction().getName());
171   EXPECT_EQ(A3.end(), std::next(A3.begin()));
172   EXPECT_EQ("a1", A3.begin()->getFunction().getName());
173
174   for (LazyCallGraph::Node &N : B1)
175     Nodes.push_back(N.getFunction().getName());
176   std::sort(Nodes.begin(), Nodes.end());
177   EXPECT_EQ("b2", Nodes[0]);
178   EXPECT_EQ("d3", Nodes[1]);
179   Nodes.clear();
180
181   EXPECT_EQ(B2.end(), std::next(B2.begin()));
182   EXPECT_EQ("b3", B2.begin()->getFunction().getName());
183   EXPECT_EQ(B3.end(), std::next(B3.begin()));
184   EXPECT_EQ("b1", B3.begin()->getFunction().getName());
185
186   for (LazyCallGraph::Node &N : C1)
187     Nodes.push_back(N.getFunction().getName());
188   std::sort(Nodes.begin(), Nodes.end());
189   EXPECT_EQ("c2", Nodes[0]);
190   EXPECT_EQ("d2", Nodes[1]);
191   Nodes.clear();
192
193   EXPECT_EQ(C2.end(), std::next(C2.begin()));
194   EXPECT_EQ("c3", C2.begin()->getFunction().getName());
195   EXPECT_EQ(C3.end(), std::next(C3.begin()));
196   EXPECT_EQ("c1", C3.begin()->getFunction().getName());
197
198   EXPECT_EQ(D1.end(), std::next(D1.begin()));
199   EXPECT_EQ("d2", D1.begin()->getFunction().getName());
200   EXPECT_EQ(D2.end(), std::next(D2.begin()));
201   EXPECT_EQ("d3", D2.begin()->getFunction().getName());
202   EXPECT_EQ(D3.end(), std::next(D3.begin()));
203   EXPECT_EQ("d1", D3.begin()->getFunction().getName());
204
205   // Now lets look at the SCCs.
206   auto SCCI = CG.postorder_scc_begin();
207
208   LazyCallGraph::SCC &D = *SCCI++;
209   for (LazyCallGraph::Node *N : D)
210     Nodes.push_back(N->getFunction().getName());
211   std::sort(Nodes.begin(), Nodes.end());
212   EXPECT_EQ(3u, Nodes.size());
213   EXPECT_EQ("d1", Nodes[0]);
214   EXPECT_EQ("d2", Nodes[1]);
215   EXPECT_EQ("d3", Nodes[2]);
216   Nodes.clear();
217   EXPECT_FALSE(D.isParentOf(D));
218   EXPECT_FALSE(D.isChildOf(D));
219   EXPECT_FALSE(D.isAncestorOf(D));
220   EXPECT_FALSE(D.isDescendantOf(D));
221
222   LazyCallGraph::SCC &C = *SCCI++;
223   for (LazyCallGraph::Node *N : C)
224     Nodes.push_back(N->getFunction().getName());
225   std::sort(Nodes.begin(), Nodes.end());
226   EXPECT_EQ(3u, Nodes.size());
227   EXPECT_EQ("c1", Nodes[0]);
228   EXPECT_EQ("c2", Nodes[1]);
229   EXPECT_EQ("c3", Nodes[2]);
230   Nodes.clear();
231   EXPECT_TRUE(C.isParentOf(D));
232   EXPECT_FALSE(C.isChildOf(D));
233   EXPECT_TRUE(C.isAncestorOf(D));
234   EXPECT_FALSE(C.isDescendantOf(D));
235
236   LazyCallGraph::SCC &B = *SCCI++;
237   for (LazyCallGraph::Node *N : B)
238     Nodes.push_back(N->getFunction().getName());
239   std::sort(Nodes.begin(), Nodes.end());
240   EXPECT_EQ(3u, Nodes.size());
241   EXPECT_EQ("b1", Nodes[0]);
242   EXPECT_EQ("b2", Nodes[1]);
243   EXPECT_EQ("b3", Nodes[2]);
244   Nodes.clear();
245   EXPECT_TRUE(B.isParentOf(D));
246   EXPECT_FALSE(B.isChildOf(D));
247   EXPECT_TRUE(B.isAncestorOf(D));
248   EXPECT_FALSE(B.isDescendantOf(D));
249   EXPECT_FALSE(B.isAncestorOf(C));
250   EXPECT_FALSE(C.isAncestorOf(B));
251
252   LazyCallGraph::SCC &A = *SCCI++;
253   for (LazyCallGraph::Node *N : A)
254     Nodes.push_back(N->getFunction().getName());
255   std::sort(Nodes.begin(), Nodes.end());
256   EXPECT_EQ(3u, Nodes.size());
257   EXPECT_EQ("a1", Nodes[0]);
258   EXPECT_EQ("a2", Nodes[1]);
259   EXPECT_EQ("a3", Nodes[2]);
260   Nodes.clear();
261   EXPECT_TRUE(A.isParentOf(B));
262   EXPECT_TRUE(A.isParentOf(C));
263   EXPECT_FALSE(A.isParentOf(D));
264   EXPECT_TRUE(A.isAncestorOf(B));
265   EXPECT_TRUE(A.isAncestorOf(C));
266   EXPECT_TRUE(A.isAncestorOf(D));
267
268   EXPECT_EQ(CG.postorder_scc_end(), SCCI);
269 }
270
271 static Function &lookupFunction(Module &M, StringRef Name) {
272   for (Function &F : M)
273     if (F.getName() == Name)
274       return F;
275   report_fatal_error("Couldn't find function!");
276 }
277
278 TEST(LazyCallGraphTest, BasicGraphMutation) {
279   std::unique_ptr<Module> M = parseAssembly(
280       "define void @a() {\n"
281       "entry:\n"
282       "  call void @b()\n"
283       "  call void @c()\n"
284       "  ret void\n"
285       "}\n"
286       "define void @b() {\n"
287       "entry:\n"
288       "  ret void\n"
289       "}\n"
290       "define void @c() {\n"
291       "entry:\n"
292       "  ret void\n"
293       "}\n");
294   LazyCallGraph CG(*M);
295
296   LazyCallGraph::Node &A = CG.get(lookupFunction(*M, "a"));
297   LazyCallGraph::Node &B = CG.get(lookupFunction(*M, "b"));
298   EXPECT_EQ(2, std::distance(A.begin(), A.end()));
299   EXPECT_EQ(0, std::distance(B.begin(), B.end()));
300
301   CG.insertEdge(B, lookupFunction(*M, "c"));
302   EXPECT_EQ(1, std::distance(B.begin(), B.end()));
303   LazyCallGraph::Node &C = *B.begin();
304   EXPECT_EQ(0, std::distance(C.begin(), C.end()));
305
306   CG.insertEdge(C, B.getFunction());
307   EXPECT_EQ(1, std::distance(C.begin(), C.end()));
308   EXPECT_EQ(&B, &*C.begin());
309
310   CG.insertEdge(C, C.getFunction());
311   EXPECT_EQ(2, std::distance(C.begin(), C.end()));
312   EXPECT_EQ(&B, &*C.begin());
313   EXPECT_EQ(&C, &*std::next(C.begin()));
314
315   CG.removeEdge(C, B.getFunction());
316   EXPECT_EQ(1, std::distance(C.begin(), C.end()));
317   EXPECT_EQ(&C, &*C.begin());
318
319   CG.removeEdge(C, C.getFunction());
320   EXPECT_EQ(0, std::distance(C.begin(), C.end()));
321
322   CG.removeEdge(B, C.getFunction());
323   EXPECT_EQ(0, std::distance(B.begin(), B.end()));
324 }
325
326 TEST(LazyCallGraphTest, MultiArmSCC) {
327   // Two interlocking cycles. The really useful thing about this SCC is that it
328   // will require Tarjan's DFS to backtrack and finish processing all of the
329   // children of each node in the SCC.
330   std::unique_ptr<Module> M = parseAssembly(
331       "define void @a() {\n"
332       "entry:\n"
333       "  call void @b()\n"
334       "  call void @d()\n"
335       "  ret void\n"
336       "}\n"
337       "define void @b() {\n"
338       "entry:\n"
339       "  call void @c()\n"
340       "  ret void\n"
341       "}\n"
342       "define void @c() {\n"
343       "entry:\n"
344       "  call void @a()\n"
345       "  ret void\n"
346       "}\n"
347       "define void @d() {\n"
348       "entry:\n"
349       "  call void @e()\n"
350       "  ret void\n"
351       "}\n"
352       "define void @e() {\n"
353       "entry:\n"
354       "  call void @a()\n"
355       "  ret void\n"
356       "}\n");
357   LazyCallGraph CG(*M);
358
359   // Force the graph to be fully expanded.
360   auto SCCI = CG.postorder_scc_begin();
361   LazyCallGraph::SCC &SCC = *SCCI++;
362   EXPECT_EQ(CG.postorder_scc_end(), SCCI);
363
364   LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
365   LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
366   LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
367   LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
368   LazyCallGraph::Node &E = *CG.lookup(lookupFunction(*M, "e"));
369   EXPECT_EQ(&SCC, CG.lookupSCC(A));
370   EXPECT_EQ(&SCC, CG.lookupSCC(B));
371   EXPECT_EQ(&SCC, CG.lookupSCC(C));
372   EXPECT_EQ(&SCC, CG.lookupSCC(D));
373   EXPECT_EQ(&SCC, CG.lookupSCC(E));
374 }
375
376 TEST(LazyCallGraphTest, InterSCCEdgeRemoval) {
377   std::unique_ptr<Module> M = parseAssembly(
378       "define void @a() {\n"
379       "entry:\n"
380       "  call void @b()\n"
381       "  ret void\n"
382       "}\n"
383       "define void @b() {\n"
384       "entry:\n"
385       "  ret void\n"
386       "}\n");
387   LazyCallGraph CG(*M);
388
389   // Force the graph to be fully expanded.
390   for (LazyCallGraph::SCC &C : CG.postorder_sccs())
391     (void)C;
392
393   LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
394   LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
395   LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
396   LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
397
398   EXPECT_EQ("b", A.begin()->getFunction().getName());
399   EXPECT_EQ(B.end(), B.begin());
400   EXPECT_EQ(&AC, &*BC.parent_begin());
401
402   AC.removeInterSCCEdge(A, B);
403
404   EXPECT_EQ(A.end(), A.begin());
405   EXPECT_EQ(B.end(), B.begin());
406   EXPECT_EQ(BC.parent_end(), BC.parent_begin());
407 }
408
409 TEST(LazyCallGraphTest, IntraSCCEdgeInsertion) {
410   std::unique_ptr<Module> M1 = parseAssembly(
411       "define void @a() {\n"
412       "entry:\n"
413       "  call void @b()\n"
414       "  ret void\n"
415       "}\n"
416       "define void @b() {\n"
417       "entry:\n"
418       "  call void @c()\n"
419       "  ret void\n"
420       "}\n"
421       "define void @c() {\n"
422       "entry:\n"
423       "  call void @a()\n"
424       "  ret void\n"
425       "}\n");
426   LazyCallGraph CG1(*M1);
427
428   // Force the graph to be fully expanded.
429   auto SCCI = CG1.postorder_scc_begin();
430   LazyCallGraph::SCC &SCC = *SCCI++;
431   EXPECT_EQ(CG1.postorder_scc_end(), SCCI);
432
433   LazyCallGraph::Node &A = *CG1.lookup(lookupFunction(*M1, "a"));
434   LazyCallGraph::Node &B = *CG1.lookup(lookupFunction(*M1, "b"));
435   LazyCallGraph::Node &C = *CG1.lookup(lookupFunction(*M1, "c"));
436   EXPECT_EQ(&SCC, CG1.lookupSCC(A));
437   EXPECT_EQ(&SCC, CG1.lookupSCC(B));
438   EXPECT_EQ(&SCC, CG1.lookupSCC(C));
439
440   // Insert an edge from 'a' to 'c'. Nothing changes about the SCCs.
441   SCC.insertIntraSCCEdge(A, C);
442   EXPECT_EQ(2, std::distance(A.begin(), A.end()));
443   EXPECT_EQ(&SCC, CG1.lookupSCC(A));
444   EXPECT_EQ(&SCC, CG1.lookupSCC(B));
445   EXPECT_EQ(&SCC, CG1.lookupSCC(C));
446
447   // Insert a self edge from 'a' back to 'a'.
448   SCC.insertIntraSCCEdge(A, A);
449   EXPECT_EQ(3, std::distance(A.begin(), A.end()));
450   EXPECT_EQ(&SCC, CG1.lookupSCC(A));
451   EXPECT_EQ(&SCC, CG1.lookupSCC(B));
452   EXPECT_EQ(&SCC, CG1.lookupSCC(C));
453 }
454
455 TEST(LazyCallGraphTest, IntraSCCEdgeRemoval) {
456   // A nice fully connected (including self-edges) SCC.
457   std::unique_ptr<Module> M1 = parseAssembly(
458       "define void @a() {\n"
459       "entry:\n"
460       "  call void @a()\n"
461       "  call void @b()\n"
462       "  call void @c()\n"
463       "  ret void\n"
464       "}\n"
465       "define void @b() {\n"
466       "entry:\n"
467       "  call void @a()\n"
468       "  call void @b()\n"
469       "  call void @c()\n"
470       "  ret void\n"
471       "}\n"
472       "define void @c() {\n"
473       "entry:\n"
474       "  call void @a()\n"
475       "  call void @b()\n"
476       "  call void @c()\n"
477       "  ret void\n"
478       "}\n");
479   LazyCallGraph CG1(*M1);
480
481   // Force the graph to be fully expanded.
482   auto SCCI = CG1.postorder_scc_begin();
483   LazyCallGraph::SCC &SCC = *SCCI++;
484   EXPECT_EQ(CG1.postorder_scc_end(), SCCI);
485
486   LazyCallGraph::Node &A = *CG1.lookup(lookupFunction(*M1, "a"));
487   LazyCallGraph::Node &B = *CG1.lookup(lookupFunction(*M1, "b"));
488   LazyCallGraph::Node &C = *CG1.lookup(lookupFunction(*M1, "c"));
489   EXPECT_EQ(&SCC, CG1.lookupSCC(A));
490   EXPECT_EQ(&SCC, CG1.lookupSCC(B));
491   EXPECT_EQ(&SCC, CG1.lookupSCC(C));
492
493   // Remove the edge from b -> a, which should leave the 3 functions still in
494   // a single connected component because of a -> b -> c -> a.
495   SmallVector<LazyCallGraph::SCC *, 1> NewSCCs = SCC.removeIntraSCCEdge(B, A);
496   EXPECT_EQ(0u, NewSCCs.size());
497   EXPECT_EQ(&SCC, CG1.lookupSCC(A));
498   EXPECT_EQ(&SCC, CG1.lookupSCC(B));
499   EXPECT_EQ(&SCC, CG1.lookupSCC(C));
500
501   // Remove the edge from c -> a, which should leave 'a' in the original SCC
502   // and form a new SCC for 'b' and 'c'.
503   NewSCCs = SCC.removeIntraSCCEdge(C, A);
504   EXPECT_EQ(1u, NewSCCs.size());
505   EXPECT_EQ(&SCC, CG1.lookupSCC(A));
506   EXPECT_EQ(1, std::distance(SCC.begin(), SCC.end()));
507   LazyCallGraph::SCC *SCC2 = CG1.lookupSCC(B);
508   EXPECT_EQ(SCC2, CG1.lookupSCC(C));
509   EXPECT_EQ(SCC2, NewSCCs[0]);
510 }
511
512 }