[llvm] [SelectionDAG] Add more cases for UDIV and SDIV (PR #86452)

via llvm-commits llvm-commits at lists.llvm.org
Sun Mar 24 13:26:47 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-support

Author: AtariDreams (AtariDreams)

<details>
<summary>Changes</summary>

Also have UDIV just exit early if it can calculate that LHS is less than the RHS.

---
Full diff: https://github.com/llvm/llvm-project/pull/86452.diff


2 Files Affected:

- (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (+28-3) 
- (modified) llvm/lib/Support/KnownBits.cpp (+3-1) 


``````````diff
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 0ab5142ab81676..5f80c7c7315ee4 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -5392,14 +5392,39 @@ bool SelectionDAG::isKnownNeverZero(SDValue Op, unsigned Depth) const {
       return true;
     break;
   }
-  case ISD::UDIV:
-  case ISD::SDIV:
+  case ISD::UDIV: {
     // div exact can only produce a zero if the dividend is zero.
-    // TODO: For udiv this is also true if Op1 u<= Op0
     if (Op->getFlags().hasExact())
       return isKnownNeverZero(Op.getOperand(0), Depth + 1);
+
+    // If Op1 <= Op0, then Op0 is at least 1, and therefore not 0.
+    KnownBits Op0 = computeKnownBits(Op.getOperand(0), Depth + 1);
+    KnownBits Op1 = computeKnownBits(Op.getOperand(1), Depth + 1);
+    std::optional<bool> uge = KnownBits::uge(Op0, Op1);
+    if (uge && *uge)
+      return true;
+
+    if (KnownBits::udiv(Op0, Op1).isNonZero())
+      return true;
     break;
+  }
+  case ISD::SDIV: {
+    // div exact can only produce a zero if the dividend is zero.
+    if (Op->getFlags().hasExact())
+      return isKnownNeverZero(Op.getOperand(0), Depth + 1);
 
+    KnownBits Op0 = computeKnownBits(Op.getOperand(0), Depth + 1);
+    KnownBits Op1 = computeKnownBits(Op.getOperand(1), Depth + 1);
+    if (Op0.isStrictlyPositive() && Op1.isStrictlyPositive()) {
+      std::optional<bool> uge = KnownBits::uge(Op0, Op1);
+      if (uge && *uge)
+        return true;
+    }
+
+    if (KnownBits::sdiv(Op0, Op1).isNonZero())
+      return true;
+    break;
+  }
   case ISD::ADD:
     if (Op->getFlags().hasNoUnsignedWrap())
       if (isKnownNeverZero(Op.getOperand(1), Depth + 1) ||
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index d72355dab6f1d3..fac9980a9349fc 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -979,7 +979,9 @@ KnownBits KnownBits::udiv(const KnownBits &LHS, const KnownBits &RHS,
   assert(!LHS.hasConflict() && !RHS.hasConflict());
   KnownBits Known(BitWidth);
 
-  if (LHS.isZero() || RHS.isZero()) {
+  // if LHS < RHS, then LHS / RHS is 0.
+  std::optional<bool> ult = KnownBits::ult(LHS, RHS);
+  if (LHS.isZero() || RHS.isZero() || (ult && *ult)) {
     // Result is either known Zero or UB. Return Zero either way.
     // Checking this earlier saves us a lot of special cases later on.
     Known.setAllZero();

``````````

</details>


https://github.com/llvm/llvm-project/pull/86452


More information about the llvm-commits mailing list