blob: d7f14c3e1c35e7ac1fcdc57ee36b470193628a35 [file] [log] [blame]
Nick Lewycky81e48042013-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 Lewycky81e48042013-07-27 01:24:00 +000011#include "llvm/Analysis/LoopInfo.h"
Chandler Carruthbc65a8d2014-01-07 12:34:26 +000012#include "llvm/AsmParser/Parser.h"
Chandler Carruth56e13942014-01-13 09:26:24 +000013#include "llvm/IR/Dominators.h"
Nick Lewycky81e48042013-07-27 01:24:00 +000014#include "llvm/IR/Function.h"
Chandler Carruth876ac602014-03-04 10:30:26 +000015#include "llvm/IR/InstIterator.h"
Chandler Carruth974a4452014-01-07 11:48:04 +000016#include "llvm/IR/LLVMContext.h"
Chandler Carruth3c0d6072017-06-06 11:06:56 +000017#include "llvm/IR/LegacyPassManager.h"
Nick Lewycky81e48042013-07-27 01:24:00 +000018#include "llvm/IR/Module.h"
Chandler Carruth974a4452014-01-07 11:48:04 +000019#include "llvm/Pass.h"
Nick Lewycky81e48042013-07-27 01:24:00 +000020#include "llvm/Support/ErrorHandling.h"
Nick Lewycky81e48042013-07-27 01:24:00 +000021#include "llvm/Support/SourceMgr.h"
Nick Lewycky81e48042013-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) {
Nick Lewycky81e48042013-07-27 01:24:00 +000033 SMDiagnostic Error;
Mehdi Amini8be77072016-04-14 21:59:01 +000034 M = parseAssemblyString(Assembly, Error, Context);
Nick Lewycky81e48042013-07-27 01:24:00 +000035
36 std::string errMsg;
37 raw_string_ostream os(errMsg);
38 Error.print("", os);
39
Rafael Espindola9b29ff92014-08-19 16:58:54 +000040 // A failure here means that the test itself is buggy.
41 if (!M)
Nick Lewycky81e48042013-07-27 01:24:00 +000042 report_fatal_error(os.str().c_str());
Nick Lewycky81e48042013-07-27 01:24:00 +000043
44 Function *F = M->getFunction("test");
Craig Topperb1770412014-06-08 22:29:17 +000045 if (F == nullptr)
Nick Lewycky81e48042013-07-27 01:24:00 +000046 report_fatal_error("Test must have a function named @test");
47
Craig Topperb1770412014-06-08 22:29:17 +000048 A = B = nullptr;
Nick Lewycky81e48042013-07-27 01:24:00 +000049 for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
50 if (I->hasName()) {
51 if (I->getName() == "A")
52 A = &*I;
53 else if (I->getName() == "B")
54 B = &*I;
55 }
56 }
Craig Topperb1770412014-06-08 22:29:17 +000057 if (A == nullptr)
Nick Lewycky81e48042013-07-27 01:24:00 +000058 report_fatal_error("@test must have an instruction %A");
Craig Topperb1770412014-06-08 22:29:17 +000059 if (B == nullptr)
Nick Lewycky81e48042013-07-27 01:24:00 +000060 report_fatal_error("@test must have an instruction %B");
61 }
62
63 void ExpectPath(bool ExpectedResult) {
64 static char ID;
65 class IsPotentiallyReachableTestPass : public FunctionPass {
66 public:
67 IsPotentiallyReachableTestPass(bool ExpectedResult,
68 Instruction *A, Instruction *B)
69 : FunctionPass(ID), ExpectedResult(ExpectedResult), A(A), B(B) {}
70
71 static int initialize() {
72 PassInfo *PI = new PassInfo("isPotentiallyReachable testing pass",
Craig Topperb1770412014-06-08 22:29:17 +000073 "", &ID, nullptr, true, true);
Nick Lewycky81e48042013-07-27 01:24:00 +000074 PassRegistry::getPassRegistry()->registerPass(*PI, false);
Chandler Carruthde5df292015-01-17 14:16:18 +000075 initializeLoopInfoWrapperPassPass(*PassRegistry::getPassRegistry());
Chandler Carruth7f2eff72014-01-13 13:07:17 +000076 initializeDominatorTreeWrapperPassPass(
77 *PassRegistry::getPassRegistry());
Nick Lewycky81e48042013-07-27 01:24:00 +000078 return 0;
79 }
80
Alexander Kornienkoc16fc542015-04-11 02:11:45 +000081 void getAnalysisUsage(AnalysisUsage &AU) const override {
Nick Lewycky81e48042013-07-27 01:24:00 +000082 AU.setPreservesAll();
Chandler Carruthde5df292015-01-17 14:16:18 +000083 AU.addRequired<LoopInfoWrapperPass>();
Chandler Carruth7f2eff72014-01-13 13:07:17 +000084 AU.addRequired<DominatorTreeWrapperPass>();
Nick Lewycky81e48042013-07-27 01:24:00 +000085 }
86
Alexander Kornienkoc16fc542015-04-11 02:11:45 +000087 bool runOnFunction(Function &F) override {
Nick Lewycky81e48042013-07-27 01:24:00 +000088 if (!F.hasName() || F.getName() != "test")
89 return false;
90
Chandler Carruthde5df292015-01-17 14:16:18 +000091 LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
Chandler Carruth7f2eff72014-01-13 13:07:17 +000092 DominatorTree *DT =
93 &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
Craig Topperb1770412014-06-08 22:29:17 +000094 EXPECT_EQ(isPotentiallyReachable(A, B, nullptr, nullptr),
95 ExpectedResult);
96 EXPECT_EQ(isPotentiallyReachable(A, B, DT, nullptr), ExpectedResult);
97 EXPECT_EQ(isPotentiallyReachable(A, B, nullptr, LI), ExpectedResult);
Nick Lewycky81e48042013-07-27 01:24:00 +000098 EXPECT_EQ(isPotentiallyReachable(A, B, DT, LI), ExpectedResult);
99 return false;
100 }
101 bool ExpectedResult;
102 Instruction *A, *B;
103 };
104
105 static int initialize = IsPotentiallyReachableTestPass::initialize();
106 (void)initialize;
107
108 IsPotentiallyReachableTestPass *P =
109 new IsPotentiallyReachableTestPass(ExpectedResult, A, B);
Chandler Carruth417c5c12015-02-13 10:01:29 +0000110 legacy::PassManager PM;
Nick Lewycky81e48042013-07-27 01:24:00 +0000111 PM.add(P);
112 PM.run(*M);
113 }
Benjamin Kramer299918a2014-02-10 14:17:42 +0000114
Mehdi Amini8be77072016-04-14 21:59:01 +0000115 LLVMContext Context;
Ahmed Charlesf4ccd112014-03-06 05:51:42 +0000116 std::unique_ptr<Module> M;
Nick Lewycky81e48042013-07-27 01:24:00 +0000117 Instruction *A, *B;
118};
119
120}
121
122TEST_F(IsPotentiallyReachableTest, SameBlockNoPath) {
123 ParseAssembly(
124 "define void @test() {\n"
125 "entry:\n"
126 " bitcast i8 undef to i8\n"
127 " %B = bitcast i8 undef to i8\n"
128 " bitcast i8 undef to i8\n"
129 " bitcast i8 undef to i8\n"
130 " %A = bitcast i8 undef to i8\n"
131 " ret void\n"
132 "}\n");
133 ExpectPath(false);
134}
135
136TEST_F(IsPotentiallyReachableTest, SameBlockPath) {
137 ParseAssembly(
138 "define void @test() {\n"
139 "entry:\n"
140 " %A = bitcast i8 undef to i8\n"
141 " bitcast i8 undef to i8\n"
142 " bitcast i8 undef to i8\n"
143 " %B = bitcast i8 undef to i8\n"
144 " ret void\n"
145 "}\n");
146 ExpectPath(true);
147}
148
Nick Lewycky72dba2542013-08-13 00:03:47 +0000149TEST_F(IsPotentiallyReachableTest, SameBlockNoLoop) {
150 ParseAssembly(
151 "define void @test() {\n"
152 "entry:\n"
153 " br label %middle\n"
154 "middle:\n"
155 " %B = bitcast i8 undef to i8\n"
156 " bitcast i8 undef to i8\n"
157 " bitcast i8 undef to i8\n"
158 " %A = bitcast i8 undef to i8\n"
159 " br label %nextblock\n"
160 "nextblock:\n"
161 " ret void\n"
162 "}\n");
163 ExpectPath(false);
164}
165
Nick Lewycky81e48042013-07-27 01:24:00 +0000166TEST_F(IsPotentiallyReachableTest, StraightNoPath) {
167 ParseAssembly(
168 "define void @test() {\n"
169 "entry:\n"
170 " %B = bitcast i8 undef to i8\n"
171 " br label %exit\n"
172 "exit:\n"
173 " %A = bitcast i8 undef to i8\n"
174 " ret void\n"
175 "}");
176 ExpectPath(false);
177}
178
179TEST_F(IsPotentiallyReachableTest, StraightPath) {
180 ParseAssembly(
181 "define void @test() {\n"
182 "entry:\n"
183 " %A = bitcast i8 undef to i8\n"
184 " br label %exit\n"
185 "exit:\n"
186 " %B = bitcast i8 undef to i8\n"
187 " ret void\n"
188 "}");
189 ExpectPath(true);
190}
191
192TEST_F(IsPotentiallyReachableTest, DestUnreachable) {
193 ParseAssembly(
194 "define void @test() {\n"
195 "entry:\n"
196 " br label %midblock\n"
197 "midblock:\n"
198 " %A = bitcast i8 undef to i8\n"
199 " ret void\n"
200 "unreachable:\n"
201 " %B = bitcast i8 undef to i8\n"
202 " br label %midblock\n"
203 "}");
204 ExpectPath(false);
205}
206
207TEST_F(IsPotentiallyReachableTest, BranchToReturn) {
208 ParseAssembly(
209 "define void @test(i1 %x) {\n"
210 "entry:\n"
211 " %A = bitcast i8 undef to i8\n"
212 " br i1 %x, label %block1, label %block2\n"
213 "block1:\n"
214 " ret void\n"
215 "block2:\n"
216 " %B = bitcast i8 undef to i8\n"
217 " ret void\n"
218 "}");
219 ExpectPath(true);
220}
221
222TEST_F(IsPotentiallyReachableTest, SimpleLoop1) {
223 ParseAssembly(
224 "declare i1 @switch()\n"
225 "\n"
226 "define void @test() {\n"
227 "entry:\n"
228 " br label %loop\n"
229 "loop:\n"
230 " %B = bitcast i8 undef to i8\n"
231 " %A = bitcast i8 undef to i8\n"
232 " %x = call i1 @switch()\n"
233 " br i1 %x, label %loop, label %exit\n"
234 "exit:\n"
235 " ret void\n"
236 "}");
237 ExpectPath(true);
238}
239
240TEST_F(IsPotentiallyReachableTest, SimpleLoop2) {
241 ParseAssembly(
242 "declare i1 @switch()\n"
243 "\n"
244 "define void @test() {\n"
245 "entry:\n"
246 " %B = bitcast i8 undef to i8\n"
247 " br label %loop\n"
248 "loop:\n"
249 " %A = bitcast i8 undef to i8\n"
250 " %x = call i1 @switch()\n"
251 " br i1 %x, label %loop, label %exit\n"
252 "exit:\n"
253 " ret void\n"
254 "}");
255 ExpectPath(false);
256}
257
258TEST_F(IsPotentiallyReachableTest, SimpleLoop3) {
259 ParseAssembly(
260 "declare i1 @switch()\n"
261 "\n"
262 "define void @test() {\n"
263 "entry:\n"
264 " br label %loop\n"
265 "loop:\n"
266 " %B = bitcast i8 undef to i8\n"
267 " %x = call i1 @switch()\n"
268 " br i1 %x, label %loop, label %exit\n"
269 "exit:\n"
270 " %A = bitcast i8 undef to i8\n"
271 " ret void\n"
272 "}");
273 ExpectPath(false);
274}
275
276
277TEST_F(IsPotentiallyReachableTest, OneLoopAfterTheOther1) {
278 ParseAssembly(
279 "declare i1 @switch()\n"
280 "\n"
281 "define void @test() {\n"
282 "entry:\n"
283 " br label %loop1\n"
284 "loop1:\n"
285 " %A = bitcast i8 undef to i8\n"
286 " %x = call i1 @switch()\n"
287 " br i1 %x, label %loop1, label %loop1exit\n"
288 "loop1exit:\n"
289 " br label %loop2\n"
290 "loop2:\n"
291 " %B = bitcast i8 undef to i8\n"
292 " %y = call i1 @switch()\n"
293 " br i1 %x, label %loop2, label %loop2exit\n"
294 "loop2exit:"
295 " ret void\n"
296 "}");
297 ExpectPath(true);
298}
299
300TEST_F(IsPotentiallyReachableTest, OneLoopAfterTheOther2) {
301 ParseAssembly(
302 "declare i1 @switch()\n"
303 "\n"
304 "define void @test() {\n"
305 "entry:\n"
306 " br label %loop1\n"
307 "loop1:\n"
308 " %B = bitcast i8 undef to i8\n"
309 " %x = call i1 @switch()\n"
310 " br i1 %x, label %loop1, label %loop1exit\n"
311 "loop1exit:\n"
312 " br label %loop2\n"
313 "loop2:\n"
314 " %A = bitcast i8 undef to i8\n"
315 " %y = call i1 @switch()\n"
316 " br i1 %x, label %loop2, label %loop2exit\n"
317 "loop2exit:"
318 " ret void\n"
319 "}");
320 ExpectPath(false);
321}
322
323TEST_F(IsPotentiallyReachableTest, OneLoopAfterTheOtherInsideAThirdLoop) {
324 ParseAssembly(
325 "declare i1 @switch()\n"
326 "\n"
327 "define void @test() {\n"
328 "entry:\n"
329 " br label %outerloop3\n"
330 "outerloop3:\n"
331 " br label %innerloop1\n"
332 "innerloop1:\n"
333 " %B = bitcast i8 undef to i8\n"
334 " %x = call i1 @switch()\n"
335 " br i1 %x, label %innerloop1, label %innerloop1exit\n"
336 "innerloop1exit:\n"
337 " br label %innerloop2\n"
338 "innerloop2:\n"
339 " %A = bitcast i8 undef to i8\n"
340 " %y = call i1 @switch()\n"
341 " br i1 %x, label %innerloop2, label %innerloop2exit\n"
342 "innerloop2exit:"
343 " ;; In outer loop3 now.\n"
344 " %z = call i1 @switch()\n"
345 " br i1 %z, label %outerloop3, label %exit\n"
346 "exit:\n"
347 " ret void\n"
348 "}");
349 ExpectPath(true);
350}
351
Benjamin Kramer299918a2014-02-10 14:17:42 +0000352static const char *BranchInsideLoopIR =
353 "declare i1 @switch()\n"
354 "\n"
355 "define void @test() {\n"
356 "entry:\n"
357 " br label %loop\n"
358 "loop:\n"
359 " %x = call i1 @switch()\n"
360 " br i1 %x, label %nextloopblock, label %exit\n"
361 "nextloopblock:\n"
362 " %y = call i1 @switch()\n"
363 " br i1 %y, label %left, label %right\n"
364 "left:\n"
365 " %A = bitcast i8 undef to i8\n"
366 " br label %loop\n"
367 "right:\n"
368 " %B = bitcast i8 undef to i8\n"
369 " br label %loop\n"
370 "exit:\n"
371 " ret void\n"
372 "}";
373
Nick Lewycky81e48042013-07-27 01:24:00 +0000374TEST_F(IsPotentiallyReachableTest, BranchInsideLoop) {
Benjamin Kramer299918a2014-02-10 14:17:42 +0000375 ParseAssembly(BranchInsideLoopIR);
376 ExpectPath(true);
377}
378
379TEST_F(IsPotentiallyReachableTest, ModifyTest) {
380 ParseAssembly(BranchInsideLoopIR);
381
Duncan P. N. Exon Smith70f8c202015-10-20 18:30:20 +0000382 succ_iterator S = succ_begin(&*++M->getFunction("test")->begin());
Benjamin Kramer299918a2014-02-10 14:17:42 +0000383 BasicBlock *OldBB = S[0];
384 S[0] = S[1];
385 ExpectPath(false);
386 S[0] = OldBB;
Nick Lewycky81e48042013-07-27 01:24:00 +0000387 ExpectPath(true);
388}