1ca02360fSXin Tong //===- LoopInfoTest.cpp - LoopInfo unit tests -----------------------------===// 2ca02360fSXin Tong // 3ca02360fSXin Tong // The LLVM Compiler Infrastructure 4ca02360fSXin Tong // 5ca02360fSXin Tong // This file is distributed under the University of Illinois Open Source 6ca02360fSXin Tong // License. See LICENSE.TXT for details. 7ca02360fSXin Tong // 8ca02360fSXin Tong //===----------------------------------------------------------------------===// 9ca02360fSXin Tong 10ca02360fSXin Tong #include "llvm/Analysis/LoopInfo.h" 11ca02360fSXin Tong #include "llvm/AsmParser/Parser.h" 12ca02360fSXin Tong #include "llvm/IR/Dominators.h" 13ca02360fSXin Tong #include "llvm/Support/SourceMgr.h" 14ca02360fSXin Tong #include "gtest/gtest.h" 15ca02360fSXin Tong 16ca02360fSXin Tong using namespace llvm; 17ca02360fSXin Tong 1843c1a264SXin Tong /// Build the loop info for the function and run the Test. 1943c1a264SXin Tong static void 2043c1a264SXin Tong runWithLoopInfo(Module &M, StringRef FuncName, 2143c1a264SXin Tong function_ref<void(Function &F, LoopInfo &LI)> Test) { 2243c1a264SXin Tong auto *F = M.getFunction(FuncName); 2343c1a264SXin Tong ASSERT_NE(F, nullptr) << "Could not find " << FuncName; 2443c1a264SXin Tong // Compute the dominator tree and the loop info for the function. 2543c1a264SXin Tong DominatorTree DT(*F); 2643c1a264SXin Tong LoopInfo LI(DT); 2743c1a264SXin Tong Test(*F, LI); 2843c1a264SXin Tong } 2943c1a264SXin Tong 30ca02360fSXin Tong static std::unique_ptr<Module> makeLLVMModule(LLVMContext &Context, 31ca02360fSXin Tong const char *ModuleStr) { 32ca02360fSXin Tong SMDiagnostic Err; 33ca02360fSXin Tong return parseAssemblyString(ModuleStr, Err, Context); 34ca02360fSXin Tong } 35ca02360fSXin Tong 36ca02360fSXin Tong // This tests that for a loop with a single latch, we get the loop id from 37ca02360fSXin Tong // its only latch, even in case the loop may not be in a simplified form. 38ca02360fSXin Tong TEST(LoopInfoTest, LoopWithSingleLatch) { 39ca02360fSXin Tong const char *ModuleStr = 40ca02360fSXin Tong "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n" 41ca02360fSXin Tong "define void @foo(i32 %n) {\n" 42ca02360fSXin Tong "entry:\n" 43ca02360fSXin Tong " br i1 undef, label %for.cond, label %for.end\n" 44ca02360fSXin Tong "for.cond:\n" 45ca02360fSXin Tong " %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]\n" 46ca02360fSXin Tong " %cmp = icmp slt i32 %i.0, %n\n" 47ca02360fSXin Tong " br i1 %cmp, label %for.inc, label %for.end\n" 48ca02360fSXin Tong "for.inc:\n" 49ca02360fSXin Tong " %inc = add nsw i32 %i.0, 1\n" 50ca02360fSXin Tong " br label %for.cond, !llvm.loop !0\n" 51ca02360fSXin Tong "for.end:\n" 52ca02360fSXin Tong " ret void\n" 53ca02360fSXin Tong "}\n" 54ca02360fSXin Tong "!0 = distinct !{!0, !1}\n" 55ca02360fSXin Tong "!1 = !{!\"llvm.loop.distribute.enable\", i1 true}\n"; 56ca02360fSXin Tong 57ca02360fSXin Tong // Parse the module. 58ca02360fSXin Tong LLVMContext Context; 59ca02360fSXin Tong std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 60ca02360fSXin Tong 6143c1a264SXin Tong runWithLoopInfo(*M, "foo", [&](Function &F, LoopInfo &LI) { 62ca02360fSXin Tong Function::iterator FI = F.begin(); 6343c1a264SXin Tong // First basic block is entry - skip it. 6443c1a264SXin Tong BasicBlock *Header = &*(++FI); 65ca02360fSXin Tong assert(Header->getName() == "for.cond"); 66ca02360fSXin Tong Loop *L = LI.getLoopFor(Header); 67ca02360fSXin Tong 68ca02360fSXin Tong // This loop is not in simplified form. 69ca02360fSXin Tong EXPECT_FALSE(L->isLoopSimplifyForm()); 70ca02360fSXin Tong 71ca02360fSXin Tong // Analyze the loop metadata id. 72ca02360fSXin Tong bool loopIDFoundAndSet = false; 73ca02360fSXin Tong // Try to get and set the metadata id for the loop. 74ca02360fSXin Tong if (MDNode *D = L->getLoopID()) { 75ca02360fSXin Tong L->setLoopID(D); 76ca02360fSXin Tong loopIDFoundAndSet = true; 77ca02360fSXin Tong } 78ca02360fSXin Tong 79ca02360fSXin Tong // We must have successfully found and set the loop id in the 80ca02360fSXin Tong // only latch the loop has. 81ca02360fSXin Tong EXPECT_TRUE(loopIDFoundAndSet); 8243c1a264SXin Tong }); 83ca02360fSXin Tong } 84*f002264dSChandler Carruth 85*f002264dSChandler Carruth TEST(LoopInfoTest, PreorderTraversals) { 86*f002264dSChandler Carruth const char *ModuleStr = "define void @f() {\n" 87*f002264dSChandler Carruth "entry:\n" 88*f002264dSChandler Carruth " br label %loop.0\n" 89*f002264dSChandler Carruth "loop.0:\n" 90*f002264dSChandler Carruth " br i1 undef, label %loop.0.0, label %loop.1\n" 91*f002264dSChandler Carruth "loop.0.0:\n" 92*f002264dSChandler Carruth " br i1 undef, label %loop.0.0, label %loop.0.1\n" 93*f002264dSChandler Carruth "loop.0.1:\n" 94*f002264dSChandler Carruth " br i1 undef, label %loop.0.1, label %loop.0.2\n" 95*f002264dSChandler Carruth "loop.0.2:\n" 96*f002264dSChandler Carruth " br i1 undef, label %loop.0.2, label %loop.0\n" 97*f002264dSChandler Carruth "loop.1:\n" 98*f002264dSChandler Carruth " br i1 undef, label %loop.1.0, label %end\n" 99*f002264dSChandler Carruth "loop.1.0:\n" 100*f002264dSChandler Carruth " br i1 undef, label %loop.1.0, label %loop.1.1\n" 101*f002264dSChandler Carruth "loop.1.1:\n" 102*f002264dSChandler Carruth " br i1 undef, label %loop.1.1, label %loop.1.2\n" 103*f002264dSChandler Carruth "loop.1.2:\n" 104*f002264dSChandler Carruth " br i1 undef, label %loop.1.2, label %loop.1\n" 105*f002264dSChandler Carruth "end:\n" 106*f002264dSChandler Carruth " ret void\n" 107*f002264dSChandler Carruth "}\n"; 108*f002264dSChandler Carruth // Parse the module. 109*f002264dSChandler Carruth LLVMContext Context; 110*f002264dSChandler Carruth std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 111*f002264dSChandler Carruth Function &F = *M->begin(); 112*f002264dSChandler Carruth 113*f002264dSChandler Carruth DominatorTree DT(F); 114*f002264dSChandler Carruth LoopInfo LI; 115*f002264dSChandler Carruth LI.analyze(DT); 116*f002264dSChandler Carruth 117*f002264dSChandler Carruth Function::iterator I = F.begin(); 118*f002264dSChandler Carruth ASSERT_EQ("entry", I->getName()); 119*f002264dSChandler Carruth ++I; 120*f002264dSChandler Carruth Loop &L_0 = *LI.getLoopFor(&*I++); 121*f002264dSChandler Carruth ASSERT_EQ("loop.0", L_0.getHeader()->getName()); 122*f002264dSChandler Carruth Loop &L_0_0 = *LI.getLoopFor(&*I++); 123*f002264dSChandler Carruth ASSERT_EQ("loop.0.0", L_0_0.getHeader()->getName()); 124*f002264dSChandler Carruth Loop &L_0_1 = *LI.getLoopFor(&*I++); 125*f002264dSChandler Carruth ASSERT_EQ("loop.0.1", L_0_1.getHeader()->getName()); 126*f002264dSChandler Carruth Loop &L_0_2 = *LI.getLoopFor(&*I++); 127*f002264dSChandler Carruth ASSERT_EQ("loop.0.2", L_0_2.getHeader()->getName()); 128*f002264dSChandler Carruth Loop &L_1 = *LI.getLoopFor(&*I++); 129*f002264dSChandler Carruth ASSERT_EQ("loop.1", L_1.getHeader()->getName()); 130*f002264dSChandler Carruth Loop &L_1_0 = *LI.getLoopFor(&*I++); 131*f002264dSChandler Carruth ASSERT_EQ("loop.1.0", L_1_0.getHeader()->getName()); 132*f002264dSChandler Carruth Loop &L_1_1 = *LI.getLoopFor(&*I++); 133*f002264dSChandler Carruth ASSERT_EQ("loop.1.1", L_1_1.getHeader()->getName()); 134*f002264dSChandler Carruth Loop &L_1_2 = *LI.getLoopFor(&*I++); 135*f002264dSChandler Carruth ASSERT_EQ("loop.1.2", L_1_2.getHeader()->getName()); 136*f002264dSChandler Carruth 137*f002264dSChandler Carruth auto Preorder = LI.getLoopsInPreorder(); 138*f002264dSChandler Carruth ASSERT_EQ(8u, Preorder.size()); 139*f002264dSChandler Carruth EXPECT_EQ(&L_0, Preorder[0]); 140*f002264dSChandler Carruth EXPECT_EQ(&L_0_0, Preorder[1]); 141*f002264dSChandler Carruth EXPECT_EQ(&L_0_1, Preorder[2]); 142*f002264dSChandler Carruth EXPECT_EQ(&L_0_2, Preorder[3]); 143*f002264dSChandler Carruth EXPECT_EQ(&L_1, Preorder[4]); 144*f002264dSChandler Carruth EXPECT_EQ(&L_1_0, Preorder[5]); 145*f002264dSChandler Carruth EXPECT_EQ(&L_1_1, Preorder[6]); 146*f002264dSChandler Carruth EXPECT_EQ(&L_1_2, Preorder[7]); 147*f002264dSChandler Carruth 148*f002264dSChandler Carruth auto ReverseSiblingPreorder = LI.getLoopsInReverseSiblingPreorder(); 149*f002264dSChandler Carruth ASSERT_EQ(8u, ReverseSiblingPreorder.size()); 150*f002264dSChandler Carruth EXPECT_EQ(&L_1, ReverseSiblingPreorder[0]); 151*f002264dSChandler Carruth EXPECT_EQ(&L_1_2, ReverseSiblingPreorder[1]); 152*f002264dSChandler Carruth EXPECT_EQ(&L_1_1, ReverseSiblingPreorder[2]); 153*f002264dSChandler Carruth EXPECT_EQ(&L_1_0, ReverseSiblingPreorder[3]); 154*f002264dSChandler Carruth EXPECT_EQ(&L_0, ReverseSiblingPreorder[4]); 155*f002264dSChandler Carruth EXPECT_EQ(&L_0_2, ReverseSiblingPreorder[5]); 156*f002264dSChandler Carruth EXPECT_EQ(&L_0_1, ReverseSiblingPreorder[6]); 157*f002264dSChandler Carruth EXPECT_EQ(&L_0_0, ReverseSiblingPreorder[7]); 158*f002264dSChandler Carruth } 159