Home | History | Annotate | Download | only in Analysis
      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 }
    360