Skip to content

Commit

Permalink
[LoopUtils] Add isKnownPositiveInLoop and isKnownNonPositiveInLoop fu…
Browse files Browse the repository at this point in the history
…nctions
  • Loading branch information
d-makogon committed Apr 12, 2023
1 parent 7e5b10b commit 797da79
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 0 deletions.
8 changes: 8 additions & 0 deletions llvm/include/llvm/Transforms/Utils/LoopUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,14 @@ bool isKnownNegativeInLoop(const SCEV *S, const Loop *L, ScalarEvolution &SE);
/// loop \p L.
bool isKnownNonNegativeInLoop(const SCEV *S, const Loop *L,
ScalarEvolution &SE);
/// Returns true if we can prove that \p S is defined and always positive in
/// loop \p L.
bool isKnownPositiveInLoop(const SCEV *S, const Loop *L, ScalarEvolution &SE);

/// Returns true if we can prove that \p S is defined and always non-positive in
/// loop \p L.
bool isKnownNonPositiveInLoop(const SCEV *S, const Loop *L,
ScalarEvolution &SE);

/// Returns true if \p S is defined and never is equal to signed/unsigned max.
bool cannotBeMaxInLoop(const SCEV *S, const Loop *L, ScalarEvolution &SE,
Expand Down
14 changes: 14 additions & 0 deletions llvm/lib/Transforms/Utils/LoopUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1136,6 +1136,20 @@ bool llvm::isKnownNonNegativeInLoop(const SCEV *S, const Loop *L,
SE.isLoopEntryGuardedByCond(L, ICmpInst::ICMP_SGE, S, Zero);
}

bool llvm::isKnownPositiveInLoop(const SCEV *S, const Loop *L,
ScalarEvolution &SE) {
const SCEV *Zero = SE.getZero(S->getType());
return SE.isAvailableAtLoopEntry(S, L) &&
SE.isLoopEntryGuardedByCond(L, ICmpInst::ICMP_SGT, S, Zero);
}

bool llvm::isKnownNonPositiveInLoop(const SCEV *S, const Loop *L,
ScalarEvolution &SE) {
const SCEV *Zero = SE.getZero(S->getType());
return SE.isAvailableAtLoopEntry(S, L) &&
SE.isLoopEntryGuardedByCond(L, ICmpInst::ICMP_SLE, S, Zero);
}

bool llvm::cannotBeMinInLoop(const SCEV *S, const Loop *L, ScalarEvolution &SE,
bool Signed) {
unsigned BitWidth = cast<IntegerType>(S->getType())->getBitWidth();
Expand Down
48 changes: 48 additions & 0 deletions llvm/unittests/Transforms/Utils/LoopUtilsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,51 @@ TEST(LoopUtils, DeleteDeadLoopNest) {
EXPECT_EQ(BI->getSuccessor(0)->getName(), "for.end");
});
}

TEST(LoopUtils, IsKnownPositiveInLoopTest) {
LLVMContext C;
std::unique_ptr<Module> M =
parseIR(C, "define void @foo(i32 %n, i1 %c) {\n"
"entry:\n"
" %is.positive = icmp sgt i32 %n, 0\n"
" br i1 %is.positive, label %loop, label %exit\n"
"loop:\n"
" br i1 %c, label %loop, label %exit\n"
"exit:\n"
" ret void\n"
"}\n");

run(*M, "foo",
[&](Function &F, DominatorTree &DT, ScalarEvolution &SE, LoopInfo &LI) {
assert(LI.begin() != LI.end() && "Expecting loops in function F");
Loop *L = *LI.begin();
assert(L && L->getName() == "loop" && "Expecting loop 'loop'");
auto *Arg = F.getArg(0);
auto *ArgSCEV = SE.getSCEV(Arg);
EXPECT_EQ(isKnownPositiveInLoop(ArgSCEV, L, SE), true);
});
}

TEST(LoopUtils, IsKnownNonPositiveInLoopTest) {
LLVMContext C;
std::unique_ptr<Module> M =
parseIR(C, "define void @foo(i32 %n, i1 %c) {\n"
"entry:\n"
" %is.non.positive = icmp sle i32 %n, 0\n"
" br i1 %is.non.positive, label %loop, label %exit\n"
"loop:\n"
" br i1 %c, label %loop, label %exit\n"
"exit:\n"
" ret void\n"
"}\n");

run(*M, "foo",
[&](Function &F, DominatorTree &DT, ScalarEvolution &SE, LoopInfo &LI) {
assert(LI.begin() != LI.end() && "Expecting loops in function F");
Loop *L = *LI.begin();
assert(L && L->getName() == "loop" && "Expecting loop 'loop'");
auto *Arg = F.getArg(0);
auto *ArgSCEV = SE.getSCEV(Arg);
EXPECT_EQ(isKnownNonPositiveInLoop(ArgSCEV, L, SE), true);
});
}

0 comments on commit 797da79

Please sign in to comment.