[llvm] 797da79 - [LoopUtils] Add isKnownPositiveInLoop and isKnownNonPositiveInLoop functions
Dmitry Makogon via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 12 04:46:47 PDT 2023
Author: Dmitry Makogon
Date: 2023-04-12T18:46:11+07:00
New Revision: 797da79a928eef3b389883ea873cc32060e812fa
URL: https://github.com/llvm/llvm-project/commit/797da79a928eef3b389883ea873cc32060e812fa
DIFF: https://github.com/llvm/llvm-project/commit/797da79a928eef3b389883ea873cc32060e812fa.diff
LOG: [LoopUtils] Add isKnownPositiveInLoop and isKnownNonPositiveInLoop functions
Added:
Modified:
llvm/include/llvm/Transforms/Utils/LoopUtils.h
llvm/lib/Transforms/Utils/LoopUtils.cpp
llvm/unittests/Transforms/Utils/LoopUtilsTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Transforms/Utils/LoopUtils.h b/llvm/include/llvm/Transforms/Utils/LoopUtils.h
index 960be75a2eb30..56adb7f72a187 100644
--- a/llvm/include/llvm/Transforms/Utils/LoopUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/LoopUtils.h
@@ -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,
diff --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp
index 1c58370a77d55..31872c15b0334 100644
--- a/llvm/lib/Transforms/Utils/LoopUtils.cpp
+++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp
@@ -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();
diff --git a/llvm/unittests/Transforms/Utils/LoopUtilsTest.cpp b/llvm/unittests/Transforms/Utils/LoopUtilsTest.cpp
index aa0d72cf8bb33..8272c304ba288 100644
--- a/llvm/unittests/Transforms/Utils/LoopUtilsTest.cpp
+++ b/llvm/unittests/Transforms/Utils/LoopUtilsTest.cpp
@@ -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);
+ });
+}
More information about the llvm-commits
mailing list