Home | History | Annotate | Download | only in Analysis
      1 //===- UnrollAnalyzerTest.cpp - UnrollAnalyzer unit 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/AsmParser/Parser.h"
     11 #include "llvm/IR/LegacyPassManager.h"
     12 #include "llvm/Support/SourceMgr.h"
     13 #include "llvm/Analysis/LoopUnrollAnalyzer.h"
     14 #include "llvm/IR/Dominators.h"
     15 #include "gtest/gtest.h"
     16 
     17 using namespace llvm;
     18 namespace llvm {
     19 void initializeUnrollAnalyzerTestPass(PassRegistry &);
     20 
     21 static SmallVector<DenseMap<Value *, Constant *>, 16> SimplifiedValuesVector;
     22 static unsigned TripCount = 0;
     23 
     24 namespace {
     25 struct UnrollAnalyzerTest : public FunctionPass {
     26   static char ID;
     27   bool runOnFunction(Function &F) override {
     28     LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
     29     ScalarEvolution *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
     30 
     31     Function::iterator FI = F.begin();
     32     FI++; // First basic block is entry - skip it.
     33     BasicBlock *Header = &*FI++;
     34     Loop *L = LI->getLoopFor(Header);
     35     BasicBlock *Exiting = L->getExitingBlock();
     36 
     37     SimplifiedValuesVector.clear();
     38     TripCount = SE->getSmallConstantTripCount(L, Exiting);
     39     for (unsigned Iteration = 0; Iteration < TripCount; Iteration++) {
     40       DenseMap<Value *, Constant *> SimplifiedValues;
     41       UnrolledInstAnalyzer Analyzer(Iteration, SimplifiedValues, *SE, L);
     42       for (auto *BB : L->getBlocks())
     43         for (Instruction &I : *BB)
     44           Analyzer.visit(I);
     45       SimplifiedValuesVector.push_back(SimplifiedValues);
     46     }
     47     return false;
     48   }
     49   void getAnalysisUsage(AnalysisUsage &AU) const override {
     50     AU.addRequired<DominatorTreeWrapperPass>();
     51     AU.addRequired<LoopInfoWrapperPass>();
     52     AU.addRequired<ScalarEvolutionWrapperPass>();
     53     AU.setPreservesAll();
     54   }
     55   UnrollAnalyzerTest() : FunctionPass(ID) {
     56     initializeUnrollAnalyzerTestPass(*PassRegistry::getPassRegistry());
     57   }
     58 };
     59 }
     60 
     61 char UnrollAnalyzerTest::ID = 0;
     62 
     63 std::unique_ptr<Module> makeLLVMModule(LLVMContext &Context,
     64                                        UnrollAnalyzerTest *P,
     65                                        const char *ModuleStr) {
     66   SMDiagnostic Err;
     67   return parseAssemblyString(ModuleStr, Err, Context);
     68 }
     69 
     70 TEST(UnrollAnalyzerTest, BasicSimplifications) {
     71   const char *ModuleStr =
     72       "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n"
     73       "define i64 @propagate_loop_phis() {\n"
     74       "entry:\n"
     75       "  br label %loop\n"
     76       "loop:\n"
     77       "  %iv = phi i64 [ 0, %entry ], [ %inc, %loop ]\n"
     78       "  %x0 = phi i64 [ 0, %entry ], [ %x2, %loop ]\n"
     79       "  %x1 = or i64 %x0, 1\n"
     80       "  %x2 = or i64 %x1, 2\n"
     81       "  %inc = add nuw nsw i64 %iv, 1\n"
     82       "  %cond = icmp sge i64 %inc, 8\n"
     83       "  br i1 %cond, label %loop.end, label %loop\n"
     84       "loop.end:\n"
     85       "  %x.lcssa = phi i64 [ %x2, %loop ]\n"
     86       "  ret i64 %x.lcssa\n"
     87       "}\n";
     88   UnrollAnalyzerTest *P = new UnrollAnalyzerTest();
     89   LLVMContext Context;
     90   std::unique_ptr<Module> M = makeLLVMModule(Context, P, ModuleStr);
     91   legacy::PassManager Passes;
     92   Passes.add(P);
     93   Passes.run(*M);
     94 
     95   // Perform checks
     96   Module::iterator MI = M->begin();
     97   Function *F = &*MI++;
     98   Function::iterator FI = F->begin();
     99   FI++; // First basic block is entry - skip it.
    100   BasicBlock *Header = &*FI++;
    101 
    102   BasicBlock::iterator BBI = Header->begin();
    103   std::advance(BBI, 4);
    104   Instruction *Y1 = &*BBI++;
    105   Instruction *Y2 = &*BBI++;
    106   // Check simplification expected on the 1st iteration.
    107   // Check that "%inc = add nuw nsw i64 %iv, 1" is simplified to 1
    108   auto I1 = SimplifiedValuesVector[0].find(Y1);
    109   EXPECT_TRUE(I1 != SimplifiedValuesVector[0].end());
    110   EXPECT_EQ(cast<ConstantInt>((*I1).second)->getZExtValue(), 1U);
    111 
    112   // Check that "%cond = icmp sge i64 %inc, 10" is simplified to false
    113   auto I2 = SimplifiedValuesVector[0].find(Y2);
    114   EXPECT_TRUE(I2 != SimplifiedValuesVector[0].end());
    115   EXPECT_FALSE(cast<ConstantInt>((*I2).second)->getZExtValue());
    116 
    117   // Check simplification expected on the last iteration.
    118   // Check that "%inc = add nuw nsw i64 %iv, 1" is simplified to 8
    119   I1 = SimplifiedValuesVector[TripCount - 1].find(Y1);
    120   EXPECT_TRUE(I1 != SimplifiedValuesVector[TripCount - 1].end());
    121   EXPECT_EQ(cast<ConstantInt>((*I1).second)->getZExtValue(), TripCount);
    122 
    123   // Check that "%cond = icmp sge i64 %inc, 10" is simplified to false
    124   I2 = SimplifiedValuesVector[TripCount - 1].find(Y2);
    125   EXPECT_TRUE(I2 != SimplifiedValuesVector[TripCount - 1].end());
    126   EXPECT_TRUE(cast<ConstantInt>((*I2).second)->getZExtValue());
    127 }
    128 
    129 TEST(UnrollAnalyzerTest, OuterLoopSimplification) {
    130   const char *ModuleStr =
    131       "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n"
    132       "define void @foo() {\n"
    133       "entry:\n"
    134       "  br label %outer.loop\n"
    135       "outer.loop:\n"
    136       "  %iv.outer = phi i64 [ 0, %entry ], [ %iv.outer.next, %outer.loop.latch ]\n"
    137       "  %iv.outer.next = add nuw nsw i64 %iv.outer, 1\n"
    138       "  br label %inner.loop\n"
    139       "inner.loop:\n"
    140       "  %iv.inner = phi i64 [ 0, %outer.loop ], [ %iv.inner.next, %inner.loop ]\n"
    141       "  %iv.inner.next = add nuw nsw i64 %iv.inner, 1\n"
    142       "  %exitcond.inner = icmp eq i64 %iv.inner.next, 1000\n"
    143       "  br i1 %exitcond.inner, label %outer.loop.latch, label %inner.loop\n"
    144       "outer.loop.latch:\n"
    145       "  %exitcond.outer = icmp eq i64 %iv.outer.next, 40\n"
    146       "  br i1 %exitcond.outer, label %exit, label %outer.loop\n"
    147       "exit:\n"
    148       "  ret void\n"
    149       "}\n";
    150 
    151   UnrollAnalyzerTest *P = new UnrollAnalyzerTest();
    152   LLVMContext Context;
    153   std::unique_ptr<Module> M = makeLLVMModule(Context, P, ModuleStr);
    154   legacy::PassManager Passes;
    155   Passes.add(P);
    156   Passes.run(*M);
    157 
    158   Module::iterator MI = M->begin();
    159   Function *F = &*MI++;
    160   Function::iterator FI = F->begin();
    161   FI++;
    162   BasicBlock *Header = &*FI++;
    163   BasicBlock *InnerBody = &*FI++;
    164 
    165   BasicBlock::iterator BBI = Header->begin();
    166   BBI++;
    167   Instruction *Y1 = &*BBI;
    168   BBI = InnerBody->begin();
    169   BBI++;
    170   Instruction *Y2 = &*BBI;
    171   // Check that we can simplify IV of the outer loop, but can't simplify the IV
    172   // of the inner loop if we only know the iteration number of the outer loop.
    173   //
    174   //  Y1 is %iv.outer.next, Y2 is %iv.inner.next
    175   auto I1 = SimplifiedValuesVector[0].find(Y1);
    176   EXPECT_TRUE(I1 != SimplifiedValuesVector[0].end());
    177   auto I2 = SimplifiedValuesVector[0].find(Y2);
    178   EXPECT_TRUE(I2 == SimplifiedValuesVector[0].end());
    179 }
    180 TEST(UnrollAnalyzerTest, CmpSimplifications) {
    181   const char *ModuleStr =
    182       "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n"
    183       "define void @branch_iv_trunc() {\n"
    184       "entry:\n"
    185       "  br label %for.body\n"
    186       "for.body:\n"
    187       "  %indvars.iv = phi i64 [ 0, %entry ], [ %tmp3, %for.body ]\n"
    188       "  %tmp2 = trunc i64 %indvars.iv to i32\n"
    189       "  %cmp3 = icmp eq i32 %tmp2, 5\n"
    190       "  %tmp3 = add nuw nsw i64 %indvars.iv, 1\n"
    191       "  %exitcond = icmp eq i64 %tmp3, 10\n"
    192       "  br i1 %exitcond, label %for.end, label %for.body\n"
    193       "for.end:\n"
    194       "  ret void\n"
    195       "}\n";
    196   UnrollAnalyzerTest *P = new UnrollAnalyzerTest();
    197   LLVMContext Context;
    198   std::unique_ptr<Module> M = makeLLVMModule(Context, P, ModuleStr);
    199   legacy::PassManager Passes;
    200   Passes.add(P);
    201   Passes.run(*M);
    202 
    203   // Perform checks
    204   Module::iterator MI = M->begin();
    205   Function *F = &*MI++;
    206   Function::iterator FI = F->begin();
    207   FI++; // First basic block is entry - skip it.
    208   BasicBlock *Header = &*FI++;
    209 
    210   BasicBlock::iterator BBI = Header->begin();
    211   BBI++;
    212   Instruction *Y1 = &*BBI++;
    213   Instruction *Y2 = &*BBI++;
    214   // Check simplification expected on the 5th iteration.
    215   // Check that "%tmp2 = trunc i64 %indvars.iv to i32" is simplified to 5
    216   // and "%cmp3 = icmp eq i32 %tmp2, 5" is simplified to 1 (i.e. true).
    217   auto I1 = SimplifiedValuesVector[5].find(Y1);
    218   EXPECT_TRUE(I1 != SimplifiedValuesVector[5].end());
    219   EXPECT_EQ(cast<ConstantInt>((*I1).second)->getZExtValue(), 5U);
    220   auto I2 = SimplifiedValuesVector[5].find(Y2);
    221   EXPECT_TRUE(I2 != SimplifiedValuesVector[5].end());
    222   EXPECT_EQ(cast<ConstantInt>((*I2).second)->getZExtValue(), 1U);
    223 }
    224 TEST(UnrollAnalyzerTest, PtrCmpSimplifications) {
    225   const char *ModuleStr =
    226       "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n"
    227       "define void @ptr_cmp(i8 *%a) {\n"
    228       "entry:\n"
    229       "  %limit = getelementptr i8, i8* %a, i64 40\n"
    230       "  %start.iv2 = getelementptr i8, i8* %a, i64 7\n"
    231       "  br label %loop.body\n"
    232       "loop.body:\n"
    233       "  %iv.0 = phi i8* [ %a, %entry ], [ %iv.1, %loop.body ]\n"
    234       "  %iv2.0 = phi i8* [ %start.iv2, %entry ], [ %iv2.1, %loop.body ]\n"
    235       "  %cmp = icmp eq i8* %iv2.0, %iv.0\n"
    236       "  %iv.1 = getelementptr inbounds i8, i8* %iv.0, i64 1\n"
    237       "  %iv2.1 = getelementptr inbounds i8, i8* %iv2.0, i64 1\n"
    238       "  %exitcond = icmp ne i8* %iv.1, %limit\n"
    239       "  br i1 %exitcond, label %loop.body, label %loop.exit\n"
    240       "loop.exit:\n"
    241       "  ret void\n"
    242       "}\n";
    243   UnrollAnalyzerTest *P = new UnrollAnalyzerTest();
    244   LLVMContext Context;
    245   std::unique_ptr<Module> M = makeLLVMModule(Context, P, ModuleStr);
    246   legacy::PassManager Passes;
    247   Passes.add(P);
    248   Passes.run(*M);
    249 
    250   // Perform checks
    251   Module::iterator MI = M->begin();
    252   Function *F = &*MI++;
    253   Function::iterator FI = F->begin();
    254   FI++; // First basic block is entry - skip it.
    255   BasicBlock *Header = &*FI;
    256 
    257   BasicBlock::iterator BBI = Header->begin();
    258   std::advance(BBI, 2);
    259   Instruction *Y1 = &*BBI;
    260   // Check simplification expected on the 5th iteration.
    261   // Check that "%cmp = icmp eq i8* %iv2.0, %iv.0" is simplified to 0.
    262   auto I1 = SimplifiedValuesVector[5].find(Y1);
    263   EXPECT_TRUE(I1 != SimplifiedValuesVector[5].end());
    264   EXPECT_EQ(cast<ConstantInt>((*I1).second)->getZExtValue(), 0U);
    265 }
    266 TEST(UnrollAnalyzerTest, CastSimplifications) {
    267   const char *ModuleStr =
    268       "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n"
    269       "@known_constant = internal unnamed_addr constant [10 x i32] [i32 0, i32 1, i32 0, i32 1, i32 0, i32 259, i32 0, i32 1, i32 0, i32 1], align 16\n"
    270       "define void @const_load_cast() {\n"
    271       "entry:\n"
    272       "  br label %loop\n"
    273       "\n"
    274       "loop:\n"
    275       "  %iv = phi i64 [ 0, %entry ], [ %inc, %loop ]\n"
    276       "  %array_const_idx = getelementptr inbounds [10 x i32], [10 x i32]* @known_constant, i64 0, i64 %iv\n"
    277       "  %const_array_element = load i32, i32* %array_const_idx, align 4\n"
    278       "  %se = sext i32 %const_array_element to i64\n"
    279       "  %ze = zext i32 %const_array_element to i64\n"
    280       "  %tr = trunc i32 %const_array_element to i8\n"
    281       "  %inc = add nuw nsw i64 %iv, 1\n"
    282       "  %exitcond86.i = icmp eq i64 %inc, 10\n"
    283       "  br i1 %exitcond86.i, label %loop.end, label %loop\n"
    284       "\n"
    285       "loop.end:\n"
    286       "  ret void\n"
    287       "}\n";
    288 
    289   UnrollAnalyzerTest *P = new UnrollAnalyzerTest();
    290   LLVMContext Context;
    291   std::unique_ptr<Module> M = makeLLVMModule(Context, P, ModuleStr);
    292   legacy::PassManager Passes;
    293   Passes.add(P);
    294   Passes.run(*M);
    295 
    296   // Perform checks
    297   Module::iterator MI = M->begin();
    298   Function *F = &*MI++;
    299   Function::iterator FI = F->begin();
    300   FI++; // First basic block is entry - skip it.
    301   BasicBlock *Header = &*FI++;
    302 
    303   BasicBlock::iterator BBI = Header->begin();
    304   std::advance(BBI, 3);
    305   Instruction *Y1 = &*BBI++;
    306   Instruction *Y2 = &*BBI++;
    307   Instruction *Y3 = &*BBI++;
    308   // Check simplification expected on the 5th iteration.
    309   // "%se = sext i32 %const_array_element to i64" should be simplified to 259,
    310   // "%ze = zext i32 %const_array_element to i64" should be simplified to 259,
    311   // "%tr = trunc i32 %const_array_element to i8" should be simplified to 3.
    312   auto I1 = SimplifiedValuesVector[5].find(Y1);
    313   EXPECT_TRUE(I1 != SimplifiedValuesVector[5].end());
    314   EXPECT_EQ(cast<ConstantInt>((*I1).second)->getZExtValue(), 259U);
    315   auto I2 = SimplifiedValuesVector[5].find(Y2);
    316   EXPECT_TRUE(I2 != SimplifiedValuesVector[5].end());
    317   EXPECT_EQ(cast<ConstantInt>((*I2).second)->getZExtValue(), 259U);
    318   auto I3 = SimplifiedValuesVector[5].find(Y3);
    319   EXPECT_TRUE(I3 != SimplifiedValuesVector[5].end());
    320   EXPECT_EQ(cast<ConstantInt>((*I3).second)->getZExtValue(), 3U);
    321 }
    322 
    323 } // end namespace llvm
    324 
    325 INITIALIZE_PASS_BEGIN(UnrollAnalyzerTest, "unrollanalyzertestpass",
    326                       "unrollanalyzertestpass", false, false)
    327 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
    328 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
    329 INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
    330 INITIALIZE_PASS_END(UnrollAnalyzerTest, "unrollanalyzertestpass",
    331                     "unrollanalyzertestpass", false, false)
    332