[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:20 PDT 2024


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

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

>From 9884d6304762e8cc405cc3bd0f8146b8b230dbfd Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Sun, 24 Mar 2024 14:09:28 -0400
Subject: [PATCH] [SelectionDAG] Add more cases for UDIV and SDIV

Also have UDIV just exit early if it can calculate that LHS is less than the RHS.
---
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 31 +++++++++++++++++--
 llvm/lib/Support/KnownBits.cpp                |  4 ++-
 2 files changed, 31 insertions(+), 4 deletions(-)

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();



More information about the llvm-commits mailing list