ac5e71061d8ae61c83aa95d8cc4b826b6df4200b
[oota-llvm.git] / unittests / Analysis / CFGTest.cpp
1 //===- 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"
11 #include "llvm/Analysis/LoopInfo.h"
12 #include "llvm/AsmParser/Parser.h"
13 #include "llvm/IR/Dominators.h"
14 #include "llvm/IR/Function.h"
15 #include "llvm/IR/InstIterator.h"
16 #include "llvm/IR/LLVMContext.h"
17 #include "llvm/IR/Module.h"
18 #include "llvm/Pass.h"
19 #include "llvm/PassManager.h"
20 #include "llvm/Support/ErrorHandling.h"
21 #include "llvm/Support/SourceMgr.h"
22 #include "gtest/gtest.h"
23
24 using namespace llvm;
25
26 namespace {
27
28 // This fixture assists in running the isPotentiallyReachable utility four ways
29 // and ensuring it produces the correct answer each time.
30 class IsPotentiallyReachableTest : public testing::Test {
31 protected:
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 == nullptr)
50       report_fatal_error("Test must have a function named @test");
51
52     A = B = nullptr;
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 == nullptr)
62       report_fatal_error("@test must have an instruction %A");
63     if (B == nullptr)
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, nullptr, true, true);
78         PassRegistry::getPassRegistry()->registerPass(*PI, false);
79         initializeLoopInfoPass(*PassRegistry::getPassRegistry());
80         initializeDominatorTreeWrapperPassPass(
81             *PassRegistry::getPassRegistry());
82         return 0;
83       }
84
85       void getAnalysisUsage(AnalysisUsage &AU) const {
86         AU.setPreservesAll();
87         AU.addRequired<LoopInfo>();
88         AU.addRequired<DominatorTreeWrapperPass>();
89       }
90
91       bool runOnFunction(Function &F) {
92         if (!F.hasName() || F.getName() != "test")
93           return false;
94
95         LoopInfo *LI = &getAnalysis<LoopInfo>();
96         DominatorTree *DT =
97             &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
98         EXPECT_EQ(isPotentiallyReachable(A, B, nullptr, nullptr),
99                   ExpectedResult);
100         EXPECT_EQ(isPotentiallyReachable(A, B, DT, nullptr), ExpectedResult);
101         EXPECT_EQ(isPotentiallyReachable(A, B, nullptr, LI), ExpectedResult);
102         EXPECT_EQ(isPotentiallyReachable(A, B, DT, LI), ExpectedResult);
103         return false;
104       }
105       bool ExpectedResult;
106       Instruction *A, *B;
107     };
108
109     static int initialize = IsPotentiallyReachableTestPass::initialize();
110     (void)initialize;
111
112     IsPotentiallyReachableTestPass *P =
113         new IsPotentiallyReachableTestPass(ExpectedResult, A, B);
114     PassManager PM;
115     PM.add(P);
116     PM.run(*M);
117   }
118
119   std::unique_ptr<Module> M;
120   Instruction *A, *B;
121 };
122
123 }
124
125 TEST_F(IsPotentiallyReachableTest, SameBlockNoPath) {
126   ParseAssembly(
127       "define void @test() {\n"
128       "entry:\n"
129       "  bitcast i8 undef to i8\n"
130       "  %B = bitcast i8 undef to i8\n"
131       "  bitcast i8 undef to i8\n"
132       "  bitcast i8 undef to i8\n"
133       "  %A = bitcast i8 undef to i8\n"
134       "  ret void\n"
135       "}\n");
136   ExpectPath(false);
137 }
138
139 TEST_F(IsPotentiallyReachableTest, SameBlockPath) {
140   ParseAssembly(
141       "define void @test() {\n"
142       "entry:\n"
143       "  %A = bitcast i8 undef to i8\n"
144       "  bitcast i8 undef to i8\n"
145       "  bitcast i8 undef to i8\n"
146       "  %B = bitcast i8 undef to i8\n"
147       "  ret void\n"
148       "}\n");
149   ExpectPath(true);
150 }
151
152 TEST_F(IsPotentiallyReachableTest, SameBlockNoLoop) {
153   ParseAssembly(
154       "define void @test() {\n"
155       "entry:\n"
156       "  br label %middle\n"
157       "middle:\n"
158       "  %B = bitcast i8 undef to i8\n"
159       "  bitcast i8 undef to i8\n"
160       "  bitcast i8 undef to i8\n"
161       "  %A = bitcast i8 undef to i8\n"
162       "  br label %nextblock\n"
163       "nextblock:\n"
164       "  ret void\n"
165       "}\n");
166   ExpectPath(false);
167 }
168
169 TEST_F(IsPotentiallyReachableTest, StraightNoPath) {
170   ParseAssembly(
171       "define void @test() {\n"
172       "entry:\n"
173       "  %B = bitcast i8 undef to i8\n"
174       "  br label %exit\n"
175       "exit:\n"
176       "  %A = bitcast i8 undef to i8\n"
177       "  ret void\n"
178       "}");
179   ExpectPath(false);
180 }
181
182 TEST_F(IsPotentiallyReachableTest, StraightPath) {
183   ParseAssembly(
184       "define void @test() {\n"
185       "entry:\n"
186       "  %A = bitcast i8 undef to i8\n"
187       "  br label %exit\n"
188       "exit:\n"
189       "  %B = bitcast i8 undef to i8\n"
190       "  ret void\n"
191       "}");
192   ExpectPath(true);
193 }
194
195 TEST_F(IsPotentiallyReachableTest, DestUnreachable) {
196   ParseAssembly(
197       "define void @test() {\n"
198       "entry:\n"
199       "  br label %midblock\n"
200       "midblock:\n"
201       "  %A = bitcast i8 undef to i8\n"
202       "  ret void\n"
203       "unreachable:\n"
204       "  %B = bitcast i8 undef to i8\n"
205       "  br label %midblock\n"
206       "}");
207   ExpectPath(false);
208 }
209
210 TEST_F(IsPotentiallyReachableTest, BranchToReturn) {
211   ParseAssembly(
212       "define void @test(i1 %x) {\n"
213       "entry:\n"
214       "  %A = bitcast i8 undef to i8\n"
215       "  br i1 %x, label %block1, label %block2\n"
216       "block1:\n"
217       "  ret void\n"
218       "block2:\n"
219       "  %B = bitcast i8 undef to i8\n"
220       "  ret void\n"
221       "}");
222   ExpectPath(true);
223 }
224
225 TEST_F(IsPotentiallyReachableTest, SimpleLoop1) {
226   ParseAssembly(
227       "declare i1 @switch()\n"
228       "\n"
229       "define void @test() {\n"
230       "entry:\n"
231       "  br label %loop\n"
232       "loop:\n"
233       "  %B = bitcast i8 undef to i8\n"
234       "  %A = bitcast i8 undef to i8\n"
235       "  %x = call i1 @switch()\n"
236       "  br i1 %x, label %loop, label %exit\n"
237       "exit:\n"
238       "  ret void\n"
239       "}");
240   ExpectPath(true);
241 }
242
243 TEST_F(IsPotentiallyReachableTest, SimpleLoop2) {
244   ParseAssembly(
245       "declare i1 @switch()\n"
246       "\n"
247       "define void @test() {\n"
248       "entry:\n"
249       "  %B = bitcast i8 undef to i8\n"
250       "  br label %loop\n"
251       "loop:\n"
252       "  %A = bitcast i8 undef to i8\n"
253       "  %x = call i1 @switch()\n"
254       "  br i1 %x, label %loop, label %exit\n"
255       "exit:\n"
256       "  ret void\n"
257       "}");
258   ExpectPath(false);
259 }
260
261 TEST_F(IsPotentiallyReachableTest, SimpleLoop3) {
262   ParseAssembly(
263       "declare i1 @switch()\n"
264       "\n"
265       "define void @test() {\n"
266       "entry:\n"
267       "  br label %loop\n"
268       "loop:\n"
269       "  %B = bitcast i8 undef to i8\n"
270       "  %x = call i1 @switch()\n"
271       "  br i1 %x, label %loop, label %exit\n"
272       "exit:\n"
273       "  %A = bitcast i8 undef to i8\n"
274       "  ret void\n"
275       "}");
276   ExpectPath(false);
277 }
278
279
280 TEST_F(IsPotentiallyReachableTest, OneLoopAfterTheOther1) {
281   ParseAssembly(
282       "declare i1 @switch()\n"
283       "\n"
284       "define void @test() {\n"
285       "entry:\n"
286       "  br label %loop1\n"
287       "loop1:\n"
288       "  %A = bitcast i8 undef to i8\n"
289       "  %x = call i1 @switch()\n"
290       "  br i1 %x, label %loop1, label %loop1exit\n"
291       "loop1exit:\n"
292       "  br label %loop2\n"
293       "loop2:\n"
294       "  %B = bitcast i8 undef to i8\n"
295       "  %y = call i1 @switch()\n"
296       "  br i1 %x, label %loop2, label %loop2exit\n"
297       "loop2exit:"
298       "  ret void\n"
299       "}");
300   ExpectPath(true);
301 }
302
303 TEST_F(IsPotentiallyReachableTest, OneLoopAfterTheOther2) {
304   ParseAssembly(
305       "declare i1 @switch()\n"
306       "\n"
307       "define void @test() {\n"
308       "entry:\n"
309       "  br label %loop1\n"
310       "loop1:\n"
311       "  %B = bitcast i8 undef to i8\n"
312       "  %x = call i1 @switch()\n"
313       "  br i1 %x, label %loop1, label %loop1exit\n"
314       "loop1exit:\n"
315       "  br label %loop2\n"
316       "loop2:\n"
317       "  %A = bitcast i8 undef to i8\n"
318       "  %y = call i1 @switch()\n"
319       "  br i1 %x, label %loop2, label %loop2exit\n"
320       "loop2exit:"
321       "  ret void\n"
322       "}");
323   ExpectPath(false);
324 }
325
326 TEST_F(IsPotentiallyReachableTest, OneLoopAfterTheOtherInsideAThirdLoop) {
327   ParseAssembly(
328       "declare i1 @switch()\n"
329       "\n"
330       "define void @test() {\n"
331       "entry:\n"
332       "  br label %outerloop3\n"
333       "outerloop3:\n"
334       "  br label %innerloop1\n"
335       "innerloop1:\n"
336       "  %B = bitcast i8 undef to i8\n"
337       "  %x = call i1 @switch()\n"
338       "  br i1 %x, label %innerloop1, label %innerloop1exit\n"
339       "innerloop1exit:\n"
340       "  br label %innerloop2\n"
341       "innerloop2:\n"
342       "  %A = bitcast i8 undef to i8\n"
343       "  %y = call i1 @switch()\n"
344       "  br i1 %x, label %innerloop2, label %innerloop2exit\n"
345       "innerloop2exit:"
346       "  ;; In outer loop3 now.\n"
347       "  %z = call i1 @switch()\n"
348       "  br i1 %z, label %outerloop3, label %exit\n"
349       "exit:\n"
350       "  ret void\n"
351       "}");
352   ExpectPath(true);
353 }
354
355 static const char *BranchInsideLoopIR =
356     "declare i1 @switch()\n"
357     "\n"
358     "define void @test() {\n"
359     "entry:\n"
360     "  br label %loop\n"
361     "loop:\n"
362     "  %x = call i1 @switch()\n"
363     "  br i1 %x, label %nextloopblock, label %exit\n"
364     "nextloopblock:\n"
365     "  %y = call i1 @switch()\n"
366     "  br i1 %y, label %left, label %right\n"
367     "left:\n"
368     "  %A = bitcast i8 undef to i8\n"
369     "  br label %loop\n"
370     "right:\n"
371     "  %B = bitcast i8 undef to i8\n"
372     "  br label %loop\n"
373     "exit:\n"
374     "  ret void\n"
375     "}";
376
377 TEST_F(IsPotentiallyReachableTest, BranchInsideLoop) {
378   ParseAssembly(BranchInsideLoopIR);
379   ExpectPath(true);
380 }
381
382 TEST_F(IsPotentiallyReachableTest, ModifyTest) {
383   ParseAssembly(BranchInsideLoopIR);
384
385   succ_iterator S = succ_begin(++M->getFunction("test")->begin());
386   BasicBlock *OldBB = S[0];
387   S[0] = S[1];
388   ExpectPath(false);
389   S[0] = OldBB;
390   ExpectPath(true);
391 }