1ca02360fSXin Tong //===- LoopInfoTest.cpp - LoopInfo unit tests -----------------------------===// 2ca02360fSXin Tong // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6ca02360fSXin Tong // 7ca02360fSXin Tong //===----------------------------------------------------------------------===// 8ca02360fSXin Tong 9ca02360fSXin Tong #include "llvm/Analysis/LoopInfo.h" 102d0896c1SWhitney Tsang #include "llvm/Analysis/AssumptionCache.h" 112d0896c1SWhitney Tsang #include "llvm/Analysis/ScalarEvolution.h" 122d0896c1SWhitney Tsang #include "llvm/Analysis/TargetLibraryInfo.h" 13ca02360fSXin Tong #include "llvm/AsmParser/Parser.h" 14*71c3a551Sserge-sans-paille #include "llvm/IR/Constants.h" 15ca02360fSXin Tong #include "llvm/IR/Dominators.h" 16ca02360fSXin Tong #include "llvm/Support/SourceMgr.h" 17ca02360fSXin Tong #include "gtest/gtest.h" 18ca02360fSXin Tong 19ca02360fSXin Tong using namespace llvm; 20ca02360fSXin Tong 2143c1a264SXin Tong /// Build the loop info for the function and run the Test. 2243c1a264SXin Tong static void 2343c1a264SXin Tong runWithLoopInfo(Module &M, StringRef FuncName, 2443c1a264SXin Tong function_ref<void(Function &F, LoopInfo &LI)> Test) { 2543c1a264SXin Tong auto *F = M.getFunction(FuncName); 2643c1a264SXin Tong ASSERT_NE(F, nullptr) << "Could not find " << FuncName; 2743c1a264SXin Tong // Compute the dominator tree and the loop info for the function. 2843c1a264SXin Tong DominatorTree DT(*F); 2943c1a264SXin Tong LoopInfo LI(DT); 3043c1a264SXin Tong Test(*F, LI); 3143c1a264SXin Tong } 3243c1a264SXin Tong 332d0896c1SWhitney Tsang /// Build the loop info and scalar evolution for the function and run the Test. 342d0896c1SWhitney Tsang static void runWithLoopInfoPlus( 352d0896c1SWhitney Tsang Module &M, StringRef FuncName, 368ee361ebSWhitney Tsang function_ref<void(Function &F, LoopInfo &LI, ScalarEvolution &SE)> Test) { 372d0896c1SWhitney Tsang auto *F = M.getFunction(FuncName); 382d0896c1SWhitney Tsang ASSERT_NE(F, nullptr) << "Could not find " << FuncName; 392d0896c1SWhitney Tsang 402d0896c1SWhitney Tsang TargetLibraryInfoImpl TLII; 412d0896c1SWhitney Tsang TargetLibraryInfo TLI(TLII); 422d0896c1SWhitney Tsang AssumptionCache AC(*F); 432d0896c1SWhitney Tsang DominatorTree DT(*F); 442d0896c1SWhitney Tsang LoopInfo LI(DT); 452d0896c1SWhitney Tsang ScalarEvolution SE(*F, TLI, AC, DT, LI); 468ee361ebSWhitney Tsang Test(*F, LI, SE); 472d0896c1SWhitney Tsang } 482d0896c1SWhitney Tsang 49ca02360fSXin Tong static std::unique_ptr<Module> makeLLVMModule(LLVMContext &Context, 50ca02360fSXin Tong const char *ModuleStr) { 51ca02360fSXin Tong SMDiagnostic Err; 52ca02360fSXin Tong return parseAssemblyString(ModuleStr, Err, Context); 53ca02360fSXin Tong } 54ca02360fSXin Tong 55ca02360fSXin Tong // This tests that for a loop with a single latch, we get the loop id from 56ca02360fSXin Tong // its only latch, even in case the loop may not be in a simplified form. 57ca02360fSXin Tong TEST(LoopInfoTest, LoopWithSingleLatch) { 58ca02360fSXin Tong const char *ModuleStr = 59ca02360fSXin Tong "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n" 60ca02360fSXin Tong "define void @foo(i32 %n) {\n" 61ca02360fSXin Tong "entry:\n" 62ca02360fSXin Tong " br i1 undef, label %for.cond, label %for.end\n" 63ca02360fSXin Tong "for.cond:\n" 64ca02360fSXin Tong " %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]\n" 65ca02360fSXin Tong " %cmp = icmp slt i32 %i.0, %n\n" 66ca02360fSXin Tong " br i1 %cmp, label %for.inc, label %for.end\n" 67ca02360fSXin Tong "for.inc:\n" 68ca02360fSXin Tong " %inc = add nsw i32 %i.0, 1\n" 69ca02360fSXin Tong " br label %for.cond, !llvm.loop !0\n" 70ca02360fSXin Tong "for.end:\n" 71ca02360fSXin Tong " ret void\n" 72ca02360fSXin Tong "}\n" 73ca02360fSXin Tong "!0 = distinct !{!0, !1}\n" 74ca02360fSXin Tong "!1 = !{!\"llvm.loop.distribute.enable\", i1 true}\n"; 75ca02360fSXin Tong 76ca02360fSXin Tong // Parse the module. 77ca02360fSXin Tong LLVMContext Context; 78ca02360fSXin Tong std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 79ca02360fSXin Tong 8043c1a264SXin Tong runWithLoopInfo(*M, "foo", [&](Function &F, LoopInfo &LI) { 81ca02360fSXin Tong Function::iterator FI = F.begin(); 8243c1a264SXin Tong // First basic block is entry - skip it. 8343c1a264SXin Tong BasicBlock *Header = &*(++FI); 84ca02360fSXin Tong assert(Header->getName() == "for.cond"); 85ca02360fSXin Tong Loop *L = LI.getLoopFor(Header); 86ca02360fSXin Tong 87ca02360fSXin Tong // This loop is not in simplified form. 88ca02360fSXin Tong EXPECT_FALSE(L->isLoopSimplifyForm()); 89ca02360fSXin Tong 90ca02360fSXin Tong // Analyze the loop metadata id. 91ca02360fSXin Tong bool loopIDFoundAndSet = false; 92ca02360fSXin Tong // Try to get and set the metadata id for the loop. 93ca02360fSXin Tong if (MDNode *D = L->getLoopID()) { 94ca02360fSXin Tong L->setLoopID(D); 95ca02360fSXin Tong loopIDFoundAndSet = true; 96ca02360fSXin Tong } 97ca02360fSXin Tong 98ca02360fSXin Tong // We must have successfully found and set the loop id in the 99ca02360fSXin Tong // only latch the loop has. 100ca02360fSXin Tong EXPECT_TRUE(loopIDFoundAndSet); 10143c1a264SXin Tong }); 102ca02360fSXin Tong } 103f002264dSChandler Carruth 104a58e9214SJohannes Doerfert // Test loop id handling for a loop with multiple latches. 105a58e9214SJohannes Doerfert TEST(LoopInfoTest, LoopWithMultipleLatches) { 106a58e9214SJohannes Doerfert const char *ModuleStr = 107a58e9214SJohannes Doerfert "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n" 108a58e9214SJohannes Doerfert "define void @foo(i32 %n) {\n" 109a58e9214SJohannes Doerfert "entry:\n" 110a58e9214SJohannes Doerfert " br i1 undef, label %for.cond, label %for.end\n" 111a58e9214SJohannes Doerfert "for.cond:\n" 112a58e9214SJohannes Doerfert " %i.0 = phi i32 [ 0, %entry ], [ %inc, %latch.1 ], [ %inc, %latch.2 ]\n" 113a58e9214SJohannes Doerfert " %inc = add nsw i32 %i.0, 1\n" 114a58e9214SJohannes Doerfert " %cmp = icmp slt i32 %i.0, %n\n" 115a58e9214SJohannes Doerfert " br i1 %cmp, label %latch.1, label %for.end\n" 116a58e9214SJohannes Doerfert "latch.1:\n" 117a58e9214SJohannes Doerfert " br i1 undef, label %for.cond, label %latch.2, !llvm.loop !0\n" 118a58e9214SJohannes Doerfert "latch.2:\n" 119a58e9214SJohannes Doerfert " br label %for.cond, !llvm.loop !0\n" 120a58e9214SJohannes Doerfert "for.end:\n" 121a58e9214SJohannes Doerfert " ret void\n" 122a58e9214SJohannes Doerfert "}\n" 123a58e9214SJohannes Doerfert "!0 = distinct !{!0, !1}\n" 124a58e9214SJohannes Doerfert "!1 = !{!\"llvm.loop.distribute.enable\", i1 true}\n"; 125a58e9214SJohannes Doerfert 126a58e9214SJohannes Doerfert // Parse the module. 127a58e9214SJohannes Doerfert LLVMContext Context; 128a58e9214SJohannes Doerfert std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 129a58e9214SJohannes Doerfert 130a58e9214SJohannes Doerfert runWithLoopInfo(*M, "foo", [&](Function &F, LoopInfo &LI) { 131a58e9214SJohannes Doerfert Function::iterator FI = F.begin(); 132a58e9214SJohannes Doerfert // First basic block is entry - skip it. 133a58e9214SJohannes Doerfert BasicBlock *Header = &*(++FI); 134a58e9214SJohannes Doerfert assert(Header->getName() == "for.cond"); 135a58e9214SJohannes Doerfert Loop *L = LI.getLoopFor(Header); 136a58e9214SJohannes Doerfert EXPECT_NE(L, nullptr); 137a58e9214SJohannes Doerfert 138a58e9214SJohannes Doerfert // This loop is not in simplified form. 139a58e9214SJohannes Doerfert EXPECT_FALSE(L->isLoopSimplifyForm()); 140a58e9214SJohannes Doerfert 141a58e9214SJohannes Doerfert // Try to get and set the metadata id for the loop. 142a58e9214SJohannes Doerfert MDNode *OldLoopID = L->getLoopID(); 143a58e9214SJohannes Doerfert EXPECT_NE(OldLoopID, nullptr); 144a58e9214SJohannes Doerfert 145a58e9214SJohannes Doerfert MDNode *NewLoopID = MDNode::get(Context, {nullptr}); 146a58e9214SJohannes Doerfert // Set operand 0 to refer to the loop id itself. 147a58e9214SJohannes Doerfert NewLoopID->replaceOperandWith(0, NewLoopID); 148a58e9214SJohannes Doerfert 149a58e9214SJohannes Doerfert L->setLoopID(NewLoopID); 150a58e9214SJohannes Doerfert EXPECT_EQ(L->getLoopID(), NewLoopID); 151a58e9214SJohannes Doerfert EXPECT_NE(L->getLoopID(), OldLoopID); 152a58e9214SJohannes Doerfert 153a58e9214SJohannes Doerfert L->setLoopID(OldLoopID); 154a58e9214SJohannes Doerfert EXPECT_EQ(L->getLoopID(), OldLoopID); 155a58e9214SJohannes Doerfert EXPECT_NE(L->getLoopID(), NewLoopID); 156a58e9214SJohannes Doerfert }); 157a58e9214SJohannes Doerfert } 158a58e9214SJohannes Doerfert 159f002264dSChandler Carruth TEST(LoopInfoTest, PreorderTraversals) { 160f002264dSChandler Carruth const char *ModuleStr = "define void @f() {\n" 161f002264dSChandler Carruth "entry:\n" 162f002264dSChandler Carruth " br label %loop.0\n" 163f002264dSChandler Carruth "loop.0:\n" 164f002264dSChandler Carruth " br i1 undef, label %loop.0.0, label %loop.1\n" 165f002264dSChandler Carruth "loop.0.0:\n" 166f002264dSChandler Carruth " br i1 undef, label %loop.0.0, label %loop.0.1\n" 167f002264dSChandler Carruth "loop.0.1:\n" 168f002264dSChandler Carruth " br i1 undef, label %loop.0.1, label %loop.0.2\n" 169f002264dSChandler Carruth "loop.0.2:\n" 170f002264dSChandler Carruth " br i1 undef, label %loop.0.2, label %loop.0\n" 171f002264dSChandler Carruth "loop.1:\n" 172f002264dSChandler Carruth " br i1 undef, label %loop.1.0, label %end\n" 173f002264dSChandler Carruth "loop.1.0:\n" 174f002264dSChandler Carruth " br i1 undef, label %loop.1.0, label %loop.1.1\n" 175f002264dSChandler Carruth "loop.1.1:\n" 176f002264dSChandler Carruth " br i1 undef, label %loop.1.1, label %loop.1.2\n" 177f002264dSChandler Carruth "loop.1.2:\n" 178f002264dSChandler Carruth " br i1 undef, label %loop.1.2, label %loop.1\n" 179f002264dSChandler Carruth "end:\n" 180f002264dSChandler Carruth " ret void\n" 181f002264dSChandler Carruth "}\n"; 182f002264dSChandler Carruth // Parse the module. 183f002264dSChandler Carruth LLVMContext Context; 184f002264dSChandler Carruth std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 185f002264dSChandler Carruth Function &F = *M->begin(); 186f002264dSChandler Carruth 187f002264dSChandler Carruth DominatorTree DT(F); 188f002264dSChandler Carruth LoopInfo LI; 189f002264dSChandler Carruth LI.analyze(DT); 190f002264dSChandler Carruth 191f002264dSChandler Carruth Function::iterator I = F.begin(); 192f002264dSChandler Carruth ASSERT_EQ("entry", I->getName()); 193f002264dSChandler Carruth ++I; 194f002264dSChandler Carruth Loop &L_0 = *LI.getLoopFor(&*I++); 195f002264dSChandler Carruth ASSERT_EQ("loop.0", L_0.getHeader()->getName()); 196f002264dSChandler Carruth Loop &L_0_0 = *LI.getLoopFor(&*I++); 197f002264dSChandler Carruth ASSERT_EQ("loop.0.0", L_0_0.getHeader()->getName()); 198f002264dSChandler Carruth Loop &L_0_1 = *LI.getLoopFor(&*I++); 199f002264dSChandler Carruth ASSERT_EQ("loop.0.1", L_0_1.getHeader()->getName()); 200f002264dSChandler Carruth Loop &L_0_2 = *LI.getLoopFor(&*I++); 201f002264dSChandler Carruth ASSERT_EQ("loop.0.2", L_0_2.getHeader()->getName()); 202f002264dSChandler Carruth Loop &L_1 = *LI.getLoopFor(&*I++); 203f002264dSChandler Carruth ASSERT_EQ("loop.1", L_1.getHeader()->getName()); 204f002264dSChandler Carruth Loop &L_1_0 = *LI.getLoopFor(&*I++); 205f002264dSChandler Carruth ASSERT_EQ("loop.1.0", L_1_0.getHeader()->getName()); 206f002264dSChandler Carruth Loop &L_1_1 = *LI.getLoopFor(&*I++); 207f002264dSChandler Carruth ASSERT_EQ("loop.1.1", L_1_1.getHeader()->getName()); 208f002264dSChandler Carruth Loop &L_1_2 = *LI.getLoopFor(&*I++); 209f002264dSChandler Carruth ASSERT_EQ("loop.1.2", L_1_2.getHeader()->getName()); 210f002264dSChandler Carruth 211f002264dSChandler Carruth auto Preorder = LI.getLoopsInPreorder(); 212f002264dSChandler Carruth ASSERT_EQ(8u, Preorder.size()); 213f002264dSChandler Carruth EXPECT_EQ(&L_0, Preorder[0]); 214f002264dSChandler Carruth EXPECT_EQ(&L_0_0, Preorder[1]); 215f002264dSChandler Carruth EXPECT_EQ(&L_0_1, Preorder[2]); 216f002264dSChandler Carruth EXPECT_EQ(&L_0_2, Preorder[3]); 217f002264dSChandler Carruth EXPECT_EQ(&L_1, Preorder[4]); 218f002264dSChandler Carruth EXPECT_EQ(&L_1_0, Preorder[5]); 219f002264dSChandler Carruth EXPECT_EQ(&L_1_1, Preorder[6]); 220f002264dSChandler Carruth EXPECT_EQ(&L_1_2, Preorder[7]); 221f002264dSChandler Carruth 222f002264dSChandler Carruth auto ReverseSiblingPreorder = LI.getLoopsInReverseSiblingPreorder(); 223f002264dSChandler Carruth ASSERT_EQ(8u, ReverseSiblingPreorder.size()); 224f002264dSChandler Carruth EXPECT_EQ(&L_1, ReverseSiblingPreorder[0]); 225f002264dSChandler Carruth EXPECT_EQ(&L_1_2, ReverseSiblingPreorder[1]); 226f002264dSChandler Carruth EXPECT_EQ(&L_1_1, ReverseSiblingPreorder[2]); 227f002264dSChandler Carruth EXPECT_EQ(&L_1_0, ReverseSiblingPreorder[3]); 228f002264dSChandler Carruth EXPECT_EQ(&L_0, ReverseSiblingPreorder[4]); 229f002264dSChandler Carruth EXPECT_EQ(&L_0_2, ReverseSiblingPreorder[5]); 230f002264dSChandler Carruth EXPECT_EQ(&L_0_1, ReverseSiblingPreorder[6]); 231f002264dSChandler Carruth EXPECT_EQ(&L_0_0, ReverseSiblingPreorder[7]); 232f002264dSChandler Carruth } 2332d0896c1SWhitney Tsang 2342d0896c1SWhitney Tsang TEST(LoopInfoTest, CanonicalLoop) { 2352d0896c1SWhitney Tsang const char *ModuleStr = 2362d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 2372d0896c1SWhitney Tsang "entry:\n" 2382d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 2392d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 2402d0896c1SWhitney Tsang "for.preheader:\n" 2412d0896c1SWhitney Tsang " br label %for.body\n" 2422d0896c1SWhitney Tsang "for.body:\n" 2432d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 2442d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 2452d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 2462d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 2472d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 2482d0896c1SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 2492d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 2502d0896c1SWhitney Tsang "for.exit:\n" 2512d0896c1SWhitney Tsang " br label %for.end\n" 2522d0896c1SWhitney Tsang "for.end:\n" 2532d0896c1SWhitney Tsang " ret void\n" 2542d0896c1SWhitney Tsang "}\n"; 2552d0896c1SWhitney Tsang 2562d0896c1SWhitney Tsang // Parse the module. 2572d0896c1SWhitney Tsang LLVMContext Context; 2582d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 2592d0896c1SWhitney Tsang 2602d0896c1SWhitney Tsang runWithLoopInfoPlus( 2612d0896c1SWhitney Tsang *M, "foo", 2628ee361ebSWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) { 2632d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 2648ee361ebSWhitney Tsang BasicBlock *Entry = &*(FI); 2658ee361ebSWhitney Tsang BranchInst *Guard = dyn_cast<BranchInst>(Entry->getTerminator()); 2662d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 2672d0896c1SWhitney Tsang ++FI; 2682d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 2692d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 2702d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 2712d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 2722d0896c1SWhitney Tsang 2732d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 2742d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 2752d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 2762d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 2772d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 2782d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 2792d0896c1SWhitney Tsang ConstantInt *StepValue = 2802d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 2812d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 2822d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 2832d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 2842d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 2852d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 2862d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 2878ee361ebSWhitney Tsang EXPECT_EQ(L->getLoopGuardBranch(), Guard); 2888ee361ebSWhitney Tsang EXPECT_TRUE(L->isGuarded()); 28961368c8eSKit Barton EXPECT_TRUE(L->isRotatedForm()); 2902d0896c1SWhitney Tsang }); 2912d0896c1SWhitney Tsang } 2922d0896c1SWhitney Tsang 2932d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopWithInverseGuardSuccs) { 2942d0896c1SWhitney Tsang const char *ModuleStr = 2952d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 2962d0896c1SWhitney Tsang "entry:\n" 2972d0896c1SWhitney Tsang " %guardcmp = icmp sge i32 0, %ub\n" 2982d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.end, label %for.preheader\n" 2992d0896c1SWhitney Tsang "for.preheader:\n" 3002d0896c1SWhitney Tsang " br label %for.body\n" 3012d0896c1SWhitney Tsang "for.body:\n" 3022d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 3032d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 3042d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 3052d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 3062d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 3072d0896c1SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 3082d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 3092d0896c1SWhitney Tsang "for.exit:\n" 3102d0896c1SWhitney Tsang " br label %for.end\n" 3112d0896c1SWhitney Tsang "for.end:\n" 3122d0896c1SWhitney Tsang " ret void\n" 3132d0896c1SWhitney Tsang "}\n"; 3142d0896c1SWhitney Tsang 3152d0896c1SWhitney Tsang // Parse the module. 3162d0896c1SWhitney Tsang LLVMContext Context; 3172d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 3182d0896c1SWhitney Tsang 3192d0896c1SWhitney Tsang runWithLoopInfoPlus( 3202d0896c1SWhitney Tsang *M, "foo", 3218ee361ebSWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) { 3222d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 3238ee361ebSWhitney Tsang BasicBlock *Entry = &*(FI); 3248ee361ebSWhitney Tsang BranchInst *Guard = dyn_cast<BranchInst>(Entry->getTerminator()); 3252d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 3262d0896c1SWhitney Tsang ++FI; 3272d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 3282d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 3292d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 3302d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 3312d0896c1SWhitney Tsang 3322d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 3332d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 3342d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 3352d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 3362d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 3372d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 3382d0896c1SWhitney Tsang ConstantInt *StepValue = 3392d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 3402d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 3412d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 3422d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 3432d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 3442d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 3452d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 3468ee361ebSWhitney Tsang EXPECT_EQ(L->getLoopGuardBranch(), Guard); 3478ee361ebSWhitney Tsang EXPECT_TRUE(L->isGuarded()); 34861368c8eSKit Barton EXPECT_TRUE(L->isRotatedForm()); 3492d0896c1SWhitney Tsang }); 3502d0896c1SWhitney Tsang } 3512d0896c1SWhitney Tsang 3522d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopWithSwappedGuardCmp) { 3532d0896c1SWhitney Tsang const char *ModuleStr = 3542d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 3552d0896c1SWhitney Tsang "entry:\n" 3562d0896c1SWhitney Tsang " %guardcmp = icmp sgt i32 %ub, 0\n" 3572d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 3582d0896c1SWhitney Tsang "for.preheader:\n" 3592d0896c1SWhitney Tsang " br label %for.body\n" 3602d0896c1SWhitney Tsang "for.body:\n" 3612d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 3622d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 3632d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 3642d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 3652d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 3662d0896c1SWhitney Tsang " %cmp = icmp sge i32 %inc, %ub\n" 3672d0896c1SWhitney Tsang " br i1 %cmp, label %for.exit, label %for.body\n" 3682d0896c1SWhitney Tsang "for.exit:\n" 3692d0896c1SWhitney Tsang " br label %for.end\n" 3702d0896c1SWhitney Tsang "for.end:\n" 3712d0896c1SWhitney Tsang " ret void\n" 3722d0896c1SWhitney Tsang "}\n"; 3732d0896c1SWhitney Tsang 3742d0896c1SWhitney Tsang // Parse the module. 3752d0896c1SWhitney Tsang LLVMContext Context; 3762d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 3772d0896c1SWhitney Tsang 3782d0896c1SWhitney Tsang runWithLoopInfoPlus( 3792d0896c1SWhitney Tsang *M, "foo", 3808ee361ebSWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) { 3812d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 3828ee361ebSWhitney Tsang BasicBlock *Entry = &*(FI); 3838ee361ebSWhitney Tsang BranchInst *Guard = dyn_cast<BranchInst>(Entry->getTerminator()); 3842d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 3852d0896c1SWhitney Tsang ++FI; 3862d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 3872d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 3882d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 3892d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 3902d0896c1SWhitney Tsang 3912d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 3922d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 3932d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 3942d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 3952d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 3962d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 3972d0896c1SWhitney Tsang ConstantInt *StepValue = 3982d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 3992d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 4002d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 4012d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 4022d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 4032d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 4042d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 4058ee361ebSWhitney Tsang EXPECT_EQ(L->getLoopGuardBranch(), Guard); 4068ee361ebSWhitney Tsang EXPECT_TRUE(L->isGuarded()); 40761368c8eSKit Barton EXPECT_TRUE(L->isRotatedForm()); 4082d0896c1SWhitney Tsang }); 4092d0896c1SWhitney Tsang } 4102d0896c1SWhitney Tsang 4112d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopWithInverseLatchSuccs) { 4122d0896c1SWhitney Tsang const char *ModuleStr = 4132d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 4142d0896c1SWhitney Tsang "entry:\n" 4152d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 4162d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 4172d0896c1SWhitney Tsang "for.preheader:\n" 4182d0896c1SWhitney Tsang " br label %for.body\n" 4192d0896c1SWhitney Tsang "for.body:\n" 4202d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 4212d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 4222d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 4232d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 4242d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 4252d0896c1SWhitney Tsang " %cmp = icmp sge i32 %inc, %ub\n" 4262d0896c1SWhitney Tsang " br i1 %cmp, label %for.exit, label %for.body\n" 4272d0896c1SWhitney Tsang "for.exit:\n" 4282d0896c1SWhitney Tsang " br label %for.end\n" 4292d0896c1SWhitney Tsang "for.end:\n" 4302d0896c1SWhitney Tsang " ret void\n" 4312d0896c1SWhitney Tsang "}\n"; 4322d0896c1SWhitney Tsang 4332d0896c1SWhitney Tsang // Parse the module. 4342d0896c1SWhitney Tsang LLVMContext Context; 4352d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 4362d0896c1SWhitney Tsang 4372d0896c1SWhitney Tsang runWithLoopInfoPlus( 4382d0896c1SWhitney Tsang *M, "foo", 4398ee361ebSWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) { 4402d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 4418ee361ebSWhitney Tsang BasicBlock *Entry = &*(FI); 4428ee361ebSWhitney Tsang BranchInst *Guard = dyn_cast<BranchInst>(Entry->getTerminator()); 4432d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 4442d0896c1SWhitney Tsang ++FI; 4452d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 4462d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 4472d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 4482d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 4492d0896c1SWhitney Tsang 4502d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 4512d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 4522d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 4532d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 4542d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 4552d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 4562d0896c1SWhitney Tsang ConstantInt *StepValue = 4572d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 4582d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 4592d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 4602d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 4612d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 4622d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 4632d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 4648ee361ebSWhitney Tsang EXPECT_EQ(L->getLoopGuardBranch(), Guard); 4658ee361ebSWhitney Tsang EXPECT_TRUE(L->isGuarded()); 46661368c8eSKit Barton EXPECT_TRUE(L->isRotatedForm()); 4672d0896c1SWhitney Tsang }); 4682d0896c1SWhitney Tsang } 4692d0896c1SWhitney Tsang 4702d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopWithLatchCmpNE) { 4712d0896c1SWhitney Tsang const char *ModuleStr = 4722d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 4732d0896c1SWhitney Tsang "entry:\n" 4742d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 4752d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 4762d0896c1SWhitney Tsang "for.preheader:\n" 4772d0896c1SWhitney Tsang " br label %for.body\n" 4782d0896c1SWhitney Tsang "for.body:\n" 4792d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 4802d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 4812d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 4822d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 4832d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 4842d0896c1SWhitney Tsang " %cmp = icmp ne i32 %i, %ub\n" 4852d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 4862d0896c1SWhitney Tsang "for.exit:\n" 4872d0896c1SWhitney Tsang " br label %for.end\n" 4882d0896c1SWhitney Tsang "for.end:\n" 4892d0896c1SWhitney Tsang " ret void\n" 4902d0896c1SWhitney Tsang "}\n"; 4912d0896c1SWhitney Tsang 4922d0896c1SWhitney Tsang // Parse the module. 4932d0896c1SWhitney Tsang LLVMContext Context; 4942d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 4952d0896c1SWhitney Tsang 4962d0896c1SWhitney Tsang runWithLoopInfoPlus( 4972d0896c1SWhitney Tsang *M, "foo", 4988ee361ebSWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) { 4992d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 5008ee361ebSWhitney Tsang BasicBlock *Entry = &*(FI); 5018ee361ebSWhitney Tsang BranchInst *Guard = dyn_cast<BranchInst>(Entry->getTerminator()); 5022d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 5032d0896c1SWhitney Tsang ++FI; 5042d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 5052d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 5062d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 5072d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 5082d0896c1SWhitney Tsang 5092d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 5102d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 5112d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 5122d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 5132d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 5142d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 5152d0896c1SWhitney Tsang ConstantInt *StepValue = 5162d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 5172d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 5182d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 5192d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 5202d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 5212d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 5222d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 5238ee361ebSWhitney Tsang EXPECT_EQ(L->getLoopGuardBranch(), Guard); 5248ee361ebSWhitney Tsang EXPECT_TRUE(L->isGuarded()); 52561368c8eSKit Barton EXPECT_TRUE(L->isRotatedForm()); 5262d0896c1SWhitney Tsang }); 5272d0896c1SWhitney Tsang } 5282d0896c1SWhitney Tsang 5292d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopWithGuardCmpSLE) { 5302d0896c1SWhitney Tsang const char *ModuleStr = 5312d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 5322d0896c1SWhitney Tsang "entry:\n" 5332d0896c1SWhitney Tsang " %ubPlusOne = add i32 %ub, 1\n" 5342d0896c1SWhitney Tsang " %guardcmp = icmp sle i32 0, %ub\n" 5352d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 5362d0896c1SWhitney Tsang "for.preheader:\n" 5372d0896c1SWhitney Tsang " br label %for.body\n" 5382d0896c1SWhitney Tsang "for.body:\n" 5392d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 5402d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 5412d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 5422d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 5432d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 5442d0896c1SWhitney Tsang " %cmp = icmp ne i32 %i, %ubPlusOne\n" 5452d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 5462d0896c1SWhitney Tsang "for.exit:\n" 5472d0896c1SWhitney Tsang " br label %for.end\n" 5482d0896c1SWhitney Tsang "for.end:\n" 5492d0896c1SWhitney Tsang " ret void\n" 5502d0896c1SWhitney Tsang "}\n"; 5512d0896c1SWhitney Tsang 5522d0896c1SWhitney Tsang // Parse the module. 5532d0896c1SWhitney Tsang LLVMContext Context; 5542d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 5552d0896c1SWhitney Tsang 5562d0896c1SWhitney Tsang runWithLoopInfoPlus( 5572d0896c1SWhitney Tsang *M, "foo", 5588ee361ebSWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) { 5592d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 5608ee361ebSWhitney Tsang BasicBlock *Entry = &*(FI); 5618ee361ebSWhitney Tsang BranchInst *Guard = dyn_cast<BranchInst>(Entry->getTerminator()); 5622d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 5632d0896c1SWhitney Tsang ++FI; 5642d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 5652d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 5662d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 5672d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 5682d0896c1SWhitney Tsang 5692d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 5702d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 5712d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 5722d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 5732d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 5742d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 5752d0896c1SWhitney Tsang ConstantInt *StepValue = 5762d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 5772d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 5782d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ubPlusOne"); 5792d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 5802d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 5812d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 5822d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 5838ee361ebSWhitney Tsang EXPECT_EQ(L->getLoopGuardBranch(), Guard); 5848ee361ebSWhitney Tsang EXPECT_TRUE(L->isGuarded()); 58561368c8eSKit Barton EXPECT_TRUE(L->isRotatedForm()); 5862d0896c1SWhitney Tsang }); 5872d0896c1SWhitney Tsang } 5882d0896c1SWhitney Tsang 5892d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopNonConstantStep) { 5902d0896c1SWhitney Tsang const char *ModuleStr = 5912d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub, i32 %step) {\n" 5922d0896c1SWhitney Tsang "entry:\n" 5932d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 5942d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 5952d0896c1SWhitney Tsang "for.preheader:\n" 5962d0896c1SWhitney Tsang " br label %for.body\n" 5972d0896c1SWhitney Tsang "for.body:\n" 5982d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 5992d0896c1SWhitney Tsang " %idxprom = zext i32 %i to i64\n" 6002d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 6012d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 6022d0896c1SWhitney Tsang " %inc = add nsw i32 %i, %step\n" 6032d0896c1SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 6042d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 6052d0896c1SWhitney Tsang "for.exit:\n" 6062d0896c1SWhitney Tsang " br label %for.end\n" 6072d0896c1SWhitney Tsang "for.end:\n" 6082d0896c1SWhitney Tsang " ret void\n" 6092d0896c1SWhitney Tsang "}\n"; 6102d0896c1SWhitney Tsang 6112d0896c1SWhitney Tsang // Parse the module. 6122d0896c1SWhitney Tsang LLVMContext Context; 6132d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 6142d0896c1SWhitney Tsang 6152d0896c1SWhitney Tsang runWithLoopInfoPlus( 6162d0896c1SWhitney Tsang *M, "foo", 6178ee361ebSWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) { 6182d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 6198ee361ebSWhitney Tsang BasicBlock *Entry = &*(FI); 6208ee361ebSWhitney Tsang BranchInst *Guard = dyn_cast<BranchInst>(Entry->getTerminator()); 6212d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 6222d0896c1SWhitney Tsang ++FI; 6232d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 6242d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 6252d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 6262d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 6272d0896c1SWhitney Tsang 6282d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 6292d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 6302d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 6312d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 6322d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 6332d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 6342d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepValue()->getName(), "step"); 6352d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 6362d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 6372d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), Loop::LoopBounds::Direction::Unknown); 6382d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 6398ee361ebSWhitney Tsang EXPECT_EQ(L->getLoopGuardBranch(), Guard); 6408ee361ebSWhitney Tsang EXPECT_TRUE(L->isGuarded()); 64161368c8eSKit Barton EXPECT_TRUE(L->isRotatedForm()); 6422d0896c1SWhitney Tsang }); 6432d0896c1SWhitney Tsang } 6442d0896c1SWhitney Tsang 6452d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopUnsignedBounds) { 6462d0896c1SWhitney Tsang const char *ModuleStr = 6472d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 6482d0896c1SWhitney Tsang "entry:\n" 6492d0896c1SWhitney Tsang " %guardcmp = icmp ult i32 0, %ub\n" 6502d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 6512d0896c1SWhitney Tsang "for.preheader:\n" 6522d0896c1SWhitney Tsang " br label %for.body\n" 6532d0896c1SWhitney Tsang "for.body:\n" 6542d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 6552d0896c1SWhitney Tsang " %idxprom = zext i32 %i to i64\n" 6562d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 6572d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 6582d0896c1SWhitney Tsang " %inc = add i32 %i, 1\n" 6592d0896c1SWhitney Tsang " %cmp = icmp ult i32 %inc, %ub\n" 6602d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 6612d0896c1SWhitney Tsang "for.exit:\n" 6622d0896c1SWhitney Tsang " br label %for.end\n" 6632d0896c1SWhitney Tsang "for.end:\n" 6642d0896c1SWhitney Tsang " ret void\n" 6652d0896c1SWhitney Tsang "}\n"; 6662d0896c1SWhitney Tsang 6672d0896c1SWhitney Tsang // Parse the module. 6682d0896c1SWhitney Tsang LLVMContext Context; 6692d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 6702d0896c1SWhitney Tsang 6712d0896c1SWhitney Tsang runWithLoopInfoPlus( 6722d0896c1SWhitney Tsang *M, "foo", 6738ee361ebSWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) { 6742d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 6758ee361ebSWhitney Tsang BasicBlock *Entry = &*(FI); 6768ee361ebSWhitney Tsang BranchInst *Guard = dyn_cast<BranchInst>(Entry->getTerminator()); 6772d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 6782d0896c1SWhitney Tsang ++FI; 6792d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 6802d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 6812d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 6822d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 6832d0896c1SWhitney Tsang 6842d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 6852d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 6862d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 6872d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 6882d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 6892d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 6902d0896c1SWhitney Tsang ConstantInt *StepValue = 6912d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 6922d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 6932d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 6942d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_ULT); 6952d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 6962d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 6972d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 6988ee361ebSWhitney Tsang EXPECT_EQ(L->getLoopGuardBranch(), Guard); 6998ee361ebSWhitney Tsang EXPECT_TRUE(L->isGuarded()); 70061368c8eSKit Barton EXPECT_TRUE(L->isRotatedForm()); 7012d0896c1SWhitney Tsang }); 7022d0896c1SWhitney Tsang } 7032d0896c1SWhitney Tsang 7042d0896c1SWhitney Tsang TEST(LoopInfoTest, DecreasingLoop) { 7052d0896c1SWhitney Tsang const char *ModuleStr = 7062d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 7072d0896c1SWhitney Tsang "entry:\n" 7082d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 7092d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 7102d0896c1SWhitney Tsang "for.preheader:\n" 7112d0896c1SWhitney Tsang " br label %for.body\n" 7122d0896c1SWhitney Tsang "for.body:\n" 7132d0896c1SWhitney Tsang " %i = phi i32 [ %ub, %for.preheader ], [ %inc, %for.body ]\n" 7142d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 7152d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 7162d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 7172d0896c1SWhitney Tsang " %inc = sub nsw i32 %i, 1\n" 7182d0896c1SWhitney Tsang " %cmp = icmp sgt i32 %inc, 0\n" 7192d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 7202d0896c1SWhitney Tsang "for.exit:\n" 7212d0896c1SWhitney Tsang " br label %for.end\n" 7222d0896c1SWhitney Tsang "for.end:\n" 7232d0896c1SWhitney Tsang " ret void\n" 7242d0896c1SWhitney Tsang "}\n"; 7252d0896c1SWhitney Tsang 7262d0896c1SWhitney Tsang // Parse the module. 7272d0896c1SWhitney Tsang LLVMContext Context; 7282d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 7292d0896c1SWhitney Tsang 7302d0896c1SWhitney Tsang runWithLoopInfoPlus( 7312d0896c1SWhitney Tsang *M, "foo", 7328ee361ebSWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) { 7332d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 7348ee361ebSWhitney Tsang BasicBlock *Entry = &*(FI); 7358ee361ebSWhitney Tsang BranchInst *Guard = dyn_cast<BranchInst>(Entry->getTerminator()); 7362d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 7372d0896c1SWhitney Tsang ++FI; 7382d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 7392d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 7402d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 7412d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 7422d0896c1SWhitney Tsang 7432d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 7442d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 7452d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getInitialIVValue().getName(), "ub"); 7462d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 7472d0896c1SWhitney Tsang ConstantInt *StepValue = 7482d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 7492d0896c1SWhitney Tsang EXPECT_EQ(StepValue, nullptr); 7502d0896c1SWhitney Tsang ConstantInt *FinalIVValue = 7512d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getFinalIVValue()); 7522d0896c1SWhitney Tsang EXPECT_TRUE(FinalIVValue && FinalIVValue->isZero()); 7532d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SGT); 7542d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 7552d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Decreasing); 7562d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 7578ee361ebSWhitney Tsang EXPECT_EQ(L->getLoopGuardBranch(), Guard); 7588ee361ebSWhitney Tsang EXPECT_TRUE(L->isGuarded()); 75961368c8eSKit Barton EXPECT_TRUE(L->isRotatedForm()); 7602d0896c1SWhitney Tsang }); 7612d0896c1SWhitney Tsang } 7622d0896c1SWhitney Tsang 7632d0896c1SWhitney Tsang TEST(LoopInfoTest, CannotFindDirection) { 7642d0896c1SWhitney Tsang const char *ModuleStr = 7652d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub, i32 %step) {\n" 7662d0896c1SWhitney Tsang "entry:\n" 7672d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 7682d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 7692d0896c1SWhitney Tsang "for.preheader:\n" 7702d0896c1SWhitney Tsang " br label %for.body\n" 7712d0896c1SWhitney Tsang "for.body:\n" 7722d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 7732d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 7742d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 7752d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 7762d0896c1SWhitney Tsang " %inc = add nsw i32 %i, %step\n" 7772d0896c1SWhitney Tsang " %cmp = icmp ne i32 %i, %ub\n" 7782d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 7792d0896c1SWhitney Tsang "for.exit:\n" 7802d0896c1SWhitney Tsang " br label %for.end\n" 7812d0896c1SWhitney Tsang "for.end:\n" 7822d0896c1SWhitney Tsang " ret void\n" 7832d0896c1SWhitney Tsang "}\n"; 7842d0896c1SWhitney Tsang 7852d0896c1SWhitney Tsang // Parse the module. 7862d0896c1SWhitney Tsang LLVMContext Context; 7872d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 7882d0896c1SWhitney Tsang 7898ee361ebSWhitney Tsang runWithLoopInfoPlus( 7908ee361ebSWhitney Tsang *M, "foo", 7918ee361ebSWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) { 7922d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 7938ee361ebSWhitney Tsang BasicBlock *Entry = &*(FI); 7948ee361ebSWhitney Tsang BranchInst *Guard = dyn_cast<BranchInst>(Entry->getTerminator()); 7952d0896c1SWhitney Tsang // First two basic block are entry and for.preheader 7962d0896c1SWhitney Tsang // - skip them. 7972d0896c1SWhitney Tsang ++FI; 7982d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 7992d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 8002d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 8012d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 8022d0896c1SWhitney Tsang 8032d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 8042d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 8052d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 8062d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 8072d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 8082d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 8092d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepValue()->getName(), "step"); 8102d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 8112d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), 8122d0896c1SWhitney Tsang ICmpInst::BAD_ICMP_PREDICATE); 8138ee361ebSWhitney Tsang EXPECT_EQ(Bounds->getDirection(), Loop::LoopBounds::Direction::Unknown); 8142d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 8158ee361ebSWhitney Tsang EXPECT_EQ(L->getLoopGuardBranch(), Guard); 8168ee361ebSWhitney Tsang EXPECT_TRUE(L->isGuarded()); 81761368c8eSKit Barton EXPECT_TRUE(L->isRotatedForm()); 8182d0896c1SWhitney Tsang }); 8192d0896c1SWhitney Tsang } 8202d0896c1SWhitney Tsang 8212d0896c1SWhitney Tsang TEST(LoopInfoTest, ZextIndVar) { 8222d0896c1SWhitney Tsang const char *ModuleStr = 8232d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 8242d0896c1SWhitney Tsang "entry:\n" 8252d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 8262d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 8272d0896c1SWhitney Tsang "for.preheader:\n" 8282d0896c1SWhitney Tsang " br label %for.body\n" 8292d0896c1SWhitney Tsang "for.body:\n" 8302d0896c1SWhitney Tsang " %indvars.iv = phi i64 [ 0, %for.preheader ], [ %indvars.iv.next, %for.body ]\n" 8312d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 8322d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 8332d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 8342d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 8352d0896c1SWhitney Tsang " %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n" 8362d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 8372d0896c1SWhitney Tsang " %wide.trip.count = zext i32 %ub to i64\n" 8382d0896c1SWhitney Tsang " %exitcond = icmp ne i64 %indvars.iv.next, %wide.trip.count\n" 8392d0896c1SWhitney Tsang " br i1 %exitcond, label %for.body, label %for.exit\n" 8402d0896c1SWhitney Tsang "for.exit:\n" 8412d0896c1SWhitney Tsang " br label %for.end\n" 8422d0896c1SWhitney Tsang "for.end:\n" 8432d0896c1SWhitney Tsang " ret void\n" 8442d0896c1SWhitney Tsang "}\n"; 8452d0896c1SWhitney Tsang 8462d0896c1SWhitney Tsang // Parse the module. 8472d0896c1SWhitney Tsang LLVMContext Context; 8482d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 8492d0896c1SWhitney Tsang 8502d0896c1SWhitney Tsang runWithLoopInfoPlus( 8512d0896c1SWhitney Tsang *M, "foo", 8528ee361ebSWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) { 8532d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 8548ee361ebSWhitney Tsang BasicBlock *Entry = &*(FI); 8558ee361ebSWhitney Tsang BranchInst *Guard = dyn_cast<BranchInst>(Entry->getTerminator()); 8562d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 8572d0896c1SWhitney Tsang ++FI; 8582d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 8592d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 8602d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 8612d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 8622d0896c1SWhitney Tsang 8632d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 8642d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 8652d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 8662d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 8672d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 8682d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "indvars.iv.next"); 8692d0896c1SWhitney Tsang ConstantInt *StepValue = 8702d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 8712d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 8722d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "wide.trip.count"); 8732d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_NE); 8742d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 8752d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 8762d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "indvars.iv"); 8778ee361ebSWhitney Tsang EXPECT_EQ(L->getLoopGuardBranch(), Guard); 8788ee361ebSWhitney Tsang EXPECT_TRUE(L->isGuarded()); 87961368c8eSKit Barton EXPECT_TRUE(L->isRotatedForm()); 8802d0896c1SWhitney Tsang }); 8812d0896c1SWhitney Tsang } 8822d0896c1SWhitney Tsang 8839c5fbcf9SWhitney Tsang TEST(LoopInfoTest, MultiExitingLoop) { 8849c5fbcf9SWhitney Tsang const char *ModuleStr = 8859c5fbcf9SWhitney Tsang "define void @foo(i32* %A, i32 %ub, i1 %cond) {\n" 8869c5fbcf9SWhitney Tsang "entry:\n" 8879c5fbcf9SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 8889c5fbcf9SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 8899c5fbcf9SWhitney Tsang "for.preheader:\n" 8909c5fbcf9SWhitney Tsang " br label %for.body\n" 8919c5fbcf9SWhitney Tsang "for.body:\n" 8929c5fbcf9SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body.1 ]\n" 8939c5fbcf9SWhitney Tsang " br i1 %cond, label %for.body.1, label %for.exit\n" 8949c5fbcf9SWhitney Tsang "for.body.1:\n" 8959c5fbcf9SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 8969c5fbcf9SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 8979c5fbcf9SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 8989c5fbcf9SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 8999c5fbcf9SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 9009c5fbcf9SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 9019c5fbcf9SWhitney Tsang "for.exit:\n" 9029c5fbcf9SWhitney Tsang " br label %for.end\n" 9039c5fbcf9SWhitney Tsang "for.end:\n" 9049c5fbcf9SWhitney Tsang " ret void\n" 9059c5fbcf9SWhitney Tsang "}\n"; 9069c5fbcf9SWhitney Tsang 9079c5fbcf9SWhitney Tsang // Parse the module. 9089c5fbcf9SWhitney Tsang LLVMContext Context; 9099c5fbcf9SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 9109c5fbcf9SWhitney Tsang 9119c5fbcf9SWhitney Tsang runWithLoopInfoPlus( 9129c5fbcf9SWhitney Tsang *M, "foo", 9139c5fbcf9SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) { 9149c5fbcf9SWhitney Tsang Function::iterator FI = F.begin(); 9159c5fbcf9SWhitney Tsang BasicBlock *Entry = &*(FI); 9169c5fbcf9SWhitney Tsang BranchInst *Guard = dyn_cast<BranchInst>(Entry->getTerminator()); 9179c5fbcf9SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 9189c5fbcf9SWhitney Tsang ++FI; 9199c5fbcf9SWhitney Tsang BasicBlock *Header = &*(++FI); 9209c5fbcf9SWhitney Tsang assert(Header->getName() == "for.body"); 9219c5fbcf9SWhitney Tsang Loop *L = LI.getLoopFor(Header); 9229c5fbcf9SWhitney Tsang EXPECT_NE(L, nullptr); 9239c5fbcf9SWhitney Tsang 9249c5fbcf9SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 9259c5fbcf9SWhitney Tsang EXPECT_NE(Bounds, None); 9269c5fbcf9SWhitney Tsang ConstantInt *InitialIVValue = 9279c5fbcf9SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 9289c5fbcf9SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 9299c5fbcf9SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 9309c5fbcf9SWhitney Tsang ConstantInt *StepValue = 9319c5fbcf9SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 9329c5fbcf9SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 9339c5fbcf9SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 9349c5fbcf9SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 9359c5fbcf9SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 9369c5fbcf9SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 9379c5fbcf9SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 9389c5fbcf9SWhitney Tsang EXPECT_EQ(L->getLoopGuardBranch(), Guard); 9399c5fbcf9SWhitney Tsang EXPECT_TRUE(L->isGuarded()); 9409c5fbcf9SWhitney Tsang }); 9419c5fbcf9SWhitney Tsang } 9429c5fbcf9SWhitney Tsang 9439c5fbcf9SWhitney Tsang TEST(LoopInfoTest, MultiExitLoop) { 9449c5fbcf9SWhitney Tsang const char *ModuleStr = 9459c5fbcf9SWhitney Tsang "define void @foo(i32* %A, i32 %ub, i1 %cond) {\n" 9469c5fbcf9SWhitney Tsang "entry:\n" 9479c5fbcf9SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 9489c5fbcf9SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 9499c5fbcf9SWhitney Tsang "for.preheader:\n" 9509c5fbcf9SWhitney Tsang " br label %for.body\n" 9519c5fbcf9SWhitney Tsang "for.body:\n" 9529c5fbcf9SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body.1 ]\n" 9539c5fbcf9SWhitney Tsang " br i1 %cond, label %for.body.1, label %for.exit\n" 9549c5fbcf9SWhitney Tsang "for.body.1:\n" 9559c5fbcf9SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 9569c5fbcf9SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 9579c5fbcf9SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 9589c5fbcf9SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 9599c5fbcf9SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 9609c5fbcf9SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit.1\n" 9619c5fbcf9SWhitney Tsang "for.exit:\n" 9629c5fbcf9SWhitney Tsang " br label %for.end\n" 9639c5fbcf9SWhitney Tsang "for.exit.1:\n" 9649c5fbcf9SWhitney Tsang " br label %for.end\n" 9659c5fbcf9SWhitney Tsang "for.end:\n" 9669c5fbcf9SWhitney Tsang " ret void\n" 9679c5fbcf9SWhitney Tsang "}\n"; 9689c5fbcf9SWhitney Tsang 9699c5fbcf9SWhitney Tsang // Parse the module. 9709c5fbcf9SWhitney Tsang LLVMContext Context; 9719c5fbcf9SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 9729c5fbcf9SWhitney Tsang 9739c5fbcf9SWhitney Tsang runWithLoopInfoPlus( 9749c5fbcf9SWhitney Tsang *M, "foo", 9759c5fbcf9SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) { 9769c5fbcf9SWhitney Tsang Function::iterator FI = F.begin(); 9779c5fbcf9SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 9789c5fbcf9SWhitney Tsang ++FI; 9799c5fbcf9SWhitney Tsang BasicBlock *Header = &*(++FI); 9809c5fbcf9SWhitney Tsang assert(Header->getName() == "for.body"); 9819c5fbcf9SWhitney Tsang Loop *L = LI.getLoopFor(Header); 9829c5fbcf9SWhitney Tsang EXPECT_NE(L, nullptr); 9839c5fbcf9SWhitney Tsang 9849c5fbcf9SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 9859c5fbcf9SWhitney Tsang EXPECT_NE(Bounds, None); 9869c5fbcf9SWhitney Tsang ConstantInt *InitialIVValue = 9879c5fbcf9SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 9889c5fbcf9SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 9899c5fbcf9SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 9909c5fbcf9SWhitney Tsang ConstantInt *StepValue = 9919c5fbcf9SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 9929c5fbcf9SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 9939c5fbcf9SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 9949c5fbcf9SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 9959c5fbcf9SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 9969c5fbcf9SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 9979c5fbcf9SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 9989c5fbcf9SWhitney Tsang EXPECT_EQ(L->getLoopGuardBranch(), nullptr); 9999c5fbcf9SWhitney Tsang EXPECT_FALSE(L->isGuarded()); 10009c5fbcf9SWhitney Tsang }); 10019c5fbcf9SWhitney Tsang } 10029c5fbcf9SWhitney Tsang 10032d0896c1SWhitney Tsang TEST(LoopInfoTest, UnguardedLoop) { 10042d0896c1SWhitney Tsang const char *ModuleStr = 10052d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 10062d0896c1SWhitney Tsang "entry:\n" 10072d0896c1SWhitney Tsang " br label %for.body\n" 10082d0896c1SWhitney Tsang "for.body:\n" 10092d0896c1SWhitney Tsang " %i = phi i32 [ 0, %entry ], [ %inc, %for.body ]\n" 10102d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 10112d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 10122d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 10132d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 10142d0896c1SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 10152d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 10162d0896c1SWhitney Tsang "for.exit:\n" 10172d0896c1SWhitney Tsang " br label %for.end\n" 10182d0896c1SWhitney Tsang "for.end:\n" 10192d0896c1SWhitney Tsang " ret void\n" 10202d0896c1SWhitney Tsang "}\n"; 10212d0896c1SWhitney Tsang 10222d0896c1SWhitney Tsang // Parse the module. 10232d0896c1SWhitney Tsang LLVMContext Context; 10242d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 10252d0896c1SWhitney Tsang 10262d0896c1SWhitney Tsang runWithLoopInfoPlus( 10272d0896c1SWhitney Tsang *M, "foo", 10288ee361ebSWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) { 10292d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 10302d0896c1SWhitney Tsang // First basic block is entry - skip it. 10312d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 10322d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 10332d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 10342d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 10352d0896c1SWhitney Tsang 10362d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 10372d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 10382d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 10392d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 10402d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 10412d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 10422d0896c1SWhitney Tsang ConstantInt *StepValue = 10432d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 10442d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 10452d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 10462d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 10472d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 10482d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 10492d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 10508ee361ebSWhitney Tsang EXPECT_EQ(L->getLoopGuardBranch(), nullptr); 10518ee361ebSWhitney Tsang EXPECT_FALSE(L->isGuarded()); 105261368c8eSKit Barton EXPECT_TRUE(L->isRotatedForm()); 10532d0896c1SWhitney Tsang }); 10542d0896c1SWhitney Tsang } 10552d0896c1SWhitney Tsang 10562d0896c1SWhitney Tsang TEST(LoopInfoTest, UnguardedLoopWithControlFlow) { 10572d0896c1SWhitney Tsang const char *ModuleStr = 10582d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub, i1 %cond) {\n" 10592d0896c1SWhitney Tsang "entry:\n" 10602d0896c1SWhitney Tsang " br i1 %cond, label %for.preheader, label %for.end\n" 10612d0896c1SWhitney Tsang "for.preheader:\n" 10622d0896c1SWhitney Tsang " br label %for.body\n" 10632d0896c1SWhitney Tsang "for.body:\n" 10642d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 10652d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 10662d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 10672d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 10682d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 10692d0896c1SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 10702d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 10712d0896c1SWhitney Tsang "for.exit:\n" 10722d0896c1SWhitney Tsang " br label %for.end\n" 10732d0896c1SWhitney Tsang "for.end:\n" 10742d0896c1SWhitney Tsang " ret void\n" 10752d0896c1SWhitney Tsang "}\n"; 10762d0896c1SWhitney Tsang 10772d0896c1SWhitney Tsang // Parse the module. 10782d0896c1SWhitney Tsang LLVMContext Context; 10792d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 10802d0896c1SWhitney Tsang 10812d0896c1SWhitney Tsang runWithLoopInfoPlus( 10822d0896c1SWhitney Tsang *M, "foo", 10838ee361ebSWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) { 10842d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 10858ee361ebSWhitney Tsang BasicBlock *Entry = &*(FI); 10868ee361ebSWhitney Tsang BranchInst *Guard = dyn_cast<BranchInst>(Entry->getTerminator()); 10872d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 10882d0896c1SWhitney Tsang ++FI; 10892d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 10902d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 10912d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 10922d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 10932d0896c1SWhitney Tsang 10942d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 10952d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 10962d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 10972d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 10982d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 10992d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 11002d0896c1SWhitney Tsang ConstantInt *StepValue = 11012d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 11022d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 11032d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 11042d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 11052d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 11062d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 11072d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 11088ee361ebSWhitney Tsang EXPECT_EQ(L->getLoopGuardBranch(), Guard); 11098ee361ebSWhitney Tsang EXPECT_TRUE(L->isGuarded()); 111061368c8eSKit Barton EXPECT_TRUE(L->isRotatedForm()); 11112d0896c1SWhitney Tsang }); 11122d0896c1SWhitney Tsang } 11132d0896c1SWhitney Tsang 11142d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopNest) { 11152d0896c1SWhitney Tsang const char *ModuleStr = 11162d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 11172d0896c1SWhitney Tsang "entry:\n" 11182d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 11192d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.outer.preheader, label %for.end\n" 11202d0896c1SWhitney Tsang "for.outer.preheader:\n" 11212d0896c1SWhitney Tsang " br label %for.outer\n" 11222d0896c1SWhitney Tsang "for.outer:\n" 11232d0896c1SWhitney Tsang " %j = phi i32 [ 0, %for.outer.preheader ], [ %inc.outer, %for.outer.latch ]\n" 11242d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.inner.preheader, label %for.outer.latch\n" 11252d0896c1SWhitney Tsang "for.inner.preheader:\n" 11262d0896c1SWhitney Tsang " br label %for.inner\n" 11272d0896c1SWhitney Tsang "for.inner:\n" 11282d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.inner.preheader ], [ %inc, %for.inner ]\n" 11292d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 11302d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 11312d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 11322d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 11332d0896c1SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 11342d0896c1SWhitney Tsang " br i1 %cmp, label %for.inner, label %for.inner.exit\n" 11352d0896c1SWhitney Tsang "for.inner.exit:\n" 11362d0896c1SWhitney Tsang " br label %for.outer.latch\n" 11372d0896c1SWhitney Tsang "for.outer.latch:\n" 11382d0896c1SWhitney Tsang " %inc.outer = add nsw i32 %j, 1\n" 11392d0896c1SWhitney Tsang " %cmp.outer = icmp slt i32 %inc.outer, %ub\n" 11402d0896c1SWhitney Tsang " br i1 %cmp.outer, label %for.outer, label %for.outer.exit\n" 11412d0896c1SWhitney Tsang "for.outer.exit:\n" 11422d0896c1SWhitney Tsang " br label %for.end\n" 11432d0896c1SWhitney Tsang "for.end:\n" 11442d0896c1SWhitney Tsang " ret void\n" 11452d0896c1SWhitney Tsang "}\n"; 11462d0896c1SWhitney Tsang 11472d0896c1SWhitney Tsang // Parse the module. 11482d0896c1SWhitney Tsang LLVMContext Context; 11492d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 11502d0896c1SWhitney Tsang 11512d0896c1SWhitney Tsang runWithLoopInfoPlus( 11522d0896c1SWhitney Tsang *M, "foo", 11538ee361ebSWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) { 11542d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 11558ee361ebSWhitney Tsang BasicBlock *Entry = &*(FI); 11568ee361ebSWhitney Tsang BranchInst *OuterGuard = dyn_cast<BranchInst>(Entry->getTerminator()); 11572d0896c1SWhitney Tsang // First two basic block are entry and for.outer.preheader - skip them. 11582d0896c1SWhitney Tsang ++FI; 11592d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 11602d0896c1SWhitney Tsang assert(Header->getName() == "for.outer"); 11618ee361ebSWhitney Tsang BranchInst *InnerGuard = dyn_cast<BranchInst>(Header->getTerminator()); 11622d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 11632d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 11642d0896c1SWhitney Tsang 11652d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 11662d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 11672d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 11682d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 11692d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 11702d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc.outer"); 11712d0896c1SWhitney Tsang ConstantInt *StepValue = 11722d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 11732d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 11742d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 11752d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 11762d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 11772d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 11782d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "j"); 11798ee361ebSWhitney Tsang EXPECT_EQ(L->getLoopGuardBranch(), OuterGuard); 11808ee361ebSWhitney Tsang EXPECT_TRUE(L->isGuarded()); 118161368c8eSKit Barton EXPECT_TRUE(L->isRotatedForm()); 11822d0896c1SWhitney Tsang 11832d0896c1SWhitney Tsang // Next two basic blocks are for.outer and for.inner.preheader - skip 11842d0896c1SWhitney Tsang // them. 11852d0896c1SWhitney Tsang ++FI; 11862d0896c1SWhitney Tsang Header = &*(++FI); 11872d0896c1SWhitney Tsang assert(Header->getName() == "for.inner"); 11882d0896c1SWhitney Tsang L = LI.getLoopFor(Header); 11892d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 11902d0896c1SWhitney Tsang 11912d0896c1SWhitney Tsang Optional<Loop::LoopBounds> InnerBounds = L->getBounds(SE); 11922d0896c1SWhitney Tsang EXPECT_NE(InnerBounds, None); 11932d0896c1SWhitney Tsang InitialIVValue = 11942d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&InnerBounds->getInitialIVValue()); 11952d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 11962d0896c1SWhitney Tsang EXPECT_EQ(InnerBounds->getStepInst().getName(), "inc"); 11972d0896c1SWhitney Tsang StepValue = dyn_cast_or_null<ConstantInt>(InnerBounds->getStepValue()); 11982d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 11992d0896c1SWhitney Tsang EXPECT_EQ(InnerBounds->getFinalIVValue().getName(), "ub"); 12002d0896c1SWhitney Tsang EXPECT_EQ(InnerBounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 12012d0896c1SWhitney Tsang EXPECT_EQ(InnerBounds->getDirection(), 12022d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 12032d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 12048ee361ebSWhitney Tsang EXPECT_EQ(L->getLoopGuardBranch(), InnerGuard); 12058ee361ebSWhitney Tsang EXPECT_TRUE(L->isGuarded()); 120661368c8eSKit Barton EXPECT_TRUE(L->isRotatedForm()); 12072d0896c1SWhitney Tsang }); 12082d0896c1SWhitney Tsang } 12092d0896c1SWhitney Tsang 12102d0896c1SWhitney Tsang TEST(LoopInfoTest, AuxiliaryIV) { 12112d0896c1SWhitney Tsang const char *ModuleStr = 12122d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 12132d0896c1SWhitney Tsang "entry:\n" 12142d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 12152d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 12162d0896c1SWhitney Tsang "for.preheader:\n" 12172d0896c1SWhitney Tsang " br label %for.body\n" 12182d0896c1SWhitney Tsang "for.body:\n" 12192d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 12202d0896c1SWhitney Tsang " %aux = phi i32 [ 0, %for.preheader ], [ %auxinc, %for.body ]\n" 12212d0896c1SWhitney Tsang " %loopvariant = phi i32 [ 0, %for.preheader ], [ %loopvariantinc, %for.body ]\n" 12222d0896c1SWhitney Tsang " %usedoutside = phi i32 [ 0, %for.preheader ], [ %usedoutsideinc, %for.body ]\n" 12232d0896c1SWhitney Tsang " %mulopcode = phi i32 [ 0, %for.preheader ], [ %mulopcodeinc, %for.body ]\n" 12242d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 12252d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 12262d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 12272d0896c1SWhitney Tsang " %mulopcodeinc = mul nsw i32 %mulopcode, 5\n" 12282d0896c1SWhitney Tsang " %usedoutsideinc = add nsw i32 %usedoutside, 5\n" 12292d0896c1SWhitney Tsang " %loopvariantinc = add nsw i32 %loopvariant, %i\n" 12302d0896c1SWhitney Tsang " %auxinc = add nsw i32 %aux, 5\n" 12312d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 12322d0896c1SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 12332d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 12342d0896c1SWhitney Tsang "for.exit:\n" 12352d0896c1SWhitney Tsang " %lcssa = phi i32 [ %usedoutside, %for.body ]\n" 12362d0896c1SWhitney Tsang " br label %for.end\n" 12372d0896c1SWhitney Tsang "for.end:\n" 12382d0896c1SWhitney Tsang " ret void\n" 12392d0896c1SWhitney Tsang "}\n"; 12402d0896c1SWhitney Tsang 12412d0896c1SWhitney Tsang // Parse the module. 12422d0896c1SWhitney Tsang LLVMContext Context; 12432d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 12442d0896c1SWhitney Tsang 12452d0896c1SWhitney Tsang runWithLoopInfoPlus( 12462d0896c1SWhitney Tsang *M, "foo", 12478ee361ebSWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) { 12482d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 12498ee361ebSWhitney Tsang BasicBlock *Entry = &*(FI); 12508ee361ebSWhitney Tsang BranchInst *Guard = dyn_cast<BranchInst>(Entry->getTerminator()); 12512d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 12522d0896c1SWhitney Tsang ++FI; 12532d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 12542d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 12552d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 12562d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 12572d0896c1SWhitney Tsang 12582d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 12592d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 12602d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 12612d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 12622d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 12632d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 12642d0896c1SWhitney Tsang ConstantInt *StepValue = 12652d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 12662d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 12672d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 12682d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 12692d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 12702d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 12712d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 12722d0896c1SWhitney Tsang BasicBlock::iterator II = Header->begin(); 12732d0896c1SWhitney Tsang PHINode &Instruction_i = cast<PHINode>(*(II)); 12742d0896c1SWhitney Tsang EXPECT_TRUE(L->isAuxiliaryInductionVariable(Instruction_i, SE)); 12752d0896c1SWhitney Tsang PHINode &Instruction_aux = cast<PHINode>(*(++II)); 12762d0896c1SWhitney Tsang EXPECT_TRUE(L->isAuxiliaryInductionVariable(Instruction_aux, SE)); 12772d0896c1SWhitney Tsang PHINode &Instruction_loopvariant = cast<PHINode>(*(++II)); 12782d0896c1SWhitney Tsang EXPECT_FALSE( 12792d0896c1SWhitney Tsang L->isAuxiliaryInductionVariable(Instruction_loopvariant, SE)); 12802d0896c1SWhitney Tsang PHINode &Instruction_usedoutside = cast<PHINode>(*(++II)); 12812d0896c1SWhitney Tsang EXPECT_FALSE( 12822d0896c1SWhitney Tsang L->isAuxiliaryInductionVariable(Instruction_usedoutside, SE)); 12832d0896c1SWhitney Tsang PHINode &Instruction_mulopcode = cast<PHINode>(*(++II)); 12842d0896c1SWhitney Tsang EXPECT_FALSE( 12852d0896c1SWhitney Tsang L->isAuxiliaryInductionVariable(Instruction_mulopcode, SE)); 12868ee361ebSWhitney Tsang EXPECT_EQ(L->getLoopGuardBranch(), Guard); 12878ee361ebSWhitney Tsang EXPECT_TRUE(L->isGuarded()); 128861368c8eSKit Barton EXPECT_TRUE(L->isRotatedForm()); 12892d0896c1SWhitney Tsang }); 12902d0896c1SWhitney Tsang } 1291f1ee04c4SSerguei Katkov 1292dcb75bf8SWhitney Tsang TEST(LoopInfoTest, LoopNotInSimplifyForm) { 1293dcb75bf8SWhitney Tsang const char *ModuleStr = 1294dcb75bf8SWhitney Tsang "define void @foo(i32 %n) {\n" 1295dcb75bf8SWhitney Tsang "entry:\n" 1296dcb75bf8SWhitney Tsang " %guard.cmp = icmp sgt i32 %n, 0\n" 1297dcb75bf8SWhitney Tsang " br i1 %guard.cmp, label %for.cond, label %for.end\n" 1298dcb75bf8SWhitney Tsang "for.cond:\n" 1299dcb75bf8SWhitney Tsang " %i.0 = phi i32 [ 0, %entry ], [ %inc, %latch.1 ], [ %inc, %latch.2 ]\n" 1300dcb75bf8SWhitney Tsang " %inc = add nsw i32 %i.0, 1\n" 1301dcb75bf8SWhitney Tsang " %cmp = icmp slt i32 %i.0, %n\n" 1302dcb75bf8SWhitney Tsang " br i1 %cmp, label %latch.1, label %for.end\n" 1303dcb75bf8SWhitney Tsang "latch.1:\n" 1304dcb75bf8SWhitney Tsang " br i1 undef, label %for.cond, label %latch.2\n" 1305dcb75bf8SWhitney Tsang "latch.2:\n" 1306dcb75bf8SWhitney Tsang " br label %for.cond\n" 1307dcb75bf8SWhitney Tsang "for.end:\n" 1308dcb75bf8SWhitney Tsang " ret void\n" 1309dcb75bf8SWhitney Tsang "}\n"; 1310dcb75bf8SWhitney Tsang 1311dcb75bf8SWhitney Tsang // Parse the module. 1312dcb75bf8SWhitney Tsang LLVMContext Context; 1313dcb75bf8SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 1314dcb75bf8SWhitney Tsang 1315dcb75bf8SWhitney Tsang runWithLoopInfo(*M, "foo", [&](Function &F, LoopInfo &LI) { 1316dcb75bf8SWhitney Tsang Function::iterator FI = F.begin(); 1317dcb75bf8SWhitney Tsang // First basic block is entry - skip it. 1318dcb75bf8SWhitney Tsang BasicBlock *Header = &*(++FI); 1319dcb75bf8SWhitney Tsang assert(Header && "No header"); 1320dcb75bf8SWhitney Tsang Loop *L = LI.getLoopFor(Header); 1321dcb75bf8SWhitney Tsang EXPECT_NE(L, nullptr); 1322dcb75bf8SWhitney Tsang EXPECT_FALSE(L->isLoopSimplifyForm()); 1323dcb75bf8SWhitney Tsang // No loop guard because loop in not in simplify form. 1324dcb75bf8SWhitney Tsang EXPECT_EQ(L->getLoopGuardBranch(), nullptr); 1325dcb75bf8SWhitney Tsang EXPECT_FALSE(L->isGuarded()); 1326dcb75bf8SWhitney Tsang }); 1327dcb75bf8SWhitney Tsang } 1328dcb75bf8SWhitney Tsang 1329dcb75bf8SWhitney Tsang TEST(LoopInfoTest, LoopLatchNotExiting) { 1330dcb75bf8SWhitney Tsang const char *ModuleStr = 1331dcb75bf8SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 1332dcb75bf8SWhitney Tsang "entry:\n" 1333dcb75bf8SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 1334dcb75bf8SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 1335dcb75bf8SWhitney Tsang "for.preheader:\n" 1336dcb75bf8SWhitney Tsang " br label %for.body\n" 1337dcb75bf8SWhitney Tsang "for.body:\n" 1338dcb75bf8SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 1339dcb75bf8SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 1340dcb75bf8SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 1341dcb75bf8SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 1342dcb75bf8SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 1343dcb75bf8SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 1344dcb75bf8SWhitney Tsang " br i1 %cmp, label %for.latch, label %for.exit\n" 1345dcb75bf8SWhitney Tsang "for.latch:\n" 1346dcb75bf8SWhitney Tsang " br label %for.body\n" 1347dcb75bf8SWhitney Tsang "for.exit:\n" 1348dcb75bf8SWhitney Tsang " br label %for.end\n" 1349dcb75bf8SWhitney Tsang "for.end:\n" 1350dcb75bf8SWhitney Tsang " ret void\n" 1351dcb75bf8SWhitney Tsang "}\n"; 1352dcb75bf8SWhitney Tsang 1353dcb75bf8SWhitney Tsang // Parse the module. 1354dcb75bf8SWhitney Tsang LLVMContext Context; 1355dcb75bf8SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 1356dcb75bf8SWhitney Tsang 1357dcb75bf8SWhitney Tsang runWithLoopInfoPlus( 1358dcb75bf8SWhitney Tsang *M, "foo", 1359dcb75bf8SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) { 1360dcb75bf8SWhitney Tsang Function::iterator FI = F.begin(); 1361dcb75bf8SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 1362dcb75bf8SWhitney Tsang ++FI; 1363dcb75bf8SWhitney Tsang BasicBlock *Header = &*(++FI); 1364dcb75bf8SWhitney Tsang BasicBlock *Latch = &*(++FI); 1365dcb75bf8SWhitney Tsang assert(Header && "No header"); 1366dcb75bf8SWhitney Tsang Loop *L = LI.getLoopFor(Header); 1367dcb75bf8SWhitney Tsang EXPECT_NE(L, nullptr); 1368dcb75bf8SWhitney Tsang EXPECT_TRUE(L->isLoopSimplifyForm()); 1369dcb75bf8SWhitney Tsang EXPECT_EQ(L->getLoopLatch(), Latch); 1370dcb75bf8SWhitney Tsang EXPECT_FALSE(L->isLoopExiting(Latch)); 1371dcb75bf8SWhitney Tsang // No loop guard becuase loop is not exiting on latch. 1372dcb75bf8SWhitney Tsang EXPECT_EQ(L->getLoopGuardBranch(), nullptr); 1373dcb75bf8SWhitney Tsang EXPECT_FALSE(L->isGuarded()); 1374dcb75bf8SWhitney Tsang }); 1375dcb75bf8SWhitney Tsang } 1376dcb75bf8SWhitney Tsang 1377f1ee04c4SSerguei Katkov // Examine getUniqueExitBlocks/getUniqueNonLatchExitBlocks functions. 1378f1ee04c4SSerguei Katkov TEST(LoopInfoTest, LoopUniqueExitBlocks) { 1379f1ee04c4SSerguei Katkov const char *ModuleStr = 1380f1ee04c4SSerguei Katkov "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n" 1381f1ee04c4SSerguei Katkov "define void @foo(i32 %n, i1 %cond) {\n" 1382f1ee04c4SSerguei Katkov "entry:\n" 1383f1ee04c4SSerguei Katkov " br label %for.cond\n" 1384f1ee04c4SSerguei Katkov "for.cond:\n" 1385f1ee04c4SSerguei Katkov " %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]\n" 1386f1ee04c4SSerguei Katkov " %cmp = icmp slt i32 %i.0, %n\n" 1387f1ee04c4SSerguei Katkov " br i1 %cond, label %for.inc, label %for.end1\n" 1388f1ee04c4SSerguei Katkov "for.inc:\n" 1389f1ee04c4SSerguei Katkov " %inc = add nsw i32 %i.0, 1\n" 1390f1ee04c4SSerguei Katkov " br i1 %cmp, label %for.cond, label %for.end2, !llvm.loop !0\n" 1391f1ee04c4SSerguei Katkov "for.end1:\n" 1392f1ee04c4SSerguei Katkov " br label %for.end\n" 1393f1ee04c4SSerguei Katkov "for.end2:\n" 1394f1ee04c4SSerguei Katkov " br label %for.end\n" 1395f1ee04c4SSerguei Katkov "for.end:\n" 1396f1ee04c4SSerguei Katkov " ret void\n" 1397f1ee04c4SSerguei Katkov "}\n" 1398f1ee04c4SSerguei Katkov "!0 = distinct !{!0, !1}\n" 1399f1ee04c4SSerguei Katkov "!1 = !{!\"llvm.loop.distribute.enable\", i1 true}\n"; 1400f1ee04c4SSerguei Katkov 1401f1ee04c4SSerguei Katkov // Parse the module. 1402f1ee04c4SSerguei Katkov LLVMContext Context; 1403f1ee04c4SSerguei Katkov std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 1404f1ee04c4SSerguei Katkov 1405f1ee04c4SSerguei Katkov runWithLoopInfo(*M, "foo", [&](Function &F, LoopInfo &LI) { 1406f1ee04c4SSerguei Katkov Function::iterator FI = F.begin(); 1407f1ee04c4SSerguei Katkov // First basic block is entry - skip it. 1408f1ee04c4SSerguei Katkov BasicBlock *Header = &*(++FI); 1409f1ee04c4SSerguei Katkov assert(Header->getName() == "for.cond"); 1410f1ee04c4SSerguei Katkov Loop *L = LI.getLoopFor(Header); 1411f1ee04c4SSerguei Katkov 1412f1ee04c4SSerguei Katkov SmallVector<BasicBlock *, 2> Exits; 1413f1ee04c4SSerguei Katkov // This loop has 2 unique exits. 1414f1ee04c4SSerguei Katkov L->getUniqueExitBlocks(Exits); 1415f1ee04c4SSerguei Katkov EXPECT_TRUE(Exits.size() == 2); 1416f1ee04c4SSerguei Katkov // And one unique non latch exit. 1417f1ee04c4SSerguei Katkov Exits.clear(); 1418f1ee04c4SSerguei Katkov L->getUniqueNonLatchExitBlocks(Exits); 1419f1ee04c4SSerguei Katkov EXPECT_TRUE(Exits.size() == 1); 1420f1ee04c4SSerguei Katkov }); 1421f1ee04c4SSerguei Katkov } 1422587d13d4SSerguei Katkov 1423587d13d4SSerguei Katkov // Regression test for getUniqueNonLatchExitBlocks functions. 1424587d13d4SSerguei Katkov // It should detect the exit if it comes from both latch and non-latch blocks. 1425587d13d4SSerguei Katkov TEST(LoopInfoTest, LoopNonLatchUniqueExitBlocks) { 1426587d13d4SSerguei Katkov const char *ModuleStr = 1427587d13d4SSerguei Katkov "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n" 1428587d13d4SSerguei Katkov "define void @foo(i32 %n, i1 %cond) {\n" 1429587d13d4SSerguei Katkov "entry:\n" 1430587d13d4SSerguei Katkov " br label %for.cond\n" 1431587d13d4SSerguei Katkov "for.cond:\n" 1432587d13d4SSerguei Katkov " %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]\n" 1433587d13d4SSerguei Katkov " %cmp = icmp slt i32 %i.0, %n\n" 1434587d13d4SSerguei Katkov " br i1 %cond, label %for.inc, label %for.end\n" 1435587d13d4SSerguei Katkov "for.inc:\n" 1436587d13d4SSerguei Katkov " %inc = add nsw i32 %i.0, 1\n" 1437587d13d4SSerguei Katkov " br i1 %cmp, label %for.cond, label %for.end, !llvm.loop !0\n" 1438587d13d4SSerguei Katkov "for.end:\n" 1439587d13d4SSerguei Katkov " ret void\n" 1440587d13d4SSerguei Katkov "}\n" 1441587d13d4SSerguei Katkov "!0 = distinct !{!0, !1}\n" 1442587d13d4SSerguei Katkov "!1 = !{!\"llvm.loop.distribute.enable\", i1 true}\n"; 1443587d13d4SSerguei Katkov 1444587d13d4SSerguei Katkov // Parse the module. 1445587d13d4SSerguei Katkov LLVMContext Context; 1446587d13d4SSerguei Katkov std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 1447587d13d4SSerguei Katkov 1448587d13d4SSerguei Katkov runWithLoopInfo(*M, "foo", [&](Function &F, LoopInfo &LI) { 1449587d13d4SSerguei Katkov Function::iterator FI = F.begin(); 1450587d13d4SSerguei Katkov // First basic block is entry - skip it. 1451587d13d4SSerguei Katkov BasicBlock *Header = &*(++FI); 1452587d13d4SSerguei Katkov assert(Header->getName() == "for.cond"); 1453587d13d4SSerguei Katkov Loop *L = LI.getLoopFor(Header); 1454587d13d4SSerguei Katkov 1455587d13d4SSerguei Katkov SmallVector<BasicBlock *, 2> Exits; 1456587d13d4SSerguei Katkov // This loop has 1 unique exit. 1457587d13d4SSerguei Katkov L->getUniqueExitBlocks(Exits); 1458587d13d4SSerguei Katkov EXPECT_TRUE(Exits.size() == 1); 1459587d13d4SSerguei Katkov // And one unique non latch exit. 1460587d13d4SSerguei Katkov Exits.clear(); 1461587d13d4SSerguei Katkov L->getUniqueNonLatchExitBlocks(Exits); 1462587d13d4SSerguei Katkov EXPECT_TRUE(Exits.size() == 1); 1463587d13d4SSerguei Katkov }); 1464587d13d4SSerguei Katkov } 1465942c9946SKit Barton 1466942c9946SKit Barton // Test that a pointer-chasing loop is not rotated. 1467942c9946SKit Barton TEST(LoopInfoTest, LoopNotRotated) { 1468942c9946SKit Barton const char *ModuleStr = 1469942c9946SKit Barton "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n" 1470942c9946SKit Barton "define void @foo(i32* %elem) {\n" 1471942c9946SKit Barton "entry:\n" 1472942c9946SKit Barton " br label %while.cond\n" 1473942c9946SKit Barton "while.cond:\n" 1474942c9946SKit Barton " %elem.addr.0 = phi i32* [ %elem, %entry ], [ %incdec.ptr, %while.body " 1475942c9946SKit Barton "]\n" 1476942c9946SKit Barton " %tobool = icmp eq i32* %elem.addr.0, null\n" 1477942c9946SKit Barton " br i1 %tobool, label %while.end, label %while.body\n" 1478942c9946SKit Barton "while.body:\n" 1479942c9946SKit Barton " %incdec.ptr = getelementptr inbounds i32, i32* %elem.addr.0, i64 1\n" 1480942c9946SKit Barton " br label %while.cond\n" 1481942c9946SKit Barton "while.end:\n" 1482942c9946SKit Barton " ret void\n" 1483942c9946SKit Barton "}\n"; 1484942c9946SKit Barton 1485942c9946SKit Barton // Parse the module. 1486942c9946SKit Barton LLVMContext Context; 1487942c9946SKit Barton std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 1488942c9946SKit Barton 1489942c9946SKit Barton runWithLoopInfo(*M, "foo", [&](Function &F, LoopInfo &LI) { 1490942c9946SKit Barton Function::iterator FI = F.begin(); 1491942c9946SKit Barton // First basic block is entry - skip it. 1492942c9946SKit Barton BasicBlock *Header = &*(++FI); 1493942c9946SKit Barton assert(Header->getName() == "while.cond"); 1494942c9946SKit Barton Loop *L = LI.getLoopFor(Header); 1495942c9946SKit Barton EXPECT_NE(L, nullptr); 1496942c9946SKit Barton 1497942c9946SKit Barton // This loop is in simplified form. 1498942c9946SKit Barton EXPECT_TRUE(L->isLoopSimplifyForm()); 1499942c9946SKit Barton 1500942c9946SKit Barton // This loop is not rotated. 150161368c8eSKit Barton EXPECT_FALSE(L->isRotatedForm()); 1502942c9946SKit Barton }); 1503942c9946SKit Barton } 15041006ac39SWhitney Tsang 15051006ac39SWhitney Tsang TEST(LoopInfoTest, LoopUserBranch) { 15061006ac39SWhitney Tsang const char *ModuleStr = 15071006ac39SWhitney Tsang "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n" 15081006ac39SWhitney Tsang "define void @foo(i32* %B, i64 signext %nx, i1 %cond) {\n" 15091006ac39SWhitney Tsang "entry:\n" 15101006ac39SWhitney Tsang " br i1 %cond, label %bb, label %guard\n" 15111006ac39SWhitney Tsang "guard:\n" 15121006ac39SWhitney Tsang " %cmp.guard = icmp slt i64 0, %nx\n" 15131006ac39SWhitney Tsang " br i1 %cmp.guard, label %for.i.preheader, label %for.end\n" 15141006ac39SWhitney Tsang "for.i.preheader:\n" 15151006ac39SWhitney Tsang " br label %for.i\n" 15161006ac39SWhitney Tsang "for.i:\n" 15171006ac39SWhitney Tsang " %i = phi i64 [ 0, %for.i.preheader ], [ %inc13, %for.i ]\n" 15181006ac39SWhitney Tsang " %Bi = getelementptr inbounds i32, i32* %B, i64 %i\n" 15191006ac39SWhitney Tsang " store i32 0, i32* %Bi, align 4\n" 15201006ac39SWhitney Tsang " %inc13 = add nsw i64 %i, 1\n" 15211006ac39SWhitney Tsang " %cmp = icmp slt i64 %inc13, %nx\n" 15221006ac39SWhitney Tsang " br i1 %cmp, label %for.i, label %for.i.exit\n" 15231006ac39SWhitney Tsang "for.i.exit:\n" 15241006ac39SWhitney Tsang " br label %bb\n" 15251006ac39SWhitney Tsang "bb:\n" 15261006ac39SWhitney Tsang " br label %for.end\n" 15271006ac39SWhitney Tsang "for.end:\n" 15281006ac39SWhitney Tsang " ret void\n" 15291006ac39SWhitney Tsang "}\n"; 15301006ac39SWhitney Tsang 15311006ac39SWhitney Tsang // Parse the module. 15321006ac39SWhitney Tsang LLVMContext Context; 15331006ac39SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 15341006ac39SWhitney Tsang 15351006ac39SWhitney Tsang runWithLoopInfo(*M, "foo", [&](Function &F, LoopInfo &LI) { 15361006ac39SWhitney Tsang Function::iterator FI = F.begin(); 15371006ac39SWhitney Tsang FI = ++FI; 153872460490SFangrui Song assert(FI->getName() == "guard"); 15391006ac39SWhitney Tsang 15401006ac39SWhitney Tsang FI = ++FI; 15411006ac39SWhitney Tsang BasicBlock *Header = &*(++FI); 15421006ac39SWhitney Tsang assert(Header->getName() == "for.i"); 15431006ac39SWhitney Tsang 15441006ac39SWhitney Tsang Loop *L = LI.getLoopFor(Header); 15451006ac39SWhitney Tsang EXPECT_NE(L, nullptr); 15461006ac39SWhitney Tsang 15471006ac39SWhitney Tsang // L should not have a guard branch 15481006ac39SWhitney Tsang EXPECT_EQ(L->getLoopGuardBranch(), nullptr); 15491006ac39SWhitney Tsang }); 15501006ac39SWhitney Tsang } 155153dc5258Sduanbo.db 155253dc5258Sduanbo.db TEST(LoopInfoTest, LoopInductionVariable) { 155353dc5258Sduanbo.db const char *ModuleStr = 155453dc5258Sduanbo.db "define i32 @foo(i32* %addr) {\n" 155553dc5258Sduanbo.db "entry:\n" 155653dc5258Sduanbo.db " br label %for.body\n" 155753dc5258Sduanbo.db "for.body:\n" 155853dc5258Sduanbo.db " %sum.08 = phi i32 [ 0, %entry ], [ %add, %for.body ]\n" 155953dc5258Sduanbo.db " %addr.addr.06 = phi i32* [ %addr, %entry ], [ %incdec.ptr, %for.body " 156053dc5258Sduanbo.db "]\n" 156153dc5258Sduanbo.db " %count.07 = phi i32 [ 6000, %entry ], [ %dec, %for.body ]\n" 156253dc5258Sduanbo.db " %0 = load i32, i32* %addr.addr.06, align 4\n" 156353dc5258Sduanbo.db " %add = add nsw i32 %0, %sum.08\n" 156453dc5258Sduanbo.db " %dec = add nsw i32 %count.07, -1\n" 156553dc5258Sduanbo.db " %incdec.ptr = getelementptr inbounds i32, i32* %addr.addr.06, i64 1\n" 156653dc5258Sduanbo.db " %cmp = icmp ugt i32 %count.07, 1\n" 156753dc5258Sduanbo.db " br i1 %cmp, label %for.body, label %for.end\n" 156853dc5258Sduanbo.db "for.end:\n" 156953dc5258Sduanbo.db " %cmp1 = icmp eq i32 %add, -1\n" 157053dc5258Sduanbo.db " %conv = zext i1 %cmp1 to i32\n" 157153dc5258Sduanbo.db " ret i32 %conv\n" 157253dc5258Sduanbo.db "}\n"; 157353dc5258Sduanbo.db 157453dc5258Sduanbo.db // Parse the module. 157553dc5258Sduanbo.db LLVMContext Context; 157653dc5258Sduanbo.db std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 157753dc5258Sduanbo.db 157853dc5258Sduanbo.db runWithLoopInfoPlus( 157953dc5258Sduanbo.db *M, "foo", [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) { 158053dc5258Sduanbo.db Function::iterator FI = F.begin(); 158153dc5258Sduanbo.db BasicBlock *Header = &*(++FI); 158253dc5258Sduanbo.db Loop *L = LI.getLoopFor(Header); 158353dc5258Sduanbo.db EXPECT_NE(L, nullptr); 158453dc5258Sduanbo.db EXPECT_EQ(L->getInductionVariable(SE)->getName(), "count.07"); 158553dc5258Sduanbo.db }); 158653dc5258Sduanbo.db } 1587