1ca02360fSXin Tong //===- LoopInfoTest.cpp - LoopInfo unit tests -----------------------------===// 2ca02360fSXin Tong // 3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6ca02360fSXin Tong // 7ca02360fSXin Tong //===----------------------------------------------------------------------===// 8ca02360fSXin Tong 9ca02360fSXin Tong #include "llvm/Analysis/LoopInfo.h" 10ca02360fSXin Tong #include "llvm/AsmParser/Parser.h" 11ca02360fSXin Tong #include "llvm/IR/Dominators.h" 12ca02360fSXin Tong #include "llvm/Support/SourceMgr.h" 13ca02360fSXin Tong #include "gtest/gtest.h" 14ca02360fSXin Tong 15ca02360fSXin Tong using namespace llvm; 16ca02360fSXin Tong 1743c1a264SXin Tong /// Build the loop info for the function and run the Test. 1843c1a264SXin Tong static void 1943c1a264SXin Tong runWithLoopInfo(Module &M, StringRef FuncName, 2043c1a264SXin Tong function_ref<void(Function &F, LoopInfo &LI)> Test) { 2143c1a264SXin Tong auto *F = M.getFunction(FuncName); 2243c1a264SXin Tong ASSERT_NE(F, nullptr) << "Could not find " << FuncName; 2343c1a264SXin Tong // Compute the dominator tree and the loop info for the function. 2443c1a264SXin Tong DominatorTree DT(*F); 2543c1a264SXin Tong LoopInfo LI(DT); 2643c1a264SXin Tong Test(*F, LI); 2743c1a264SXin Tong } 2843c1a264SXin Tong 29ca02360fSXin Tong static std::unique_ptr<Module> makeLLVMModule(LLVMContext &Context, 30ca02360fSXin Tong const char *ModuleStr) { 31ca02360fSXin Tong SMDiagnostic Err; 32ca02360fSXin Tong return parseAssemblyString(ModuleStr, Err, Context); 33ca02360fSXin Tong } 34ca02360fSXin Tong 35ca02360fSXin Tong // This tests that for a loop with a single latch, we get the loop id from 36ca02360fSXin Tong // its only latch, even in case the loop may not be in a simplified form. 37ca02360fSXin Tong TEST(LoopInfoTest, LoopWithSingleLatch) { 38ca02360fSXin Tong const char *ModuleStr = 39ca02360fSXin Tong "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n" 40ca02360fSXin Tong "define void @foo(i32 %n) {\n" 41ca02360fSXin Tong "entry:\n" 42ca02360fSXin Tong " br i1 undef, label %for.cond, label %for.end\n" 43ca02360fSXin Tong "for.cond:\n" 44ca02360fSXin Tong " %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]\n" 45ca02360fSXin Tong " %cmp = icmp slt i32 %i.0, %n\n" 46ca02360fSXin Tong " br i1 %cmp, label %for.inc, label %for.end\n" 47ca02360fSXin Tong "for.inc:\n" 48ca02360fSXin Tong " %inc = add nsw i32 %i.0, 1\n" 49ca02360fSXin Tong " br label %for.cond, !llvm.loop !0\n" 50ca02360fSXin Tong "for.end:\n" 51ca02360fSXin Tong " ret void\n" 52ca02360fSXin Tong "}\n" 53ca02360fSXin Tong "!0 = distinct !{!0, !1}\n" 54ca02360fSXin Tong "!1 = !{!\"llvm.loop.distribute.enable\", i1 true}\n"; 55ca02360fSXin Tong 56ca02360fSXin Tong // Parse the module. 57ca02360fSXin Tong LLVMContext Context; 58ca02360fSXin Tong std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 59ca02360fSXin Tong 6043c1a264SXin Tong runWithLoopInfo(*M, "foo", [&](Function &F, LoopInfo &LI) { 61ca02360fSXin Tong Function::iterator FI = F.begin(); 6243c1a264SXin Tong // First basic block is entry - skip it. 6343c1a264SXin Tong BasicBlock *Header = &*(++FI); 64ca02360fSXin Tong assert(Header->getName() == "for.cond"); 65ca02360fSXin Tong Loop *L = LI.getLoopFor(Header); 66ca02360fSXin Tong 67ca02360fSXin Tong // This loop is not in simplified form. 68ca02360fSXin Tong EXPECT_FALSE(L->isLoopSimplifyForm()); 69ca02360fSXin Tong 70ca02360fSXin Tong // Analyze the loop metadata id. 71ca02360fSXin Tong bool loopIDFoundAndSet = false; 72ca02360fSXin Tong // Try to get and set the metadata id for the loop. 73ca02360fSXin Tong if (MDNode *D = L->getLoopID()) { 74ca02360fSXin Tong L->setLoopID(D); 75ca02360fSXin Tong loopIDFoundAndSet = true; 76ca02360fSXin Tong } 77ca02360fSXin Tong 78ca02360fSXin Tong // We must have successfully found and set the loop id in the 79ca02360fSXin Tong // only latch the loop has. 80ca02360fSXin Tong EXPECT_TRUE(loopIDFoundAndSet); 8143c1a264SXin Tong }); 82ca02360fSXin Tong } 83f002264dSChandler Carruth 84a58e9214SJohannes Doerfert // Test loop id handling for a loop with multiple latches. 85a58e9214SJohannes Doerfert TEST(LoopInfoTest, LoopWithMultipleLatches) { 86a58e9214SJohannes Doerfert const char *ModuleStr = 87a58e9214SJohannes Doerfert "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n" 88a58e9214SJohannes Doerfert "define void @foo(i32 %n) {\n" 89a58e9214SJohannes Doerfert "entry:\n" 90a58e9214SJohannes Doerfert " br i1 undef, label %for.cond, label %for.end\n" 91a58e9214SJohannes Doerfert "for.cond:\n" 92a58e9214SJohannes Doerfert " %i.0 = phi i32 [ 0, %entry ], [ %inc, %latch.1 ], [ %inc, %latch.2 ]\n" 93a58e9214SJohannes Doerfert " %inc = add nsw i32 %i.0, 1\n" 94a58e9214SJohannes Doerfert " %cmp = icmp slt i32 %i.0, %n\n" 95a58e9214SJohannes Doerfert " br i1 %cmp, label %latch.1, label %for.end\n" 96a58e9214SJohannes Doerfert "latch.1:\n" 97a58e9214SJohannes Doerfert " br i1 undef, label %for.cond, label %latch.2, !llvm.loop !0\n" 98a58e9214SJohannes Doerfert "latch.2:\n" 99a58e9214SJohannes Doerfert " br label %for.cond, !llvm.loop !0\n" 100a58e9214SJohannes Doerfert "for.end:\n" 101a58e9214SJohannes Doerfert " ret void\n" 102a58e9214SJohannes Doerfert "}\n" 103a58e9214SJohannes Doerfert "!0 = distinct !{!0, !1}\n" 104a58e9214SJohannes Doerfert "!1 = !{!\"llvm.loop.distribute.enable\", i1 true}\n"; 105a58e9214SJohannes Doerfert 106a58e9214SJohannes Doerfert // Parse the module. 107a58e9214SJohannes Doerfert LLVMContext Context; 108a58e9214SJohannes Doerfert std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 109a58e9214SJohannes Doerfert 110a58e9214SJohannes Doerfert runWithLoopInfo(*M, "foo", [&](Function &F, LoopInfo &LI) { 111a58e9214SJohannes Doerfert Function::iterator FI = F.begin(); 112a58e9214SJohannes Doerfert // First basic block is entry - skip it. 113a58e9214SJohannes Doerfert BasicBlock *Header = &*(++FI); 114a58e9214SJohannes Doerfert assert(Header->getName() == "for.cond"); 115a58e9214SJohannes Doerfert Loop *L = LI.getLoopFor(Header); 116a58e9214SJohannes Doerfert EXPECT_NE(L, nullptr); 117a58e9214SJohannes Doerfert 118a58e9214SJohannes Doerfert // This loop is not in simplified form. 119a58e9214SJohannes Doerfert EXPECT_FALSE(L->isLoopSimplifyForm()); 120a58e9214SJohannes Doerfert 121a58e9214SJohannes Doerfert // Try to get and set the metadata id for the loop. 122a58e9214SJohannes Doerfert MDNode *OldLoopID = L->getLoopID(); 123a58e9214SJohannes Doerfert EXPECT_NE(OldLoopID, nullptr); 124a58e9214SJohannes Doerfert 125a58e9214SJohannes Doerfert MDNode *NewLoopID = MDNode::get(Context, {nullptr}); 126a58e9214SJohannes Doerfert // Set operand 0 to refer to the loop id itself. 127a58e9214SJohannes Doerfert NewLoopID->replaceOperandWith(0, NewLoopID); 128a58e9214SJohannes Doerfert 129a58e9214SJohannes Doerfert L->setLoopID(NewLoopID); 130a58e9214SJohannes Doerfert EXPECT_EQ(L->getLoopID(), NewLoopID); 131a58e9214SJohannes Doerfert EXPECT_NE(L->getLoopID(), OldLoopID); 132a58e9214SJohannes Doerfert 133a58e9214SJohannes Doerfert L->setLoopID(OldLoopID); 134a58e9214SJohannes Doerfert EXPECT_EQ(L->getLoopID(), OldLoopID); 135a58e9214SJohannes Doerfert EXPECT_NE(L->getLoopID(), NewLoopID); 136a58e9214SJohannes Doerfert }); 137a58e9214SJohannes Doerfert } 138a58e9214SJohannes Doerfert 139f002264dSChandler Carruth TEST(LoopInfoTest, PreorderTraversals) { 140f002264dSChandler Carruth const char *ModuleStr = "define void @f() {\n" 141f002264dSChandler Carruth "entry:\n" 142f002264dSChandler Carruth " br label %loop.0\n" 143f002264dSChandler Carruth "loop.0:\n" 144f002264dSChandler Carruth " br i1 undef, label %loop.0.0, label %loop.1\n" 145f002264dSChandler Carruth "loop.0.0:\n" 146f002264dSChandler Carruth " br i1 undef, label %loop.0.0, label %loop.0.1\n" 147f002264dSChandler Carruth "loop.0.1:\n" 148f002264dSChandler Carruth " br i1 undef, label %loop.0.1, label %loop.0.2\n" 149f002264dSChandler Carruth "loop.0.2:\n" 150f002264dSChandler Carruth " br i1 undef, label %loop.0.2, label %loop.0\n" 151f002264dSChandler Carruth "loop.1:\n" 152f002264dSChandler Carruth " br i1 undef, label %loop.1.0, label %end\n" 153f002264dSChandler Carruth "loop.1.0:\n" 154f002264dSChandler Carruth " br i1 undef, label %loop.1.0, label %loop.1.1\n" 155f002264dSChandler Carruth "loop.1.1:\n" 156f002264dSChandler Carruth " br i1 undef, label %loop.1.1, label %loop.1.2\n" 157f002264dSChandler Carruth "loop.1.2:\n" 158f002264dSChandler Carruth " br i1 undef, label %loop.1.2, label %loop.1\n" 159f002264dSChandler Carruth "end:\n" 160f002264dSChandler Carruth " ret void\n" 161f002264dSChandler Carruth "}\n"; 162f002264dSChandler Carruth // Parse the module. 163f002264dSChandler Carruth LLVMContext Context; 164f002264dSChandler Carruth std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr); 165f002264dSChandler Carruth Function &F = *M->begin(); 166f002264dSChandler Carruth 167f002264dSChandler Carruth DominatorTree DT(F); 168f002264dSChandler Carruth LoopInfo LI; 169f002264dSChandler Carruth LI.analyze(DT); 170f002264dSChandler Carruth 171f002264dSChandler Carruth Function::iterator I = F.begin(); 172f002264dSChandler Carruth ASSERT_EQ("entry", I->getName()); 173f002264dSChandler Carruth ++I; 174f002264dSChandler Carruth Loop &L_0 = *LI.getLoopFor(&*I++); 175f002264dSChandler Carruth ASSERT_EQ("loop.0", L_0.getHeader()->getName()); 176f002264dSChandler Carruth Loop &L_0_0 = *LI.getLoopFor(&*I++); 177f002264dSChandler Carruth ASSERT_EQ("loop.0.0", L_0_0.getHeader()->getName()); 178f002264dSChandler Carruth Loop &L_0_1 = *LI.getLoopFor(&*I++); 179f002264dSChandler Carruth ASSERT_EQ("loop.0.1", L_0_1.getHeader()->getName()); 180f002264dSChandler Carruth Loop &L_0_2 = *LI.getLoopFor(&*I++); 181f002264dSChandler Carruth ASSERT_EQ("loop.0.2", L_0_2.getHeader()->getName()); 182f002264dSChandler Carruth Loop &L_1 = *LI.getLoopFor(&*I++); 183f002264dSChandler Carruth ASSERT_EQ("loop.1", L_1.getHeader()->getName()); 184f002264dSChandler Carruth Loop &L_1_0 = *LI.getLoopFor(&*I++); 185f002264dSChandler Carruth ASSERT_EQ("loop.1.0", L_1_0.getHeader()->getName()); 186f002264dSChandler Carruth Loop &L_1_1 = *LI.getLoopFor(&*I++); 187f002264dSChandler Carruth ASSERT_EQ("loop.1.1", L_1_1.getHeader()->getName()); 188f002264dSChandler Carruth Loop &L_1_2 = *LI.getLoopFor(&*I++); 189f002264dSChandler Carruth ASSERT_EQ("loop.1.2", L_1_2.getHeader()->getName()); 190f002264dSChandler Carruth 191f002264dSChandler Carruth auto Preorder = LI.getLoopsInPreorder(); 192f002264dSChandler Carruth ASSERT_EQ(8u, Preorder.size()); 193f002264dSChandler Carruth EXPECT_EQ(&L_0, Preorder[0]); 194f002264dSChandler Carruth EXPECT_EQ(&L_0_0, Preorder[1]); 195f002264dSChandler Carruth EXPECT_EQ(&L_0_1, Preorder[2]); 196f002264dSChandler Carruth EXPECT_EQ(&L_0_2, Preorder[3]); 197f002264dSChandler Carruth EXPECT_EQ(&L_1, Preorder[4]); 198f002264dSChandler Carruth EXPECT_EQ(&L_1_0, Preorder[5]); 199f002264dSChandler Carruth EXPECT_EQ(&L_1_1, Preorder[6]); 200f002264dSChandler Carruth EXPECT_EQ(&L_1_2, Preorder[7]); 201f002264dSChandler Carruth 202f002264dSChandler Carruth auto ReverseSiblingPreorder = LI.getLoopsInReverseSiblingPreorder(); 203f002264dSChandler Carruth ASSERT_EQ(8u, ReverseSiblingPreorder.size()); 204f002264dSChandler Carruth EXPECT_EQ(&L_1, ReverseSiblingPreorder[0]); 205f002264dSChandler Carruth EXPECT_EQ(&L_1_2, ReverseSiblingPreorder[1]); 206f002264dSChandler Carruth EXPECT_EQ(&L_1_1, ReverseSiblingPreorder[2]); 207f002264dSChandler Carruth EXPECT_EQ(&L_1_0, ReverseSiblingPreorder[3]); 208f002264dSChandler Carruth EXPECT_EQ(&L_0, ReverseSiblingPreorder[4]); 209f002264dSChandler Carruth EXPECT_EQ(&L_0_2, ReverseSiblingPreorder[5]); 210f002264dSChandler Carruth EXPECT_EQ(&L_0_1, ReverseSiblingPreorder[6]); 211f002264dSChandler Carruth EXPECT_EQ(&L_0_0, ReverseSiblingPreorder[7]); 212f002264dSChandler Carruth } 213