blob: 66cd9a1e4850e88c4196ef1741bde7da5a38cd91 [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"
Chandler Carruth5dbc1642016-10-12 07:59:56 +000012#include "llvm/IR/Instructions.h"
Chandler Carruthc7bad9a2014-04-23 08:08:49 +000013#include "llvm/IR/Function.h"
14#include "llvm/IR/LLVMContext.h"
15#include "llvm/IR/Module.h"
16#include "llvm/Support/ErrorHandling.h"
17#include "llvm/Support/SourceMgr.h"
18#include "gtest/gtest.h"
19#include <memory>
20
21using namespace llvm;
22
23namespace {
24
Mehdi Amini03b42e42016-04-14 21:59:01 +000025std::unique_ptr<Module> parseAssembly(LLVMContext &Context,
26 const char *Assembly) {
Chandler Carruthc7bad9a2014-04-23 08:08:49 +000027 SMDiagnostic Error;
Mehdi Amini03b42e42016-04-14 21:59:01 +000028 std::unique_ptr<Module> M = parseAssemblyString(Assembly, Error, Context);
Chandler Carruthc7bad9a2014-04-23 08:08:49 +000029
30 std::string ErrMsg;
31 raw_string_ostream OS(ErrMsg);
32 Error.print("", OS);
33
34 // A failure here means that the test itself is buggy.
Rafael Espindola11c07d72014-08-19 16:58:54 +000035 if (!M)
Chandler Carruthc7bad9a2014-04-23 08:08:49 +000036 report_fatal_error(OS.str().c_str());
37
38 return M;
39}
40
Filipe Cabecinhas39545662014-10-22 02:16:06 +000041/*
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 */
Chandler Carruthc7bad9a2014-04-23 08:08:49 +000058static const char DiamondOfTriangles[] =
59 "define void @a1() {\n"
60 "entry:\n"
61 " call void @a2()\n"
62 " call void @b2()\n"
63 " call void @c3()\n"
64 " ret void\n"
65 "}\n"
66 "define void @a2() {\n"
67 "entry:\n"
68 " call void @a3()\n"
69 " ret void\n"
70 "}\n"
71 "define void @a3() {\n"
72 "entry:\n"
73 " call void @a1()\n"
74 " ret void\n"
75 "}\n"
76 "define void @b1() {\n"
77 "entry:\n"
78 " call void @b2()\n"
79 " call void @d3()\n"
80 " ret void\n"
81 "}\n"
82 "define void @b2() {\n"
83 "entry:\n"
84 " call void @b3()\n"
85 " ret void\n"
86 "}\n"
87 "define void @b3() {\n"
88 "entry:\n"
89 " call void @b1()\n"
90 " ret void\n"
91 "}\n"
92 "define void @c1() {\n"
93 "entry:\n"
94 " call void @c2()\n"
95 " call void @d2()\n"
96 " ret void\n"
97 "}\n"
98 "define void @c2() {\n"
99 "entry:\n"
100 " call void @c3()\n"
101 " ret void\n"
102 "}\n"
103 "define void @c3() {\n"
104 "entry:\n"
105 " call void @c1()\n"
106 " ret void\n"
107 "}\n"
108 "define void @d1() {\n"
109 "entry:\n"
110 " call void @d2()\n"
111 " ret void\n"
112 "}\n"
113 "define void @d2() {\n"
114 "entry:\n"
115 " call void @d3()\n"
116 " ret void\n"
117 "}\n"
118 "define void @d3() {\n"
119 "entry:\n"
120 " call void @d1()\n"
121 " ret void\n"
122 "}\n";
123
Chandler Carruth49d728a2016-09-16 10:20:17 +0000124/*
125 IR forming a reference graph with a diamond of triangle-shaped RefSCCs
126
127 d1
128 / \
129 d3--d2
130 / \
131 b1 c1
132 / \ / \
133 b3--b2 c3--c2
134 \ /
135 a1
136 / \
137 a3--a2
138
139 All call edges go up between RefSCCs, and clockwise around the RefSCC.
140 */
141static const char DiamondOfTrianglesRefGraph[] =
142 "define void @a1() {\n"
143 "entry:\n"
144 " %a = alloca void ()*\n"
145 " store void ()* @a2, void ()** %a\n"
146 " store void ()* @b2, void ()** %a\n"
147 " store void ()* @c3, void ()** %a\n"
148 " ret void\n"
149 "}\n"
150 "define void @a2() {\n"
151 "entry:\n"
152 " %a = alloca void ()*\n"
153 " store void ()* @a3, void ()** %a\n"
154 " ret void\n"
155 "}\n"
156 "define void @a3() {\n"
157 "entry:\n"
158 " %a = alloca void ()*\n"
159 " store void ()* @a1, void ()** %a\n"
160 " ret void\n"
161 "}\n"
162 "define void @b1() {\n"
163 "entry:\n"
164 " %a = alloca void ()*\n"
165 " store void ()* @b2, void ()** %a\n"
166 " store void ()* @d3, void ()** %a\n"
167 " ret void\n"
168 "}\n"
169 "define void @b2() {\n"
170 "entry:\n"
171 " %a = alloca void ()*\n"
172 " store void ()* @b3, void ()** %a\n"
173 " ret void\n"
174 "}\n"
175 "define void @b3() {\n"
176 "entry:\n"
177 " %a = alloca void ()*\n"
178 " store void ()* @b1, void ()** %a\n"
179 " ret void\n"
180 "}\n"
181 "define void @c1() {\n"
182 "entry:\n"
183 " %a = alloca void ()*\n"
184 " store void ()* @c2, void ()** %a\n"
185 " store void ()* @d2, void ()** %a\n"
186 " ret void\n"
187 "}\n"
188 "define void @c2() {\n"
189 "entry:\n"
190 " %a = alloca void ()*\n"
191 " store void ()* @c3, void ()** %a\n"
192 " ret void\n"
193 "}\n"
194 "define void @c3() {\n"
195 "entry:\n"
196 " %a = alloca void ()*\n"
197 " store void ()* @c1, void ()** %a\n"
198 " ret void\n"
199 "}\n"
200 "define void @d1() {\n"
201 "entry:\n"
202 " %a = alloca void ()*\n"
203 " store void ()* @d2, void ()** %a\n"
204 " ret void\n"
205 "}\n"
206 "define void @d2() {\n"
207 "entry:\n"
208 " %a = alloca void ()*\n"
209 " store void ()* @d3, void ()** %a\n"
210 " ret void\n"
211 "}\n"
212 "define void @d3() {\n"
213 "entry:\n"
214 " %a = alloca void ()*\n"
215 " store void ()* @d1, void ()** %a\n"
216 " ret void\n"
217 "}\n";
218
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000219TEST(LazyCallGraphTest, BasicGraphFormation) {
Mehdi Amini03b42e42016-04-14 21:59:01 +0000220 LLVMContext Context;
221 std::unique_ptr<Module> M = parseAssembly(Context, DiamondOfTriangles);
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000222 LazyCallGraph CG(*M);
223
224 // The order of the entry nodes should be stable w.r.t. the source order of
225 // the IR, and everything in our module is an entry node, so just directly
226 // build variables for each node.
227 auto I = CG.begin();
Chandler Carrutha4499e92016-02-02 03:57:13 +0000228 LazyCallGraph::Node &A1 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000229 EXPECT_EQ("a1", A1.getFunction().getName());
Chandler Carrutha4499e92016-02-02 03:57:13 +0000230 LazyCallGraph::Node &A2 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000231 EXPECT_EQ("a2", A2.getFunction().getName());
Chandler Carrutha4499e92016-02-02 03:57:13 +0000232 LazyCallGraph::Node &A3 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000233 EXPECT_EQ("a3", A3.getFunction().getName());
Chandler Carrutha4499e92016-02-02 03:57:13 +0000234 LazyCallGraph::Node &B1 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000235 EXPECT_EQ("b1", B1.getFunction().getName());
Chandler Carrutha4499e92016-02-02 03:57:13 +0000236 LazyCallGraph::Node &B2 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000237 EXPECT_EQ("b2", B2.getFunction().getName());
Chandler Carrutha4499e92016-02-02 03:57:13 +0000238 LazyCallGraph::Node &B3 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000239 EXPECT_EQ("b3", B3.getFunction().getName());
Chandler Carrutha4499e92016-02-02 03:57:13 +0000240 LazyCallGraph::Node &C1 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000241 EXPECT_EQ("c1", C1.getFunction().getName());
Chandler Carrutha4499e92016-02-02 03:57:13 +0000242 LazyCallGraph::Node &C2 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000243 EXPECT_EQ("c2", C2.getFunction().getName());
Chandler Carrutha4499e92016-02-02 03:57:13 +0000244 LazyCallGraph::Node &C3 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000245 EXPECT_EQ("c3", C3.getFunction().getName());
Chandler Carrutha4499e92016-02-02 03:57:13 +0000246 LazyCallGraph::Node &D1 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000247 EXPECT_EQ("d1", D1.getFunction().getName());
Chandler Carrutha4499e92016-02-02 03:57:13 +0000248 LazyCallGraph::Node &D2 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000249 EXPECT_EQ("d2", D2.getFunction().getName());
Chandler Carrutha4499e92016-02-02 03:57:13 +0000250 LazyCallGraph::Node &D3 = (I++)->getNode(CG);
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000251 EXPECT_EQ("d3", D3.getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000252 EXPECT_EQ(CG.end(), I);
253
254 // Build vectors and sort them for the rest of the assertions to make them
255 // independent of order.
256 std::vector<std::string> Nodes;
257
Chandler Carrutha4499e92016-02-02 03:57:13 +0000258 for (LazyCallGraph::Edge &E : A1)
259 Nodes.push_back(E.getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000260 std::sort(Nodes.begin(), Nodes.end());
261 EXPECT_EQ("a2", Nodes[0]);
262 EXPECT_EQ("b2", Nodes[1]);
263 EXPECT_EQ("c3", Nodes[2]);
264 Nodes.clear();
265
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000266 EXPECT_EQ(A2.end(), std::next(A2.begin()));
267 EXPECT_EQ("a3", A2.begin()->getFunction().getName());
268 EXPECT_EQ(A3.end(), std::next(A3.begin()));
269 EXPECT_EQ("a1", A3.begin()->getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000270
Chandler Carrutha4499e92016-02-02 03:57:13 +0000271 for (LazyCallGraph::Edge &E : B1)
272 Nodes.push_back(E.getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000273 std::sort(Nodes.begin(), Nodes.end());
274 EXPECT_EQ("b2", Nodes[0]);
275 EXPECT_EQ("d3", Nodes[1]);
276 Nodes.clear();
277
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000278 EXPECT_EQ(B2.end(), std::next(B2.begin()));
279 EXPECT_EQ("b3", B2.begin()->getFunction().getName());
280 EXPECT_EQ(B3.end(), std::next(B3.begin()));
281 EXPECT_EQ("b1", B3.begin()->getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000282
Chandler Carrutha4499e92016-02-02 03:57:13 +0000283 for (LazyCallGraph::Edge &E : C1)
284 Nodes.push_back(E.getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000285 std::sort(Nodes.begin(), Nodes.end());
286 EXPECT_EQ("c2", Nodes[0]);
287 EXPECT_EQ("d2", Nodes[1]);
288 Nodes.clear();
289
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000290 EXPECT_EQ(C2.end(), std::next(C2.begin()));
291 EXPECT_EQ("c3", C2.begin()->getFunction().getName());
292 EXPECT_EQ(C3.end(), std::next(C3.begin()));
293 EXPECT_EQ("c1", C3.begin()->getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000294
Chandler Carruthbd5d3082014-04-23 23:34:48 +0000295 EXPECT_EQ(D1.end(), std::next(D1.begin()));
296 EXPECT_EQ("d2", D1.begin()->getFunction().getName());
297 EXPECT_EQ(D2.end(), std::next(D2.begin()));
298 EXPECT_EQ("d3", D2.begin()->getFunction().getName());
299 EXPECT_EQ(D3.end(), std::next(D3.begin()));
300 EXPECT_EQ("d1", D3.begin()->getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000301
Chandler Carruthe5944d92016-02-17 00:18:16 +0000302 // Now lets look at the RefSCCs and SCCs.
303 auto J = CG.postorder_ref_scc_begin();
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000304
Chandler Carruthe5944d92016-02-17 00:18:16 +0000305 LazyCallGraph::RefSCC &D = *J++;
306 ASSERT_EQ(1, D.size());
307 for (LazyCallGraph::Node &N : *D.begin())
308 Nodes.push_back(N.getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000309 std::sort(Nodes.begin(), Nodes.end());
Chandler Carruthead50d32014-04-24 09:59:56 +0000310 EXPECT_EQ(3u, Nodes.size());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000311 EXPECT_EQ("d1", Nodes[0]);
312 EXPECT_EQ("d2", Nodes[1]);
313 EXPECT_EQ("d3", Nodes[2]);
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000314 Nodes.clear();
Chandler Carruth4b096742014-05-01 12:12:42 +0000315 EXPECT_FALSE(D.isParentOf(D));
316 EXPECT_FALSE(D.isChildOf(D));
317 EXPECT_FALSE(D.isAncestorOf(D));
318 EXPECT_FALSE(D.isDescendantOf(D));
Chandler Carruth49d728a2016-09-16 10:20:17 +0000319 EXPECT_EQ(&D, &*CG.postorder_ref_scc_begin());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000320
Chandler Carruthe5944d92016-02-17 00:18:16 +0000321 LazyCallGraph::RefSCC &C = *J++;
322 ASSERT_EQ(1, C.size());
323 for (LazyCallGraph::Node &N : *C.begin())
324 Nodes.push_back(N.getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000325 std::sort(Nodes.begin(), Nodes.end());
Chandler Carruthead50d32014-04-24 09:59:56 +0000326 EXPECT_EQ(3u, Nodes.size());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000327 EXPECT_EQ("c1", Nodes[0]);
328 EXPECT_EQ("c2", Nodes[1]);
329 EXPECT_EQ("c3", Nodes[2]);
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000330 Nodes.clear();
Chandler Carruth4b096742014-05-01 12:12:42 +0000331 EXPECT_TRUE(C.isParentOf(D));
332 EXPECT_FALSE(C.isChildOf(D));
333 EXPECT_TRUE(C.isAncestorOf(D));
334 EXPECT_FALSE(C.isDescendantOf(D));
Chandler Carruth49d728a2016-09-16 10:20:17 +0000335 EXPECT_EQ(&C, &*std::next(CG.postorder_ref_scc_begin()));
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000336
Chandler Carruthe5944d92016-02-17 00:18:16 +0000337 LazyCallGraph::RefSCC &B = *J++;
338 ASSERT_EQ(1, B.size());
339 for (LazyCallGraph::Node &N : *B.begin())
340 Nodes.push_back(N.getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000341 std::sort(Nodes.begin(), Nodes.end());
Chandler Carruthead50d32014-04-24 09:59:56 +0000342 EXPECT_EQ(3u, Nodes.size());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000343 EXPECT_EQ("b1", Nodes[0]);
344 EXPECT_EQ("b2", Nodes[1]);
345 EXPECT_EQ("b3", Nodes[2]);
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000346 Nodes.clear();
Chandler Carruth4b096742014-05-01 12:12:42 +0000347 EXPECT_TRUE(B.isParentOf(D));
348 EXPECT_FALSE(B.isChildOf(D));
349 EXPECT_TRUE(B.isAncestorOf(D));
350 EXPECT_FALSE(B.isDescendantOf(D));
351 EXPECT_FALSE(B.isAncestorOf(C));
352 EXPECT_FALSE(C.isAncestorOf(B));
Chandler Carruth49d728a2016-09-16 10:20:17 +0000353 EXPECT_EQ(&B, &*std::next(CG.postorder_ref_scc_begin(), 2));
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000354
Chandler Carruthe5944d92016-02-17 00:18:16 +0000355 LazyCallGraph::RefSCC &A = *J++;
356 ASSERT_EQ(1, A.size());
357 for (LazyCallGraph::Node &N : *A.begin())
358 Nodes.push_back(N.getFunction().getName());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000359 std::sort(Nodes.begin(), Nodes.end());
Chandler Carruthead50d32014-04-24 09:59:56 +0000360 EXPECT_EQ(3u, Nodes.size());
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000361 EXPECT_EQ("a1", Nodes[0]);
362 EXPECT_EQ("a2", Nodes[1]);
363 EXPECT_EQ("a3", Nodes[2]);
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000364 Nodes.clear();
Chandler Carruth4b096742014-05-01 12:12:42 +0000365 EXPECT_TRUE(A.isParentOf(B));
366 EXPECT_TRUE(A.isParentOf(C));
367 EXPECT_FALSE(A.isParentOf(D));
368 EXPECT_TRUE(A.isAncestorOf(B));
369 EXPECT_TRUE(A.isAncestorOf(C));
370 EXPECT_TRUE(A.isAncestorOf(D));
Chandler Carruth49d728a2016-09-16 10:20:17 +0000371 EXPECT_EQ(&A, &*std::next(CG.postorder_ref_scc_begin(), 3));
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000372
Chandler Carruthe5944d92016-02-17 00:18:16 +0000373 EXPECT_EQ(CG.postorder_ref_scc_end(), J);
Chandler Carruth49d728a2016-09-16 10:20:17 +0000374 EXPECT_EQ(J, std::next(CG.postorder_ref_scc_begin(), 4));
Chandler Carruthc7bad9a2014-04-23 08:08:49 +0000375}
376
Chandler Carruthcace6622014-04-23 10:31:17 +0000377static Function &lookupFunction(Module &M, StringRef Name) {
378 for (Function &F : M)
379 if (F.getName() == Name)
380 return F;
381 report_fatal_error("Couldn't find function!");
382}
383
Chandler Carruthc00a7ff2014-04-28 11:10:23 +0000384TEST(LazyCallGraphTest, BasicGraphMutation) {
Mehdi Amini03b42e42016-04-14 21:59:01 +0000385 LLVMContext Context;
386 std::unique_ptr<Module> M = parseAssembly(Context, "define void @a() {\n"
387 "entry:\n"
388 " call void @b()\n"
389 " call void @c()\n"
390 " ret void\n"
391 "}\n"
392 "define void @b() {\n"
393 "entry:\n"
394 " ret void\n"
395 "}\n"
396 "define void @c() {\n"
397 "entry:\n"
398 " ret void\n"
399 "}\n");
Chandler Carruthc00a7ff2014-04-28 11:10:23 +0000400 LazyCallGraph CG(*M);
401
402 LazyCallGraph::Node &A = CG.get(lookupFunction(*M, "a"));
403 LazyCallGraph::Node &B = CG.get(lookupFunction(*M, "b"));
404 EXPECT_EQ(2, std::distance(A.begin(), A.end()));
405 EXPECT_EQ(0, std::distance(B.begin(), B.end()));
406
Chandler Carrutha4499e92016-02-02 03:57:13 +0000407 CG.insertEdge(B, lookupFunction(*M, "c"), LazyCallGraph::Edge::Call);
Chandler Carruthc00a7ff2014-04-28 11:10:23 +0000408 EXPECT_EQ(1, std::distance(B.begin(), B.end()));
Chandler Carrutha4499e92016-02-02 03:57:13 +0000409 LazyCallGraph::Node &C = B.begin()->getNode(CG);
Chandler Carruthc00a7ff2014-04-28 11:10:23 +0000410 EXPECT_EQ(0, std::distance(C.begin(), C.end()));
411
Chandler Carrutha4499e92016-02-02 03:57:13 +0000412 CG.insertEdge(C, B.getFunction(), LazyCallGraph::Edge::Call);
Chandler Carruthc00a7ff2014-04-28 11:10:23 +0000413 EXPECT_EQ(1, std::distance(C.begin(), C.end()));
Chandler Carrutha4499e92016-02-02 03:57:13 +0000414 EXPECT_EQ(&B, C.begin()->getNode());
Chandler Carruthc00a7ff2014-04-28 11:10:23 +0000415
Chandler Carrutha4499e92016-02-02 03:57:13 +0000416 CG.insertEdge(C, C.getFunction(), LazyCallGraph::Edge::Call);
Chandler Carruthc00a7ff2014-04-28 11:10:23 +0000417 EXPECT_EQ(2, std::distance(C.begin(), C.end()));
Chandler Carrutha4499e92016-02-02 03:57:13 +0000418 EXPECT_EQ(&B, C.begin()->getNode());
419 EXPECT_EQ(&C, std::next(C.begin())->getNode());
Chandler Carruthc5026b62014-04-30 07:45:27 +0000420
421 CG.removeEdge(C, B.getFunction());
422 EXPECT_EQ(1, std::distance(C.begin(), C.end()));
Chandler Carrutha4499e92016-02-02 03:57:13 +0000423 EXPECT_EQ(&C, C.begin()->getNode());
Chandler Carruthc5026b62014-04-30 07:45:27 +0000424
425 CG.removeEdge(C, C.getFunction());
426 EXPECT_EQ(0, std::distance(C.begin(), C.end()));
427
428 CG.removeEdge(B, C.getFunction());
429 EXPECT_EQ(0, std::distance(B.begin(), B.end()));
Chandler Carruthc00a7ff2014-04-28 11:10:23 +0000430}
431
Chandler Carruthe5944d92016-02-17 00:18:16 +0000432TEST(LazyCallGraphTest, InnerSCCFormation) {
Mehdi Amini03b42e42016-04-14 21:59:01 +0000433 LLVMContext Context;
434 std::unique_ptr<Module> M = parseAssembly(Context, DiamondOfTriangles);
Chandler Carruthe5944d92016-02-17 00:18:16 +0000435 LazyCallGraph CG(*M);
436
437 // Now mutate the graph to connect every node into a single RefSCC to ensure
438 // that our inner SCC formation handles the rest.
439 CG.insertEdge(lookupFunction(*M, "d1"), lookupFunction(*M, "a1"),
440 LazyCallGraph::Edge::Ref);
441
442 // Build vectors and sort them for the rest of the assertions to make them
443 // independent of order.
444 std::vector<std::string> Nodes;
445
446 // We should build a single RefSCC for the entire graph.
447 auto I = CG.postorder_ref_scc_begin();
448 LazyCallGraph::RefSCC &RC = *I++;
449 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
450
451 // Now walk the four SCCs which should be in post-order.
452 auto J = RC.begin();
453 LazyCallGraph::SCC &D = *J++;
454 for (LazyCallGraph::Node &N : D)
455 Nodes.push_back(N.getFunction().getName());
456 std::sort(Nodes.begin(), Nodes.end());
457 EXPECT_EQ(3u, Nodes.size());
458 EXPECT_EQ("d1", Nodes[0]);
459 EXPECT_EQ("d2", Nodes[1]);
460 EXPECT_EQ("d3", Nodes[2]);
461 Nodes.clear();
462
463 LazyCallGraph::SCC &B = *J++;
464 for (LazyCallGraph::Node &N : B)
465 Nodes.push_back(N.getFunction().getName());
466 std::sort(Nodes.begin(), Nodes.end());
467 EXPECT_EQ(3u, Nodes.size());
468 EXPECT_EQ("b1", Nodes[0]);
469 EXPECT_EQ("b2", Nodes[1]);
470 EXPECT_EQ("b3", Nodes[2]);
471 Nodes.clear();
472
473 LazyCallGraph::SCC &C = *J++;
474 for (LazyCallGraph::Node &N : C)
475 Nodes.push_back(N.getFunction().getName());
476 std::sort(Nodes.begin(), Nodes.end());
477 EXPECT_EQ(3u, Nodes.size());
478 EXPECT_EQ("c1", Nodes[0]);
479 EXPECT_EQ("c2", Nodes[1]);
480 EXPECT_EQ("c3", Nodes[2]);
481 Nodes.clear();
482
483 LazyCallGraph::SCC &A = *J++;
484 for (LazyCallGraph::Node &N : A)
485 Nodes.push_back(N.getFunction().getName());
486 std::sort(Nodes.begin(), Nodes.end());
487 EXPECT_EQ(3u, Nodes.size());
488 EXPECT_EQ("a1", Nodes[0]);
489 EXPECT_EQ("a2", Nodes[1]);
490 EXPECT_EQ("a3", Nodes[2]);
491 Nodes.clear();
492
493 EXPECT_EQ(RC.end(), J);
494}
495
Chandler Carruthcace6622014-04-23 10:31:17 +0000496TEST(LazyCallGraphTest, MultiArmSCC) {
Mehdi Amini03b42e42016-04-14 21:59:01 +0000497 LLVMContext Context;
Chandler Carruthcace6622014-04-23 10:31:17 +0000498 // Two interlocking cycles. The really useful thing about this SCC is that it
499 // will require Tarjan's DFS to backtrack and finish processing all of the
Chandler Carruthe5944d92016-02-17 00:18:16 +0000500 // children of each node in the SCC. Since this involves call edges, both
501 // Tarjan implementations will have to successfully navigate the structure.
Mehdi Amini03b42e42016-04-14 21:59:01 +0000502 std::unique_ptr<Module> M = parseAssembly(Context, "define void @f1() {\n"
503 "entry:\n"
504 " call void @f2()\n"
505 " call void @f4()\n"
506 " ret void\n"
507 "}\n"
508 "define void @f2() {\n"
509 "entry:\n"
510 " call void @f3()\n"
511 " ret void\n"
512 "}\n"
513 "define void @f3() {\n"
514 "entry:\n"
515 " call void @f1()\n"
516 " ret void\n"
517 "}\n"
518 "define void @f4() {\n"
519 "entry:\n"
520 " call void @f5()\n"
521 " ret void\n"
522 "}\n"
523 "define void @f5() {\n"
524 "entry:\n"
525 " call void @f1()\n"
526 " ret void\n"
527 "}\n");
Chandler Carruthcace6622014-04-23 10:31:17 +0000528 LazyCallGraph CG(*M);
529
530 // Force the graph to be fully expanded.
Chandler Carruthe5944d92016-02-17 00:18:16 +0000531 auto I = CG.postorder_ref_scc_begin();
532 LazyCallGraph::RefSCC &RC = *I++;
533 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
Chandler Carruthcace6622014-04-23 10:31:17 +0000534
Chandler Carruthe5944d92016-02-17 00:18:16 +0000535 LazyCallGraph::Node &N1 = *CG.lookup(lookupFunction(*M, "f1"));
536 LazyCallGraph::Node &N2 = *CG.lookup(lookupFunction(*M, "f2"));
537 LazyCallGraph::Node &N3 = *CG.lookup(lookupFunction(*M, "f3"));
538 LazyCallGraph::Node &N4 = *CG.lookup(lookupFunction(*M, "f4"));
539 LazyCallGraph::Node &N5 = *CG.lookup(lookupFunction(*M, "f4"));
540 EXPECT_EQ(&RC, CG.lookupRefSCC(N1));
541 EXPECT_EQ(&RC, CG.lookupRefSCC(N2));
542 EXPECT_EQ(&RC, CG.lookupRefSCC(N3));
543 EXPECT_EQ(&RC, CG.lookupRefSCC(N4));
544 EXPECT_EQ(&RC, CG.lookupRefSCC(N5));
545
546 ASSERT_EQ(1, RC.size());
547
548 LazyCallGraph::SCC &C = *RC.begin();
549 EXPECT_EQ(&C, CG.lookupSCC(N1));
550 EXPECT_EQ(&C, CG.lookupSCC(N2));
551 EXPECT_EQ(&C, CG.lookupSCC(N3));
552 EXPECT_EQ(&C, CG.lookupSCC(N4));
553 EXPECT_EQ(&C, CG.lookupSCC(N5));
Chandler Carruthcace6622014-04-23 10:31:17 +0000554}
555
Chandler Carruthe5944d92016-02-17 00:18:16 +0000556TEST(LazyCallGraphTest, OutgoingEdgeMutation) {
Mehdi Amini03b42e42016-04-14 21:59:01 +0000557 LLVMContext Context;
558 std::unique_ptr<Module> M = parseAssembly(Context, "define void @a() {\n"
559 "entry:\n"
560 " call void @b()\n"
561 " call void @c()\n"
562 " ret void\n"
563 "}\n"
564 "define void @b() {\n"
565 "entry:\n"
566 " call void @d()\n"
567 " ret void\n"
568 "}\n"
569 "define void @c() {\n"
570 "entry:\n"
571 " call void @d()\n"
572 " ret void\n"
573 "}\n"
574 "define void @d() {\n"
575 "entry:\n"
576 " ret void\n"
577 "}\n");
Chandler Carruthcc6e1872014-05-04 09:38:23 +0000578 LazyCallGraph CG(*M);
579
580 // Force the graph to be fully expanded.
Chandler Carruthe5944d92016-02-17 00:18:16 +0000581 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
Chandler Carruth49d728a2016-09-16 10:20:17 +0000582 dbgs() << "Formed RefSCC: " << RC << "\n";
Chandler Carruthcc6e1872014-05-04 09:38:23 +0000583
584 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
585 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
586 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
587 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
588 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
589 LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
590 LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
591 LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
Chandler Carruthe5944d92016-02-17 00:18:16 +0000592 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(A);
593 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(B);
594 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(C);
595 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(D);
596 EXPECT_TRUE(ARC.isParentOf(BRC));
597 EXPECT_TRUE(ARC.isParentOf(CRC));
598 EXPECT_FALSE(ARC.isParentOf(DRC));
599 EXPECT_TRUE(ARC.isAncestorOf(DRC));
600 EXPECT_FALSE(DRC.isChildOf(ARC));
601 EXPECT_TRUE(DRC.isDescendantOf(ARC));
602 EXPECT_TRUE(DRC.isChildOf(BRC));
603 EXPECT_TRUE(DRC.isChildOf(CRC));
Chandler Carruthcc6e1872014-05-04 09:38:23 +0000604
605 EXPECT_EQ(2, std::distance(A.begin(), A.end()));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000606 ARC.insertOutgoingEdge(A, D, LazyCallGraph::Edge::Call);
Chandler Carruthcc6e1872014-05-04 09:38:23 +0000607 EXPECT_EQ(3, std::distance(A.begin(), A.end()));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000608 const LazyCallGraph::Edge &NewE = A[D];
609 EXPECT_TRUE(NewE);
610 EXPECT_TRUE(NewE.isCall());
611 EXPECT_EQ(&D, NewE.getNode());
612
613 // Only the parent and child tests sholud have changed. The rest of the graph
614 // remains the same.
615 EXPECT_TRUE(ARC.isParentOf(DRC));
616 EXPECT_TRUE(ARC.isAncestorOf(DRC));
617 EXPECT_TRUE(DRC.isChildOf(ARC));
618 EXPECT_TRUE(DRC.isDescendantOf(ARC));
Chandler Carruthcc6e1872014-05-04 09:38:23 +0000619 EXPECT_EQ(&AC, CG.lookupSCC(A));
620 EXPECT_EQ(&BC, CG.lookupSCC(B));
621 EXPECT_EQ(&CC, CG.lookupSCC(C));
622 EXPECT_EQ(&DC, CG.lookupSCC(D));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000623 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
624 EXPECT_EQ(&BRC, CG.lookupRefSCC(B));
625 EXPECT_EQ(&CRC, CG.lookupRefSCC(C));
626 EXPECT_EQ(&DRC, CG.lookupRefSCC(D));
627
628 ARC.switchOutgoingEdgeToRef(A, D);
629 EXPECT_FALSE(NewE.isCall());
630
631 // Verify the graph remains the same.
632 EXPECT_TRUE(ARC.isParentOf(DRC));
633 EXPECT_TRUE(ARC.isAncestorOf(DRC));
634 EXPECT_TRUE(DRC.isChildOf(ARC));
635 EXPECT_TRUE(DRC.isDescendantOf(ARC));
636 EXPECT_EQ(&AC, CG.lookupSCC(A));
637 EXPECT_EQ(&BC, CG.lookupSCC(B));
638 EXPECT_EQ(&CC, CG.lookupSCC(C));
639 EXPECT_EQ(&DC, CG.lookupSCC(D));
640 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
641 EXPECT_EQ(&BRC, CG.lookupRefSCC(B));
642 EXPECT_EQ(&CRC, CG.lookupRefSCC(C));
643 EXPECT_EQ(&DRC, CG.lookupRefSCC(D));
644
645 ARC.switchOutgoingEdgeToCall(A, D);
646 EXPECT_TRUE(NewE.isCall());
647
648 // Verify the graph remains the same.
649 EXPECT_TRUE(ARC.isParentOf(DRC));
650 EXPECT_TRUE(ARC.isAncestorOf(DRC));
651 EXPECT_TRUE(DRC.isChildOf(ARC));
652 EXPECT_TRUE(DRC.isDescendantOf(ARC));
653 EXPECT_EQ(&AC, CG.lookupSCC(A));
654 EXPECT_EQ(&BC, CG.lookupSCC(B));
655 EXPECT_EQ(&CC, CG.lookupSCC(C));
656 EXPECT_EQ(&DC, CG.lookupSCC(D));
657 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
658 EXPECT_EQ(&BRC, CG.lookupRefSCC(B));
659 EXPECT_EQ(&CRC, CG.lookupRefSCC(C));
660 EXPECT_EQ(&DRC, CG.lookupRefSCC(D));
661
662 ARC.removeOutgoingEdge(A, D);
663 EXPECT_EQ(2, std::distance(A.begin(), A.end()));
664
665 // Now the parent and child tests fail again but the rest remains the same.
666 EXPECT_FALSE(ARC.isParentOf(DRC));
667 EXPECT_TRUE(ARC.isAncestorOf(DRC));
668 EXPECT_FALSE(DRC.isChildOf(ARC));
669 EXPECT_TRUE(DRC.isDescendantOf(ARC));
670 EXPECT_EQ(&AC, CG.lookupSCC(A));
671 EXPECT_EQ(&BC, CG.lookupSCC(B));
672 EXPECT_EQ(&CC, CG.lookupSCC(C));
673 EXPECT_EQ(&DC, CG.lookupSCC(D));
674 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
675 EXPECT_EQ(&BRC, CG.lookupRefSCC(B));
676 EXPECT_EQ(&CRC, CG.lookupRefSCC(C));
677 EXPECT_EQ(&DRC, CG.lookupRefSCC(D));
Chandler Carruthcc6e1872014-05-04 09:38:23 +0000678}
679
Chandler Carruthe5944d92016-02-17 00:18:16 +0000680TEST(LazyCallGraphTest, IncomingEdgeInsertion) {
Mehdi Amini03b42e42016-04-14 21:59:01 +0000681 LLVMContext Context;
Chandler Carruth312dddf2014-05-04 09:38:32 +0000682 // We want to ensure we can add edges even across complex diamond graphs, so
683 // we use the diamond of triangles graph defined above. The ascii diagram is
684 // repeated here for easy reference.
685 //
686 // d1 |
687 // / \ |
688 // d3--d2 |
689 // / \ |
690 // b1 c1 |
691 // / \ / \ |
692 // b3--b2 c3--c2 |
693 // \ / |
694 // a1 |
695 // / \ |
696 // a3--a2 |
697 //
Mehdi Amini03b42e42016-04-14 21:59:01 +0000698 std::unique_ptr<Module> M = parseAssembly(Context, DiamondOfTriangles);
Chandler Carruth312dddf2014-05-04 09:38:32 +0000699 LazyCallGraph CG(*M);
700
701 // Force the graph to be fully expanded.
Chandler Carruthe5944d92016-02-17 00:18:16 +0000702 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
Chandler Carruth49d728a2016-09-16 10:20:17 +0000703 dbgs() << "Formed RefSCC: " << RC << "\n";
Chandler Carruth312dddf2014-05-04 09:38:32 +0000704
705 LazyCallGraph::Node &A1 = *CG.lookup(lookupFunction(*M, "a1"));
706 LazyCallGraph::Node &A2 = *CG.lookup(lookupFunction(*M, "a2"));
707 LazyCallGraph::Node &A3 = *CG.lookup(lookupFunction(*M, "a3"));
708 LazyCallGraph::Node &B1 = *CG.lookup(lookupFunction(*M, "b1"));
709 LazyCallGraph::Node &B2 = *CG.lookup(lookupFunction(*M, "b2"));
710 LazyCallGraph::Node &B3 = *CG.lookup(lookupFunction(*M, "b3"));
711 LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
712 LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
713 LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
714 LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
715 LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
716 LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000717 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(A1);
718 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(B1);
719 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(C1);
720 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(D1);
721 ASSERT_EQ(&ARC, CG.lookupRefSCC(A2));
722 ASSERT_EQ(&ARC, CG.lookupRefSCC(A3));
723 ASSERT_EQ(&BRC, CG.lookupRefSCC(B2));
724 ASSERT_EQ(&BRC, CG.lookupRefSCC(B3));
725 ASSERT_EQ(&CRC, CG.lookupRefSCC(C2));
726 ASSERT_EQ(&CRC, CG.lookupRefSCC(C3));
727 ASSERT_EQ(&DRC, CG.lookupRefSCC(D2));
728 ASSERT_EQ(&DRC, CG.lookupRefSCC(D3));
Chandler Carruth312dddf2014-05-04 09:38:32 +0000729 ASSERT_EQ(1, std::distance(D2.begin(), D2.end()));
730
731 // Add an edge to make the graph:
732 //
733 // d1 |
734 // / \ |
735 // d3--d2---. |
736 // / \ | |
737 // b1 c1 | |
738 // / \ / \ / |
739 // b3--b2 c3--c2 |
740 // \ / |
741 // a1 |
742 // / \ |
743 // a3--a2 |
Chandler Carruthe5944d92016-02-17 00:18:16 +0000744 auto MergedRCs = CRC.insertIncomingRefEdge(D2, C2);
Chandler Carruth312dddf2014-05-04 09:38:32 +0000745 // Make sure we connected the nodes.
Chandler Carruthe5944d92016-02-17 00:18:16 +0000746 for (LazyCallGraph::Edge E : D2) {
747 if (E.getNode() == &D3)
748 continue;
749 EXPECT_EQ(&C2, E.getNode());
750 }
751 // And marked the D ref-SCC as no longer valid.
752 EXPECT_EQ(1u, MergedRCs.size());
753 EXPECT_EQ(&DRC, MergedRCs[0]);
Chandler Carruth312dddf2014-05-04 09:38:32 +0000754
755 // Make sure we have the correct nodes in the SCC sets.
Chandler Carruthe5944d92016-02-17 00:18:16 +0000756 EXPECT_EQ(&ARC, CG.lookupRefSCC(A1));
757 EXPECT_EQ(&ARC, CG.lookupRefSCC(A2));
758 EXPECT_EQ(&ARC, CG.lookupRefSCC(A3));
759 EXPECT_EQ(&BRC, CG.lookupRefSCC(B1));
760 EXPECT_EQ(&BRC, CG.lookupRefSCC(B2));
761 EXPECT_EQ(&BRC, CG.lookupRefSCC(B3));
762 EXPECT_EQ(&CRC, CG.lookupRefSCC(C1));
763 EXPECT_EQ(&CRC, CG.lookupRefSCC(C2));
764 EXPECT_EQ(&CRC, CG.lookupRefSCC(C3));
765 EXPECT_EQ(&CRC, CG.lookupRefSCC(D1));
766 EXPECT_EQ(&CRC, CG.lookupRefSCC(D2));
767 EXPECT_EQ(&CRC, CG.lookupRefSCC(D3));
Chandler Carruth312dddf2014-05-04 09:38:32 +0000768
769 // And that ancestry tests have been updated.
Chandler Carruthe5944d92016-02-17 00:18:16 +0000770 EXPECT_TRUE(ARC.isParentOf(CRC));
771 EXPECT_TRUE(BRC.isParentOf(CRC));
Chandler Carruth49d728a2016-09-16 10:20:17 +0000772
773 // And verify the post-order walk reflects the updated structure.
774 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
775 ASSERT_NE(I, E);
776 EXPECT_EQ(&CRC, &*I) << "Actual RefSCC: " << *I;
777 ASSERT_NE(++I, E);
778 EXPECT_EQ(&BRC, &*I) << "Actual RefSCC: " << *I;
779 ASSERT_NE(++I, E);
780 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
781 EXPECT_EQ(++I, E);
Chandler Carruth312dddf2014-05-04 09:38:32 +0000782}
783
Chandler Carruthe5944d92016-02-17 00:18:16 +0000784TEST(LazyCallGraphTest, IncomingEdgeInsertionMidTraversal) {
Mehdi Amini03b42e42016-04-14 21:59:01 +0000785 LLVMContext Context;
Chandler Carruth312dddf2014-05-04 09:38:32 +0000786 // This is the same fundamental test as the previous, but we perform it
Chandler Carruthe5944d92016-02-17 00:18:16 +0000787 // having only partially walked the RefSCCs of the graph.
Mehdi Amini03b42e42016-04-14 21:59:01 +0000788 std::unique_ptr<Module> M = parseAssembly(Context, DiamondOfTriangles);
Chandler Carruth312dddf2014-05-04 09:38:32 +0000789 LazyCallGraph CG(*M);
790
Chandler Carruthe5944d92016-02-17 00:18:16 +0000791 // Walk the RefSCCs until we find the one containing 'c1'.
792 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
793 ASSERT_NE(I, E);
794 LazyCallGraph::RefSCC &DRC = *I;
795 ASSERT_NE(&DRC, nullptr);
796 ++I;
797 ASSERT_NE(I, E);
798 LazyCallGraph::RefSCC &CRC = *I;
799 ASSERT_NE(&CRC, nullptr);
Chandler Carruth312dddf2014-05-04 09:38:32 +0000800
801 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a1")));
802 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a2")));
803 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a3")));
804 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b1")));
805 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b2")));
806 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b3")));
807 LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
808 LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
809 LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
810 LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
811 LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
812 LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000813 ASSERT_EQ(&CRC, CG.lookupRefSCC(C1));
814 ASSERT_EQ(&CRC, CG.lookupRefSCC(C2));
815 ASSERT_EQ(&CRC, CG.lookupRefSCC(C3));
816 ASSERT_EQ(&DRC, CG.lookupRefSCC(D1));
817 ASSERT_EQ(&DRC, CG.lookupRefSCC(D2));
818 ASSERT_EQ(&DRC, CG.lookupRefSCC(D3));
Chandler Carruth312dddf2014-05-04 09:38:32 +0000819 ASSERT_EQ(1, std::distance(D2.begin(), D2.end()));
820
Chandler Carruthe5944d92016-02-17 00:18:16 +0000821 auto MergedRCs = CRC.insertIncomingRefEdge(D2, C2);
822 // Make sure we connected the nodes.
823 for (LazyCallGraph::Edge E : D2) {
824 if (E.getNode() == &D3)
825 continue;
826 EXPECT_EQ(&C2, E.getNode());
827 }
828 // And marked the D ref-SCC as no longer valid.
829 EXPECT_EQ(1u, MergedRCs.size());
830 EXPECT_EQ(&DRC, MergedRCs[0]);
Chandler Carruth312dddf2014-05-04 09:38:32 +0000831
Chandler Carruthe5944d92016-02-17 00:18:16 +0000832 // Make sure we have the correct nodes in the RefSCCs.
833 EXPECT_EQ(&CRC, CG.lookupRefSCC(C1));
834 EXPECT_EQ(&CRC, CG.lookupRefSCC(C2));
835 EXPECT_EQ(&CRC, CG.lookupRefSCC(C3));
836 EXPECT_EQ(&CRC, CG.lookupRefSCC(D1));
837 EXPECT_EQ(&CRC, CG.lookupRefSCC(D2));
838 EXPECT_EQ(&CRC, CG.lookupRefSCC(D3));
Chandler Carruth312dddf2014-05-04 09:38:32 +0000839
Chandler Carruth49d728a2016-09-16 10:20:17 +0000840 // Verify that the post-order walk reflects the updated but still incomplete
841 // structure.
842 auto J = CG.postorder_ref_scc_begin();
843 EXPECT_NE(J, E);
844 EXPECT_EQ(&CRC, &*J) << "Actual RefSCC: " << *J;
845 EXPECT_EQ(I, J);
846
847 // Check that we can form the last two RefSCCs now, and even that we can do
848 // it with alternating iterators.
849 ++J;
850 EXPECT_NE(J, E);
851 LazyCallGraph::RefSCC &BRC = *J;
Chandler Carruthe5944d92016-02-17 00:18:16 +0000852 EXPECT_NE(&BRC, nullptr);
853 EXPECT_EQ(&BRC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "b1"))));
854 EXPECT_EQ(&BRC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "b2"))));
855 EXPECT_EQ(&BRC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "b3"))));
856 EXPECT_TRUE(BRC.isParentOf(CRC));
857 ++I;
Chandler Carruth49d728a2016-09-16 10:20:17 +0000858 EXPECT_EQ(J, I);
859 EXPECT_EQ(&BRC, &*I) << "Actual RefSCC: " << *I;
860
861 // Increment I this time to form the new RefSCC, flopping back to the first
862 // iterator.
863 ++I;
Chandler Carruthe5944d92016-02-17 00:18:16 +0000864 EXPECT_NE(I, E);
865 LazyCallGraph::RefSCC &ARC = *I;
866 EXPECT_NE(&ARC, nullptr);
867 EXPECT_EQ(&ARC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "a1"))));
868 EXPECT_EQ(&ARC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "a2"))));
869 EXPECT_EQ(&ARC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "a3"))));
870 EXPECT_TRUE(ARC.isParentOf(CRC));
Chandler Carruth49d728a2016-09-16 10:20:17 +0000871 ++J;
872 EXPECT_EQ(I, J);
873 EXPECT_EQ(&ARC, &*J) << "Actual RefSCC: " << *J;
Chandler Carruthe5944d92016-02-17 00:18:16 +0000874 ++I;
875 EXPECT_EQ(E, I);
Chandler Carruth49d728a2016-09-16 10:20:17 +0000876 ++J;
877 EXPECT_EQ(E, J);
878}
879
880TEST(LazyCallGraphTest, IncomingEdgeInsertionRefGraph) {
881 LLVMContext Context;
882 // Another variation of the above test but with all the edges switched to
883 // references rather than calls.
884 std::unique_ptr<Module> M =
885 parseAssembly(Context, DiamondOfTrianglesRefGraph);
886 LazyCallGraph CG(*M);
887
888 // Force the graph to be fully expanded.
889 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
890 dbgs() << "Formed RefSCC: " << RC << "\n";
891
892 LazyCallGraph::Node &A1 = *CG.lookup(lookupFunction(*M, "a1"));
893 LazyCallGraph::Node &A2 = *CG.lookup(lookupFunction(*M, "a2"));
894 LazyCallGraph::Node &A3 = *CG.lookup(lookupFunction(*M, "a3"));
895 LazyCallGraph::Node &B1 = *CG.lookup(lookupFunction(*M, "b1"));
896 LazyCallGraph::Node &B2 = *CG.lookup(lookupFunction(*M, "b2"));
897 LazyCallGraph::Node &B3 = *CG.lookup(lookupFunction(*M, "b3"));
898 LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
899 LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
900 LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
901 LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
902 LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
903 LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
904 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(A1);
905 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(B1);
906 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(C1);
907 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(D1);
908 ASSERT_EQ(&ARC, CG.lookupRefSCC(A2));
909 ASSERT_EQ(&ARC, CG.lookupRefSCC(A3));
910 ASSERT_EQ(&BRC, CG.lookupRefSCC(B2));
911 ASSERT_EQ(&BRC, CG.lookupRefSCC(B3));
912 ASSERT_EQ(&CRC, CG.lookupRefSCC(C2));
913 ASSERT_EQ(&CRC, CG.lookupRefSCC(C3));
914 ASSERT_EQ(&DRC, CG.lookupRefSCC(D2));
915 ASSERT_EQ(&DRC, CG.lookupRefSCC(D3));
916 ASSERT_EQ(1, std::distance(D2.begin(), D2.end()));
917
918 // Add an edge to make the graph:
919 //
920 // d1 |
921 // / \ |
922 // d3--d2---. |
923 // / \ | |
924 // b1 c1 | |
925 // / \ / \ / |
926 // b3--b2 c3--c2 |
927 // \ / |
928 // a1 |
929 // / \ |
930 // a3--a2 |
931 auto MergedRCs = CRC.insertIncomingRefEdge(D2, C2);
932 // Make sure we connected the nodes.
933 for (LazyCallGraph::Edge E : D2) {
934 if (E.getNode() == &D3)
935 continue;
936 EXPECT_EQ(&C2, E.getNode());
937 }
938 // And marked the D ref-SCC as no longer valid.
939 EXPECT_EQ(1u, MergedRCs.size());
940 EXPECT_EQ(&DRC, MergedRCs[0]);
941
942 // Make sure we have the correct nodes in the SCC sets.
943 EXPECT_EQ(&ARC, CG.lookupRefSCC(A1));
944 EXPECT_EQ(&ARC, CG.lookupRefSCC(A2));
945 EXPECT_EQ(&ARC, CG.lookupRefSCC(A3));
946 EXPECT_EQ(&BRC, CG.lookupRefSCC(B1));
947 EXPECT_EQ(&BRC, CG.lookupRefSCC(B2));
948 EXPECT_EQ(&BRC, CG.lookupRefSCC(B3));
949 EXPECT_EQ(&CRC, CG.lookupRefSCC(C1));
950 EXPECT_EQ(&CRC, CG.lookupRefSCC(C2));
951 EXPECT_EQ(&CRC, CG.lookupRefSCC(C3));
952 EXPECT_EQ(&CRC, CG.lookupRefSCC(D1));
953 EXPECT_EQ(&CRC, CG.lookupRefSCC(D2));
954 EXPECT_EQ(&CRC, CG.lookupRefSCC(D3));
955
956 // And that ancestry tests have been updated.
957 EXPECT_TRUE(ARC.isParentOf(CRC));
958 EXPECT_TRUE(BRC.isParentOf(CRC));
959
960 // And verify the post-order walk reflects the updated structure.
961 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
962 ASSERT_NE(I, E);
963 EXPECT_EQ(&CRC, &*I) << "Actual RefSCC: " << *I;
964 ASSERT_NE(++I, E);
965 EXPECT_EQ(&BRC, &*I) << "Actual RefSCC: " << *I;
966 ASSERT_NE(++I, E);
967 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
968 EXPECT_EQ(++I, E);
969}
970
971TEST(LazyCallGraphTest, IncomingEdgeInsertionLargeCallCycle) {
972 LLVMContext Context;
973 std::unique_ptr<Module> M = parseAssembly(Context, "define void @a() {\n"
974 "entry:\n"
975 " call void @b()\n"
976 " ret void\n"
977 "}\n"
978 "define void @b() {\n"
979 "entry:\n"
980 " call void @c()\n"
981 " ret void\n"
982 "}\n"
983 "define void @c() {\n"
984 "entry:\n"
985 " call void @d()\n"
986 " ret void\n"
987 "}\n"
988 "define void @d() {\n"
989 "entry:\n"
990 " ret void\n"
991 "}\n");
992 LazyCallGraph CG(*M);
993
994 // Force the graph to be fully expanded.
995 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
996 dbgs() << "Formed RefSCC: " << RC << "\n";
997
998 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
999 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1000 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1001 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
1002 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
1003 LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
1004 LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
1005 LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
1006 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(A);
1007 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(B);
1008 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(C);
1009 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(D);
1010
1011 // Connect the top to the bottom forming a large RefSCC made up mostly of calls.
1012 auto MergedRCs = ARC.insertIncomingRefEdge(D, A);
1013 // Make sure we connected the nodes.
1014 EXPECT_NE(D.begin(), D.end());
1015 EXPECT_EQ(&A, D.begin()->getNode());
1016
1017 // Check that we have the dead RCs, but ignore the order.
1018 EXPECT_EQ(3u, MergedRCs.size());
1019 EXPECT_NE(find(MergedRCs, &BRC), MergedRCs.end());
1020 EXPECT_NE(find(MergedRCs, &CRC), MergedRCs.end());
1021 EXPECT_NE(find(MergedRCs, &DRC), MergedRCs.end());
1022
1023 // Make sure the nodes point to the right place now.
1024 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
1025 EXPECT_EQ(&ARC, CG.lookupRefSCC(B));
1026 EXPECT_EQ(&ARC, CG.lookupRefSCC(C));
1027 EXPECT_EQ(&ARC, CG.lookupRefSCC(D));
1028
1029 // Check that the SCCs are in postorder.
1030 EXPECT_EQ(4, ARC.size());
1031 EXPECT_EQ(&DC, &ARC[0]);
1032 EXPECT_EQ(&CC, &ARC[1]);
1033 EXPECT_EQ(&BC, &ARC[2]);
1034 EXPECT_EQ(&AC, &ARC[3]);
1035
1036 // And verify the post-order walk reflects the updated structure.
1037 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
1038 ASSERT_NE(I, E);
1039 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
1040 EXPECT_EQ(++I, E);
1041}
1042
1043TEST(LazyCallGraphTest, IncomingEdgeInsertionLargeRefCycle) {
1044 LLVMContext Context;
1045 std::unique_ptr<Module> M =
1046 parseAssembly(Context, "define void @a() {\n"
1047 "entry:\n"
1048 " %p = alloca void ()*\n"
1049 " store void ()* @b, void ()** %p\n"
1050 " ret void\n"
1051 "}\n"
1052 "define void @b() {\n"
1053 "entry:\n"
1054 " %p = alloca void ()*\n"
1055 " store void ()* @c, void ()** %p\n"
1056 " ret void\n"
1057 "}\n"
1058 "define void @c() {\n"
1059 "entry:\n"
1060 " %p = alloca void ()*\n"
1061 " store void ()* @d, void ()** %p\n"
1062 " ret void\n"
1063 "}\n"
1064 "define void @d() {\n"
1065 "entry:\n"
1066 " ret void\n"
1067 "}\n");
1068 LazyCallGraph CG(*M);
1069
1070 // Force the graph to be fully expanded.
1071 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
1072 dbgs() << "Formed RefSCC: " << RC << "\n";
1073
1074 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1075 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1076 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1077 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
1078 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(A);
1079 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(B);
1080 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(C);
1081 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(D);
1082
1083 // Connect the top to the bottom forming a large RefSCC made up just of
1084 // references.
1085 auto MergedRCs = ARC.insertIncomingRefEdge(D, A);
1086 // Make sure we connected the nodes.
1087 EXPECT_NE(D.begin(), D.end());
1088 EXPECT_EQ(&A, D.begin()->getNode());
1089
1090 // Check that we have the dead RCs, but ignore the order.
1091 EXPECT_EQ(3u, MergedRCs.size());
1092 EXPECT_NE(find(MergedRCs, &BRC), MergedRCs.end());
1093 EXPECT_NE(find(MergedRCs, &CRC), MergedRCs.end());
1094 EXPECT_NE(find(MergedRCs, &DRC), MergedRCs.end());
1095
1096 // Make sure the nodes point to the right place now.
1097 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
1098 EXPECT_EQ(&ARC, CG.lookupRefSCC(B));
1099 EXPECT_EQ(&ARC, CG.lookupRefSCC(C));
1100 EXPECT_EQ(&ARC, CG.lookupRefSCC(D));
1101
1102 // And verify the post-order walk reflects the updated structure.
1103 auto I = CG.postorder_ref_scc_begin(), End = CG.postorder_ref_scc_end();
1104 ASSERT_NE(I, End);
1105 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
1106 EXPECT_EQ(++I, End);
Chandler Carruth312dddf2014-05-04 09:38:32 +00001107}
1108
Chandler Carruth5dbc1642016-10-12 07:59:56 +00001109TEST(LazyCallGraphTest, InlineAndDeleteFunction) {
1110 LLVMContext Context;
1111 // We want to ensure we can delete nodes from relatively complex graphs and
1112 // so use the diamond of triangles graph defined above.
1113 //
1114 // The ascii diagram is repeated here for easy reference.
1115 //
1116 // d1 |
1117 // / \ |
1118 // d3--d2 |
1119 // / \ |
1120 // b1 c1 |
1121 // / \ / \ |
1122 // b3--b2 c3--c2 |
1123 // \ / |
1124 // a1 |
1125 // / \ |
1126 // a3--a2 |
1127 //
1128 std::unique_ptr<Module> M = parseAssembly(Context, DiamondOfTriangles);
1129 LazyCallGraph CG(*M);
1130
1131 // Force the graph to be fully expanded.
1132 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
1133 dbgs() << "Formed RefSCC: " << RC << "\n";
1134
1135 LazyCallGraph::Node &A1 = *CG.lookup(lookupFunction(*M, "a1"));
1136 LazyCallGraph::Node &A2 = *CG.lookup(lookupFunction(*M, "a2"));
1137 LazyCallGraph::Node &A3 = *CG.lookup(lookupFunction(*M, "a3"));
1138 LazyCallGraph::Node &B1 = *CG.lookup(lookupFunction(*M, "b1"));
1139 LazyCallGraph::Node &B2 = *CG.lookup(lookupFunction(*M, "b2"));
1140 LazyCallGraph::Node &B3 = *CG.lookup(lookupFunction(*M, "b3"));
1141 LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
1142 LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
1143 LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
1144 LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
1145 LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
1146 LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
1147 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(A1);
1148 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(B1);
1149 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(C1);
1150 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(D1);
1151 ASSERT_EQ(&ARC, CG.lookupRefSCC(A2));
1152 ASSERT_EQ(&ARC, CG.lookupRefSCC(A3));
1153 ASSERT_EQ(&BRC, CG.lookupRefSCC(B2));
1154 ASSERT_EQ(&BRC, CG.lookupRefSCC(B3));
1155 ASSERT_EQ(&CRC, CG.lookupRefSCC(C2));
1156 ASSERT_EQ(&CRC, CG.lookupRefSCC(C3));
1157 ASSERT_EQ(&DRC, CG.lookupRefSCC(D2));
1158 ASSERT_EQ(&DRC, CG.lookupRefSCC(D3));
1159 ASSERT_EQ(1, std::distance(D2.begin(), D2.end()));
1160
1161 // Delete d2 from the graph, as if it had been inlined.
1162 //
1163 // d1 |
1164 // / / |
1165 // d3--. |
1166 // / \ |
1167 // b1 c1 |
1168 // / \ / \ |
1169 // b3--b2 c3--c2 |
1170 // \ / |
1171 // a1 |
1172 // / \ |
1173 // a3--a2 |
1174
1175 Function &D2F = D2.getFunction();
1176 CallInst *C1Call = nullptr, *D1Call = nullptr;
1177 for (User *U : D2F.users()) {
1178 CallInst *CI = dyn_cast<CallInst>(U);
1179 ASSERT_TRUE(CI) << "Expected a call: " << *U;
1180 if (CI->getParent()->getParent() == &C1.getFunction()) {
1181 ASSERT_EQ(nullptr, C1Call) << "Found too many C1 calls: " << *CI;
1182 C1Call = CI;
1183 } else if (CI->getParent()->getParent() == &D1.getFunction()) {
1184 ASSERT_EQ(nullptr, D1Call) << "Found too many D1 calls: " << *CI;
1185 D1Call = CI;
1186 } else {
1187 FAIL() << "Found an unexpected call instruction: " << *CI;
1188 }
1189 }
1190 ASSERT_NE(C1Call, nullptr);
1191 ASSERT_NE(D1Call, nullptr);
1192 ASSERT_EQ(&D2F, C1Call->getCalledFunction());
1193 ASSERT_EQ(&D2F, D1Call->getCalledFunction());
1194 C1Call->setCalledFunction(&D3.getFunction());
1195 D1Call->setCalledFunction(&D3.getFunction());
1196 ASSERT_EQ(0u, D2F.getNumUses());
1197
1198 // Insert new edges first.
1199 CRC.insertTrivialCallEdge(C1, D3);
1200 DRC.insertTrivialCallEdge(D1, D3);
1201
1202 // Then remove the old ones.
1203 LazyCallGraph::SCC &DC = *CG.lookupSCC(D2);
1204 auto NewCs = DRC.switchInternalEdgeToRef(D1, D2);
1205 EXPECT_EQ(&DC, CG.lookupSCC(D2));
1206 EXPECT_EQ(NewCs.end(), std::next(NewCs.begin()));
1207 LazyCallGraph::SCC &NewDC = *NewCs.begin();
1208 EXPECT_EQ(&NewDC, CG.lookupSCC(D1));
1209 EXPECT_EQ(&NewDC, CG.lookupSCC(D3));
1210 auto NewRCs = DRC.removeInternalRefEdge(D1, D2);
1211 EXPECT_EQ(&DRC, CG.lookupRefSCC(D2));
1212 EXPECT_EQ(NewRCs.end(), std::next(NewRCs.begin()));
1213 LazyCallGraph::RefSCC &NewDRC = **NewRCs.begin();
1214 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D1));
1215 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D3));
1216 EXPECT_FALSE(NewDRC.isParentOf(DRC));
1217 EXPECT_TRUE(CRC.isParentOf(DRC));
1218 EXPECT_TRUE(CRC.isParentOf(NewDRC));
1219 EXPECT_TRUE(DRC.isParentOf(NewDRC));
1220 CRC.removeOutgoingEdge(C1, D2);
1221 EXPECT_FALSE(CRC.isParentOf(DRC));
1222 EXPECT_TRUE(CRC.isParentOf(NewDRC));
1223 EXPECT_TRUE(DRC.isParentOf(NewDRC));
1224
1225 // Now that we've updated the call graph, D2 is dead, so remove it.
1226 CG.removeDeadFunction(D2F);
1227
1228 // Check that the graph still looks the same.
1229 EXPECT_EQ(&ARC, CG.lookupRefSCC(A1));
1230 EXPECT_EQ(&ARC, CG.lookupRefSCC(A2));
1231 EXPECT_EQ(&ARC, CG.lookupRefSCC(A3));
1232 EXPECT_EQ(&BRC, CG.lookupRefSCC(B1));
1233 EXPECT_EQ(&BRC, CG.lookupRefSCC(B2));
1234 EXPECT_EQ(&BRC, CG.lookupRefSCC(B3));
1235 EXPECT_EQ(&CRC, CG.lookupRefSCC(C1));
1236 EXPECT_EQ(&CRC, CG.lookupRefSCC(C2));
1237 EXPECT_EQ(&CRC, CG.lookupRefSCC(C3));
1238 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D1));
1239 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D3));
1240 EXPECT_TRUE(CRC.isParentOf(NewDRC));
1241
1242 // Verify the post-order walk hasn't changed.
1243 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
1244 ASSERT_NE(I, E);
1245 EXPECT_EQ(&NewDRC, &*I) << "Actual RefSCC: " << *I;
1246 ASSERT_NE(++I, E);
1247 EXPECT_EQ(&CRC, &*I) << "Actual RefSCC: " << *I;
1248 ASSERT_NE(++I, E);
1249 EXPECT_EQ(&BRC, &*I) << "Actual RefSCC: " << *I;
1250 ASSERT_NE(++I, E);
1251 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
1252 EXPECT_EQ(++I, E);
1253}
1254
1255TEST(LazyCallGraphTest, InlineAndDeleteFunctionMidTraversal) {
1256 LLVMContext Context;
1257 // This is the same fundamental test as the previous, but we perform it
1258 // having only partially walked the RefSCCs of the graph.
1259 //
1260 // The ascii diagram is repeated here for easy reference.
1261 //
1262 // d1 |
1263 // / \ |
1264 // d3--d2 |
1265 // / \ |
1266 // b1 c1 |
1267 // / \ / \ |
1268 // b3--b2 c3--c2 |
1269 // \ / |
1270 // a1 |
1271 // / \ |
1272 // a3--a2 |
1273 //
1274 std::unique_ptr<Module> M = parseAssembly(Context, DiamondOfTriangles);
1275 LazyCallGraph CG(*M);
1276
1277 // Walk the RefSCCs until we find the one containing 'c1'.
1278 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
1279 ASSERT_NE(I, E);
1280 LazyCallGraph::RefSCC &DRC = *I;
1281 ASSERT_NE(&DRC, nullptr);
1282 ++I;
1283 ASSERT_NE(I, E);
1284 LazyCallGraph::RefSCC &CRC = *I;
1285 ASSERT_NE(&CRC, nullptr);
1286
1287 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a1")));
1288 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a2")));
1289 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a3")));
1290 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b1")));
1291 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b2")));
1292 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b3")));
1293 LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
1294 LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
1295 LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
1296 LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
1297 LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
1298 LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
1299 ASSERT_EQ(&CRC, CG.lookupRefSCC(C1));
1300 ASSERT_EQ(&CRC, CG.lookupRefSCC(C2));
1301 ASSERT_EQ(&CRC, CG.lookupRefSCC(C3));
1302 ASSERT_EQ(&DRC, CG.lookupRefSCC(D1));
1303 ASSERT_EQ(&DRC, CG.lookupRefSCC(D2));
1304 ASSERT_EQ(&DRC, CG.lookupRefSCC(D3));
1305 ASSERT_EQ(1, std::distance(D2.begin(), D2.end()));
1306
1307 // Delete d2 from the graph, as if it had been inlined.
1308 //
1309 // d1 |
1310 // / / |
1311 // d3--. |
1312 // / \ |
1313 // b1 c1 |
1314 // / \ / \ |
1315 // b3--b2 c3--c2 |
1316 // \ / |
1317 // a1 |
1318 // / \ |
1319 // a3--a2 |
1320
1321 Function &D2F = D2.getFunction();
1322 CallInst *C1Call = nullptr, *D1Call = nullptr;
1323 for (User *U : D2F.users()) {
1324 CallInst *CI = dyn_cast<CallInst>(U);
1325 ASSERT_TRUE(CI) << "Expected a call: " << *U;
1326 if (CI->getParent()->getParent() == &C1.getFunction()) {
1327 ASSERT_EQ(nullptr, C1Call) << "Found too many C1 calls: " << *CI;
1328 C1Call = CI;
1329 } else if (CI->getParent()->getParent() == &D1.getFunction()) {
1330 ASSERT_EQ(nullptr, D1Call) << "Found too many D1 calls: " << *CI;
1331 D1Call = CI;
1332 } else {
1333 FAIL() << "Found an unexpected call instruction: " << *CI;
1334 }
1335 }
1336 ASSERT_NE(C1Call, nullptr);
1337 ASSERT_NE(D1Call, nullptr);
1338 ASSERT_EQ(&D2F, C1Call->getCalledFunction());
1339 ASSERT_EQ(&D2F, D1Call->getCalledFunction());
1340 C1Call->setCalledFunction(&D3.getFunction());
1341 D1Call->setCalledFunction(&D3.getFunction());
1342 ASSERT_EQ(0u, D2F.getNumUses());
1343
1344 // Insert new edges first.
1345 CRC.insertTrivialCallEdge(C1, D3);
1346 DRC.insertTrivialCallEdge(D1, D3);
1347
1348 // Then remove the old ones.
1349 LazyCallGraph::SCC &DC = *CG.lookupSCC(D2);
1350 auto NewCs = DRC.switchInternalEdgeToRef(D1, D2);
1351 EXPECT_EQ(&DC, CG.lookupSCC(D2));
1352 EXPECT_EQ(NewCs.end(), std::next(NewCs.begin()));
1353 LazyCallGraph::SCC &NewDC = *NewCs.begin();
1354 EXPECT_EQ(&NewDC, CG.lookupSCC(D1));
1355 EXPECT_EQ(&NewDC, CG.lookupSCC(D3));
1356 auto NewRCs = DRC.removeInternalRefEdge(D1, D2);
1357 EXPECT_EQ(&DRC, CG.lookupRefSCC(D2));
1358 EXPECT_EQ(NewRCs.end(), std::next(NewRCs.begin()));
1359 LazyCallGraph::RefSCC &NewDRC = **NewRCs.begin();
1360 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D1));
1361 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D3));
1362 EXPECT_FALSE(NewDRC.isParentOf(DRC));
1363 EXPECT_TRUE(CRC.isParentOf(DRC));
1364 EXPECT_TRUE(CRC.isParentOf(NewDRC));
1365 EXPECT_TRUE(DRC.isParentOf(NewDRC));
1366 CRC.removeOutgoingEdge(C1, D2);
1367 EXPECT_FALSE(CRC.isParentOf(DRC));
1368 EXPECT_TRUE(CRC.isParentOf(NewDRC));
1369 EXPECT_TRUE(DRC.isParentOf(NewDRC));
1370
1371 // Now that we've updated the call graph, D2 is dead, so remove it.
1372 CG.removeDeadFunction(D2F);
1373
1374 // Check that the graph still looks the same.
1375 EXPECT_EQ(&CRC, CG.lookupRefSCC(C1));
1376 EXPECT_EQ(&CRC, CG.lookupRefSCC(C2));
1377 EXPECT_EQ(&CRC, CG.lookupRefSCC(C3));
1378 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D1));
1379 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D3));
1380 EXPECT_TRUE(CRC.isParentOf(NewDRC));
1381
1382 // Verify that the post-order walk reflects the updated but still incomplete
1383 // structure.
1384 auto J = CG.postorder_ref_scc_begin();
1385 EXPECT_NE(J, E);
1386 EXPECT_EQ(&NewDRC, &*J) << "Actual RefSCC: " << *J;
1387 ++J;
1388 EXPECT_NE(J, E);
1389 EXPECT_EQ(&CRC, &*J) << "Actual RefSCC: " << *J;
1390 EXPECT_EQ(I, J);
1391
1392 // Check that we can form the last two RefSCCs now, and even that we can do
1393 // it with alternating iterators.
1394 ++J;
1395 EXPECT_NE(J, E);
1396 LazyCallGraph::RefSCC &BRC = *J;
1397 EXPECT_NE(&BRC, nullptr);
1398 EXPECT_EQ(&BRC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "b1"))));
1399 EXPECT_EQ(&BRC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "b2"))));
1400 EXPECT_EQ(&BRC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "b3"))));
1401 EXPECT_TRUE(BRC.isParentOf(NewDRC));
1402 ++I;
1403 EXPECT_EQ(J, I);
1404 EXPECT_EQ(&BRC, &*I) << "Actual RefSCC: " << *I;
1405
1406 // Increment I this time to form the new RefSCC, flopping back to the first
1407 // iterator.
1408 ++I;
1409 EXPECT_NE(I, E);
1410 LazyCallGraph::RefSCC &ARC = *I;
1411 EXPECT_NE(&ARC, nullptr);
1412 EXPECT_EQ(&ARC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "a1"))));
1413 EXPECT_EQ(&ARC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "a2"))));
1414 EXPECT_EQ(&ARC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "a3"))));
1415 EXPECT_TRUE(ARC.isParentOf(BRC));
1416 EXPECT_TRUE(ARC.isParentOf(CRC));
1417 ++J;
1418 EXPECT_EQ(I, J);
1419 EXPECT_EQ(&ARC, &*J) << "Actual RefSCC: " << *J;
1420 ++I;
1421 EXPECT_EQ(E, I);
1422 ++J;
1423 EXPECT_EQ(E, J);
1424}
1425
Chandler Carruthe5944d92016-02-17 00:18:16 +00001426TEST(LazyCallGraphTest, InternalEdgeMutation) {
Mehdi Amini03b42e42016-04-14 21:59:01 +00001427 LLVMContext Context;
1428 std::unique_ptr<Module> M = parseAssembly(Context, "define void @a() {\n"
1429 "entry:\n"
1430 " call void @b()\n"
1431 " ret void\n"
1432 "}\n"
1433 "define void @b() {\n"
1434 "entry:\n"
1435 " call void @c()\n"
1436 " ret void\n"
1437 "}\n"
1438 "define void @c() {\n"
1439 "entry:\n"
1440 " call void @a()\n"
1441 " ret void\n"
1442 "}\n");
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001443 LazyCallGraph CG(*M);
1444
1445 // Force the graph to be fully expanded.
Chandler Carruthe5944d92016-02-17 00:18:16 +00001446 auto I = CG.postorder_ref_scc_begin();
1447 LazyCallGraph::RefSCC &RC = *I++;
1448 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001449
Chandler Carrutha10e2402014-04-23 23:12:06 +00001450 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1451 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
Chandler Carruthe5944d92016-02-17 00:18:16 +00001452 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1453 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1454 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1455 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
1456 EXPECT_EQ(1, RC.size());
1457 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(A));
1458 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(B));
1459 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(C));
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001460
Chandler Carruthe5944d92016-02-17 00:18:16 +00001461 // Insert an edge from 'a' to 'c'. Nothing changes about the graph.
1462 RC.insertInternalRefEdge(A, C);
Chandler Carruth5217c942014-04-30 10:48:36 +00001463 EXPECT_EQ(2, std::distance(A.begin(), A.end()));
Chandler Carruthe5944d92016-02-17 00:18:16 +00001464 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1465 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1466 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
1467 EXPECT_EQ(1, RC.size());
1468 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(A));
1469 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(B));
1470 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(C));
Chandler Carruth5217c942014-04-30 10:48:36 +00001471
Chandler Carruthe5944d92016-02-17 00:18:16 +00001472 // Switch the call edge from 'b' to 'c' to a ref edge. This will break the
1473 // call cycle and cause us to form more SCCs. The RefSCC will remain the same
1474 // though.
1475 RC.switchInternalEdgeToRef(B, C);
1476 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1477 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1478 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
1479 auto J = RC.begin();
1480 // The SCCs must be in *post-order* which means successors before
1481 // predecessors. At this point we have call edges from C to A and from A to
1482 // B. The only valid postorder is B, A, C.
1483 EXPECT_EQ(&*J++, CG.lookupSCC(B));
1484 EXPECT_EQ(&*J++, CG.lookupSCC(A));
1485 EXPECT_EQ(&*J++, CG.lookupSCC(C));
1486 EXPECT_EQ(RC.end(), J);
1487
1488 // Test turning the ref edge from A to C into a call edge. This will form an
1489 // SCC out of A and C. Since we previously had a call edge from C to A, the
1490 // C SCC should be preserved and have A merged into it while the A SCC should
1491 // be invalidated.
1492 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
1493 LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
1494 auto InvalidatedSCCs = RC.switchInternalEdgeToCall(A, C);
1495 ASSERT_EQ(1u, InvalidatedSCCs.size());
1496 EXPECT_EQ(&AC, InvalidatedSCCs[0]);
1497 EXPECT_EQ(2, CC.size());
1498 EXPECT_EQ(&CC, CG.lookupSCC(A));
1499 EXPECT_EQ(&CC, CG.lookupSCC(C));
1500 J = RC.begin();
1501 EXPECT_EQ(&*J++, CG.lookupSCC(B));
1502 EXPECT_EQ(&*J++, CG.lookupSCC(C));
1503 EXPECT_EQ(RC.end(), J);
Chandler Carruth5217c942014-04-30 10:48:36 +00001504}
1505
Chandler Carruthe5944d92016-02-17 00:18:16 +00001506TEST(LazyCallGraphTest, InternalEdgeRemoval) {
Mehdi Amini03b42e42016-04-14 21:59:01 +00001507 LLVMContext Context;
Chandler Carruthe5944d92016-02-17 00:18:16 +00001508 // A nice fully connected (including self-edges) RefSCC.
1509 std::unique_ptr<Module> M = parseAssembly(
Mehdi Amini03b42e42016-04-14 21:59:01 +00001510 Context, "define void @a(i8** %ptr) {\n"
1511 "entry:\n"
1512 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1513 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1514 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1515 " ret void\n"
1516 "}\n"
1517 "define void @b(i8** %ptr) {\n"
1518 "entry:\n"
1519 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1520 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1521 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1522 " ret void\n"
1523 "}\n"
1524 "define void @c(i8** %ptr) {\n"
1525 "entry:\n"
1526 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1527 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1528 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1529 " ret void\n"
1530 "}\n");
Chandler Carruthe5944d92016-02-17 00:18:16 +00001531 LazyCallGraph CG(*M);
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001532
1533 // Force the graph to be fully expanded.
Chandler Carruth49d728a2016-09-16 10:20:17 +00001534 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
1535 LazyCallGraph::RefSCC &RC = *I;
1536 EXPECT_EQ(E, std::next(I));
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001537
Chandler Carruthe5944d92016-02-17 00:18:16 +00001538 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1539 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1540 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1541 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1542 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1543 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001544
1545 // Remove the edge from b -> a, which should leave the 3 functions still in
1546 // a single connected component because of a -> b -> c -> a.
Chandler Carruthe5944d92016-02-17 00:18:16 +00001547 SmallVector<LazyCallGraph::RefSCC *, 1> NewRCs =
1548 RC.removeInternalRefEdge(B, A);
1549 EXPECT_EQ(0u, NewRCs.size());
1550 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1551 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1552 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
Chandler Carruth49d728a2016-09-16 10:20:17 +00001553 auto J = CG.postorder_ref_scc_begin();
1554 EXPECT_EQ(I, J);
1555 EXPECT_EQ(&RC, &*J);
1556 EXPECT_EQ(E, std::next(J));
Chandler Carruthe5944d92016-02-17 00:18:16 +00001557
1558 // Remove the edge from c -> a, which should leave 'a' in the original RefSCC
1559 // and form a new RefSCC for 'b' and 'c'.
1560 NewRCs = RC.removeInternalRefEdge(C, A);
1561 EXPECT_EQ(1u, NewRCs.size());
1562 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1563 EXPECT_EQ(1, std::distance(RC.begin(), RC.end()));
Chandler Carruth49d728a2016-09-16 10:20:17 +00001564 LazyCallGraph::RefSCC &RC2 = *CG.lookupRefSCC(B);
1565 EXPECT_EQ(&RC2, CG.lookupRefSCC(C));
1566 EXPECT_EQ(&RC2, NewRCs[0]);
1567 J = CG.postorder_ref_scc_begin();
1568 EXPECT_NE(I, J);
1569 EXPECT_EQ(&RC2, &*J);
1570 ++J;
1571 EXPECT_EQ(I, J);
1572 EXPECT_EQ(&RC, &*J);
1573 ++I;
1574 EXPECT_EQ(E, I);
1575 ++J;
1576 EXPECT_EQ(E, J);
Chandler Carruthe5944d92016-02-17 00:18:16 +00001577}
1578
1579TEST(LazyCallGraphTest, InternalCallEdgeToRef) {
Mehdi Amini03b42e42016-04-14 21:59:01 +00001580 LLVMContext Context;
Chandler Carruthe5944d92016-02-17 00:18:16 +00001581 // A nice fully connected (including self-edges) SCC (and RefSCC)
Mehdi Amini03b42e42016-04-14 21:59:01 +00001582 std::unique_ptr<Module> M = parseAssembly(Context, "define void @a() {\n"
1583 "entry:\n"
1584 " call void @a()\n"
1585 " call void @b()\n"
1586 " call void @c()\n"
1587 " ret void\n"
1588 "}\n"
1589 "define void @b() {\n"
1590 "entry:\n"
1591 " call void @a()\n"
1592 " call void @b()\n"
1593 " call void @c()\n"
1594 " ret void\n"
1595 "}\n"
1596 "define void @c() {\n"
1597 "entry:\n"
1598 " call void @a()\n"
1599 " call void @b()\n"
1600 " call void @c()\n"
1601 " ret void\n"
1602 "}\n");
Chandler Carruthe5944d92016-02-17 00:18:16 +00001603 LazyCallGraph CG(*M);
1604
1605 // Force the graph to be fully expanded.
1606 auto I = CG.postorder_ref_scc_begin();
1607 LazyCallGraph::RefSCC &RC = *I++;
1608 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1609
1610 EXPECT_EQ(1, RC.size());
1611 LazyCallGraph::SCC &CallC = *RC.begin();
1612
1613 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1614 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1615 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1616 EXPECT_EQ(&CallC, CG.lookupSCC(A));
1617 EXPECT_EQ(&CallC, CG.lookupSCC(B));
1618 EXPECT_EQ(&CallC, CG.lookupSCC(C));
1619
1620 // Remove the call edge from b -> a to a ref edge, which should leave the
1621 // 3 functions still in a single connected component because of a -> b ->
1622 // c -> a.
1623 RC.switchInternalEdgeToRef(B, A);
1624 EXPECT_EQ(1, RC.size());
1625 EXPECT_EQ(&CallC, CG.lookupSCC(A));
1626 EXPECT_EQ(&CallC, CG.lookupSCC(B));
1627 EXPECT_EQ(&CallC, CG.lookupSCC(C));
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001628
1629 // Remove the edge from c -> a, which should leave 'a' in the original SCC
1630 // and form a new SCC for 'b' and 'c'.
Chandler Carruthe5944d92016-02-17 00:18:16 +00001631 RC.switchInternalEdgeToRef(C, A);
1632 EXPECT_EQ(2, RC.size());
1633 EXPECT_EQ(&CallC, CG.lookupSCC(A));
1634 LazyCallGraph::SCC &BCallC = *CG.lookupSCC(B);
1635 EXPECT_NE(&BCallC, &CallC);
1636 EXPECT_EQ(&BCallC, CG.lookupSCC(C));
1637 auto J = RC.find(CallC);
1638 EXPECT_EQ(&CallC, &*J);
1639 --J;
1640 EXPECT_EQ(&BCallC, &*J);
1641 EXPECT_EQ(RC.begin(), J);
1642
1643 // Remove the edge from c -> b, which should leave 'b' in the original SCC
1644 // and form a new SCC for 'c'. It shouldn't change 'a's SCC.
1645 RC.switchInternalEdgeToRef(C, B);
1646 EXPECT_EQ(3, RC.size());
1647 EXPECT_EQ(&CallC, CG.lookupSCC(A));
1648 EXPECT_EQ(&BCallC, CG.lookupSCC(B));
1649 LazyCallGraph::SCC &CCallC = *CG.lookupSCC(C);
1650 EXPECT_NE(&CCallC, &CallC);
1651 EXPECT_NE(&CCallC, &BCallC);
1652 J = RC.find(CallC);
1653 EXPECT_EQ(&CallC, &*J);
1654 --J;
1655 EXPECT_EQ(&BCallC, &*J);
1656 --J;
1657 EXPECT_EQ(&CCallC, &*J);
1658 EXPECT_EQ(RC.begin(), J);
1659}
1660
1661TEST(LazyCallGraphTest, InternalRefEdgeToCall) {
Mehdi Amini03b42e42016-04-14 21:59:01 +00001662 LLVMContext Context;
Chandler Carruthe5944d92016-02-17 00:18:16 +00001663 // Basic tests for making a ref edge a call. This hits the basics of the
1664 // process only.
Mehdi Amini03b42e42016-04-14 21:59:01 +00001665 std::unique_ptr<Module> M =
1666 parseAssembly(Context, "define void @a() {\n"
1667 "entry:\n"
1668 " call void @b()\n"
1669 " call void @c()\n"
1670 " store void()* @d, void()** undef\n"
1671 " ret void\n"
1672 "}\n"
1673 "define void @b() {\n"
1674 "entry:\n"
1675 " store void()* @c, void()** undef\n"
1676 " call void @d()\n"
1677 " ret void\n"
1678 "}\n"
1679 "define void @c() {\n"
1680 "entry:\n"
1681 " store void()* @b, void()** undef\n"
1682 " call void @d()\n"
1683 " ret void\n"
1684 "}\n"
1685 "define void @d() {\n"
1686 "entry:\n"
1687 " store void()* @a, void()** undef\n"
1688 " ret void\n"
1689 "}\n");
Chandler Carruthe5944d92016-02-17 00:18:16 +00001690 LazyCallGraph CG(*M);
1691
1692 // Force the graph to be fully expanded.
1693 auto I = CG.postorder_ref_scc_begin();
1694 LazyCallGraph::RefSCC &RC = *I++;
1695 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1696
1697 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1698 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1699 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1700 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
1701 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
1702 LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
1703 LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
1704 LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
1705
1706 // Check the initial post-order. Note that B and C could be flipped here (and
1707 // in our mutation) without changing the nature of this test.
1708 ASSERT_EQ(4, RC.size());
1709 EXPECT_EQ(&DC, &RC[0]);
1710 EXPECT_EQ(&BC, &RC[1]);
1711 EXPECT_EQ(&CC, &RC[2]);
1712 EXPECT_EQ(&AC, &RC[3]);
1713
1714 // Switch the ref edge from A -> D to a call edge. This should have no
1715 // effect as it is already in postorder and no new cycles are formed.
1716 auto MergedCs = RC.switchInternalEdgeToCall(A, D);
1717 EXPECT_EQ(0u, MergedCs.size());
1718 ASSERT_EQ(4, RC.size());
1719 EXPECT_EQ(&DC, &RC[0]);
1720 EXPECT_EQ(&BC, &RC[1]);
1721 EXPECT_EQ(&CC, &RC[2]);
1722 EXPECT_EQ(&AC, &RC[3]);
1723
1724 // Switch B -> C to a call edge. This doesn't form any new cycles but does
1725 // require reordering the SCCs.
1726 MergedCs = RC.switchInternalEdgeToCall(B, C);
1727 EXPECT_EQ(0u, MergedCs.size());
1728 ASSERT_EQ(4, RC.size());
1729 EXPECT_EQ(&DC, &RC[0]);
1730 EXPECT_EQ(&CC, &RC[1]);
1731 EXPECT_EQ(&BC, &RC[2]);
1732 EXPECT_EQ(&AC, &RC[3]);
1733
1734 // Switch C -> B to a call edge. This forms a cycle and forces merging SCCs.
1735 MergedCs = RC.switchInternalEdgeToCall(C, B);
1736 ASSERT_EQ(1u, MergedCs.size());
1737 EXPECT_EQ(&CC, MergedCs[0]);
1738 ASSERT_EQ(3, RC.size());
1739 EXPECT_EQ(&DC, &RC[0]);
1740 EXPECT_EQ(&BC, &RC[1]);
1741 EXPECT_EQ(&AC, &RC[2]);
1742 EXPECT_EQ(2, BC.size());
1743 EXPECT_EQ(&BC, CG.lookupSCC(B));
1744 EXPECT_EQ(&BC, CG.lookupSCC(C));
1745}
1746
1747TEST(LazyCallGraphTest, InternalRefEdgeToCallNoCycleInterleaved) {
Mehdi Amini03b42e42016-04-14 21:59:01 +00001748 LLVMContext Context;
Chandler Carruthe5944d92016-02-17 00:18:16 +00001749 // Test for having a post-order prior to changing a ref edge to a call edge
1750 // with SCCs connecting to the source and connecting to the target, but not
1751 // connecting to both, interleaved between the source and target. This
1752 // ensures we correctly partition the range rather than simply moving one or
1753 // the other.
Mehdi Amini03b42e42016-04-14 21:59:01 +00001754 std::unique_ptr<Module> M =
1755 parseAssembly(Context, "define void @a() {\n"
1756 "entry:\n"
1757 " call void @b1()\n"
1758 " call void @c1()\n"
1759 " ret void\n"
1760 "}\n"
1761 "define void @b1() {\n"
1762 "entry:\n"
1763 " call void @c1()\n"
1764 " call void @b2()\n"
1765 " ret void\n"
1766 "}\n"
1767 "define void @c1() {\n"
1768 "entry:\n"
1769 " call void @b2()\n"
1770 " call void @c2()\n"
1771 " ret void\n"
1772 "}\n"
1773 "define void @b2() {\n"
1774 "entry:\n"
1775 " call void @c2()\n"
1776 " call void @b3()\n"
1777 " ret void\n"
1778 "}\n"
1779 "define void @c2() {\n"
1780 "entry:\n"
1781 " call void @b3()\n"
1782 " call void @c3()\n"
1783 " ret void\n"
1784 "}\n"
1785 "define void @b3() {\n"
1786 "entry:\n"
1787 " call void @c3()\n"
1788 " call void @d()\n"
1789 " ret void\n"
1790 "}\n"
1791 "define void @c3() {\n"
1792 "entry:\n"
1793 " store void()* @b1, void()** undef\n"
1794 " call void @d()\n"
1795 " ret void\n"
1796 "}\n"
1797 "define void @d() {\n"
1798 "entry:\n"
1799 " store void()* @a, void()** undef\n"
1800 " ret void\n"
1801 "}\n");
Chandler Carruthe5944d92016-02-17 00:18:16 +00001802 LazyCallGraph CG(*M);
1803
1804 // Force the graph to be fully expanded.
1805 auto I = CG.postorder_ref_scc_begin();
1806 LazyCallGraph::RefSCC &RC = *I++;
1807 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1808
1809 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1810 LazyCallGraph::Node &B1 = *CG.lookup(lookupFunction(*M, "b1"));
1811 LazyCallGraph::Node &B2 = *CG.lookup(lookupFunction(*M, "b2"));
1812 LazyCallGraph::Node &B3 = *CG.lookup(lookupFunction(*M, "b3"));
1813 LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
1814 LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
1815 LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
1816 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
1817 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
1818 LazyCallGraph::SCC &B1C = *CG.lookupSCC(B1);
1819 LazyCallGraph::SCC &B2C = *CG.lookupSCC(B2);
1820 LazyCallGraph::SCC &B3C = *CG.lookupSCC(B3);
1821 LazyCallGraph::SCC &C1C = *CG.lookupSCC(C1);
1822 LazyCallGraph::SCC &C2C = *CG.lookupSCC(C2);
1823 LazyCallGraph::SCC &C3C = *CG.lookupSCC(C3);
1824 LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
1825
1826 // Several call edges are initially present to force a particual post-order.
1827 // Remove them now, leaving an interleaved post-order pattern.
1828 RC.switchInternalEdgeToRef(B3, C3);
1829 RC.switchInternalEdgeToRef(C2, B3);
1830 RC.switchInternalEdgeToRef(B2, C2);
1831 RC.switchInternalEdgeToRef(C1, B2);
1832 RC.switchInternalEdgeToRef(B1, C1);
1833
1834 // Check the initial post-order. We ensure this order with the extra edges
1835 // that are nuked above.
1836 ASSERT_EQ(8, RC.size());
1837 EXPECT_EQ(&DC, &RC[0]);
1838 EXPECT_EQ(&C3C, &RC[1]);
1839 EXPECT_EQ(&B3C, &RC[2]);
1840 EXPECT_EQ(&C2C, &RC[3]);
1841 EXPECT_EQ(&B2C, &RC[4]);
1842 EXPECT_EQ(&C1C, &RC[5]);
1843 EXPECT_EQ(&B1C, &RC[6]);
1844 EXPECT_EQ(&AC, &RC[7]);
1845
1846 // Switch C3 -> B1 to a call edge. This doesn't form any new cycles but does
1847 // require reordering the SCCs in the face of tricky internal node
1848 // structures.
1849 auto MergedCs = RC.switchInternalEdgeToCall(C3, B1);
1850 EXPECT_EQ(0u, MergedCs.size());
1851 ASSERT_EQ(8, RC.size());
1852 EXPECT_EQ(&DC, &RC[0]);
1853 EXPECT_EQ(&B3C, &RC[1]);
1854 EXPECT_EQ(&B2C, &RC[2]);
1855 EXPECT_EQ(&B1C, &RC[3]);
1856 EXPECT_EQ(&C3C, &RC[4]);
1857 EXPECT_EQ(&C2C, &RC[5]);
1858 EXPECT_EQ(&C1C, &RC[6]);
1859 EXPECT_EQ(&AC, &RC[7]);
1860}
1861
1862TEST(LazyCallGraphTest, InternalRefEdgeToCallBothPartitionAndMerge) {
Mehdi Amini03b42e42016-04-14 21:59:01 +00001863 LLVMContext Context;
Chandler Carruthe5944d92016-02-17 00:18:16 +00001864 // Test for having a postorder where between the source and target are all
1865 // three kinds of other SCCs:
1866 // 1) One connected to the target only that have to be shifted below the
1867 // source.
1868 // 2) One connected to the source only that have to be shifted below the
1869 // target.
1870 // 3) One connected to both source and target that has to remain and get
1871 // merged away.
1872 //
1873 // To achieve this we construct a heavily connected graph to force
1874 // a particular post-order. Then we remove the forcing edges and connect
1875 // a cycle.
1876 //
1877 // Diagram for the graph we want on the left and the graph we use to force
1878 // the ordering on the right. Edges ponit down or right.
1879 //
1880 // A | A |
1881 // / \ | / \ |
1882 // B E | B \ |
1883 // |\ | | |\ | |
1884 // | D | | C-D-E |
1885 // | \| | | \| |
1886 // C F | \ F |
1887 // \ / | \ / |
1888 // G | G |
1889 //
1890 // And we form a cycle by connecting F to B.
Mehdi Amini03b42e42016-04-14 21:59:01 +00001891 std::unique_ptr<Module> M =
1892 parseAssembly(Context, "define void @a() {\n"
1893 "entry:\n"
1894 " call void @b()\n"
1895 " call void @e()\n"
1896 " ret void\n"
1897 "}\n"
1898 "define void @b() {\n"
1899 "entry:\n"
1900 " call void @c()\n"
1901 " call void @d()\n"
1902 " ret void\n"
1903 "}\n"
1904 "define void @c() {\n"
1905 "entry:\n"
1906 " call void @d()\n"
1907 " call void @g()\n"
1908 " ret void\n"
1909 "}\n"
1910 "define void @d() {\n"
1911 "entry:\n"
1912 " call void @e()\n"
1913 " call void @f()\n"
1914 " ret void\n"
1915 "}\n"
1916 "define void @e() {\n"
1917 "entry:\n"
1918 " call void @f()\n"
1919 " ret void\n"
1920 "}\n"
1921 "define void @f() {\n"
1922 "entry:\n"
1923 " store void()* @b, void()** undef\n"
1924 " call void @g()\n"
1925 " ret void\n"
1926 "}\n"
1927 "define void @g() {\n"
1928 "entry:\n"
1929 " store void()* @a, void()** undef\n"
1930 " ret void\n"
1931 "}\n");
Chandler Carruthe5944d92016-02-17 00:18:16 +00001932 LazyCallGraph CG(*M);
1933
1934 // Force the graph to be fully expanded.
1935 auto I = CG.postorder_ref_scc_begin();
1936 LazyCallGraph::RefSCC &RC = *I++;
1937 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1938
1939 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1940 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1941 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1942 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
1943 LazyCallGraph::Node &E = *CG.lookup(lookupFunction(*M, "e"));
1944 LazyCallGraph::Node &F = *CG.lookup(lookupFunction(*M, "f"));
1945 LazyCallGraph::Node &G = *CG.lookup(lookupFunction(*M, "g"));
1946 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
1947 LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
1948 LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
1949 LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
1950 LazyCallGraph::SCC &EC = *CG.lookupSCC(E);
1951 LazyCallGraph::SCC &FC = *CG.lookupSCC(F);
1952 LazyCallGraph::SCC &GC = *CG.lookupSCC(G);
1953
1954 // Remove the extra edges that were used to force a particular post-order.
1955 RC.switchInternalEdgeToRef(C, D);
1956 RC.switchInternalEdgeToRef(D, E);
1957
1958 // Check the initial post-order. We ensure this order with the extra edges
1959 // that are nuked above.
1960 ASSERT_EQ(7, RC.size());
1961 EXPECT_EQ(&GC, &RC[0]);
1962 EXPECT_EQ(&FC, &RC[1]);
1963 EXPECT_EQ(&EC, &RC[2]);
1964 EXPECT_EQ(&DC, &RC[3]);
1965 EXPECT_EQ(&CC, &RC[4]);
1966 EXPECT_EQ(&BC, &RC[5]);
1967 EXPECT_EQ(&AC, &RC[6]);
1968
1969 // Switch F -> B to a call edge. This merges B, D, and F into a single SCC,
1970 // and has to place the C and E SCCs on either side of it:
1971 // A A |
1972 // / \ / \ |
1973 // B E | E |
1974 // |\ | \ / |
1975 // | D | -> B |
1976 // | \| / \ |
1977 // C F C | |
1978 // \ / \ / |
1979 // G G |
1980 auto MergedCs = RC.switchInternalEdgeToCall(F, B);
1981 ASSERT_EQ(2u, MergedCs.size());
1982 EXPECT_EQ(&FC, MergedCs[0]);
1983 EXPECT_EQ(&DC, MergedCs[1]);
1984 EXPECT_EQ(3, BC.size());
1985
1986 // And make sure the postorder was updated.
1987 ASSERT_EQ(5, RC.size());
1988 EXPECT_EQ(&GC, &RC[0]);
1989 EXPECT_EQ(&CC, &RC[1]);
1990 EXPECT_EQ(&BC, &RC[2]);
1991 EXPECT_EQ(&EC, &RC[3]);
1992 EXPECT_EQ(&AC, &RC[4]);
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001993}
1994
Chandler Carruthc7bad9a2014-04-23 08:08:49 +00001995}