blob: 8d8c560d9e300b1b5a0b68ee30debe4a6afeec02 [file] [log] [blame]
Nick Lewycky0b682452013-07-27 01:24:00 +00001//===- CFGTest.cpp - CFG tests --------------------------------------------===//
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/CFG.h"
Nick Lewycky0b682452013-07-27 01:24:00 +000011#include "llvm/Analysis/LoopInfo.h"
Chandler Carruth9aca9182014-01-07 12:34:26 +000012#include "llvm/AsmParser/Parser.h"
Chandler Carruth5ad5f152014-01-13 09:26:24 +000013#include "llvm/IR/Dominators.h"
Nick Lewycky0b682452013-07-27 01:24:00 +000014#include "llvm/IR/Function.h"
Chandler Carruth83948572014-03-04 10:30:26 +000015#include "llvm/IR/InstIterator.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000016#include "llvm/IR/LLVMContext.h"
Nick Lewycky0b682452013-07-27 01:24:00 +000017#include "llvm/IR/Module.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000018#include "llvm/Pass.h"
19#include "llvm/PassManager.h"
Nick Lewycky0b682452013-07-27 01:24:00 +000020#include "llvm/Support/ErrorHandling.h"
Nick Lewycky0b682452013-07-27 01:24:00 +000021#include "llvm/Support/SourceMgr.h"
Nick Lewycky0b682452013-07-27 01:24:00 +000022#include "gtest/gtest.h"
23
24using namespace llvm;
25
26namespace {
27
28// This fixture assists in running the isPotentiallyReachable utility four ways
29// and ensuring it produces the correct answer each time.
30class IsPotentiallyReachableTest : public testing::Test {
31protected:
32 void ParseAssembly(const char *Assembly) {
33 M.reset(new Module("Module", getGlobalContext()));
34
35 SMDiagnostic Error;
36 bool Parsed = ParseAssemblyString(Assembly, M.get(),
37 Error, M->getContext()) == M.get();
38
39 std::string errMsg;
40 raw_string_ostream os(errMsg);
41 Error.print("", os);
42
43 if (!Parsed) {
44 // A failure here means that the test itself is buggy.
45 report_fatal_error(os.str().c_str());
46 }
47
48 Function *F = M->getFunction("test");
49 if (F == NULL)
50 report_fatal_error("Test must have a function named @test");
51
52 A = B = NULL;
53 for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
54 if (I->hasName()) {
55 if (I->getName() == "A")
56 A = &*I;
57 else if (I->getName() == "B")
58 B = &*I;
59 }
60 }
61 if (A == NULL)
62 report_fatal_error("@test must have an instruction %A");
63 if (B == NULL)
64 report_fatal_error("@test must have an instruction %B");
65 }
66
67 void ExpectPath(bool ExpectedResult) {
68 static char ID;
69 class IsPotentiallyReachableTestPass : public FunctionPass {
70 public:
71 IsPotentiallyReachableTestPass(bool ExpectedResult,
72 Instruction *A, Instruction *B)
73 : FunctionPass(ID), ExpectedResult(ExpectedResult), A(A), B(B) {}
74
75 static int initialize() {
76 PassInfo *PI = new PassInfo("isPotentiallyReachable testing pass",
77 "", &ID, 0, true, true);
78 PassRegistry::getPassRegistry()->registerPass(*PI, false);
79 initializeLoopInfoPass(*PassRegistry::getPassRegistry());
Chandler Carruth73523022014-01-13 13:07:17 +000080 initializeDominatorTreeWrapperPassPass(
81 *PassRegistry::getPassRegistry());
Nick Lewycky0b682452013-07-27 01:24:00 +000082 return 0;
83 }
84
85 void getAnalysisUsage(AnalysisUsage &AU) const {
86 AU.setPreservesAll();
87 AU.addRequired<LoopInfo>();
Chandler Carruth73523022014-01-13 13:07:17 +000088 AU.addRequired<DominatorTreeWrapperPass>();
Nick Lewycky0b682452013-07-27 01:24:00 +000089 }
90
91 bool runOnFunction(Function &F) {
92 if (!F.hasName() || F.getName() != "test")
93 return false;
94
95 LoopInfo *LI = &getAnalysis<LoopInfo>();
Chandler Carruth73523022014-01-13 13:07:17 +000096 DominatorTree *DT =
97 &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
Nick Lewycky0b682452013-07-27 01:24:00 +000098 EXPECT_EQ(isPotentiallyReachable(A, B, 0, 0), ExpectedResult);
99 EXPECT_EQ(isPotentiallyReachable(A, B, DT, 0), ExpectedResult);
100 EXPECT_EQ(isPotentiallyReachable(A, B, 0, LI), ExpectedResult);
101 EXPECT_EQ(isPotentiallyReachable(A, B, DT, LI), ExpectedResult);
102 return false;
103 }
104 bool ExpectedResult;
105 Instruction *A, *B;
106 };
107
108 static int initialize = IsPotentiallyReachableTestPass::initialize();
109 (void)initialize;
110
111 IsPotentiallyReachableTestPass *P =
112 new IsPotentiallyReachableTestPass(ExpectedResult, A, B);
113 PassManager PM;
114 PM.add(P);
115 PM.run(*M);
116 }
Benjamin Kramer3c29c072014-02-10 14:17:42 +0000117
Ahmed Charles56440fd2014-03-06 05:51:42 +0000118 std::unique_ptr<Module> M;
Nick Lewycky0b682452013-07-27 01:24:00 +0000119 Instruction *A, *B;
120};
121
122}
123
124TEST_F(IsPotentiallyReachableTest, SameBlockNoPath) {
125 ParseAssembly(
126 "define void @test() {\n"
127 "entry:\n"
128 " bitcast i8 undef to i8\n"
129 " %B = bitcast i8 undef to i8\n"
130 " bitcast i8 undef to i8\n"
131 " bitcast i8 undef to i8\n"
132 " %A = bitcast i8 undef to i8\n"
133 " ret void\n"
134 "}\n");
135 ExpectPath(false);
136}
137
138TEST_F(IsPotentiallyReachableTest, SameBlockPath) {
139 ParseAssembly(
140 "define void @test() {\n"
141 "entry:\n"
142 " %A = bitcast i8 undef to i8\n"
143 " bitcast i8 undef to i8\n"
144 " bitcast i8 undef to i8\n"
145 " %B = bitcast i8 undef to i8\n"
146 " ret void\n"
147 "}\n");
148 ExpectPath(true);
149}
150
Nick Lewycky8d2e86d2013-08-13 00:03:47 +0000151TEST_F(IsPotentiallyReachableTest, SameBlockNoLoop) {
152 ParseAssembly(
153 "define void @test() {\n"
154 "entry:\n"
155 " br label %middle\n"
156 "middle:\n"
157 " %B = bitcast i8 undef to i8\n"
158 " bitcast i8 undef to i8\n"
159 " bitcast i8 undef to i8\n"
160 " %A = bitcast i8 undef to i8\n"
161 " br label %nextblock\n"
162 "nextblock:\n"
163 " ret void\n"
164 "}\n");
165 ExpectPath(false);
166}
167
Nick Lewycky0b682452013-07-27 01:24:00 +0000168TEST_F(IsPotentiallyReachableTest, StraightNoPath) {
169 ParseAssembly(
170 "define void @test() {\n"
171 "entry:\n"
172 " %B = bitcast i8 undef to i8\n"
173 " br label %exit\n"
174 "exit:\n"
175 " %A = bitcast i8 undef to i8\n"
176 " ret void\n"
177 "}");
178 ExpectPath(false);
179}
180
181TEST_F(IsPotentiallyReachableTest, StraightPath) {
182 ParseAssembly(
183 "define void @test() {\n"
184 "entry:\n"
185 " %A = bitcast i8 undef to i8\n"
186 " br label %exit\n"
187 "exit:\n"
188 " %B = bitcast i8 undef to i8\n"
189 " ret void\n"
190 "}");
191 ExpectPath(true);
192}
193
194TEST_F(IsPotentiallyReachableTest, DestUnreachable) {
195 ParseAssembly(
196 "define void @test() {\n"
197 "entry:\n"
198 " br label %midblock\n"
199 "midblock:\n"
200 " %A = bitcast i8 undef to i8\n"
201 " ret void\n"
202 "unreachable:\n"
203 " %B = bitcast i8 undef to i8\n"
204 " br label %midblock\n"
205 "}");
206 ExpectPath(false);
207}
208
209TEST_F(IsPotentiallyReachableTest, BranchToReturn) {
210 ParseAssembly(
211 "define void @test(i1 %x) {\n"
212 "entry:\n"
213 " %A = bitcast i8 undef to i8\n"
214 " br i1 %x, label %block1, label %block2\n"
215 "block1:\n"
216 " ret void\n"
217 "block2:\n"
218 " %B = bitcast i8 undef to i8\n"
219 " ret void\n"
220 "}");
221 ExpectPath(true);
222}
223
224TEST_F(IsPotentiallyReachableTest, SimpleLoop1) {
225 ParseAssembly(
226 "declare i1 @switch()\n"
227 "\n"
228 "define void @test() {\n"
229 "entry:\n"
230 " br label %loop\n"
231 "loop:\n"
232 " %B = bitcast i8 undef to i8\n"
233 " %A = bitcast i8 undef to i8\n"
234 " %x = call i1 @switch()\n"
235 " br i1 %x, label %loop, label %exit\n"
236 "exit:\n"
237 " ret void\n"
238 "}");
239 ExpectPath(true);
240}
241
242TEST_F(IsPotentiallyReachableTest, SimpleLoop2) {
243 ParseAssembly(
244 "declare i1 @switch()\n"
245 "\n"
246 "define void @test() {\n"
247 "entry:\n"
248 " %B = bitcast i8 undef to i8\n"
249 " br label %loop\n"
250 "loop:\n"
251 " %A = bitcast i8 undef to i8\n"
252 " %x = call i1 @switch()\n"
253 " br i1 %x, label %loop, label %exit\n"
254 "exit:\n"
255 " ret void\n"
256 "}");
257 ExpectPath(false);
258}
259
260TEST_F(IsPotentiallyReachableTest, SimpleLoop3) {
261 ParseAssembly(
262 "declare i1 @switch()\n"
263 "\n"
264 "define void @test() {\n"
265 "entry:\n"
266 " br label %loop\n"
267 "loop:\n"
268 " %B = bitcast i8 undef to i8\n"
269 " %x = call i1 @switch()\n"
270 " br i1 %x, label %loop, label %exit\n"
271 "exit:\n"
272 " %A = bitcast i8 undef to i8\n"
273 " ret void\n"
274 "}");
275 ExpectPath(false);
276}
277
278
279TEST_F(IsPotentiallyReachableTest, OneLoopAfterTheOther1) {
280 ParseAssembly(
281 "declare i1 @switch()\n"
282 "\n"
283 "define void @test() {\n"
284 "entry:\n"
285 " br label %loop1\n"
286 "loop1:\n"
287 " %A = bitcast i8 undef to i8\n"
288 " %x = call i1 @switch()\n"
289 " br i1 %x, label %loop1, label %loop1exit\n"
290 "loop1exit:\n"
291 " br label %loop2\n"
292 "loop2:\n"
293 " %B = bitcast i8 undef to i8\n"
294 " %y = call i1 @switch()\n"
295 " br i1 %x, label %loop2, label %loop2exit\n"
296 "loop2exit:"
297 " ret void\n"
298 "}");
299 ExpectPath(true);
300}
301
302TEST_F(IsPotentiallyReachableTest, OneLoopAfterTheOther2) {
303 ParseAssembly(
304 "declare i1 @switch()\n"
305 "\n"
306 "define void @test() {\n"
307 "entry:\n"
308 " br label %loop1\n"
309 "loop1:\n"
310 " %B = bitcast i8 undef to i8\n"
311 " %x = call i1 @switch()\n"
312 " br i1 %x, label %loop1, label %loop1exit\n"
313 "loop1exit:\n"
314 " br label %loop2\n"
315 "loop2:\n"
316 " %A = bitcast i8 undef to i8\n"
317 " %y = call i1 @switch()\n"
318 " br i1 %x, label %loop2, label %loop2exit\n"
319 "loop2exit:"
320 " ret void\n"
321 "}");
322 ExpectPath(false);
323}
324
325TEST_F(IsPotentiallyReachableTest, OneLoopAfterTheOtherInsideAThirdLoop) {
326 ParseAssembly(
327 "declare i1 @switch()\n"
328 "\n"
329 "define void @test() {\n"
330 "entry:\n"
331 " br label %outerloop3\n"
332 "outerloop3:\n"
333 " br label %innerloop1\n"
334 "innerloop1:\n"
335 " %B = bitcast i8 undef to i8\n"
336 " %x = call i1 @switch()\n"
337 " br i1 %x, label %innerloop1, label %innerloop1exit\n"
338 "innerloop1exit:\n"
339 " br label %innerloop2\n"
340 "innerloop2:\n"
341 " %A = bitcast i8 undef to i8\n"
342 " %y = call i1 @switch()\n"
343 " br i1 %x, label %innerloop2, label %innerloop2exit\n"
344 "innerloop2exit:"
345 " ;; In outer loop3 now.\n"
346 " %z = call i1 @switch()\n"
347 " br i1 %z, label %outerloop3, label %exit\n"
348 "exit:\n"
349 " ret void\n"
350 "}");
351 ExpectPath(true);
352}
353
Benjamin Kramer3c29c072014-02-10 14:17:42 +0000354static const char *BranchInsideLoopIR =
355 "declare i1 @switch()\n"
356 "\n"
357 "define void @test() {\n"
358 "entry:\n"
359 " br label %loop\n"
360 "loop:\n"
361 " %x = call i1 @switch()\n"
362 " br i1 %x, label %nextloopblock, label %exit\n"
363 "nextloopblock:\n"
364 " %y = call i1 @switch()\n"
365 " br i1 %y, label %left, label %right\n"
366 "left:\n"
367 " %A = bitcast i8 undef to i8\n"
368 " br label %loop\n"
369 "right:\n"
370 " %B = bitcast i8 undef to i8\n"
371 " br label %loop\n"
372 "exit:\n"
373 " ret void\n"
374 "}";
375
Nick Lewycky0b682452013-07-27 01:24:00 +0000376TEST_F(IsPotentiallyReachableTest, BranchInsideLoop) {
Benjamin Kramer3c29c072014-02-10 14:17:42 +0000377 ParseAssembly(BranchInsideLoopIR);
378 ExpectPath(true);
379}
380
381TEST_F(IsPotentiallyReachableTest, ModifyTest) {
382 ParseAssembly(BranchInsideLoopIR);
383
384 succ_iterator S = succ_begin(++M->getFunction("test")->begin());
385 BasicBlock *OldBB = S[0];
386 S[0] = S[1];
387 ExpectPath(false);
388 S[0] = OldBB;
Nick Lewycky0b682452013-07-27 01:24:00 +0000389 ExpectPath(true);
390}