Author: SiHuaN Date: 2026-10-23T14:55:02+08:00 New Revision: 85b46e668a8a905338b9fa5bd6d5e4ec96d0ec73
URL: https://github.com/llvm/llvm-project/commit/85b46e668a8a905338b9fa5bd6d5e4ec96d0ec73 DIFF: https://github.com/llvm/llvm-project/commit/85b46e668a8a905338b9fa5bd6d5e4ec96d0ec73.diff LOG: [RISCV][P-ext] Add scalar mqwacc/mqrwacc intrinsics (#234560) Add the scalar "Q-format" Multiply with Widening Accumulate intrinsics: https://github.com/riscv/riscv-p-spec/blob/master/P-ext-intrinsics.adoc#q-format-multiply-with-widening-accumulate - `__riscv_mqwacc_i64` - `__riscv_mqrwacc_i64` Added: Modified: clang/include/clang/Basic/BuiltinsRISCV.td clang/lib/CodeGen/TargetBuiltins/RISCV.cpp clang/lib/Headers/riscv_packed_simd.h clang/test/CodeGen/RISCV/rvp-intrinsics.c cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c llvm/include/llvm/IR/IntrinsicsRISCV.td llvm/lib/Target/RISCV/RISCVISelLowering.cpp llvm/test/CodeGen/RISCV/rvp-scalar.ll Removed: ################################################################################ diff --git a/clang/include/clang/Basic/BuiltinsRISCV.td b/clang/include/clang/Basic/BuiltinsRISCV.td index 08986145b288f..0a51ebdd3301d 100644 --- a/clang/include/clang/Basic/BuiltinsRISCV.td +++ b/clang/include/clang/Basic/BuiltinsRISCV.td @@ -299,6 +299,10 @@ def mhraccsu_i32 : RISCVBuiltin<"int32_t(int32_t, int32_t, uint32_t)">; def mulq_i32 : RISCVBuiltin<"int32_t(int32_t, int32_t)">; def mulqr_i32 : RISCVBuiltin<"int32_t(int32_t, int32_t)">; +// Scalar "Q-format" Multiply with Widening Accumulate +def mqwacc_i64 : RISCVBuiltin<"int64_t(int64_t, int32_t, int32_t)">; +def mqrwacc_i64 : RISCVBuiltin<"int64_t(int64_t, int32_t, int32_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 7c49a78f8c6e8..eb38a20f32e28 100644 --- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp @@ -1760,6 +1760,14 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID, ID = Intrinsic::riscv_mulqr_i32; break; + // Scalar "Q-format" Multiply with Widening Accumulate + case RISCV::BI__builtin_riscv_mqwacc_i64: + ID = Intrinsic::riscv_mqwacc_i64; + break; + case RISCV::BI__builtin_riscv_mqrwacc_i64: + ID = Intrinsic::riscv_mqrwacc_i64; + 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 29c0ae7c3e724..e166308fd6058 100644 --- a/clang/lib/Headers/riscv_packed_simd.h +++ b/clang/lib/Headers/riscv_packed_simd.h @@ -498,6 +498,10 @@ __packed_ternary_builtin_mixed(mhraccsu_i32, int32_t, int32_t, uint32_t, __built __packed_binary_builtin(mulq_i32, int32_t, __builtin_riscv_mulq_i32) __packed_binary_builtin(mulqr_i32, int32_t, __builtin_riscv_mulqr_i32) +/* Scalar "Q-format" Multiply with Widening Accumulate */ +__packed_ternary_builtin_mixed(mqwacc_i64, int64_t, int32_t, int32_t, __builtin_riscv_mqwacc_i64) +__packed_ternary_builtin_mixed(mqrwacc_i64, int64_t, int32_t, int32_t, __builtin_riscv_mqrwacc_i64) + /* 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 b5d5b46898eaf..7decad176c949 100644 --- a/clang/test/CodeGen/RISCV/rvp-intrinsics.c +++ b/clang/test/CodeGen/RISCV/rvp-intrinsics.c @@ -584,6 +584,40 @@ int32_t test_mulqr_i32(int32_t a, int32_t b) { return __riscv_mulqr_i32(a, b); } +/* Scalar "Q-format" Multiply with Widening Accumulate */ + +// RV32-LABEL: define dso_local i64 @test_mqwacc_i64( +// RV32-SAME: i64 noundef [[RD:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.mqwacc.i64(i64 [[RD]], i32 [[A]], i32 [[B]]) +// RV32-NEXT: ret i64 [[TMP0]] +// +// RV64-LABEL: define dso_local i64 @test_mqwacc_i64( +// RV64-SAME: i64 noundef [[RD:%.*]], i32 noundef signext [[A:%.*]], i32 noundef signext [[B:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.mqwacc.i64(i64 [[RD]], i32 [[A]], i32 [[B]]) +// RV64-NEXT: ret i64 [[TMP0]] +// +int64_t test_mqwacc_i64(int64_t rd, int32_t a, int32_t b) { + return __riscv_mqwacc_i64(rd, a, b); +} + +// RV32-LABEL: define dso_local i64 @test_mqrwacc_i64( +// RV32-SAME: i64 noundef [[RD:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.mqrwacc.i64(i64 [[RD]], i32 [[A]], i32 [[B]]) +// RV32-NEXT: ret i64 [[TMP0]] +// +// RV64-LABEL: define dso_local i64 @test_mqrwacc_i64( +// RV64-SAME: i64 noundef [[RD:%.*]], i32 noundef signext [[A:%.*]], i32 noundef signext [[B:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.mqrwacc.i64(i64 [[RD]], i32 [[A]], i32 [[B]]) +// RV64-NEXT: ret i64 [[TMP0]] +// +int64_t test_mqrwacc_i64(int64_t rd, int32_t a, int32_t b) { + return __riscv_mqrwacc_i64(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 01c9bceeb7e51..20947a723b1fc 100644 --- a/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c +++ b/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c @@ -3200,6 +3200,21 @@ int32_t test_mulqr_i32(int32_t rs1, int32_t rs2) { return __riscv_mulqr_i32(rs1, rs2); } +// Scalar "Q-format" multiply with widening accumulate +// CHECK-LABEL: test_mqwacc_i64: +// RV32: mqwacc{{[[:space:]]}} +// RV64: mqacc.w00 +int64_t test_mqwacc_i64(int64_t rd, int32_t rs1, int32_t rs2) { + return __riscv_mqwacc_i64(rd, rs1, rs2); +} + +// CHECK-LABEL: test_mqrwacc_i64: +// RV32: mqrwacc{{[[:space:]]}} +// RV64: mqracc.w00 +int64_t test_mqrwacc_i64(int64_t rd, int32_t rs1, int32_t rs2) { + return __riscv_mqrwacc_i64(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 62240d869496e..79b7022d476de 100644 --- a/llvm/include/llvm/IR/IntrinsicsRISCV.td +++ b/llvm/include/llvm/IR/IntrinsicsRISCV.td @@ -2211,6 +2211,14 @@ class RVPBinaryIntrinsic def int_riscv_mulq_i32 : RVPScalarBinaryIntrinsic; def int_riscv_mulqr_i32 : RVPScalarBinaryIntrinsic; + // Scalar "Q-format" Multiply with Widening Accumulate. + class RVPScalarQFormatWideningAccIntrinsic + : DefaultAttrsIntrinsic<[llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, IntrSpeculatable]>; + def int_riscv_mqwacc_i64 : RVPScalarQFormatWideningAccIntrinsic; + def int_riscv_mqrwacc_i64 : RVPScalarQFormatWideningAccIntrinsic; + // 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 99bc59f61286a..728e406c822b3 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -13473,6 +13473,18 @@ SDValue RISCVTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, unsigned Opc = getRVScalarQFormatMulOpcode(IntNo); return DAG.getNode(Opc, DL, MVT::i32, Op.getOperand(1), Op.getOperand(2)); } + case Intrinsic::riscv_mqwacc_i64: + case Intrinsic::riscv_mqrwacc_i64: { + // RV32 goes via ReplaceNodeResults. RV64 uses mqacc.w00 on the low words. + unsigned Opc = IntNo == Intrinsic::riscv_mqwacc_i64 + ? RISCVISD::MQACC_HALVES_00 + : RISCVISD::MQRACC_HALVES_00; + SDValue Rs1 = + DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2i32, Op.getOperand(2)); + SDValue Rs2 = + DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2i32, Op.getOperand(3)); + return DAG.getNode(Opc, DL, MVT::i64, Op.getOperand(1), Rs1, Rs2); + } case Intrinsic::riscv_pmhacc: case Intrinsic::riscv_pmhracc: case Intrinsic::riscv_pmhaccu: @@ -18344,6 +18356,21 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N, Results.push_back(DAG.getExtractVectorElt(DL, MVT::i32, Res, 0)); return; } + case Intrinsic::riscv_mqwacc_i64: + case Intrinsic::riscv_mqrwacc_i64: { + if (Subtarget.is64Bit()) + return; + unsigned Opc = IntNo == Intrinsic::riscv_mqwacc_i64 ? RISCVISD::MQWACC + : RISCVISD::MQRWACC; + auto [RdLo, RdHi] = + DAG.SplitScalar(N->getOperand(1), DL, MVT::i32, MVT::i32); + SDValue Acc = + DAG.getNode(Opc, DL, DAG.getVTList(MVT::i32, MVT::i32), + {RdLo, RdHi, N->getOperand(2), N->getOperand(3)}); + Results.push_back(DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, + Acc.getValue(0), Acc.getValue(1))); + return; + } case Intrinsic::riscv_pnclipp: case Intrinsic::riscv_pnclipup: { bool IsSigned = IntNo == Intrinsic::riscv_pnclipp; diff --git a/llvm/test/CodeGen/RISCV/rvp-scalar.ll b/llvm/test/CodeGen/RISCV/rvp-scalar.ll index 53f660ef91d13..0292a0b44c195 100644 --- a/llvm/test/CodeGen/RISCV/rvp-scalar.ll +++ b/llvm/test/CodeGen/RISCV/rvp-scalar.ll @@ -3815,3 +3815,31 @@ define i32 @test_mulqr_i32(i32 %a, i32 %b) { %res = call i32 @llvm.riscv.mulqr.i32(i32 %a, i32 %b) ret i32 %res } + +define i64 @test_mqwacc_i64(i64 %rd, i32 %a, i32 %b) { +; RV32-LABEL: test_mqwacc_i64: +; RV32: # %bb.0: +; RV32-NEXT: mqwacc a0, a2, a3 +; RV32-NEXT: ret +; +; RV64-LABEL: test_mqwacc_i64: +; RV64: # %bb.0: +; RV64-NEXT: mqacc.w00 a0, a1, a2 +; RV64-NEXT: ret + %res = call i64 @llvm.riscv.mqwacc.i64(i64 %rd, i32 %a, i32 %b) + ret i64 %res +} + +define i64 @test_mqrwacc_i64(i64 %rd, i32 %a, i32 %b) { +; RV32-LABEL: test_mqrwacc_i64: +; RV32: # %bb.0: +; RV32-NEXT: mqrwacc a0, a2, a3 +; RV32-NEXT: ret +; +; RV64-LABEL: test_mqrwacc_i64: +; RV64: # %bb.0: +; RV64-NEXT: mqracc.w00 a0, a1, a2 +; RV64-NEXT: ret + %res = call i64 @llvm.riscv.mqrwacc.i64(i64 %rd, i32 %a, i32 %b) + ret i64 %res +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
