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/PostDominators.h" 122d0896c1SWhitney Tsang #include "llvm/Analysis/ScalarEvolution.h" 132d0896c1SWhitney Tsang #include "llvm/Analysis/TargetLibraryInfo.h" 14ca02360fSXin Tong #include "llvm/AsmParser/Parser.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, 362d0896c1SWhitney Tsang function_ref<void(Function &F, LoopInfo &LI, ScalarEvolution &SE, 372d0896c1SWhitney Tsang PostDominatorTree &PDT)> 382d0896c1SWhitney Tsang Test) { 392d0896c1SWhitney Tsang auto *F = M.getFunction(FuncName); 402d0896c1SWhitney Tsang ASSERT_NE(F, nullptr) << "Could not find " << FuncName; 412d0896c1SWhitney Tsang 422d0896c1SWhitney Tsang TargetLibraryInfoImpl TLII; 432d0896c1SWhitney Tsang TargetLibraryInfo TLI(TLII); 442d0896c1SWhitney Tsang AssumptionCache AC(*F); 452d0896c1SWhitney Tsang DominatorTree DT(*F); 462d0896c1SWhitney Tsang LoopInfo LI(DT); 472d0896c1SWhitney Tsang ScalarEvolution SE(*F, TLI, AC, DT, LI); 482d0896c1SWhitney Tsang 492d0896c1SWhitney Tsang PostDominatorTree PDT(*F); 502d0896c1SWhitney Tsang Test(*F, LI, SE, PDT); 512d0896c1SWhitney Tsang } 522d0896c1SWhitney Tsang 53ca02360fSXin Tong static std::unique_ptr<Module> makeLLVMModule(LLVMContext &Context, 54ca02360fSXin Tong const char *ModuleStr) { 55ca02360fSXin Tong SMDiagnostic Err; 56ca02360fSXin Tong return parseAssemblyString(ModuleStr, Err, Context); 57ca02360fSXin Tong } 58ca02360fSXin Tong 59ca02360fSXin Tong // This tests that for a loop with a single latch, we get the loop id from 60ca02360fSXin Tong // its only latch, even in case the loop may not be in a simplified form. 61ca02360fSXin Tong TEST(LoopInfoTest, LoopWithSingleLatch) { 62ca02360fSXin Tong const char *ModuleStr = 63ca02360fSXin Tong "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n" 64ca02360fSXin Tong "define void @foo(i32 %n) {\n" 65ca02360fSXin Tong "entry:\n" 66ca02360fSXin Tong " br i1 undef, label %for.cond, label %for.end\n" 67ca02360fSXin Tong "for.cond:\n" 68ca02360fSXin Tong " %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]\n" 69ca02360fSXin Tong " %cmp = icmp slt i32 %i.0, %n\n" 70ca02360fSXin Tong " br i1 %cmp, label %for.inc, label %for.end\n" 71ca02360fSXin Tong "for.inc:\n" 72ca02360fSXin Tong " %inc = add nsw i32 %i.0, 1\n" 73ca02360fSXin Tong " br label %for.cond, !llvm.loop !0\n" 74ca02360fSXin Tong "for.end:\n" 75ca02360fSXin Tong " ret void\n" 76ca02360fSXin Tong "}\n" 77ca02360fSXin Tong "!0 = distinct !{!0, !1}\n" 78ca02360fSXin Tong "!1 = !{!\"llvm.loop.distribute.enable\", i1 true}\n"; 79ca02360fSXin Tong 80ca02360fSXin Tong // Parse the module. 81ca02360fSXin Tong LLVMContext Context; 82ca02360fSXin Tong std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 83ca02360fSXin Tong 8443c1a264SXin Tong runWithLoopInfo(*M, "foo", [&](Function &F, LoopInfo &LI) { 85ca02360fSXin Tong Function::iterator FI = F.begin(); 8643c1a264SXin Tong // First basic block is entry - skip it. 8743c1a264SXin Tong BasicBlock *Header = &*(++FI); 88ca02360fSXin Tong assert(Header->getName() == "for.cond"); 89ca02360fSXin Tong Loop *L = LI.getLoopFor(Header); 90ca02360fSXin Tong 91ca02360fSXin Tong // This loop is not in simplified form. 92ca02360fSXin Tong EXPECT_FALSE(L->isLoopSimplifyForm()); 93ca02360fSXin Tong 94ca02360fSXin Tong // Analyze the loop metadata id. 95ca02360fSXin Tong bool loopIDFoundAndSet = false; 96ca02360fSXin Tong // Try to get and set the metadata id for the loop. 97ca02360fSXin Tong if (MDNode *D = L->getLoopID()) { 98ca02360fSXin Tong L->setLoopID(D); 99ca02360fSXin Tong loopIDFoundAndSet = true; 100ca02360fSXin Tong } 101ca02360fSXin Tong 102ca02360fSXin Tong // We must have successfully found and set the loop id in the 103ca02360fSXin Tong // only latch the loop has. 104ca02360fSXin Tong EXPECT_TRUE(loopIDFoundAndSet); 10543c1a264SXin Tong }); 106ca02360fSXin Tong } 107f002264dSChandler Carruth 108a58e9214SJohannes Doerfert // Test loop id handling for a loop with multiple latches. 109a58e9214SJohannes Doerfert TEST(LoopInfoTest, LoopWithMultipleLatches) { 110a58e9214SJohannes Doerfert const char *ModuleStr = 111a58e9214SJohannes Doerfert "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n" 112a58e9214SJohannes Doerfert "define void @foo(i32 %n) {\n" 113a58e9214SJohannes Doerfert "entry:\n" 114a58e9214SJohannes Doerfert " br i1 undef, label %for.cond, label %for.end\n" 115a58e9214SJohannes Doerfert "for.cond:\n" 116a58e9214SJohannes Doerfert " %i.0 = phi i32 [ 0, %entry ], [ %inc, %latch.1 ], [ %inc, %latch.2 ]\n" 117a58e9214SJohannes Doerfert " %inc = add nsw i32 %i.0, 1\n" 118a58e9214SJohannes Doerfert " %cmp = icmp slt i32 %i.0, %n\n" 119a58e9214SJohannes Doerfert " br i1 %cmp, label %latch.1, label %for.end\n" 120a58e9214SJohannes Doerfert "latch.1:\n" 121a58e9214SJohannes Doerfert " br i1 undef, label %for.cond, label %latch.2, !llvm.loop !0\n" 122a58e9214SJohannes Doerfert "latch.2:\n" 123a58e9214SJohannes Doerfert " br label %for.cond, !llvm.loop !0\n" 124a58e9214SJohannes Doerfert "for.end:\n" 125a58e9214SJohannes Doerfert " ret void\n" 126a58e9214SJohannes Doerfert "}\n" 127a58e9214SJohannes Doerfert "!0 = distinct !{!0, !1}\n" 128a58e9214SJohannes Doerfert "!1 = !{!\"llvm.loop.distribute.enable\", i1 true}\n"; 129a58e9214SJohannes Doerfert 130a58e9214SJohannes Doerfert // Parse the module. 131a58e9214SJohannes Doerfert LLVMContext Context; 132a58e9214SJohannes Doerfert std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 133a58e9214SJohannes Doerfert 134a58e9214SJohannes Doerfert runWithLoopInfo(*M, "foo", [&](Function &F, LoopInfo &LI) { 135a58e9214SJohannes Doerfert Function::iterator FI = F.begin(); 136a58e9214SJohannes Doerfert // First basic block is entry - skip it. 137a58e9214SJohannes Doerfert BasicBlock *Header = &*(++FI); 138a58e9214SJohannes Doerfert assert(Header->getName() == "for.cond"); 139a58e9214SJohannes Doerfert Loop *L = LI.getLoopFor(Header); 140a58e9214SJohannes Doerfert EXPECT_NE(L, nullptr); 141a58e9214SJohannes Doerfert 142a58e9214SJohannes Doerfert // This loop is not in simplified form. 143a58e9214SJohannes Doerfert EXPECT_FALSE(L->isLoopSimplifyForm()); 144a58e9214SJohannes Doerfert 145a58e9214SJohannes Doerfert // Try to get and set the metadata id for the loop. 146a58e9214SJohannes Doerfert MDNode *OldLoopID = L->getLoopID(); 147a58e9214SJohannes Doerfert EXPECT_NE(OldLoopID, nullptr); 148a58e9214SJohannes Doerfert 149a58e9214SJohannes Doerfert MDNode *NewLoopID = MDNode::get(Context, {nullptr}); 150a58e9214SJohannes Doerfert // Set operand 0 to refer to the loop id itself. 151a58e9214SJohannes Doerfert NewLoopID->replaceOperandWith(0, NewLoopID); 152a58e9214SJohannes Doerfert 153a58e9214SJohannes Doerfert L->setLoopID(NewLoopID); 154a58e9214SJohannes Doerfert EXPECT_EQ(L->getLoopID(), NewLoopID); 155a58e9214SJohannes Doerfert EXPECT_NE(L->getLoopID(), OldLoopID); 156a58e9214SJohannes Doerfert 157a58e9214SJohannes Doerfert L->setLoopID(OldLoopID); 158a58e9214SJohannes Doerfert EXPECT_EQ(L->getLoopID(), OldLoopID); 159a58e9214SJohannes Doerfert EXPECT_NE(L->getLoopID(), NewLoopID); 160a58e9214SJohannes Doerfert }); 161a58e9214SJohannes Doerfert } 162a58e9214SJohannes Doerfert 163f002264dSChandler Carruth TEST(LoopInfoTest, PreorderTraversals) { 164f002264dSChandler Carruth const char *ModuleStr = "define void @f() {\n" 165f002264dSChandler Carruth "entry:\n" 166f002264dSChandler Carruth " br label %loop.0\n" 167f002264dSChandler Carruth "loop.0:\n" 168f002264dSChandler Carruth " br i1 undef, label %loop.0.0, label %loop.1\n" 169f002264dSChandler Carruth "loop.0.0:\n" 170f002264dSChandler Carruth " br i1 undef, label %loop.0.0, label %loop.0.1\n" 171f002264dSChandler Carruth "loop.0.1:\n" 172f002264dSChandler Carruth " br i1 undef, label %loop.0.1, label %loop.0.2\n" 173f002264dSChandler Carruth "loop.0.2:\n" 174f002264dSChandler Carruth " br i1 undef, label %loop.0.2, label %loop.0\n" 175f002264dSChandler Carruth "loop.1:\n" 176f002264dSChandler Carruth " br i1 undef, label %loop.1.0, label %end\n" 177f002264dSChandler Carruth "loop.1.0:\n" 178f002264dSChandler Carruth " br i1 undef, label %loop.1.0, label %loop.1.1\n" 179f002264dSChandler Carruth "loop.1.1:\n" 180f002264dSChandler Carruth " br i1 undef, label %loop.1.1, label %loop.1.2\n" 181f002264dSChandler Carruth "loop.1.2:\n" 182f002264dSChandler Carruth " br i1 undef, label %loop.1.2, label %loop.1\n" 183f002264dSChandler Carruth "end:\n" 184f002264dSChandler Carruth " ret void\n" 185f002264dSChandler Carruth "}\n"; 186f002264dSChandler Carruth // Parse the module. 187f002264dSChandler Carruth LLVMContext Context; 188f002264dSChandler Carruth std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 189f002264dSChandler Carruth Function &F = *M->begin(); 190f002264dSChandler Carruth 191f002264dSChandler Carruth DominatorTree DT(F); 192f002264dSChandler Carruth LoopInfo LI; 193f002264dSChandler Carruth LI.analyze(DT); 194f002264dSChandler Carruth 195f002264dSChandler Carruth Function::iterator I = F.begin(); 196f002264dSChandler Carruth ASSERT_EQ("entry", I->getName()); 197f002264dSChandler Carruth ++I; 198f002264dSChandler Carruth Loop &L_0 = *LI.getLoopFor(&*I++); 199f002264dSChandler Carruth ASSERT_EQ("loop.0", L_0.getHeader()->getName()); 200f002264dSChandler Carruth Loop &L_0_0 = *LI.getLoopFor(&*I++); 201f002264dSChandler Carruth ASSERT_EQ("loop.0.0", L_0_0.getHeader()->getName()); 202f002264dSChandler Carruth Loop &L_0_1 = *LI.getLoopFor(&*I++); 203f002264dSChandler Carruth ASSERT_EQ("loop.0.1", L_0_1.getHeader()->getName()); 204f002264dSChandler Carruth Loop &L_0_2 = *LI.getLoopFor(&*I++); 205f002264dSChandler Carruth ASSERT_EQ("loop.0.2", L_0_2.getHeader()->getName()); 206f002264dSChandler Carruth Loop &L_1 = *LI.getLoopFor(&*I++); 207f002264dSChandler Carruth ASSERT_EQ("loop.1", L_1.getHeader()->getName()); 208f002264dSChandler Carruth Loop &L_1_0 = *LI.getLoopFor(&*I++); 209f002264dSChandler Carruth ASSERT_EQ("loop.1.0", L_1_0.getHeader()->getName()); 210f002264dSChandler Carruth Loop &L_1_1 = *LI.getLoopFor(&*I++); 211f002264dSChandler Carruth ASSERT_EQ("loop.1.1", L_1_1.getHeader()->getName()); 212f002264dSChandler Carruth Loop &L_1_2 = *LI.getLoopFor(&*I++); 213f002264dSChandler Carruth ASSERT_EQ("loop.1.2", L_1_2.getHeader()->getName()); 214f002264dSChandler Carruth 215f002264dSChandler Carruth auto Preorder = LI.getLoopsInPreorder(); 216f002264dSChandler Carruth ASSERT_EQ(8u, Preorder.size()); 217f002264dSChandler Carruth EXPECT_EQ(&L_0, Preorder[0]); 218f002264dSChandler Carruth EXPECT_EQ(&L_0_0, Preorder[1]); 219f002264dSChandler Carruth EXPECT_EQ(&L_0_1, Preorder[2]); 220f002264dSChandler Carruth EXPECT_EQ(&L_0_2, Preorder[3]); 221f002264dSChandler Carruth EXPECT_EQ(&L_1, Preorder[4]); 222f002264dSChandler Carruth EXPECT_EQ(&L_1_0, Preorder[5]); 223f002264dSChandler Carruth EXPECT_EQ(&L_1_1, Preorder[6]); 224f002264dSChandler Carruth EXPECT_EQ(&L_1_2, Preorder[7]); 225f002264dSChandler Carruth 226f002264dSChandler Carruth auto ReverseSiblingPreorder = LI.getLoopsInReverseSiblingPreorder(); 227f002264dSChandler Carruth ASSERT_EQ(8u, ReverseSiblingPreorder.size()); 228f002264dSChandler Carruth EXPECT_EQ(&L_1, ReverseSiblingPreorder[0]); 229f002264dSChandler Carruth EXPECT_EQ(&L_1_2, ReverseSiblingPreorder[1]); 230f002264dSChandler Carruth EXPECT_EQ(&L_1_1, ReverseSiblingPreorder[2]); 231f002264dSChandler Carruth EXPECT_EQ(&L_1_0, ReverseSiblingPreorder[3]); 232f002264dSChandler Carruth EXPECT_EQ(&L_0, ReverseSiblingPreorder[4]); 233f002264dSChandler Carruth EXPECT_EQ(&L_0_2, ReverseSiblingPreorder[5]); 234f002264dSChandler Carruth EXPECT_EQ(&L_0_1, ReverseSiblingPreorder[6]); 235f002264dSChandler Carruth EXPECT_EQ(&L_0_0, ReverseSiblingPreorder[7]); 236f002264dSChandler Carruth } 2372d0896c1SWhitney Tsang 2382d0896c1SWhitney Tsang TEST(LoopInfoTest, CanonicalLoop) { 2392d0896c1SWhitney Tsang const char *ModuleStr = 2402d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 2412d0896c1SWhitney Tsang "entry:\n" 2422d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 2432d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 2442d0896c1SWhitney Tsang "for.preheader:\n" 2452d0896c1SWhitney Tsang " br label %for.body\n" 2462d0896c1SWhitney Tsang "for.body:\n" 2472d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 2482d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 2492d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 2502d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 2512d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 2522d0896c1SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 2532d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 2542d0896c1SWhitney Tsang "for.exit:\n" 2552d0896c1SWhitney Tsang " br label %for.end\n" 2562d0896c1SWhitney Tsang "for.end:\n" 2572d0896c1SWhitney Tsang " ret void\n" 2582d0896c1SWhitney Tsang "}\n"; 2592d0896c1SWhitney Tsang 2602d0896c1SWhitney Tsang // Parse the module. 2612d0896c1SWhitney Tsang LLVMContext Context; 2622d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 2632d0896c1SWhitney Tsang 2642d0896c1SWhitney Tsang runWithLoopInfoPlus( 2652d0896c1SWhitney Tsang *M, "foo", 2662d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 2672d0896c1SWhitney Tsang PostDominatorTree &PDT) { 2682d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 2692d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 2702d0896c1SWhitney Tsang ++FI; 2712d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 2722d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 2732d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 2742d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 2752d0896c1SWhitney Tsang 2762d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 2772d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 2782d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 2792d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 2802d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 2812d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 2822d0896c1SWhitney Tsang ConstantInt *StepValue = 2832d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 2842d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 2852d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 2862d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 2872d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 2882d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 2892d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 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", 3212d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 3222d0896c1SWhitney Tsang PostDominatorTree &PDT) { 3232d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 3242d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 3252d0896c1SWhitney Tsang ++FI; 3262d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 3272d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 3282d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 3292d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 3302d0896c1SWhitney Tsang 3312d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 3322d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 3332d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 3342d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 3352d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 3362d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 3372d0896c1SWhitney Tsang ConstantInt *StepValue = 3382d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 3392d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 3402d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 3412d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 3422d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 3432d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 3442d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 3452d0896c1SWhitney Tsang }); 3462d0896c1SWhitney Tsang } 3472d0896c1SWhitney Tsang 3482d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopWithSwappedGuardCmp) { 3492d0896c1SWhitney Tsang const char *ModuleStr = 3502d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 3512d0896c1SWhitney Tsang "entry:\n" 3522d0896c1SWhitney Tsang " %guardcmp = icmp sgt i32 %ub, 0\n" 3532d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 3542d0896c1SWhitney Tsang "for.preheader:\n" 3552d0896c1SWhitney Tsang " br label %for.body\n" 3562d0896c1SWhitney Tsang "for.body:\n" 3572d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 3582d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 3592d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 3602d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 3612d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 3622d0896c1SWhitney Tsang " %cmp = icmp sge i32 %inc, %ub\n" 3632d0896c1SWhitney Tsang " br i1 %cmp, label %for.exit, label %for.body\n" 3642d0896c1SWhitney Tsang "for.exit:\n" 3652d0896c1SWhitney Tsang " br label %for.end\n" 3662d0896c1SWhitney Tsang "for.end:\n" 3672d0896c1SWhitney Tsang " ret void\n" 3682d0896c1SWhitney Tsang "}\n"; 3692d0896c1SWhitney Tsang 3702d0896c1SWhitney Tsang // Parse the module. 3712d0896c1SWhitney Tsang LLVMContext Context; 3722d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 3732d0896c1SWhitney Tsang 3742d0896c1SWhitney Tsang runWithLoopInfoPlus( 3752d0896c1SWhitney Tsang *M, "foo", 3762d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 3772d0896c1SWhitney Tsang PostDominatorTree &PDT) { 3782d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 3792d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 3802d0896c1SWhitney Tsang ++FI; 3812d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 3822d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 3832d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 3842d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 3852d0896c1SWhitney Tsang 3862d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 3872d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 3882d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 3892d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 3902d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 3912d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 3922d0896c1SWhitney Tsang ConstantInt *StepValue = 3932d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 3942d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 3952d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 3962d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 3972d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 3982d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 3992d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 4002d0896c1SWhitney Tsang }); 4012d0896c1SWhitney Tsang } 4022d0896c1SWhitney Tsang 4032d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopWithInverseLatchSuccs) { 4042d0896c1SWhitney Tsang const char *ModuleStr = 4052d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 4062d0896c1SWhitney Tsang "entry:\n" 4072d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 4082d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 4092d0896c1SWhitney Tsang "for.preheader:\n" 4102d0896c1SWhitney Tsang " br label %for.body\n" 4112d0896c1SWhitney Tsang "for.body:\n" 4122d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 4132d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 4142d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 4152d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 4162d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 4172d0896c1SWhitney Tsang " %cmp = icmp sge i32 %inc, %ub\n" 4182d0896c1SWhitney Tsang " br i1 %cmp, label %for.exit, label %for.body\n" 4192d0896c1SWhitney Tsang "for.exit:\n" 4202d0896c1SWhitney Tsang " br label %for.end\n" 4212d0896c1SWhitney Tsang "for.end:\n" 4222d0896c1SWhitney Tsang " ret void\n" 4232d0896c1SWhitney Tsang "}\n"; 4242d0896c1SWhitney Tsang 4252d0896c1SWhitney Tsang // Parse the module. 4262d0896c1SWhitney Tsang LLVMContext Context; 4272d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 4282d0896c1SWhitney Tsang 4292d0896c1SWhitney Tsang runWithLoopInfoPlus( 4302d0896c1SWhitney Tsang *M, "foo", 4312d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 4322d0896c1SWhitney Tsang PostDominatorTree &PDT) { 4332d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 4342d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 4352d0896c1SWhitney Tsang ++FI; 4362d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 4372d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 4382d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 4392d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 4402d0896c1SWhitney Tsang 4412d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 4422d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 4432d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 4442d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 4452d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 4462d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 4472d0896c1SWhitney Tsang ConstantInt *StepValue = 4482d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 4492d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 4502d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 4512d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 4522d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 4532d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 4542d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 4552d0896c1SWhitney Tsang }); 4562d0896c1SWhitney Tsang } 4572d0896c1SWhitney Tsang 4582d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopWithLatchCmpNE) { 4592d0896c1SWhitney Tsang const char *ModuleStr = 4602d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 4612d0896c1SWhitney Tsang "entry:\n" 4622d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 4632d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 4642d0896c1SWhitney Tsang "for.preheader:\n" 4652d0896c1SWhitney Tsang " br label %for.body\n" 4662d0896c1SWhitney Tsang "for.body:\n" 4672d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 4682d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 4692d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 4702d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 4712d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 4722d0896c1SWhitney Tsang " %cmp = icmp ne i32 %i, %ub\n" 4732d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 4742d0896c1SWhitney Tsang "for.exit:\n" 4752d0896c1SWhitney Tsang " br label %for.end\n" 4762d0896c1SWhitney Tsang "for.end:\n" 4772d0896c1SWhitney Tsang " ret void\n" 4782d0896c1SWhitney Tsang "}\n"; 4792d0896c1SWhitney Tsang 4802d0896c1SWhitney Tsang // Parse the module. 4812d0896c1SWhitney Tsang LLVMContext Context; 4822d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 4832d0896c1SWhitney Tsang 4842d0896c1SWhitney Tsang runWithLoopInfoPlus( 4852d0896c1SWhitney Tsang *M, "foo", 4862d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 4872d0896c1SWhitney Tsang PostDominatorTree &PDT) { 4882d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 4892d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 4902d0896c1SWhitney Tsang ++FI; 4912d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 4922d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 4932d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 4942d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 4952d0896c1SWhitney Tsang 4962d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 4972d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 4982d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 4992d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 5002d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 5012d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 5022d0896c1SWhitney Tsang ConstantInt *StepValue = 5032d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 5042d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 5052d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 5062d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 5072d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 5082d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 5092d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 5102d0896c1SWhitney Tsang }); 5112d0896c1SWhitney Tsang } 5122d0896c1SWhitney Tsang 5132d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopWithGuardCmpSLE) { 5142d0896c1SWhitney Tsang const char *ModuleStr = 5152d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 5162d0896c1SWhitney Tsang "entry:\n" 5172d0896c1SWhitney Tsang " %ubPlusOne = add i32 %ub, 1\n" 5182d0896c1SWhitney Tsang " %guardcmp = icmp sle i32 0, %ub\n" 5192d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 5202d0896c1SWhitney Tsang "for.preheader:\n" 5212d0896c1SWhitney Tsang " br label %for.body\n" 5222d0896c1SWhitney Tsang "for.body:\n" 5232d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 5242d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 5252d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 5262d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 5272d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 5282d0896c1SWhitney Tsang " %cmp = icmp ne i32 %i, %ubPlusOne\n" 5292d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 5302d0896c1SWhitney Tsang "for.exit:\n" 5312d0896c1SWhitney Tsang " br label %for.end\n" 5322d0896c1SWhitney Tsang "for.end:\n" 5332d0896c1SWhitney Tsang " ret void\n" 5342d0896c1SWhitney Tsang "}\n"; 5352d0896c1SWhitney Tsang 5362d0896c1SWhitney Tsang // Parse the module. 5372d0896c1SWhitney Tsang LLVMContext Context; 5382d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 5392d0896c1SWhitney Tsang 5402d0896c1SWhitney Tsang runWithLoopInfoPlus( 5412d0896c1SWhitney Tsang *M, "foo", 5422d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 5432d0896c1SWhitney Tsang PostDominatorTree &PDT) { 5442d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 5452d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 5462d0896c1SWhitney Tsang ++FI; 5472d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 5482d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 5492d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 5502d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 5512d0896c1SWhitney Tsang 5522d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 5532d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 5542d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 5552d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 5562d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 5572d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 5582d0896c1SWhitney Tsang ConstantInt *StepValue = 5592d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 5602d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 5612d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ubPlusOne"); 5622d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 5632d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 5642d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 5652d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 5662d0896c1SWhitney Tsang }); 5672d0896c1SWhitney Tsang } 5682d0896c1SWhitney Tsang 5692d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopNonConstantStep) { 5702d0896c1SWhitney Tsang const char *ModuleStr = 5712d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub, i32 %step) {\n" 5722d0896c1SWhitney Tsang "entry:\n" 5732d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 5742d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 5752d0896c1SWhitney Tsang "for.preheader:\n" 5762d0896c1SWhitney Tsang " br label %for.body\n" 5772d0896c1SWhitney Tsang "for.body:\n" 5782d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 5792d0896c1SWhitney Tsang " %idxprom = zext i32 %i to i64\n" 5802d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 5812d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 5822d0896c1SWhitney Tsang " %inc = add nsw i32 %i, %step\n" 5832d0896c1SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 5842d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 5852d0896c1SWhitney Tsang "for.exit:\n" 5862d0896c1SWhitney Tsang " br label %for.end\n" 5872d0896c1SWhitney Tsang "for.end:\n" 5882d0896c1SWhitney Tsang " ret void\n" 5892d0896c1SWhitney Tsang "}\n"; 5902d0896c1SWhitney Tsang 5912d0896c1SWhitney Tsang // Parse the module. 5922d0896c1SWhitney Tsang LLVMContext Context; 5932d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 5942d0896c1SWhitney Tsang 5952d0896c1SWhitney Tsang runWithLoopInfoPlus( 5962d0896c1SWhitney Tsang *M, "foo", 5972d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 5982d0896c1SWhitney Tsang PostDominatorTree &PDT) { 5992d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 6002d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 6012d0896c1SWhitney Tsang ++FI; 6022d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 6032d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 6042d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 6052d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 6062d0896c1SWhitney Tsang 6072d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 6082d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 6092d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 6102d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 6112d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 6122d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 6132d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepValue()->getName(), "step"); 6142d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 6152d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 6162d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), Loop::LoopBounds::Direction::Unknown); 6172d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 6182d0896c1SWhitney Tsang }); 6192d0896c1SWhitney Tsang } 6202d0896c1SWhitney Tsang 6212d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopUnsignedBounds) { 6222d0896c1SWhitney Tsang const char *ModuleStr = 6232d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 6242d0896c1SWhitney Tsang "entry:\n" 6252d0896c1SWhitney Tsang " %guardcmp = icmp ult i32 0, %ub\n" 6262d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 6272d0896c1SWhitney Tsang "for.preheader:\n" 6282d0896c1SWhitney Tsang " br label %for.body\n" 6292d0896c1SWhitney Tsang "for.body:\n" 6302d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 6312d0896c1SWhitney Tsang " %idxprom = zext i32 %i to i64\n" 6322d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 6332d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 6342d0896c1SWhitney Tsang " %inc = add i32 %i, 1\n" 6352d0896c1SWhitney Tsang " %cmp = icmp ult i32 %inc, %ub\n" 6362d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 6372d0896c1SWhitney Tsang "for.exit:\n" 6382d0896c1SWhitney Tsang " br label %for.end\n" 6392d0896c1SWhitney Tsang "for.end:\n" 6402d0896c1SWhitney Tsang " ret void\n" 6412d0896c1SWhitney Tsang "}\n"; 6422d0896c1SWhitney Tsang 6432d0896c1SWhitney Tsang // Parse the module. 6442d0896c1SWhitney Tsang LLVMContext Context; 6452d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 6462d0896c1SWhitney Tsang 6472d0896c1SWhitney Tsang runWithLoopInfoPlus( 6482d0896c1SWhitney Tsang *M, "foo", 6492d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 6502d0896c1SWhitney Tsang PostDominatorTree &PDT) { 6512d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 6522d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 6532d0896c1SWhitney Tsang ++FI; 6542d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 6552d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 6562d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 6572d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 6582d0896c1SWhitney Tsang 6592d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 6602d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 6612d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 6622d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 6632d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 6642d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 6652d0896c1SWhitney Tsang ConstantInt *StepValue = 6662d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 6672d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 6682d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 6692d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_ULT); 6702d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 6712d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 6722d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 6732d0896c1SWhitney Tsang }); 6742d0896c1SWhitney Tsang } 6752d0896c1SWhitney Tsang 6762d0896c1SWhitney Tsang TEST(LoopInfoTest, DecreasingLoop) { 6772d0896c1SWhitney Tsang const char *ModuleStr = 6782d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 6792d0896c1SWhitney Tsang "entry:\n" 6802d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 6812d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 6822d0896c1SWhitney Tsang "for.preheader:\n" 6832d0896c1SWhitney Tsang " br label %for.body\n" 6842d0896c1SWhitney Tsang "for.body:\n" 6852d0896c1SWhitney Tsang " %i = phi i32 [ %ub, %for.preheader ], [ %inc, %for.body ]\n" 6862d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 6872d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 6882d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 6892d0896c1SWhitney Tsang " %inc = sub nsw i32 %i, 1\n" 6902d0896c1SWhitney Tsang " %cmp = icmp sgt i32 %inc, 0\n" 6912d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 6922d0896c1SWhitney Tsang "for.exit:\n" 6932d0896c1SWhitney Tsang " br label %for.end\n" 6942d0896c1SWhitney Tsang "for.end:\n" 6952d0896c1SWhitney Tsang " ret void\n" 6962d0896c1SWhitney Tsang "}\n"; 6972d0896c1SWhitney Tsang 6982d0896c1SWhitney Tsang // Parse the module. 6992d0896c1SWhitney Tsang LLVMContext Context; 7002d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 7012d0896c1SWhitney Tsang 7022d0896c1SWhitney Tsang runWithLoopInfoPlus( 7032d0896c1SWhitney Tsang *M, "foo", 7042d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 7052d0896c1SWhitney Tsang PostDominatorTree &PDT) { 7062d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 7072d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 7082d0896c1SWhitney Tsang ++FI; 7092d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 7102d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 7112d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 7122d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 7132d0896c1SWhitney Tsang 7142d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 7152d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 7162d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getInitialIVValue().getName(), "ub"); 7172d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 7182d0896c1SWhitney Tsang ConstantInt *StepValue = 7192d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 7202d0896c1SWhitney Tsang EXPECT_EQ(StepValue, nullptr); 7212d0896c1SWhitney Tsang ConstantInt *FinalIVValue = 7222d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getFinalIVValue()); 7232d0896c1SWhitney Tsang EXPECT_TRUE(FinalIVValue && FinalIVValue->isZero()); 7242d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SGT); 7252d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 7262d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Decreasing); 7272d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 7282d0896c1SWhitney Tsang }); 7292d0896c1SWhitney Tsang } 7302d0896c1SWhitney Tsang 7312d0896c1SWhitney Tsang TEST(LoopInfoTest, CannotFindDirection) { 7322d0896c1SWhitney Tsang const char *ModuleStr = 7332d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub, i32 %step) {\n" 7342d0896c1SWhitney Tsang "entry:\n" 7352d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 7362d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 7372d0896c1SWhitney Tsang "for.preheader:\n" 7382d0896c1SWhitney Tsang " br label %for.body\n" 7392d0896c1SWhitney Tsang "for.body:\n" 7402d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 7412d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 7422d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 7432d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 7442d0896c1SWhitney Tsang " %inc = add nsw i32 %i, %step\n" 7452d0896c1SWhitney Tsang " %cmp = icmp ne i32 %i, %ub\n" 7462d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 7472d0896c1SWhitney Tsang "for.exit:\n" 7482d0896c1SWhitney Tsang " br label %for.end\n" 7492d0896c1SWhitney Tsang "for.end:\n" 7502d0896c1SWhitney Tsang " ret void\n" 7512d0896c1SWhitney Tsang "}\n"; 7522d0896c1SWhitney Tsang 7532d0896c1SWhitney Tsang // Parse the module. 7542d0896c1SWhitney Tsang LLVMContext Context; 7552d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 7562d0896c1SWhitney Tsang 7572d0896c1SWhitney Tsang runWithLoopInfoPlus(*M, "foo", 7582d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 7592d0896c1SWhitney Tsang PostDominatorTree &PDT) { 7602d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 7612d0896c1SWhitney Tsang // First two basic block are entry and for.preheader 7622d0896c1SWhitney Tsang // - skip them. 7632d0896c1SWhitney Tsang ++FI; 7642d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 7652d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 7662d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 7672d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 7682d0896c1SWhitney Tsang 7692d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 7702d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 7712d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 7722d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 7732d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 7742d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 7752d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepValue()->getName(), "step"); 7762d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 7772d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), 7782d0896c1SWhitney Tsang ICmpInst::BAD_ICMP_PREDICATE); 7792d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 7802d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Unknown); 7812d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 7822d0896c1SWhitney Tsang }); 7832d0896c1SWhitney Tsang } 7842d0896c1SWhitney Tsang 7852d0896c1SWhitney Tsang TEST(LoopInfoTest, ZextIndVar) { 7862d0896c1SWhitney Tsang const char *ModuleStr = 7872d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 7882d0896c1SWhitney Tsang "entry:\n" 7892d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 7902d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 7912d0896c1SWhitney Tsang "for.preheader:\n" 7922d0896c1SWhitney Tsang " br label %for.body\n" 7932d0896c1SWhitney Tsang "for.body:\n" 7942d0896c1SWhitney Tsang " %indvars.iv = phi i64 [ 0, %for.preheader ], [ %indvars.iv.next, %for.body ]\n" 7952d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 7962d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 7972d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 7982d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 7992d0896c1SWhitney Tsang " %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n" 8002d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 8012d0896c1SWhitney Tsang " %wide.trip.count = zext i32 %ub to i64\n" 8022d0896c1SWhitney Tsang " %exitcond = icmp ne i64 %indvars.iv.next, %wide.trip.count\n" 8032d0896c1SWhitney Tsang " br i1 %exitcond, label %for.body, label %for.exit\n" 8042d0896c1SWhitney Tsang "for.exit:\n" 8052d0896c1SWhitney Tsang " br label %for.end\n" 8062d0896c1SWhitney Tsang "for.end:\n" 8072d0896c1SWhitney Tsang " ret void\n" 8082d0896c1SWhitney Tsang "}\n"; 8092d0896c1SWhitney Tsang 8102d0896c1SWhitney Tsang // Parse the module. 8112d0896c1SWhitney Tsang LLVMContext Context; 8122d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 8132d0896c1SWhitney Tsang 8142d0896c1SWhitney Tsang runWithLoopInfoPlus( 8152d0896c1SWhitney Tsang *M, "foo", 8162d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 8172d0896c1SWhitney Tsang PostDominatorTree &PDT) { 8182d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 8192d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 8202d0896c1SWhitney Tsang ++FI; 8212d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 8222d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 8232d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 8242d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 8252d0896c1SWhitney Tsang 8262d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 8272d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 8282d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 8292d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 8302d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 8312d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "indvars.iv.next"); 8322d0896c1SWhitney Tsang ConstantInt *StepValue = 8332d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 8342d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 8352d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "wide.trip.count"); 8362d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_NE); 8372d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 8382d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 8392d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "indvars.iv"); 8402d0896c1SWhitney Tsang }); 8412d0896c1SWhitney Tsang } 8422d0896c1SWhitney Tsang 8432d0896c1SWhitney Tsang TEST(LoopInfoTest, UnguardedLoop) { 8442d0896c1SWhitney Tsang const char *ModuleStr = 8452d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 8462d0896c1SWhitney Tsang "entry:\n" 8472d0896c1SWhitney Tsang " br label %for.body\n" 8482d0896c1SWhitney Tsang "for.body:\n" 8492d0896c1SWhitney Tsang " %i = phi i32 [ 0, %entry ], [ %inc, %for.body ]\n" 8502d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 8512d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 8522d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 8532d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 8542d0896c1SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 8552d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 8562d0896c1SWhitney Tsang "for.exit:\n" 8572d0896c1SWhitney Tsang " br label %for.end\n" 8582d0896c1SWhitney Tsang "for.end:\n" 8592d0896c1SWhitney Tsang " ret void\n" 8602d0896c1SWhitney Tsang "}\n"; 8612d0896c1SWhitney Tsang 8622d0896c1SWhitney Tsang // Parse the module. 8632d0896c1SWhitney Tsang LLVMContext Context; 8642d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 8652d0896c1SWhitney Tsang 8662d0896c1SWhitney Tsang runWithLoopInfoPlus( 8672d0896c1SWhitney Tsang *M, "foo", 8682d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 8692d0896c1SWhitney Tsang PostDominatorTree &PDT) { 8702d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 8712d0896c1SWhitney Tsang // First basic block is entry - skip it. 8722d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 8732d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 8742d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 8752d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 8762d0896c1SWhitney Tsang 8772d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 8782d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 8792d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 8802d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 8812d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 8822d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 8832d0896c1SWhitney Tsang ConstantInt *StepValue = 8842d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 8852d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 8862d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 8872d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 8882d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 8892d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 8902d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 8912d0896c1SWhitney Tsang }); 8922d0896c1SWhitney Tsang } 8932d0896c1SWhitney Tsang 8942d0896c1SWhitney Tsang TEST(LoopInfoTest, UnguardedLoopWithControlFlow) { 8952d0896c1SWhitney Tsang const char *ModuleStr = 8962d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub, i1 %cond) {\n" 8972d0896c1SWhitney Tsang "entry:\n" 8982d0896c1SWhitney Tsang " br i1 %cond, label %for.preheader, label %for.end\n" 8992d0896c1SWhitney Tsang "for.preheader:\n" 9002d0896c1SWhitney Tsang " br label %for.body\n" 9012d0896c1SWhitney Tsang "for.body:\n" 9022d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 9032d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 9042d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 9052d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 9062d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 9072d0896c1SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 9082d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 9092d0896c1SWhitney Tsang "for.exit:\n" 9102d0896c1SWhitney Tsang " br label %for.end\n" 9112d0896c1SWhitney Tsang "for.end:\n" 9122d0896c1SWhitney Tsang " ret void\n" 9132d0896c1SWhitney Tsang "}\n"; 9142d0896c1SWhitney Tsang 9152d0896c1SWhitney Tsang // Parse the module. 9162d0896c1SWhitney Tsang LLVMContext Context; 9172d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 9182d0896c1SWhitney Tsang 9192d0896c1SWhitney Tsang runWithLoopInfoPlus( 9202d0896c1SWhitney Tsang *M, "foo", 9212d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 9222d0896c1SWhitney Tsang PostDominatorTree &PDT) { 9232d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 9242d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 9252d0896c1SWhitney Tsang ++FI; 9262d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 9272d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 9282d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 9292d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 9302d0896c1SWhitney Tsang 9312d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 9322d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 9332d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 9342d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 9352d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 9362d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 9372d0896c1SWhitney Tsang ConstantInt *StepValue = 9382d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 9392d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 9402d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 9412d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 9422d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 9432d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 9442d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 9452d0896c1SWhitney Tsang }); 9462d0896c1SWhitney Tsang } 9472d0896c1SWhitney Tsang 9482d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopNest) { 9492d0896c1SWhitney Tsang const char *ModuleStr = 9502d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 9512d0896c1SWhitney Tsang "entry:\n" 9522d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 9532d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.outer.preheader, label %for.end\n" 9542d0896c1SWhitney Tsang "for.outer.preheader:\n" 9552d0896c1SWhitney Tsang " br label %for.outer\n" 9562d0896c1SWhitney Tsang "for.outer:\n" 9572d0896c1SWhitney Tsang " %j = phi i32 [ 0, %for.outer.preheader ], [ %inc.outer, %for.outer.latch ]\n" 9582d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.inner.preheader, label %for.outer.latch\n" 9592d0896c1SWhitney Tsang "for.inner.preheader:\n" 9602d0896c1SWhitney Tsang " br label %for.inner\n" 9612d0896c1SWhitney Tsang "for.inner:\n" 9622d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.inner.preheader ], [ %inc, %for.inner ]\n" 9632d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 9642d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 9652d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 9662d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 9672d0896c1SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 9682d0896c1SWhitney Tsang " br i1 %cmp, label %for.inner, label %for.inner.exit\n" 9692d0896c1SWhitney Tsang "for.inner.exit:\n" 9702d0896c1SWhitney Tsang " br label %for.outer.latch\n" 9712d0896c1SWhitney Tsang "for.outer.latch:\n" 9722d0896c1SWhitney Tsang " %inc.outer = add nsw i32 %j, 1\n" 9732d0896c1SWhitney Tsang " %cmp.outer = icmp slt i32 %inc.outer, %ub\n" 9742d0896c1SWhitney Tsang " br i1 %cmp.outer, label %for.outer, label %for.outer.exit\n" 9752d0896c1SWhitney Tsang "for.outer.exit:\n" 9762d0896c1SWhitney Tsang " br label %for.end\n" 9772d0896c1SWhitney Tsang "for.end:\n" 9782d0896c1SWhitney Tsang " ret void\n" 9792d0896c1SWhitney Tsang "}\n"; 9802d0896c1SWhitney Tsang 9812d0896c1SWhitney Tsang // Parse the module. 9822d0896c1SWhitney Tsang LLVMContext Context; 9832d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 9842d0896c1SWhitney Tsang 9852d0896c1SWhitney Tsang runWithLoopInfoPlus( 9862d0896c1SWhitney Tsang *M, "foo", 9872d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 9882d0896c1SWhitney Tsang PostDominatorTree &PDT) { 9892d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 9902d0896c1SWhitney Tsang // First two basic block are entry and for.outer.preheader - skip them. 9912d0896c1SWhitney Tsang ++FI; 9922d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 9932d0896c1SWhitney Tsang assert(Header->getName() == "for.outer"); 9942d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 9952d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 9962d0896c1SWhitney Tsang 9972d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 9982d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 9992d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 10002d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 10012d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 10022d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc.outer"); 10032d0896c1SWhitney Tsang ConstantInt *StepValue = 10042d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 10052d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 10062d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 10072d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 10082d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 10092d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 10102d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "j"); 10112d0896c1SWhitney Tsang 10122d0896c1SWhitney Tsang // Next two basic blocks are for.outer and for.inner.preheader - skip 10132d0896c1SWhitney Tsang // them. 10142d0896c1SWhitney Tsang ++FI; 10152d0896c1SWhitney Tsang Header = &*(++FI); 10162d0896c1SWhitney Tsang assert(Header->getName() == "for.inner"); 10172d0896c1SWhitney Tsang L = LI.getLoopFor(Header); 10182d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 10192d0896c1SWhitney Tsang 10202d0896c1SWhitney Tsang Optional<Loop::LoopBounds> InnerBounds = L->getBounds(SE); 10212d0896c1SWhitney Tsang EXPECT_NE(InnerBounds, None); 10222d0896c1SWhitney Tsang InitialIVValue = 10232d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&InnerBounds->getInitialIVValue()); 10242d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 10252d0896c1SWhitney Tsang EXPECT_EQ(InnerBounds->getStepInst().getName(), "inc"); 10262d0896c1SWhitney Tsang StepValue = dyn_cast_or_null<ConstantInt>(InnerBounds->getStepValue()); 10272d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 10282d0896c1SWhitney Tsang EXPECT_EQ(InnerBounds->getFinalIVValue().getName(), "ub"); 10292d0896c1SWhitney Tsang EXPECT_EQ(InnerBounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 10302d0896c1SWhitney Tsang EXPECT_EQ(InnerBounds->getDirection(), 10312d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 10322d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 10332d0896c1SWhitney Tsang }); 10342d0896c1SWhitney Tsang } 10352d0896c1SWhitney Tsang 10362d0896c1SWhitney Tsang TEST(LoopInfoTest, AuxiliaryIV) { 10372d0896c1SWhitney Tsang const char *ModuleStr = 10382d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 10392d0896c1SWhitney Tsang "entry:\n" 10402d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 10412d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 10422d0896c1SWhitney Tsang "for.preheader:\n" 10432d0896c1SWhitney Tsang " br label %for.body\n" 10442d0896c1SWhitney Tsang "for.body:\n" 10452d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 10462d0896c1SWhitney Tsang " %aux = phi i32 [ 0, %for.preheader ], [ %auxinc, %for.body ]\n" 10472d0896c1SWhitney Tsang " %loopvariant = phi i32 [ 0, %for.preheader ], [ %loopvariantinc, %for.body ]\n" 10482d0896c1SWhitney Tsang " %usedoutside = phi i32 [ 0, %for.preheader ], [ %usedoutsideinc, %for.body ]\n" 10492d0896c1SWhitney Tsang " %mulopcode = phi i32 [ 0, %for.preheader ], [ %mulopcodeinc, %for.body ]\n" 10502d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 10512d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 10522d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 10532d0896c1SWhitney Tsang " %mulopcodeinc = mul nsw i32 %mulopcode, 5\n" 10542d0896c1SWhitney Tsang " %usedoutsideinc = add nsw i32 %usedoutside, 5\n" 10552d0896c1SWhitney Tsang " %loopvariantinc = add nsw i32 %loopvariant, %i\n" 10562d0896c1SWhitney Tsang " %auxinc = add nsw i32 %aux, 5\n" 10572d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 10582d0896c1SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 10592d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 10602d0896c1SWhitney Tsang "for.exit:\n" 10612d0896c1SWhitney Tsang " %lcssa = phi i32 [ %usedoutside, %for.body ]\n" 10622d0896c1SWhitney Tsang " br label %for.end\n" 10632d0896c1SWhitney Tsang "for.end:\n" 10642d0896c1SWhitney Tsang " ret void\n" 10652d0896c1SWhitney Tsang "}\n"; 10662d0896c1SWhitney Tsang 10672d0896c1SWhitney Tsang // Parse the module. 10682d0896c1SWhitney Tsang LLVMContext Context; 10692d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 10702d0896c1SWhitney Tsang 10712d0896c1SWhitney Tsang runWithLoopInfoPlus( 10722d0896c1SWhitney Tsang *M, "foo", 10732d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 10742d0896c1SWhitney Tsang PostDominatorTree &PDT) { 10752d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 10762d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 10772d0896c1SWhitney Tsang ++FI; 10782d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 10792d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 10802d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 10812d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 10822d0896c1SWhitney Tsang 10832d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 10842d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 10852d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 10862d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 10872d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 10882d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 10892d0896c1SWhitney Tsang ConstantInt *StepValue = 10902d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 10912d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 10922d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 10932d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 10942d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 10952d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 10962d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 10972d0896c1SWhitney Tsang BasicBlock::iterator II = Header->begin(); 10982d0896c1SWhitney Tsang PHINode &Instruction_i = cast<PHINode>(*(II)); 10992d0896c1SWhitney Tsang EXPECT_TRUE(L->isAuxiliaryInductionVariable(Instruction_i, SE)); 11002d0896c1SWhitney Tsang PHINode &Instruction_aux = cast<PHINode>(*(++II)); 11012d0896c1SWhitney Tsang EXPECT_TRUE(L->isAuxiliaryInductionVariable(Instruction_aux, SE)); 11022d0896c1SWhitney Tsang PHINode &Instruction_loopvariant = cast<PHINode>(*(++II)); 11032d0896c1SWhitney Tsang EXPECT_FALSE( 11042d0896c1SWhitney Tsang L->isAuxiliaryInductionVariable(Instruction_loopvariant, SE)); 11052d0896c1SWhitney Tsang PHINode &Instruction_usedoutside = cast<PHINode>(*(++II)); 11062d0896c1SWhitney Tsang EXPECT_FALSE( 11072d0896c1SWhitney Tsang L->isAuxiliaryInductionVariable(Instruction_usedoutside, SE)); 11082d0896c1SWhitney Tsang PHINode &Instruction_mulopcode = cast<PHINode>(*(++II)); 11092d0896c1SWhitney Tsang EXPECT_FALSE( 11102d0896c1SWhitney Tsang L->isAuxiliaryInductionVariable(Instruction_mulopcode, SE)); 11112d0896c1SWhitney Tsang }); 11122d0896c1SWhitney Tsang } 1113*f1ee04c4SSerguei Katkov 1114*f1ee04c4SSerguei Katkov // Examine getUniqueExitBlocks/getUniqueNonLatchExitBlocks functions. 1115*f1ee04c4SSerguei Katkov TEST(LoopInfoTest, LoopUniqueExitBlocks) { 1116*f1ee04c4SSerguei Katkov const char *ModuleStr = 1117*f1ee04c4SSerguei Katkov "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n" 1118*f1ee04c4SSerguei Katkov "define void @foo(i32 %n, i1 %cond) {\n" 1119*f1ee04c4SSerguei Katkov "entry:\n" 1120*f1ee04c4SSerguei Katkov " br label %for.cond\n" 1121*f1ee04c4SSerguei Katkov "for.cond:\n" 1122*f1ee04c4SSerguei Katkov " %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]\n" 1123*f1ee04c4SSerguei Katkov " %cmp = icmp slt i32 %i.0, %n\n" 1124*f1ee04c4SSerguei Katkov " br i1 %cond, label %for.inc, label %for.end1\n" 1125*f1ee04c4SSerguei Katkov "for.inc:\n" 1126*f1ee04c4SSerguei Katkov " %inc = add nsw i32 %i.0, 1\n" 1127*f1ee04c4SSerguei Katkov " br i1 %cmp, label %for.cond, label %for.end2, !llvm.loop !0\n" 1128*f1ee04c4SSerguei Katkov "for.end1:\n" 1129*f1ee04c4SSerguei Katkov " br label %for.end\n" 1130*f1ee04c4SSerguei Katkov "for.end2:\n" 1131*f1ee04c4SSerguei Katkov " br label %for.end\n" 1132*f1ee04c4SSerguei Katkov "for.end:\n" 1133*f1ee04c4SSerguei Katkov " ret void\n" 1134*f1ee04c4SSerguei Katkov "}\n" 1135*f1ee04c4SSerguei Katkov "!0 = distinct !{!0, !1}\n" 1136*f1ee04c4SSerguei Katkov "!1 = !{!\"llvm.loop.distribute.enable\", i1 true}\n"; 1137*f1ee04c4SSerguei Katkov 1138*f1ee04c4SSerguei Katkov // Parse the module. 1139*f1ee04c4SSerguei Katkov LLVMContext Context; 1140*f1ee04c4SSerguei Katkov std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 1141*f1ee04c4SSerguei Katkov 1142*f1ee04c4SSerguei Katkov runWithLoopInfo(*M, "foo", [&](Function &F, LoopInfo &LI) { 1143*f1ee04c4SSerguei Katkov Function::iterator FI = F.begin(); 1144*f1ee04c4SSerguei Katkov // First basic block is entry - skip it. 1145*f1ee04c4SSerguei Katkov BasicBlock *Header = &*(++FI); 1146*f1ee04c4SSerguei Katkov assert(Header->getName() == "for.cond"); 1147*f1ee04c4SSerguei Katkov Loop *L = LI.getLoopFor(Header); 1148*f1ee04c4SSerguei Katkov 1149*f1ee04c4SSerguei Katkov SmallVector<BasicBlock *, 2> Exits; 1150*f1ee04c4SSerguei Katkov // This loop has 2 unique exits. 1151*f1ee04c4SSerguei Katkov L->getUniqueExitBlocks(Exits); 1152*f1ee04c4SSerguei Katkov EXPECT_TRUE(Exits.size() == 2); 1153*f1ee04c4SSerguei Katkov // And one unique non latch exit. 1154*f1ee04c4SSerguei Katkov Exits.clear(); 1155*f1ee04c4SSerguei Katkov L->getUniqueNonLatchExitBlocks(Exits); 1156*f1ee04c4SSerguei Katkov EXPECT_TRUE(Exits.size() == 1); 1157*f1ee04c4SSerguei Katkov }); 1158*f1ee04c4SSerguei Katkov } 1159