1 //===- LoopUtilsTest.cpp - Unit tests for LoopUtils -----------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Transforms/Utils/LoopUtils.h"
10 #include "llvm/Analysis/AssumptionCache.h"
11 #include "llvm/Analysis/LoopInfo.h"
12 #include "llvm/Analysis/ScalarEvolution.h"
13 #include "llvm/Analysis/TargetLibraryInfo.h"
14 #include "llvm/AsmParser/Parser.h"
15 #include "llvm/IR/Dominators.h"
16 #include "llvm/IR/Module.h"
17 #include "llvm/Support/SourceMgr.h"
18 #include "gtest/gtest.h"
22 static std::unique_ptr
<Module
> parseIR(LLVMContext
&C
, const char *IR
) {
24 std::unique_ptr
<Module
> Mod
= parseAssemblyString(IR
, Err
, C
);
26 Err
.print("LoopUtilsTests", errs());
30 static void run(Module
&M
, StringRef FuncName
,
31 function_ref
<void(Function
&F
, DominatorTree
&DT
,
32 ScalarEvolution
&SE
, LoopInfo
&LI
)>
34 Function
*F
= M
.getFunction(FuncName
);
36 TargetLibraryInfoImpl TLII
;
37 TargetLibraryInfo
TLI(TLII
);
38 AssumptionCache
AC(*F
);
40 ScalarEvolution
SE(*F
, TLI
, AC
, DT
, LI
);
44 TEST(LoopUtils
, DeleteDeadLoopNest
) {
46 std::unique_ptr
<Module
> M
=
47 parseIR(C
, "define void @foo() {\n"
51 " %i = phi i64 [ 0, %entry ], [ %inc.i, %for.i.latch ]\n"
54 " %j = phi i64 [ 0, %for.i ], [ %inc.j, %for.j ]\n"
55 " %inc.j = add nsw i64 %j, 1\n"
56 " %cmp.j = icmp slt i64 %inc.j, 100\n"
57 " br i1 %cmp.j, label %for.j, label %for.k.preheader\n"
61 " %k = phi i64 [ %inc.k, %for.k ], [ 0, %for.k.preheader ]\n"
62 " %inc.k = add nsw i64 %k, 1\n"
63 " %cmp.k = icmp slt i64 %inc.k, 100\n"
64 " br i1 %cmp.k, label %for.k, label %for.i.latch\n"
66 " %inc.i = add nsw i64 %i, 1\n"
67 " %cmp.i = icmp slt i64 %inc.i, 100\n"
68 " br i1 %cmp.i, label %for.i, label %for.end\n"
74 [&](Function
&F
, DominatorTree
&DT
, ScalarEvolution
&SE
, LoopInfo
&LI
) {
75 assert(LI
.begin() != LI
.end() && "Expecting loops in function F");
76 Loop
*L
= *LI
.begin();
77 assert(L
&& L
->getName() == "for.i" && "Expecting loop for.i");
79 deleteDeadLoop(L
, &DT
, &SE
, &LI
);
81 assert(DT
.verify(DominatorTree::VerificationLevel::Fast
) &&
82 "Expecting valid dominator tree");
84 assert(LI
.begin() == LI
.end() &&
85 "Expecting no loops left in function F");
88 Function::iterator FI
= F
.begin();
89 BasicBlock
*Entry
= &*(FI
++);
90 assert(Entry
->getName() == "entry" && "Expecting BasicBlock entry");
91 const BranchInst
*BI
= dyn_cast
<BranchInst
>(Entry
->getTerminator());
92 assert(BI
&& "Expecting valid branch instruction");
93 EXPECT_EQ(BI
->getNumSuccessors(), (unsigned)1);
94 EXPECT_EQ(BI
->getSuccessor(0)->getName(), "for.end");
98 TEST(LoopUtils
, IsKnownPositiveInLoopTest
) {
100 std::unique_ptr
<Module
> M
=
101 parseIR(C
, "define void @foo(i32 %n, i1 %c) {\n"
103 " %is.positive = icmp sgt i32 %n, 0\n"
104 " br i1 %is.positive, label %loop, label %exit\n"
106 " br i1 %c, label %loop, label %exit\n"
112 [&](Function
&F
, DominatorTree
&DT
, ScalarEvolution
&SE
, LoopInfo
&LI
) {
113 assert(LI
.begin() != LI
.end() && "Expecting loops in function F");
114 Loop
*L
= *LI
.begin();
115 assert(L
&& L
->getName() == "loop" && "Expecting loop 'loop'");
116 auto *Arg
= F
.getArg(0);
117 const SCEV
*ArgSCEV
= SE
.getSCEV(Arg
);
118 EXPECT_EQ(isKnownPositiveInLoop(ArgSCEV
, L
, SE
), true);
122 TEST(LoopUtils
, IsKnownNonPositiveInLoopTest
) {
124 std::unique_ptr
<Module
> M
=
125 parseIR(C
, "define void @foo(i32 %n, i1 %c) {\n"
127 " %is.non.positive = icmp sle i32 %n, 0\n"
128 " br i1 %is.non.positive, label %loop, label %exit\n"
130 " br i1 %c, label %loop, label %exit\n"
136 [&](Function
&F
, DominatorTree
&DT
, ScalarEvolution
&SE
, LoopInfo
&LI
) {
137 assert(LI
.begin() != LI
.end() && "Expecting loops in function F");
138 Loop
*L
= *LI
.begin();
139 assert(L
&& L
->getName() == "loop" && "Expecting loop 'loop'");
140 auto *Arg
= F
.getArg(0);
141 const SCEV
*ArgSCEV
= SE
.getSCEV(Arg
);
142 EXPECT_EQ(isKnownNonPositiveInLoop(ArgSCEV
, L
, SE
), true);