[PATCH] D150923: [KnownBits] Factor out and improve the lowbit computation for {u,s}div

Noah Goldstein via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu May 18 17:38:47 PDT 2023


goldstein.w.n created this revision.
goldstein.w.n added reviewers: foad, nikic, RKSimon.
Herald added subscribers: StephenFan, hiraditya.
Herald added a project: All.
goldstein.w.n requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

There are some new cases if the division is `exact`:

  1: If `TZ(LHS) == TZ(RHS)` then the result is always Odd
  2: If `TZ(LHS) > TZ(RHS)` then the `TZ(LHS)-TZ(RHS)` bits of the
     result are zero.

Proofs: https://alive2.llvm.org/ce/z/3rAZqF

As well, return zero in known poison cases to be consistent rather
than just working about the bits we are changing.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D150923

Files:
  llvm/lib/Support/KnownBits.cpp


Index: llvm/lib/Support/KnownBits.cpp
===================================================================
--- llvm/lib/Support/KnownBits.cpp
+++ llvm/lib/Support/KnownBits.cpp
@@ -536,6 +536,39 @@
   return mul(WideLHS, WideRHS).extractBits(BitWidth, BitWidth);
 }
 
+static KnownBits divComputeLowBit(const KnownBits &Known, const KnownBits &LHS,
+                                  const KnownBits &RHS, bool Exact) {
+
+  if (!Exact)
+    return Known;
+
+  // If we already have a constant, we can skip this.
+  unsigned BitWidth = LHS.getBitWidth();
+  KnownBits KnownOut(Known);
+  unsigned LHSMinTZ = LHS.countMinTrailingZeros();
+  assert(LHSMinTZ < BitWidth && "We should have already handled Zero LHS");
+
+  // Odd / X -> Odd
+  //    X must be odd, otherwise the div is not exact.
+  // EvenX / EvenY [if TZ(X) == TZ(Y)] -> Odd
+  if (LHS.One[LHSMinTZ] &&
+      (LHSMinTZ == 0 ||
+       (RHS.countMinTrailingZeros() == LHSMinTZ && RHS.One[LHSMinTZ])))
+    KnownOut.One.setBit(0);
+
+  // For exact TZ(LHS) - TZ(RHS) bits must all be zero.
+  // This also covers Even / Odd -> Even
+  if (LHSMinTZ > RHS.countMaxTrailingZeros())
+    KnownOut.Zero.setLowBits(LHSMinTZ - RHS.countMaxTrailingZeros());
+
+  // In the KnownBits exhaustive tests, we have poison inputs for exact values
+  // a LOT. If we have a conflict, just return all zeros.
+  if (KnownOut.hasConflict())
+    KnownOut.setAllZero();
+
+  return KnownOut;
+}
+
 KnownBits KnownBits::sdiv(const KnownBits &LHS, const KnownBits &RHS,
                           bool Exact) {
   // Equivalent of `udiv`. We must have caught this before it was folded.
@@ -599,20 +632,7 @@
     }
   }
 
-  if (Exact) {
-    // Odd / Odd -> Odd
-    if (LHS.One[0] && RHS.One[0]) {
-      Known.Zero.clearBit(0);
-      Known.One.setBit(0);
-    }
-    // Even / Odd -> Even
-    else if (LHS.Zero[0] && RHS.One[0]) {
-      Known.One.clearBit(0);
-      Known.Zero.setBit(0);
-    }
-    // Odd / Even -> impossible
-    // Even / Even -> unknown
-  }
+  Known = divComputeLowBit(Known, LHS, RHS, Exact);
 
   assert(!Known.hasConflict() && "Bad Output");
   return Known;
@@ -640,20 +660,7 @@
   unsigned LeadZ = MaxRes.countLeadingZeros();
 
   Known.Zero.setHighBits(LeadZ);
-  if (Exact) {
-    // Odd / Odd -> Odd
-    if (LHS.One[0] && RHS.One[0]) {
-      Known.Zero.clearBit(0);
-      Known.One.setBit(0);
-    }
-    // Even / Odd -> Even
-    else if (LHS.Zero[0] && RHS.One[0]) {
-      Known.One.clearBit(0);
-      Known.Zero.setBit(0);
-    }
-    // Odd / Even -> impossible
-    // Even / Even -> unknown
-  }
+  Known = divComputeLowBit(Known, LHS, RHS, Exact);
 
   assert(!Known.hasConflict() && "Bad Output");
   return Known;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D150923.523616.patch
Type: text/x-patch
Size: 2707 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230519/40867423/attachment.bin>


More information about the llvm-commits mailing list