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