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