[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