[llvm] [ConstraintElim] Use cond from header as upper bound on IV in exit BB. (PR #94610)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 29 02:36:11 PDT 2024


https://github.com/fhahn updated https://github.com/llvm/llvm-project/pull/94610

>From 8310ce60596043e3ca50e4c03f779c2834b97fc6 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Thu, 6 Jun 2024 13:47:20 +0100
Subject: [PATCH 1/3] [ConstraintElim] Use cond from header as upper bound on
 IV in exit BB.

For loops, we can use the condition in the loop header as upper bound on
the compared induction in the unique exit block, if it exists. This can
be done even if there are multiple in-loop edges to the unique exit
block, as any other exit may only exit earlier.

More generally, we could add the OR of all exit conditions to the exit,
but that's a possible future extension.

Fixes https://github.com/llvm/llvm-project/issues/90417.
---
 .../Transforms/Scalar/ConstraintElimination.cpp | 17 +++++++++++++++++
 .../induction-condition-in-loop-exit.ll         |  9 +++------
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index 05012321d7244..976c0a9c2ee14 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -1031,6 +1031,23 @@ void State::addInfoForInductions(BasicBlock &BB) {
   WorkList.push_back(FactOrCheck::getConditionFact(
       DTN, CmpInst::ICMP_SLT, PN, B,
       ConditionTy(CmpInst::ICMP_SLE, StartValue, B)));
+
+  assert(!StepOffset.isNegative() && "induction must be increasing");
+  // Try to add condition from header to the unique exit block, if there is one.
+  // When exiting either with EQ or NE, we know that the induction value must be
+  // u<= B, as a different exit may exit earlier.
+  if (Pred == CmpInst::ICMP_EQ) {
+    BasicBlock *EB = cast<BranchInst>(BB.getTerminator())->getSuccessor(0);
+    if (L->getUniqueExitBlock() == EB)
+      WorkList.emplace_back(FactOrCheck::getConditionFact(
+          DT.getNode(EB), CmpInst::ICMP_ULE, A, B));
+  }
+  if (Pred == CmpInst::ICMP_NE) {
+    BasicBlock *EB = cast<BranchInst>(BB.getTerminator())->getSuccessor(1);
+    if (L->getUniqueExitBlock() == EB)
+      WorkList.emplace_back(FactOrCheck::getConditionFact(
+          DT.getNode(EB), CmpInst::ICMP_ULE, A, B));
+  }
 }
 
 void State::addInfoFor(BasicBlock &BB) {
diff --git a/llvm/test/Transforms/ConstraintElimination/induction-condition-in-loop-exit.ll b/llvm/test/Transforms/ConstraintElimination/induction-condition-in-loop-exit.ll
index 05c7c9e5b90d8..80a34d15c69c8 100644
--- a/llvm/test/Transforms/ConstraintElimination/induction-condition-in-loop-exit.ll
+++ b/llvm/test/Transforms/ConstraintElimination/induction-condition-in-loop-exit.ll
@@ -19,8 +19,7 @@ define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_known(ptr %s) {
 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
 ; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]]
 ; CHECK:       [[EXIT]]:
-; CHECK-NEXT:    [[T:%.*]] = icmp ult i32 [[IV]], 1235
-; CHECK-NEXT:    ret i1 [[T]]
+; CHECK-NEXT:    ret i1 true
 ;
 entry:
   br label %loop.header
@@ -341,8 +340,7 @@ define i1 @multi_exiting_loop_eq_same_unique_exit_var_compare_known(ptr %s, i32
 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
 ; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]]
 ; CHECK:       [[EXIT]]:
-; CHECK-NEXT:    [[T:%.*]] = icmp ule i32 [[IV]], [[N]]
-; CHECK-NEXT:    ret i1 [[T]]
+; CHECK-NEXT:    ret i1 true
 ;
 entry:
   br label %loop.header
@@ -419,8 +417,7 @@ define i1 @multi_exiting_loop_ne_same_unique_exit_const_compare_known(ptr %s) {
 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
 ; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]]
 ; CHECK:       [[EXIT]]:
-; CHECK-NEXT:    [[T:%.*]] = icmp ult i32 [[IV]], 1235
-; CHECK-NEXT:    ret i1 [[T]]
+; CHECK-NEXT:    ret i1 true
 ;
 entry:
   br label %loop.header

>From 474acb53f2d9a6ffd501ee4855ca2709a0b7ab45 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Thu, 6 Jun 2024 15:37:40 +0100
Subject: [PATCH 2/3] !fixup properly handle non-monotonically increasing case.

---
 llvm/lib/Transforms/Scalar/ConstraintElimination.cpp   | 10 +++++++---
 .../induction-condition-in-loop-exit.ll                |  3 +--
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index 976c0a9c2ee14..99a7e6d6c4dc1 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -1036,17 +1036,21 @@ void State::addInfoForInductions(BasicBlock &BB) {
   // Try to add condition from header to the unique exit block, if there is one.
   // When exiting either with EQ or NE, we know that the induction value must be
   // u<= B, as a different exit may exit earlier.
+  ConditionTy Precond;
+  if (!MonotonicallyIncreasingUnsigned)
+    Precond = {CmpInst::ICMP_ULE, StartValue, B};
   if (Pred == CmpInst::ICMP_EQ) {
     BasicBlock *EB = cast<BranchInst>(BB.getTerminator())->getSuccessor(0);
-    if (L->getUniqueExitBlock() == EB)
+    if (L->getUniqueExitBlock() == EB) {
       WorkList.emplace_back(FactOrCheck::getConditionFact(
-          DT.getNode(EB), CmpInst::ICMP_ULE, A, B));
+          DT.getNode(EB), CmpInst::ICMP_ULE, A, B, Precond));
+    }
   }
   if (Pred == CmpInst::ICMP_NE) {
     BasicBlock *EB = cast<BranchInst>(BB.getTerminator())->getSuccessor(1);
     if (L->getUniqueExitBlock() == EB)
       WorkList.emplace_back(FactOrCheck::getConditionFact(
-          DT.getNode(EB), CmpInst::ICMP_ULE, A, B));
+          DT.getNode(EB), CmpInst::ICMP_ULE, A, B, Precond));
   }
 }
 
