[llvm] [DAGCombiner][LegalizeTypes] Fuse i128 sdiv+srem / udiv+urem into single __divmodti4 / __udivmodti4 call (PR #187908)

Takashi Idobe via llvm-commits llvm-commits at lists.llvm.org
Fri May 1 05:55:56 PDT 2026


================
@@ -4939,6 +4943,87 @@ void DAGTypeLegalizer::ExpandIntRes_SADDSUBO(SDNode *Node,
   ReplaceValueWith(SDValue(Node, 1), Ovf);
 }
 
+void DAGTypeLegalizer::ExpandIntRes_DIVREM(SDNode *N, unsigned ResNo,
+                                           SDValue &Lo, SDValue &Hi) {
+  SDLoc dl(N);
+  EVT VT = N->getValueType(0);
+  bool IsSigned = (N->getOpcode() == ISD::SDIVREM);
+
+  // Only i128 is handled here; other widths require generalizing this
+  // function to select the libcall by VT.
+  RTLIB::Libcall LC = IsSigned ? RTLIB::SDIVREM_I128 : RTLIB::UDIVREM_I128;
+  assert(VT == MVT::i128 &&
+         "ExpandIntRes_DIVREM only handles i128; generalize by VT first");
+
+  // If no fused divrem libcall is available (or VT is not i128 in release
+  // builds), fall back to separate div and rem.
+  if (VT != MVT::i128 ||
+      DAG.getLibcalls().getLibcallImpl(LC) == RTLIB::Unsupported) {
+    unsigned DivOp = IsSigned ? ISD::SDIV : ISD::UDIV;
+    unsigned RemOp = IsSigned ? ISD::SREM : ISD::UREM;
+    SDValue Ops[2] = {N->getOperand(0), N->getOperand(1)};
+    SDValue Q = DAG.getNode(DivOp, dl, VT, Ops);
+    SDValue R = DAG.getNode(RemOp, dl, VT, Ops);
+    if (ResNo == 0) {
+      SplitInteger(Q, Lo, Hi);
+      ReplaceValueWith(SDValue(N, 1), R);
+    } else {
+      SplitInteger(R, Lo, Hi);
----------------
Takashiidobe wrote:

Yup, made the change.

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


More information about the llvm-commits mailing list