blob: 45c24eedf7e1e420ac31c02ca1d4d0c6a9dfc1b2 [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));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000597 EXPECT_TRUE(AC.isParentOf(BC));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000598 EXPECT_TRUE(ARC.isParentOf(CRC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000599 EXPECT_TRUE(AC.isParentOf(CC));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000600 EXPECT_FALSE(ARC.isParentOf(DRC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000601 EXPECT_FALSE(AC.isParentOf(DC));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000602 EXPECT_TRUE(ARC.isAncestorOf(DRC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000603 EXPECT_TRUE(AC.isAncestorOf(DC));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000604 EXPECT_FALSE(DRC.isChildOf(ARC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000605 EXPECT_FALSE(DC.isChildOf(AC));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000606 EXPECT_TRUE(DRC.isDescendantOf(ARC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000607 EXPECT_TRUE(DC.isDescendantOf(AC));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000608 EXPECT_TRUE(DRC.isChildOf(BRC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000609 EXPECT_TRUE(DC.isChildOf(BC));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000610 EXPECT_TRUE(DRC.isChildOf(CRC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000611 EXPECT_TRUE(DC.isChildOf(CC));
Chandler Carruthcc6e1872014-05-04 09:38:23 +0000612
613 EXPECT_EQ(2, std::distance(A.begin(), A.end()));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000614 ARC.insertOutgoingEdge(A, D, LazyCallGraph::Edge::Call);
Chandler Carruthcc6e1872014-05-04 09:38:23 +0000615 EXPECT_EQ(3, std::distance(A.begin(), A.end()));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000616 const LazyCallGraph::Edge &NewE = A[D];
617 EXPECT_TRUE(NewE);
618 EXPECT_TRUE(NewE.isCall());
619 EXPECT_EQ(&D, NewE.getNode());
620
621 // Only the parent and child tests sholud have changed. The rest of the graph
622 // remains the same.
623 EXPECT_TRUE(ARC.isParentOf(DRC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000624 EXPECT_TRUE(AC.isParentOf(DC));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000625 EXPECT_TRUE(ARC.isAncestorOf(DRC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000626 EXPECT_TRUE(AC.isAncestorOf(DC));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000627 EXPECT_TRUE(DRC.isChildOf(ARC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000628 EXPECT_TRUE(DC.isChildOf(AC));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000629 EXPECT_TRUE(DRC.isDescendantOf(ARC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000630 EXPECT_TRUE(DC.isDescendantOf(AC));
Chandler Carruthcc6e1872014-05-04 09:38:23 +0000631 EXPECT_EQ(&AC, CG.lookupSCC(A));
632 EXPECT_EQ(&BC, CG.lookupSCC(B));
633 EXPECT_EQ(&CC, CG.lookupSCC(C));
634 EXPECT_EQ(&DC, CG.lookupSCC(D));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000635 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
636 EXPECT_EQ(&BRC, CG.lookupRefSCC(B));
637 EXPECT_EQ(&CRC, CG.lookupRefSCC(C));
638 EXPECT_EQ(&DRC, CG.lookupRefSCC(D));
639
640 ARC.switchOutgoingEdgeToRef(A, D);
641 EXPECT_FALSE(NewE.isCall());
642
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000643 // Verify the reference graph remains the same but the SCC graph is updated.
Chandler Carruthe5944d92016-02-17 00:18:16 +0000644 EXPECT_TRUE(ARC.isParentOf(DRC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000645 EXPECT_FALSE(AC.isParentOf(DC));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000646 EXPECT_TRUE(ARC.isAncestorOf(DRC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000647 EXPECT_TRUE(AC.isAncestorOf(DC));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000648 EXPECT_TRUE(DRC.isChildOf(ARC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000649 EXPECT_FALSE(DC.isChildOf(AC));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000650 EXPECT_TRUE(DRC.isDescendantOf(ARC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000651 EXPECT_TRUE(DC.isDescendantOf(AC));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000652 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.switchOutgoingEdgeToCall(A, D);
662 EXPECT_TRUE(NewE.isCall());
663
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000664 // Verify the reference graph remains the same but the SCC graph is updated.
Chandler Carruthe5944d92016-02-17 00:18:16 +0000665 EXPECT_TRUE(ARC.isParentOf(DRC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000666 EXPECT_TRUE(AC.isParentOf(DC));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000667 EXPECT_TRUE(ARC.isAncestorOf(DRC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000668 EXPECT_TRUE(AC.isAncestorOf(DC));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000669 EXPECT_TRUE(DRC.isChildOf(ARC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000670 EXPECT_TRUE(DC.isChildOf(AC));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000671 EXPECT_TRUE(DRC.isDescendantOf(ARC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000672 EXPECT_TRUE(DC.isDescendantOf(AC));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000673 EXPECT_EQ(&AC, CG.lookupSCC(A));
674 EXPECT_EQ(&BC, CG.lookupSCC(B));
675 EXPECT_EQ(&CC, CG.lookupSCC(C));
676 EXPECT_EQ(&DC, CG.lookupSCC(D));
677 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
678 EXPECT_EQ(&BRC, CG.lookupRefSCC(B));
679 EXPECT_EQ(&CRC, CG.lookupRefSCC(C));
680 EXPECT_EQ(&DRC, CG.lookupRefSCC(D));
681
682 ARC.removeOutgoingEdge(A, D);
683 EXPECT_EQ(2, std::distance(A.begin(), A.end()));
684
685 // Now the parent and child tests fail again but the rest remains the same.
686 EXPECT_FALSE(ARC.isParentOf(DRC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000687 EXPECT_FALSE(AC.isParentOf(DC));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000688 EXPECT_TRUE(ARC.isAncestorOf(DRC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000689 EXPECT_TRUE(AC.isAncestorOf(DC));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000690 EXPECT_FALSE(DRC.isChildOf(ARC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000691 EXPECT_FALSE(DC.isChildOf(AC));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000692 EXPECT_TRUE(DRC.isDescendantOf(ARC));
Chandler Carruthf8c09d62016-11-22 20:35:32 +0000693 EXPECT_TRUE(DC.isDescendantOf(AC));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000694 EXPECT_EQ(&AC, CG.lookupSCC(A));
695 EXPECT_EQ(&BC, CG.lookupSCC(B));
696 EXPECT_EQ(&CC, CG.lookupSCC(C));
697 EXPECT_EQ(&DC, CG.lookupSCC(D));
698 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
699 EXPECT_EQ(&BRC, CG.lookupRefSCC(B));
700 EXPECT_EQ(&CRC, CG.lookupRefSCC(C));
701 EXPECT_EQ(&DRC, CG.lookupRefSCC(D));
Chandler Carruthcc6e1872014-05-04 09:38:23 +0000702}
703
Chandler Carruthe5944d92016-02-17 00:18:16 +0000704TEST(LazyCallGraphTest, IncomingEdgeInsertion) {
Mehdi Amini03b42e42016-04-14 21:59:01 +0000705 LLVMContext Context;
Chandler Carruth312dddf2014-05-04 09:38:32 +0000706 // We want to ensure we can add edges even across complex diamond graphs, so
707 // we use the diamond of triangles graph defined above. The ascii diagram is
708 // repeated here for easy reference.
709 //
710 // d1 |
711 // / \ |
712 // d3--d2 |
713 // / \ |
714 // b1 c1 |
715 // / \ / \ |
716 // b3--b2 c3--c2 |
717 // \ / |
718 // a1 |
719 // / \ |
720 // a3--a2 |
721 //
Mehdi Amini03b42e42016-04-14 21:59:01 +0000722 std::unique_ptr<Module> M = parseAssembly(Context, DiamondOfTriangles);
Chandler Carruth312dddf2014-05-04 09:38:32 +0000723 LazyCallGraph CG(*M);
724
725 // Force the graph to be fully expanded.
Chandler Carruthe5944d92016-02-17 00:18:16 +0000726 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
Chandler Carruth49d728a2016-09-16 10:20:17 +0000727 dbgs() << "Formed RefSCC: " << RC << "\n";
Chandler Carruth312dddf2014-05-04 09:38:32 +0000728
729 LazyCallGraph::Node &A1 = *CG.lookup(lookupFunction(*M, "a1"));
730 LazyCallGraph::Node &A2 = *CG.lookup(lookupFunction(*M, "a2"));
731 LazyCallGraph::Node &A3 = *CG.lookup(lookupFunction(*M, "a3"));
732 LazyCallGraph::Node &B1 = *CG.lookup(lookupFunction(*M, "b1"));
733 LazyCallGraph::Node &B2 = *CG.lookup(lookupFunction(*M, "b2"));
734 LazyCallGraph::Node &B3 = *CG.lookup(lookupFunction(*M, "b3"));
735 LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
736 LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
737 LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
738 LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
739 LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
740 LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000741 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(A1);
742 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(B1);
743 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(C1);
744 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(D1);
745 ASSERT_EQ(&ARC, CG.lookupRefSCC(A2));
746 ASSERT_EQ(&ARC, CG.lookupRefSCC(A3));
747 ASSERT_EQ(&BRC, CG.lookupRefSCC(B2));
748 ASSERT_EQ(&BRC, CG.lookupRefSCC(B3));
749 ASSERT_EQ(&CRC, CG.lookupRefSCC(C2));
750 ASSERT_EQ(&CRC, CG.lookupRefSCC(C3));
751 ASSERT_EQ(&DRC, CG.lookupRefSCC(D2));
752 ASSERT_EQ(&DRC, CG.lookupRefSCC(D3));
Chandler Carruth312dddf2014-05-04 09:38:32 +0000753 ASSERT_EQ(1, std::distance(D2.begin(), D2.end()));
754
755 // Add an edge to make the graph:
756 //
757 // d1 |
758 // / \ |
759 // d3--d2---. |
760 // / \ | |
761 // b1 c1 | |
762 // / \ / \ / |
763 // b3--b2 c3--c2 |
764 // \ / |
765 // a1 |
766 // / \ |
767 // a3--a2 |
Chandler Carruthe5944d92016-02-17 00:18:16 +0000768 auto MergedRCs = CRC.insertIncomingRefEdge(D2, C2);
Chandler Carruth312dddf2014-05-04 09:38:32 +0000769 // Make sure we connected the nodes.
Chandler Carruthe5944d92016-02-17 00:18:16 +0000770 for (LazyCallGraph::Edge E : D2) {
771 if (E.getNode() == &D3)
772 continue;
773 EXPECT_EQ(&C2, E.getNode());
774 }
775 // And marked the D ref-SCC as no longer valid.
776 EXPECT_EQ(1u, MergedRCs.size());
777 EXPECT_EQ(&DRC, MergedRCs[0]);
Chandler Carruth312dddf2014-05-04 09:38:32 +0000778
779 // Make sure we have the correct nodes in the SCC sets.
Chandler Carruthe5944d92016-02-17 00:18:16 +0000780 EXPECT_EQ(&ARC, CG.lookupRefSCC(A1));
781 EXPECT_EQ(&ARC, CG.lookupRefSCC(A2));
782 EXPECT_EQ(&ARC, CG.lookupRefSCC(A3));
783 EXPECT_EQ(&BRC, CG.lookupRefSCC(B1));
784 EXPECT_EQ(&BRC, CG.lookupRefSCC(B2));
785 EXPECT_EQ(&BRC, CG.lookupRefSCC(B3));
786 EXPECT_EQ(&CRC, CG.lookupRefSCC(C1));
787 EXPECT_EQ(&CRC, CG.lookupRefSCC(C2));
788 EXPECT_EQ(&CRC, CG.lookupRefSCC(C3));
789 EXPECT_EQ(&CRC, CG.lookupRefSCC(D1));
790 EXPECT_EQ(&CRC, CG.lookupRefSCC(D2));
791 EXPECT_EQ(&CRC, CG.lookupRefSCC(D3));
Chandler Carruth312dddf2014-05-04 09:38:32 +0000792
793 // And that ancestry tests have been updated.
Chandler Carruthe5944d92016-02-17 00:18:16 +0000794 EXPECT_TRUE(ARC.isParentOf(CRC));
795 EXPECT_TRUE(BRC.isParentOf(CRC));
Chandler Carruth49d728a2016-09-16 10:20:17 +0000796
797 // And verify the post-order walk reflects the updated structure.
798 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
799 ASSERT_NE(I, E);
800 EXPECT_EQ(&CRC, &*I) << "Actual RefSCC: " << *I;
801 ASSERT_NE(++I, E);
802 EXPECT_EQ(&BRC, &*I) << "Actual RefSCC: " << *I;
803 ASSERT_NE(++I, E);
804 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
805 EXPECT_EQ(++I, E);
Chandler Carruth312dddf2014-05-04 09:38:32 +0000806}
807
Chandler Carruthe5944d92016-02-17 00:18:16 +0000808TEST(LazyCallGraphTest, IncomingEdgeInsertionMidTraversal) {
Mehdi Amini03b42e42016-04-14 21:59:01 +0000809 LLVMContext Context;
Chandler Carruth312dddf2014-05-04 09:38:32 +0000810 // This is the same fundamental test as the previous, but we perform it
Chandler Carruthe5944d92016-02-17 00:18:16 +0000811 // having only partially walked the RefSCCs of the graph.
Mehdi Amini03b42e42016-04-14 21:59:01 +0000812 std::unique_ptr<Module> M = parseAssembly(Context, DiamondOfTriangles);
Chandler Carruth312dddf2014-05-04 09:38:32 +0000813 LazyCallGraph CG(*M);
814
Chandler Carruthe5944d92016-02-17 00:18:16 +0000815 // Walk the RefSCCs until we find the one containing 'c1'.
816 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
817 ASSERT_NE(I, E);
818 LazyCallGraph::RefSCC &DRC = *I;
819 ASSERT_NE(&DRC, nullptr);
820 ++I;
821 ASSERT_NE(I, E);
822 LazyCallGraph::RefSCC &CRC = *I;
823 ASSERT_NE(&CRC, nullptr);
Chandler Carruth312dddf2014-05-04 09:38:32 +0000824
825 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a1")));
826 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a2")));
827 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a3")));
828 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b1")));
829 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b2")));
830 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b3")));
831 LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
832 LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
833 LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
834 LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
835 LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
836 LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
Chandler Carruthe5944d92016-02-17 00:18:16 +0000837 ASSERT_EQ(&CRC, CG.lookupRefSCC(C1));
838 ASSERT_EQ(&CRC, CG.lookupRefSCC(C2));
839 ASSERT_EQ(&CRC, CG.lookupRefSCC(C3));
840 ASSERT_EQ(&DRC, CG.lookupRefSCC(D1));
841 ASSERT_EQ(&DRC, CG.lookupRefSCC(D2));
842 ASSERT_EQ(&DRC, CG.lookupRefSCC(D3));
Chandler Carruth312dddf2014-05-04 09:38:32 +0000843 ASSERT_EQ(1, std::distance(D2.begin(), D2.end()));
844
Chandler Carruthe5944d92016-02-17 00:18:16 +0000845 auto MergedRCs = CRC.insertIncomingRefEdge(D2, C2);
846 // Make sure we connected the nodes.
847 for (LazyCallGraph::Edge E : D2) {
848 if (E.getNode() == &D3)
849 continue;
850 EXPECT_EQ(&C2, E.getNode());
851 }
852 // And marked the D ref-SCC as no longer valid.
853 EXPECT_EQ(1u, MergedRCs.size());
854 EXPECT_EQ(&DRC, MergedRCs[0]);
Chandler Carruth312dddf2014-05-04 09:38:32 +0000855
Chandler Carruthe5944d92016-02-17 00:18:16 +0000856 // Make sure we have the correct nodes in the RefSCCs.
857 EXPECT_EQ(&CRC, CG.lookupRefSCC(C1));
858 EXPECT_EQ(&CRC, CG.lookupRefSCC(C2));
859 EXPECT_EQ(&CRC, CG.lookupRefSCC(C3));
860 EXPECT_EQ(&CRC, CG.lookupRefSCC(D1));
861 EXPECT_EQ(&CRC, CG.lookupRefSCC(D2));
862 EXPECT_EQ(&CRC, CG.lookupRefSCC(D3));
Chandler Carruth312dddf2014-05-04 09:38:32 +0000863
Chandler Carruth49d728a2016-09-16 10:20:17 +0000864 // Verify that the post-order walk reflects the updated but still incomplete
865 // structure.
866 auto J = CG.postorder_ref_scc_begin();
867 EXPECT_NE(J, E);
868 EXPECT_EQ(&CRC, &*J) << "Actual RefSCC: " << *J;
869 EXPECT_EQ(I, J);
870
871 // Check that we can form the last two RefSCCs now, and even that we can do
872 // it with alternating iterators.
873 ++J;
874 EXPECT_NE(J, E);
875 LazyCallGraph::RefSCC &BRC = *J;
Chandler Carruthe5944d92016-02-17 00:18:16 +0000876 EXPECT_NE(&BRC, nullptr);
877 EXPECT_EQ(&BRC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "b1"))));
878 EXPECT_EQ(&BRC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "b2"))));
879 EXPECT_EQ(&BRC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "b3"))));
880 EXPECT_TRUE(BRC.isParentOf(CRC));
881 ++I;
Chandler Carruth49d728a2016-09-16 10:20:17 +0000882 EXPECT_EQ(J, I);
883 EXPECT_EQ(&BRC, &*I) << "Actual RefSCC: " << *I;
884
885 // Increment I this time to form the new RefSCC, flopping back to the first
886 // iterator.
887 ++I;
Chandler Carruthe5944d92016-02-17 00:18:16 +0000888 EXPECT_NE(I, E);
889 LazyCallGraph::RefSCC &ARC = *I;
890 EXPECT_NE(&ARC, nullptr);
891 EXPECT_EQ(&ARC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "a1"))));
892 EXPECT_EQ(&ARC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "a2"))));
893 EXPECT_EQ(&ARC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "a3"))));
894 EXPECT_TRUE(ARC.isParentOf(CRC));
Chandler Carruth49d728a2016-09-16 10:20:17 +0000895 ++J;
896 EXPECT_EQ(I, J);
897 EXPECT_EQ(&ARC, &*J) << "Actual RefSCC: " << *J;
Chandler Carruthe5944d92016-02-17 00:18:16 +0000898 ++I;
899 EXPECT_EQ(E, I);
Chandler Carruth49d728a2016-09-16 10:20:17 +0000900 ++J;
901 EXPECT_EQ(E, J);
902}
903
904TEST(LazyCallGraphTest, IncomingEdgeInsertionRefGraph) {
905 LLVMContext Context;
906 // Another variation of the above test but with all the edges switched to
907 // references rather than calls.
908 std::unique_ptr<Module> M =
909 parseAssembly(Context, DiamondOfTrianglesRefGraph);
910 LazyCallGraph CG(*M);
911
912 // Force the graph to be fully expanded.
913 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
914 dbgs() << "Formed RefSCC: " << RC << "\n";
915
916 LazyCallGraph::Node &A1 = *CG.lookup(lookupFunction(*M, "a1"));
917 LazyCallGraph::Node &A2 = *CG.lookup(lookupFunction(*M, "a2"));
918 LazyCallGraph::Node &A3 = *CG.lookup(lookupFunction(*M, "a3"));
919 LazyCallGraph::Node &B1 = *CG.lookup(lookupFunction(*M, "b1"));
920 LazyCallGraph::Node &B2 = *CG.lookup(lookupFunction(*M, "b2"));
921 LazyCallGraph::Node &B3 = *CG.lookup(lookupFunction(*M, "b3"));
922 LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
923 LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
924 LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
925 LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
926 LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
927 LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
928 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(A1);
929 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(B1);
930 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(C1);
931 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(D1);
932 ASSERT_EQ(&ARC, CG.lookupRefSCC(A2));
933 ASSERT_EQ(&ARC, CG.lookupRefSCC(A3));
934 ASSERT_EQ(&BRC, CG.lookupRefSCC(B2));
935 ASSERT_EQ(&BRC, CG.lookupRefSCC(B3));
936 ASSERT_EQ(&CRC, CG.lookupRefSCC(C2));
937 ASSERT_EQ(&CRC, CG.lookupRefSCC(C3));
938 ASSERT_EQ(&DRC, CG.lookupRefSCC(D2));
939 ASSERT_EQ(&DRC, CG.lookupRefSCC(D3));
940 ASSERT_EQ(1, std::distance(D2.begin(), D2.end()));
941
942 // Add an edge to make the graph:
943 //
944 // d1 |
945 // / \ |
946 // d3--d2---. |
947 // / \ | |
948 // b1 c1 | |
949 // / \ / \ / |
950 // b3--b2 c3--c2 |
951 // \ / |
952 // a1 |
953 // / \ |
954 // a3--a2 |
955 auto MergedRCs = CRC.insertIncomingRefEdge(D2, C2);
956 // Make sure we connected the nodes.
957 for (LazyCallGraph::Edge E : D2) {
958 if (E.getNode() == &D3)
959 continue;
960 EXPECT_EQ(&C2, E.getNode());
961 }
962 // And marked the D ref-SCC as no longer valid.
963 EXPECT_EQ(1u, MergedRCs.size());
964 EXPECT_EQ(&DRC, MergedRCs[0]);
965
966 // Make sure we have the correct nodes in the SCC sets.
967 EXPECT_EQ(&ARC, CG.lookupRefSCC(A1));
968 EXPECT_EQ(&ARC, CG.lookupRefSCC(A2));
969 EXPECT_EQ(&ARC, CG.lookupRefSCC(A3));
970 EXPECT_EQ(&BRC, CG.lookupRefSCC(B1));
971 EXPECT_EQ(&BRC, CG.lookupRefSCC(B2));
972 EXPECT_EQ(&BRC, CG.lookupRefSCC(B3));
973 EXPECT_EQ(&CRC, CG.lookupRefSCC(C1));
974 EXPECT_EQ(&CRC, CG.lookupRefSCC(C2));
975 EXPECT_EQ(&CRC, CG.lookupRefSCC(C3));
976 EXPECT_EQ(&CRC, CG.lookupRefSCC(D1));
977 EXPECT_EQ(&CRC, CG.lookupRefSCC(D2));
978 EXPECT_EQ(&CRC, CG.lookupRefSCC(D3));
979
980 // And that ancestry tests have been updated.
981 EXPECT_TRUE(ARC.isParentOf(CRC));
982 EXPECT_TRUE(BRC.isParentOf(CRC));
983
984 // And verify the post-order walk reflects the updated structure.
985 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
986 ASSERT_NE(I, E);
987 EXPECT_EQ(&CRC, &*I) << "Actual RefSCC: " << *I;
988 ASSERT_NE(++I, E);
989 EXPECT_EQ(&BRC, &*I) << "Actual RefSCC: " << *I;
990 ASSERT_NE(++I, E);
991 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
992 EXPECT_EQ(++I, E);
993}
994
995TEST(LazyCallGraphTest, IncomingEdgeInsertionLargeCallCycle) {
996 LLVMContext Context;
997 std::unique_ptr<Module> M = parseAssembly(Context, "define void @a() {\n"
998 "entry:\n"
999 " call void @b()\n"
1000 " ret void\n"
1001 "}\n"
1002 "define void @b() {\n"
1003 "entry:\n"
1004 " call void @c()\n"
1005 " ret void\n"
1006 "}\n"
1007 "define void @c() {\n"
1008 "entry:\n"
1009 " call void @d()\n"
1010 " ret void\n"
1011 "}\n"
1012 "define void @d() {\n"
1013 "entry:\n"
1014 " ret void\n"
1015 "}\n");
1016 LazyCallGraph CG(*M);
1017
1018 // Force the graph to be fully expanded.
1019 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
1020 dbgs() << "Formed RefSCC: " << RC << "\n";
1021
1022 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1023 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1024 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1025 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
1026 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
1027 LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
1028 LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
1029 LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
1030 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(A);
1031 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(B);
1032 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(C);
1033 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(D);
1034
1035 // Connect the top to the bottom forming a large RefSCC made up mostly of calls.
1036 auto MergedRCs = ARC.insertIncomingRefEdge(D, A);
1037 // Make sure we connected the nodes.
1038 EXPECT_NE(D.begin(), D.end());
1039 EXPECT_EQ(&A, D.begin()->getNode());
1040
1041 // Check that we have the dead RCs, but ignore the order.
1042 EXPECT_EQ(3u, MergedRCs.size());
1043 EXPECT_NE(find(MergedRCs, &BRC), MergedRCs.end());
1044 EXPECT_NE(find(MergedRCs, &CRC), MergedRCs.end());
1045 EXPECT_NE(find(MergedRCs, &DRC), MergedRCs.end());
1046
1047 // Make sure the nodes point to the right place now.
1048 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
1049 EXPECT_EQ(&ARC, CG.lookupRefSCC(B));
1050 EXPECT_EQ(&ARC, CG.lookupRefSCC(C));
1051 EXPECT_EQ(&ARC, CG.lookupRefSCC(D));
1052
1053 // Check that the SCCs are in postorder.
1054 EXPECT_EQ(4, ARC.size());
1055 EXPECT_EQ(&DC, &ARC[0]);
1056 EXPECT_EQ(&CC, &ARC[1]);
1057 EXPECT_EQ(&BC, &ARC[2]);
1058 EXPECT_EQ(&AC, &ARC[3]);
1059
1060 // And verify the post-order walk reflects the updated structure.
1061 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
1062 ASSERT_NE(I, E);
1063 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
1064 EXPECT_EQ(++I, E);
1065}
1066
1067TEST(LazyCallGraphTest, IncomingEdgeInsertionLargeRefCycle) {
1068 LLVMContext Context;
1069 std::unique_ptr<Module> M =
1070 parseAssembly(Context, "define void @a() {\n"
1071 "entry:\n"
1072 " %p = alloca void ()*\n"
1073 " store void ()* @b, void ()** %p\n"
1074 " ret void\n"
1075 "}\n"
1076 "define void @b() {\n"
1077 "entry:\n"
1078 " %p = alloca void ()*\n"
1079 " store void ()* @c, void ()** %p\n"
1080 " ret void\n"
1081 "}\n"
1082 "define void @c() {\n"
1083 "entry:\n"
1084 " %p = alloca void ()*\n"
1085 " store void ()* @d, void ()** %p\n"
1086 " ret void\n"
1087 "}\n"
1088 "define void @d() {\n"
1089 "entry:\n"
1090 " ret void\n"
1091 "}\n");
1092 LazyCallGraph CG(*M);
1093
1094 // Force the graph to be fully expanded.
1095 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
1096 dbgs() << "Formed RefSCC: " << RC << "\n";
1097
1098 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1099 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1100 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1101 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
1102 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(A);
1103 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(B);
1104 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(C);
1105 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(D);
1106
1107 // Connect the top to the bottom forming a large RefSCC made up just of
1108 // references.
1109 auto MergedRCs = ARC.insertIncomingRefEdge(D, A);
1110 // Make sure we connected the nodes.
1111 EXPECT_NE(D.begin(), D.end());
1112 EXPECT_EQ(&A, D.begin()->getNode());
1113
1114 // Check that we have the dead RCs, but ignore the order.
1115 EXPECT_EQ(3u, MergedRCs.size());
1116 EXPECT_NE(find(MergedRCs, &BRC), MergedRCs.end());
1117 EXPECT_NE(find(MergedRCs, &CRC), MergedRCs.end());
1118 EXPECT_NE(find(MergedRCs, &DRC), MergedRCs.end());
1119
1120 // Make sure the nodes point to the right place now.
1121 EXPECT_EQ(&ARC, CG.lookupRefSCC(A));
1122 EXPECT_EQ(&ARC, CG.lookupRefSCC(B));
1123 EXPECT_EQ(&ARC, CG.lookupRefSCC(C));
1124 EXPECT_EQ(&ARC, CG.lookupRefSCC(D));
1125
1126 // And verify the post-order walk reflects the updated structure.
1127 auto I = CG.postorder_ref_scc_begin(), End = CG.postorder_ref_scc_end();
1128 ASSERT_NE(I, End);
1129 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
1130 EXPECT_EQ(++I, End);
Chandler Carruth312dddf2014-05-04 09:38:32 +00001131}
1132
Chandler Carruth5dbc1642016-10-12 07:59:56 +00001133TEST(LazyCallGraphTest, InlineAndDeleteFunction) {
1134 LLVMContext Context;
1135 // We want to ensure we can delete nodes from relatively complex graphs and
1136 // so use the diamond of triangles graph defined above.
1137 //
1138 // The ascii diagram is repeated here for easy reference.
1139 //
1140 // d1 |
1141 // / \ |
1142 // d3--d2 |
1143 // / \ |
1144 // b1 c1 |
1145 // / \ / \ |
1146 // b3--b2 c3--c2 |
1147 // \ / |
1148 // a1 |
1149 // / \ |
1150 // a3--a2 |
1151 //
1152 std::unique_ptr<Module> M = parseAssembly(Context, DiamondOfTriangles);
1153 LazyCallGraph CG(*M);
1154
1155 // Force the graph to be fully expanded.
1156 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs())
1157 dbgs() << "Formed RefSCC: " << RC << "\n";
1158
1159 LazyCallGraph::Node &A1 = *CG.lookup(lookupFunction(*M, "a1"));
1160 LazyCallGraph::Node &A2 = *CG.lookup(lookupFunction(*M, "a2"));
1161 LazyCallGraph::Node &A3 = *CG.lookup(lookupFunction(*M, "a3"));
1162 LazyCallGraph::Node &B1 = *CG.lookup(lookupFunction(*M, "b1"));
1163 LazyCallGraph::Node &B2 = *CG.lookup(lookupFunction(*M, "b2"));
1164 LazyCallGraph::Node &B3 = *CG.lookup(lookupFunction(*M, "b3"));
1165 LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
1166 LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
1167 LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
1168 LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
1169 LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
1170 LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
1171 LazyCallGraph::RefSCC &ARC = *CG.lookupRefSCC(A1);
1172 LazyCallGraph::RefSCC &BRC = *CG.lookupRefSCC(B1);
1173 LazyCallGraph::RefSCC &CRC = *CG.lookupRefSCC(C1);
1174 LazyCallGraph::RefSCC &DRC = *CG.lookupRefSCC(D1);
1175 ASSERT_EQ(&ARC, CG.lookupRefSCC(A2));
1176 ASSERT_EQ(&ARC, CG.lookupRefSCC(A3));
1177 ASSERT_EQ(&BRC, CG.lookupRefSCC(B2));
1178 ASSERT_EQ(&BRC, CG.lookupRefSCC(B3));
1179 ASSERT_EQ(&CRC, CG.lookupRefSCC(C2));
1180 ASSERT_EQ(&CRC, CG.lookupRefSCC(C3));
1181 ASSERT_EQ(&DRC, CG.lookupRefSCC(D2));
1182 ASSERT_EQ(&DRC, CG.lookupRefSCC(D3));
1183 ASSERT_EQ(1, std::distance(D2.begin(), D2.end()));
1184
1185 // Delete d2 from the graph, as if it had been inlined.
1186 //
1187 // d1 |
1188 // / / |
1189 // d3--. |
1190 // / \ |
1191 // b1 c1 |
1192 // / \ / \ |
1193 // b3--b2 c3--c2 |
1194 // \ / |
1195 // a1 |
1196 // / \ |
1197 // a3--a2 |
1198
1199 Function &D2F = D2.getFunction();
1200 CallInst *C1Call = nullptr, *D1Call = nullptr;
1201 for (User *U : D2F.users()) {
1202 CallInst *CI = dyn_cast<CallInst>(U);
1203 ASSERT_TRUE(CI) << "Expected a call: " << *U;
1204 if (CI->getParent()->getParent() == &C1.getFunction()) {
1205 ASSERT_EQ(nullptr, C1Call) << "Found too many C1 calls: " << *CI;
1206 C1Call = CI;
1207 } else if (CI->getParent()->getParent() == &D1.getFunction()) {
1208 ASSERT_EQ(nullptr, D1Call) << "Found too many D1 calls: " << *CI;
1209 D1Call = CI;
1210 } else {
1211 FAIL() << "Found an unexpected call instruction: " << *CI;
1212 }
1213 }
1214 ASSERT_NE(C1Call, nullptr);
1215 ASSERT_NE(D1Call, nullptr);
1216 ASSERT_EQ(&D2F, C1Call->getCalledFunction());
1217 ASSERT_EQ(&D2F, D1Call->getCalledFunction());
1218 C1Call->setCalledFunction(&D3.getFunction());
1219 D1Call->setCalledFunction(&D3.getFunction());
1220 ASSERT_EQ(0u, D2F.getNumUses());
1221
1222 // Insert new edges first.
1223 CRC.insertTrivialCallEdge(C1, D3);
1224 DRC.insertTrivialCallEdge(D1, D3);
1225
1226 // Then remove the old ones.
1227 LazyCallGraph::SCC &DC = *CG.lookupSCC(D2);
1228 auto NewCs = DRC.switchInternalEdgeToRef(D1, D2);
1229 EXPECT_EQ(&DC, CG.lookupSCC(D2));
1230 EXPECT_EQ(NewCs.end(), std::next(NewCs.begin()));
1231 LazyCallGraph::SCC &NewDC = *NewCs.begin();
1232 EXPECT_EQ(&NewDC, CG.lookupSCC(D1));
1233 EXPECT_EQ(&NewDC, CG.lookupSCC(D3));
1234 auto NewRCs = DRC.removeInternalRefEdge(D1, D2);
1235 EXPECT_EQ(&DRC, CG.lookupRefSCC(D2));
1236 EXPECT_EQ(NewRCs.end(), std::next(NewRCs.begin()));
1237 LazyCallGraph::RefSCC &NewDRC = **NewRCs.begin();
1238 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D1));
1239 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D3));
1240 EXPECT_FALSE(NewDRC.isParentOf(DRC));
1241 EXPECT_TRUE(CRC.isParentOf(DRC));
1242 EXPECT_TRUE(CRC.isParentOf(NewDRC));
1243 EXPECT_TRUE(DRC.isParentOf(NewDRC));
1244 CRC.removeOutgoingEdge(C1, D2);
1245 EXPECT_FALSE(CRC.isParentOf(DRC));
1246 EXPECT_TRUE(CRC.isParentOf(NewDRC));
1247 EXPECT_TRUE(DRC.isParentOf(NewDRC));
1248
1249 // Now that we've updated the call graph, D2 is dead, so remove it.
1250 CG.removeDeadFunction(D2F);
1251
1252 // Check that the graph still looks the same.
1253 EXPECT_EQ(&ARC, CG.lookupRefSCC(A1));
1254 EXPECT_EQ(&ARC, CG.lookupRefSCC(A2));
1255 EXPECT_EQ(&ARC, CG.lookupRefSCC(A3));
1256 EXPECT_EQ(&BRC, CG.lookupRefSCC(B1));
1257 EXPECT_EQ(&BRC, CG.lookupRefSCC(B2));
1258 EXPECT_EQ(&BRC, CG.lookupRefSCC(B3));
1259 EXPECT_EQ(&CRC, CG.lookupRefSCC(C1));
1260 EXPECT_EQ(&CRC, CG.lookupRefSCC(C2));
1261 EXPECT_EQ(&CRC, CG.lookupRefSCC(C3));
1262 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D1));
1263 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D3));
1264 EXPECT_TRUE(CRC.isParentOf(NewDRC));
1265
1266 // Verify the post-order walk hasn't changed.
1267 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
1268 ASSERT_NE(I, E);
1269 EXPECT_EQ(&NewDRC, &*I) << "Actual RefSCC: " << *I;
1270 ASSERT_NE(++I, E);
1271 EXPECT_EQ(&CRC, &*I) << "Actual RefSCC: " << *I;
1272 ASSERT_NE(++I, E);
1273 EXPECT_EQ(&BRC, &*I) << "Actual RefSCC: " << *I;
1274 ASSERT_NE(++I, E);
1275 EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I;
1276 EXPECT_EQ(++I, E);
1277}
1278
1279TEST(LazyCallGraphTest, InlineAndDeleteFunctionMidTraversal) {
1280 LLVMContext Context;
1281 // This is the same fundamental test as the previous, but we perform it
1282 // having only partially walked the RefSCCs of the graph.
1283 //
1284 // The ascii diagram is repeated here for easy reference.
1285 //
1286 // d1 |
1287 // / \ |
1288 // d3--d2 |
1289 // / \ |
1290 // b1 c1 |
1291 // / \ / \ |
1292 // b3--b2 c3--c2 |
1293 // \ / |
1294 // a1 |
1295 // / \ |
1296 // a3--a2 |
1297 //
1298 std::unique_ptr<Module> M = parseAssembly(Context, DiamondOfTriangles);
1299 LazyCallGraph CG(*M);
1300
1301 // Walk the RefSCCs until we find the one containing 'c1'.
1302 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
1303 ASSERT_NE(I, E);
1304 LazyCallGraph::RefSCC &DRC = *I;
1305 ASSERT_NE(&DRC, nullptr);
1306 ++I;
1307 ASSERT_NE(I, E);
1308 LazyCallGraph::RefSCC &CRC = *I;
1309 ASSERT_NE(&CRC, nullptr);
1310
1311 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a1")));
1312 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a2")));
1313 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a3")));
1314 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b1")));
1315 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b2")));
1316 ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b3")));
1317 LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
1318 LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
1319 LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
1320 LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
1321 LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
1322 LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
1323 ASSERT_EQ(&CRC, CG.lookupRefSCC(C1));
1324 ASSERT_EQ(&CRC, CG.lookupRefSCC(C2));
1325 ASSERT_EQ(&CRC, CG.lookupRefSCC(C3));
1326 ASSERT_EQ(&DRC, CG.lookupRefSCC(D1));
1327 ASSERT_EQ(&DRC, CG.lookupRefSCC(D2));
1328 ASSERT_EQ(&DRC, CG.lookupRefSCC(D3));
1329 ASSERT_EQ(1, std::distance(D2.begin(), D2.end()));
1330
1331 // Delete d2 from the graph, as if it had been inlined.
1332 //
1333 // d1 |
1334 // / / |
1335 // d3--. |
1336 // / \ |
1337 // b1 c1 |
1338 // / \ / \ |
1339 // b3--b2 c3--c2 |
1340 // \ / |
1341 // a1 |
1342 // / \ |
1343 // a3--a2 |
1344
1345 Function &D2F = D2.getFunction();
1346 CallInst *C1Call = nullptr, *D1Call = nullptr;
1347 for (User *U : D2F.users()) {
1348 CallInst *CI = dyn_cast<CallInst>(U);
1349 ASSERT_TRUE(CI) << "Expected a call: " << *U;
1350 if (CI->getParent()->getParent() == &C1.getFunction()) {
1351 ASSERT_EQ(nullptr, C1Call) << "Found too many C1 calls: " << *CI;
1352 C1Call = CI;
1353 } else if (CI->getParent()->getParent() == &D1.getFunction()) {
1354 ASSERT_EQ(nullptr, D1Call) << "Found too many D1 calls: " << *CI;
1355 D1Call = CI;
1356 } else {
1357 FAIL() << "Found an unexpected call instruction: " << *CI;
1358 }
1359 }
1360 ASSERT_NE(C1Call, nullptr);
1361 ASSERT_NE(D1Call, nullptr);
1362 ASSERT_EQ(&D2F, C1Call->getCalledFunction());
1363 ASSERT_EQ(&D2F, D1Call->getCalledFunction());
1364 C1Call->setCalledFunction(&D3.getFunction());
1365 D1Call->setCalledFunction(&D3.getFunction());
1366 ASSERT_EQ(0u, D2F.getNumUses());
1367
1368 // Insert new edges first.
1369 CRC.insertTrivialCallEdge(C1, D3);
1370 DRC.insertTrivialCallEdge(D1, D3);
1371
1372 // Then remove the old ones.
1373 LazyCallGraph::SCC &DC = *CG.lookupSCC(D2);
1374 auto NewCs = DRC.switchInternalEdgeToRef(D1, D2);
1375 EXPECT_EQ(&DC, CG.lookupSCC(D2));
1376 EXPECT_EQ(NewCs.end(), std::next(NewCs.begin()));
1377 LazyCallGraph::SCC &NewDC = *NewCs.begin();
1378 EXPECT_EQ(&NewDC, CG.lookupSCC(D1));
1379 EXPECT_EQ(&NewDC, CG.lookupSCC(D3));
1380 auto NewRCs = DRC.removeInternalRefEdge(D1, D2);
1381 EXPECT_EQ(&DRC, CG.lookupRefSCC(D2));
1382 EXPECT_EQ(NewRCs.end(), std::next(NewRCs.begin()));
1383 LazyCallGraph::RefSCC &NewDRC = **NewRCs.begin();
1384 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D1));
1385 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D3));
1386 EXPECT_FALSE(NewDRC.isParentOf(DRC));
1387 EXPECT_TRUE(CRC.isParentOf(DRC));
1388 EXPECT_TRUE(CRC.isParentOf(NewDRC));
1389 EXPECT_TRUE(DRC.isParentOf(NewDRC));
1390 CRC.removeOutgoingEdge(C1, D2);
1391 EXPECT_FALSE(CRC.isParentOf(DRC));
1392 EXPECT_TRUE(CRC.isParentOf(NewDRC));
1393 EXPECT_TRUE(DRC.isParentOf(NewDRC));
1394
1395 // Now that we've updated the call graph, D2 is dead, so remove it.
1396 CG.removeDeadFunction(D2F);
1397
1398 // Check that the graph still looks the same.
1399 EXPECT_EQ(&CRC, CG.lookupRefSCC(C1));
1400 EXPECT_EQ(&CRC, CG.lookupRefSCC(C2));
1401 EXPECT_EQ(&CRC, CG.lookupRefSCC(C3));
1402 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D1));
1403 EXPECT_EQ(&NewDRC, CG.lookupRefSCC(D3));
1404 EXPECT_TRUE(CRC.isParentOf(NewDRC));
1405
1406 // Verify that the post-order walk reflects the updated but still incomplete
1407 // structure.
1408 auto J = CG.postorder_ref_scc_begin();
1409 EXPECT_NE(J, E);
1410 EXPECT_EQ(&NewDRC, &*J) << "Actual RefSCC: " << *J;
1411 ++J;
1412 EXPECT_NE(J, E);
1413 EXPECT_EQ(&CRC, &*J) << "Actual RefSCC: " << *J;
1414 EXPECT_EQ(I, J);
1415
1416 // Check that we can form the last two RefSCCs now, and even that we can do
1417 // it with alternating iterators.
1418 ++J;
1419 EXPECT_NE(J, E);
1420 LazyCallGraph::RefSCC &BRC = *J;
1421 EXPECT_NE(&BRC, nullptr);
1422 EXPECT_EQ(&BRC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "b1"))));
1423 EXPECT_EQ(&BRC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "b2"))));
1424 EXPECT_EQ(&BRC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "b3"))));
1425 EXPECT_TRUE(BRC.isParentOf(NewDRC));
1426 ++I;
1427 EXPECT_EQ(J, I);
1428 EXPECT_EQ(&BRC, &*I) << "Actual RefSCC: " << *I;
1429
1430 // Increment I this time to form the new RefSCC, flopping back to the first
1431 // iterator.
1432 ++I;
1433 EXPECT_NE(I, E);
1434 LazyCallGraph::RefSCC &ARC = *I;
1435 EXPECT_NE(&ARC, nullptr);
1436 EXPECT_EQ(&ARC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "a1"))));
1437 EXPECT_EQ(&ARC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "a2"))));
1438 EXPECT_EQ(&ARC, CG.lookupRefSCC(*CG.lookup(lookupFunction(*M, "a3"))));
1439 EXPECT_TRUE(ARC.isParentOf(BRC));
1440 EXPECT_TRUE(ARC.isParentOf(CRC));
1441 ++J;
1442 EXPECT_EQ(I, J);
1443 EXPECT_EQ(&ARC, &*J) << "Actual RefSCC: " << *J;
1444 ++I;
1445 EXPECT_EQ(E, I);
1446 ++J;
1447 EXPECT_EQ(E, J);
1448}
1449
Chandler Carruthe5944d92016-02-17 00:18:16 +00001450TEST(LazyCallGraphTest, InternalEdgeMutation) {
Mehdi Amini03b42e42016-04-14 21:59:01 +00001451 LLVMContext Context;
1452 std::unique_ptr<Module> M = parseAssembly(Context, "define void @a() {\n"
1453 "entry:\n"
1454 " call void @b()\n"
1455 " ret void\n"
1456 "}\n"
1457 "define void @b() {\n"
1458 "entry:\n"
1459 " call void @c()\n"
1460 " ret void\n"
1461 "}\n"
1462 "define void @c() {\n"
1463 "entry:\n"
1464 " call void @a()\n"
1465 " ret void\n"
1466 "}\n");
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001467 LazyCallGraph CG(*M);
1468
1469 // Force the graph to be fully expanded.
Chandler Carruthe5944d92016-02-17 00:18:16 +00001470 auto I = CG.postorder_ref_scc_begin();
1471 LazyCallGraph::RefSCC &RC = *I++;
1472 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001473
Chandler Carrutha10e2402014-04-23 23:12:06 +00001474 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1475 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
Chandler Carruthe5944d92016-02-17 00:18:16 +00001476 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1477 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1478 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1479 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
1480 EXPECT_EQ(1, RC.size());
1481 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(A));
1482 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(B));
1483 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(C));
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001484
Chandler Carruthe5944d92016-02-17 00:18:16 +00001485 // Insert an edge from 'a' to 'c'. Nothing changes about the graph.
1486 RC.insertInternalRefEdge(A, C);
Chandler Carruth5217c942014-04-30 10:48:36 +00001487 EXPECT_EQ(2, std::distance(A.begin(), A.end()));
Chandler Carruthe5944d92016-02-17 00:18:16 +00001488 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1489 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1490 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
1491 EXPECT_EQ(1, RC.size());
1492 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(A));
1493 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(B));
1494 EXPECT_EQ(&*RC.begin(), CG.lookupSCC(C));
Chandler Carruth5217c942014-04-30 10:48:36 +00001495
Chandler Carruthe5944d92016-02-17 00:18:16 +00001496 // Switch the call edge from 'b' to 'c' to a ref edge. This will break the
1497 // call cycle and cause us to form more SCCs. The RefSCC will remain the same
1498 // though.
1499 RC.switchInternalEdgeToRef(B, C);
1500 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1501 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1502 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
1503 auto J = RC.begin();
1504 // The SCCs must be in *post-order* which means successors before
1505 // predecessors. At this point we have call edges from C to A and from A to
1506 // B. The only valid postorder is B, A, C.
1507 EXPECT_EQ(&*J++, CG.lookupSCC(B));
1508 EXPECT_EQ(&*J++, CG.lookupSCC(A));
1509 EXPECT_EQ(&*J++, CG.lookupSCC(C));
1510 EXPECT_EQ(RC.end(), J);
1511
1512 // Test turning the ref edge from A to C into a call edge. This will form an
1513 // SCC out of A and C. Since we previously had a call edge from C to A, the
1514 // C SCC should be preserved and have A merged into it while the A SCC should
1515 // be invalidated.
1516 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
1517 LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
1518 auto InvalidatedSCCs = RC.switchInternalEdgeToCall(A, C);
1519 ASSERT_EQ(1u, InvalidatedSCCs.size());
1520 EXPECT_EQ(&AC, InvalidatedSCCs[0]);
1521 EXPECT_EQ(2, CC.size());
1522 EXPECT_EQ(&CC, CG.lookupSCC(A));
1523 EXPECT_EQ(&CC, CG.lookupSCC(C));
1524 J = RC.begin();
1525 EXPECT_EQ(&*J++, CG.lookupSCC(B));
1526 EXPECT_EQ(&*J++, CG.lookupSCC(C));
1527 EXPECT_EQ(RC.end(), J);
Chandler Carruth5217c942014-04-30 10:48:36 +00001528}
1529
Chandler Carruthe5944d92016-02-17 00:18:16 +00001530TEST(LazyCallGraphTest, InternalEdgeRemoval) {
Mehdi Amini03b42e42016-04-14 21:59:01 +00001531 LLVMContext Context;
Chandler Carruthe5944d92016-02-17 00:18:16 +00001532 // A nice fully connected (including self-edges) RefSCC.
1533 std::unique_ptr<Module> M = parseAssembly(
Mehdi Amini03b42e42016-04-14 21:59:01 +00001534 Context, "define void @a(i8** %ptr) {\n"
1535 "entry:\n"
1536 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1537 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1538 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1539 " ret void\n"
1540 "}\n"
1541 "define void @b(i8** %ptr) {\n"
1542 "entry:\n"
1543 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1544 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1545 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1546 " ret void\n"
1547 "}\n"
1548 "define void @c(i8** %ptr) {\n"
1549 "entry:\n"
1550 " store i8* bitcast (void(i8**)* @a to i8*), i8** %ptr\n"
1551 " store i8* bitcast (void(i8**)* @b to i8*), i8** %ptr\n"
1552 " store i8* bitcast (void(i8**)* @c to i8*), i8** %ptr\n"
1553 " ret void\n"
1554 "}\n");
Chandler Carruthe5944d92016-02-17 00:18:16 +00001555 LazyCallGraph CG(*M);
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001556
1557 // Force the graph to be fully expanded.
Chandler Carruth49d728a2016-09-16 10:20:17 +00001558 auto I = CG.postorder_ref_scc_begin(), E = CG.postorder_ref_scc_end();
1559 LazyCallGraph::RefSCC &RC = *I;
1560 EXPECT_EQ(E, std::next(I));
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001561
Chandler Carruthe5944d92016-02-17 00:18:16 +00001562 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1563 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1564 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1565 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1566 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1567 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001568
1569 // Remove the edge from b -> a, which should leave the 3 functions still in
1570 // a single connected component because of a -> b -> c -> a.
Chandler Carruthe5944d92016-02-17 00:18:16 +00001571 SmallVector<LazyCallGraph::RefSCC *, 1> NewRCs =
1572 RC.removeInternalRefEdge(B, A);
1573 EXPECT_EQ(0u, NewRCs.size());
1574 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1575 EXPECT_EQ(&RC, CG.lookupRefSCC(B));
1576 EXPECT_EQ(&RC, CG.lookupRefSCC(C));
Chandler Carruth49d728a2016-09-16 10:20:17 +00001577 auto J = CG.postorder_ref_scc_begin();
1578 EXPECT_EQ(I, J);
1579 EXPECT_EQ(&RC, &*J);
1580 EXPECT_EQ(E, std::next(J));
Chandler Carruthe5944d92016-02-17 00:18:16 +00001581
1582 // Remove the edge from c -> a, which should leave 'a' in the original RefSCC
1583 // and form a new RefSCC for 'b' and 'c'.
1584 NewRCs = RC.removeInternalRefEdge(C, A);
1585 EXPECT_EQ(1u, NewRCs.size());
1586 EXPECT_EQ(&RC, CG.lookupRefSCC(A));
1587 EXPECT_EQ(1, std::distance(RC.begin(), RC.end()));
Chandler Carruth49d728a2016-09-16 10:20:17 +00001588 LazyCallGraph::RefSCC &RC2 = *CG.lookupRefSCC(B);
1589 EXPECT_EQ(&RC2, CG.lookupRefSCC(C));
1590 EXPECT_EQ(&RC2, NewRCs[0]);
1591 J = CG.postorder_ref_scc_begin();
1592 EXPECT_NE(I, J);
1593 EXPECT_EQ(&RC2, &*J);
1594 ++J;
1595 EXPECT_EQ(I, J);
1596 EXPECT_EQ(&RC, &*J);
1597 ++I;
1598 EXPECT_EQ(E, I);
1599 ++J;
1600 EXPECT_EQ(E, J);
Chandler Carruthe5944d92016-02-17 00:18:16 +00001601}
1602
1603TEST(LazyCallGraphTest, InternalCallEdgeToRef) {
Mehdi Amini03b42e42016-04-14 21:59:01 +00001604 LLVMContext Context;
Chandler Carruthe5944d92016-02-17 00:18:16 +00001605 // A nice fully connected (including self-edges) SCC (and RefSCC)
Mehdi Amini03b42e42016-04-14 21:59:01 +00001606 std::unique_ptr<Module> M = parseAssembly(Context, "define void @a() {\n"
1607 "entry:\n"
1608 " call void @a()\n"
1609 " call void @b()\n"
1610 " call void @c()\n"
1611 " ret void\n"
1612 "}\n"
1613 "define void @b() {\n"
1614 "entry:\n"
1615 " call void @a()\n"
1616 " call void @b()\n"
1617 " call void @c()\n"
1618 " ret void\n"
1619 "}\n"
1620 "define void @c() {\n"
1621 "entry:\n"
1622 " call void @a()\n"
1623 " call void @b()\n"
1624 " call void @c()\n"
1625 " ret void\n"
1626 "}\n");
Chandler Carruthe5944d92016-02-17 00:18:16 +00001627 LazyCallGraph CG(*M);
1628
1629 // Force the graph to be fully expanded.
1630 auto I = CG.postorder_ref_scc_begin();
1631 LazyCallGraph::RefSCC &RC = *I++;
1632 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1633
1634 EXPECT_EQ(1, RC.size());
1635 LazyCallGraph::SCC &CallC = *RC.begin();
1636
1637 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1638 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1639 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1640 EXPECT_EQ(&CallC, CG.lookupSCC(A));
1641 EXPECT_EQ(&CallC, CG.lookupSCC(B));
1642 EXPECT_EQ(&CallC, CG.lookupSCC(C));
1643
1644 // Remove the call edge from b -> a to a ref edge, which should leave the
1645 // 3 functions still in a single connected component because of a -> b ->
1646 // c -> a.
1647 RC.switchInternalEdgeToRef(B, A);
1648 EXPECT_EQ(1, RC.size());
1649 EXPECT_EQ(&CallC, CG.lookupSCC(A));
1650 EXPECT_EQ(&CallC, CG.lookupSCC(B));
1651 EXPECT_EQ(&CallC, CG.lookupSCC(C));
Chandler Carruth9302fbf2014-04-23 11:03:03 +00001652
1653 // Remove the edge from c -> a, which should leave 'a' in the original SCC
1654 // and form a new SCC for 'b' and 'c'.
Chandler Carruthe5944d92016-02-17 00:18:16 +00001655 RC.switchInternalEdgeToRef(C, A);
1656 EXPECT_EQ(2, RC.size());
1657 EXPECT_EQ(&CallC, CG.lookupSCC(A));
1658 LazyCallGraph::SCC &BCallC = *CG.lookupSCC(B);
1659 EXPECT_NE(&BCallC, &CallC);
1660 EXPECT_EQ(&BCallC, CG.lookupSCC(C));
1661 auto J = RC.find(CallC);
1662 EXPECT_EQ(&CallC, &*J);
1663 --J;
1664 EXPECT_EQ(&BCallC, &*J);
1665 EXPECT_EQ(RC.begin(), J);
1666
1667 // Remove the edge from c -> b, which should leave 'b' in the original SCC
1668 // and form a new SCC for 'c'. It shouldn't change 'a's SCC.
1669 RC.switchInternalEdgeToRef(C, B);
1670 EXPECT_EQ(3, RC.size());
1671 EXPECT_EQ(&CallC, CG.lookupSCC(A));
1672 EXPECT_EQ(&BCallC, CG.lookupSCC(B));
1673 LazyCallGraph::SCC &CCallC = *CG.lookupSCC(C);
1674 EXPECT_NE(&CCallC, &CallC);
1675 EXPECT_NE(&CCallC, &BCallC);
1676 J = RC.find(CallC);
1677 EXPECT_EQ(&CallC, &*J);
1678 --J;
1679 EXPECT_EQ(&BCallC, &*J);
1680 --J;
1681 EXPECT_EQ(&CCallC, &*J);
1682 EXPECT_EQ(RC.begin(), J);
1683}
1684
1685TEST(LazyCallGraphTest, InternalRefEdgeToCall) {
Mehdi Amini03b42e42016-04-14 21:59:01 +00001686 LLVMContext Context;
Chandler Carruthe5944d92016-02-17 00:18:16 +00001687 // Basic tests for making a ref edge a call. This hits the basics of the
1688 // process only.
Mehdi Amini03b42e42016-04-14 21:59:01 +00001689 std::unique_ptr<Module> M =
1690 parseAssembly(Context, "define void @a() {\n"
1691 "entry:\n"
1692 " call void @b()\n"
1693 " call void @c()\n"
1694 " store void()* @d, void()** undef\n"
1695 " ret void\n"
1696 "}\n"
1697 "define void @b() {\n"
1698 "entry:\n"
1699 " store void()* @c, void()** undef\n"
1700 " call void @d()\n"
1701 " ret void\n"
1702 "}\n"
1703 "define void @c() {\n"
1704 "entry:\n"
1705 " store void()* @b, void()** undef\n"
1706 " call void @d()\n"
1707 " ret void\n"
1708 "}\n"
1709 "define void @d() {\n"
1710 "entry:\n"
1711 " store void()* @a, void()** undef\n"
1712 " ret void\n"
1713 "}\n");
Chandler Carruthe5944d92016-02-17 00:18:16 +00001714 LazyCallGraph CG(*M);
1715
1716 // Force the graph to be fully expanded.
1717 auto I = CG.postorder_ref_scc_begin();
1718 LazyCallGraph::RefSCC &RC = *I++;
1719 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1720
1721 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1722 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1723 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1724 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
1725 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
1726 LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
1727 LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
1728 LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
1729
1730 // Check the initial post-order. Note that B and C could be flipped here (and
1731 // in our mutation) without changing the nature of this test.
1732 ASSERT_EQ(4, RC.size());
1733 EXPECT_EQ(&DC, &RC[0]);
1734 EXPECT_EQ(&BC, &RC[1]);
1735 EXPECT_EQ(&CC, &RC[2]);
1736 EXPECT_EQ(&AC, &RC[3]);
1737
1738 // Switch the ref edge from A -> D to a call edge. This should have no
1739 // effect as it is already in postorder and no new cycles are formed.
1740 auto MergedCs = RC.switchInternalEdgeToCall(A, D);
1741 EXPECT_EQ(0u, MergedCs.size());
1742 ASSERT_EQ(4, RC.size());
1743 EXPECT_EQ(&DC, &RC[0]);
1744 EXPECT_EQ(&BC, &RC[1]);
1745 EXPECT_EQ(&CC, &RC[2]);
1746 EXPECT_EQ(&AC, &RC[3]);
1747
1748 // Switch B -> C to a call edge. This doesn't form any new cycles but does
1749 // require reordering the SCCs.
1750 MergedCs = RC.switchInternalEdgeToCall(B, C);
1751 EXPECT_EQ(0u, MergedCs.size());
1752 ASSERT_EQ(4, RC.size());
1753 EXPECT_EQ(&DC, &RC[0]);
1754 EXPECT_EQ(&CC, &RC[1]);
1755 EXPECT_EQ(&BC, &RC[2]);
1756 EXPECT_EQ(&AC, &RC[3]);
1757
1758 // Switch C -> B to a call edge. This forms a cycle and forces merging SCCs.
1759 MergedCs = RC.switchInternalEdgeToCall(C, B);
1760 ASSERT_EQ(1u, MergedCs.size());
1761 EXPECT_EQ(&CC, MergedCs[0]);
1762 ASSERT_EQ(3, RC.size());
1763 EXPECT_EQ(&DC, &RC[0]);
1764 EXPECT_EQ(&BC, &RC[1]);
1765 EXPECT_EQ(&AC, &RC[2]);
1766 EXPECT_EQ(2, BC.size());
1767 EXPECT_EQ(&BC, CG.lookupSCC(B));
1768 EXPECT_EQ(&BC, CG.lookupSCC(C));
1769}
1770
1771TEST(LazyCallGraphTest, InternalRefEdgeToCallNoCycleInterleaved) {
Mehdi Amini03b42e42016-04-14 21:59:01 +00001772 LLVMContext Context;
Chandler Carruthe5944d92016-02-17 00:18:16 +00001773 // Test for having a post-order prior to changing a ref edge to a call edge
1774 // with SCCs connecting to the source and connecting to the target, but not
1775 // connecting to both, interleaved between the source and target. This
1776 // ensures we correctly partition the range rather than simply moving one or
1777 // the other.
Mehdi Amini03b42e42016-04-14 21:59:01 +00001778 std::unique_ptr<Module> M =
1779 parseAssembly(Context, "define void @a() {\n"
1780 "entry:\n"
1781 " call void @b1()\n"
1782 " call void @c1()\n"
1783 " ret void\n"
1784 "}\n"
1785 "define void @b1() {\n"
1786 "entry:\n"
1787 " call void @c1()\n"
1788 " call void @b2()\n"
1789 " ret void\n"
1790 "}\n"
1791 "define void @c1() {\n"
1792 "entry:\n"
1793 " call void @b2()\n"
1794 " call void @c2()\n"
1795 " ret void\n"
1796 "}\n"
1797 "define void @b2() {\n"
1798 "entry:\n"
1799 " call void @c2()\n"
1800 " call void @b3()\n"
1801 " ret void\n"
1802 "}\n"
1803 "define void @c2() {\n"
1804 "entry:\n"
1805 " call void @b3()\n"
1806 " call void @c3()\n"
1807 " ret void\n"
1808 "}\n"
1809 "define void @b3() {\n"
1810 "entry:\n"
1811 " call void @c3()\n"
1812 " call void @d()\n"
1813 " ret void\n"
1814 "}\n"
1815 "define void @c3() {\n"
1816 "entry:\n"
1817 " store void()* @b1, void()** undef\n"
1818 " call void @d()\n"
1819 " ret void\n"
1820 "}\n"
1821 "define void @d() {\n"
1822 "entry:\n"
1823 " store void()* @a, void()** undef\n"
1824 " ret void\n"
1825 "}\n");
Chandler Carruthe5944d92016-02-17 00:18:16 +00001826 LazyCallGraph CG(*M);
1827
1828 // Force the graph to be fully expanded.
1829 auto I = CG.postorder_ref_scc_begin();
1830 LazyCallGraph::RefSCC &RC = *I++;
1831 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1832
1833 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1834 LazyCallGraph::Node &B1 = *CG.lookup(lookupFunction(*M, "b1"));
1835 LazyCallGraph::Node &B2 = *CG.lookup(lookupFunction(*M, "b2"));
1836 LazyCallGraph::Node &B3 = *CG.lookup(lookupFunction(*M, "b3"));
1837 LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
1838 LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
1839 LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
1840 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
1841 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
1842 LazyCallGraph::SCC &B1C = *CG.lookupSCC(B1);
1843 LazyCallGraph::SCC &B2C = *CG.lookupSCC(B2);
1844 LazyCallGraph::SCC &B3C = *CG.lookupSCC(B3);
1845 LazyCallGraph::SCC &C1C = *CG.lookupSCC(C1);
1846 LazyCallGraph::SCC &C2C = *CG.lookupSCC(C2);
1847 LazyCallGraph::SCC &C3C = *CG.lookupSCC(C3);
1848 LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
1849
1850 // Several call edges are initially present to force a particual post-order.
1851 // Remove them now, leaving an interleaved post-order pattern.
1852 RC.switchInternalEdgeToRef(B3, C3);
1853 RC.switchInternalEdgeToRef(C2, B3);
1854 RC.switchInternalEdgeToRef(B2, C2);
1855 RC.switchInternalEdgeToRef(C1, B2);
1856 RC.switchInternalEdgeToRef(B1, C1);
1857
1858 // Check the initial post-order. We ensure this order with the extra edges
1859 // that are nuked above.
1860 ASSERT_EQ(8, RC.size());
1861 EXPECT_EQ(&DC, &RC[0]);
1862 EXPECT_EQ(&C3C, &RC[1]);
1863 EXPECT_EQ(&B3C, &RC[2]);
1864 EXPECT_EQ(&C2C, &RC[3]);
1865 EXPECT_EQ(&B2C, &RC[4]);
1866 EXPECT_EQ(&C1C, &RC[5]);
1867 EXPECT_EQ(&B1C, &RC[6]);
1868 EXPECT_EQ(&AC, &RC[7]);
1869
1870 // Switch C3 -> B1 to a call edge. This doesn't form any new cycles but does
1871 // require reordering the SCCs in the face of tricky internal node
1872 // structures.
1873 auto MergedCs = RC.switchInternalEdgeToCall(C3, B1);
1874 EXPECT_EQ(0u, MergedCs.size());
1875 ASSERT_EQ(8, RC.size());
1876 EXPECT_EQ(&DC, &RC[0]);
1877 EXPECT_EQ(&B3C, &RC[1]);
1878 EXPECT_EQ(&B2C, &RC[2]);
1879 EXPECT_EQ(&B1C, &RC[3]);
1880 EXPECT_EQ(&C3C, &RC[4]);
1881 EXPECT_EQ(&C2C, &RC[5]);
1882 EXPECT_EQ(&C1C, &RC[6]);
1883 EXPECT_EQ(&AC, &RC[7]);
1884}
1885
1886TEST(LazyCallGraphTest, InternalRefEdgeToCallBothPartitionAndMerge) {
Mehdi Amini03b42e42016-04-14 21:59:01 +00001887 LLVMContext Context;
Chandler Carruthe5944d92016-02-17 00:18:16 +00001888 // Test for having a postorder where between the source and target are all
1889 // three kinds of other SCCs:
1890 // 1) One connected to the target only that have to be shifted below the
1891 // source.
1892 // 2) One connected to the source only that have to be shifted below the
1893 // target.
1894 // 3) One connected to both source and target that has to remain and get
1895 // merged away.
1896 //
1897 // To achieve this we construct a heavily connected graph to force
1898 // a particular post-order. Then we remove the forcing edges and connect
1899 // a cycle.
1900 //
1901 // Diagram for the graph we want on the left and the graph we use to force
1902 // the ordering on the right. Edges ponit down or right.
1903 //
1904 // A | A |
1905 // / \ | / \ |
1906 // B E | B \ |
1907 // |\ | | |\ | |
1908 // | D | | C-D-E |
1909 // | \| | | \| |
1910 // C F | \ F |
1911 // \ / | \ / |
1912 // G | G |
1913 //
1914 // And we form a cycle by connecting F to B.
Mehdi Amini03b42e42016-04-14 21:59:01 +00001915 std::unique_ptr<Module> M =
1916 parseAssembly(Context, "define void @a() {\n"
1917 "entry:\n"
1918 " call void @b()\n"
1919 " call void @e()\n"
1920 " ret void\n"
1921 "}\n"
1922 "define void @b() {\n"
1923 "entry:\n"
1924 " call void @c()\n"
1925 " call void @d()\n"
1926 " ret void\n"
1927 "}\n"
1928 "define void @c() {\n"
1929 "entry:\n"
1930 " call void @d()\n"
1931 " call void @g()\n"
1932 " ret void\n"
1933 "}\n"
1934 "define void @d() {\n"
1935 "entry:\n"
1936 " call void @e()\n"
1937 " call void @f()\n"
1938 " ret void\n"
1939 "}\n"
1940 "define void @e() {\n"
1941 "entry:\n"
1942 " call void @f()\n"
1943 " ret void\n"
1944 "}\n"
1945 "define void @f() {\n"
1946 "entry:\n"
1947 " store void()* @b, void()** undef\n"
1948 " call void @g()\n"
1949 " ret void\n"
1950 "}\n"
1951 "define void @g() {\n"
1952 "entry:\n"
1953 " store void()* @a, void()** undef\n"
1954 " ret void\n"
1955 "}\n");
Chandler Carruthe5944d92016-02-17 00:18:16 +00001956 LazyCallGraph CG(*M);
1957
1958 // Force the graph to be fully expanded.
1959 auto I = CG.postorder_ref_scc_begin();
1960 LazyCallGraph::RefSCC &RC = *I++;
1961 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
1962
1963 LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
1964 LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
1965 LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
1966 LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
1967 LazyCallGraph::Node &E = *CG.lookup(lookupFunction(*M, "e"));
1968 LazyCallGraph::Node &F = *CG.lookup(lookupFunction(*M, "f"));
1969 LazyCallGraph::Node &G = *CG.lookup(lookupFunction(*M, "g"));
1970 LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
1971 LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
1972 LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
1973 LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
1974 LazyCallGraph::SCC &EC = *CG.lookupSCC(E);
1975 LazyCallGraph::SCC &FC = *CG.lookupSCC(F);
1976 LazyCallGraph::SCC &GC = *CG.lookupSCC(G);
1977
1978 // Remove the extra edges that were used to force a particular post-order.
1979 RC.switchInternalEdgeToRef(C, D);
1980 RC.switchInternalEdgeToRef(D, E);
1981
1982 // Check the initial post-order. We ensure this order with the extra edges
1983 // that are nuked above.
1984 ASSERT_EQ(7, RC.size());
1985 EXPECT_EQ(&GC, &RC[0]);
1986 EXPECT_EQ(&FC, &RC[1]);
1987 EXPECT_EQ(&EC, &RC[2]);
1988 EXPECT_EQ(&DC, &RC[3]);
1989 EXPECT_EQ(&CC, &RC[4]);
1990 EXPECT_EQ(&BC, &RC[5]);
1991 EXPECT_EQ(&AC, &RC[6]);
1992
1993 // Switch F -> B to a call edge. This merges B, D, and F into a single SCC,
1994 // and has to place the C and E SCCs on either side of it:
1995 // A A |
1996 // / \ / \ |
1997 // B E | E |
1998 // |\ | \ / |
1999 // | D | -> B |
2000 // | \| / \ |
2001 // C F C | |
2002 // \ / \ / |
2003 // G G |
2004 auto MergedCs = RC.switchInternalEdgeToCall(F, B);
2005 ASSERT_EQ(2u, MergedCs.size());
2006 EXPECT_EQ(&FC, MergedCs[0]);
2007 EXPECT_EQ(&DC, MergedCs[1]);
2008 EXPECT_EQ(3, BC.size());
2009
2010 // And make sure the postorder was updated.
2011 ASSERT_EQ(5, RC.size());
2012 EXPECT_EQ(&GC, &RC[0]);
2013 EXPECT_EQ(&CC, &RC[1]);
2014 EXPECT_EQ(&BC, &RC[2]);
2015 EXPECT_EQ(&EC, &RC[3]);
2016 EXPECT_EQ(&AC, &RC[4]);
Chandler Carruth9302fbf2014-04-23 11:03:03 +00002017}
2018
Chandler Carruth16250452016-12-27 05:00:45 +00002019// Test for IR containing constants using blockaddress constant expressions.
2020// These are truly unique constructs: constant expressions with non-constant
2021// operands.
2022TEST(LazyCallGraphTest, HandleBlockAddress) {
2023 LLVMContext Context;
2024 std::unique_ptr<Module> M =
2025 parseAssembly(Context, "define void @f() {\n"
2026 "entry:\n"
2027 " ret void\n"
2028 "bb:\n"
2029 " unreachable\n"
2030 "}\n"
2031 "define void @g(i8** %ptr) {\n"
2032 "entry:\n"
2033 " store i8* blockaddress(@f, %bb), i8** %ptr\n"
2034 " ret void\n"
2035 "}\n");
2036 LazyCallGraph CG(*M);
2037
2038 auto I = CG.postorder_ref_scc_begin();
2039 LazyCallGraph::RefSCC &FRC = *I++;
2040 LazyCallGraph::RefSCC &GRC = *I++;
2041 EXPECT_EQ(CG.postorder_ref_scc_end(), I);
2042
2043 LazyCallGraph::Node &F = *CG.lookup(lookupFunction(*M, "f"));
2044 LazyCallGraph::Node &G = *CG.lookup(lookupFunction(*M, "g"));
2045 EXPECT_EQ(&FRC, CG.lookupRefSCC(F));
2046 EXPECT_EQ(&GRC, CG.lookupRefSCC(G));
2047 EXPECT_TRUE(GRC.isParentOf(FRC));
2048}
2049
Chandler Carruthc7bad9a2014-04-23 08:08:49 +00002050}