23588037784e8ad41f9f9288b5e2f15c206fdee9
[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/ADT/OwningPtr.h"
12 #include "llvm/Analysis/Dominators.h"
13 #include "llvm/Analysis/LoopInfo.h"
14 #include "llvm/Assembly/Parser.h"
15 #include "llvm/IR/LLVMContext.h"
16 #include "llvm/IR/Function.h"
17 #include "llvm/IR/Module.h"
18 #include "llvm/Support/ErrorHandling.h"
19 #include "llvm/Support/InstIterator.h"
20 #include "llvm/Support/SourceMgr.h"
21 #include "llvm/Pass.h"
22 #include "llvm/PassManager.h"
23 #include "gtest/gtest.h"
24
25 using namespace llvm;
26
27 namespace {
28
29 // This fixture assists in running the isPotentiallyReachable utility four ways
30 // and ensuring it produces the correct answer each time.
31 class IsPotentiallyReachableTest : public testing::Test {
32 protected:
33   void ParseAssembly(const char *Assembly) {
34     M.reset(new Module("Module", getGlobalContext()));
35
36     SMDiagnostic Error;
37     bool Parsed = ParseAssemblyString(Assembly, M.get(),
38                                       Error, M->getContext()) == M.get();
39
40     std::string errMsg;
41     raw_string_ostream os(errMsg);
42     Error.print("", os);
43
44     if (!Parsed) {
45       // A failure here means that the test itself is buggy.
46       report_fatal_error(os.str().c_str());
47     }
48
49     Function *F = M->getFunction("test");
50     if (F == NULL)
51       report_fatal_error("Test must have a function named @test");
52
53     A = B = NULL;
54     for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
55       if (I->hasName()) {
56         if (I->getName() == "A")
57           A = &*I;
58         else if (I->getName() == "B")
59           B = &*I;
60       }
61     }
62     if (A == NULL)
63       report_fatal_error("@test must have an instruction %A");
64     if (B == NULL)
65       report_fatal_error("@test must have an instruction %B");
66   }
67
68   void ExpectPath(bool ExpectedResult) {
69     static char ID;
70     class IsPotentiallyReachableTestPass : public FunctionPass {
71      public:
72       IsPotentiallyReachableTestPass(bool ExpectedResult,
73                                      Instruction *A, Instruction *B)
74           : FunctionPass(ID), ExpectedResult(ExpectedResult), A(A), B(B) {}
75
76       static int initialize() {
77         PassInfo *PI = new PassInfo("isPotentiallyReachable testing pass",
78                                     "", &ID, 0, true, true);
79         PassRegistry::getPassRegistry()->registerPass(*PI, false);
80         initializeLoopInfoPass(*PassRegistry::getPassRegistry());
81         initializeDominatorTreePass(*PassRegistry::getPassRegistry());
82         return 0;
83       }
84
85       void getAnalysisUsage(AnalysisUsage &AU) const {
86         AU.setPreservesAll();
87         AU.addRequired<LoopInfo>();
88         AU.addRequired<DominatorTree>();
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 = &getAnalysis<DominatorTree>();
97         EXPECT_EQ(isPotentiallyReachable(A, B, 0, 0), ExpectedResult);
98         EXPECT_EQ(isPotentiallyReachable(A, B, DT, 0), ExpectedResult);
99         EXPECT_EQ(isPotentiallyReachable(A, B, 0, LI), ExpectedResult);
100         EXPECT_EQ(isPotentiallyReachable(A, B, DT, LI), ExpectedResult);
101         return false;
102       }
103       bool ExpectedResult;
104       Instruction *A, *B;
105     };
106
107     static int initialize = IsPotentiallyReachableTestPass::initialize();
108     (void)initialize;
109
110     IsPotentiallyReachableTestPass *P =
111         new IsPotentiallyReachableTestPass(ExpectedResult, A, B);
112     PassManager PM;
113     PM.add(P);
114     PM.run(*M);
115   }
116 private:
117   OwningPtr<Module> M;
118   Instruction *A, *B;
119 };
120
121 }
122
123 TEST_F(IsPotentiallyReachableTest, SameBlockNoPath) {
124   ParseAssembly(
125       "define void @test() {\n"
126       "entry:\n"
127       "  bitcast i8 undef to i8\n"
128       "  %B = bitcast i8 undef to i8\n"
129       "  bitcast i8 undef to i8\n"
130       "  bitcast i8 undef to i8\n"
131       "  %A = bitcast i8 undef to i8\n"
132       "  ret void\n"
133       "}\n");
134   ExpectPath(false);
135 }
136
137 TEST_F(IsPotentiallyReachableTest, SameBlockPath) {
138   ParseAssembly(
139       "define void @test() {\n"
140       "entry:\n"
141       "  %A = bitcast i8 undef to i8\n"
142       "  bitcast i8 undef to i8\n"
143       "  bitcast i8 undef to i8\n"
144       "  %B = bitcast i8 undef to i8\n"
145       "  ret void\n"
146       "}\n");
147   ExpectPath(true);
148 }
149
150 TEST_F(IsPotentiallyReachableTest, StraightNoPath) {
151   ParseAssembly(
152       "define void @test() {\n"
153       "entry:\n"
154       "  %B = bitcast i8 undef to i8\n"
155       "  br label %exit\n"
156       "exit:\n"
157       "  %A = bitcast i8 undef to i8\n"
158       "  ret void\n"
159       "}");
160   ExpectPath(false);
161 }
162
163 TEST_F(IsPotentiallyReachableTest, StraightPath) {
164   ParseAssembly(
165       "define void @test() {\n"
166       "entry:\n"
167       "  %A = bitcast i8 undef to i8\n"
168       "  br label %exit\n"
169       "exit:\n"
170       "  %B = bitcast i8 undef to i8\n"
171       "  ret void\n"
172       "}");
173   ExpectPath(true);
174 }
175
176 TEST_F(IsPotentiallyReachableTest, DestUnreachable) {
177   ParseAssembly(
178       "define void @test() {\n"
179       "entry:\n"
180       "  br label %midblock\n"
181       "midblock:\n"
182       "  %A = bitcast i8 undef to i8\n"
183       "  ret void\n"
184       "unreachable:\n"
185       "  %B = bitcast i8 undef to i8\n"
186       "  br label %midblock\n"
187       "}");
188   ExpectPath(false);
189 }
190
191 TEST_F(IsPotentiallyReachableTest, BranchToReturn) {
192   ParseAssembly(
193       "define void @test(i1 %x) {\n"
194       "entry:\n"
195       "  %A = bitcast i8 undef to i8\n"
196       "  br i1 %x, label %block1, label %block2\n"
197       "block1:\n"
198       "  ret void\n"
199       "block2:\n"
200       "  %B = bitcast i8 undef to i8\n"
201       "  ret void\n"
202       "}");
203   ExpectPath(true);
204 }
205
206 TEST_F(IsPotentiallyReachableTest, SimpleLoop1) {
207   ParseAssembly(
208       "declare i1 @switch()\n"
209       "\n"
210       "define void @test() {\n"
211       "entry:\n"
212       "  br label %loop\n"
213       "loop:\n"
214       "  %B = bitcast i8 undef to i8\n"
215       "  %A = bitcast i8 undef to i8\n"
216       "  %x = call i1 @switch()\n"
217       "  br i1 %x, label %loop, label %exit\n"
218       "exit:\n"
219       "  ret void\n"
220       "}");
221   ExpectPath(true);
222 }
223
224 TEST_F(IsPotentiallyReachableTest, SimpleLoop2) {
225   ParseAssembly(
226       "declare i1 @switch()\n"
227       "\n"
228       "define void @test() {\n"
229       "entry:\n"
230       "  %B = bitcast i8 undef to i8\n"
231       "  br label %loop\n"
232       "loop:\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(false);
240 }
241
242 TEST_F(IsPotentiallyReachableTest, SimpleLoop3) {
243   ParseAssembly(
244       "declare i1 @switch()\n"
245       "\n"
246       "define void @test() {\n"
247       "entry:\n"
248       "  br label %loop\n"
249       "loop:\n"
250       "  %B = bitcast i8 undef to i8\n"
251       "  %x = call i1 @switch()\n"
252       "  br i1 %x, label %loop, label %exit\n"
253       "exit:\n"
254       "  %A = bitcast i8 undef to i8\n"
255       "  ret void\n"
256       "}");
257   ExpectPath(false);
258 }
259
260
261 TEST_F(IsPotentiallyReachableTest, OneLoopAfterTheOther1) {
262   ParseAssembly(
263       "declare i1 @switch()\n"
264       "\n"
265       "define void @test() {\n"
266       "entry:\n"
267       "  br label %loop1\n"
268       "loop1:\n"
269       "  %A = bitcast i8 undef to i8\n"
270       "  %x = call i1 @switch()\n"
271       "  br i1 %x, label %loop1, label %loop1exit\n"
272       "loop1exit:\n"
273       "  br label %loop2\n"
274       "loop2:\n"
275       "  %B = bitcast i8 undef to i8\n"
276       "  %y = call i1 @switch()\n"
277       "  br i1 %x, label %loop2, label %loop2exit\n"
278       "loop2exit:"
279       "  ret void\n"
280       "}");
281   ExpectPath(true);
282 }
283
284 TEST_F(IsPotentiallyReachableTest, OneLoopAfterTheOther2) {
285   ParseAssembly(
286       "declare i1 @switch()\n"
287       "\n"
288       "define void @test() {\n"
289       "entry:\n"
290       "  br label %loop1\n"
291       "loop1:\n"
292       "  %B = bitcast i8 undef to i8\n"
293       "  %x = call i1 @switch()\n"
294       "  br i1 %x, label %loop1, label %loop1exit\n"
295       "loop1exit:\n"
296       "  br label %loop2\n"
297       "loop2:\n"
298       "  %A = bitcast i8 undef to i8\n"
299       "  %y = call i1 @switch()\n"
300       "  br i1 %x, label %loop2, label %loop2exit\n"
301       "loop2exit:"
302       "  ret void\n"
303       "}");
304   ExpectPath(false);
305 }
306
307 TEST_F(IsPotentiallyReachableTest, OneLoopAfterTheOtherInsideAThirdLoop) {
308   ParseAssembly(
309       "declare i1 @switch()\n"
310       "\n"
311       "define void @test() {\n"
312       "entry:\n"
313       "  br label %outerloop3\n"
314       "outerloop3:\n"
315       "  br label %innerloop1\n"
316       "innerloop1:\n"
317       "  %B = bitcast i8 undef to i8\n"
318       "  %x = call i1 @switch()\n"
319       "  br i1 %x, label %innerloop1, label %innerloop1exit\n"
320       "innerloop1exit:\n"
321       "  br label %innerloop2\n"
322       "innerloop2:\n"
323       "  %A = bitcast i8 undef to i8\n"
324       "  %y = call i1 @switch()\n"
325       "  br i1 %x, label %innerloop2, label %innerloop2exit\n"
326       "innerloop2exit:"
327       "  ;; In outer loop3 now.\n"
328       "  %z = call i1 @switch()\n"
329       "  br i1 %z, label %outerloop3, label %exit\n"
330       "exit:\n"
331       "  ret void\n"
332       "}");
333   ExpectPath(true);
334 }
335
336 TEST_F(IsPotentiallyReachableTest, BranchInsideLoop) {
337   ParseAssembly(
338       "declare i1 @switch()\n"
339       "\n"
340       "define void @test() {\n"
341       "entry:\n"
342       "  br label %loop\n"
343       "loop:\n"
344       "  %x = call i1 @switch()\n"
345       "  br i1 %x, label %nextloopblock, label %exit\n"
346       "nextloopblock:\n"
347       "  %y = call i1 @switch()\n"
348       "  br i1 %y, label %left, label %right\n"
349       "left:\n"
350       "  %A = bitcast i8 undef to i8\n"
351       "  br label %loop\n"
352       "right:\n"
353       "  %B = bitcast i8 undef to i8\n"
354       "  br label %loop\n"
355       "exit:\n"
356       "  ret void\n"
357       "}");
358   ExpectPath(true);
359 }