[llvm] db70744 - [RISCV][P-ext] Fold an add of a multiply-parts product into the accumulate form (#222748)

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 10 20:06:56 PDT 2026


Author: SiHuaN
Date: 2026-09-11T03:06:50Z
New Revision: db70744d03adbc9e76f08a66c003b6b362df888d

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

LOG: [RISCV][P-ext] Fold an add of a multiply-parts product into the accumulate form (#222748)

An add of a multiply-parts product selects the accumulating instruction, so
that a loop written with `sum += __riscv_mul_h00_i32(a, b)` gets `macc.h00`
rather than a separate multiply and add.

Rewriting the add before type legalization keeps the shapes whose result is
illegal, so the existing accumulate lowering covers all of them.

Added: 
    llvm/test/CodeGen/RISCV/rvp-mul-parts-acc-fold.ll

Modified: 
    llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index e2d91fc4c4cfa..19b4a01b7733b 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -12548,6 +12548,47 @@ static Intrinsic::ID getRVPScalarMulPartsIntrinsic(unsigned IntNo) {
   }
 }
 
+/// Return the accumulate form of multiply-parts intrinsic \p IntNo, or
+/// Intrinsic::not_intrinsic if there is none.
+static Intrinsic::ID getRVPMulPartsAccIntrinsic(unsigned IntNo) {
+  switch (IntNo) {
+  default:
+    return Intrinsic::not_intrinsic;
+  case Intrinsic::riscv_mul_00:
+    return Intrinsic::riscv_macc_00;
+  case Intrinsic::riscv_pmul_00:
+    return Intrinsic::riscv_pmacc_00;
+  case Intrinsic::riscv_mul_01:
+    return Intrinsic::riscv_macc_01;
+  case Intrinsic::riscv_pmul_01:
+    return Intrinsic::riscv_pmacc_01;
+  case Intrinsic::riscv_mul_11:
+    return Intrinsic::riscv_macc_11;
+  case Intrinsic::riscv_pmul_11:
+    return Intrinsic::riscv_pmacc_11;
+  case Intrinsic::riscv_mulu_00:
+    return Intrinsic::riscv_maccu_00;
+  case Intrinsic::riscv_pmulu_00:
+    return Intrinsic::riscv_pmaccu_00;
+  case Intrinsic::riscv_mulu_01:
+    return Intrinsic::riscv_maccu_01;
+  case Intrinsic::riscv_pmulu_01:
+    return Intrinsic::riscv_pmaccu_01;
+  case Intrinsic::riscv_mulu_11:
+    return Intrinsic::riscv_maccu_11;
+  case Intrinsic::riscv_pmulu_11:
+    return Intrinsic::riscv_pmaccu_11;
+  case Intrinsic::riscv_mulsu_00:
+    return Intrinsic::riscv_maccsu_00;
+  case Intrinsic::riscv_pmulsu_00:
+    return Intrinsic::riscv_pmaccsu_00;
+  case Intrinsic::riscv_mulsu_11:
+    return Intrinsic::riscv_maccsu_11;
+  case Intrinsic::riscv_pmulsu_11:
+    return Intrinsic::riscv_pmaccsu_11;
+  }
+}
+
 /// Return the multiply-parts accumulate node for \p IntNo.
 static unsigned getRVPMulAccHalvesOpcode(unsigned IntNo) {
   switch (IntNo) {
@@ -18510,6 +18551,30 @@ static SDValue combineAddMulh(SDNode *N, SelectionDAG &DAG,
   return DAG.getNode(RISCVISD::MULHSU, DL, VT, X, Mulh.getOperand(1));
 }
 
+// Fold an add of a multiply-parts product into the accumulating form.
+static SDValue combineAddMulParts(SDNode *N, SelectionDAG &DAG,
+                                  const RISCVSubtarget &Subtarget) {
+  if (!Subtarget.hasStdExtP())
+    return SDValue();
+
+  for (unsigned I = 0; I != 2; ++I) {
+    SDValue Mul = N->getOperand(I);
+    if (Mul.getOpcode() != ISD::INTRINSIC_WO_CHAIN || !Mul.hasOneUse())
+      continue;
+    Intrinsic::ID AccId =
+        getRVPMulPartsAccIntrinsic(Mul.getConstantOperandVal(0));
+    if (AccId == Intrinsic::not_intrinsic)
+      continue;
+
+    SDLoc DL(N);
+    return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, N->getValueType(0),
+                       DAG.getTargetConstant(AccId, DL, Subtarget.getXLenVT()),
+                       N->getOperand(1 - I), Mul.getOperand(1),
+                       Mul.getOperand(2));
+  }
+  return SDValue();
+}
+
 static SDValue combinePExtWideningAddSub(SDNode *N, SelectionDAG &DAG,
                                          const RISCVSubtarget &Subtarget) {
   // Recognize the RV64 decompositions listed for the 32-bit packed widening
@@ -18595,6 +18660,8 @@ static SDValue performADDCombine(SDNode *N,
     return V;
   if (SDValue V = combineBinOpOfZExt(N, DAG))
     return V;
+  if (SDValue V = combineAddMulParts(N, DAG, Subtarget))
+    return V;
   if (SDValue V = combineAddMulh(N, DAG, Subtarget))
     return V;
 

diff  --git a/llvm/test/CodeGen/RISCV/rvp-mul-parts-acc-fold.ll b/llvm/test/CodeGen/RISCV/rvp-mul-parts-acc-fold.ll
new file mode 100644
index 0000000000000..fa660331631d0
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rvp-mul-parts-acc-fold.ll
@@ -0,0 +1,429 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-p,+m,+zbb -verify-machineinstrs < %s | FileCheck %s --check-prefixes=RV32
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-p,+m,+zbb -verify-machineinstrs < %s | FileCheck %s --check-prefixes=RV64
+
+; An add of a multiply-parts product selects the accumulating instruction.
+
+define i32 @macc_h00(i32 %rd, <2 x i16> %a, <2 x i16> %b) {
+; RV32-LABEL: macc_h00:
+; RV32:       # %bb.0:
+; RV32-NEXT:    macc.h00 a0, a1, a2
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: macc_h00:
+; RV64:       # %bb.0:
+; RV64-NEXT:    pmacc.w.h00 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call i32 @llvm.riscv.mul.00.i32.v2i16(<2 x i16> %a, <2 x i16> %b)
+  %r = add i32 %rd, %m
+  ret i32 %r
+}
+
+define i32 @macc_h01(i32 %rd, <2 x i16> %a, <2 x i16> %b) {
+; RV32-LABEL: macc_h01:
+; RV32:       # %bb.0:
+; RV32-NEXT:    macc.h01 a0, a1, a2
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: macc_h01:
+; RV64:       # %bb.0:
+; RV64-NEXT:    pmacc.w.h01 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call i32 @llvm.riscv.mul.01.i32.v2i16(<2 x i16> %a, <2 x i16> %b)
+  %r = add i32 %rd, %m
+  ret i32 %r
+}
+
+define i32 @macc_h11(i32 %rd, <2 x i16> %a, <2 x i16> %b) {
+; RV32-LABEL: macc_h11:
+; RV32:       # %bb.0:
+; RV32-NEXT:    macc.h11 a0, a1, a2
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: macc_h11:
+; RV64:       # %bb.0:
+; RV64-NEXT:    pmacc.w.h11 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call i32 @llvm.riscv.mul.11.i32.v2i16(<2 x i16> %a, <2 x i16> %b)
+  %r = add i32 %rd, %m
+  ret i32 %r
+}
+
+define i32 @maccu_h00(i32 %rd, <2 x i16> %a, <2 x i16> %b) {
+; RV32-LABEL: maccu_h00:
+; RV32:       # %bb.0:
+; RV32-NEXT:    maccu.h00 a0, a1, a2
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: maccu_h00:
+; RV64:       # %bb.0:
+; RV64-NEXT:    pmaccu.w.h00 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call i32 @llvm.riscv.mulu.00.i32.v2i16(<2 x i16> %a, <2 x i16> %b)
+  %r = add i32 %rd, %m
+  ret i32 %r
+}
+
+define i32 @maccu_h01(i32 %rd, <2 x i16> %a, <2 x i16> %b) {
+; RV32-LABEL: maccu_h01:
+; RV32:       # %bb.0:
+; RV32-NEXT:    maccu.h01 a0, a1, a2
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: maccu_h01:
+; RV64:       # %bb.0:
+; RV64-NEXT:    pmaccu.w.h01 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call i32 @llvm.riscv.mulu.01.i32.v2i16(<2 x i16> %a, <2 x i16> %b)
+  %r = add i32 %rd, %m
+  ret i32 %r
+}
+
+define i32 @maccu_h11(i32 %rd, <2 x i16> %a, <2 x i16> %b) {
+; RV32-LABEL: maccu_h11:
+; RV32:       # %bb.0:
+; RV32-NEXT:    maccu.h11 a0, a1, a2
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: maccu_h11:
+; RV64:       # %bb.0:
+; RV64-NEXT:    pmaccu.w.h11 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call i32 @llvm.riscv.mulu.11.i32.v2i16(<2 x i16> %a, <2 x i16> %b)
+  %r = add i32 %rd, %m
+  ret i32 %r
+}
+
+define i32 @maccsu_h00(i32 %rd, <2 x i16> %a, <2 x i16> %b) {
+; RV32-LABEL: maccsu_h00:
+; RV32:       # %bb.0:
+; RV32-NEXT:    maccsu.h00 a0, a1, a2
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: maccsu_h00:
+; RV64:       # %bb.0:
+; RV64-NEXT:    pmaccsu.w.h00 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call i32 @llvm.riscv.mulsu.00.i32.v2i16(<2 x i16> %a, <2 x i16> %b)
+  %r = add i32 %rd, %m
+  ret i32 %r
+}
+
+define i32 @maccsu_h11(i32 %rd, <2 x i16> %a, <2 x i16> %b) {
+; RV32-LABEL: maccsu_h11:
+; RV32:       # %bb.0:
+; RV32-NEXT:    maccsu.h11 a0, a1, a2
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: maccsu_h11:
+; RV64:       # %bb.0:
+; RV64-NEXT:    pmaccsu.w.h11 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call i32 @llvm.riscv.mulsu.11.i32.v2i16(<2 x i16> %a, <2 x i16> %b)
+  %r = add i32 %rd, %m
+  ret i32 %r
+}
+
+define i64 @macc_w00(i64 %rd, <2 x i32> %a, <2 x i32> %b) {
+; RV32-LABEL: macc_w00:
+; RV32:       # %bb.0:
+; RV32-NEXT:    wmacc a0, a2, a4
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: macc_w00:
+; RV64:       # %bb.0:
+; RV64-NEXT:    macc.w00 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call i64 @llvm.riscv.mul.00.i64.v2i32(<2 x i32> %a, <2 x i32> %b)
+  %r = add i64 %rd, %m
+  ret i64 %r
+}
+
+define i64 @macc_w01(i64 %rd, <2 x i32> %a, <2 x i32> %b) {
+; RV32-LABEL: macc_w01:
+; RV32:       # %bb.0:
+; RV32-NEXT:    wmacc a0, a2, a5
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: macc_w01:
+; RV64:       # %bb.0:
+; RV64-NEXT:    macc.w01 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call i64 @llvm.riscv.mul.01.i64.v2i32(<2 x i32> %a, <2 x i32> %b)
+  %r = add i64 %rd, %m
+  ret i64 %r
+}
+
+define i64 @macc_w11(i64 %rd, <2 x i32> %a, <2 x i32> %b) {
+; RV32-LABEL: macc_w11:
+; RV32:       # %bb.0:
+; RV32-NEXT:    wmacc a0, a3, a5
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: macc_w11:
+; RV64:       # %bb.0:
+; RV64-NEXT:    macc.w11 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call i64 @llvm.riscv.mul.11.i64.v2i32(<2 x i32> %a, <2 x i32> %b)
+  %r = add i64 %rd, %m
+  ret i64 %r
+}
+
+define i64 @maccu_w00(i64 %rd, <2 x i32> %a, <2 x i32> %b) {
+; RV32-LABEL: maccu_w00:
+; RV32:       # %bb.0:
+; RV32-NEXT:    wmaccu a0, a2, a4
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: maccu_w00:
+; RV64:       # %bb.0:
+; RV64-NEXT:    maccu.w00 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call i64 @llvm.riscv.mulu.00.i64.v2i32(<2 x i32> %a, <2 x i32> %b)
+  %r = add i64 %rd, %m
+  ret i64 %r
+}
+
+define i64 @maccu_w01(i64 %rd, <2 x i32> %a, <2 x i32> %b) {
+; RV32-LABEL: maccu_w01:
+; RV32:       # %bb.0:
+; RV32-NEXT:    wmaccu a0, a2, a5
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: maccu_w01:
+; RV64:       # %bb.0:
+; RV64-NEXT:    maccu.w01 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call i64 @llvm.riscv.mulu.01.i64.v2i32(<2 x i32> %a, <2 x i32> %b)
+  %r = add i64 %rd, %m
+  ret i64 %r
+}
+
+define i64 @maccu_w11(i64 %rd, <2 x i32> %a, <2 x i32> %b) {
+; RV32-LABEL: maccu_w11:
+; RV32:       # %bb.0:
+; RV32-NEXT:    wmaccu a0, a3, a5
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: maccu_w11:
+; RV64:       # %bb.0:
+; RV64-NEXT:    maccu.w11 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call i64 @llvm.riscv.mulu.11.i64.v2i32(<2 x i32> %a, <2 x i32> %b)
+  %r = add i64 %rd, %m
+  ret i64 %r
+}
+
+define i64 @maccsu_w00(i64 %rd, <2 x i32> %a, <2 x i32> %b) {
+; RV32-LABEL: maccsu_w00:
+; RV32:       # %bb.0:
+; RV32-NEXT:    wmaccsu a0, a2, a4
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: maccsu_w00:
+; RV64:       # %bb.0:
+; RV64-NEXT:    maccsu.w00 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call i64 @llvm.riscv.mulsu.00.i64.v2i32(<2 x i32> %a, <2 x i32> %b)
+  %r = add i64 %rd, %m
+  ret i64 %r
+}
+
+define i64 @maccsu_w11(i64 %rd, <2 x i32> %a, <2 x i32> %b) {
+; RV32-LABEL: maccsu_w11:
+; RV32:       # %bb.0:
+; RV32-NEXT:    wmaccsu a0, a3, a5
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: maccsu_w11:
+; RV64:       # %bb.0:
+; RV64-NEXT:    maccsu.w11 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call i64 @llvm.riscv.mulsu.11.i64.v2i32(<2 x i32> %a, <2 x i32> %b)
+  %r = add i64 %rd, %m
+  ret i64 %r
+}
+
+define <2 x i32> @pmacc_h00(<2 x i32> %rd, <4 x i16> %a, <4 x i16> %b) {
+; RV32-LABEL: pmacc_h00:
+; RV32:       # %bb.0:
+; RV32-NEXT:    macc.h00 a1, a3, a5
+; RV32-NEXT:    macc.h00 a0, a2, a4
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: pmacc_h00:
+; RV64:       # %bb.0:
+; RV64-NEXT:    pmacc.w.h00 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call <2 x i32> @llvm.riscv.pmul.00.v2i32(<4 x i16> %a, <4 x i16> %b)
+  %r = add <2 x i32> %rd, %m
+  ret <2 x i32> %r
+}
+
+define <2 x i32> @pmacc_h01(<2 x i32> %rd, <4 x i16> %a, <4 x i16> %b) {
+; RV32-LABEL: pmacc_h01:
+; RV32:       # %bb.0:
+; RV32-NEXT:    macc.h01 a1, a3, a5
+; RV32-NEXT:    macc.h01 a0, a2, a4
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: pmacc_h01:
+; RV64:       # %bb.0:
+; RV64-NEXT:    pmacc.w.h01 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call <2 x i32> @llvm.riscv.pmul.01.v2i32(<4 x i16> %a, <4 x i16> %b)
+  %r = add <2 x i32> %rd, %m
+  ret <2 x i32> %r
+}
+
+define <2 x i32> @pmacc_h11(<2 x i32> %rd, <4 x i16> %a, <4 x i16> %b) {
+; RV32-LABEL: pmacc_h11:
+; RV32:       # %bb.0:
+; RV32-NEXT:    macc.h11 a1, a3, a5
+; RV32-NEXT:    macc.h11 a0, a2, a4
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: pmacc_h11:
+; RV64:       # %bb.0:
+; RV64-NEXT:    pmacc.w.h11 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call <2 x i32> @llvm.riscv.pmul.11.v2i32(<4 x i16> %a, <4 x i16> %b)
+  %r = add <2 x i32> %rd, %m
+  ret <2 x i32> %r
+}
+
+define <2 x i32> @pmaccu_h00(<2 x i32> %rd, <4 x i16> %a, <4 x i16> %b) {
+; RV32-LABEL: pmaccu_h00:
+; RV32:       # %bb.0:
+; RV32-NEXT:    maccu.h00 a1, a3, a5
+; RV32-NEXT:    maccu.h00 a0, a2, a4
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: pmaccu_h00:
+; RV64:       # %bb.0:
+; RV64-NEXT:    pmaccu.w.h00 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call <2 x i32> @llvm.riscv.pmulu.00.v2i32(<4 x i16> %a, <4 x i16> %b)
+  %r = add <2 x i32> %rd, %m
+  ret <2 x i32> %r
+}
+
+define <2 x i32> @pmaccu_h01(<2 x i32> %rd, <4 x i16> %a, <4 x i16> %b) {
+; RV32-LABEL: pmaccu_h01:
+; RV32:       # %bb.0:
+; RV32-NEXT:    maccu.h01 a1, a3, a5
+; RV32-NEXT:    maccu.h01 a0, a2, a4
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: pmaccu_h01:
+; RV64:       # %bb.0:
+; RV64-NEXT:    pmaccu.w.h01 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call <2 x i32> @llvm.riscv.pmulu.01.v2i32(<4 x i16> %a, <4 x i16> %b)
+  %r = add <2 x i32> %rd, %m
+  ret <2 x i32> %r
+}
+
+define <2 x i32> @pmaccu_h11(<2 x i32> %rd, <4 x i16> %a, <4 x i16> %b) {
+; RV32-LABEL: pmaccu_h11:
+; RV32:       # %bb.0:
+; RV32-NEXT:    maccu.h11 a1, a3, a5
+; RV32-NEXT:    maccu.h11 a0, a2, a4
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: pmaccu_h11:
+; RV64:       # %bb.0:
+; RV64-NEXT:    pmaccu.w.h11 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call <2 x i32> @llvm.riscv.pmulu.11.v2i32(<4 x i16> %a, <4 x i16> %b)
+  %r = add <2 x i32> %rd, %m
+  ret <2 x i32> %r
+}
+
+define <2 x i32> @pmaccsu_h00(<2 x i32> %rd, <4 x i16> %a, <4 x i16> %b) {
+; RV32-LABEL: pmaccsu_h00:
+; RV32:       # %bb.0:
+; RV32-NEXT:    maccsu.h00 a1, a3, a5
+; RV32-NEXT:    maccsu.h00 a0, a2, a4
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: pmaccsu_h00:
+; RV64:       # %bb.0:
+; RV64-NEXT:    pmaccsu.w.h00 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call <2 x i32> @llvm.riscv.pmulsu.00.v2i32(<4 x i16> %a, <4 x i16> %b)
+  %r = add <2 x i32> %rd, %m
+  ret <2 x i32> %r
+}
+
+define <2 x i32> @pmaccsu_h11(<2 x i32> %rd, <4 x i16> %a, <4 x i16> %b) {
+; RV32-LABEL: pmaccsu_h11:
+; RV32:       # %bb.0:
+; RV32-NEXT:    maccsu.h11 a1, a3, a5
+; RV32-NEXT:    maccsu.h11 a0, a2, a4
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: pmaccsu_h11:
+; RV64:       # %bb.0:
+; RV64-NEXT:    pmaccsu.w.h11 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call <2 x i32> @llvm.riscv.pmulsu.11.v2i32(<4 x i16> %a, <4 x i16> %b)
+  %r = add <2 x i32> %rd, %m
+  ret <2 x i32> %r
+}
+
+; The product is used twice, so folding would recompute it.
+define i32 @multi_use(i32 %rd, <2 x i16> %a, <2 x i16> %b) {
+; RV32-LABEL: multi_use:
+; RV32:       # %bb.0:
+; RV32-NEXT:    mul.h00 a1, a1, a2
+; RV32-NEXT:    add a0, a0, a1
+; RV32-NEXT:    add a0, a0, a1
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: multi_use:
+; RV64:       # %bb.0:
+; RV64-NEXT:    pmul.w.h00 a1, a1, a2
+; RV64-NEXT:    add a0, a0, a1
+; RV64-NEXT:    addw a0, a0, a1
+; RV64-NEXT:    ret
+  %m = call i32 @llvm.riscv.mul.00.i32.v2i16(<2 x i16> %a, <2 x i16> %b)
+  %r = add i32 %rd, %m
+  %s = add i32 %r, %m
+  ret i32 %s
+}
+
+; add is commutative.
+define i32 @swapped_operands(i32 %rd, <2 x i16> %a, <2 x i16> %b) {
+; RV32-LABEL: swapped_operands:
+; RV32:       # %bb.0:
+; RV32-NEXT:    macc.h00 a0, a1, a2
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: swapped_operands:
+; RV64:       # %bb.0:
+; RV64-NEXT:    pmacc.w.h00 a0, a1, a2
+; RV64-NEXT:    ret
+  %m = call i32 @llvm.riscv.mul.00.i32.v2i16(<2 x i16> %a, <2 x i16> %b)
+  %r = add i32 %m, %rd
+  ret i32 %r
+}
+
+define i32 @accumulate_chain(i32 %rd, <2 x i16> %a, <2 x i16> %b, <2 x i16> %c, <2 x i16> %d) {
+; RV32-LABEL: accumulate_chain:
+; RV32:       # %bb.0:
+; RV32-NEXT:    macc.h00 a0, a1, a2
+; RV32-NEXT:    macc.h00 a0, a3, a4
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: accumulate_chain:
+; RV64:       # %bb.0:
+; RV64-NEXT:    pmacc.w.h00 a0, a1, a2
+; RV64-NEXT:    pmacc.w.h00 a0, a3, a4
+; RV64-NEXT:    ret
+  %m1 = call i32 @llvm.riscv.mul.00.i32.v2i16(<2 x i16> %a, <2 x i16> %b)
+  %r1 = add i32 %rd, %m1
+  %m2 = call i32 @llvm.riscv.mul.00.i32.v2i16(<2 x i16> %c, <2 x i16> %d)
+  %r2 = add i32 %r1, %m2
+  ret i32 %r2
+}


        


More information about the llvm-commits mailing list