[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