blob: b29c168ce08b3bee15b07579e999e3ca83ec321c [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"
Chandler Carruth30d69c22015-02-13 10:01:29 +000019#include "llvm/IR/LegacyPassManager.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) {
Nick Lewycky0b682452013-07-27 01:24:00 +000033 SMDiagnostic Error;
Rafael Espindola11c07d72014-08-19 16:58:54 +000034 M = parseAssemblyString(Assembly, Error, getGlobalContext());
Nick Lewycky0b682452013-07-27 01:24:00 +000035
36 std::string errMsg;
37 raw_string_ostream os(errMsg);
38 Error.print("", os);
39
Rafael Espindola11c07d72014-08-19 16:58:54 +000040 // A failure here means that the test itself is buggy.
41 if (!M)
Nick Lewycky0b682452013-07-27 01:24:00 +000042 report_fatal_error(os.str().c_str());
Nick Lewycky0b682452013-07-27 01:24:00 +000043
44 Function *F = M->getFunction("test");
Craig Topper66f09ad2014-06-08 22:29:17 +000045 if (F == nullptr)
Nick Lewycky0b682452013-07-27 01:24:00 +000046 report_fatal_error("Test must have a function named @test");
47
Craig Topper66f09ad2014-06-08 22:29:17 +000048 A = B = nullptr;
Nick Lewycky0b682452013-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 Topper66f09ad2014-06-08 22:29:17 +000057 if (A == nullptr)
Nick Lewycky0b682452013-07-27 01:24:00 +000058 report_fatal_error("@test must have an instruction %A");
Craig Topper66f09ad2014-06-08 22:29:17 +000059 if (B == nullptr)
Nick Lewycky0b682452013-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 Topper66f09ad2014-06-08 22:29:17 +000073 "", &ID, nullptr, true, true);
Nick Lewycky0b682452013-07-27 01:24:00 +000074 PassRegistry::getPassRegistry()->registerPass(*PI, false);
Chandler Carruth4f8f3072015-01-17 14:16:18 +000075 initializeLoopInfoWrapperPassPass(*PassRegistry::getPassRegistry());
Chandler Carruth73523022014-01-13 13:07:17 +000076 initializeDominatorTreeWrapperPassPass(
77 *PassRegistry::getPassRegistry());
Nick Lewycky0b682452013-07-27 01:24:00 +000078 return 0;
79 }
80
Alexander Kornienkof817c1c2015-04-11 02:11:45 +000081 void getAnalysisUsage(AnalysisUsage &AU) const override {
Nick Lewycky0b682452013-07-27 01:24:00 +000082 AU.setPreservesAll();
Chandler Carruth4f8f3072015-01-17 14:16:18 +000083 AU.addRequired<LoopInfoWrapperPass>();
Chandler Carruth73523022014-01-13 13:07:17 +000084 AU.addRequired<DominatorTreeWrapperPass>();
Nick Lewycky0b682452013-07-27 01:24:00 +000085 }
86
Alexander Kornienkof817c1c2015-04-11 02:11:45 +000087 bool runOnFunction(Function &F) override {
Nick Lewycky0b682452013-07-27 01:24:00 +000088 if (!F.hasName() || F.getName() != "test")
89 return false;
90
Chandler Carruth4f8f3072015-01-17 14:16:18 +000091 LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
Chandler Carruth73523022014-01-13 13:07:17 +000092 DominatorTree *DT =
93 &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
Craig Topper66f09ad2014-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 Lewycky0b682452013-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 Carruth30d69c22015-02-13 10:01:29 +0000110 legacy::PassManager PM;
Nick Lewycky0b682452013-07-27 01:24:00 +0000111 PM.add(P);
112 PM.run(*M);
113 }
Benjamin Kramer3c29c072014-02-10 14:17:42 +0000114
Ahmed Charles56440fd2014-03-06 05:51:42 +0000115 std::unique_ptr<Module> M;
Nick Lewycky0b682452013-07-27 01:24:00 +0000116 Instruction *A, *B;
117};
118
119}
120
121TEST_F(IsPotentiallyReachableTest, SameBlockNoPath) {
122 ParseAssembly(
123 "define void @test() {\n"
124 "entry:\n"
125 " bitcast i8 undef to i8\n"
126 " %B = bitcast i8 undef to i8\n"
127 " bitcast i8 undef to i8\n"
128 " bitcast i8 undef to i8\n"
129 " %A = bitcast i8 undef to i8\n"
130 " ret void\n"
131 "}\n");
132 ExpectPath(false);
133}
134
135TEST_F(IsPotentiallyReachableTest, SameBlockPath) {
136 ParseAssembly(
137 "define void @test() {\n"
138 "entry:\n"
139 " %A = bitcast i8 undef to i8\n"
140 " bitcast i8 undef to i8\n"
141 " bitcast i8 undef to i8\n"
142 " %B = bitcast i8 undef to i8\n"
143 " ret void\n"
144 "}\n");
145 ExpectPath(true);
146}
147
Nick Lewycky8d2e86d2013-08-13 00:03:47 +0000148TEST_F(IsPotentiallyReachableTest, SameBlockNoLoop) {
149 ParseAssembly(
150 "define void @test() {\n"
151 "entry:\n"
152 " br label %middle\n"
153 "middle:\n"
154 " %B = bitcast i8 undef to i8\n"
155 " bitcast i8 undef to i8\n"
156 " bitcast i8 undef to i8\n"
157 " %A = bitcast i8 undef to i8\n"
158 " br label %nextblock\n"
159 "nextblock:\n"
160 " ret void\n"
161 "}\n");
162 ExpectPath(false);
163}
164
Nick Lewycky0b682452013-07-27 01:24:00 +0000165TEST_F(IsPotentiallyReachableTest, StraightNoPath) {
166 ParseAssembly(
167 "define void @test() {\n"
168 "entry:\n"
169 " %B = bitcast i8 undef to i8\n"
170 " br label %exit\n"
171 "exit:\n"
172 " %A = bitcast i8 undef to i8\n"
173 " ret void\n"
174 "}");
175 ExpectPath(false);
176}
177
178TEST_F(IsPotentiallyReachableTest, StraightPath) {
179 ParseAssembly(
180 "define void @test() {\n"
181 "entry:\n"
182 " %A = bitcast i8 undef to i8\n"
183 " br label %exit\n"
184 "exit:\n"
185 " %B = bitcast i8 undef to i8\n"
186 " ret void\n"
187 "}");
188 ExpectPath(true);
189}
190
191TEST_F(IsPotentiallyReachableTest, DestUnreachable) {
192 ParseAssembly(
193 "define void @test() {\n"
194 "entry:\n"
195 " br label %midblock\n"
196 "midblock:\n"
197 " %A = bitcast i8 undef to i8\n"
198 " ret void\n"
199 "unreachable:\n"
200 " %B = bitcast i8 undef to i8\n"
201 " br label %midblock\n"
202 "}");
203 ExpectPath(false);
204}
205
206TEST_F(IsPotentiallyReachableTest, BranchToReturn) {
207 ParseAssembly(
208 "define void @test(i1 %x) {\n"
209 "entry:\n"
210 " %A = bitcast i8 undef to i8\n"
211 " br i1 %x, label %block1, label %block2\n"
212 "block1:\n"
213 " ret void\n"
214 "block2:\n"
215 " %B = bitcast i8 undef to i8\n"
216 " ret void\n"
217 "}");
218 ExpectPath(true);
219}
220
221TEST_F(IsPotentiallyReachableTest, SimpleLoop1) {
222 ParseAssembly(
223 "declare i1 @switch()\n"
224 "\n"
225 "define void @test() {\n"
226 "entry:\n"
227 " br label %loop\n"
228 "loop:\n"
229 " %B = bitcast i8 undef to i8\n"
230 " %A = bitcast i8 undef to i8\n"
231 " %x = call i1 @switch()\n"
232 " br i1 %x, label %loop, label %exit\n"
233 "exit:\n"
234 " ret void\n"
235 "}");
236 ExpectPath(true);
237}
238
239TEST_F(IsPotentiallyReachableTest, SimpleLoop2) {
240 ParseAssembly(
241 "declare i1 @switch()\n"
242 "\n"
243 "define void @test() {\n"
244 "entry:\n"
245 " %B = bitcast i8 undef to i8\n"
246 " br label %loop\n"
247 "loop:\n"
248 " %A = bitcast i8 undef to i8\n"
249 " %x = call i1 @switch()\n"
250 " br i1 %x, label %loop, label %exit\n"
251 "exit:\n"
252 " ret void\n"
253 "}");
254 ExpectPath(false);
255}
256
257TEST_F(IsPotentiallyReachableTest, SimpleLoop3) {
258 ParseAssembly(
259 "declare i1 @switch()\n"
260 "\n"
261 "define void @test() {\n"
262 "entry:\n"
263 " br label %loop\n"
264 "loop:\n"
265 " %B = bitcast i8 undef to i8\n"
266 " %x = call i1 @switch()\n"
267 " br i1 %x, label %loop, label %exit\n"
268 "exit:\n"
269 " %A = bitcast i8 undef to i8\n"
270 " ret void\n"
271 "}");
272 ExpectPath(false);
273}
274
275
276TEST_F(IsPotentiallyReachableTest, OneLoopAfterTheOther1) {
277 ParseAssembly(
278 "declare i1 @switch()\n"
279 "\n"
280 "define void @test() {\n"
281 "entry:\n"
282 " br label %loop1\n"
283 "loop1:\n"
284 " %A = bitcast i8 undef to i8\n"
285 " %x = call i1 @switch()\n"
286 " br i1 %x, label %loop1, label %loop1exit\n"
287 "loop1exit:\n"
288 " br label %loop2\n"
289 "loop2:\n"
290 " %B = bitcast i8 undef to i8\n"
291 " %y = call i1 @switch()\n"
292 " br i1 %x, label %loop2, label %loop2exit\n"
293 "loop2exit:"
294 " ret void\n"
295 "}");
296 ExpectPath(true);
297}
298
299TEST_F(IsPotentiallyReachableTest, OneLoopAfterTheOther2) {
300 ParseAssembly(
301 "declare i1 @switch()\n"
302 "\n"
303 "define void @test() {\n"
304 "entry:\n"
305 " br label %loop1\n"
306 "loop1:\n"
307 " %B = bitcast i8 undef to i8\n"
308 " %x = call i1 @switch()\n"
309 " br i1 %x, label %loop1, label %loop1exit\n"
310 "loop1exit:\n"
311 " br label %loop2\n"
312 "loop2:\n"
313 " %A = bitcast i8 undef to i8\n"
314 " %y = call i1 @switch()\n"
315 " br i1 %x, label %loop2, label %loop2exit\n"
316 "loop2exit:"
317 " ret void\n"
318 "}");
319 ExpectPath(false);
320}
321
322TEST_F(IsPotentiallyReachableTest, OneLoopAfterTheOtherInsideAThirdLoop) {
323 ParseAssembly(
324 "declare i1 @switch()\n"
325 "\n"
326 "define void @test() {\n"
327 "entry:\n"
328 " br label %outerloop3\n"
329 "outerloop3:\n"
330 " br label %innerloop1\n"
331 "innerloop1:\n"
332 " %B = bitcast i8 undef to i8\n"
333 " %x = call i1 @switch()\n"
334 " br i1 %x, label %innerloop1, label %innerloop1exit\n"
335 "innerloop1exit:\n"
336 " br label %innerloop2\n"
337 "innerloop2:\n"
338 " %A = bitcast i8 undef to i8\n"
339 " %y = call i1 @switch()\n"
340 " br i1 %x, label %innerloop2, label %innerloop2exit\n"
341 "innerloop2exit:"
342 " ;; In outer loop3 now.\n"
343 " %z = call i1 @switch()\n"
344 " br i1 %z, label %outerloop3, label %exit\n"
345 "exit:\n"
346 " ret void\n"
347 "}");
348 ExpectPath(true);
349}
350
Benjamin Kramer3c29c072014-02-10 14:17:42 +0000351static const char *BranchInsideLoopIR =
352 "declare i1 @switch()\n"
353 "\n"
354 "define void @test() {\n"
355 "entry:\n"
356 " br label %loop\n"
357 "loop:\n"
358 " %x = call i1 @switch()\n"
359 " br i1 %x, label %nextloopblock, label %exit\n"
360 "nextloopblock:\n"
361 " %y = call i1 @switch()\n"
362 " br i1 %y, label %left, label %right\n"
363 "left:\n"
364 " %A = bitcast i8 undef to i8\n"
365 " br label %loop\n"
366 "right:\n"
367 " %B = bitcast i8 undef to i8\n"
368 " br label %loop\n"
369 "exit:\n"
370 " ret void\n"
371 "}";
372
Nick Lewycky0b682452013-07-27 01:24:00 +0000373TEST_F(IsPotentiallyReachableTest, BranchInsideLoop) {
Benjamin Kramer3c29c072014-02-10 14:17:42 +0000374 ParseAssembly(BranchInsideLoopIR);
375 ExpectPath(true);
376}
377
378TEST_F(IsPotentiallyReachableTest, ModifyTest) {
379 ParseAssembly(BranchInsideLoopIR);
380
381 succ_iterator S = succ_begin(++M->getFunction("test")->begin());
382 BasicBlock *OldBB = S[0];
383 S[0] = S[1];
384 ExpectPath(false);
385 S[0] = OldBB;
Nick Lewycky0b682452013-07-27 01:24:00 +0000386 ExpectPath(true);
387}