[clang] [llvm] [Clang][RISCV][P-ext] Add packed Q-format widening accumulate intrinsics (PR #228009)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 1 02:28:38 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-risc-v
Author: 陈子昂 (Michael-Chen-NJU)
<details>
<summary>Changes</summary>
Add support for the Packed "Q-format" Multiply with Widening Accumulate intrinsics:
- `__riscv_pmqwacc_i32x2`
- `__riscv_pmqrwacc_i32x2`
RV32 selects the direct instructions, while RV64 lowers to the spec-listed `zip16p` and packed Q-format accumulate sequences.
---
Full diff: https://github.com/llvm/llvm-project/pull/228009.diff
9 Files Affected:
- (modified) clang/include/clang/Basic/BuiltinsRISCV.td (+4)
- (modified) clang/lib/CodeGen/TargetBuiltins/RISCV.cpp (+9)
- (modified) clang/lib/Headers/riscv_packed_simd.h (+6)
- (modified) clang/test/CodeGen/RISCV/rvp-intrinsics.c (+28)
- (modified) cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c (+16)
- (modified) llvm/include/llvm/IR/IntrinsicsRISCV.td (+8)
- (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+24)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoP.td (+17-5)
- (modified) llvm/test/CodeGen/RISCV/rvp-simd-64.ll (+32)
``````````diff
diff --git a/clang/include/clang/Basic/BuiltinsRISCV.td b/clang/include/clang/Basic/BuiltinsRISCV.td
index e38c0ffe73c80..3a3e85c25b664 100644
--- a/clang/include/clang/Basic/BuiltinsRISCV.td
+++ b/clang/include/clang/Basic/BuiltinsRISCV.td
@@ -329,6 +329,10 @@ def pmhacc_h1_i32x2 : RISCVBuiltin<"_Vector<2, int>(_Vector<2, int>, _Vector<2,
def pmhaccsu_h0_i32x2 : RISCVBuiltin<"_Vector<2, int>(_Vector<2, int>, _Vector<2, int>, _Vector<4, unsigned short>)">;
def pmhaccsu_h1_i32x2 : RISCVBuiltin<"_Vector<2, int>(_Vector<2, int>, _Vector<2, int>, _Vector<4, unsigned short>)">;
+// Packed "Q-format" Multiply with Widening Accumulate
+def pmqwacc_i32x2 : RISCVBuiltin<"_Vector<2, int>(_Vector<2, int>, _Vector<2, short>, _Vector<2, short>)">;
+def pmqrwacc_i32x2 : RISCVBuiltin<"_Vector<2, int>(_Vector<2, int>, _Vector<2, short>, _Vector<2, short>)">;
+
// Packed Multiplication with Horizontal Addition (32-bit)
def pm4add_i8x4 : RISCVBuiltin<"int(_Vector<4, signed char>, _Vector<4, signed char>)">;
def pm2add_i16x2 : RISCVBuiltin<"int(_Vector<2, short>, _Vector<2, short>)">;
diff --git a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
index 474a0aa577734..74f85712e4828 100644
--- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
@@ -1661,6 +1661,15 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
break;
}
+ // Packed "Q-format" Multiply with Widening Accumulate
+ case RISCV::BI__builtin_riscv_pmqwacc_i32x2:
+ case RISCV::BI__builtin_riscv_pmqrwacc_i32x2: {
+ ID = BuiltinID == RISCV::BI__builtin_riscv_pmqwacc_i32x2
+ ? Intrinsic::riscv_pmqwacc_i32x2
+ : Intrinsic::riscv_pmqrwacc_i32x2;
+ break;
+ }
+
// Packed Multiplication with Horizontal Addition
case RISCV::BI__builtin_riscv_pm4add_i8x4:
case RISCV::BI__builtin_riscv_pm4add_i8x8:
diff --git a/clang/lib/Headers/riscv_packed_simd.h b/clang/lib/Headers/riscv_packed_simd.h
index 6bc610d74246b..4148b165e28f3 100644
--- a/clang/lib/Headers/riscv_packed_simd.h
+++ b/clang/lib/Headers/riscv_packed_simd.h
@@ -826,6 +826,12 @@ __packed_widen_mulsu(pwmulsu_i16x4, int16x4_t, int8x4_t, uint8x4_t, uint16x4_t)
__packed_widen_mulsu(pwmulsu_i32x2, int32x2_t, int16x2_t, uint16x2_t,
uint32x2_t)
+/* Packed "Q-format" Multiply with Widening Accumulate */
+__packed_ternary_builtin_mixed(pmqwacc_i32x2, int32x2_t, int16x2_t, int16x2_t,
+ __builtin_riscv_pmqwacc_i32x2)
+__packed_ternary_builtin_mixed(pmqrwacc_i32x2, int32x2_t, int16x2_t, int16x2_t,
+ __builtin_riscv_pmqrwacc_i32x2)
+
/* Packed Narrowing Convert */
__packed_narrow_even4(pncvt_i8x4, int8x4_t, int16x4_t, int8x8_t)
__packed_narrow_even4(pncvt_u8x4, uint8x4_t, uint16x4_t, uint8x8_t)
diff --git a/clang/test/CodeGen/RISCV/rvp-intrinsics.c b/clang/test/CodeGen/RISCV/rvp-intrinsics.c
index b26b75b3e1431..5f57545cf6c9f 100644
--- a/clang/test/CodeGen/RISCV/rvp-intrinsics.c
+++ b/clang/test/CodeGen/RISCV/rvp-intrinsics.c
@@ -5801,6 +5801,34 @@ int32x2_t test_pwmul_i32x2(int16x2_t rs1, int16x2_t rs2) {
return __riscv_pwmul_i32x2(rs1, rs2);
}
+// CHECK-LABEL: define dso_local i64 @test_pmqwacc_i32x2(
+// CHECK-SAME: i64 noundef [[RD_COERCE:%.*]], i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast i64 [[RD_COERCE]] to <2 x i32>
+// CHECK-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS1_COERCE]] to <2 x i16>
+// CHECK-NEXT: [[TMP2:%.*]] = bitcast i32 [[RS2_COERCE]] to <2 x i16>
+// CHECK-NEXT: [[TMP3:%.*]] = call <2 x i32> @llvm.riscv.pmqwacc.i32x2(<2 x i32> [[TMP0]], <2 x i16> [[TMP1]], <2 x i16> [[TMP2]])
+// CHECK-NEXT: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to i64
+// CHECK-NEXT: ret i64 [[TMP4]]
+//
+int32x2_t test_pmqwacc_i32x2(int32x2_t rd, int16x2_t rs1, int16x2_t rs2) {
+ return __riscv_pmqwacc_i32x2(rd, rs1, rs2);
+}
+
+// CHECK-LABEL: define dso_local i64 @test_pmqrwacc_i32x2(
+// CHECK-SAME: i64 noundef [[RD_COERCE:%.*]], i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast i64 [[RD_COERCE]] to <2 x i32>
+// CHECK-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS1_COERCE]] to <2 x i16>
+// CHECK-NEXT: [[TMP2:%.*]] = bitcast i32 [[RS2_COERCE]] to <2 x i16>
+// CHECK-NEXT: [[TMP3:%.*]] = call <2 x i32> @llvm.riscv.pmqrwacc.i32x2(<2 x i32> [[TMP0]], <2 x i16> [[TMP1]], <2 x i16> [[TMP2]])
+// CHECK-NEXT: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to i64
+// CHECK-NEXT: ret i64 [[TMP4]]
+//
+int32x2_t test_pmqrwacc_i32x2(int32x2_t rd, int16x2_t rs1, int16x2_t rs2) {
+ return __riscv_pmqrwacc_i32x2(rd, rs1, rs2);
+}
+
// CHECK-LABEL: define dso_local i64 @test_pwmulu_u16x4(
// CHECK-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
diff --git a/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c b/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
index 469c3d6846ed8..e7ad4af120270 100644
--- a/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
+++ b/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
@@ -2632,6 +2632,22 @@ int32x2_t test_pwmul_i32x2(int16x2_t rs1, int16x2_t rs2) {
return __riscv_pwmul_i32x2(rs1, rs2);
}
+// CHECK-LABEL: test_pmqwacc_i32x2:
+// RV32: pmqwacc.h{{[[:space:]]}}
+// RV64: zip16p{{[[:space:]]}}
+// RV64: pmqacc.w.h01{{[[:space:]]}}
+int32x2_t test_pmqwacc_i32x2(int32x2_t rd, int16x2_t rs1, int16x2_t rs2) {
+ return __riscv_pmqwacc_i32x2(rd, rs1, rs2);
+}
+
+// CHECK-LABEL: test_pmqrwacc_i32x2:
+// RV32: pmqrwacc.h{{[[:space:]]}}
+// RV64: zip16p{{[[:space:]]}}
+// RV64: pmqracc.w.h01{{[[:space:]]}}
+int32x2_t test_pmqrwacc_i32x2(int32x2_t rd, int16x2_t rs1, int16x2_t rs2) {
+ return __riscv_pmqrwacc_i32x2(rd, rs1, rs2);
+}
+
// CHECK-LABEL: test_pwmulu_u16x4:
// RV32: pwmulu.b
// RV64: zip8p
diff --git a/llvm/include/llvm/IR/IntrinsicsRISCV.td b/llvm/include/llvm/IR/IntrinsicsRISCV.td
index b2e9bbba3ad6f..3ff0b10bb6f53 100644
--- a/llvm/include/llvm/IR/IntrinsicsRISCV.td
+++ b/llvm/include/llvm/IR/IntrinsicsRISCV.td
@@ -2217,6 +2217,14 @@ class RVPBinaryIntrinsic
def int_riscv_pmulhsu_h0 : RVPMulHighPartsIntrinsic;
def int_riscv_pmulhsu_h1 : RVPMulHighPartsIntrinsic;
+ // Packed "Q-format" Multiply with Widening Accumulate.
+ class RVPQFormatWideningAccIntrinsic
+ : DefaultAttrsIntrinsic<[llvm_v2i32_ty],
+ [llvm_v2i32_ty, llvm_v2i16_ty, llvm_v2i16_ty],
+ [IntrNoMem, IntrSpeculatable]>;
+ def int_riscv_pmqwacc_i32x2 : RVPQFormatWideningAccIntrinsic;
+ def int_riscv_pmqrwacc_i32x2 : RVPQFormatWideningAccIntrinsic;
+
// The scalar forms keep a single product of the full-width rs1 and one
// halfword of rs2: <2 x i16> pairs with i32.
class RVPScalarMulHighPartsIntrinsic
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 7730a52a2e26d..477d5a331eb81 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -13414,6 +13414,30 @@ SDValue RISCVTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
return SDValue();
}
+ case Intrinsic::riscv_pmqwacc_i32x2:
+ case Intrinsic::riscv_pmqrwacc_i32x2: {
+ EVT VT = Op.getValueType();
+ SDValue Acc = Op.getOperand(1);
+ SDValue Rs1 = Op.getOperand(2);
+ SDValue Rs2 = Op.getOperand(3);
+
+ if (!Subtarget.is64Bit()) {
+ unsigned Opc = IntNo == Intrinsic::riscv_pmqwacc_i32x2
+ ? RISCVISD::PMQWACC_H
+ : RISCVISD::PMQRWACC_H;
+ return DAG.getNode(Opc, DL, VT, Acc, Rs1, Rs2);
+ }
+
+ Rs1 = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v4i16, Rs1,
+ DAG.getUNDEF(MVT::v2i16));
+ Rs2 = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v4i16, Rs2,
+ DAG.getUNDEF(MVT::v2i16));
+ SDValue Zip = DAG.getNode(RISCVISD::PZIP, DL, MVT::v4i16, Rs1, Rs2);
+ unsigned Opc = IntNo == Intrinsic::riscv_pmqwacc_i32x2
+ ? RISCVISD::PMQACC_W_H01
+ : RISCVISD::PMQRACC_W_H01;
+ return DAG.getNode(Opc, DL, VT, Acc, Zip, Zip);
+ }
case Intrinsic::riscv_mulh_h0:
case Intrinsic::riscv_mulh_h1:
case Intrinsic::riscv_mulhsu_h0:
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index 8a6754b900028..67fee79db0582 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -1926,16 +1926,20 @@ def riscv_pm2waddu
def riscv_pm2waddsu
: RVSDNode<"PM2WADDSU", SDT_RISCVPackedWideningHorizontalAdd>;
-// Packed multiplication with widening horizontal addition and accumulate.
-def SDT_RISCVPackedWideningHorizontalAddAcc
+// Packed widening multiply-accumulate operations.
+def SDT_RISCVPackedWideningAcc
: SDTypeProfile<1, 3, [SDTCisVT<0, v2i32>, SDTCisSameAs<0, 1>,
SDTCisVT<2, v2i16>, SDTCisSameAs<2, 3>]>;
+def riscv_pmqwacc_h
+ : RVSDNode<"PMQWACC_H", SDT_RISCVPackedWideningAcc>;
+def riscv_pmqrwacc_h
+ : RVSDNode<"PMQRWACC_H", SDT_RISCVPackedWideningAcc>;
def riscv_pm2wadda
- : RVSDNode<"PM2WADDA", SDT_RISCVPackedWideningHorizontalAddAcc>;
+ : RVSDNode<"PM2WADDA", SDT_RISCVPackedWideningAcc>;
def riscv_pm2waddau
- : RVSDNode<"PM2WADDAU", SDT_RISCVPackedWideningHorizontalAddAcc>;
+ : RVSDNode<"PM2WADDAU", SDT_RISCVPackedWideningAcc>;
def riscv_pm2waddasu
- : RVSDNode<"PM2WADDASU", SDT_RISCVPackedWideningHorizontalAddAcc>;
+ : RVSDNode<"PM2WADDASU", SDT_RISCVPackedWideningAcc>;
def SDT_RISCVPM2Halfword
: SDTypeProfile<1, 2, [SDTCisVT<0, v2i32>,
@@ -2717,6 +2721,14 @@ let append Predicates = [IsRV32] in {
def : Pat<(v2i32 (riscv_pwmulsu (v2i16 GPR:$rs1), (v2i16 GPR:$rs2))),
(PWMULSU_H GPR:$rs1, GPR:$rs2)>;
+ // Packed Q-format widening multiply-accumulate patterns.
+ def : Pat<(v2i32 (riscv_pmqwacc_h (v2i32 GPRPair:$rd),
+ (v2i16 GPR:$rs1), (v2i16 GPR:$rs2))),
+ (PMQWACC_H GPRPair:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(v2i32 (riscv_pmqrwacc_h (v2i32 GPRPair:$rd),
+ (v2i16 GPR:$rs1), (v2i16 GPR:$rs2))),
+ (PMQRWACC_H GPRPair:$rd, GPR:$rs1, GPR:$rs2)>;
+
// Packed multiplication with widening horizontal addition patterns.
def : Pat<(v2i32 (riscv_pm2wadd (v2i16 GPR:$rs1), (v2i16 GPR:$rs2))),
(PM2WADD_H GPR:$rs1, GPR:$rs2)>;
diff --git a/llvm/test/CodeGen/RISCV/rvp-simd-64.ll b/llvm/test/CodeGen/RISCV/rvp-simd-64.ll
index 77376296bfbdf..3ba711d2082e0 100644
--- a/llvm/test/CodeGen/RISCV/rvp-simd-64.ll
+++ b/llvm/test/CodeGen/RISCV/rvp-simd-64.ll
@@ -8017,6 +8017,38 @@ declare <2 x i32> @llvm.riscv.pmhacc.h0.v2i32(<2 x i32>, <2 x i32>, <4 x i16>)
declare <2 x i32> @llvm.riscv.pmhacc.h1.v2i32(<2 x i32>, <2 x i32>, <4 x i16>)
declare <2 x i32> @llvm.riscv.pmhaccsu.h0.v2i32(<2 x i32>, <2 x i32>, <4 x i16>)
declare <2 x i32> @llvm.riscv.pmhaccsu.h1.v2i32(<2 x i32>, <2 x i32>, <4 x i16>)
+declare <2 x i32> @llvm.riscv.pmqwacc.i32x2(<2 x i32>, <2 x i16>, <2 x i16>)
+declare <2 x i32> @llvm.riscv.pmqrwacc.i32x2(<2 x i32>, <2 x i16>, <2 x i16>)
+
+define <2 x i32> @test_pmqwacc_i32x2(<2 x i32> %rd, <2 x i16> %rs1, <2 x i16> %rs2) {
+; RV32-LABEL: test_pmqwacc_i32x2:
+; RV32: # %bb.0:
+; RV32-NEXT: pmqwacc.h a0, a2, a3
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_pmqwacc_i32x2:
+; RV64: # %bb.0:
+; RV64-NEXT: zip16p a1, a1, a2
+; RV64-NEXT: pmqacc.w.h01 a0, a1, a1
+; RV64-NEXT: ret
+ %r = call <2 x i32> @llvm.riscv.pmqwacc.i32x2(<2 x i32> %rd, <2 x i16> %rs1, <2 x i16> %rs2)
+ ret <2 x i32> %r
+}
+
+define <2 x i32> @test_pmqrwacc_i32x2(<2 x i32> %rd, <2 x i16> %rs1, <2 x i16> %rs2) {
+; RV32-LABEL: test_pmqrwacc_i32x2:
+; RV32: # %bb.0:
+; RV32-NEXT: pmqrwacc.h a0, a2, a3
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_pmqrwacc_i32x2:
+; RV64: # %bb.0:
+; RV64-NEXT: zip16p a1, a1, a2
+; RV64-NEXT: pmqracc.w.h01 a0, a1, a1
+; RV64-NEXT: ret
+ %r = call <2 x i32> @llvm.riscv.pmqrwacc.i32x2(<2 x i32> %rd, <2 x i16> %rs1, <2 x i16> %rs2)
+ ret <2 x i32> %r
+}
define <2 x i32> @test_pmacc_h00_v2i32(<2 x i32> %rd, <4 x i16> %a, <4 x i16> %b) {
; RV32-LABEL: test_pmacc_h00_v2i32:
``````````
</details>
https://github.com/llvm/llvm-project/pull/228009
More information about the llvm-commits
mailing list