[llvm] [TargetLowering] Refactor expandDIVREMByConstant to share more code. NFC (PR #187582)

Shivam Gupta via llvm-commits llvm-commits at lists.llvm.org
Sat Mar 21 01:54:54 PDT 2026


================
@@ -8238,77 +8268,41 @@ bool TargetLowering::expandDIVREMByConstant(SDNode *N,
       Sum = DAG.getNode(ISD::ADD, dl, HiLoVT, Sum, Carry);
     }
   } else {
-    // If we cannot split in two halves, look for a smaller chunk width W
-    // such that (1 << W) % Divisor == 1.
-    unsigned BitWidth = VT.getScalarSizeInBits();
-    unsigned BestChunkWidth = 0;
-
-    // Determine the legal scalar integer type for chunk operations.
-    EVT LegalVT = getTypeToTransformTo(*DAG.getContext(), VT);
-    unsigned LegalWidth = LegalVT.getScalarSizeInBits();
-    unsigned MaxChunk = std::min<unsigned>(LegalWidth, BitWidth);
-
-    // Search for I where 2^I % Divisor == 1
-    for (unsigned I = MaxChunk, E = MaxChunk / 2; I > E; --I) {
-      APInt Mod = APInt::getOneBitSet(Divisor.getBitWidth(), I).urem(Divisor);
-
-      if (Mod.isOne()) {
-        // Ensure (NumChunks * MaxChunkValue) doesn't overflow LegalVT
-        unsigned NumChunks = divideCeil(BitWidth, I);
-
-        // Ensure the sum won't overflow the hardware register (LegalWidth).
-        // Summing N chunks adds ceil(log2(N)) extra carry bits to the width.
-        // Safety check: Base Chunk Width (I) + Carry Bits <= Register Width.
-        if (I + llvm::bit_width(NumChunks - 1) <= LegalWidth) {
-          BestChunkWidth = I;
-          break;
-        }
-      }
-    }
-
-    if (!BestChunkWidth)
-      return false;
-
-    SDValue In =
-        LL ? DAG.getNode(ISD::BUILD_PAIR, dl, VT, LL, LH) : N->getOperand(0);
-    if (TrailingZeros) {
-      // Save the shifted off bits if we need the remainder.
-      if (Opcode != ISD::UDIV) {
-        APInt Mask = APInt::getLowBitsSet(BitWidth, TrailingZeros);
-        PartialRem =
-            DAG.getNode(ISD::AND, dl, VT, In, DAG.getConstant(Mask, dl, VT));
-      }
-      EVT ShiftVT = getShiftAmountTy(VT, DAG.getDataLayout());
-      In = DAG.getNode(ISD::SRL, dl, VT, In,
-                       DAG.getShiftAmountConstant(TrailingZeros, ShiftVT, dl));
-
-      std::tie(LL, LH) = DAG.SplitScalar(In, dl, HiLoVT, HiLoVT);
-    } else if (!LL) {
-      std::tie(LL, LH) = DAG.SplitScalar(In, dl, HiLoVT, HiLoVT);
-    }
-
-    SDValue TotalSum = DAG.getConstant(0, dl, LegalVT);
+    // Otherwise split into multple chunks and add them together. We chose
+    // BestChunkWidth so that the sum will not overflow.
     SDValue Mask = DAG.getConstant(
-        APInt::getLowBitsSet(LegalWidth, BestChunkWidth), dl, LegalVT);
+        APInt::getLowBitsSet(HBitWidth, BestChunkWidth), dl, HiLoVT);
 
     for (unsigned I = 0; I < BitWidth; I += BestChunkWidth) {
-      SDValue Shift = DAG.getShiftAmountConstant(I, VT, dl);
-      SDValue Chunk = DAG.getNode(ISD::SRL, dl, VT, In, Shift);
-      // Truncate to LegalVT
-      SDValue TruncChunk = DAG.getNode(ISD::TRUNCATE, dl, LegalVT, Chunk);
+      SDValue Chunk;
+      if (I == 0) {
+        Chunk = LL;
+      } else if (I >= HBitWidth) {
+        Chunk =
+            DAG.getNode(ISD::SRL, dl, HiLoVT, LH,
+                        DAG.getShiftAmountConstant(I - HBitWidth, HiLoVT, dl));
+      } else if (isOperationLegal(ISD::FSHR, HiLoVT)) {
----------------
xgupta wrote:

`isOperationLegal` loop invariant can be move out of loop, it is also use above in if(TrailingZeros).

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


More information about the llvm-commits mailing list