[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