blob: 0ac9b6554c25c13ad83cfb23ccf4066f6095135c [file] [log] [blame]
Chandler Carruthc7bad9a2014-04-23 08:08:49 +00001//===- 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
20using namespace llvm;
21
22namespace {
23
Mehdi Amini03b42e42016-04-14 21:59:01 +000024std::unique_ptr<Module> parseAssembly(LLVMContext &Context,
25 const char *Assembly) {
Chandler Carruthc7bad9a2014-04-23 08:08:49 +000026 SMDiagnostic Error;
Mehdi Amini03b42e42016-04-14 21:59:01 +000027 std::unique_ptr<Module> M = parseAssemblyString(Assembly, Error, Context);
Chandler Carruthc7bad9a2014-04-23 08:08:49 +000028
29 std::string ErrMsg;
30 raw_string_ostream OS(ErrMsg);
31 Error.print("", OS);
32
33 // A failure here means that the test itself is buggy.
Rafael Espindola11c07d72014-08-19 16:58:54 +000034 if (!M)
Chandler Carruthc7bad9a2014-04-23 08:08:49 +000035 report_fatal_error(OS.str().c_str());
36
37 return M;
38}
39
Filipe Cabecinhas39545662014-10-22 02:16:06 +000040/*
41 IR forming a call graph with a diamond of triangle-shaped SCCs:
42
43 d1
44 / \
45 d3--d2
46 / \
47 b1 c1
48 / \ / \
49 b3--b2 c3--c2
50 \ /
51 a1
52 / \
53 a3--a2
54
55 All call edges go up between SCCs, and clockwise around the SCC.
56 */
Chandler Carruthc7bad9a2014-04-23 08:08:49 +000057static 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
Chandler Carruth49d728a2016-09-16 10:20:17 +0000123/*
124 IR forming a reference graph with a diamond of triangle-shaped RefSCCs
125
126 d1
127 / \
128 d3--d2
129 / \
130 b1 c1
131 / \ / \
132 b3--b2 c3--c2
133 \ /
134 a1
135 / \
136 a3--a2
137
138 All call edges go up between RefSCCs, and clockwise around the RefSCC.
139 */
140static const char DiamondOfTrianglesRefGraph[] =
141 "define void @a1() {\n"
142 "entry:\n"
143 " %a = alloca void ()*\n"
144 " store void ()* @a2, void ()** %a\n"
145 " store void ()* @b2, void ()** %a\n"
146 " store void ()* @c3, void ()** %a\n"
147 " ret void\n"
148 "}\n"
149 "define void @a2() {\n"
150 "entry:\n"
151 " %a = alloca void ()*\n"
152 " store void ()* @a3, void ()** %a\n"
153 " ret void\n"
154 "}\n"
155 "define void @a3() {\n"
156 "entry:\n"
157 " %a = alloca void ()*\n"
158 " store void ()* @a1, void ()** %a\n"
159 " ret void\n"
160 "}\n"
161 "define void @b1() {\n"
162 "entry:\n"
163 " %a = alloca void ()*\n"
164 " store void ()* @b2, void ()** %a\n"
165 " store void ()* @d3, void ()** %a\n"
166 " ret void\n"
167 "}\n"
168 "define void @b2() {\n"
169 "entry:\n"
170 " %a = alloca void ()*\n"
171 " store void ()* @b3, void ()** %a\n"
172 " ret void\n"
173 "}\n"
174 "define void @b3() {\n"
175 "entry:\n"
176 " %a = alloca void ()*\n"
177 " store void ()* @b1, void ()** %a\n"
178 " ret void\n"
179 "}\n"
180 "define void @c1() {\n"
181 "entry:\n"
182 " %a = alloca void ()*\n"
183 " store void ()* @c2, void ()** %a\n"
184 " store void ()* @d2, void ()** %a\n"
185 " ret void\n"
186 "}\n"
187 "define void @c2() {\n"
188 "entry:\n"
189 " %a = alloca void ()*\n"
190 " store void ()* @c3, void ()** %a\n"
191 " ret void\n"
192 "}\n"
193 "define void @c3() {\n"
194 "entry:\n"
195 " %a = alloca void ()*\n"
196 " store void ()* @c1, void ()** %a\n"
197 " ret void\n"
198 "}\n"
199 "define void @d1() {\n"
200 "entry:\n"
201 " %a = alloca void ()*\n"
202 " store void ()* @d2, void ()** %a\n"
203 " ret void\n"
204 "}\n"
205 "define void @d2() {\n"
206 "entry:\n"
207 " %a = alloca void ()*\n"
208 " store void ()* @d3, void ()** %a\n"
209 " ret void\n"
210 "}\n"
211 "define void @d3() {\n"
212 "entry:\n"
213 " %a = alloca void ()*\n"
214 " store void ()* @d1, void ()** %a\n"
215 " ret void\n"
216 "}\n";
217
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000218TEST(LazyCallGraphTest, BasicGraphFormation) {
Mehdi Amini03b42e42016-04-14 21:59:01 +0000219 LLVMContext Context;
220 std::unique_ptr<Module> M = parseAssembly(Context, DiamondOfTriangles);
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000221 LazyCallGraph CG(*M);
222
223 // The order of the entry nodes should be stable w.r.t. the source order of
224 // the IR, and everything in our module is an entry node, so just directly
225 // build variables for each node.
226 auto I = CG.begin();
Chandler Carrutha4499e92016-02-02 03:57:13 +0000227 LazyCallGraph::Node &A1 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000228 EXPECT_EQ("a1", A1.getFunction().getName());
Chandler Carrutha4499e92016-02-02 03:57:13 +0000229 LazyCallGraph::Node &A2 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000230 EXPECT_EQ("a2", A2.getFunction().getName());
Chandler Carrutha4499e92016-02-02 03:57:13 +0000231 LazyCallGraph::Node &A3 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000232 EXPECT_EQ("a3", A3.getFunction().getName());
Chandler Carrutha4499e92016-02-02 03:57:13 +0000233 LazyCallGraph::Node &B1 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000234 EXPECT_EQ("b1", B1.getFunction().getName());
Chandler Carrutha4499e92016-02-02 03:57:13 +0000235 LazyCallGraph::Node &B2 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000236 EXPECT_EQ("b2", B2.getFunction().getName());
Chandler Carrutha4499e92016-02-02 03:57:13 +0000237 LazyCallGraph::Node &B3 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000238 EXPECT_EQ("b3", B3.getFunction().getName());
Chandler Carrutha4499e92016-02-02 03:57:13 +0000239 LazyCallGraph::Node &C1 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000240 EXPECT_EQ("c1", C1.getFunction().getName());
Chandler Carrutha4499e92016-02-02 03:57:13 +0000241 LazyCallGraph::Node &C2 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000242 EXPECT_EQ("c2", C2.getFunction().getName());
Chandler Carrutha4499e92016-02-02 03:57:13 +0000243 LazyCallGraph::Node &C3 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000244 EXPECT_EQ("c3", C3.getFunction().getName());
Chandler Carrutha4499e92016-02-02 03:57:13 +0000245 LazyCallGraph::Node &D1 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000246 EXPECT_EQ("d1", D1.getFunction().getName());
Chandler Carrutha4499e92016-02-02 03:57:13 +0000247 LazyCallGraph::Node &D2 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000248 EXPECT_EQ("d2", D2.getFunction().getName());
Chandler Carrutha4499e92016-02-02 03:57:13 +0000249 LazyCallGraph::Node &D3 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000250 EXPECT_EQ("d3", D3.getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000251 EXPECT_EQ(CG.end(), I);
252
253 // Build vectors and sort them for the rest of the assertions to make them
254 // independent of order.
255 std::vector<std::string> Nodes;
256
Chandler Carrutha4499e92016-02-02 03:57:13 +0000257 for (LazyCallGraph::Edge &E : A1)
258 Nodes.push_back(E.getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000259 std::sort(Nodes.begin(), Nodes.end());
260 EXPECT_EQ("a2", Nodes[0]);
261 EXPECT_EQ("b2", Nodes[1]);
262 EXPECT_EQ("c3", Nodes[2]);
263 Nodes.clear();
264
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000265 EXPECT_EQ(A2.end(), std::next(A2.begin()));
266 EXPECT_EQ("a3", A2.begin()->getFunction().getName());
267 EXPECT_EQ(A3.end(), std::next(A3.begin()));
268 EXPECT_EQ("a1", A3.begin()->getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000269
Chandler Carrutha4499e92016-02-02 03:57:13 +0000270 for (LazyCallGraph::Edge &E : B1)
271 Nodes.push_back(E.getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000272 std::sort(Nodes.begin(), Nodes.end());
273 EXPECT_EQ("b2", Nodes[0]);
274 EXPECT_EQ("d3", Nodes[1]);
275 Nodes.clear();
276
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000277 EXPECT_EQ(B2.end(), std::next(B2.begin()));
278 EXPECT_EQ("b3", B2.begin()->getFunction().getName());
279 EXPECT_EQ(B3.end(), std::next(B3.begin()));
280 EXPECT_EQ("b1", B3.begin()->getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000281
Chandler Carrutha4499e92016-02-02 03:57:13 +0000282 for (LazyCallGraph::Edge &E : C1)
283 Nodes.push_back(E.getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000284 std::sort(Nodes.begin(), Nodes.end());
285 EXPECT_EQ("c2", Nodes[0]);
286 EXPECT_EQ("d2", Nodes[1]);
287 Nodes.clear();
288
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000289 EXPECT_EQ(C2.end(), std::next(C2.begin()));
290 EXPECT_EQ("c3", C2.begin()->getFunction().getName());
291 EXPECT_EQ(C3.end(), std::next(C3.begin()));
292 EXPECT_EQ("c1", C3.begin()->getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000293
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000294 EXPECT_EQ(D1.end(), std::next(D1.begin()));
295 EXPECT_EQ("d2", D1.begin()->getFunction().getName());
296 EXPECT_EQ(D2.end(), std::next(D2.begin()));
297 EXPECT_EQ("d3", D2.begin()->getFunction().getName());
298 EXPECT_EQ(D3.end(), std::next(D3.begin()));
299 EXPECT_EQ("d1", D3.begin()->getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000300
Chandler Carruthe5944d92016-02-17 00:18:16 +0000301 // Now lets look at the RefSCCs and SCCs.
302 auto J = CG.postorder_ref_scc_begin();
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000303
Chandler Carruthe5944d92016-02-17 00:18:16 +0000304 LazyCallGraph::RefSCC &D = *J++;
305 ASSERT_EQ(1, D.size());
306 for (LazyCallGraph::Node &N : *D.begin())
307 Nodes.push_back(N.getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000308 std::sort(Nodes.begin(), Nodes.end());
Chandler Carruthead50d32014-04-24 09:59:56 +0000309 EXPECT_EQ(3u, Nodes.size());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000310 EXPECT_EQ("d1", Nodes[0]);
311 EXPECT_EQ("d2", Nodes[1]);
312 EXPECT_EQ("d3", Nodes[2]);
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000313 Nodes.clear();
Chandler Carruth4b096742014-05-01 12:12:42 +0000314 EXPECT_FALSE(D.isParentOf(D));
315 EXPECT_FALSE(D.isChildOf(D));
316 EXPECT_FALSE(D.isAncestorOf(D));
317 EXPECT_FALSE(D.isDescendantOf(D));
Chandler Carruth49d728a2016-09-16 10:20:17 +0000318 EXPECT_EQ(&D, &*CG.postorder_ref_scc_begin());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000319
Chandler Carruthe5944d92016-02-17 00:18:16 +0000320 LazyCallGraph::RefSCC &C = *J++;
321 ASSERT_EQ(1, C.size());
322 for (LazyCallGraph::Node &N : *C.begin())
323 Nodes.push_back(N.getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000324 std::sort(Nodes.begin(), Nodes.end());
Chandler Carruthead50d32014-04-24 09:59:56 +0000325 EXPECT_EQ(3u, Nodes.size());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000326 EXPECT_EQ("c1", Nodes[0]);
327 EXPECT_EQ("c2", Nodes[1]);
328 EXPECT_EQ("c3", Nodes[2]);
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000329 Nodes.clear();
Chandler Carruth4b096742014-05-01 12:12:42 +0000330 EXPECT_TRUE(C.isParentOf(D));
331 EXPECT_FALSE(C.isChildOf(D));
332 EXPECT_TRUE(C.isAncestorOf(D));
333 EXPECT_FALSE(C.isDescendantOf(D));
Chandler Carruth49d728a2016-09-16 10:20:17 +0000334 EXPECT_EQ(&C, &*std::next(CG.postorder_ref_scc_begin()));
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000335
Chandler Carruthe5944d92016-02-17 00:18:16 +0000336 LazyCallGraph::RefSCC &B = *J++;
337 ASSERT_EQ(1, B.size());
338 for (LazyCallGraph::Node &N : *B.begin())
339 Nodes.push_back(N.getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000340 std::sort(Nodes.begin(), Nodes.end());
Chandler Carruthead50d32014-04-24 09:59:56 +0000341 EXPECT_EQ(3u, Nodes.size());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000342 EXPECT_EQ("b1", Nodes[0]);
343 EXPECT_EQ("b2", Nodes[1]);
344 EXPECT_EQ("b3", Nodes[2]);
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000345 Nodes.clear();
Chandler Carruth4b096742014-05-01 12:12:42 +0000346 EXPECT_TRUE(B.isParentOf(D));
347 EXPECT_FALSE(B.isChildOf(D));
348 EXPECT_TRUE(B.isAncestorOf(D));
349 EXPECT_FALSE(B.isDescendantOf(D));
350 EXPECT_FALSE(B.isAncestorOf(C));
351 EXPECT_FALSE(C.isAncestorOf(B));
Chandler Carruth49d728a2016-09-16 10:20:17 +0000352 EXPECT_EQ(&B, &*std::next(CG.postorder_ref_scc_begin(), 2));
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000353
Chandler Carruthe5944d92016-02-17 00:18:16 +0000354 LazyCallGraph::RefSCC &A = *J++;
355 ASSERT_EQ(1, A.size());
356 for (LazyCallGraph::Node &N : *A.begin())
357 Nodes.push_back(N.getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000358 std::sort(Nodes.begin(), Nodes.end());
Chandler Carruthead50d32014-04-24 09:59:56 +0000359 EXPECT_EQ(3u, Nodes.size());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000360 EXPECT_EQ("a1", Nodes[0]);
361 EXPECT_EQ("a2", Nodes[1]);
362 EXPECT_EQ("a3", Nodes[2]);
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000363 Nodes.clear();
Chandler Carruth4b096742014-05-01 12:12:42 +0000364 EXPECT_TRUE(A.isParentOf(B));
365 EXPECT_TRUE(A.isParentOf(C));
366 EXPECT_FALSE(A.isParentOf(D));
367 EXPECT_TRUE(A.isAncestorOf(B));
368 EXPECT_TRUE(A.isAncestorOf(C));
369 EXPECT_TRUE(A.isAncestorOf(D));
Chandler Carruth49d728a2016-09-16 10:20:17 +0000370 EXPECT_EQ(&A, &*std::next(CG.postorder_ref_scc_begin(), 3));
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000371
Chandler Carruthe5944d92016-02-17 00:18:16 +0000372 EXPECT_EQ(CG.postorder_ref_scc_end(), J);
Chandler Carruth49d728a2016-09-16 10:20:17 +0000373 EXPECT_EQ(J, std::next(CG.postorder_ref_scc_begin(), 4));
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000374}
375
Chandler Carruthcace6622014-04-23 10:31:17 +0000376static Function &lookupFunction(Module &M, StringRef Name) {
377 for (Function &F : M)
378 if (F.getName() == Name)
379 return F;
380 report_fatal_error("Couldn't find function!");
381}
382
Chandler Carruthc00a7ff2014-04-28 11:10:23 +0000383TEST(LazyCallGraphTest, BasicGraphMutation) {
Mehdi Amini03b42e42016-04-14 21:59:01 +0000384 LLVMContext Context;
385 std::unique_ptr<Module> M = parseAssembly(Context, "define void @a() {\n"
386 "entry:\n"
387 " call void @b()\n"
388 " call void @c()\n"
389 " ret void\n"
390 "}\n"
391 "define void @b() {\n"
392 "entry:\n"
393 " ret void\n"
394 "}\n"
395 "define void @c() {\n"
396 "entry:\n"
397 " ret void\n"
398 "}\n");
Chandler Carruthc00a7ff2014-04-28 11:10:23 +0000399 LazyCallGraph CG(*M);
400
401 LazyCallGraph::Node &A = CG.get(lookupFunction(*M, "a"));
402 LazyCallGraph::Node &B = CG.get(lookupFunction(*M, "b"));
403 EXPECT_EQ(2, std::distance(A.begin(), A.end()));
404 EXPECT_EQ(0, std::distance(B.begin(), B.end()));
405
Chandler Carrutha4499e92016-02-02 03:57:13 +0000406 CG.insertEdge(B, lookupFunction(*M, "c"), LazyCallGraph::Edge::Call);
Chandler Carruthc00a7ff2014-04-28 11:10:23 +0000407 EXPECT_EQ(1, std::distance(B.begin(), B.end()));
Chandler Carrutha4499e92016-02-02 03:57:13 +0000408 LazyCallGraph::Node &C = B.begin()->getNode(CG);
Chandler Carruthc00a7ff2014-04-28 11:10:23 +0000409 EXPECT_EQ(0, std::distance(C.begin(), C.end()));
410
Chandler Carrutha4499e92016-02-02 03:57:13 +0000411 CG.insertEdge(C, B.getFunction(), LazyCallGraph::Edge::Call);
Chandler Carruthc00a7ff2014-04-28 11:10:23 +0000412 EXPECT_EQ(1, std::distance(C.begin(), C.end()));
Chandler Carrutha4499e92016-02-02 03:57:13 +0000413 EXPECT_EQ(&B, C.begin()->getNode());
Chandler Carruthc00a7ff2014-04-28 11:10:23 +0000414
Chandler Carrutha4499e92016-02-02 03:57:13 +0000415 CG.insertEdge(C, C.getFunction(), LazyCallGraph::Edge::Call);
Chandler Carruthc00a7ff2014-04-28 11:10:23 +0000416 EXPECT_EQ(2, std::distance(C.begin(), C.end()));
Chandler Carrutha4499e92016-02-02 03:57:13 +0000417 EXPECT_EQ(&B, C.begin()->getNode());
418 EXPECT_EQ(&C, std::next(C.begin())->getNode());
Chandler Carruthc5026b62014-04-30 07:45:27 +0000419
420 CG.removeEdge(C, B.getFunction());
421 EXPECT_EQ(1, std::distance(C.begin(), C.end()));
Chandler Carrutha4499e92016-02-02 03:57:13 +0000422 EXPECT_EQ(&C, C.begin()->getNode());
Chandler Carruthc5026b62014-04-30 07:45:27 +0000423
424 CG.removeEdge(C, C.getFunction());
425 EXPECT_EQ(0, std::distance(C.begin(), C.end()));
426
427 CG.removeEdge(B, C.getFunction());
428 EXPECT_EQ(0, std::distance(B.begin(), B.end()));
Chandler Carruthc00a7ff2014-04-28 11:10:23 +0000429}
430
Chandler Carruthe5944d92016-02-17 00:18:16 +0000431TEST(LazyCallGraphTest, InnerSCCFormation) {
Mehdi Amini03b42e42016-04-14 21:59:01 +0000432 LLVMContext Context;
433 std::unique_ptr<Module> M = parseAssembly(Context, DiamondOfTriangles);
Chandler Carruthe5944d92016-02-17 00:18:16 +0000434 LazyCallGraph CG(*M);
435
436 // Now mutate the graph to connect every node into a single RefSCC to ensure
437 // that our inner SCC formation handles the rest.
438 CG.insertEdge(lookupFunction(*M, "d1"), lookupFunction(*M, "a1"),
439 LazyCallGraph::Edge::Ref);
440
441 // Build vectors and sort them for the rest of the assertions to make them
442 // independent of order.
443 std::vector<std::string> Nodes;
444
445 // We should build a single RefSCC for the entire graph.
446 auto I = CG.postorder_ref_scc_begin();
447 LazyCallGraph::RefSCC &RC = *I++;
448 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
449
450 // Now walk the four SCCs which should be in post-order.
451 auto J = RC.begin();
452 LazyCallGraph::SCC &D = *J++;
453 for (LazyCallGraph::Node &N : D)
454 Nodes.push_back(N.getFunction().getName());
455 std::sort(Nodes.begin(), Nodes.end());
456 EXPECT_EQ(3u, Nodes.size());
457 EXPECT_EQ("d1", Nodes[0]);
458 EXPECT_EQ("d2", Nodes[1]);
459 EXPECT_EQ("d3", Nodes[2]);
460 Nodes.clear();
461
462 LazyCallGraph::SCC &B = *J++;
463 for (LazyCallGraph::Node &N : B)
464 Nodes.push_back(N.getFunction().getName());
465 std::sort(Nodes.begin(), Nodes.end());
466 EXPECT_EQ(3u, Nodes.size());
467 EXPECT_EQ("b1", Nodes[0]);
468 EXPECT_EQ("b2", Nodes[1]);
469 EXPECT_EQ("b3", Nodes[2]);
470 Nodes.clear();
471
472 LazyCallGraph::SCC &C = *J++;
473 for (LazyCallGraph::Node &N : C)
474 Nodes.push_back(N.getFunction().getName());
475 std::sort(Nodes.begin(), Nodes.end());
476 EXPECT_EQ(3u, Nodes.size());
477 EXPECT_EQ("c1", Nodes[0]);
478 EXPECT_EQ("c2", Nodes[1]);
479 EXPECT_EQ("c3", Nodes[2]);
480 Nodes.clear();
481
482 LazyCallGraph::SCC &A = *J++;
483 for (LazyCallGraph::Node &N : A)
484 Nodes.push_back(N.getFunction().getName());
485 std::sort(Nodes.begin(), Nodes.end());
486 EXPECT_EQ(3u, Nodes.size());
487 EXPECT_EQ("a1", Nodes[0]);
488 EXPECT_EQ("a2", Nodes[1]);
489 EXPECT_EQ("a3", Nodes[2]);
490 Nodes.clear();
491
492 EXPECT_EQ(RC.end(), J);
493}
494
Chandler Carruthcace6622014-04-23 10:31:17 +0000495TEST(LazyCallGraphTest, MultiArmSCC) {
Mehdi Amini03b42e42016-04-14 21:59:01 +0000496 LLVMContext Context;
Chandler Carruthcace6622014-04-23 10:31:17 +0000497 // Two interlocking cycles. The really useful thing about this SCC is that it
498 // will require Tarjan's DFS to backtrack and finish processing all of the
Chandler Carruthe5944d92016-02-17 00:18:16 +0000499 // children of each node in the SCC. Since this involves call edges, both
500 // Tarjan implementations will have to successfully navigate the structure.
Mehdi Amini03b42e42016-04-14 21:59:01 +0000501 std::unique_ptr<Module> M = parseAssembly(Context, "define void @f1() {\n"
502 "entry:\n"
503 " call void @f2()\n"
504 " call void @f4()\n"
505 " ret void\n"
506 "}\n"
507 "define void @f2() {\n"
508 "entry:\n"
509 " call void @f3()\n"
510 " ret void\n"
511 "}\n"
512 "define void @f3() {\n"
513 "entry:\n"
514 " call void @f1()\n"
515 " ret void\n"
516 "}\n"
517 "define void @f4() {\n"
518 "entry:\n"
519 " call void @f5()\n"
520 " ret void\n"
521 "}\n"
522 "define void @f5() {\n"
523 "entry:\n"
524 " call void @f1()\n"
525 " ret void\n"
526 "}\n");
Chandler Carruthcace6622014-04-23 10:31:17 +0000527 LazyCallGraph CG(*M);
528
529 // Force the graph to be fully expanded.
Chandler Carruthe5944d92016-02-17 00:18:16 +0000530 auto I = CG.postorder_ref_scc_begin();
531 LazyCallGraph::RefSCC &RC = *I++;
532 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
Chandler Carruthcace6622014-04-23 10:31:17 +0000533
Chandler Carruthe5944d92016-02-17 00:18:16 +0000534 LazyCallGraph::Node &N1 = *CG.lookup(lookupFunction(*M, "f1"));
535 LazyCallGraph::Node &N2 = *CG.lookup(lookupFunction(*M, "f2"));
536 LazyCallGraph::Node &N3 = *CG.lookup(lookupFunction(*M, "f3"));
537 LazyCallGraph::Node &N4 = *CG.lookup(lookupFunction(*M, "f4"));
538 LazyCallGraph::Node &N5 = *CG.lookup(lookupFunction(*M, "f4"));
539 EXPECT_EQ(&RC, CG.lookupRefSCC(N1));
540 EXPECT_EQ(&RC, CG.lookupRefSCC(N2));
541 EXPECT_EQ(&RC, CG.lookupRefSCC(N3));
542 EXPECT_EQ(&RC, CG.lookupRefSCC(N4));
543 EXPECT_EQ(&RC, CG.lookupRefSCC(N5));
544
545 ASSERT_EQ(1, RC.size());
546
547 LazyCallGraph::SCC &C = *RC.begin();
548 EXPECT_EQ(&C, CG.lookupSCC(N1));
549 EXPECT_EQ(&C, CG.lookupSCC(N2));
550 EXPECT_EQ(&C, CG.lookupSCC(N3));
551 EXPECT_EQ(&C, CG.lookupSCC(N4));
552 EXPECT_EQ(&C, CG.lookupSCC(N5));
Chandler Carruthcace6622014-04-23 10:31:17 +0000553}
554
Chandler Carruthe5944d92016-02-17 00:18:16 +0000555TEST(LazyCallGraphTest, OutgoingEdgeMutation) {
Mehdi Amini03b42e42016-04-14 21:59:01 +0000556 LLVMContext Context;
557 std::unique_ptr<Module> M = parseAssembly(Context, "define void @a() {\n"
558 "entry:\n"
559 " call void @b()\n"
560 " call void @c()\n"
561 " ret void\n"
562 "}\n"
563 "define void @b() {\n"
564 "entry:\n"
565 " call void @d()\n"
566 " ret void\n"
567 "}\n"
568 "define void @c() {\n"
569 "entry:\n"
570 " call void @d()\n"
571 " ret void\n"
572 "}\n"
573 "define void @d() {\n"
574 "entry:\n"
575 " ret void\n"
576 "}\n");
Chandler Carruthcc6e1872014-05-04 09:38:23 +0000577 LazyCallGraph CG(*M);
578
579 // Force the graph to be fully expanded.
Chandler Carruthe5944d92016-02-17 00:18:16 +0000580 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
Chandler Carruth49d728a2016-09-16 10:20:17 +0000581 dbgs() << "Formed RefSCC: " << RC << "\n";
Chandler Carruthcc6e1872014-05-04 09:38:23 +0000582
583 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
584 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
585 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
586 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
587 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
588 LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
589 LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
590 LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
Chandler Carruthe5944d92016-02-17 00:18:16 +0000591 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(A);
592 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(B);
593 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(C);
594 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(D);
595 EXPECT_TRUE(ARC.isParentOf(BRC));
596 EXPECT_TRUE(ARC.isParentOf(CRC));
597 EXPECT_FALSE(ARC.isParentOf(DRC));
598 EXPECT_TRUE(ARC.isAncestorOf(DRC));
599 EXPECT_FALSE(DRC.isChildOf(ARC));
600 EXPECT_TRUE(DRC.isDescendantOf(ARC));
601 EXPECT_TRUE(DRC.isChildOf(BRC));
602 EXPECT_TRUE(DRC.isChildOf(CRC));
Chandler Carruthcc6e1872014-05-04 09:38:23 +0000603
604 EXPECT_EQ(2, std::distance(A.begin(), A.end()));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000605 ARC.insertOutgoingEdge(A, D, LazyCallGraph::Edge::Call);
Chandler Carruthcc6e1872014-05-04 09:38:23 +0000606 EXPECT_EQ(3, std::distance(A.begin(), A.end()));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000607 const LazyCallGraph::Edge &NewE = A[D];
608 EXPECT_TRUE(NewE);
609 EXPECT_TRUE(NewE.isCall());
610 EXPECT_EQ(&D, NewE.getNode());
611
612 // Only the parent and child tests sholud have changed. The rest of the graph
613 // remains the same.
614 EXPECT_TRUE(ARC.isParentOf(DRC));
615 EXPECT_TRUE(ARC.isAncestorOf(DRC));
616 EXPECT_TRUE(DRC.isChildOf(ARC));
617 EXPECT_TRUE(DRC.isDescendantOf(ARC));
Chandler Carruthcc6e1872014-05-04 09:38:23 +0000618 EXPECT_EQ(&AC, CG.lookupSCC(A));
619 EXPECT_EQ(&BC, CG.lookupSCC(B));
620 EXPECT_EQ(&CC, CG.lookupSCC(C));
621 EXPECT_EQ(&DC, CG.lookupSCC(D));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000622 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
623 EXPECT_EQ(&BRC, CG.lookupRefSCC(B));
624 EXPECT_EQ(&CRC, CG.lookupRefSCC(C));
625 EXPECT_EQ(&DRC, CG.lookupRefSCC(D));
626
627 ARC.switchOutgoingEdgeToRef(A, D);
628 EXPECT_FALSE(NewE.isCall());
629
630 // Verify the graph remains the same.
631 EXPECT_TRUE(ARC.isParentOf(DRC));
632 EXPECT_TRUE(ARC.isAncestorOf(DRC));
633 EXPECT_TRUE(DRC.isChildOf(ARC));
634 EXPECT_TRUE(DRC.isDescendantOf(ARC));
635 EXPECT_EQ(&AC, CG.lookupSCC(A));
636 EXPECT_EQ(&BC, CG.lookupSCC(B));
637 EXPECT_EQ(&CC, CG.lookupSCC(C));
638 EXPECT_EQ(&DC, CG.lookupSCC(D));
639 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
640 EXPECT_EQ(&BRC, CG.lookupRefSCC(B));
641 EXPECT_EQ(&CRC, CG.lookupRefSCC(C));
642 EXPECT_EQ(&DRC, CG.lookupRefSCC(D));
643
644 ARC.switchOutgoingEdgeToCall(A, D);
645 EXPECT_TRUE(NewE.isCall());
646
647 // Verify the graph remains the same.
648 EXPECT_TRUE(ARC.isParentOf(DRC));
649 EXPECT_TRUE(ARC.isAncestorOf(DRC));
650 EXPECT_TRUE(DRC.isChildOf(ARC));
651 EXPECT_TRUE(DRC.isDescendantOf(ARC));
652 EXPECT_EQ(&AC, CG.lookupSCC(A));
653 EXPECT_EQ(&BC, CG.lookupSCC(B));
654 EXPECT_EQ(&CC, CG.lookupSCC(C));
655 EXPECT_EQ(&DC, CG.lookupSCC(D));
656 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
657 EXPECT_EQ(&BRC, CG.lookupRefSCC(B));
658 EXPECT_EQ(&CRC, CG.lookupRefSCC(C));
659 EXPECT_EQ(&DRC, CG.lookupRefSCC(D));
660
661 ARC.removeOutgoingEdge(A, D);
662 EXPECT_EQ(2, std::distance(A.begin(), A.end()));
663
664 // Now the parent and child tests fail again but the rest remains the same.
665 EXPECT_FALSE(ARC.isParentOf(DRC));
666 EXPECT_TRUE(ARC.isAncestorOf(DRC));
667 EXPECT_FALSE(DRC.isChildOf(ARC));
668 EXPECT_TRUE(DRC.isDescendantOf(ARC));
669 EXPECT_EQ(&AC, CG.lookupSCC(A));
670 EXPECT_EQ(&BC, CG.lookupSCC(B));
671 EXPECT_EQ(&CC, CG.lookupSCC(C));
672 EXPECT_EQ(&DC, CG.lookupSCC(D));
673 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
674 EXPECT_EQ(&BRC, CG.lookupRefSCC(B));
675 EXPECT_EQ(&CRC, CG.lookupRefSCC(C));
676 EXPECT_EQ(&DRC, CG.lookupRefSCC(D));
Chandler Carruthcc6e1872014-05-04 09:38:23 +0000677}
678
Chandler Carruthe5944d92016-02-17 00:18:16 +0000679TEST(LazyCallGraphTest, IncomingEdgeInsertion) {
Mehdi Amini03b42e42016-04-14 21:59:01 +0000680 LLVMContext Context;
Chandler Carruth312dddf2014-05-04 09:38:32 +0000681 // We want to ensure we can add edges even across complex diamond graphs, so
682 // we use the diamond of triangles graph defined above. The ascii diagram is
683 // repeated here for easy reference.
684 //
685 // d1 |
686 // / \ |
687 // d3--d2 |
688 // / \ |
689 // b1 c1 |
690 // / \ / \ |
691 // b3--b2 c3--c2 |
692 // \ / |
693 // a1 |
694 // / \ |
695 // a3--a2 |
696 //
Mehdi Amini03b42e42016-04-14 21:59:01 +0000697 std::unique_ptr<Module> M = parseAssembly(Context, DiamondOfTriangles);
Chandler Carruth312dddf2014-05-04 09:38:32 +0000698 LazyCallGraph CG(*M);
699
700 // Force the graph to be fully expanded.
Chandler Carruthe5944d92016-02-17 00:18:16 +0000701 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
Chandler Carruth49d728a2016-09-16 10:20:17 +0000702 dbgs() << "Formed RefSCC: " << RC << "\n";
Chandler Carruth312dddf2014-05-04 09:38:32 +0000703
704 LazyCallGraph::Node &A1 = *CG.lookup(lookupFunction(*M, "a1"));
705 LazyCallGraph::Node &A2 = *CG.lookup(lookupFunction(*M, "a2"));
706 LazyCallGraph::Node &A3 = *CG.lookup(lookupFunction(*M, "a3"));
707 LazyCallGraph::Node &B1 = *CG.lookup(lookupFunction(*M, "b1"));
708 LazyCallGraph::Node &B2 = *CG.lookup(lookupFunction(*M, "b2"));
709 LazyCallGraph::Node &B3 = *CG.lookup(lookupFunction(*M, "b3"));
710 LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
711 LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
712 LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
713 LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
714 LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
715 LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000716 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(A1);
717 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(B1);
718 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(C1);
719 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(D1);
720 ASSERT_EQ(&ARC, CG.lookupRefSCC(A2));
721 ASSERT_EQ(&ARC, CG.lookupRefSCC(A3));
722 ASSERT_EQ(&BRC, CG.lookupRefSCC(B2));
723 ASSERT_EQ(&BRC, CG.lookupRefSCC(B3));
724 ASSERT_EQ(&CRC, CG.lookupRefSCC(C2));
725 ASSERT_EQ(&CRC, CG.lookupRefSCC(C3));
726 ASSERT_EQ(&DRC, CG.lookupRefSCC(D2));
727 ASSERT_EQ(&DRC, CG.lookupRefSCC(D3));
Chandler Carruth312dddf2014-05-04 09:38:32 +0000728 ASSERT_EQ(1, std::distance(D2.begin(), D2.end()));
729
730 // Add an edge to make the graph:
731 //
732 // d1 |
733 // / \ |
734 // d3--d2---. |
735 // / \ | |
736 // b1 c1 | |
737 // / \ / \ / |
738 // b3--b2 c3--c2 |
739 // \ / |
740 // a1 |
741 // / \ |
742 // a3--a2 |
Chandler Carruthe5944d92016-02-17 00:18:16 +0000743 auto MergedRCs = CRC.insertIncomingRefEdge(D2, C2);
Chandler Carruth312dddf2014-05-04 09:38:32 +0000744 // Make sure we connected the nodes.
Chandler Carruthe5944d92016-02-17 00:18:16 +0000745 for (LazyCallGraph::Edge E : D2) {
746 if (E.getNode() == &D3)
747 continue;
748 EXPECT_EQ(&C2, E.getNode());
749 }
750 // And marked the D ref-SCC as no longer valid.
751 EXPECT_EQ(1u, MergedRCs.size());
752 EXPECT_EQ(&DRC, MergedRCs[0]);
Chandler Carruth312dddf2014-05-04 09:38:32 +0000753
754 // Make sure we have the correct nodes in the SCC sets.
Chandler Carruthe5944d92016-02-17 00:18:16 +0000755 EXPECT_EQ(&ARC, CG.lookupRefSCC(A1));
756 EXPECT_EQ(&ARC, CG.lookupRefSCC(A2));
757 EXPECT_EQ(&ARC, CG.lookupRefSCC(A3));
758 EXPECT_EQ(&BRC, CG.lookupRefSCC(B1));
759 EXPECT_EQ(&BRC, CG.lookupRefSCC(B2));
760 EXPECT_EQ(&BRC, CG.lookupRefSCC(B3));
761 EXPECT_EQ(&CRC, CG.lookupRefSCC(C1));
762 EXPECT_EQ(&CRC, CG.lookupRefSCC(C2));
763 EXPECT_EQ(&CRC, CG.lookupRefSCC(C3));
764 EXPECT_EQ(&CRC, CG.lookupRefSCC(D1));
765 EXPECT_EQ(&CRC, CG.lookupRefSCC(D2));
766 EXPECT_EQ(&CRC, CG.lookupRefSCC(D3));
Chandler Carruth312dddf2014-05-04 09:38:32 +0000767
768 // And that ancestry tests have been updated.
Chandler Carruthe5944d92016-02-17 00:18:16 +0000769 EXPECT_TRUE(ARC.isParentOf(CRC));
770 EXPECT_TRUE(BRC.isParentOf(CRC));
Chandler Carruth49d728a2016-09-16 10:20:17 +0000771
772 // And verify the post-order walk reflects the updated structure.
773 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
774 ASSERT_NE(I, E);
775 EXPECT_EQ(&CRC, &*I) << "Actual RefSCC: " << *I;
776 ASSERT_NE(++I, E);
777 EXPECT_EQ(&BRC, &*I) << "Actual RefSCC: " << *I;
778 ASSERT_NE(++I, E);
779 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
780 EXPECT_EQ(++I, E);
Chandler Carruth312dddf2014-05-04 09:38:32 +0000781}
782
Chandler Carruthe5944d92016-02-17 00:18:16 +0000783TEST(LazyCallGraphTest, IncomingEdgeInsertionMidTraversal) {
Mehdi Amini03b42e42016-04-14 21:59:01 +0000784 LLVMContext Context;
Chandler Carruth312dddf2014-05-04 09:38:32 +0000785 // This is the same fundamental test as the previous, but we perform it
Chandler Carruthe5944d92016-02-17 00:18:16 +0000786 // having only partially walked the RefSCCs of the graph.
Mehdi Amini03b42e42016-04-14 21:59:01 +0000787 std::unique_ptr<Module> M = parseAssembly(Context, DiamondOfTriangles);
Chandler Carruth312dddf2014-05-04 09:38:32 +0000788 LazyCallGraph CG(*M);
789
Chandler Carruthe5944d92016-02-17 00:18:16 +0000790 // Walk the RefSCCs until we find the one containing 'c1'.
791 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
792 ASSERT_NE(I, E);
793 LazyCallGraph::RefSCC &DRC = *I;
794 ASSERT_NE(&DRC, nullptr);
795 ++I;
796 ASSERT_NE(I, E);
797 LazyCallGraph::RefSCC &CRC = *I;
798 ASSERT_NE(&CRC, nullptr);
Chandler Carruth312dddf2014-05-04 09:38:32 +0000799
800 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a1")));
801 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a2")));
802 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a3")));
803 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b1")));
804 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b2")));
805 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b3")));
806 LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
807 LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
808 LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
809 LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
810 LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
811 LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000812 ASSERT_EQ(&CRC, CG.lookupRefSCC(C1));
813 ASSERT_EQ(&CRC, CG.lookupRefSCC(C2));
814 ASSERT_EQ(&CRC, CG.lookupRefSCC(C3));
815 ASSERT_EQ(&DRC, CG.lookupRefSCC(D1));
816 ASSERT_EQ(&DRC, CG.lookupRefSCC(D2));
817 ASSERT_EQ(&DRC, CG.lookupRefSCC(D3));
Chandler Carruth312dddf2014-05-04 09:38:32 +0000818 ASSERT_EQ(1, std::distance(D2.begin(), D2.end()));
819
Chandler Carruthe5944d92016-02-17 00:18:16 +0000820 auto MergedRCs = CRC.insertIncomingRefEdge(D2, C2);
821 // Make sure we connected the nodes.
822 for (LazyCallGraph::Edge E : D2) {
823 if (E.getNode() == &D3)
824 continue;
825 EXPECT_EQ(&C2, E.getNode());
826 }
827 // And marked the D ref-SCC as no longer valid.
828 EXPECT_EQ(1u, MergedRCs.size());
829 EXPECT_EQ(&DRC, MergedRCs[0]);
Chandler Carruth312dddf2014-05-04 09:38:32 +0000830
Chandler Carruthe5944d92016-02-17 00:18:16 +0000831 // Make sure we have the correct nodes in the RefSCCs.
832 EXPECT_EQ(&CRC, CG.lookupRefSCC(C1));
833 EXPECT_EQ(&CRC, CG.lookupRefSCC(C2));
834 EXPECT_EQ(&CRC, CG.lookupRefSCC(C3));
835 EXPECT_EQ(&CRC, CG.lookupRefSCC(D1));
836 EXPECT_EQ(&CRC, CG.lookupRefSCC(D2));
837 EXPECT_EQ(&CRC, CG.lookupRefSCC(D3));
Chandler Carruth312dddf2014-05-04 09:38:32 +0000838
Chandler Carruth49d728a2016-09-16 10:20:17 +0000839 // Verify that the post-order walk reflects the updated but still incomplete
840 // structure.
841 auto J = CG.postorder_ref_scc_begin();
842 EXPECT_NE(J, E);
843 EXPECT_EQ(&CRC, &*J) << "Actual RefSCC: " << *J;
844 EXPECT_EQ(I, J);
845
846 // Check that we can form the last two RefSCCs now, and even that we can do
847 // it with alternating iterators.
848 ++J;
849 EXPECT_NE(J, E);
850 LazyCallGraph::RefSCC &BRC = *J;
Chandler Carruthe5944d92016-02-17 00:18:16 +0000851 EXPECT_NE(&BRC, nullptr);
852 EXPECT_EQ(&BRC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "b1"))));
853 EXPECT_EQ(&BRC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "b2"))));
854 EXPECT_EQ(&BRC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "b3"))));
855 EXPECT_TRUE(BRC.isParentOf(CRC));
856 ++I;
Chandler Carruth49d728a2016-09-16 10:20:17 +0000857 EXPECT_EQ(J, I);
858 EXPECT_EQ(&BRC, &*I) << "Actual RefSCC: " << *I;
859
860 // Increment I this time to form the new RefSCC, flopping back to the first
861 // iterator.
862 ++I;
Chandler Carruthe5944d92016-02-17 00:18:16 +0000863 EXPECT_NE(I, E);
864 LazyCallGraph::RefSCC &ARC = *I;
865 EXPECT_NE(&ARC, nullptr);
866 EXPECT_EQ(&ARC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "a1"))));
867 EXPECT_EQ(&ARC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "a2"))));
868 EXPECT_EQ(&ARC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "a3"))));
869 EXPECT_TRUE(ARC.isParentOf(CRC));
Chandler Carruth49d728a2016-09-16 10:20:17 +0000870 ++J;
871 EXPECT_EQ(I, J);
872 EXPECT_EQ(&ARC, &*J) << "Actual RefSCC: " << *J;
Chandler Carruthe5944d92016-02-17 00:18:16 +0000873 ++I;
874 EXPECT_EQ(E, I);
Chandler Carruth49d728a2016-09-16 10:20:17 +0000875 ++J;
876 EXPECT_EQ(E, J);
877}
878
879TEST(LazyCallGraphTest, IncomingEdgeInsertionRefGraph) {
880 LLVMContext Context;
881 // Another variation of the above test but with all the edges switched to
882 // references rather than calls.
883 std::unique_ptr<Module> M =
884 parseAssembly(Context, DiamondOfTrianglesRefGraph);
885 LazyCallGraph CG(*M);
886
887 // Force the graph to be fully expanded.
888 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
889 dbgs() << "Formed RefSCC: " << RC << "\n";
890
891 LazyCallGraph::Node &A1 = *CG.lookup(lookupFunction(*M, "a1"));
892 LazyCallGraph::Node &A2 = *CG.lookup(lookupFunction(*M, "a2"));
893 LazyCallGraph::Node &A3 = *CG.lookup(lookupFunction(*M, "a3"));
894 LazyCallGraph::Node &B1 = *CG.lookup(lookupFunction(*M, "b1"));
895 LazyCallGraph::Node &B2 = *CG.lookup(lookupFunction(*M, "b2"));
896 LazyCallGraph::Node &B3 = *CG.lookup(lookupFunction(*M, "b3"));
897 LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
898 LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
899 LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
900 LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
901 LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
902 LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
903 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(A1);
904 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(B1);
905 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(C1);
906 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(D1);
907 ASSERT_EQ(&ARC, CG.lookupRefSCC(A2));
908 ASSERT_EQ(&ARC, CG.lookupRefSCC(A3));
909 ASSERT_EQ(&BRC, CG.lookupRefSCC(B2));
910 ASSERT_EQ(&BRC, CG.lookupRefSCC(B3));
911 ASSERT_EQ(&CRC, CG.lookupRefSCC(C2));
912 ASSERT_EQ(&CRC, CG.lookupRefSCC(C3));
913 ASSERT_EQ(&DRC, CG.lookupRefSCC(D2));
914 ASSERT_EQ(&DRC, CG.lookupRefSCC(D3));
915 ASSERT_EQ(1, std::distance(D2.begin(), D2.end()));
916
917 // Add an edge to make the graph:
918 //
919 // d1 |
920 // / \ |
921 // d3--d2---. |
922 // / \ | |
923 // b1 c1 | |
924 // / \ / \ / |
925 // b3--b2 c3--c2 |
926 // \ / |
927 // a1 |
928 // / \ |
929 // a3--a2 |
930 auto MergedRCs = CRC.insertIncomingRefEdge(D2, C2);
931 // Make sure we connected the nodes.
932 for (LazyCallGraph::Edge E : D2) {
933 if (E.getNode() == &D3)
934 continue;
935 EXPECT_EQ(&C2, E.getNode());
936 }
937 // And marked the D ref-SCC as no longer valid.
938 EXPECT_EQ(1u, MergedRCs.size());
939 EXPECT_EQ(&DRC, MergedRCs[0]);
940
941 // Make sure we have the correct nodes in the SCC sets.
942 EXPECT_EQ(&ARC, CG.lookupRefSCC(A1));
943 EXPECT_EQ(&ARC, CG.lookupRefSCC(A2));
944 EXPECT_EQ(&ARC, CG.lookupRefSCC(A3));
945 EXPECT_EQ(&BRC, CG.lookupRefSCC(B1));
946 EXPECT_EQ(&BRC, CG.lookupRefSCC(B2));
947 EXPECT_EQ(&BRC, CG.lookupRefSCC(B3));
948 EXPECT_EQ(&CRC, CG.lookupRefSCC(C1));
949 EXPECT_EQ(&CRC, CG.lookupRefSCC(C2));
950 EXPECT_EQ(&CRC, CG.lookupRefSCC(C3));
951 EXPECT_EQ(&CRC, CG.lookupRefSCC(D1));
952 EXPECT_EQ(&CRC, CG.lookupRefSCC(D2));
953 EXPECT_EQ(&CRC, CG.lookupRefSCC(D3));
954
955 // And that ancestry tests have been updated.
956 EXPECT_TRUE(ARC.isParentOf(CRC));
957 EXPECT_TRUE(BRC.isParentOf(CRC));
958
959 // And verify the post-order walk reflects the updated structure.
960 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
961 ASSERT_NE(I, E);
962 EXPECT_EQ(&CRC, &*I) << "Actual RefSCC: " << *I;
963 ASSERT_NE(++I, E);
964 EXPECT_EQ(&BRC, &*I) << "Actual RefSCC: " << *I;
965 ASSERT_NE(++I, E);
966 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
967 EXPECT_EQ(++I, E);
968}
969
970TEST(LazyCallGraphTest, IncomingEdgeInsertionLargeCallCycle) {
971 LLVMContext Context;
972 std::unique_ptr<Module> M = parseAssembly(Context, "define void @a() {\n"
973 "entry:\n"
974 " call void @b()\n"
975 " ret void\n"
976 "}\n"
977 "define void @b() {\n"
978 "entry:\n"
979 " call void @c()\n"
980 " ret void\n"
981 "}\n"
982 "define void @c() {\n"
983 "entry:\n"
984 " call void @d()\n"
985 " ret void\n"
986 "}\n"
987 "define void @d() {\n"
988 "entry:\n"
989 " ret void\n"
990 "}\n");
991 LazyCallGraph CG(*M);
992
993 // Force the graph to be fully expanded.
994 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
995 dbgs() << "Formed RefSCC: " << RC << "\n";
996
997 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
998 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
999 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1000 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
1001 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
1002 LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
1003 LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
1004 LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
1005 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(A);
1006 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(B);
1007 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(C);
1008 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(D);
1009
1010 // Connect the top to the bottom forming a large RefSCC made up mostly of calls.
1011 auto MergedRCs = ARC.insertIncomingRefEdge(D, A);
1012 // Make sure we connected the nodes.
1013 EXPECT_NE(D.begin(), D.end());
1014 EXPECT_EQ(&A, D.begin()->getNode());
1015
1016 // Check that we have the dead RCs, but ignore the order.
1017 EXPECT_EQ(3u, MergedRCs.size());
1018 EXPECT_NE(find(MergedRCs, &BRC), MergedRCs.end());
1019 EXPECT_NE(find(MergedRCs, &CRC), MergedRCs.end());
1020 EXPECT_NE(find(MergedRCs, &DRC), MergedRCs.end());
1021
1022 // Make sure the nodes point to the right place now.
1023 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
1024 EXPECT_EQ(&ARC, CG.lookupRefSCC(B));
1025 EXPECT_EQ(&ARC, CG.lookupRefSCC(C));
1026 EXPECT_EQ(&ARC, CG.lookupRefSCC(D));
1027
1028 // Check that the SCCs are in postorder.
1029 EXPECT_EQ(4, ARC.size());
1030 EXPECT_EQ(&DC, &ARC[0]);
1031 EXPECT_EQ(&CC, &ARC[1]);
1032 EXPECT_EQ(&BC, &ARC[2]);
1033 EXPECT_EQ(&AC, &ARC[3]);
1034
1035 // And verify the post-order walk reflects the updated structure.
1036 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
1037 ASSERT_NE(I, E);
1038 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
1039 EXPECT_EQ(++I, E);
1040}
1041
1042TEST(LazyCallGraphTest, IncomingEdgeInsertionLargeRefCycle) {
1043 LLVMContext Context;
1044 std::unique_ptr<Module> M =
1045 parseAssembly(Context, "define void @a() {\n"
1046 "entry:\n"
1047 " %p = alloca void ()*\n"
1048 " store void ()* @b, void ()** %p\n"
1049 " ret void\n"
1050 "}\n"
1051 "define void @b() {\n"
1052 "entry:\n"
1053 " %p = alloca void ()*\n"
1054 " store void ()* @c, void ()** %p\n"
1055 " ret void\n"
1056 "}\n"
1057 "define void @c() {\n"
1058 "entry:\n"
1059 " %p = alloca void ()*\n"
1060 " store void ()* @d, void ()** %p\n"
1061 " ret void\n"
1062 "}\n"
1063 "define void @d() {\n"
1064 "entry:\n"
1065 " ret void\n"
1066 "}\n");
1067 LazyCallGraph CG(*M);
1068
1069 // Force the graph to be fully expanded.
1070 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
1071 dbgs() << "Formed RefSCC: " << RC << "\n";
1072
1073 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1074 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1075 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1076 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
1077 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(A);
1078 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(B);
1079 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(C);
1080 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(D);
1081
1082 // Connect the top to the bottom forming a large RefSCC made up just of
1083 // references.
1084 auto MergedRCs = ARC.insertIncomingRefEdge(D, A);
1085 // Make sure we connected the nodes.
1086 EXPECT_NE(D.begin(), D.end());
1087 EXPECT_EQ(&A, D.begin()->getNode());
1088
1089 // Check that we have the dead RCs, but ignore the order.
1090 EXPECT_EQ(3u, MergedRCs.size());
1091 EXPECT_NE(find(MergedRCs, &BRC), MergedRCs.end());
1092 EXPECT_NE(find(MergedRCs, &CRC), MergedRCs.end());
1093 EXPECT_NE(find(MergedRCs, &DRC), MergedRCs.end());
1094
1095 // Make sure the nodes point to the right place now.
1096 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
1097 EXPECT_EQ(&ARC, CG.lookupRefSCC(B));
1098 EXPECT_EQ(&ARC, CG.lookupRefSCC(C));
1099 EXPECT_EQ(&ARC, CG.lookupRefSCC(D));
1100
1101 // And verify the post-order walk reflects the updated structure.
1102 auto I = CG.postorder_ref_scc_begin(), End = CG.postorder_ref_scc_end();
1103 ASSERT_NE(I, End);
1104 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
1105 EXPECT_EQ(++I, End);
Chandler Carruth312dddf2014-05-04 09:38:32 +00001106}
1107
Chandler Carruthe5944d92016-02-17 00:18:16 +00001108TEST(LazyCallGraphTest, InternalEdgeMutation) {
Mehdi Amini03b42e42016-04-14 21:59:01 +00001109 LLVMContext Context;
1110 std::unique_ptr<Module> M = parseAssembly(Context, "define void @a() {\n"
1111 "entry:\n"
1112 " call void @b()\n"
1113 " ret void\n"
1114 "}\n"
1115 "define void @b() {\n"
1116 "entry:\n"
1117 " call void @c()\n"
1118 " ret void\n"
1119 "}\n"
1120 "define void @c() {\n"
1121 "entry:\n"
1122 " call void @a()\n"
1123 " ret void\n"
1124 "}\n");
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001125 LazyCallGraph CG(*M);
1126
1127 // Force the graph to be fully expanded.
Chandler Carruthe5944d92016-02-17 00:18:16 +00001128 auto I = CG.postorder_ref_scc_begin();
1129 LazyCallGraph::RefSCC &RC = *I++;
1130 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001131
Chandler Carrutha10e2402014-04-23 23:12:06 +00001132 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1133 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
Chandler Carruthe5944d92016-02-17 00:18:16 +00001134 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1135 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1136 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1137 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
1138 EXPECT_EQ(1, RC.size());
1139 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(A));
1140 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(B));
1141 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(C));
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001142
Chandler Carruthe5944d92016-02-17 00:18:16 +00001143 // Insert an edge from 'a' to 'c'. Nothing changes about the graph.
1144 RC.insertInternalRefEdge(A, C);
Chandler Carruth5217c942014-04-30 10:48:36 +00001145 EXPECT_EQ(2, std::distance(A.begin(), A.end()));
Chandler Carruthe5944d92016-02-17 00:18:16 +00001146 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1147 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1148 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
1149 EXPECT_EQ(1, RC.size());
1150 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(A));
1151 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(B));
1152 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(C));
Chandler Carruth5217c942014-04-30 10:48:36 +00001153
Chandler Carruthe5944d92016-02-17 00:18:16 +00001154 // Switch the call edge from 'b' to 'c' to a ref edge. This will break the
1155 // call cycle and cause us to form more SCCs. The RefSCC will remain the same
1156 // though.
1157 RC.switchInternalEdgeToRef(B, C);
1158 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1159 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1160 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
1161 auto J = RC.begin();
1162 // The SCCs must be in *post-order* which means successors before
1163 // predecessors. At this point we have call edges from C to A and from A to
1164 // B. The only valid postorder is B, A, C.
1165 EXPECT_EQ(&*J++, CG.lookupSCC(B));
1166 EXPECT_EQ(&*J++, CG.lookupSCC(A));
1167 EXPECT_EQ(&*J++, CG.lookupSCC(C));
1168 EXPECT_EQ(RC.end(), J);
1169
1170 // Test turning the ref edge from A to C into a call edge. This will form an
1171 // SCC out of A and C. Since we previously had a call edge from C to A, the
1172 // C SCC should be preserved and have A merged into it while the A SCC should
1173 // be invalidated.
1174 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
1175 LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
1176 auto InvalidatedSCCs = RC.switchInternalEdgeToCall(A, C);
1177 ASSERT_EQ(1u, InvalidatedSCCs.size());
1178 EXPECT_EQ(&AC, InvalidatedSCCs[0]);
1179 EXPECT_EQ(2, CC.size());
1180 EXPECT_EQ(&CC, CG.lookupSCC(A));
1181 EXPECT_EQ(&CC, CG.lookupSCC(C));
1182 J = RC.begin();
1183 EXPECT_EQ(&*J++, CG.lookupSCC(B));
1184 EXPECT_EQ(&*J++, CG.lookupSCC(C));
1185 EXPECT_EQ(RC.end(), J);
Chandler Carruth5217c942014-04-30 10:48:36 +00001186}
1187
Chandler Carruthe5944d92016-02-17 00:18:16 +00001188TEST(LazyCallGraphTest, InternalEdgeRemoval) {
Mehdi Amini03b42e42016-04-14 21:59:01 +00001189 LLVMContext Context;
Chandler Carruthe5944d92016-02-17 00:18:16 +00001190 // A nice fully connected (including self-edges) RefSCC.
1191 std::unique_ptr<Module> M = parseAssembly(
Mehdi Amini03b42e42016-04-14 21:59:01 +00001192 Context, "define void @a(i8** %ptr) {\n"
1193 "entry:\n"
1194 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1195 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1196 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1197 " ret void\n"
1198 "}\n"
1199 "define void @b(i8** %ptr) {\n"
1200 "entry:\n"
1201 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1202 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1203 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1204 " ret void\n"
1205 "}\n"
1206 "define void @c(i8** %ptr) {\n"
1207 "entry:\n"
1208 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1209 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1210 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1211 " ret void\n"
1212 "}\n");
Chandler Carruthe5944d92016-02-17 00:18:16 +00001213 LazyCallGraph CG(*M);
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001214
1215 // Force the graph to be fully expanded.
Chandler Carruth49d728a2016-09-16 10:20:17 +00001216 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
1217 LazyCallGraph::RefSCC &RC = *I;
1218 EXPECT_EQ(E, std::next(I));
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001219
Chandler Carruthe5944d92016-02-17 00:18:16 +00001220 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1221 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1222 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1223 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1224 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1225 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001226
1227 // Remove the edge from b -> a, which should leave the 3 functions still in
1228 // a single connected component because of a -> b -> c -> a.
Chandler Carruthe5944d92016-02-17 00:18:16 +00001229 SmallVector<LazyCallGraph::RefSCC *, 1> NewRCs =
1230 RC.removeInternalRefEdge(B, A);
1231 EXPECT_EQ(0u, NewRCs.size());
1232 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1233 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1234 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
Chandler Carruth49d728a2016-09-16 10:20:17 +00001235 auto J = CG.postorder_ref_scc_begin();
1236 EXPECT_EQ(I, J);
1237 EXPECT_EQ(&RC, &*J);
1238 EXPECT_EQ(E, std::next(J));
Chandler Carruthe5944d92016-02-17 00:18:16 +00001239
1240 // Remove the edge from c -> a, which should leave 'a' in the original RefSCC
1241 // and form a new RefSCC for 'b' and 'c'.
1242 NewRCs = RC.removeInternalRefEdge(C, A);
1243 EXPECT_EQ(1u, NewRCs.size());
1244 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1245 EXPECT_EQ(1, std::distance(RC.begin(), RC.end()));
Chandler Carruth49d728a2016-09-16 10:20:17 +00001246 LazyCallGraph::RefSCC &RC2 = *CG.lookupRefSCC(B);
1247 EXPECT_EQ(&RC2, CG.lookupRefSCC(C));
1248 EXPECT_EQ(&RC2, NewRCs[0]);
1249 J = CG.postorder_ref_scc_begin();
1250 EXPECT_NE(I, J);
1251 EXPECT_EQ(&RC2, &*J);
1252 ++J;
1253 EXPECT_EQ(I, J);
1254 EXPECT_EQ(&RC, &*J);
1255 ++I;
1256 EXPECT_EQ(E, I);
1257 ++J;
1258 EXPECT_EQ(E, J);
Chandler Carruthe5944d92016-02-17 00:18:16 +00001259}
1260
1261TEST(LazyCallGraphTest, InternalCallEdgeToRef) {
Mehdi Amini03b42e42016-04-14 21:59:01 +00001262 LLVMContext Context;
Chandler Carruthe5944d92016-02-17 00:18:16 +00001263 // A nice fully connected (including self-edges) SCC (and RefSCC)
Mehdi Amini03b42e42016-04-14 21:59:01 +00001264 std::unique_ptr<Module> M = parseAssembly(Context, "define void @a() {\n"
1265 "entry:\n"
1266 " call void @a()\n"
1267 " call void @b()\n"
1268 " call void @c()\n"
1269 " ret void\n"
1270 "}\n"
1271 "define void @b() {\n"
1272 "entry:\n"
1273 " call void @a()\n"
1274 " call void @b()\n"
1275 " call void @c()\n"
1276 " ret void\n"
1277 "}\n"
1278 "define void @c() {\n"
1279 "entry:\n"
1280 " call void @a()\n"
1281 " call void @b()\n"
1282 " call void @c()\n"
1283 " ret void\n"
1284 "}\n");
Chandler Carruthe5944d92016-02-17 00:18:16 +00001285 LazyCallGraph CG(*M);
1286
1287 // Force the graph to be fully expanded.
1288 auto I = CG.postorder_ref_scc_begin();
1289 LazyCallGraph::RefSCC &RC = *I++;
1290 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1291
1292 EXPECT_EQ(1, RC.size());
1293 LazyCallGraph::SCC &CallC = *RC.begin();
1294
1295 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1296 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1297 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1298 EXPECT_EQ(&CallC, CG.lookupSCC(A));
1299 EXPECT_EQ(&CallC, CG.lookupSCC(B));
1300 EXPECT_EQ(&CallC, CG.lookupSCC(C));
1301
1302 // Remove the call edge from b -> a to a ref edge, which should leave the
1303 // 3 functions still in a single connected component because of a -> b ->
1304 // c -> a.
1305 RC.switchInternalEdgeToRef(B, A);
1306 EXPECT_EQ(1, RC.size());
1307 EXPECT_EQ(&CallC, CG.lookupSCC(A));
1308 EXPECT_EQ(&CallC, CG.lookupSCC(B));
1309 EXPECT_EQ(&CallC, CG.lookupSCC(C));
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001310
1311 // Remove the edge from c -> a, which should leave 'a' in the original SCC
1312 // and form a new SCC for 'b' and 'c'.
Chandler Carruthe5944d92016-02-17 00:18:16 +00001313 RC.switchInternalEdgeToRef(C, A);
1314 EXPECT_EQ(2, RC.size());
1315 EXPECT_EQ(&CallC, CG.lookupSCC(A));
1316 LazyCallGraph::SCC &BCallC = *CG.lookupSCC(B);
1317 EXPECT_NE(&BCallC, &CallC);
1318 EXPECT_EQ(&BCallC, CG.lookupSCC(C));
1319 auto J = RC.find(CallC);
1320 EXPECT_EQ(&CallC, &*J);
1321 --J;
1322 EXPECT_EQ(&BCallC, &*J);
1323 EXPECT_EQ(RC.begin(), J);
1324
1325 // Remove the edge from c -> b, which should leave 'b' in the original SCC
1326 // and form a new SCC for 'c'. It shouldn't change 'a's SCC.
1327 RC.switchInternalEdgeToRef(C, B);
1328 EXPECT_EQ(3, RC.size());
1329 EXPECT_EQ(&CallC, CG.lookupSCC(A));
1330 EXPECT_EQ(&BCallC, CG.lookupSCC(B));
1331 LazyCallGraph::SCC &CCallC = *CG.lookupSCC(C);
1332 EXPECT_NE(&CCallC, &CallC);
1333 EXPECT_NE(&CCallC, &BCallC);
1334 J = RC.find(CallC);
1335 EXPECT_EQ(&CallC, &*J);
1336 --J;
1337 EXPECT_EQ(&BCallC, &*J);
1338 --J;
1339 EXPECT_EQ(&CCallC, &*J);
1340 EXPECT_EQ(RC.begin(), J);
1341}
1342
1343TEST(LazyCallGraphTest, InternalRefEdgeToCall) {
Mehdi Amini03b42e42016-04-14 21:59:01 +00001344 LLVMContext Context;
Chandler Carruthe5944d92016-02-17 00:18:16 +00001345 // Basic tests for making a ref edge a call. This hits the basics of the
1346 // process only.
Mehdi Amini03b42e42016-04-14 21:59:01 +00001347 std::unique_ptr<Module> M =
1348 parseAssembly(Context, "define void @a() {\n"
1349 "entry:\n"
1350 " call void @b()\n"
1351 " call void @c()\n"
1352 " store void()* @d, void()** undef\n"
1353 " ret void\n"
1354 "}\n"
1355 "define void @b() {\n"
1356 "entry:\n"
1357 " store void()* @c, void()** undef\n"
1358 " call void @d()\n"
1359 " ret void\n"
1360 "}\n"
1361 "define void @c() {\n"
1362 "entry:\n"
1363 " store void()* @b, void()** undef\n"
1364 " call void @d()\n"
1365 " ret void\n"
1366 "}\n"
1367 "define void @d() {\n"
1368 "entry:\n"
1369 " store void()* @a, void()** undef\n"
1370 " ret void\n"
1371 "}\n");
Chandler Carruthe5944d92016-02-17 00:18:16 +00001372 LazyCallGraph CG(*M);
1373
1374 // Force the graph to be fully expanded.
1375 auto I = CG.postorder_ref_scc_begin();
1376 LazyCallGraph::RefSCC &RC = *I++;
1377 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1378
1379 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1380 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1381 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1382 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
1383 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
1384 LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
1385 LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
1386 LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
1387
1388 // Check the initial post-order. Note that B and C could be flipped here (and
1389 // in our mutation) without changing the nature of this test.
1390 ASSERT_EQ(4, RC.size());
1391 EXPECT_EQ(&DC, &RC[0]);
1392 EXPECT_EQ(&BC, &RC[1]);
1393 EXPECT_EQ(&CC, &RC[2]);
1394 EXPECT_EQ(&AC, &RC[3]);
1395
1396 // Switch the ref edge from A -> D to a call edge. This should have no
1397 // effect as it is already in postorder and no new cycles are formed.
1398 auto MergedCs = RC.switchInternalEdgeToCall(A, D);
1399 EXPECT_EQ(0u, MergedCs.size());
1400 ASSERT_EQ(4, RC.size());
1401 EXPECT_EQ(&DC, &RC[0]);
1402 EXPECT_EQ(&BC, &RC[1]);
1403 EXPECT_EQ(&CC, &RC[2]);
1404 EXPECT_EQ(&AC, &RC[3]);
1405
1406 // Switch B -> C to a call edge. This doesn't form any new cycles but does
1407 // require reordering the SCCs.
1408 MergedCs = RC.switchInternalEdgeToCall(B, C);
1409 EXPECT_EQ(0u, MergedCs.size());
1410 ASSERT_EQ(4, RC.size());
1411 EXPECT_EQ(&DC, &RC[0]);
1412 EXPECT_EQ(&CC, &RC[1]);
1413 EXPECT_EQ(&BC, &RC[2]);
1414 EXPECT_EQ(&AC, &RC[3]);
1415
1416 // Switch C -> B to a call edge. This forms a cycle and forces merging SCCs.
1417 MergedCs = RC.switchInternalEdgeToCall(C, B);
1418 ASSERT_EQ(1u, MergedCs.size());
1419 EXPECT_EQ(&CC, MergedCs[0]);
1420 ASSERT_EQ(3, RC.size());
1421 EXPECT_EQ(&DC, &RC[0]);
1422 EXPECT_EQ(&BC, &RC[1]);
1423 EXPECT_EQ(&AC, &RC[2]);
1424 EXPECT_EQ(2, BC.size());
1425 EXPECT_EQ(&BC, CG.lookupSCC(B));
1426 EXPECT_EQ(&BC, CG.lookupSCC(C));
1427}
1428
1429TEST(LazyCallGraphTest, InternalRefEdgeToCallNoCycleInterleaved) {
Mehdi Amini03b42e42016-04-14 21:59:01 +00001430 LLVMContext Context;
Chandler Carruthe5944d92016-02-17 00:18:16 +00001431 // Test for having a post-order prior to changing a ref edge to a call edge
1432 // with SCCs connecting to the source and connecting to the target, but not
1433 // connecting to both, interleaved between the source and target. This
1434 // ensures we correctly partition the range rather than simply moving one or
1435 // the other.
Mehdi Amini03b42e42016-04-14 21:59:01 +00001436 std::unique_ptr<Module> M =
1437 parseAssembly(Context, "define void @a() {\n"
1438 "entry:\n"
1439 " call void @b1()\n"
1440 " call void @c1()\n"
1441 " ret void\n"
1442 "}\n"
1443 "define void @b1() {\n"
1444 "entry:\n"
1445 " call void @c1()\n"
1446 " call void @b2()\n"
1447 " ret void\n"
1448 "}\n"
1449 "define void @c1() {\n"
1450 "entry:\n"
1451 " call void @b2()\n"
1452 " call void @c2()\n"
1453 " ret void\n"
1454 "}\n"
1455 "define void @b2() {\n"
1456 "entry:\n"
1457 " call void @c2()\n"
1458 " call void @b3()\n"
1459 " ret void\n"
1460 "}\n"
1461 "define void @c2() {\n"
1462 "entry:\n"
1463 " call void @b3()\n"
1464 " call void @c3()\n"
1465 " ret void\n"
1466 "}\n"
1467 "define void @b3() {\n"
1468 "entry:\n"
1469 " call void @c3()\n"
1470 " call void @d()\n"
1471 " ret void\n"
1472 "}\n"
1473 "define void @c3() {\n"
1474 "entry:\n"
1475 " store void()* @b1, void()** undef\n"
1476 " call void @d()\n"
1477 " ret void\n"
1478 "}\n"
1479 "define void @d() {\n"
1480 "entry:\n"
1481 " store void()* @a, void()** undef\n"
1482 " ret void\n"
1483 "}\n");
Chandler Carruthe5944d92016-02-17 00:18:16 +00001484 LazyCallGraph CG(*M);
1485
1486 // Force the graph to be fully expanded.
1487 auto I = CG.postorder_ref_scc_begin();
1488 LazyCallGraph::RefSCC &RC = *I++;
1489 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1490
1491 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1492 LazyCallGraph::Node &B1 = *CG.lookup(lookupFunction(*M, "b1"));
1493 LazyCallGraph::Node &B2 = *CG.lookup(lookupFunction(*M, "b2"));
1494 LazyCallGraph::Node &B3 = *CG.lookup(lookupFunction(*M, "b3"));
1495 LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
1496 LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
1497 LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
1498 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
1499 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
1500 LazyCallGraph::SCC &B1C = *CG.lookupSCC(B1);
1501 LazyCallGraph::SCC &B2C = *CG.lookupSCC(B2);
1502 LazyCallGraph::SCC &B3C = *CG.lookupSCC(B3);
1503 LazyCallGraph::SCC &C1C = *CG.lookupSCC(C1);
1504 LazyCallGraph::SCC &C2C = *CG.lookupSCC(C2);
1505 LazyCallGraph::SCC &C3C = *CG.lookupSCC(C3);
1506 LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
1507
1508 // Several call edges are initially present to force a particual post-order.
1509 // Remove them now, leaving an interleaved post-order pattern.
1510 RC.switchInternalEdgeToRef(B3, C3);
1511 RC.switchInternalEdgeToRef(C2, B3);
1512 RC.switchInternalEdgeToRef(B2, C2);
1513 RC.switchInternalEdgeToRef(C1, B2);
1514 RC.switchInternalEdgeToRef(B1, C1);
1515
1516 // Check the initial post-order. We ensure this order with the extra edges
1517 // that are nuked above.
1518 ASSERT_EQ(8, RC.size());
1519 EXPECT_EQ(&DC, &RC[0]);
1520 EXPECT_EQ(&C3C, &RC[1]);
1521 EXPECT_EQ(&B3C, &RC[2]);
1522 EXPECT_EQ(&C2C, &RC[3]);
1523 EXPECT_EQ(&B2C, &RC[4]);
1524 EXPECT_EQ(&C1C, &RC[5]);
1525 EXPECT_EQ(&B1C, &RC[6]);
1526 EXPECT_EQ(&AC, &RC[7]);
1527
1528 // Switch C3 -> B1 to a call edge. This doesn't form any new cycles but does
1529 // require reordering the SCCs in the face of tricky internal node
1530 // structures.
1531 auto MergedCs = RC.switchInternalEdgeToCall(C3, B1);
1532 EXPECT_EQ(0u, MergedCs.size());
1533 ASSERT_EQ(8, RC.size());
1534 EXPECT_EQ(&DC, &RC[0]);
1535 EXPECT_EQ(&B3C, &RC[1]);
1536 EXPECT_EQ(&B2C, &RC[2]);
1537 EXPECT_EQ(&B1C, &RC[3]);
1538 EXPECT_EQ(&C3C, &RC[4]);
1539 EXPECT_EQ(&C2C, &RC[5]);
1540 EXPECT_EQ(&C1C, &RC[6]);
1541 EXPECT_EQ(&AC, &RC[7]);
1542}
1543
1544TEST(LazyCallGraphTest, InternalRefEdgeToCallBothPartitionAndMerge) {
Mehdi Amini03b42e42016-04-14 21:59:01 +00001545 LLVMContext Context;
Chandler Carruthe5944d92016-02-17 00:18:16 +00001546 // Test for having a postorder where between the source and target are all
1547 // three kinds of other SCCs:
1548 // 1) One connected to the target only that have to be shifted below the
1549 // source.
1550 // 2) One connected to the source only that have to be shifted below the
1551 // target.
1552 // 3) One connected to both source and target that has to remain and get
1553 // merged away.
1554 //
1555 // To achieve this we construct a heavily connected graph to force
1556 // a particular post-order. Then we remove the forcing edges and connect
1557 // a cycle.
1558 //
1559 // Diagram for the graph we want on the left and the graph we use to force
1560 // the ordering on the right. Edges ponit down or right.
1561 //
1562 // A | A |
1563 // / \ | / \ |
1564 // B E | B \ |
1565 // |\ | | |\ | |
1566 // | D | | C-D-E |
1567 // | \| | | \| |
1568 // C F | \ F |
1569 // \ / | \ / |
1570 // G | G |
1571 //
1572 // And we form a cycle by connecting F to B.
Mehdi Amini03b42e42016-04-14 21:59:01 +00001573 std::unique_ptr<Module> M =
1574 parseAssembly(Context, "define void @a() {\n"
1575 "entry:\n"
1576 " call void @b()\n"
1577 " call void @e()\n"
1578 " ret void\n"
1579 "}\n"
1580 "define void @b() {\n"
1581 "entry:\n"
1582 " call void @c()\n"
1583 " call void @d()\n"
1584 " ret void\n"
1585 "}\n"
1586 "define void @c() {\n"
1587 "entry:\n"
1588 " call void @d()\n"
1589 " call void @g()\n"
1590 " ret void\n"
1591 "}\n"
1592 "define void @d() {\n"
1593 "entry:\n"
1594 " call void @e()\n"
1595 " call void @f()\n"
1596 " ret void\n"
1597 "}\n"
1598 "define void @e() {\n"
1599 "entry:\n"
1600 " call void @f()\n"
1601 " ret void\n"
1602 "}\n"
1603 "define void @f() {\n"
1604 "entry:\n"
1605 " store void()* @b, void()** undef\n"
1606 " call void @g()\n"
1607 " ret void\n"
1608 "}\n"
1609 "define void @g() {\n"
1610 "entry:\n"
1611 " store void()* @a, void()** undef\n"
1612 " ret void\n"
1613 "}\n");
Chandler Carruthe5944d92016-02-17 00:18:16 +00001614 LazyCallGraph CG(*M);
1615
1616 // Force the graph to be fully expanded.
1617 auto I = CG.postorder_ref_scc_begin();
1618 LazyCallGraph::RefSCC &RC = *I++;
1619 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1620
1621 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1622 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1623 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1624 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
1625 LazyCallGraph::Node &E = *CG.lookup(lookupFunction(*M, "e"));
1626 LazyCallGraph::Node &F = *CG.lookup(lookupFunction(*M, "f"));
1627 LazyCallGraph::Node &G = *CG.lookup(lookupFunction(*M, "g"));
1628 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
1629 LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
1630 LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
1631 LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
1632 LazyCallGraph::SCC &EC = *CG.lookupSCC(E);
1633 LazyCallGraph::SCC &FC = *CG.lookupSCC(F);
1634 LazyCallGraph::SCC &GC = *CG.lookupSCC(G);
1635
1636 // Remove the extra edges that were used to force a particular post-order.
1637 RC.switchInternalEdgeToRef(C, D);
1638 RC.switchInternalEdgeToRef(D, E);
1639
1640 // Check the initial post-order. We ensure this order with the extra edges
1641 // that are nuked above.
1642 ASSERT_EQ(7, RC.size());
1643 EXPECT_EQ(&GC, &RC[0]);
1644 EXPECT_EQ(&FC, &RC[1]);
1645 EXPECT_EQ(&EC, &RC[2]);
1646 EXPECT_EQ(&DC, &RC[3]);
1647 EXPECT_EQ(&CC, &RC[4]);
1648 EXPECT_EQ(&BC, &RC[5]);
1649 EXPECT_EQ(&AC, &RC[6]);
1650
1651 // Switch F -> B to a call edge. This merges B, D, and F into a single SCC,
1652 // and has to place the C and E SCCs on either side of it:
1653 // A A |
1654 // / \ / \ |
1655 // B E | E |
1656 // |\ | \ / |
1657 // | D | -> B |
1658 // | \| / \ |
1659 // C F C | |
1660 // \ / \ / |
1661 // G G |
1662 auto MergedCs = RC.switchInternalEdgeToCall(F, B);
1663 ASSERT_EQ(2u, MergedCs.size());
1664 EXPECT_EQ(&FC, MergedCs[0]);
1665 EXPECT_EQ(&DC, MergedCs[1]);
1666 EXPECT_EQ(3, BC.size());
1667
1668 // And make sure the postorder was updated.
1669 ASSERT_EQ(5, RC.size());
1670 EXPECT_EQ(&GC, &RC[0]);
1671 EXPECT_EQ(&CC, &RC[1]);
1672 EXPECT_EQ(&BC, &RC[2]);
1673 EXPECT_EQ(&EC, &RC[3]);
1674 EXPECT_EQ(&AC, &RC[4]);
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001675}
1676
Chandler Carruthc7bad9a2014-04-23 08:08:49 +00001677}