[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