[clang] [llvm] [RISCV][P-ext] Add scalar multiply high accumulate intrinsics (PR #232340)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 16 00:46:32 PDT 2026
https://github.com/sihuan updated https://github.com/llvm/llvm-project/pull/232340
>From 8e1a18ea44cec67a330f75c785c5e5da7a7fb649 Mon Sep 17 00:00:00 2001
From: SiHuaN <liyongtai at iscas.ac.cn>
Date: Thu, 15 Oct 2026 13:45:04 +0000
Subject: [PATCH] [RISCV][P-ext] Add scalar multiply high accumulate intrinsics
Add __riscv_mh(r)acc_i32, __riscv_mh(r)accu_u32 and __riscv_mh(r)accsu_i32.
RV32 selects the scalar instructions directly. RV64 has no scalar forms and
uses the pmhacc.w family on the low words.
---
clang/include/clang/Basic/BuiltinsRISCV.td | 8 ++
clang/lib/CodeGen/TargetBuiltins/RISCV.cpp | 20 ++++
clang/lib/Headers/riscv_packed_simd.h | 8 ++
clang/test/CodeGen/RISCV/rvp-intrinsics.c | 98 +++++++++++++++++++
.../riscv_packed_simd.c | 43 ++++++++
llvm/include/llvm/IR/IntrinsicsRISCV.td | 12 +++
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 52 ++++++++++
llvm/test/CodeGen/RISCV/rv32p.ll | 54 ++++++++++
llvm/test/CodeGen/RISCV/rv64p.ll | 54 ++++++++++
9 files changed, 349 insertions(+)
diff --git a/clang/include/clang/Basic/BuiltinsRISCV.td b/clang/include/clang/Basic/BuiltinsRISCV.td
index 9004c815c8a1e..a54f88d00cffc 100644
--- a/clang/include/clang/Basic/BuiltinsRISCV.td
+++ b/clang/include/clang/Basic/BuiltinsRISCV.td
@@ -278,6 +278,14 @@ def mulhru_u32 : RISCVBuiltin<"uint32_t(uint32_t, uint32_t)">;
def mulhsu_i32 : RISCVBuiltin<"int32_t(int32_t, uint32_t)">;
def mulhrsu_i32 : RISCVBuiltin<"int32_t(int32_t, uint32_t)">;
+// Scalar Multiply High Accumulate
+def mhacc_i32 : RISCVBuiltin<"int32_t(int32_t, int32_t, int32_t)">;
+def mhracc_i32 : RISCVBuiltin<"int32_t(int32_t, int32_t, int32_t)">;
+def mhaccu_u32 : RISCVBuiltin<"uint32_t(uint32_t, uint32_t, uint32_t)">;
+def mhraccu_u32 : RISCVBuiltin<"uint32_t(uint32_t, uint32_t, uint32_t)">;
+def mhaccsu_i32 : RISCVBuiltin<"int32_t(int32_t, int32_t, uint32_t)">;
+def mhraccsu_i32 : RISCVBuiltin<"int32_t(int32_t, int32_t, uint32_t)">;
+
// Packed Multiply High (32-bit)
def pmulh_i16x2 : RISCVBuiltin<"_Vector<2, short>(_Vector<2, short>, _Vector<2, short>)">;
def pmulhr_i16x2 : RISCVBuiltin<"_Vector<2, short>(_Vector<2, short>, _Vector<2, short>)">;
diff --git a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
index e6f1d3c59b946..e5b56b2dfd4e0 100644
--- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
@@ -1719,6 +1719,26 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
break;
}
+ // Scalar Multiply High Accumulate
+ case RISCV::BI__builtin_riscv_mhacc_i32:
+ ID = Intrinsic::riscv_mhacc_i32;
+ break;
+ case RISCV::BI__builtin_riscv_mhracc_i32:
+ ID = Intrinsic::riscv_mhracc_i32;
+ break;
+ case RISCV::BI__builtin_riscv_mhaccu_u32:
+ ID = Intrinsic::riscv_mhaccu_u32;
+ break;
+ case RISCV::BI__builtin_riscv_mhraccu_u32:
+ ID = Intrinsic::riscv_mhraccu_u32;
+ break;
+ case RISCV::BI__builtin_riscv_mhaccsu_i32:
+ ID = Intrinsic::riscv_mhaccsu_i32;
+ break;
+ case RISCV::BI__builtin_riscv_mhraccsu_i32:
+ ID = Intrinsic::riscv_mhraccsu_i32;
+ break;
+
// Packed "Q-format" Multiply with Widening Accumulate
case RISCV::BI__builtin_riscv_pmqwacc_i32x2:
case RISCV::BI__builtin_riscv_pmqrwacc_i32x2: {
diff --git a/clang/lib/Headers/riscv_packed_simd.h b/clang/lib/Headers/riscv_packed_simd.h
index 4bf017f81db9f..af6501a479be2 100644
--- a/clang/lib/Headers/riscv_packed_simd.h
+++ b/clang/lib/Headers/riscv_packed_simd.h
@@ -478,6 +478,14 @@ __packed_mulh_builtin(mulhsu_i32, int32_t, int32_t, uint32_t)
__packed_mulh_builtin(mulhrsu_i32, int32_t, int32_t, uint32_t)
#undef __packed_mulh_builtin
+/* Scalar Multiply High Accumulate */
+__packed_ternary_builtin(mhacc_i32, int32_t, __builtin_riscv_mhacc_i32)
+__packed_ternary_builtin(mhracc_i32, int32_t, __builtin_riscv_mhracc_i32)
+__packed_ternary_builtin(mhaccu_u32, uint32_t, __builtin_riscv_mhaccu_u32)
+__packed_ternary_builtin(mhraccu_u32, uint32_t, __builtin_riscv_mhraccu_u32)
+__packed_ternary_builtin_mixed(mhaccsu_i32, int32_t, int32_t, uint32_t, __builtin_riscv_mhaccsu_i32)
+__packed_ternary_builtin_mixed(mhraccsu_i32, int32_t, int32_t, uint32_t, __builtin_riscv_mhraccsu_i32)
+
/* Packed Splat (32-bit) */
__packed_splat(pmv_s_u8x4, uint8x4_t, uint8_t, __packed_splat4)
__packed_splat(pmv_s_i8x4, int8x4_t, int8_t, __packed_splat4)
diff --git a/clang/test/CodeGen/RISCV/rvp-intrinsics.c b/clang/test/CodeGen/RISCV/rvp-intrinsics.c
index b672c04bc35d5..682df011b1d1b 100644
--- a/clang/test/CodeGen/RISCV/rvp-intrinsics.c
+++ b/clang/test/CodeGen/RISCV/rvp-intrinsics.c
@@ -396,6 +396,104 @@ int32_t test_mulhrsu_i32(int32_t a, uint32_t b) {
return __riscv_mulhrsu_i32(a, b);
}
+/* Scalar Multiply High Accumulate */
+
+// RV32-LABEL: define dso_local i32 @test_mhacc_i32(
+// RV32-SAME: i32 noundef [[RD:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] {
+// RV32-NEXT: [[ENTRY:.*:]]
+// RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.mhacc.i32(i32 [[RD]], i32 [[A]], i32 [[B]])
+// RV32-NEXT: ret i32 [[TMP0]]
+//
+// RV64-LABEL: define dso_local signext i32 @test_mhacc_i32(
+// RV64-SAME: i32 noundef signext [[RD:%.*]], i32 noundef signext [[A:%.*]], i32 noundef signext [[B:%.*]]) #[[ATTR0]] {
+// RV64-NEXT: [[ENTRY:.*:]]
+// RV64-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.mhacc.i32(i32 [[RD]], i32 [[A]], i32 [[B]])
+// RV64-NEXT: ret i32 [[TMP0]]
+//
+int32_t test_mhacc_i32(int32_t rd, int32_t a, int32_t b) {
+ return __riscv_mhacc_i32(rd, a, b);
+}
+
+// RV32-LABEL: define dso_local i32 @test_mhracc_i32(
+// RV32-SAME: i32 noundef [[RD:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] {
+// RV32-NEXT: [[ENTRY:.*:]]
+// RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.mhracc.i32(i32 [[RD]], i32 [[A]], i32 [[B]])
+// RV32-NEXT: ret i32 [[TMP0]]
+//
+// RV64-LABEL: define dso_local signext i32 @test_mhracc_i32(
+// RV64-SAME: i32 noundef signext [[RD:%.*]], i32 noundef signext [[A:%.*]], i32 noundef signext [[B:%.*]]) #[[ATTR0]] {
+// RV64-NEXT: [[ENTRY:.*:]]
+// RV64-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.mhracc.i32(i32 [[RD]], i32 [[A]], i32 [[B]])
+// RV64-NEXT: ret i32 [[TMP0]]
+//
+int32_t test_mhracc_i32(int32_t rd, int32_t a, int32_t b) {
+ return __riscv_mhracc_i32(rd, a, b);
+}
+
+// RV32-LABEL: define dso_local i32 @test_mhaccu_u32(
+// RV32-SAME: i32 noundef [[RD:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] {
+// RV32-NEXT: [[ENTRY:.*:]]
+// RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.mhaccu.u32(i32 [[RD]], i32 [[A]], i32 [[B]])
+// RV32-NEXT: ret i32 [[TMP0]]
+//
+// RV64-LABEL: define dso_local signext i32 @test_mhaccu_u32(
+// RV64-SAME: i32 noundef signext [[RD:%.*]], i32 noundef signext [[A:%.*]], i32 noundef signext [[B:%.*]]) #[[ATTR0]] {
+// RV64-NEXT: [[ENTRY:.*:]]
+// RV64-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.mhaccu.u32(i32 [[RD]], i32 [[A]], i32 [[B]])
+// RV64-NEXT: ret i32 [[TMP0]]
+//
+uint32_t test_mhaccu_u32(uint32_t rd, uint32_t a, uint32_t b) {
+ return __riscv_mhaccu_u32(rd, a, b);
+}
+
+// RV32-LABEL: define dso_local i32 @test_mhraccu_u32(
+// RV32-SAME: i32 noundef [[RD:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] {
+// RV32-NEXT: [[ENTRY:.*:]]
+// RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.mhraccu.u32(i32 [[RD]], i32 [[A]], i32 [[B]])
+// RV32-NEXT: ret i32 [[TMP0]]
+//
+// RV64-LABEL: define dso_local signext i32 @test_mhraccu_u32(
+// RV64-SAME: i32 noundef signext [[RD:%.*]], i32 noundef signext [[A:%.*]], i32 noundef signext [[B:%.*]]) #[[ATTR0]] {
+// RV64-NEXT: [[ENTRY:.*:]]
+// RV64-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.mhraccu.u32(i32 [[RD]], i32 [[A]], i32 [[B]])
+// RV64-NEXT: ret i32 [[TMP0]]
+//
+uint32_t test_mhraccu_u32(uint32_t rd, uint32_t a, uint32_t b) {
+ return __riscv_mhraccu_u32(rd, a, b);
+}
+
+// RV32-LABEL: define dso_local i32 @test_mhaccsu_i32(
+// RV32-SAME: i32 noundef [[RD:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] {
+// RV32-NEXT: [[ENTRY:.*:]]
+// RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.mhaccsu.i32(i32 [[RD]], i32 [[A]], i32 [[B]])
+// RV32-NEXT: ret i32 [[TMP0]]
+//
+// RV64-LABEL: define dso_local signext i32 @test_mhaccsu_i32(
+// RV64-SAME: i32 noundef signext [[RD:%.*]], i32 noundef signext [[A:%.*]], i32 noundef signext [[B:%.*]]) #[[ATTR0]] {
+// RV64-NEXT: [[ENTRY:.*:]]
+// RV64-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.mhaccsu.i32(i32 [[RD]], i32 [[A]], i32 [[B]])
+// RV64-NEXT: ret i32 [[TMP0]]
+//
+int32_t test_mhaccsu_i32(int32_t rd, int32_t a, uint32_t b) {
+ return __riscv_mhaccsu_i32(rd, a, b);
+}
+
+// RV32-LABEL: define dso_local i32 @test_mhraccsu_i32(
+// RV32-SAME: i32 noundef [[RD:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] {
+// RV32-NEXT: [[ENTRY:.*:]]
+// RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.mhraccsu.i32(i32 [[RD]], i32 [[A]], i32 [[B]])
+// RV32-NEXT: ret i32 [[TMP0]]
+//
+// RV64-LABEL: define dso_local signext i32 @test_mhraccsu_i32(
+// RV64-SAME: i32 noundef signext [[RD:%.*]], i32 noundef signext [[A:%.*]], i32 noundef signext [[B:%.*]]) #[[ATTR0]] {
+// RV64-NEXT: [[ENTRY:.*:]]
+// RV64-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.mhraccsu.i32(i32 [[RD]], i32 [[A]], i32 [[B]])
+// RV64-NEXT: ret i32 [[TMP0]]
+//
+int32_t test_mhraccsu_i32(int32_t rd, int32_t a, uint32_t b) {
+ return __riscv_mhraccsu_i32(rd, a, b);
+}
+
/* Packed Splat (32-bit) */
// CHECK-LABEL: define dso_local i32 @test_pmv_s_u8x4(
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 75c5a1ff8b75d..8b012c3376f0f 100644
--- a/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
+++ b/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
@@ -3122,6 +3122,49 @@ int32_t test_mulhrsu_i32(int32_t rs1, uint32_t rs2) {
return __riscv_mulhrsu_i32(rs1, rs2);
}
+// Scalar multiply high accumulate
+// CHECK-LABEL: test_mhacc_i32:
+// RV32: mhacc{{[[:space:]]}}
+// RV64: pmhacc.w
+int32_t test_mhacc_i32(int32_t rd, int32_t rs1, int32_t rs2) {
+ return __riscv_mhacc_i32(rd, rs1, rs2);
+}
+
+// CHECK-LABEL: test_mhracc_i32:
+// RV32: mhracc{{[[:space:]]}}
+// RV64: pmhracc.w
+int32_t test_mhracc_i32(int32_t rd, int32_t rs1, int32_t rs2) {
+ return __riscv_mhracc_i32(rd, rs1, rs2);
+}
+
+// CHECK-LABEL: test_mhaccu_u32:
+// RV32: mhaccu{{[[:space:]]}}
+// RV64: pmhaccu.w
+uint32_t test_mhaccu_u32(uint32_t rd, uint32_t rs1, uint32_t rs2) {
+ return __riscv_mhaccu_u32(rd, rs1, rs2);
+}
+
+// CHECK-LABEL: test_mhraccu_u32:
+// RV32: mhraccu{{[[:space:]]}}
+// RV64: pmhraccu.w
+uint32_t test_mhraccu_u32(uint32_t rd, uint32_t rs1, uint32_t rs2) {
+ return __riscv_mhraccu_u32(rd, rs1, rs2);
+}
+
+// CHECK-LABEL: test_mhaccsu_i32:
+// RV32: mhaccsu{{[[:space:]]}}
+// RV64: pmhaccsu.w
+int32_t test_mhaccsu_i32(int32_t rd, int32_t rs1, uint32_t rs2) {
+ return __riscv_mhaccsu_i32(rd, rs1, rs2);
+}
+
+// CHECK-LABEL: test_mhraccsu_i32:
+// RV32: mhraccsu{{[[:space:]]}}
+// RV64: pmhraccsu.w
+int32_t test_mhraccsu_i32(int32_t rd, int32_t rs1, uint32_t rs2) {
+ return __riscv_mhraccsu_i32(rd, rs1, rs2);
+}
+
// CHECK-LABEL: test_pmulh_i16x2:
// CHECK: pmulh.h
int16x2_t test_pmulh_i16x2(int16x2_t rs1, int16x2_t rs2) {
diff --git a/llvm/include/llvm/IR/IntrinsicsRISCV.td b/llvm/include/llvm/IR/IntrinsicsRISCV.td
index c33f0fa792f0f..db2ea7052ad05 100644
--- a/llvm/include/llvm/IR/IntrinsicsRISCV.td
+++ b/llvm/include/llvm/IR/IntrinsicsRISCV.td
@@ -2186,6 +2186,18 @@ class RVPBinaryIntrinsic
def int_riscv_mulhsu_i32 : RVPScalarMulHighIntrinsic;
def int_riscv_mulhrsu_i32 : RVPScalarMulHighIntrinsic;
+ // Scalar Multiply High Accumulate.
+ class RVPScalarTernaryIntrinsic
+ : DefaultAttrsIntrinsic<[llvm_i32_ty],
+ [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
+ [IntrNoMem, IntrSpeculatable]>;
+ def int_riscv_mhacc_i32 : RVPScalarTernaryIntrinsic;
+ def int_riscv_mhracc_i32 : RVPScalarTernaryIntrinsic;
+ def int_riscv_mhaccu_u32 : RVPScalarTernaryIntrinsic;
+ def int_riscv_mhraccu_u32 : RVPScalarTernaryIntrinsic;
+ def int_riscv_mhaccsu_i32 : RVPScalarTernaryIntrinsic;
+ def int_riscv_mhraccsu_i32 : RVPScalarTernaryIntrinsic;
+
// Packed Multiply High Accumulate.
def int_riscv_pmhacc : RVPTernaryIntrinsic;
def int_riscv_pmhracc : RVPTernaryIntrinsic;
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 00dbaeab507cb..62129b8f1acbb 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -12433,6 +12433,26 @@ static unsigned getRVScalarMulHighOpcode(unsigned IntNo) {
}
}
+static unsigned getRVScalarMulHighAccumulateOpcode(unsigned IntNo) {
+ switch (IntNo) {
+ default:
+ llvm_unreachable(
+ "Unexpected RISC-V scalar multiply high accumulate intrinsic");
+ case Intrinsic::riscv_mhacc_i32:
+ return RISCVISD::MHACC;
+ case Intrinsic::riscv_mhracc_i32:
+ return RISCVISD::MHRACC;
+ case Intrinsic::riscv_mhaccu_u32:
+ return RISCVISD::MHACCU;
+ case Intrinsic::riscv_mhraccu_u32:
+ return RISCVISD::MHRACCU;
+ case Intrinsic::riscv_mhaccsu_i32:
+ return RISCVISD::MHACCSU;
+ case Intrinsic::riscv_mhraccsu_i32:
+ return RISCVISD::MHRACCSU;
+ }
+}
+
static unsigned getRVPMulHighAccumulateOpcode(unsigned IntNo) {
switch (IntNo) {
default:
@@ -13364,6 +13384,17 @@ SDValue RISCVTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
unsigned Opc = getRVScalarMulHighOpcode(IntNo);
return DAG.getNode(Opc, DL, MVT::i32, Op.getOperand(1), Op.getOperand(2));
}
+ case Intrinsic::riscv_mhacc_i32:
+ case Intrinsic::riscv_mhracc_i32:
+ case Intrinsic::riscv_mhaccu_u32:
+ case Intrinsic::riscv_mhraccu_u32:
+ case Intrinsic::riscv_mhaccsu_i32:
+ case Intrinsic::riscv_mhraccsu_i32: {
+ // RV64 goes via ReplaceNodeResults.
+ unsigned Opc = getRVScalarMulHighAccumulateOpcode(IntNo);
+ return DAG.getNode(Opc, DL, MVT::i32, Op.getOperand(1), Op.getOperand(2),
+ Op.getOperand(3));
+ }
case Intrinsic::riscv_pmhacc:
case Intrinsic::riscv_pmhracc:
case Intrinsic::riscv_pmhaccu:
@@ -18059,6 +18090,27 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
Results.push_back(DAG.getExtractVectorElt(DL, MVT::i32, Res, 0));
return;
}
+ case Intrinsic::riscv_mhacc_i32:
+ case Intrinsic::riscv_mhracc_i32:
+ case Intrinsic::riscv_mhaccu_u32:
+ case Intrinsic::riscv_mhraccu_u32:
+ case Intrinsic::riscv_mhaccsu_i32:
+ case Intrinsic::riscv_mhraccsu_i32: {
+ // RV64 has no scalar mhacc; use pmhacc.w on the low words.
+ MVT VT = N->getSimpleValueType(0);
+ if (!Subtarget.is64Bit() || VT != MVT::i32)
+ return;
+ unsigned Opc = getRVScalarMulHighAccumulateOpcode(IntNo);
+ SDValue Rd =
+ DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2i32, N->getOperand(1));
+ SDValue Rs1 =
+ DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2i32, N->getOperand(2));
+ SDValue Rs2 =
+ DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2i32, N->getOperand(3));
+ SDValue Res = DAG.getNode(Opc, DL, MVT::v2i32, Rd, Rs1, Rs2);
+ Results.push_back(DAG.getExtractVectorElt(DL, MVT::i32, Res, 0));
+ return;
+ }
case Intrinsic::riscv_pnclipp:
case Intrinsic::riscv_pnclipup: {
bool IsSigned = IntNo == Intrinsic::riscv_pnclipp;
diff --git a/llvm/test/CodeGen/RISCV/rv32p.ll b/llvm/test/CodeGen/RISCV/rv32p.ll
index 1a4d623427a0a..3f9298d2efda0 100644
--- a/llvm/test/CodeGen/RISCV/rv32p.ll
+++ b/llvm/test/CodeGen/RISCV/rv32p.ll
@@ -2421,3 +2421,57 @@ define i32 @test_mulhrsu_i32(i32 %rs1, i32 %rs2) {
%res = call i32 @llvm.riscv.mulhrsu.i32(i32 %rs1, i32 %rs2)
ret i32 %res
}
+
+define i32 @test_mhacc_i32(i32 %rd, i32 %a, i32 %b) {
+; CHECK-LABEL: test_mhacc_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: mhacc a0, a1, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.mhacc.i32(i32 %rd, i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_mhracc_i32(i32 %rd, i32 %a, i32 %b) {
+; CHECK-LABEL: test_mhracc_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: mhracc a0, a1, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.mhracc.i32(i32 %rd, i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_mhaccu_u32(i32 %rd, i32 %a, i32 %b) {
+; CHECK-LABEL: test_mhaccu_u32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: mhaccu a0, a1, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.mhaccu.u32(i32 %rd, i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_mhraccu_u32(i32 %rd, i32 %a, i32 %b) {
+; CHECK-LABEL: test_mhraccu_u32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: mhraccu a0, a1, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.mhraccu.u32(i32 %rd, i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_mhaccsu_i32(i32 %rd, i32 %a, i32 %b) {
+; CHECK-LABEL: test_mhaccsu_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: mhaccsu a0, a1, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.mhaccsu.i32(i32 %rd, i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_mhraccsu_i32(i32 %rd, i32 %a, i32 %b) {
+; CHECK-LABEL: test_mhraccsu_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: mhraccsu a0, a1, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.mhraccsu.i32(i32 %rd, i32 %a, i32 %b)
+ ret i32 %res
+}
diff --git a/llvm/test/CodeGen/RISCV/rv64p.ll b/llvm/test/CodeGen/RISCV/rv64p.ll
index 5ceae2996fe3d..c688a48998855 100644
--- a/llvm/test/CodeGen/RISCV/rv64p.ll
+++ b/llvm/test/CodeGen/RISCV/rv64p.ll
@@ -1897,3 +1897,57 @@ define i32 @test_asubu_u32(i32 %a, i32 %b) {
%res = call i32 @llvm.riscv.asubu.u32(i32 %a, i32 %b)
ret i32 %res
}
+
+define i32 @test_mhacc_i32(i32 %rd, i32 %a, i32 %b) {
+; CHECK-LABEL: test_mhacc_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pmhacc.w a0, a1, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.mhacc.i32(i32 %rd, i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_mhracc_i32(i32 %rd, i32 %a, i32 %b) {
+; CHECK-LABEL: test_mhracc_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pmhracc.w a0, a1, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.mhracc.i32(i32 %rd, i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_mhaccu_u32(i32 %rd, i32 %a, i32 %b) {
+; CHECK-LABEL: test_mhaccu_u32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pmhaccu.w a0, a1, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.mhaccu.u32(i32 %rd, i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_mhraccu_u32(i32 %rd, i32 %a, i32 %b) {
+; CHECK-LABEL: test_mhraccu_u32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pmhraccu.w a0, a1, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.mhraccu.u32(i32 %rd, i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_mhaccsu_i32(i32 %rd, i32 %a, i32 %b) {
+; CHECK-LABEL: test_mhaccsu_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pmhaccsu.w a0, a1, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.mhaccsu.i32(i32 %rd, i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_mhraccsu_i32(i32 %rd, i32 %a, i32 %b) {
+; CHECK-LABEL: test_mhraccsu_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pmhraccsu.w a0, a1, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.mhraccsu.i32(i32 %rd, i32 %a, i32 %b)
+ ret i32 %res
+}
More information about the cfe-commits
mailing list