[llvm] a809d64 - [RISCV] Remove RISCVISD::WMACC*. Match during isel. NFC (#181197)

via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 12 22:06:06 PST 2026


Author: Craig Topper
Date: 2026-02-12T22:06:01-08:00
New Revision: a809d6409f7a4785d0301bddea8a1ce6713c6179

URL: https://github.com/llvm/llvm-project/commit/a809d6409f7a4785d0301bddea8a1ce6713c6179
DIFF: https://github.com/llvm/llvm-project/commit/a809d6409f7a4785d0301bddea8a1ce6713c6179.diff

LOG: [RISCV] Remove RISCVISD::WMACC*. Match during isel. NFC (#181197)

I think we may want to be able to fold ADDD nodes independent of the MUL
in some cases. For example turning NSRAI into NSRARI.

If we fold ADDD into WMACC we would need to be able to extract it again.
Keep the nodes separate avoids this.

Code change was assisted by AI.

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
    llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h
    llvm/lib/Target/RISCV/RISCVISelLowering.cpp
    llvm/lib/Target/RISCV/RISCVInstrInfoP.td

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index afbfcdcbd11cf..021fe05a3d7fd 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -887,6 +887,97 @@ bool RISCVDAGToDAGISel::tryIndexedLoad(SDNode *Node) {
   return true;
 }
 
+static SDValue buildGPRPair(SelectionDAG *CurDAG, const SDLoc &DL, MVT VT,
+                            SDValue Lo, SDValue Hi) {
+  SDValue Ops[] = {
+      CurDAG->getTargetConstant(RISCV::GPRPairRegClassID, DL, MVT::i32), Lo,
+      CurDAG->getTargetConstant(RISCV::sub_gpr_even, DL, MVT::i32), Hi,
+      CurDAG->getTargetConstant(RISCV::sub_gpr_odd, DL, MVT::i32)};
+
+  return SDValue(
+      CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL, VT, Ops), 0);
+}
+
+// Helper to extract Lo and Hi values from a GPR pair.
+static std::pair<SDValue, SDValue>
+extractGPRPair(SelectionDAG *CurDAG, const SDLoc &DL, SDValue Pair) {
+  SDValue Lo =
+      CurDAG->getTargetExtractSubreg(RISCV::sub_gpr_even, DL, MVT::i32, Pair);
+  SDValue Hi =
+      CurDAG->getTargetExtractSubreg(RISCV::sub_gpr_odd, DL, MVT::i32, Pair);
+  return {Lo, Hi};
+}
+
+// Try to match WMACC pattern: ADDD where one operand pair comes from a
+// widening multiply (both results of UMUL_LOHI, SMUL_LOHI, or WMULSU).
+bool RISCVDAGToDAGISel::tryWideningMulAcc(SDNode *Node, const SDLoc &DL) {
+  assert(Node->getOpcode() == RISCVISD::ADDD && "Expected ADDD");
+
+  SDValue Op0Lo = Node->getOperand(0);
+  SDValue Op0Hi = Node->getOperand(1);
+  SDValue Op1Lo = Node->getOperand(2);
+  SDValue Op1Hi = Node->getOperand(3);
+
+  auto IsSupportedMul = [](unsigned Opc) {
+    return Opc == ISD::UMUL_LOHI || Opc == ISD::SMUL_LOHI ||
+           Opc == RISCVISD::WMULSU;
+  };
+
+  SDNode *MulNode = nullptr;
+  SDValue AddLo, AddHi;
+
+  // Check if first operand pair is a supported multiply.
+  if (IsSupportedMul(Op0Lo.getOpcode()) && Op0Lo.getNode() == Op0Hi.getNode() &&
+      Op0Lo.getResNo() == 0 && Op0Hi.getResNo() == 1) {
+    MulNode = Op0Lo.getNode();
+    AddLo = Op1Lo;
+    AddHi = Op1Hi;
+  }
+  // ADDD is commutative. Check if second operand pair is a supported multiply.
+  else if (IsSupportedMul(Op1Lo.getOpcode()) &&
+           Op1Lo.getNode() == Op1Hi.getNode() && Op1Lo.getResNo() == 0 &&
+           Op1Hi.getResNo() == 1) {
+    MulNode = Op1Lo.getNode();
+    AddLo = Op0Lo;
+    AddHi = Op0Hi;
+  }
+
+  // Check that we found a multiply and this is the only user.
+  // FIXME: We should check the use count before trying to commuted case.
+  if (!MulNode || !SDValue(MulNode, 0).hasOneUse() ||
+      !SDValue(MulNode, 1).hasOneUse())
+    return false;
+
+  unsigned Opc;
+  switch (MulNode->getOpcode()) {
+  default:
+    llvm_unreachable("Unexpected multiply opcode");
+  case ISD::UMUL_LOHI:
+    Opc = RISCV::WMACCU;
+    break;
+  case ISD::SMUL_LOHI:
+    Opc = RISCV::WMACC;
+    break;
+  case RISCVISD::WMULSU:
+    Opc = RISCV::WMACCSU;
+    break;
+  }
+
+  SDValue Acc = buildGPRPair(CurDAG, DL, MVT::Untyped, AddLo, AddHi);
+
+  // WMACC instruction format: rd, rs1, rs2 (rd is accumulator).
+  SDValue M0 = MulNode->getOperand(0);
+  SDValue M1 = MulNode->getOperand(1);
+  MachineSDNode *New =
+      CurDAG->getMachineNode(Opc, DL, MVT::Untyped, Acc, M0, M1);
+
+  auto [Lo, Hi] = extractGPRPair(CurDAG, DL, SDValue(New, 0));
+  ReplaceUses(SDValue(Node, 0), Lo);
+  ReplaceUses(SDValue(Node, 1), Hi);
+  CurDAG->RemoveDeadNode(Node);
+  return true;
+}
+
 static Register getTileReg(uint64_t TileNum) {
   assert(TileNum <= 15 && "Invalid tile number");
   return RISCV::T0 + TileNum;
@@ -1005,27 +1096,6 @@ static bool isApplicableToPLI(int Val) {
   return isInt<10>(Bit31To16) || Bit15To8 == Bit7To0;
 }
 
-static SDValue buildGPRPair(SelectionDAG *CurDAG, const SDLoc &DL, MVT VT,
-                            SDValue Lo, SDValue Hi) {
-  SDValue Ops[] = {
-      CurDAG->getTargetConstant(RISCV::GPRPairRegClassID, DL, MVT::i32), Lo,
-      CurDAG->getTargetConstant(RISCV::sub_gpr_even, DL, MVT::i32), Hi,
-      CurDAG->getTargetConstant(RISCV::sub_gpr_odd, DL, MVT::i32)};
-
-  return SDValue(
-      CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL, VT, Ops), 0);
-}
-
-// Helper to extract Lo and Hi values from a GPR pair.
-static std::pair<SDValue, SDValue>
-extractGPRPair(SelectionDAG *CurDAG, const SDLoc &DL, SDValue Pair) {
-  SDValue Lo =
-      CurDAG->getTargetExtractSubreg(RISCV::sub_gpr_even, DL, MVT::i32, Pair);
-  SDValue Hi =
-      CurDAG->getTargetExtractSubreg(RISCV::sub_gpr_odd, DL, MVT::i32, Pair);
-  return {Lo, Hi};
-}
-
 void RISCVDAGToDAGISel::Select(SDNode *Node) {
   // If we have a custom node, we have already selected.
   if (Node->isMachineOpcode()) {
@@ -1912,48 +1982,14 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
     CurDAG->RemoveDeadNode(Node);
     return;
   }
-  case RISCVISD::WMACCSU:
-  case RISCVISD::WMACCU:
-  case RISCVISD::WMACC: {
-    assert(!Subtarget->is64Bit() && Subtarget->hasStdExtP() &&
-           "Unexpected opcode");
-
-    // WMACCU/WMACC/WMACCSU has 4 operands: (m1, m2, addlo, addhi) -> (lo, hi)
-    SDValue M1 = Node->getOperand(0);
-    SDValue M2 = Node->getOperand(1);
-    SDValue AddLo = Node->getOperand(2);
-    SDValue AddHi = Node->getOperand(3);
-
-    // Build the register pair for the accumulator input
-    SDValue Acc = buildGPRPair(CurDAG, DL, MVT::Untyped, AddLo, AddHi);
-
-    unsigned Opc;
-    switch (Node->getOpcode()) {
-    default:
-      llvm_unreachable("Unexpected WMACC opcode");
-    case RISCVISD::WMACCU:
-      Opc = RISCV::WMACCU;
-      break;
-    case RISCVISD::WMACC:
-      Opc = RISCV::WMACC;
-      break;
-    case RISCVISD::WMACCSU:
-      Opc = RISCV::WMACCSU;
-      break;
-    }
-
-    // Instruction format: WMACCU rd, rs1, rs2 (rd is accumulator, comes first)
-    MachineSDNode *New =
-        CurDAG->getMachineNode(Opc, DL, MVT::Untyped, Acc, M1, M2);
-
-    auto [Lo, Hi] = extractGPRPair(CurDAG, DL, SDValue(New, 0));
-
-    ReplaceUses(SDValue(Node, 0), Lo);
-    ReplaceUses(SDValue(Node, 1), Hi);
-    CurDAG->RemoveDeadNode(Node);
-    return;
-  }
   case RISCVISD::ADDD:
+    // Try to match WMACC pattern: ADDD where one operand pair comes from a
+    // widening multiply.
+    if (tryWideningMulAcc(Node, DL))
+      return;
+
+    // Fall through to regular ADDD selection.
+    [[fallthrough]];
   case RISCVISD::SUBD:
   case RISCVISD::PPAIRE_DB: {
     assert(!Subtarget->is64Bit() && "Unexpected opcode");

diff  --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h
index eea041fe23432..1d59dc57c4135 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h
@@ -81,6 +81,7 @@ class RISCVDAGToDAGISel : public SelectionDAGISel {
   bool tryUnsignedBitfieldInsertInZero(SDNode *Node, const SDLoc &DL, MVT VT,
                                        SDValue X, unsigned Msb, unsigned Lsb);
   bool tryIndexedLoad(SDNode *Node);
+  bool tryWideningMulAcc(SDNode *Node, const SDLoc &DL);
 
   bool selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt);
   bool selectShiftMaskXLen(SDValue N, SDValue &ShAmt) {

diff  --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index c12426458c3a5..b368127c64c98 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -21251,80 +21251,6 @@ static SDValue performSHLCombine(SDNode *N,
                      Passthru, Mask, VL);
 }
 
-// Combine (ADDD (UMUL_LOHI x, y).0, (UMUL_LOHI x, y).1, a, b) into
-// (WMACCU x, y, a, b).
-// Combine (ADDD (SMUL_LOHI x, y).0, (SMUL_LOHI x, y).1, a, b) into
-// (WMACC x, y, a, b).
-// Combine (ADDD (WMULSU x, y).0, (WMULSU x, y).1, a, b) into
-// (WMACCSU x, y, a, b).
-static SDValue combineADDDToWMACC(SDNode *N, SelectionDAG &DAG,
-                                  const RISCVSubtarget &Subtarget) {
-  assert(N->getOpcode() == RISCVISD::ADDD && "Expected ADDD");
-  assert(!Subtarget.is64Bit() && Subtarget.hasStdExtP() &&
-         "ADDD requires RV32 with P extension");
-
-  // ADDD has 4 operands: (op0_lo, op0_hi, op1_lo, op1_hi)
-  // Try to match UMUL_LOHI, SMUL_LOHI, or WMULSU in either operand pair due to
-  // commutativity
-  SDValue Op0Lo = N->getOperand(0);
-  SDValue Op0Hi = N->getOperand(1);
-  SDValue Op1Lo = N->getOperand(2);
-  SDValue Op1Hi = N->getOperand(3);
-
-  auto IsSupportedMul = [](unsigned Opc) {
-    return Opc == ISD::UMUL_LOHI || Opc == ISD::SMUL_LOHI ||
-           Opc == RISCVISD::WMULSU;
-  };
-
-  SDNode *MulNode = nullptr;
-  SDValue AddLo, AddHi;
-
-  // Check if first operand pair is a supported multiply
-  if (IsSupportedMul(Op0Lo.getOpcode()) && Op0Lo.getNode() == Op0Hi.getNode() &&
-      Op0Lo.getResNo() == 0 && Op0Hi.getResNo() == 1) {
-    MulNode = Op0Lo.getNode();
-    AddLo = Op1Lo;
-    AddHi = Op1Hi;
-  }
-  // Check if second operand pair is a supported multiply (commutative case)
-  else if (IsSupportedMul(Op1Lo.getOpcode()) &&
-           Op1Lo.getNode() == Op1Hi.getNode() && Op1Lo.getResNo() == 0 &&
-           Op1Hi.getResNo() == 1) {
-    MulNode = Op1Lo.getNode();
-    AddLo = Op0Lo;
-    AddHi = Op0Hi;
-  } else {
-    return SDValue();
-  }
-
-  // Only combine if both multiply results are only used by this ADDD
-  if (!SDValue(MulNode, 0).hasOneUse() || !SDValue(MulNode, 1).hasOneUse())
-    return SDValue();
-
-  // Extract the multiply operands
-  SDValue MulOp0 = MulNode->getOperand(0);
-  SDValue MulOp1 = MulNode->getOperand(1);
-
-  // Create WMACCU, WMACC, or WMACCSU node: (m1, m2, addlo, addhi) -> (lo, hi)
-  SDLoc DL(N);
-  unsigned Opc;
-  switch (MulNode->getOpcode()) {
-  default:
-    llvm_unreachable("Unexpected multiply opcode");
-  case ISD::UMUL_LOHI:
-    Opc = RISCVISD::WMACCU;
-    break;
-  case ISD::SMUL_LOHI:
-    Opc = RISCVISD::WMACC;
-    break;
-  case RISCVISD::WMULSU:
-    Opc = RISCVISD::WMACCSU;
-    break;
-  }
-  return DAG.getNode(Opc, DL, DAG.getVTList(MVT::i32, MVT::i32), MulOp0, MulOp1,
-                     AddLo, AddHi);
-}
-
 SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
                                                DAGCombinerInfo &DCI) const {
   SelectionDAG &DAG = DCI.DAG;
@@ -21415,8 +21341,6 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
       return SDValue(N, 0);
     break;
   }
-  case RISCVISD::ADDD:
-    return combineADDDToWMACC(N, DAG, Subtarget);
   case RISCVISD::WMULSU: {
     // Convert to MULHSU if only the upper half is used.
     if (!N->hasAnyUseOfValue(0)) {

diff  --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index 5d9a52644a38f..d154687d22754 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -1515,19 +1515,6 @@ def BuildGPRPair : OutPatFrag<(ops node:$lo, node:$hi),
 def riscv_asub : RVSDNode<"ASUB", SDTIntBinOp>;
 def riscv_asubu : RVSDNode<"ASUBU", SDTIntBinOp>;
 
-// Widening multiply add (lo, hi) = wmacc(m1, m2, addlo, addhi)
-def SDT_RISCVWideningMAccW : SDTypeProfile<2, 4, [SDTCisVT<0, i32>,
-                                                  SDTCisVT<1, i32>,
-                                                  SDTCisVT<2, i32>,
-                                                  SDTCisVT<3, i32>,
-                                                  SDTCisSameAs<0, 4>,
-                                                  SDTCisSameAs<0, 5>]>;
-def riscv_wmacc  : RVSDNode<"WMACC", SDT_RISCVWideningMAccW,
-                            [SDNPCommutative]>;
-def riscv_wmaccu : RVSDNode<"WMACCU", SDT_RISCVWideningMAccW,
-                            [SDNPCommutative]>;
-def riscv_wmaccsu : RVSDNode<"WMACCSU", SDT_RISCVWideningMAccW>;
-
 // MULH/MULHU/MULHSU with rounding.
 def riscv_mulhr : RVSDNode<"MULHR", SDTIntBinOp>;
 def riscv_mulhru : RVSDNode<"MULHRU", SDTIntBinOp>;


        


More information about the llvm-commits mailing list