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" 10*2d0896c1SWhitney Tsang #include "llvm/Analysis/AssumptionCache.h" 11*2d0896c1SWhitney Tsang #include "llvm/Analysis/PostDominators.h" 12*2d0896c1SWhitney Tsang #include "llvm/Analysis/ScalarEvolution.h" 13*2d0896c1SWhitney 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 33*2d0896c1SWhitney Tsang /// Build the loop info and scalar evolution for the function and run the Test. 34*2d0896c1SWhitney Tsang static void runWithLoopInfoPlus( 35*2d0896c1SWhitney Tsang Module &M, StringRef FuncName, 36*2d0896c1SWhitney Tsang function_ref<void(Function &F, LoopInfo &LI, ScalarEvolution &SE, 37*2d0896c1SWhitney Tsang PostDominatorTree &PDT)> 38*2d0896c1SWhitney Tsang Test) { 39*2d0896c1SWhitney Tsang auto *F = M.getFunction(FuncName); 40*2d0896c1SWhitney Tsang ASSERT_NE(F, nullptr) << "Could not find " << FuncName; 41*2d0896c1SWhitney Tsang 42*2d0896c1SWhitney Tsang TargetLibraryInfoImpl TLII; 43*2d0896c1SWhitney Tsang TargetLibraryInfo TLI(TLII); 44*2d0896c1SWhitney Tsang AssumptionCache AC(*F); 45*2d0896c1SWhitney Tsang DominatorTree DT(*F); 46*2d0896c1SWhitney Tsang LoopInfo LI(DT); 47*2d0896c1SWhitney Tsang ScalarEvolution SE(*F, TLI, AC, DT, LI); 48*2d0896c1SWhitney Tsang 49*2d0896c1SWhitney Tsang PostDominatorTree PDT(*F); 50*2d0896c1SWhitney Tsang Test(*F, LI, SE, PDT); 51*2d0896c1SWhitney Tsang } 52*2d0896c1SWhitney 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 } 237*2d0896c1SWhitney Tsang 238*2d0896c1SWhitney Tsang TEST(LoopInfoTest, CanonicalLoop) { 239*2d0896c1SWhitney Tsang const char *ModuleStr = 240*2d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 241*2d0896c1SWhitney Tsang "entry:\n" 242*2d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 243*2d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 244*2d0896c1SWhitney Tsang "for.preheader:\n" 245*2d0896c1SWhitney Tsang " br label %for.body\n" 246*2d0896c1SWhitney Tsang "for.body:\n" 247*2d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 248*2d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 249*2d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 250*2d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 251*2d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 252*2d0896c1SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 253*2d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 254*2d0896c1SWhitney Tsang "for.exit:\n" 255*2d0896c1SWhitney Tsang " br label %for.end\n" 256*2d0896c1SWhitney Tsang "for.end:\n" 257*2d0896c1SWhitney Tsang " ret void\n" 258*2d0896c1SWhitney Tsang "}\n"; 259*2d0896c1SWhitney Tsang 260*2d0896c1SWhitney Tsang // Parse the module. 261*2d0896c1SWhitney Tsang LLVMContext Context; 262*2d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 263*2d0896c1SWhitney Tsang 264*2d0896c1SWhitney Tsang runWithLoopInfoPlus( 265*2d0896c1SWhitney Tsang *M, "foo", 266*2d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 267*2d0896c1SWhitney Tsang PostDominatorTree &PDT) { 268*2d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 269*2d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 270*2d0896c1SWhitney Tsang ++FI; 271*2d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 272*2d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 273*2d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 274*2d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 275*2d0896c1SWhitney Tsang 276*2d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 277*2d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 278*2d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 279*2d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 280*2d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 281*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 282*2d0896c1SWhitney Tsang ConstantInt *StepValue = 283*2d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 284*2d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 285*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 286*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 287*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 288*2d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 289*2d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 290*2d0896c1SWhitney Tsang }); 291*2d0896c1SWhitney Tsang } 292*2d0896c1SWhitney Tsang 293*2d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopWithInverseGuardSuccs) { 294*2d0896c1SWhitney Tsang const char *ModuleStr = 295*2d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 296*2d0896c1SWhitney Tsang "entry:\n" 297*2d0896c1SWhitney Tsang " %guardcmp = icmp sge i32 0, %ub\n" 298*2d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.end, label %for.preheader\n" 299*2d0896c1SWhitney Tsang "for.preheader:\n" 300*2d0896c1SWhitney Tsang " br label %for.body\n" 301*2d0896c1SWhitney Tsang "for.body:\n" 302*2d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 303*2d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 304*2d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 305*2d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 306*2d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 307*2d0896c1SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 308*2d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 309*2d0896c1SWhitney Tsang "for.exit:\n" 310*2d0896c1SWhitney Tsang " br label %for.end\n" 311*2d0896c1SWhitney Tsang "for.end:\n" 312*2d0896c1SWhitney Tsang " ret void\n" 313*2d0896c1SWhitney Tsang "}\n"; 314*2d0896c1SWhitney Tsang 315*2d0896c1SWhitney Tsang // Parse the module. 316*2d0896c1SWhitney Tsang LLVMContext Context; 317*2d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 318*2d0896c1SWhitney Tsang 319*2d0896c1SWhitney Tsang runWithLoopInfoPlus( 320*2d0896c1SWhitney Tsang *M, "foo", 321*2d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 322*2d0896c1SWhitney Tsang PostDominatorTree &PDT) { 323*2d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 324*2d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 325*2d0896c1SWhitney Tsang ++FI; 326*2d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 327*2d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 328*2d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 329*2d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 330*2d0896c1SWhitney Tsang 331*2d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 332*2d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 333*2d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 334*2d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 335*2d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 336*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 337*2d0896c1SWhitney Tsang ConstantInt *StepValue = 338*2d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 339*2d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 340*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 341*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 342*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 343*2d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 344*2d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 345*2d0896c1SWhitney Tsang }); 346*2d0896c1SWhitney Tsang } 347*2d0896c1SWhitney Tsang 348*2d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopWithSwappedGuardCmp) { 349*2d0896c1SWhitney Tsang const char *ModuleStr = 350*2d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 351*2d0896c1SWhitney Tsang "entry:\n" 352*2d0896c1SWhitney Tsang " %guardcmp = icmp sgt i32 %ub, 0\n" 353*2d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 354*2d0896c1SWhitney Tsang "for.preheader:\n" 355*2d0896c1SWhitney Tsang " br label %for.body\n" 356*2d0896c1SWhitney Tsang "for.body:\n" 357*2d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 358*2d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 359*2d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 360*2d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 361*2d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 362*2d0896c1SWhitney Tsang " %cmp = icmp sge i32 %inc, %ub\n" 363*2d0896c1SWhitney Tsang " br i1 %cmp, label %for.exit, label %for.body\n" 364*2d0896c1SWhitney Tsang "for.exit:\n" 365*2d0896c1SWhitney Tsang " br label %for.end\n" 366*2d0896c1SWhitney Tsang "for.end:\n" 367*2d0896c1SWhitney Tsang " ret void\n" 368*2d0896c1SWhitney Tsang "}\n"; 369*2d0896c1SWhitney Tsang 370*2d0896c1SWhitney Tsang // Parse the module. 371*2d0896c1SWhitney Tsang LLVMContext Context; 372*2d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 373*2d0896c1SWhitney Tsang 374*2d0896c1SWhitney Tsang runWithLoopInfoPlus( 375*2d0896c1SWhitney Tsang *M, "foo", 376*2d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 377*2d0896c1SWhitney Tsang PostDominatorTree &PDT) { 378*2d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 379*2d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 380*2d0896c1SWhitney Tsang ++FI; 381*2d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 382*2d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 383*2d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 384*2d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 385*2d0896c1SWhitney Tsang 386*2d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 387*2d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 388*2d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 389*2d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 390*2d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 391*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 392*2d0896c1SWhitney Tsang ConstantInt *StepValue = 393*2d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 394*2d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 395*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 396*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 397*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 398*2d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 399*2d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 400*2d0896c1SWhitney Tsang }); 401*2d0896c1SWhitney Tsang } 402*2d0896c1SWhitney Tsang 403*2d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopWithInverseLatchSuccs) { 404*2d0896c1SWhitney Tsang const char *ModuleStr = 405*2d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 406*2d0896c1SWhitney Tsang "entry:\n" 407*2d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 408*2d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 409*2d0896c1SWhitney Tsang "for.preheader:\n" 410*2d0896c1SWhitney Tsang " br label %for.body\n" 411*2d0896c1SWhitney Tsang "for.body:\n" 412*2d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 413*2d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 414*2d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 415*2d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 416*2d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 417*2d0896c1SWhitney Tsang " %cmp = icmp sge i32 %inc, %ub\n" 418*2d0896c1SWhitney Tsang " br i1 %cmp, label %for.exit, label %for.body\n" 419*2d0896c1SWhitney Tsang "for.exit:\n" 420*2d0896c1SWhitney Tsang " br label %for.end\n" 421*2d0896c1SWhitney Tsang "for.end:\n" 422*2d0896c1SWhitney Tsang " ret void\n" 423*2d0896c1SWhitney Tsang "}\n"; 424*2d0896c1SWhitney Tsang 425*2d0896c1SWhitney Tsang // Parse the module. 426*2d0896c1SWhitney Tsang LLVMContext Context; 427*2d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 428*2d0896c1SWhitney Tsang 429*2d0896c1SWhitney Tsang runWithLoopInfoPlus( 430*2d0896c1SWhitney Tsang *M, "foo", 431*2d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 432*2d0896c1SWhitney Tsang PostDominatorTree &PDT) { 433*2d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 434*2d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 435*2d0896c1SWhitney Tsang ++FI; 436*2d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 437*2d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 438*2d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 439*2d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 440*2d0896c1SWhitney Tsang 441*2d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 442*2d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 443*2d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 444*2d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 445*2d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 446*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 447*2d0896c1SWhitney Tsang ConstantInt *StepValue = 448*2d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 449*2d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 450*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 451*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 452*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 453*2d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 454*2d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 455*2d0896c1SWhitney Tsang }); 456*2d0896c1SWhitney Tsang } 457*2d0896c1SWhitney Tsang 458*2d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopWithLatchCmpNE) { 459*2d0896c1SWhitney Tsang const char *ModuleStr = 460*2d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 461*2d0896c1SWhitney Tsang "entry:\n" 462*2d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 463*2d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 464*2d0896c1SWhitney Tsang "for.preheader:\n" 465*2d0896c1SWhitney Tsang " br label %for.body\n" 466*2d0896c1SWhitney Tsang "for.body:\n" 467*2d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 468*2d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 469*2d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 470*2d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 471*2d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 472*2d0896c1SWhitney Tsang " %cmp = icmp ne i32 %i, %ub\n" 473*2d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 474*2d0896c1SWhitney Tsang "for.exit:\n" 475*2d0896c1SWhitney Tsang " br label %for.end\n" 476*2d0896c1SWhitney Tsang "for.end:\n" 477*2d0896c1SWhitney Tsang " ret void\n" 478*2d0896c1SWhitney Tsang "}\n"; 479*2d0896c1SWhitney Tsang 480*2d0896c1SWhitney Tsang // Parse the module. 481*2d0896c1SWhitney Tsang LLVMContext Context; 482*2d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 483*2d0896c1SWhitney Tsang 484*2d0896c1SWhitney Tsang runWithLoopInfoPlus( 485*2d0896c1SWhitney Tsang *M, "foo", 486*2d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 487*2d0896c1SWhitney Tsang PostDominatorTree &PDT) { 488*2d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 489*2d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 490*2d0896c1SWhitney Tsang ++FI; 491*2d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 492*2d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 493*2d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 494*2d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 495*2d0896c1SWhitney Tsang 496*2d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 497*2d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 498*2d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 499*2d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 500*2d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 501*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 502*2d0896c1SWhitney Tsang ConstantInt *StepValue = 503*2d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 504*2d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 505*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 506*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 507*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 508*2d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 509*2d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 510*2d0896c1SWhitney Tsang }); 511*2d0896c1SWhitney Tsang } 512*2d0896c1SWhitney Tsang 513*2d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopWithGuardCmpSLE) { 514*2d0896c1SWhitney Tsang const char *ModuleStr = 515*2d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 516*2d0896c1SWhitney Tsang "entry:\n" 517*2d0896c1SWhitney Tsang " %ubPlusOne = add i32 %ub, 1\n" 518*2d0896c1SWhitney Tsang " %guardcmp = icmp sle i32 0, %ub\n" 519*2d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 520*2d0896c1SWhitney Tsang "for.preheader:\n" 521*2d0896c1SWhitney Tsang " br label %for.body\n" 522*2d0896c1SWhitney Tsang "for.body:\n" 523*2d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 524*2d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 525*2d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 526*2d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 527*2d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 528*2d0896c1SWhitney Tsang " %cmp = icmp ne i32 %i, %ubPlusOne\n" 529*2d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 530*2d0896c1SWhitney Tsang "for.exit:\n" 531*2d0896c1SWhitney Tsang " br label %for.end\n" 532*2d0896c1SWhitney Tsang "for.end:\n" 533*2d0896c1SWhitney Tsang " ret void\n" 534*2d0896c1SWhitney Tsang "}\n"; 535*2d0896c1SWhitney Tsang 536*2d0896c1SWhitney Tsang // Parse the module. 537*2d0896c1SWhitney Tsang LLVMContext Context; 538*2d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 539*2d0896c1SWhitney Tsang 540*2d0896c1SWhitney Tsang runWithLoopInfoPlus( 541*2d0896c1SWhitney Tsang *M, "foo", 542*2d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 543*2d0896c1SWhitney Tsang PostDominatorTree &PDT) { 544*2d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 545*2d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 546*2d0896c1SWhitney Tsang ++FI; 547*2d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 548*2d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 549*2d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 550*2d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 551*2d0896c1SWhitney Tsang 552*2d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 553*2d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 554*2d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 555*2d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 556*2d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 557*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 558*2d0896c1SWhitney Tsang ConstantInt *StepValue = 559*2d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 560*2d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 561*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ubPlusOne"); 562*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 563*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 564*2d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 565*2d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 566*2d0896c1SWhitney Tsang }); 567*2d0896c1SWhitney Tsang } 568*2d0896c1SWhitney Tsang 569*2d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopNonConstantStep) { 570*2d0896c1SWhitney Tsang const char *ModuleStr = 571*2d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub, i32 %step) {\n" 572*2d0896c1SWhitney Tsang "entry:\n" 573*2d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 574*2d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 575*2d0896c1SWhitney Tsang "for.preheader:\n" 576*2d0896c1SWhitney Tsang " br label %for.body\n" 577*2d0896c1SWhitney Tsang "for.body:\n" 578*2d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 579*2d0896c1SWhitney Tsang " %idxprom = zext i32 %i to i64\n" 580*2d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 581*2d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 582*2d0896c1SWhitney Tsang " %inc = add nsw i32 %i, %step\n" 583*2d0896c1SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 584*2d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 585*2d0896c1SWhitney Tsang "for.exit:\n" 586*2d0896c1SWhitney Tsang " br label %for.end\n" 587*2d0896c1SWhitney Tsang "for.end:\n" 588*2d0896c1SWhitney Tsang " ret void\n" 589*2d0896c1SWhitney Tsang "}\n"; 590*2d0896c1SWhitney Tsang 591*2d0896c1SWhitney Tsang // Parse the module. 592*2d0896c1SWhitney Tsang LLVMContext Context; 593*2d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 594*2d0896c1SWhitney Tsang 595*2d0896c1SWhitney Tsang runWithLoopInfoPlus( 596*2d0896c1SWhitney Tsang *M, "foo", 597*2d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 598*2d0896c1SWhitney Tsang PostDominatorTree &PDT) { 599*2d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 600*2d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 601*2d0896c1SWhitney Tsang ++FI; 602*2d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 603*2d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 604*2d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 605*2d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 606*2d0896c1SWhitney Tsang 607*2d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 608*2d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 609*2d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 610*2d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 611*2d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 612*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 613*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepValue()->getName(), "step"); 614*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 615*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 616*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), Loop::LoopBounds::Direction::Unknown); 617*2d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 618*2d0896c1SWhitney Tsang }); 619*2d0896c1SWhitney Tsang } 620*2d0896c1SWhitney Tsang 621*2d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopUnsignedBounds) { 622*2d0896c1SWhitney Tsang const char *ModuleStr = 623*2d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 624*2d0896c1SWhitney Tsang "entry:\n" 625*2d0896c1SWhitney Tsang " %guardcmp = icmp ult i32 0, %ub\n" 626*2d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 627*2d0896c1SWhitney Tsang "for.preheader:\n" 628*2d0896c1SWhitney Tsang " br label %for.body\n" 629*2d0896c1SWhitney Tsang "for.body:\n" 630*2d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 631*2d0896c1SWhitney Tsang " %idxprom = zext i32 %i to i64\n" 632*2d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 633*2d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 634*2d0896c1SWhitney Tsang " %inc = add i32 %i, 1\n" 635*2d0896c1SWhitney Tsang " %cmp = icmp ult i32 %inc, %ub\n" 636*2d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 637*2d0896c1SWhitney Tsang "for.exit:\n" 638*2d0896c1SWhitney Tsang " br label %for.end\n" 639*2d0896c1SWhitney Tsang "for.end:\n" 640*2d0896c1SWhitney Tsang " ret void\n" 641*2d0896c1SWhitney Tsang "}\n"; 642*2d0896c1SWhitney Tsang 643*2d0896c1SWhitney Tsang // Parse the module. 644*2d0896c1SWhitney Tsang LLVMContext Context; 645*2d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 646*2d0896c1SWhitney Tsang 647*2d0896c1SWhitney Tsang runWithLoopInfoPlus( 648*2d0896c1SWhitney Tsang *M, "foo", 649*2d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 650*2d0896c1SWhitney Tsang PostDominatorTree &PDT) { 651*2d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 652*2d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 653*2d0896c1SWhitney Tsang ++FI; 654*2d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 655*2d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 656*2d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 657*2d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 658*2d0896c1SWhitney Tsang 659*2d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 660*2d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 661*2d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 662*2d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 663*2d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 664*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 665*2d0896c1SWhitney Tsang ConstantInt *StepValue = 666*2d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 667*2d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 668*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 669*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_ULT); 670*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 671*2d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 672*2d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 673*2d0896c1SWhitney Tsang }); 674*2d0896c1SWhitney Tsang } 675*2d0896c1SWhitney Tsang 676*2d0896c1SWhitney Tsang TEST(LoopInfoTest, DecreasingLoop) { 677*2d0896c1SWhitney Tsang const char *ModuleStr = 678*2d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 679*2d0896c1SWhitney Tsang "entry:\n" 680*2d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 681*2d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 682*2d0896c1SWhitney Tsang "for.preheader:\n" 683*2d0896c1SWhitney Tsang " br label %for.body\n" 684*2d0896c1SWhitney Tsang "for.body:\n" 685*2d0896c1SWhitney Tsang " %i = phi i32 [ %ub, %for.preheader ], [ %inc, %for.body ]\n" 686*2d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 687*2d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 688*2d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 689*2d0896c1SWhitney Tsang " %inc = sub nsw i32 %i, 1\n" 690*2d0896c1SWhitney Tsang " %cmp = icmp sgt i32 %inc, 0\n" 691*2d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 692*2d0896c1SWhitney Tsang "for.exit:\n" 693*2d0896c1SWhitney Tsang " br label %for.end\n" 694*2d0896c1SWhitney Tsang "for.end:\n" 695*2d0896c1SWhitney Tsang " ret void\n" 696*2d0896c1SWhitney Tsang "}\n"; 697*2d0896c1SWhitney Tsang 698*2d0896c1SWhitney Tsang // Parse the module. 699*2d0896c1SWhitney Tsang LLVMContext Context; 700*2d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 701*2d0896c1SWhitney Tsang 702*2d0896c1SWhitney Tsang runWithLoopInfoPlus( 703*2d0896c1SWhitney Tsang *M, "foo", 704*2d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 705*2d0896c1SWhitney Tsang PostDominatorTree &PDT) { 706*2d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 707*2d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 708*2d0896c1SWhitney Tsang ++FI; 709*2d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 710*2d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 711*2d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 712*2d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 713*2d0896c1SWhitney Tsang 714*2d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 715*2d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 716*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getInitialIVValue().getName(), "ub"); 717*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 718*2d0896c1SWhitney Tsang ConstantInt *StepValue = 719*2d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 720*2d0896c1SWhitney Tsang EXPECT_EQ(StepValue, nullptr); 721*2d0896c1SWhitney Tsang ConstantInt *FinalIVValue = 722*2d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getFinalIVValue()); 723*2d0896c1SWhitney Tsang EXPECT_TRUE(FinalIVValue && FinalIVValue->isZero()); 724*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SGT); 725*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 726*2d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Decreasing); 727*2d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 728*2d0896c1SWhitney Tsang }); 729*2d0896c1SWhitney Tsang } 730*2d0896c1SWhitney Tsang 731*2d0896c1SWhitney Tsang TEST(LoopInfoTest, CannotFindDirection) { 732*2d0896c1SWhitney Tsang const char *ModuleStr = 733*2d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub, i32 %step) {\n" 734*2d0896c1SWhitney Tsang "entry:\n" 735*2d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 736*2d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 737*2d0896c1SWhitney Tsang "for.preheader:\n" 738*2d0896c1SWhitney Tsang " br label %for.body\n" 739*2d0896c1SWhitney Tsang "for.body:\n" 740*2d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 741*2d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 742*2d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 743*2d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 744*2d0896c1SWhitney Tsang " %inc = add nsw i32 %i, %step\n" 745*2d0896c1SWhitney Tsang " %cmp = icmp ne i32 %i, %ub\n" 746*2d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 747*2d0896c1SWhitney Tsang "for.exit:\n" 748*2d0896c1SWhitney Tsang " br label %for.end\n" 749*2d0896c1SWhitney Tsang "for.end:\n" 750*2d0896c1SWhitney Tsang " ret void\n" 751*2d0896c1SWhitney Tsang "}\n"; 752*2d0896c1SWhitney Tsang 753*2d0896c1SWhitney Tsang // Parse the module. 754*2d0896c1SWhitney Tsang LLVMContext Context; 755*2d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 756*2d0896c1SWhitney Tsang 757*2d0896c1SWhitney Tsang runWithLoopInfoPlus(*M, "foo", 758*2d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 759*2d0896c1SWhitney Tsang PostDominatorTree &PDT) { 760*2d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 761*2d0896c1SWhitney Tsang // First two basic block are entry and for.preheader 762*2d0896c1SWhitney Tsang // - skip them. 763*2d0896c1SWhitney Tsang ++FI; 764*2d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 765*2d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 766*2d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 767*2d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 768*2d0896c1SWhitney Tsang 769*2d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 770*2d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 771*2d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 772*2d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 773*2d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 774*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 775*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepValue()->getName(), "step"); 776*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 777*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), 778*2d0896c1SWhitney Tsang ICmpInst::BAD_ICMP_PREDICATE); 779*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 780*2d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Unknown); 781*2d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 782*2d0896c1SWhitney Tsang }); 783*2d0896c1SWhitney Tsang } 784*2d0896c1SWhitney Tsang 785*2d0896c1SWhitney Tsang TEST(LoopInfoTest, ZextIndVar) { 786*2d0896c1SWhitney Tsang const char *ModuleStr = 787*2d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 788*2d0896c1SWhitney Tsang "entry:\n" 789*2d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 790*2d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 791*2d0896c1SWhitney Tsang "for.preheader:\n" 792*2d0896c1SWhitney Tsang " br label %for.body\n" 793*2d0896c1SWhitney Tsang "for.body:\n" 794*2d0896c1SWhitney Tsang " %indvars.iv = phi i64 [ 0, %for.preheader ], [ %indvars.iv.next, %for.body ]\n" 795*2d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 796*2d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 797*2d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 798*2d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 799*2d0896c1SWhitney Tsang " %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n" 800*2d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 801*2d0896c1SWhitney Tsang " %wide.trip.count = zext i32 %ub to i64\n" 802*2d0896c1SWhitney Tsang " %exitcond = icmp ne i64 %indvars.iv.next, %wide.trip.count\n" 803*2d0896c1SWhitney Tsang " br i1 %exitcond, label %for.body, label %for.exit\n" 804*2d0896c1SWhitney Tsang "for.exit:\n" 805*2d0896c1SWhitney Tsang " br label %for.end\n" 806*2d0896c1SWhitney Tsang "for.end:\n" 807*2d0896c1SWhitney Tsang " ret void\n" 808*2d0896c1SWhitney Tsang "}\n"; 809*2d0896c1SWhitney Tsang 810*2d0896c1SWhitney Tsang // Parse the module. 811*2d0896c1SWhitney Tsang LLVMContext Context; 812*2d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 813*2d0896c1SWhitney Tsang 814*2d0896c1SWhitney Tsang runWithLoopInfoPlus( 815*2d0896c1SWhitney Tsang *M, "foo", 816*2d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 817*2d0896c1SWhitney Tsang PostDominatorTree &PDT) { 818*2d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 819*2d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 820*2d0896c1SWhitney Tsang ++FI; 821*2d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 822*2d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 823*2d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 824*2d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 825*2d0896c1SWhitney Tsang 826*2d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 827*2d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 828*2d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 829*2d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 830*2d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 831*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "indvars.iv.next"); 832*2d0896c1SWhitney Tsang ConstantInt *StepValue = 833*2d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 834*2d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 835*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "wide.trip.count"); 836*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_NE); 837*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 838*2d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 839*2d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "indvars.iv"); 840*2d0896c1SWhitney Tsang }); 841*2d0896c1SWhitney Tsang } 842*2d0896c1SWhitney Tsang 843*2d0896c1SWhitney Tsang TEST(LoopInfoTest, UnguardedLoop) { 844*2d0896c1SWhitney Tsang const char *ModuleStr = 845*2d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 846*2d0896c1SWhitney Tsang "entry:\n" 847*2d0896c1SWhitney Tsang " br label %for.body\n" 848*2d0896c1SWhitney Tsang "for.body:\n" 849*2d0896c1SWhitney Tsang " %i = phi i32 [ 0, %entry ], [ %inc, %for.body ]\n" 850*2d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 851*2d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 852*2d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 853*2d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 854*2d0896c1SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 855*2d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 856*2d0896c1SWhitney Tsang "for.exit:\n" 857*2d0896c1SWhitney Tsang " br label %for.end\n" 858*2d0896c1SWhitney Tsang "for.end:\n" 859*2d0896c1SWhitney Tsang " ret void\n" 860*2d0896c1SWhitney Tsang "}\n"; 861*2d0896c1SWhitney Tsang 862*2d0896c1SWhitney Tsang // Parse the module. 863*2d0896c1SWhitney Tsang LLVMContext Context; 864*2d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 865*2d0896c1SWhitney Tsang 866*2d0896c1SWhitney Tsang runWithLoopInfoPlus( 867*2d0896c1SWhitney Tsang *M, "foo", 868*2d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 869*2d0896c1SWhitney Tsang PostDominatorTree &PDT) { 870*2d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 871*2d0896c1SWhitney Tsang // First basic block is entry - skip it. 872*2d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 873*2d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 874*2d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 875*2d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 876*2d0896c1SWhitney Tsang 877*2d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 878*2d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 879*2d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 880*2d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 881*2d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 882*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 883*2d0896c1SWhitney Tsang ConstantInt *StepValue = 884*2d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 885*2d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 886*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 887*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 888*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 889*2d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 890*2d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 891*2d0896c1SWhitney Tsang }); 892*2d0896c1SWhitney Tsang } 893*2d0896c1SWhitney Tsang 894*2d0896c1SWhitney Tsang TEST(LoopInfoTest, UnguardedLoopWithControlFlow) { 895*2d0896c1SWhitney Tsang const char *ModuleStr = 896*2d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub, i1 %cond) {\n" 897*2d0896c1SWhitney Tsang "entry:\n" 898*2d0896c1SWhitney Tsang " br i1 %cond, label %for.preheader, label %for.end\n" 899*2d0896c1SWhitney Tsang "for.preheader:\n" 900*2d0896c1SWhitney Tsang " br label %for.body\n" 901*2d0896c1SWhitney Tsang "for.body:\n" 902*2d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 903*2d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 904*2d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 905*2d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 906*2d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 907*2d0896c1SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 908*2d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 909*2d0896c1SWhitney Tsang "for.exit:\n" 910*2d0896c1SWhitney Tsang " br label %for.end\n" 911*2d0896c1SWhitney Tsang "for.end:\n" 912*2d0896c1SWhitney Tsang " ret void\n" 913*2d0896c1SWhitney Tsang "}\n"; 914*2d0896c1SWhitney Tsang 915*2d0896c1SWhitney Tsang // Parse the module. 916*2d0896c1SWhitney Tsang LLVMContext Context; 917*2d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 918*2d0896c1SWhitney Tsang 919*2d0896c1SWhitney Tsang runWithLoopInfoPlus( 920*2d0896c1SWhitney Tsang *M, "foo", 921*2d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 922*2d0896c1SWhitney Tsang PostDominatorTree &PDT) { 923*2d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 924*2d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 925*2d0896c1SWhitney Tsang ++FI; 926*2d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 927*2d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 928*2d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 929*2d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 930*2d0896c1SWhitney Tsang 931*2d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 932*2d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 933*2d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 934*2d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 935*2d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 936*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 937*2d0896c1SWhitney Tsang ConstantInt *StepValue = 938*2d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 939*2d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 940*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 941*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 942*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 943*2d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 944*2d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 945*2d0896c1SWhitney Tsang }); 946*2d0896c1SWhitney Tsang } 947*2d0896c1SWhitney Tsang 948*2d0896c1SWhitney Tsang TEST(LoopInfoTest, LoopNest) { 949*2d0896c1SWhitney Tsang const char *ModuleStr = 950*2d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 951*2d0896c1SWhitney Tsang "entry:\n" 952*2d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 953*2d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.outer.preheader, label %for.end\n" 954*2d0896c1SWhitney Tsang "for.outer.preheader:\n" 955*2d0896c1SWhitney Tsang " br label %for.outer\n" 956*2d0896c1SWhitney Tsang "for.outer:\n" 957*2d0896c1SWhitney Tsang " %j = phi i32 [ 0, %for.outer.preheader ], [ %inc.outer, %for.outer.latch ]\n" 958*2d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.inner.preheader, label %for.outer.latch\n" 959*2d0896c1SWhitney Tsang "for.inner.preheader:\n" 960*2d0896c1SWhitney Tsang " br label %for.inner\n" 961*2d0896c1SWhitney Tsang "for.inner:\n" 962*2d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.inner.preheader ], [ %inc, %for.inner ]\n" 963*2d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 964*2d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 965*2d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 966*2d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 967*2d0896c1SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 968*2d0896c1SWhitney Tsang " br i1 %cmp, label %for.inner, label %for.inner.exit\n" 969*2d0896c1SWhitney Tsang "for.inner.exit:\n" 970*2d0896c1SWhitney Tsang " br label %for.outer.latch\n" 971*2d0896c1SWhitney Tsang "for.outer.latch:\n" 972*2d0896c1SWhitney Tsang " %inc.outer = add nsw i32 %j, 1\n" 973*2d0896c1SWhitney Tsang " %cmp.outer = icmp slt i32 %inc.outer, %ub\n" 974*2d0896c1SWhitney Tsang " br i1 %cmp.outer, label %for.outer, label %for.outer.exit\n" 975*2d0896c1SWhitney Tsang "for.outer.exit:\n" 976*2d0896c1SWhitney Tsang " br label %for.end\n" 977*2d0896c1SWhitney Tsang "for.end:\n" 978*2d0896c1SWhitney Tsang " ret void\n" 979*2d0896c1SWhitney Tsang "}\n"; 980*2d0896c1SWhitney Tsang 981*2d0896c1SWhitney Tsang // Parse the module. 982*2d0896c1SWhitney Tsang LLVMContext Context; 983*2d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 984*2d0896c1SWhitney Tsang 985*2d0896c1SWhitney Tsang runWithLoopInfoPlus( 986*2d0896c1SWhitney Tsang *M, "foo", 987*2d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 988*2d0896c1SWhitney Tsang PostDominatorTree &PDT) { 989*2d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 990*2d0896c1SWhitney Tsang // First two basic block are entry and for.outer.preheader - skip them. 991*2d0896c1SWhitney Tsang ++FI; 992*2d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 993*2d0896c1SWhitney Tsang assert(Header->getName() == "for.outer"); 994*2d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 995*2d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 996*2d0896c1SWhitney Tsang 997*2d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 998*2d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 999*2d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 1000*2d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 1001*2d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 1002*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc.outer"); 1003*2d0896c1SWhitney Tsang ConstantInt *StepValue = 1004*2d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 1005*2d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 1006*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 1007*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 1008*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 1009*2d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 1010*2d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "j"); 1011*2d0896c1SWhitney Tsang 1012*2d0896c1SWhitney Tsang // Next two basic blocks are for.outer and for.inner.preheader - skip 1013*2d0896c1SWhitney Tsang // them. 1014*2d0896c1SWhitney Tsang ++FI; 1015*2d0896c1SWhitney Tsang Header = &*(++FI); 1016*2d0896c1SWhitney Tsang assert(Header->getName() == "for.inner"); 1017*2d0896c1SWhitney Tsang L = LI.getLoopFor(Header); 1018*2d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 1019*2d0896c1SWhitney Tsang 1020*2d0896c1SWhitney Tsang Optional<Loop::LoopBounds> InnerBounds = L->getBounds(SE); 1021*2d0896c1SWhitney Tsang EXPECT_NE(InnerBounds, None); 1022*2d0896c1SWhitney Tsang InitialIVValue = 1023*2d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&InnerBounds->getInitialIVValue()); 1024*2d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 1025*2d0896c1SWhitney Tsang EXPECT_EQ(InnerBounds->getStepInst().getName(), "inc"); 1026*2d0896c1SWhitney Tsang StepValue = dyn_cast_or_null<ConstantInt>(InnerBounds->getStepValue()); 1027*2d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 1028*2d0896c1SWhitney Tsang EXPECT_EQ(InnerBounds->getFinalIVValue().getName(), "ub"); 1029*2d0896c1SWhitney Tsang EXPECT_EQ(InnerBounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 1030*2d0896c1SWhitney Tsang EXPECT_EQ(InnerBounds->getDirection(), 1031*2d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 1032*2d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 1033*2d0896c1SWhitney Tsang }); 1034*2d0896c1SWhitney Tsang } 1035*2d0896c1SWhitney Tsang 1036*2d0896c1SWhitney Tsang TEST(LoopInfoTest, AuxiliaryIV) { 1037*2d0896c1SWhitney Tsang const char *ModuleStr = 1038*2d0896c1SWhitney Tsang "define void @foo(i32* %A, i32 %ub) {\n" 1039*2d0896c1SWhitney Tsang "entry:\n" 1040*2d0896c1SWhitney Tsang " %guardcmp = icmp slt i32 0, %ub\n" 1041*2d0896c1SWhitney Tsang " br i1 %guardcmp, label %for.preheader, label %for.end\n" 1042*2d0896c1SWhitney Tsang "for.preheader:\n" 1043*2d0896c1SWhitney Tsang " br label %for.body\n" 1044*2d0896c1SWhitney Tsang "for.body:\n" 1045*2d0896c1SWhitney Tsang " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" 1046*2d0896c1SWhitney Tsang " %aux = phi i32 [ 0, %for.preheader ], [ %auxinc, %for.body ]\n" 1047*2d0896c1SWhitney Tsang " %loopvariant = phi i32 [ 0, %for.preheader ], [ %loopvariantinc, %for.body ]\n" 1048*2d0896c1SWhitney Tsang " %usedoutside = phi i32 [ 0, %for.preheader ], [ %usedoutsideinc, %for.body ]\n" 1049*2d0896c1SWhitney Tsang " %mulopcode = phi i32 [ 0, %for.preheader ], [ %mulopcodeinc, %for.body ]\n" 1050*2d0896c1SWhitney Tsang " %idxprom = sext i32 %i to i64\n" 1051*2d0896c1SWhitney Tsang " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" 1052*2d0896c1SWhitney Tsang " store i32 %i, i32* %arrayidx, align 4\n" 1053*2d0896c1SWhitney Tsang " %mulopcodeinc = mul nsw i32 %mulopcode, 5\n" 1054*2d0896c1SWhitney Tsang " %usedoutsideinc = add nsw i32 %usedoutside, 5\n" 1055*2d0896c1SWhitney Tsang " %loopvariantinc = add nsw i32 %loopvariant, %i\n" 1056*2d0896c1SWhitney Tsang " %auxinc = add nsw i32 %aux, 5\n" 1057*2d0896c1SWhitney Tsang " %inc = add nsw i32 %i, 1\n" 1058*2d0896c1SWhitney Tsang " %cmp = icmp slt i32 %inc, %ub\n" 1059*2d0896c1SWhitney Tsang " br i1 %cmp, label %for.body, label %for.exit\n" 1060*2d0896c1SWhitney Tsang "for.exit:\n" 1061*2d0896c1SWhitney Tsang " %lcssa = phi i32 [ %usedoutside, %for.body ]\n" 1062*2d0896c1SWhitney Tsang " br label %for.end\n" 1063*2d0896c1SWhitney Tsang "for.end:\n" 1064*2d0896c1SWhitney Tsang " ret void\n" 1065*2d0896c1SWhitney Tsang "}\n"; 1066*2d0896c1SWhitney Tsang 1067*2d0896c1SWhitney Tsang // Parse the module. 1068*2d0896c1SWhitney Tsang LLVMContext Context; 1069*2d0896c1SWhitney Tsang std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 1070*2d0896c1SWhitney Tsang 1071*2d0896c1SWhitney Tsang runWithLoopInfoPlus( 1072*2d0896c1SWhitney Tsang *M, "foo", 1073*2d0896c1SWhitney Tsang [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, 1074*2d0896c1SWhitney Tsang PostDominatorTree &PDT) { 1075*2d0896c1SWhitney Tsang Function::iterator FI = F.begin(); 1076*2d0896c1SWhitney Tsang // First two basic block are entry and for.preheader - skip them. 1077*2d0896c1SWhitney Tsang ++FI; 1078*2d0896c1SWhitney Tsang BasicBlock *Header = &*(++FI); 1079*2d0896c1SWhitney Tsang assert(Header->getName() == "for.body"); 1080*2d0896c1SWhitney Tsang Loop *L = LI.getLoopFor(Header); 1081*2d0896c1SWhitney Tsang EXPECT_NE(L, nullptr); 1082*2d0896c1SWhitney Tsang 1083*2d0896c1SWhitney Tsang Optional<Loop::LoopBounds> Bounds = L->getBounds(SE); 1084*2d0896c1SWhitney Tsang EXPECT_NE(Bounds, None); 1085*2d0896c1SWhitney Tsang ConstantInt *InitialIVValue = 1086*2d0896c1SWhitney Tsang dyn_cast<ConstantInt>(&Bounds->getInitialIVValue()); 1087*2d0896c1SWhitney Tsang EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); 1088*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); 1089*2d0896c1SWhitney Tsang ConstantInt *StepValue = 1090*2d0896c1SWhitney Tsang dyn_cast_or_null<ConstantInt>(Bounds->getStepValue()); 1091*2d0896c1SWhitney Tsang EXPECT_TRUE(StepValue && StepValue->isOne()); 1092*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); 1093*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); 1094*2d0896c1SWhitney Tsang EXPECT_EQ(Bounds->getDirection(), 1095*2d0896c1SWhitney Tsang Loop::LoopBounds::Direction::Increasing); 1096*2d0896c1SWhitney Tsang EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); 1097*2d0896c1SWhitney Tsang BasicBlock::iterator II = Header->begin(); 1098*2d0896c1SWhitney Tsang PHINode &Instruction_i = cast<PHINode>(*(II)); 1099*2d0896c1SWhitney Tsang EXPECT_TRUE(L->isAuxiliaryInductionVariable(Instruction_i, SE)); 1100*2d0896c1SWhitney Tsang PHINode &Instruction_aux = cast<PHINode>(*(++II)); 1101*2d0896c1SWhitney Tsang EXPECT_TRUE(L->isAuxiliaryInductionVariable(Instruction_aux, SE)); 1102*2d0896c1SWhitney Tsang PHINode &Instruction_loopvariant = cast<PHINode>(*(++II)); 1103*2d0896c1SWhitney Tsang EXPECT_FALSE( 1104*2d0896c1SWhitney Tsang L->isAuxiliaryInductionVariable(Instruction_loopvariant, SE)); 1105*2d0896c1SWhitney Tsang PHINode &Instruction_usedoutside = cast<PHINode>(*(++II)); 1106*2d0896c1SWhitney Tsang EXPECT_FALSE( 1107*2d0896c1SWhitney Tsang L->isAuxiliaryInductionVariable(Instruction_usedoutside, SE)); 1108*2d0896c1SWhitney Tsang PHINode &Instruction_mulopcode = cast<PHINode>(*(++II)); 1109*2d0896c1SWhitney Tsang EXPECT_FALSE( 1110*2d0896c1SWhitney Tsang L->isAuxiliaryInductionVariable(Instruction_mulopcode, SE)); 1111*2d0896c1SWhitney Tsang }); 1112*2d0896c1SWhitney Tsang } 1113