[llvm] [RISCV] Remove RISCVISD::WMACC*. Match during isel. NFC (PR #181197)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 12 10:01:33 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-risc-v
Author: Craig Topper (topperc)
<details>
<summary>Changes</summary>
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/181197.diff
4 Files Affected:
- (modified) llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp (+88-50)
- (modified) llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h (+1)
- (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (-76)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoP.td (-13)
``````````diff
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index db65d6ac1a5df..0aef10d4ec6eb 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -887,6 +887,87 @@ bool RISCVDAGToDAGISel::tryIndexedLoad(SDNode *Node) {
return true;
}
+// 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;
+ }
+
+ // Build the register pair for the accumulator input.
+ // FIXME: Make this a utility function.
+ SDValue AccOps[] = {
+ CurDAG->getTargetConstant(RISCV::GPRPairRegClassID, DL, MVT::i32), AddLo,
+ CurDAG->getTargetConstant(RISCV::sub_gpr_even, DL, MVT::i32), AddHi,
+ CurDAG->getTargetConstant(RISCV::sub_gpr_odd, DL, MVT::i32)};
+ SDValue Acc = SDValue(CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL,
+ MVT::Untyped, AccOps),
+ 0);
+
+ // 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);
+
+ SDValue Lo = CurDAG->getTargetExtractSubreg(RISCV::sub_gpr_even, DL, MVT::i32,
+ SDValue(New, 0));
+ SDValue Hi = CurDAG->getTargetExtractSubreg(RISCV::sub_gpr_odd, DL, MVT::i32,
+ 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;
@@ -1910,57 +1991,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 AccOps[] = {
- CurDAG->getTargetConstant(RISCV::GPRPairRegClassID, DL, MVT::i32),
- AddLo, CurDAG->getTargetConstant(RISCV::sub_gpr_even, DL, MVT::i32),
- AddHi, CurDAG->getTargetConstant(RISCV::sub_gpr_odd, DL, MVT::i32)};
- SDValue Acc = SDValue(CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL,
- MVT::Untyped, AccOps),
- 0);
-
- 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);
-
- SDValue Lo = CurDAG->getTargetExtractSubreg(RISCV::sub_gpr_even, DL,
- MVT::i32, SDValue(New, 0));
- SDValue Hi = CurDAG->getTargetExtractSubreg(RISCV::sub_gpr_odd, DL,
- MVT::i32, 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>;
``````````
</details>
https://github.com/llvm/llvm-project/pull/181197
More information about the llvm-commits
mailing list