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 } 392