diff --git a/llvm/test/Transforms/ConstraintElimination/induction-condition-in-loop-exit.ll b/llvm/test/Transforms/ConstraintElimination/induction-condition-in-loop-exit.ll
index 80a34d15c69c8..7996041605681 100644
--- a/llvm/test/Transforms/ConstraintElimination/induction-condition-in-loop-exit.ll
+++ b/llvm/test/Transforms/ConstraintElimination/induction-condition-in-loop-exit.ll
@@ -98,8 +98,7 @@ define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_known_due_to_pre
 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
 ; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]]
 ; CHECK:       [[EXIT]]:
-; CHECK-NEXT:    [[T:%.*]] = icmp ult i32 [[IV]], 1235
-; CHECK-NEXT:    ret i1 [[T]]
+; CHECK-NEXT:    ret i1 true
 ;
 entry:
   %pre.c = icmp ule i32 %start, 1234

>From d51a03644e5c789eed7b5ebadeac62aee4800712 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Fri, 28 Jun 2024 15:36:28 +0100
Subject: [PATCH 3/3] !fixup always emit precondition, don't check unique
 predecessor

---
 .../Scalar/ConstraintElimination.cpp          | 29 +++++++------------
 .../induction-condition-in-loop-exit.ll       |  3 +-
 2 files changed, 12 insertions(+), 20 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index 99a7e6d6c4dc1..e1535a5cc01a1 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -1032,25 +1032,18 @@ void State::addInfoForInductions(BasicBlock &BB) {
       DTN, CmpInst::ICMP_SLT, PN, B,
       ConditionTy(CmpInst::ICMP_SLE, StartValue, B)));
 
+  // Try to add condition from header to the exit blocks. When exiting either
+  // with EQ or NE in the header, we know that the induction value must be u<=
+  // B, as other exits may only exit earlier.
   assert(!StepOffset.isNegative() && "induction must be increasing");
-  // Try to add condition from header to the unique exit block, if there is one.
-  // When exiting either with EQ or NE, we know that the induction value must be
-  // u<= B, as a different exit may exit earlier.
-  ConditionTy Precond;
-  if (!MonotonicallyIncreasingUnsigned)
-    Precond = {CmpInst::ICMP_ULE, StartValue, B};
-  if (Pred == CmpInst::ICMP_EQ) {
-    BasicBlock *EB = cast<BranchInst>(BB.getTerminator())->getSuccessor(0);
-    if (L->getUniqueExitBlock() == EB) {
-      WorkList.emplace_back(FactOrCheck::getConditionFact(
-          DT.getNode(EB), CmpInst::ICMP_ULE, A, B, Precond));
-    }
-  }
-  if (Pred == CmpInst::ICMP_NE) {
-    BasicBlock *EB = cast<BranchInst>(BB.getTerminator())->getSuccessor(1);
-    if (L->getUniqueExitBlock() == EB)
-      WorkList.emplace_back(FactOrCheck::getConditionFact(
-          DT.getNode(EB), CmpInst::ICMP_ULE, A, B, Precond));
+  assert((Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_NE) &&
+         "unsupported predicate");
+  ConditionTy Precond = {CmpInst::ICMP_ULE, StartValue, B};
+  SmallVector<BasicBlock *> ExitBBs;
+  L->getExitBlocks(ExitBBs);
+  for (BasicBlock *EB : ExitBBs) {
+    WorkList.emplace_back(FactOrCheck::getConditionFact(
+        DT.getNode(EB), CmpInst::ICMP_ULE, A, B, Precond));
   }
 }
 
diff --git a/llvm/test/Transforms/ConstraintElimination/induction-condition-in-loop-exit.ll b/llvm/test/Transforms/ConstraintElimination/induction-condition-in-loop-exit.ll
index 7996041605681..15e1d84372627 100644
--- a/llvm/test/Transforms/ConstraintElimination/induction-condition-in-loop-exit.ll
+++ b/llvm/test/Transforms/ConstraintElimination/induction-condition-in-loop-exit.ll
@@ -541,8 +541,7 @@ define i1 @multi_exiting_loop_eq_different_exits_2_const_compare_known(ptr %s, i
 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
 ; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT_2]]
 ; CHECK:       [[EXIT_1]]:
-; CHECK-NEXT:    [[T_1:%.*]] = icmp ult i32 [[IV]], 1235
-; CHECK-NEXT:    ret i1 [[T_1]]
+; CHECK-NEXT:    ret i1 true
 ; CHECK:       [[EXIT_2]]:
 ; CHECK-NEXT:    ret i1 true
 ;



More information about the llvm-commits mailing list