https://github.com/XChy created https://github.com/llvm/llvm-project/pull/218430
See also https://github.com/riscv/riscv-p-spec/blob/master/P-ext-intrinsics.adoc#packed-multiplication-with-horizontal-addition. >From 43bcc1fcfb9201599983b71aaa21b3d9bbb06dc3 Mon Sep 17 00:00:00 2001 From: XChy <[email protected]> Date: Mon, 24 Aug 2026 22:10:31 +0800 Subject: [PATCH] [RISCV] Support Packed Multiplication with Horizontal Addition --- clang/include/clang/Basic/BuiltinsRISCV.td | 41 ++ clang/lib/CodeGen/TargetBuiltins/RISCV.cpp | 110 +++++ clang/lib/Headers/riscv_packed_simd.h | 41 ++ .../riscv_packed_simd.c | 285 +++++++++++++ llvm/include/llvm/IR/IntrinsicsRISCV.td | 19 + llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 100 +++++ llvm/lib/Target/RISCV/RISCVInstrInfoP.td | 140 +++++++ llvm/test/CodeGen/RISCV/rvp-simd-32.ll | 117 ++++++ llvm/test/CodeGen/RISCV/rvp-simd-64.ll | 375 ++++++++++++++++++ 9 files changed, 1228 insertions(+) diff --git a/clang/include/clang/Basic/BuiltinsRISCV.td b/clang/include/clang/Basic/BuiltinsRISCV.td index 89dbf736f4435..9cddafd659af1 100644 --- a/clang/include/clang/Basic/BuiltinsRISCV.td +++ b/clang/include/clang/Basic/BuiltinsRISCV.td @@ -291,6 +291,47 @@ def pmhaccsu_i32x2 : RISCVBuiltin<"_Vector<2, int>(_Vector<2, int>, _Vector<2, i def pmhraccsu_i16x4 : RISCVBuiltin<"_Vector<4, short>(_Vector<4, short>, _Vector<4, short>, _Vector<4, unsigned short>)">; def pmhraccsu_i32x2 : RISCVBuiltin<"_Vector<2, int>(_Vector<2, int>, _Vector<2, int>, _Vector<2, unsigned int>)">; +// 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>)">; +def pm2add_x_i16x2 : RISCVBuiltin<"int(_Vector<2, short>, _Vector<2, short>)">; +def pm4addu_u8x4 : RISCVBuiltin<"unsigned int(_Vector<4, unsigned char>, _Vector<4, unsigned char>)">; +def pm2addu_u16x2 : RISCVBuiltin<"unsigned int(_Vector<2, unsigned short>, _Vector<2, unsigned short>)">; +def pmq2add_i16x2 : RISCVBuiltin<"int(_Vector<2, short>, _Vector<2, short>)">; +def pmqr2add_i16x2 : RISCVBuiltin<"int(_Vector<2, short>, _Vector<2, short>)">; +def pm2sadd_i16x2 : RISCVBuiltin<"int(_Vector<2, short>, _Vector<2, short>)">; +def pm2sadd_x_i16x2 : RISCVBuiltin<"int(_Vector<2, short>, _Vector<2, short>)">; +def pm2sub_i16x2 : RISCVBuiltin<"int(_Vector<2, short>, _Vector<2, short>)">; +def pm2sub_x_i16x2 : RISCVBuiltin<"int(_Vector<2, short>, _Vector<2, short>)">; +def pm4addsu_i8x4 : RISCVBuiltin<"int(_Vector<4, signed char>, _Vector<4, unsigned char>)">; +def pm2addsu_i16x2 : RISCVBuiltin<"int(_Vector<2, short>, _Vector<2, unsigned short>)">; + +// Packed Multiplication with Horizontal Addition (64-bit) +def pm4add_i8x8 : RISCVBuiltin<"_Vector<2, int>(_Vector<8, signed char>, _Vector<8, signed char>)">; +def pm2add_i16x4 : RISCVBuiltin<"_Vector<2, int>(_Vector<4, short>, _Vector<4, short>)">; +def pm2add_x_i16x4 : RISCVBuiltin<"_Vector<2, int>(_Vector<4, short>, _Vector<4, short>)">; +def pm4addu_u8x8 : RISCVBuiltin<"_Vector<2, unsigned int>(_Vector<8, unsigned char>, _Vector<8, unsigned char>)">; +def pm2addu_u16x4 : RISCVBuiltin<"_Vector<2, unsigned int>(_Vector<4, unsigned short>, _Vector<4, unsigned short>)">; +def pmq2add_i16x4 : RISCVBuiltin<"_Vector<2, int>(_Vector<4, short>, _Vector<4, short>)">; +def pmqr2add_i16x4 : RISCVBuiltin<"_Vector<2, int>(_Vector<4, short>, _Vector<4, short>)">; +def pm2sadd_i16x4 : RISCVBuiltin<"_Vector<2, int>(_Vector<4, short>, _Vector<4, short>)">; +def pm2sadd_x_i16x4 : RISCVBuiltin<"_Vector<2, int>(_Vector<4, short>, _Vector<4, short>)">; +def pm2sub_i16x4 : RISCVBuiltin<"_Vector<2, int>(_Vector<4, short>, _Vector<4, short>)">; +def pm2sub_x_i16x4 : RISCVBuiltin<"_Vector<2, int>(_Vector<4, short>, _Vector<4, short>)">; +def pm4addsu_i8x8 : RISCVBuiltin<"_Vector<2, int>(_Vector<8, signed char>, _Vector<8, unsigned char>)">; +def pm2addsu_i16x4 : RISCVBuiltin<"_Vector<2, int>(_Vector<4, short>, _Vector<4, unsigned short>)">; +def pm2add_i32x2 : RISCVBuiltin<"int64_t(_Vector<2, int>, _Vector<2, int>)">; +def pm2add_x_i32x2 : RISCVBuiltin<"int64_t(_Vector<2, int>, _Vector<2, int>)">; +def pm2addu_u32x2 : RISCVBuiltin<"uint64_t(_Vector<2, unsigned int>, _Vector<2, unsigned int>)">; +def pmq2add_i32x2 : RISCVBuiltin<"int64_t(_Vector<2, int>, _Vector<2, int>)">; +def pm2sub_i32x2 : RISCVBuiltin<"int64_t(_Vector<2, int>, _Vector<2, int>)">; +def pm2sub_x_i32x2 : RISCVBuiltin<"int64_t(_Vector<2, int>, _Vector<2, int>)">; +def pm2addsu_i32x2 : RISCVBuiltin<"int64_t(_Vector<2, int>, _Vector<2, unsigned int>)">; +def pmqr2add_i32x2 : RISCVBuiltin<"int64_t(_Vector<2, int>, _Vector<2, int>)">; +def pm4add_i16x4 : RISCVBuiltin<"int64_t(_Vector<4, short>, _Vector<4, short>)">; +def pm4addu_u16x4 : RISCVBuiltin<"uint64_t(_Vector<4, unsigned short>, _Vector<4, unsigned short>)">; +def pm4addsu_i16x4 : RISCVBuiltin<"int64_t(_Vector<4, short>, _Vector<4, unsigned short>)">; + // Packed Absolute Difference Sum (32-bit) def pabdsumu_u8x4_u32 : RISCVBuiltin<"unsigned int(_Vector<4, unsigned char>, _Vector<4, unsigned char>)">; def pabdsumau_u8x4_u32 : RISCVBuiltin<"unsigned int(unsigned int, _Vector<4, unsigned char>, _Vector<4, unsigned char>)">; diff --git a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp index 88fedecbee504..5c5ed9083057f 100644 --- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp @@ -1531,6 +1531,116 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID, break; } + // Packed Multiplication with Horizontal Addition + case RISCV::BI__builtin_riscv_pm4add_i8x4: + case RISCV::BI__builtin_riscv_pm4add_i8x8: + case RISCV::BI__builtin_riscv_pm4add_i16x4: + case RISCV::BI__builtin_riscv_pm2add_i16x2: + case RISCV::BI__builtin_riscv_pm2add_i16x4: + case RISCV::BI__builtin_riscv_pm2add_i32x2: + case RISCV::BI__builtin_riscv_pm2add_x_i16x2: + case RISCV::BI__builtin_riscv_pm2add_x_i16x4: + case RISCV::BI__builtin_riscv_pm2add_x_i32x2: + case RISCV::BI__builtin_riscv_pm4addu_u8x4: + case RISCV::BI__builtin_riscv_pm4addu_u8x8: + case RISCV::BI__builtin_riscv_pm4addu_u16x4: + case RISCV::BI__builtin_riscv_pm2addu_u16x2: + case RISCV::BI__builtin_riscv_pm2addu_u16x4: + case RISCV::BI__builtin_riscv_pm2addu_u32x2: + case RISCV::BI__builtin_riscv_pmq2add_i16x2: + case RISCV::BI__builtin_riscv_pmq2add_i16x4: + case RISCV::BI__builtin_riscv_pmq2add_i32x2: + case RISCV::BI__builtin_riscv_pmqr2add_i16x2: + case RISCV::BI__builtin_riscv_pmqr2add_i16x4: + case RISCV::BI__builtin_riscv_pmqr2add_i32x2: + case RISCV::BI__builtin_riscv_pm2sadd_i16x2: + case RISCV::BI__builtin_riscv_pm2sadd_i16x4: + case RISCV::BI__builtin_riscv_pm2sadd_x_i16x2: + case RISCV::BI__builtin_riscv_pm2sadd_x_i16x4: + case RISCV::BI__builtin_riscv_pm2sub_i16x2: + case RISCV::BI__builtin_riscv_pm2sub_i16x4: + case RISCV::BI__builtin_riscv_pm2sub_i32x2: + case RISCV::BI__builtin_riscv_pm2sub_x_i16x2: + case RISCV::BI__builtin_riscv_pm2sub_x_i16x4: + case RISCV::BI__builtin_riscv_pm2sub_x_i32x2: + case RISCV::BI__builtin_riscv_pm4addsu_i8x4: + case RISCV::BI__builtin_riscv_pm4addsu_i8x8: + case RISCV::BI__builtin_riscv_pm4addsu_i16x4: + case RISCV::BI__builtin_riscv_pm2addsu_i16x2: + case RISCV::BI__builtin_riscv_pm2addsu_i16x4: + case RISCV::BI__builtin_riscv_pm2addsu_i32x2: { + switch (BuiltinID) { + default: + llvm_unreachable("unexpected builtin ID"); + case RISCV::BI__builtin_riscv_pm4add_i8x4: + case RISCV::BI__builtin_riscv_pm4add_i8x8: + case RISCV::BI__builtin_riscv_pm4add_i16x4: + ID = Intrinsic::riscv_pm4add; + break; + case RISCV::BI__builtin_riscv_pm2add_i16x2: + case RISCV::BI__builtin_riscv_pm2add_i16x4: + case RISCV::BI__builtin_riscv_pm2add_i32x2: + ID = Intrinsic::riscv_pm2add; + break; + case RISCV::BI__builtin_riscv_pm2add_x_i16x2: + case RISCV::BI__builtin_riscv_pm2add_x_i16x4: + case RISCV::BI__builtin_riscv_pm2add_x_i32x2: + ID = Intrinsic::riscv_pm2add_x; + break; + case RISCV::BI__builtin_riscv_pm4addu_u8x4: + case RISCV::BI__builtin_riscv_pm4addu_u8x8: + case RISCV::BI__builtin_riscv_pm4addu_u16x4: + ID = Intrinsic::riscv_pm4addu; + break; + case RISCV::BI__builtin_riscv_pm2addu_u16x2: + case RISCV::BI__builtin_riscv_pm2addu_u16x4: + case RISCV::BI__builtin_riscv_pm2addu_u32x2: + ID = Intrinsic::riscv_pm2addu; + break; + case RISCV::BI__builtin_riscv_pmq2add_i16x2: + case RISCV::BI__builtin_riscv_pmq2add_i16x4: + case RISCV::BI__builtin_riscv_pmq2add_i32x2: + ID = Intrinsic::riscv_pmq2add; + break; + case RISCV::BI__builtin_riscv_pmqr2add_i16x2: + case RISCV::BI__builtin_riscv_pmqr2add_i16x4: + case RISCV::BI__builtin_riscv_pmqr2add_i32x2: + ID = Intrinsic::riscv_pmqr2add; + break; + case RISCV::BI__builtin_riscv_pm2sadd_i16x2: + case RISCV::BI__builtin_riscv_pm2sadd_i16x4: + ID = Intrinsic::riscv_pm2sadd; + break; + case RISCV::BI__builtin_riscv_pm2sadd_x_i16x2: + case RISCV::BI__builtin_riscv_pm2sadd_x_i16x4: + ID = Intrinsic::riscv_pm2sadd_x; + break; + case RISCV::BI__builtin_riscv_pm2sub_i16x2: + case RISCV::BI__builtin_riscv_pm2sub_i16x4: + case RISCV::BI__builtin_riscv_pm2sub_i32x2: + ID = Intrinsic::riscv_pm2sub; + break; + case RISCV::BI__builtin_riscv_pm2sub_x_i16x2: + case RISCV::BI__builtin_riscv_pm2sub_x_i16x4: + case RISCV::BI__builtin_riscv_pm2sub_x_i32x2: + ID = Intrinsic::riscv_pm2sub_x; + break; + case RISCV::BI__builtin_riscv_pm4addsu_i8x4: + case RISCV::BI__builtin_riscv_pm4addsu_i8x8: + case RISCV::BI__builtin_riscv_pm4addsu_i16x4: + ID = Intrinsic::riscv_pm4addsu; + break; + case RISCV::BI__builtin_riscv_pm2addsu_i16x2: + case RISCV::BI__builtin_riscv_pm2addsu_i16x4: + case RISCV::BI__builtin_riscv_pm2addsu_i32x2: + ID = Intrinsic::riscv_pm2addsu; + break; + } + + IntrinsicTypes = {ResultType, Ops[0]->getType()}; + break; + } + // Packed Reduction Sum case RISCV::BI__builtin_riscv_predsum_i8x4_i32: case RISCV::BI__builtin_riscv_predsum_i16x2_i32: diff --git a/clang/lib/Headers/riscv_packed_simd.h b/clang/lib/Headers/riscv_packed_simd.h index 318900805043c..92d01e0868c1c 100644 --- a/clang/lib/Headers/riscv_packed_simd.h +++ b/clang/lib/Headers/riscv_packed_simd.h @@ -813,6 +813,47 @@ __packed_ternary_builtin_mixed(pmhaccsu_i32x2, int32x2_t, int32x2_t, uint32x2_t, __packed_ternary_builtin_mixed(pmhraccsu_i16x4, int16x4_t, int16x4_t, uint16x4_t, __builtin_riscv_pmhraccsu_i16x4) __packed_ternary_builtin_mixed(pmhraccsu_i32x2, int32x2_t, int32x2_t, uint32x2_t, __builtin_riscv_pmhraccsu_i32x2) +/* Packed Multiplication with Horizontal Addition (32-bit) */ +__packed_binary_builtin_mixed(pm4add_i8x4, int32_t, int8x4_t, int8x4_t, __builtin_riscv_pm4add_i8x4) +__packed_binary_builtin_mixed(pm2add_i16x2, int32_t, int16x2_t, int16x2_t, __builtin_riscv_pm2add_i16x2) +__packed_binary_builtin_mixed(pm2add_x_i16x2, int32_t, int16x2_t, int16x2_t, __builtin_riscv_pm2add_x_i16x2) +__packed_binary_builtin_mixed(pm4addu_u8x4, uint32_t, uint8x4_t, uint8x4_t, __builtin_riscv_pm4addu_u8x4) +__packed_binary_builtin_mixed(pm2addu_u16x2, uint32_t, uint16x2_t, uint16x2_t, __builtin_riscv_pm2addu_u16x2) +__packed_binary_builtin_mixed(pmq2add_i16x2, int32_t, int16x2_t, int16x2_t, __builtin_riscv_pmq2add_i16x2) +__packed_binary_builtin_mixed(pmqr2add_i16x2, int32_t, int16x2_t, int16x2_t, __builtin_riscv_pmqr2add_i16x2) +__packed_binary_builtin_mixed(pm2sadd_i16x2, int32_t, int16x2_t, int16x2_t, __builtin_riscv_pm2sadd_i16x2) +__packed_binary_builtin_mixed(pm2sadd_x_i16x2, int32_t, int16x2_t, int16x2_t, __builtin_riscv_pm2sadd_x_i16x2) +__packed_binary_builtin_mixed(pm2sub_i16x2, int32_t, int16x2_t, int16x2_t, __builtin_riscv_pm2sub_i16x2) +__packed_binary_builtin_mixed(pm2sub_x_i16x2, int32_t, int16x2_t, int16x2_t, __builtin_riscv_pm2sub_x_i16x2) +__packed_binary_builtin_mixed(pm4addsu_i8x4, int32_t, int8x4_t, uint8x4_t, __builtin_riscv_pm4addsu_i8x4) +__packed_binary_builtin_mixed(pm2addsu_i16x2, int32_t, int16x2_t, uint16x2_t, __builtin_riscv_pm2addsu_i16x2) + +/* Packed Multiplication with Horizontal Addition (64-bit) */ +__packed_binary_builtin_mixed(pm4add_i8x8, int32x2_t, int8x8_t, int8x8_t, __builtin_riscv_pm4add_i8x8) +__packed_binary_builtin_mixed(pm2add_i16x4, int32x2_t, int16x4_t, int16x4_t, __builtin_riscv_pm2add_i16x4) +__packed_binary_builtin_mixed(pm2add_x_i16x4, int32x2_t, int16x4_t, int16x4_t, __builtin_riscv_pm2add_x_i16x4) +__packed_binary_builtin_mixed(pm4addu_u8x8, uint32x2_t, uint8x8_t, uint8x8_t, __builtin_riscv_pm4addu_u8x8) +__packed_binary_builtin_mixed(pm2addu_u16x4, uint32x2_t, uint16x4_t, uint16x4_t, __builtin_riscv_pm2addu_u16x4) +__packed_binary_builtin_mixed(pmq2add_i16x4, int32x2_t, int16x4_t, int16x4_t, __builtin_riscv_pmq2add_i16x4) +__packed_binary_builtin_mixed(pmqr2add_i16x4, int32x2_t, int16x4_t, int16x4_t, __builtin_riscv_pmqr2add_i16x4) +__packed_binary_builtin_mixed(pm2sadd_i16x4, int32x2_t, int16x4_t, int16x4_t, __builtin_riscv_pm2sadd_i16x4) +__packed_binary_builtin_mixed(pm2sadd_x_i16x4, int32x2_t, int16x4_t, int16x4_t, __builtin_riscv_pm2sadd_x_i16x4) +__packed_binary_builtin_mixed(pm2sub_i16x4, int32x2_t, int16x4_t, int16x4_t, __builtin_riscv_pm2sub_i16x4) +__packed_binary_builtin_mixed(pm2sub_x_i16x4, int32x2_t, int16x4_t, int16x4_t, __builtin_riscv_pm2sub_x_i16x4) +__packed_binary_builtin_mixed(pm4addsu_i8x8, int32x2_t, int8x8_t, uint8x8_t, __builtin_riscv_pm4addsu_i8x8) +__packed_binary_builtin_mixed(pm2addsu_i16x4, int32x2_t, int16x4_t, uint16x4_t, __builtin_riscv_pm2addsu_i16x4) +__packed_binary_builtin_mixed(pm2add_i32x2, int64_t, int32x2_t, int32x2_t, __builtin_riscv_pm2add_i32x2) +__packed_binary_builtin_mixed(pm2add_x_i32x2, int64_t, int32x2_t, int32x2_t, __builtin_riscv_pm2add_x_i32x2) +__packed_binary_builtin_mixed(pm2addu_u32x2, uint64_t, uint32x2_t, uint32x2_t, __builtin_riscv_pm2addu_u32x2) +__packed_binary_builtin_mixed(pmq2add_i32x2, int64_t, int32x2_t, int32x2_t, __builtin_riscv_pmq2add_i32x2) +__packed_binary_builtin_mixed(pm2sub_i32x2, int64_t, int32x2_t, int32x2_t, __builtin_riscv_pm2sub_i32x2) +__packed_binary_builtin_mixed(pm2sub_x_i32x2, int64_t, int32x2_t, int32x2_t, __builtin_riscv_pm2sub_x_i32x2) +__packed_binary_builtin_mixed(pm2addsu_i32x2, int64_t, int32x2_t, uint32x2_t, __builtin_riscv_pm2addsu_i32x2) +__packed_binary_builtin_mixed(pmqr2add_i32x2, int64_t, int32x2_t, int32x2_t, __builtin_riscv_pmqr2add_i32x2) +__packed_binary_builtin_mixed(pm4add_i16x4, int64_t, int16x4_t, int16x4_t, __builtin_riscv_pm4add_i16x4) +__packed_binary_builtin_mixed(pm4addu_u16x4, uint64_t, uint16x4_t, uint16x4_t, __builtin_riscv_pm4addu_u16x4) +__packed_binary_builtin_mixed(pm4addsu_i16x4, int64_t, int16x4_t, uint16x4_t, __builtin_riscv_pm4addsu_i16x4) + /* Packed Absolute Difference Sum (32-bit) */ __packed_abdsum(pabdsumu_u8x4_u32, uint32_t, uint8x4_t, __builtin_riscv_pabdsumu_u8x4_u32) __packed_abdsum_acc(pabdsumau_u8x4_u32, uint32_t, uint8x4_t, __builtin_riscv_pabdsumau_u8x4_u32) 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 75dcb796b66cd..7a4d909968b23 100644 --- a/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c +++ b/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c @@ -3406,3 +3406,288 @@ int32x2_t test_pnclipp_i32x2(int64_t a, int64_t b) { uint32x2_t test_pnclipup_u32x2(uint64_t a, uint64_t b) { return __riscv_pnclipup_u32x2(a, b); } + +// CHECK-LABEL: test_pm4add_i8x4: +// RV32: pm4add.b +// RV64: pm4add.b +int32_t test_pm4add_i8x4(int8x4_t rs1, int8x4_t rs2) { + return __riscv_pm4add_i8x4(rs1, rs2); +} + +// CHECK-LABEL: test_pm2add_i16x2: +// RV32: pm2add.h +// RV64: pm2add.h +int32_t test_pm2add_i16x2(int16x2_t rs1, int16x2_t rs2) { + return __riscv_pm2add_i16x2(rs1, rs2); +} + +// CHECK-LABEL: test_pm2add_x_i16x2: +// RV32: pm2add.hx +// RV64: pm2add.hx +int32_t test_pm2add_x_i16x2(int16x2_t rs1, int16x2_t rs2) { + return __riscv_pm2add_x_i16x2(rs1, rs2); +} + +// CHECK-LABEL: test_pm4addu_u8x4: +// RV32: pm4addu.b +// RV64: pm4addu.b +uint32_t test_pm4addu_u8x4(uint8x4_t rs1, uint8x4_t rs2) { + return __riscv_pm4addu_u8x4(rs1, rs2); +} + +// CHECK-LABEL: test_pm2addu_u16x2: +// RV32: pm2addu.h +// RV64: pm2addu.h +uint32_t test_pm2addu_u16x2(uint16x2_t rs1, uint16x2_t rs2) { + return __riscv_pm2addu_u16x2(rs1, rs2); +} + +// CHECK-LABEL: test_pmq2add_i16x2: +// RV32: pmq2add.h +// RV64: pmq2add.h +int32_t test_pmq2add_i16x2(int16x2_t rs1, int16x2_t rs2) { + return __riscv_pmq2add_i16x2(rs1, rs2); +} + +// CHECK-LABEL: test_pmqr2add_i16x2: +// RV32: pmqr2add.h +// RV64: pmqr2add.h +int32_t test_pmqr2add_i16x2(int16x2_t rs1, int16x2_t rs2) { + return __riscv_pmqr2add_i16x2(rs1, rs2); +} + +// CHECK-LABEL: test_pm2sadd_i16x2: +// RV32: pm2sadd.h +// RV64: pm2sadd.h +int32_t test_pm2sadd_i16x2(int16x2_t rs1, int16x2_t rs2) { + return __riscv_pm2sadd_i16x2(rs1, rs2); +} + +// CHECK-LABEL: test_pm2sadd_x_i16x2: +// RV32: pm2sadd.hx +// RV64: pm2sadd.hx +int32_t test_pm2sadd_x_i16x2(int16x2_t rs1, int16x2_t rs2) { + return __riscv_pm2sadd_x_i16x2(rs1, rs2); +} + +// CHECK-LABEL: test_pm2sub_i16x2: +// RV32: pm2sub.h +// RV64: pm2sub.h +int32_t test_pm2sub_i16x2(int16x2_t rs1, int16x2_t rs2) { + return __riscv_pm2sub_i16x2(rs1, rs2); +} + +// CHECK-LABEL: test_pm2sub_x_i16x2: +// RV32: pm2sub.hx +// RV64: pm2sub.hx +int32_t test_pm2sub_x_i16x2(int16x2_t rs1, int16x2_t rs2) { + return __riscv_pm2sub_x_i16x2(rs1, rs2); +} + +// CHECK-LABEL: test_pm4addsu_i8x4: +// RV32: pm4addsu.b +// RV64: pm4addsu.b +int32_t test_pm4addsu_i8x4(int8x4_t rs1, uint8x4_t rs2) { + return __riscv_pm4addsu_i8x4(rs1, rs2); +} + +// CHECK-LABEL: test_pm2addsu_i16x2: +// RV32: pm2addsu.h +// RV64: pm2addsu.h +int32_t test_pm2addsu_i16x2(int16x2_t rs1, uint16x2_t rs2) { + return __riscv_pm2addsu_i16x2(rs1, rs2); +} + +// CHECK-LABEL: test_pm4add_i8x8: +// RV32: pm4add.b +// RV32: pm4add.b +// RV64: pm4add.b +int32x2_t test_pm4add_i8x8(int8x8_t rs1, int8x8_t rs2) { + return __riscv_pm4add_i8x8(rs1, rs2); +} + +// CHECK-LABEL: test_pm2add_i16x4: +// RV32: pm2add.h +// RV32: pm2add.h +// RV64: pm2add.h +int32x2_t test_pm2add_i16x4(int16x4_t rs1, int16x4_t rs2) { + return __riscv_pm2add_i16x4(rs1, rs2); +} + +// CHECK-LABEL: test_pm2add_x_i16x4: +// RV32: pm2add.hx +// RV32: pm2add.hx +// RV64: pm2add.hx +int32x2_t test_pm2add_x_i16x4(int16x4_t rs1, int16x4_t rs2) { + return __riscv_pm2add_x_i16x4(rs1, rs2); +} + +// CHECK-LABEL: test_pm4addu_u8x8: +// RV32: pm4addu.b +// RV32: pm4addu.b +// RV64: pm4addu.b +uint32x2_t test_pm4addu_u8x8(uint8x8_t rs1, uint8x8_t rs2) { + return __riscv_pm4addu_u8x8(rs1, rs2); +} + +// CHECK-LABEL: test_pm2addu_u16x4: +// RV32: pm2addu.h +// RV32: pm2addu.h +// RV64: pm2addu.h +uint32x2_t test_pm2addu_u16x4(uint16x4_t rs1, uint16x4_t rs2) { + return __riscv_pm2addu_u16x4(rs1, rs2); +} + +// CHECK-LABEL: test_pmq2add_i16x4: +// RV32: pmq2add.h +// RV32: pmq2add.h +// RV64: pmq2add.h +int32x2_t test_pmq2add_i16x4(int16x4_t rs1, int16x4_t rs2) { + return __riscv_pmq2add_i16x4(rs1, rs2); +} + +// CHECK-LABEL: test_pmqr2add_i16x4: +// RV32: pmqr2add.h +// RV32: pmqr2add.h +// RV64: pmqr2add.h +int32x2_t test_pmqr2add_i16x4(int16x4_t rs1, int16x4_t rs2) { + return __riscv_pmqr2add_i16x4(rs1, rs2); +} + +// CHECK-LABEL: test_pm2sadd_i16x4: +// RV32: pm2sadd.h +// RV32: pm2sadd.h +// RV64: pm2sadd.h +int32x2_t test_pm2sadd_i16x4(int16x4_t rs1, int16x4_t rs2) { + return __riscv_pm2sadd_i16x4(rs1, rs2); +} + +// CHECK-LABEL: test_pm2sadd_x_i16x4: +// RV32: pm2sadd.hx +// RV32: pm2sadd.hx +// RV64: pm2sadd.hx +int32x2_t test_pm2sadd_x_i16x4(int16x4_t rs1, int16x4_t rs2) { + return __riscv_pm2sadd_x_i16x4(rs1, rs2); +} + +// CHECK-LABEL: test_pm2sub_i16x4: +// RV32: pm2sub.h +// RV32: pm2sub.h +// RV64: pm2sub.h +int32x2_t test_pm2sub_i16x4(int16x4_t rs1, int16x4_t rs2) { + return __riscv_pm2sub_i16x4(rs1, rs2); +} + +// CHECK-LABEL: test_pm2sub_x_i16x4: +// RV32: pm2sub.hx +// RV32: pm2sub.hx +// RV64: pm2sub.hx +int32x2_t test_pm2sub_x_i16x4(int16x4_t rs1, int16x4_t rs2) { + return __riscv_pm2sub_x_i16x4(rs1, rs2); +} + +// CHECK-LABEL: test_pm4addsu_i8x8: +// RV32: pm4addsu.b +// RV32: pm4addsu.b +// RV64: pm4addsu.b +int32x2_t test_pm4addsu_i8x8(int8x8_t rs1, uint8x8_t rs2) { + return __riscv_pm4addsu_i8x8(rs1, rs2); +} + +// CHECK-LABEL: test_pm2addsu_i16x4: +// RV32: pm2addsu.h +// RV32: pm2addsu.h +// RV64: pm2addsu.h +int32x2_t test_pm2addsu_i16x4(int16x4_t rs1, uint16x4_t rs2) { + return __riscv_pm2addsu_i16x4(rs1, rs2); +} + +// CHECK-LABEL: test_pm2add_i32x2: +// RV32: wmul +// RV32: wmacc +// RV64: pm2add.w +int64_t test_pm2add_i32x2(int32x2_t rs1, int32x2_t rs2) { + return __riscv_pm2add_i32x2(rs1, rs2); +} + +// CHECK-LABEL: test_pm2add_x_i32x2: +// RV32: wmul +// RV32: wmacc +// RV64: pm2add.wx +int64_t test_pm2add_x_i32x2(int32x2_t rs1, int32x2_t rs2) { + return __riscv_pm2add_x_i32x2(rs1, rs2); +} + +// CHECK-LABEL: test_pm2addu_u32x2: +// RV32: wmulu +// RV32: wmaccu +// RV64: pm2addu.w +uint64_t test_pm2addu_u32x2(uint32x2_t rs1, uint32x2_t rs2) { + return __riscv_pm2addu_u32x2(rs1, rs2); +} + +// CHECK-LABEL: test_pmq2add_i32x2: +// RV32: mqwacc +// RV32: mqwacc +// RV64: pmq2add.w +int64_t test_pmq2add_i32x2(int32x2_t rs1, int32x2_t rs2) { + return __riscv_pmq2add_i32x2(rs1, rs2); +} + +// CHECK-LABEL: test_pmqr2add_i32x2: +// RV32: mqrwacc +// RV32: mqrwacc +// RV64: pmqr2add.w +int64_t test_pmqr2add_i32x2(int32x2_t rs1, int32x2_t rs2) { + return __riscv_pmqr2add_i32x2(rs1, rs2); +} + +// CHECK-LABEL: test_pm2sub_i32x2: +// RV32: wmul +// RV32: wmul +// RV32: subd +// RV64: pm2sub.w +int64_t test_pm2sub_i32x2(int32x2_t rs1, int32x2_t rs2) { + return __riscv_pm2sub_i32x2(rs1, rs2); +} + +// CHECK-LABEL: test_pm2sub_x_i32x2: +// RV32: wmul +// RV32: wmul +// RV32: subd +// RV64: pm2sub.wx +int64_t test_pm2sub_x_i32x2(int32x2_t rs1, int32x2_t rs2) { + return __riscv_pm2sub_x_i32x2(rs1, rs2); +} + +// CHECK-LABEL: test_pm2addsu_i32x2: +// RV32: wmulsu +// RV32: wmaccsu +// RV64: pm2addsu.w +int64_t test_pm2addsu_i32x2(int32x2_t rs1, uint32x2_t rs2) { + return __riscv_pm2addsu_i32x2(rs1, rs2); +} + +// CHECK-LABEL: test_pm4add_i16x4: +// RV32: pm2wadd.h +// RV32: pm2wadda.h +// RV64: pm4add.h +int64_t test_pm4add_i16x4(int16x4_t rs1, int16x4_t rs2) { + return __riscv_pm4add_i16x4(rs1, rs2); +} + +// CHECK-LABEL: test_pm4addu_u16x4: +// RV32: pm2waddu.h +// RV32: pm2waddau.h +// RV64: pm4addu.h +uint64_t test_pm4addu_u16x4(uint16x4_t rs1, uint16x4_t rs2) { + return __riscv_pm4addu_u16x4(rs1, rs2); +} + +// CHECK-LABEL: test_pm4addsu_i16x4: +// RV32: pm2waddsu.h +// RV32: pm2waddasu.h +// RV64: pm4addsu.h +int64_t test_pm4addsu_i16x4(int16x4_t rs1, uint16x4_t rs2) { + return __riscv_pm4addsu_i16x4(rs1, rs2); +} diff --git a/llvm/include/llvm/IR/IntrinsicsRISCV.td b/llvm/include/llvm/IR/IntrinsicsRISCV.td index 8fa0ee78ca2a5..68fc04ed60176 100644 --- a/llvm/include/llvm/IR/IntrinsicsRISCV.td +++ b/llvm/include/llvm/IR/IntrinsicsRISCV.td @@ -2125,6 +2125,25 @@ class RVPBinaryIntrinsic def int_riscv_pmhaccsu : RVPTernaryIntrinsic; def int_riscv_pmhraccsu : RVPTernaryIntrinsic; + // Packed Multiplication with Horizontal Addition. + class RVPHorizontalMulIntrinsic + : DefaultAttrsIntrinsic<[llvm_any_ty], + [llvm_anyvector_ty, LLVMMatchType<1>], + [IntrNoMem, IntrSpeculatable]>; + def int_riscv_pm4add : RVPHorizontalMulIntrinsic; + def int_riscv_pm2add : RVPHorizontalMulIntrinsic; + def int_riscv_pm2add_x : RVPHorizontalMulIntrinsic; + def int_riscv_pm4addu : RVPHorizontalMulIntrinsic; + def int_riscv_pm2addu : RVPHorizontalMulIntrinsic; + def int_riscv_pmq2add : RVPHorizontalMulIntrinsic; + def int_riscv_pmqr2add : RVPHorizontalMulIntrinsic; + def int_riscv_pm2sadd : RVPHorizontalMulIntrinsic; + def int_riscv_pm2sadd_x : RVPHorizontalMulIntrinsic; + def int_riscv_pm2sub : RVPHorizontalMulIntrinsic; + def int_riscv_pm2sub_x : RVPHorizontalMulIntrinsic; + def int_riscv_pm4addsu : RVPHorizontalMulIntrinsic; + def int_riscv_pm2addsu : RVPHorizontalMulIntrinsic; + // Packed Absolute Difference Sum. def int_riscv_pabdsumu : DefaultAttrsIntrinsic<[llvm_anyint_ty], diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 194aad22775cf..8f80fbfa5c338 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -12254,6 +12254,40 @@ static unsigned getRVPMulHighAccumulateOpcode(unsigned IntNo) { } } +static unsigned getRVPHorizontalMulOpcode(unsigned IntNo) { + switch (IntNo) { + default: + llvm_unreachable( + "Unexpected RISC-V packed horizontal multiply intrinsic"); + case Intrinsic::riscv_pm4add: + return RISCVISD::PM4ADD; + case Intrinsic::riscv_pm2add: + return RISCVISD::PM2ADD; + case Intrinsic::riscv_pm2add_x: + return RISCVISD::PM2ADD_X; + case Intrinsic::riscv_pm4addu: + return RISCVISD::PM4ADDU; + case Intrinsic::riscv_pm2addu: + return RISCVISD::PM2ADDU; + case Intrinsic::riscv_pmq2add: + return RISCVISD::PMQ2ADD; + case Intrinsic::riscv_pmqr2add: + return RISCVISD::PMQR2ADD; + case Intrinsic::riscv_pm2sadd: + return RISCVISD::PM2SADD; + case Intrinsic::riscv_pm2sadd_x: + return RISCVISD::PM2SADD_X; + case Intrinsic::riscv_pm2sub: + return RISCVISD::PM2SUB; + case Intrinsic::riscv_pm2sub_x: + return RISCVISD::PM2SUB_X; + case Intrinsic::riscv_pm4addsu: + return RISCVISD::PM4ADDSU; + case Intrinsic::riscv_pm2addsu: + return RISCVISD::PM2ADDSU; + } +} + SDValue RISCVTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const { unsigned IntNo = Op.getConstantOperandVal(0); @@ -12643,6 +12677,36 @@ SDValue RISCVTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, return DAG.getNode(MulOpc, DL, VT, Rd, Rs1, Rs2); } + case Intrinsic::riscv_pm4add: + case Intrinsic::riscv_pm2add: + case Intrinsic::riscv_pm2add_x: + case Intrinsic::riscv_pm4addu: + case Intrinsic::riscv_pm2addu: + case Intrinsic::riscv_pmq2add: + case Intrinsic::riscv_pmqr2add: + case Intrinsic::riscv_pm2sadd: + case Intrinsic::riscv_pm2sadd_x: + case Intrinsic::riscv_pm2sub: + case Intrinsic::riscv_pm2sub_x: + case Intrinsic::riscv_pm4addsu: + case Intrinsic::riscv_pm2addsu: { + EVT VT = Op.getValueType(); + unsigned Opc = getRVPHorizontalMulOpcode(IntNo); + SDValue Rs1 = Op.getOperand(1); + SDValue Rs2 = Op.getOperand(2); + + // RV32 applies the 32-bit instruction independently to both halves of a + // 64-bit packed input. + if (!Subtarget.is64Bit() && VT == MVT::v2i32) { + auto [Rs1Lo, Rs1Hi] = DAG.SplitVector(Rs1, DL); + auto [Rs2Lo, Rs2Hi] = DAG.SplitVector(Rs2, DL); + SDValue Lo = DAG.getNode(Opc, DL, MVT::i32, Rs1Lo, Rs2Lo); + SDValue Hi = DAG.getNode(Opc, DL, MVT::i32, Rs1Hi, Rs2Hi); + return DAG.getNode(ISD::BUILD_VECTOR, DL, VT, Lo, Hi); + } + + return DAG.getNode(Opc, DL, VT, Rs1, Rs2); + } case Intrinsic::riscv_pmerge: { EVT VT = Op.getValueType(); auto buildMerge = [&](SDValue Rs1, SDValue Rs2, SDValue Mask, @@ -16734,6 +16798,42 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N, Results.push_back(DAG.getExtractSubvector(DL, VT, Res, 0)); return; } + case Intrinsic::riscv_pm4add: + case Intrinsic::riscv_pm2add: + case Intrinsic::riscv_pm2add_x: + case Intrinsic::riscv_pm4addu: + case Intrinsic::riscv_pm2addu: + case Intrinsic::riscv_pmq2add: + case Intrinsic::riscv_pmqr2add: + case Intrinsic::riscv_pm2sadd: + case Intrinsic::riscv_pm2sadd_x: + case Intrinsic::riscv_pm2sub: + case Intrinsic::riscv_pm2sub_x: + case Intrinsic::riscv_pm4addsu: + case Intrinsic::riscv_pm2addsu: { + MVT VT = N->getSimpleValueType(0); + unsigned Opc = getRVPHorizontalMulOpcode(IntNo); + SDValue Rs1 = N->getOperand(1); + SDValue Rs2 = N->getOperand(2); + + if (!Subtarget.is64Bit() && VT == MVT::i64) { + SDValue Pair = DAG.getNode(Opc, DL, MVT::v2i32, Rs1, Rs2); + Results.push_back(DAG.getBitcast(MVT::i64, Pair)); + return; + } + + assert(Subtarget.is64Bit() && VT == MVT::i32 && + "Unexpected horizontal multiply legalization"); + MVT SrcVT = Rs1.getSimpleValueType(); + MVT WideSrcVT = SrcVT == MVT::v4i8 ? MVT::v8i8 : MVT::v4i16; + Rs1 = DAG.getNode(ISD::CONCAT_VECTORS, DL, WideSrcVT, Rs1, + DAG.getUNDEF(SrcVT)); + Rs2 = DAG.getNode(ISD::CONCAT_VECTORS, DL, WideSrcVT, Rs2, + DAG.getUNDEF(SrcVT)); + SDValue Wide = DAG.getNode(Opc, DL, MVT::v2i32, Rs1, Rs2); + Results.push_back(DAG.getExtractVectorElt(DL, MVT::i32, Wide, 0)); + return; + } case Intrinsic::riscv_paadd: case Intrinsic::riscv_paaddu: case Intrinsic::riscv_pasub: diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td index 9b72141ef9bcd..ee7b78fcfa9cc 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td @@ -1923,6 +1923,23 @@ def riscv_mhraccu : RVSDNode<"MHRACCU", SDT_RISCVSameTernary>; def riscv_mhaccsu : RVSDNode<"MHACCSU", SDT_RISCVSameTernary>; def riscv_mhraccsu : RVSDNode<"MHRACCSU", SDT_RISCVSameTernary>; +// Multiply packed elements and horizontally combine each adjacent group. +def SDT_RISCVHorizontalMul + : SDTypeProfile<1, 2, [SDTCisVec<1>, SDTCisSameAs<1, 2>]>; +def riscv_pm4add : RVSDNode<"PM4ADD", SDT_RISCVHorizontalMul>; +def riscv_pm2add : RVSDNode<"PM2ADD", SDT_RISCVHorizontalMul>; +def riscv_pm2add_x : RVSDNode<"PM2ADD_X", SDT_RISCVHorizontalMul>; +def riscv_pm4addu : RVSDNode<"PM4ADDU", SDT_RISCVHorizontalMul>; +def riscv_pm2addu : RVSDNode<"PM2ADDU", SDT_RISCVHorizontalMul>; +def riscv_pmq2add : RVSDNode<"PMQ2ADD", SDT_RISCVHorizontalMul>; +def riscv_pmqr2add : RVSDNode<"PMQR2ADD", SDT_RISCVHorizontalMul>; +def riscv_pm2sadd : RVSDNode<"PM2SADD", SDT_RISCVHorizontalMul>; +def riscv_pm2sadd_x : RVSDNode<"PM2SADD_X", SDT_RISCVHorizontalMul>; +def riscv_pm2sub : RVSDNode<"PM2SUB", SDT_RISCVHorizontalMul>; +def riscv_pm2sub_x : RVSDNode<"PM2SUB_X", SDT_RISCVHorizontalMul>; +def riscv_pm4addsu : RVSDNode<"PM4ADDSU", SDT_RISCVHorizontalMul>; +def riscv_pm2addsu : RVSDNode<"PM2ADDSU", SDT_RISCVHorizontalMul>; + // "Q-format" multiplication def riscv_mulq : RVSDNode<"MULQ", SDTIntBinOp, [SDNPCommutative]>; def riscv_mulqr : RVSDNode<"MULQR", SDTIntBinOp, [SDNPCommutative]>; @@ -2023,6 +2040,11 @@ def RISCVBuildPairGPRVec : RVSDNode<"BuildPairGPRVec", SDT_RISCVBuildPairGPRVec>; def RISCVSplitGPRVec : RVSDNode<"SplitGPRVec", SDT_RISCVSplitGPRVec>; +class PatHorizontalMul<SDPatternOperator OpNode, RVInst Inst, + ValueType ResultVT, ValueType SrcVT> + : Pat<(ResultVT (OpNode (SrcVT GPR:$rs1), (SrcVT GPR:$rs2))), + (Inst GPR:$rs1, GPR:$rs2)>; + // (rs1 << 1) + rs2 class PatPSh1Add<RVInst Inst, ValueType vt> : Pat<(vt (add (riscv_pshl (vt GPR:$rs1), (XLenVT 1)), (vt GPR:$rs2))), @@ -2300,6 +2322,97 @@ let append Predicates = [IsRV32] in { def : PatGprGpr<riscv_mulq, MULQ, i32>; def : PatGprGpr<riscv_mulqr, MULQR, i32>; + // Packed multiplication with horizontal addition patterns. + def : PatHorizontalMul<riscv_pm4add, PM4ADD_B, i32, v4i8>; + def : PatHorizontalMul<riscv_pm2add, PM2ADD_H, i32, v2i16>; + def : PatHorizontalMul<riscv_pm2add_x, PM2ADD_HX, i32, v2i16>; + def : PatHorizontalMul<riscv_pm4addu, PM4ADDU_B, i32, v4i8>; + def : PatHorizontalMul<riscv_pm2addu, PM2ADDU_H, i32, v2i16>; + def : PatHorizontalMul<riscv_pmq2add, PMQ2ADD_H, i32, v2i16>; + def : PatHorizontalMul<riscv_pmqr2add, PMQR2ADD_H, i32, v2i16>; + def : PatHorizontalMul<riscv_pm2sadd, PM2SADD_H, i32, v2i16>; + def : PatHorizontalMul<riscv_pm2sadd_x, PM2SADD_HX, i32, v2i16>; + def : PatHorizontalMul<riscv_pm2sub, PM2SUB_H, i32, v2i16>; + def : PatHorizontalMul<riscv_pm2sub_x, PM2SUB_HX, i32, v2i16>; + def : PatHorizontalMul<riscv_pm4addsu, PM4ADDSU_B, i32, v4i8>; + def : PatHorizontalMul<riscv_pm2addsu, PM2ADDSU_H, i32, v2i16>; + + // Select the RV32 v2i32 result produced by type legalization into the + // instruction sequences specified for the 64-bit intrinsics. + def : Pat<(v2i32 (riscv_pm2add (v2i32 GPRPair:$rs1), + (v2i32 GPRPair:$rs2))), + (WMACC (WMUL (EXTRACT_SUBREG GPRPair:$rs1, sub_gpr_even), + (EXTRACT_SUBREG GPRPair:$rs2, sub_gpr_even)), + (EXTRACT_SUBREG GPRPair:$rs1, sub_gpr_odd), + (EXTRACT_SUBREG GPRPair:$rs2, sub_gpr_odd))>; + def : Pat<(v2i32 (riscv_pm2add_x (v2i32 GPRPair:$rs1), + (v2i32 GPRPair:$rs2))), + (WMACC (WMUL (EXTRACT_SUBREG GPRPair:$rs1, sub_gpr_even), + (EXTRACT_SUBREG GPRPair:$rs2, sub_gpr_odd)), + (EXTRACT_SUBREG GPRPair:$rs1, sub_gpr_odd), + (EXTRACT_SUBREG GPRPair:$rs2, sub_gpr_even))>; + def : Pat<(v2i32 (riscv_pm2addu (v2i32 GPRPair:$rs1), + (v2i32 GPRPair:$rs2))), + (WMACCU (WMULU (EXTRACT_SUBREG GPRPair:$rs1, sub_gpr_even), + (EXTRACT_SUBREG GPRPair:$rs2, sub_gpr_even)), + (EXTRACT_SUBREG GPRPair:$rs1, sub_gpr_odd), + (EXTRACT_SUBREG GPRPair:$rs2, sub_gpr_odd))>; + def : Pat<(v2i32 (riscv_pmq2add (v2i32 GPRPair:$rs1), + (v2i32 GPRPair:$rs2))), + (MQWACC (v2i32 (MQWACC + (v2i32 (BuildGPRPair (i32 X0), (i32 X0))), + (EXTRACT_SUBREG GPRPair:$rs1, sub_gpr_even), + (EXTRACT_SUBREG GPRPair:$rs2, sub_gpr_even))), + (EXTRACT_SUBREG GPRPair:$rs1, sub_gpr_odd), + (EXTRACT_SUBREG GPRPair:$rs2, sub_gpr_odd))>; + def : Pat<(v2i32 (riscv_pmqr2add (v2i32 GPRPair:$rs1), + (v2i32 GPRPair:$rs2))), + (MQRWACC (v2i32 (MQRWACC + (v2i32 (BuildGPRPair (i32 X0), (i32 X0))), + (EXTRACT_SUBREG GPRPair:$rs1, sub_gpr_even), + (EXTRACT_SUBREG GPRPair:$rs2, sub_gpr_even))), + (EXTRACT_SUBREG GPRPair:$rs1, sub_gpr_odd), + (EXTRACT_SUBREG GPRPair:$rs2, sub_gpr_odd))>; + def : Pat<(v2i32 (riscv_pm2sub (v2i32 GPRPair:$rs1), + (v2i32 GPRPair:$rs2))), + (SUBD (WMUL (EXTRACT_SUBREG GPRPair:$rs1, sub_gpr_even), + (EXTRACT_SUBREG GPRPair:$rs2, sub_gpr_even)), + (WMUL (EXTRACT_SUBREG GPRPair:$rs1, sub_gpr_odd), + (EXTRACT_SUBREG GPRPair:$rs2, sub_gpr_odd)))>; + def : Pat<(v2i32 (riscv_pm2sub_x (v2i32 GPRPair:$rs1), + (v2i32 GPRPair:$rs2))), + (SUBD (WMUL (EXTRACT_SUBREG GPRPair:$rs1, sub_gpr_even), + (EXTRACT_SUBREG GPRPair:$rs2, sub_gpr_odd)), + (WMUL (EXTRACT_SUBREG GPRPair:$rs1, sub_gpr_odd), + (EXTRACT_SUBREG GPRPair:$rs2, sub_gpr_even)))>; + def : Pat<(v2i32 (riscv_pm2addsu (v2i32 GPRPair:$rs1), + (v2i32 GPRPair:$rs2))), + (WMACCSU (WMULSU (EXTRACT_SUBREG GPRPair:$rs1, sub_gpr_even), + (EXTRACT_SUBREG GPRPair:$rs2, sub_gpr_even)), + (EXTRACT_SUBREG GPRPair:$rs1, sub_gpr_odd), + (EXTRACT_SUBREG GPRPair:$rs2, sub_gpr_odd))>; + def : Pat<(v2i32 (riscv_pm4add (v4i16 GPRPair:$rs1), + (v4i16 GPRPair:$rs2))), + (PM2WADDA_H + (PM2WADD_H (EXTRACT_SUBREG GPRPair:$rs1, sub_gpr_even), + (EXTRACT_SUBREG GPRPair:$rs2, sub_gpr_even)), + (EXTRACT_SUBREG GPRPair:$rs1, sub_gpr_odd), + (EXTRACT_SUBREG GPRPair:$rs2, sub_gpr_odd))>; + def : Pat<(v2i32 (riscv_pm4addu (v4i16 GPRPair:$rs1), + (v4i16 GPRPair:$rs2))), + (PM2WADDAU_H + (PM2WADDU_H (EXTRACT_SUBREG GPRPair:$rs1, sub_gpr_even), + (EXTRACT_SUBREG GPRPair:$rs2, sub_gpr_even)), + (EXTRACT_SUBREG GPRPair:$rs1, sub_gpr_odd), + (EXTRACT_SUBREG GPRPair:$rs2, sub_gpr_odd))>; + def : Pat<(v2i32 (riscv_pm4addsu (v4i16 GPRPair:$rs1), + (v4i16 GPRPair:$rs2))), + (PM2WADDASU_H + (PM2WADDSU_H (EXTRACT_SUBREG GPRPair:$rs1, sub_gpr_even), + (EXTRACT_SUBREG GPRPair:$rs2, sub_gpr_even)), + (EXTRACT_SUBREG GPRPair:$rs1, sub_gpr_odd), + (EXTRACT_SUBREG GPRPair:$rs2, sub_gpr_odd))>; + // Halfword multiply patterns where one operand is a sext.h or zext.h and // the other is a sext.h or zext.h or is known to be sign/zero-extended. We // prefer plain mul when both operands are known to be sign/zero-extended. @@ -2849,6 +2962,33 @@ let append Predicates = [IsRV64] in { def : PatGprGpr<riscv_mulq, PMULQ_W, v2i32>; def : PatGprGpr<riscv_mulqr, PMULQR_W, v2i32>; + // Packed multiplication with horizontal addition patterns. + def : PatHorizontalMul<riscv_pm4add, PM4ADD_B, v2i32, v8i8>; + def : PatHorizontalMul<riscv_pm2add, PM2ADD_H, v2i32, v4i16>; + def : PatHorizontalMul<riscv_pm2add_x, PM2ADD_HX, v2i32, v4i16>; + def : PatHorizontalMul<riscv_pm4addu, PM4ADDU_B, v2i32, v8i8>; + def : PatHorizontalMul<riscv_pm2addu, PM2ADDU_H, v2i32, v4i16>; + def : PatHorizontalMul<riscv_pmq2add, PMQ2ADD_H, v2i32, v4i16>; + def : PatHorizontalMul<riscv_pmqr2add, PMQR2ADD_H, v2i32, v4i16>; + def : PatHorizontalMul<riscv_pm2sadd, PM2SADD_H, v2i32, v4i16>; + def : PatHorizontalMul<riscv_pm2sadd_x, PM2SADD_HX, v2i32, v4i16>; + def : PatHorizontalMul<riscv_pm2sub, PM2SUB_H, v2i32, v4i16>; + def : PatHorizontalMul<riscv_pm2sub_x, PM2SUB_HX, v2i32, v4i16>; + def : PatHorizontalMul<riscv_pm4addsu, PM4ADDSU_B, v2i32, v8i8>; + def : PatHorizontalMul<riscv_pm2addsu, PM2ADDSU_H, v2i32, v4i16>; + + def : PatHorizontalMul<riscv_pm2add, PM2ADD_W, i64, v2i32>; + def : PatHorizontalMul<riscv_pm2add_x, PM2ADD_WX, i64, v2i32>; + def : PatHorizontalMul<riscv_pm2addu, PM2ADDU_W, i64, v2i32>; + def : PatHorizontalMul<riscv_pmq2add, PMQ2ADD_W, i64, v2i32>; + def : PatHorizontalMul<riscv_pmqr2add, PMQR2ADD_W, i64, v2i32>; + def : PatHorizontalMul<riscv_pm2sub, PM2SUB_W, i64, v2i32>; + def : PatHorizontalMul<riscv_pm2sub_x, PM2SUB_WX, i64, v2i32>; + def : PatHorizontalMul<riscv_pm2addsu, PM2ADDSU_W, i64, v2i32>; + def : PatHorizontalMul<riscv_pm4add, PM4ADD_H, i64, v4i16>; + def : PatHorizontalMul<riscv_pm4addu, PM4ADDU_H, i64, v4i16>; + def : PatHorizontalMul<riscv_pm4addsu, PM4ADDSU_H, i64, v4i16>; + // 8/16/32-bit multiply low patterns // FIXME custom lower def : Pat<(v8i8 (mul GPR:$rs1, GPR:$rs2)), diff --git a/llvm/test/CodeGen/RISCV/rvp-simd-32.ll b/llvm/test/CodeGen/RISCV/rvp-simd-32.ll index d38012912872d..103d91eba595f 100644 --- a/llvm/test/CodeGen/RISCV/rvp-simd-32.ll +++ b/llvm/test/CodeGen/RISCV/rvp-simd-32.ll @@ -3156,3 +3156,120 @@ define <2 x i16> @test_pnclipup_v2i16(i32 %a, i32 %b) { %r = call <2 x i16> @llvm.riscv.pnclipup.v2i16.i32(i32 %a, i32 %b) ret <2 x i16> %r } + +define i32 @test_pm4add_v4i8_i32(<4 x i8> %a, <4 x i8> %b) { +; CHECK-LABEL: test_pm4add_v4i8_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: pm4add.b a0, a0, a1 +; CHECK-NEXT: ret + %r = call i32 @llvm.riscv.pm4add.i32.v4i8(<4 x i8> %a, <4 x i8> %b) + ret i32 %r +} + +define i32 @test_pm2add_v2i16_i32(<2 x i16> %a, <2 x i16> %b) { +; CHECK-LABEL: test_pm2add_v2i16_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: pm2add.h a0, a0, a1 +; CHECK-NEXT: ret + %r = call i32 @llvm.riscv.pm2add.i32.v2i16(<2 x i16> %a, <2 x i16> %b) + ret i32 %r +} + +define i32 @test_pm2add_x_v2i16_i32(<2 x i16> %a, <2 x i16> %b) { +; CHECK-LABEL: test_pm2add_x_v2i16_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: pm2add.hx a0, a0, a1 +; CHECK-NEXT: ret + %r = call i32 @llvm.riscv.pm2add.x.i32.v2i16(<2 x i16> %a, <2 x i16> %b) + ret i32 %r +} + +define i32 @test_pm4addu_v4i8_i32(<4 x i8> %a, <4 x i8> %b) { +; CHECK-LABEL: test_pm4addu_v4i8_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: pm4addu.b a0, a0, a1 +; CHECK-NEXT: ret + %r = call i32 @llvm.riscv.pm4addu.i32.v4i8(<4 x i8> %a, <4 x i8> %b) + ret i32 %r +} + +define i32 @test_pm2addu_v2i16_i32(<2 x i16> %a, <2 x i16> %b) { +; CHECK-LABEL: test_pm2addu_v2i16_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: pm2addu.h a0, a0, a1 +; CHECK-NEXT: ret + %r = call i32 @llvm.riscv.pm2addu.i32.v2i16(<2 x i16> %a, <2 x i16> %b) + ret i32 %r +} + +define i32 @test_pmq2add_v2i16_i32(<2 x i16> %a, <2 x i16> %b) { +; CHECK-LABEL: test_pmq2add_v2i16_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: pmq2add.h a0, a0, a1 +; CHECK-NEXT: ret + %r = call i32 @llvm.riscv.pmq2add.i32.v2i16(<2 x i16> %a, <2 x i16> %b) + ret i32 %r +} + +define i32 @test_pmqr2add_v2i16_i32(<2 x i16> %a, <2 x i16> %b) { +; CHECK-LABEL: test_pmqr2add_v2i16_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: pmqr2add.h a0, a0, a1 +; CHECK-NEXT: ret + %r = call i32 @llvm.riscv.pmqr2add.i32.v2i16(<2 x i16> %a, <2 x i16> %b) + ret i32 %r +} + +define i32 @test_pm2sadd_v2i16_i32(<2 x i16> %a, <2 x i16> %b) { +; CHECK-LABEL: test_pm2sadd_v2i16_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: pm2sadd.h a0, a0, a1 +; CHECK-NEXT: ret + %r = call i32 @llvm.riscv.pm2sadd.i32.v2i16(<2 x i16> %a, <2 x i16> %b) + ret i32 %r +} + +define i32 @test_pm2sadd_x_v2i16_i32(<2 x i16> %a, <2 x i16> %b) { +; CHECK-LABEL: test_pm2sadd_x_v2i16_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: pm2sadd.hx a0, a0, a1 +; CHECK-NEXT: ret + %r = call i32 @llvm.riscv.pm2sadd.x.i32.v2i16(<2 x i16> %a, <2 x i16> %b) + ret i32 %r +} + +define i32 @test_pm2sub_v2i16_i32(<2 x i16> %a, <2 x i16> %b) { +; CHECK-LABEL: test_pm2sub_v2i16_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: pm2sub.h a0, a0, a1 +; CHECK-NEXT: ret + %r = call i32 @llvm.riscv.pm2sub.i32.v2i16(<2 x i16> %a, <2 x i16> %b) + ret i32 %r +} + +define i32 @test_pm2sub_x_v2i16_i32(<2 x i16> %a, <2 x i16> %b) { +; CHECK-LABEL: test_pm2sub_x_v2i16_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: pm2sub.hx a0, a0, a1 +; CHECK-NEXT: ret + %r = call i32 @llvm.riscv.pm2sub.x.i32.v2i16(<2 x i16> %a, <2 x i16> %b) + ret i32 %r +} + +define i32 @test_pm4addsu_v4i8_i32(<4 x i8> %a, <4 x i8> %b) { +; CHECK-LABEL: test_pm4addsu_v4i8_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: pm4addsu.b a0, a0, a1 +; CHECK-NEXT: ret + %r = call i32 @llvm.riscv.pm4addsu.i32.v4i8(<4 x i8> %a, <4 x i8> %b) + ret i32 %r +} + +define i32 @test_pm2addsu_v2i16_i32(<2 x i16> %a, <2 x i16> %b) { +; CHECK-LABEL: test_pm2addsu_v2i16_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: pm2addsu.h a0, a0, a1 +; CHECK-NEXT: ret + %r = call i32 @llvm.riscv.pm2addsu.i32.v2i16(<2 x i16> %a, <2 x i16> %b) + ret i32 %r +} diff --git a/llvm/test/CodeGen/RISCV/rvp-simd-64.ll b/llvm/test/CodeGen/RISCV/rvp-simd-64.ll index 96f16c3d52103..705718e63ba4f 100644 --- a/llvm/test/CodeGen/RISCV/rvp-simd-64.ll +++ b/llvm/test/CodeGen/RISCV/rvp-simd-64.ll @@ -6936,3 +6936,378 @@ define i64 @test_pnclipup_v2i32(i64 %a, i64 %b) { %s = bitcast <2 x i32> %r to i64 ret i64 %s } + +define <2 x i32> @test_pm4add_v8i8_v2i32(<8 x i8> %a, <8 x i8> %b) { +; RV32-LABEL: test_pm4add_v8i8_v2i32: +; RV32: # %bb.0: +; RV32-NEXT: pm4add.b a1, a1, a3 +; RV32-NEXT: pm4add.b a0, a0, a2 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pm4add_v8i8_v2i32: +; RV64: # %bb.0: +; RV64-NEXT: pm4add.b a0, a0, a1 +; RV64-NEXT: ret + %r = call <2 x i32> @llvm.riscv.pm4add.v2i32.v8i8(<8 x i8> %a, <8 x i8> %b) + ret <2 x i32> %r +} + +define <2 x i32> @test_pm2add_v4i16_v2i32(<4 x i16> %a, <4 x i16> %b) { +; RV32-LABEL: test_pm2add_v4i16_v2i32: +; RV32: # %bb.0: +; RV32-NEXT: pm2add.h a1, a1, a3 +; RV32-NEXT: pm2add.h a0, a0, a2 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pm2add_v4i16_v2i32: +; RV64: # %bb.0: +; RV64-NEXT: pm2add.h a0, a0, a1 +; RV64-NEXT: ret + %r = call <2 x i32> @llvm.riscv.pm2add.v2i32.v4i16(<4 x i16> %a, <4 x i16> %b) + ret <2 x i32> %r +} + +define <2 x i32> @test_pm2add_x_v4i16_v2i32(<4 x i16> %a, <4 x i16> %b) { +; RV32-LABEL: test_pm2add_x_v4i16_v2i32: +; RV32: # %bb.0: +; RV32-NEXT: pm2add.hx a1, a1, a3 +; RV32-NEXT: pm2add.hx a0, a0, a2 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pm2add_x_v4i16_v2i32: +; RV64: # %bb.0: +; RV64-NEXT: pm2add.hx a0, a0, a1 +; RV64-NEXT: ret + %r = call <2 x i32> @llvm.riscv.pm2add.x.v2i32.v4i16(<4 x i16> %a, <4 x i16> %b) + ret <2 x i32> %r +} + +define <2 x i32> @test_pm4addu_v8i8_v2i32(<8 x i8> %a, <8 x i8> %b) { +; RV32-LABEL: test_pm4addu_v8i8_v2i32: +; RV32: # %bb.0: +; RV32-NEXT: pm4addu.b a1, a1, a3 +; RV32-NEXT: pm4addu.b a0, a0, a2 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pm4addu_v8i8_v2i32: +; RV64: # %bb.0: +; RV64-NEXT: pm4addu.b a0, a0, a1 +; RV64-NEXT: ret + %r = call <2 x i32> @llvm.riscv.pm4addu.v2i32.v8i8(<8 x i8> %a, <8 x i8> %b) + ret <2 x i32> %r +} + +define <2 x i32> @test_pm2addu_v4i16_v2i32(<4 x i16> %a, <4 x i16> %b) { +; RV32-LABEL: test_pm2addu_v4i16_v2i32: +; RV32: # %bb.0: +; RV32-NEXT: pm2addu.h a1, a1, a3 +; RV32-NEXT: pm2addu.h a0, a0, a2 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pm2addu_v4i16_v2i32: +; RV64: # %bb.0: +; RV64-NEXT: pm2addu.h a0, a0, a1 +; RV64-NEXT: ret + %r = call <2 x i32> @llvm.riscv.pm2addu.v2i32.v4i16(<4 x i16> %a, <4 x i16> %b) + ret <2 x i32> %r +} + +define <2 x i32> @test_pmq2add_v4i16_v2i32(<4 x i16> %a, <4 x i16> %b) { +; RV32-LABEL: test_pmq2add_v4i16_v2i32: +; RV32: # %bb.0: +; RV32-NEXT: pmq2add.h a1, a1, a3 +; RV32-NEXT: pmq2add.h a0, a0, a2 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pmq2add_v4i16_v2i32: +; RV64: # %bb.0: +; RV64-NEXT: pmq2add.h a0, a0, a1 +; RV64-NEXT: ret + %r = call <2 x i32> @llvm.riscv.pmq2add.v2i32.v4i16(<4 x i16> %a, <4 x i16> %b) + ret <2 x i32> %r +} + +define <2 x i32> @test_pmqr2add_v4i16_v2i32(<4 x i16> %a, <4 x i16> %b) { +; RV32-LABEL: test_pmqr2add_v4i16_v2i32: +; RV32: # %bb.0: +; RV32-NEXT: pmqr2add.h a1, a1, a3 +; RV32-NEXT: pmqr2add.h a0, a0, a2 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pmqr2add_v4i16_v2i32: +; RV64: # %bb.0: +; RV64-NEXT: pmqr2add.h a0, a0, a1 +; RV64-NEXT: ret + %r = call <2 x i32> @llvm.riscv.pmqr2add.v2i32.v4i16(<4 x i16> %a, <4 x i16> %b) + ret <2 x i32> %r +} + +define <2 x i32> @test_pm2sadd_v4i16_v2i32(<4 x i16> %a, <4 x i16> %b) { +; RV32-LABEL: test_pm2sadd_v4i16_v2i32: +; RV32: # %bb.0: +; RV32-NEXT: pm2sadd.h a1, a1, a3 +; RV32-NEXT: pm2sadd.h a0, a0, a2 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pm2sadd_v4i16_v2i32: +; RV64: # %bb.0: +; RV64-NEXT: pm2sadd.h a0, a0, a1 +; RV64-NEXT: ret + %r = call <2 x i32> @llvm.riscv.pm2sadd.v2i32.v4i16(<4 x i16> %a, <4 x i16> %b) + ret <2 x i32> %r +} + +define <2 x i32> @test_pm2sadd_x_v4i16_v2i32(<4 x i16> %a, <4 x i16> %b) { +; RV32-LABEL: test_pm2sadd_x_v4i16_v2i32: +; RV32: # %bb.0: +; RV32-NEXT: pm2sadd.hx a1, a1, a3 +; RV32-NEXT: pm2sadd.hx a0, a0, a2 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pm2sadd_x_v4i16_v2i32: +; RV64: # %bb.0: +; RV64-NEXT: pm2sadd.hx a0, a0, a1 +; RV64-NEXT: ret + %r = call <2 x i32> @llvm.riscv.pm2sadd.x.v2i32.v4i16(<4 x i16> %a, <4 x i16> %b) + ret <2 x i32> %r +} + +define <2 x i32> @test_pm2sub_v4i16_v2i32(<4 x i16> %a, <4 x i16> %b) { +; RV32-LABEL: test_pm2sub_v4i16_v2i32: +; RV32: # %bb.0: +; RV32-NEXT: pm2sub.h a1, a1, a3 +; RV32-NEXT: pm2sub.h a0, a0, a2 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pm2sub_v4i16_v2i32: +; RV64: # %bb.0: +; RV64-NEXT: pm2sub.h a0, a0, a1 +; RV64-NEXT: ret + %r = call <2 x i32> @llvm.riscv.pm2sub.v2i32.v4i16(<4 x i16> %a, <4 x i16> %b) + ret <2 x i32> %r +} + +define <2 x i32> @test_pm2sub_x_v4i16_v2i32(<4 x i16> %a, <4 x i16> %b) { +; RV32-LABEL: test_pm2sub_x_v4i16_v2i32: +; RV32: # %bb.0: +; RV32-NEXT: pm2sub.hx a1, a1, a3 +; RV32-NEXT: pm2sub.hx a0, a0, a2 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pm2sub_x_v4i16_v2i32: +; RV64: # %bb.0: +; RV64-NEXT: pm2sub.hx a0, a0, a1 +; RV64-NEXT: ret + %r = call <2 x i32> @llvm.riscv.pm2sub.x.v2i32.v4i16(<4 x i16> %a, <4 x i16> %b) + ret <2 x i32> %r +} + +define <2 x i32> @test_pm4addsu_v8i8_v2i32(<8 x i8> %a, <8 x i8> %b) { +; RV32-LABEL: test_pm4addsu_v8i8_v2i32: +; RV32: # %bb.0: +; RV32-NEXT: pm4addsu.b a1, a1, a3 +; RV32-NEXT: pm4addsu.b a0, a0, a2 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pm4addsu_v8i8_v2i32: +; RV64: # %bb.0: +; RV64-NEXT: pm4addsu.b a0, a0, a1 +; RV64-NEXT: ret + %r = call <2 x i32> @llvm.riscv.pm4addsu.v2i32.v8i8(<8 x i8> %a, <8 x i8> %b) + ret <2 x i32> %r +} + +define <2 x i32> @test_pm2addsu_v4i16_v2i32(<4 x i16> %a, <4 x i16> %b) { +; RV32-LABEL: test_pm2addsu_v4i16_v2i32: +; RV32: # %bb.0: +; RV32-NEXT: pm2addsu.h a1, a1, a3 +; RV32-NEXT: pm2addsu.h a0, a0, a2 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pm2addsu_v4i16_v2i32: +; RV64: # %bb.0: +; RV64-NEXT: pm2addsu.h a0, a0, a1 +; RV64-NEXT: ret + %r = call <2 x i32> @llvm.riscv.pm2addsu.v2i32.v4i16(<4 x i16> %a, <4 x i16> %b) + ret <2 x i32> %r +} + +define i64 @test_pm2add_v2i32_i64(<2 x i32> %a, <2 x i32> %b) { +; RV32-LABEL: test_pm2add_v2i32_i64: +; RV32: # %bb.0: +; RV32-NEXT: mv a4, a1 +; RV32-NEXT: wmul a0, a0, a2 +; RV32-NEXT: wmacc a0, a4, a3 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pm2add_v2i32_i64: +; RV64: # %bb.0: +; RV64-NEXT: pm2add.w a0, a0, a1 +; RV64-NEXT: ret + %r = call i64 @llvm.riscv.pm2add.i64.v2i32(<2 x i32> %a, <2 x i32> %b) + ret i64 %r +} + +define i64 @test_pm2add_x_v2i32_i64(<2 x i32> %a, <2 x i32> %b) { +; RV32-LABEL: test_pm2add_x_v2i32_i64: +; RV32: # %bb.0: +; RV32-NEXT: mv a4, a1 +; RV32-NEXT: wmul a0, a0, a3 +; RV32-NEXT: wmacc a0, a4, a2 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pm2add_x_v2i32_i64: +; RV64: # %bb.0: +; RV64-NEXT: pm2add.wx a0, a0, a1 +; RV64-NEXT: ret + %r = call i64 @llvm.riscv.pm2add.x.i64.v2i32(<2 x i32> %a, <2 x i32> %b) + ret i64 %r +} + +define i64 @test_pm2addu_v2i32_i64(<2 x i32> %a, <2 x i32> %b) { +; RV32-LABEL: test_pm2addu_v2i32_i64: +; RV32: # %bb.0: +; RV32-NEXT: mv a4, a1 +; RV32-NEXT: wmulu a0, a0, a2 +; RV32-NEXT: wmaccu a0, a4, a3 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pm2addu_v2i32_i64: +; RV64: # %bb.0: +; RV64-NEXT: pm2addu.w a0, a0, a1 +; RV64-NEXT: ret + %r = call i64 @llvm.riscv.pm2addu.i64.v2i32(<2 x i32> %a, <2 x i32> %b) + ret i64 %r +} + +define i64 @test_pmq2add_v2i32_i64(<2 x i32> %a, <2 x i32> %b) { +; RV32-LABEL: test_pmq2add_v2i32_i64: +; RV32: # %bb.0: +; RV32-NEXT: li a4, 0 +; RV32-NEXT: li a5, 0 +; RV32-NEXT: mqwacc a4, a0, a2 +; RV32-NEXT: mqwacc a4, a1, a3 +; RV32-NEXT: mvd a0, a4 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pmq2add_v2i32_i64: +; RV64: # %bb.0: +; RV64-NEXT: pmq2add.w a0, a0, a1 +; RV64-NEXT: ret + %r = call i64 @llvm.riscv.pmq2add.i64.v2i32(<2 x i32> %a, <2 x i32> %b) + ret i64 %r +} + +define i64 @test_pmqr2add_v2i32_i64(<2 x i32> %a, <2 x i32> %b) { +; RV32-LABEL: test_pmqr2add_v2i32_i64: +; RV32: # %bb.0: +; RV32-NEXT: li a4, 0 +; RV32-NEXT: li a5, 0 +; RV32-NEXT: mqrwacc a4, a0, a2 +; RV32-NEXT: mqrwacc a4, a1, a3 +; RV32-NEXT: mvd a0, a4 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pmqr2add_v2i32_i64: +; RV64: # %bb.0: +; RV64-NEXT: pmqr2add.w a0, a0, a1 +; RV64-NEXT: ret + %r = call i64 @llvm.riscv.pmqr2add.i64.v2i32(<2 x i32> %a, <2 x i32> %b) + ret i64 %r +} + +define i64 @test_pm2sub_v2i32_i64(<2 x i32> %a, <2 x i32> %b) { +; RV32-LABEL: test_pm2sub_v2i32_i64: +; RV32: # %bb.0: +; RV32-NEXT: wmul a4, a1, a3 +; RV32-NEXT: wmul a0, a0, a2 +; RV32-NEXT: subd a0, a0, a4 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pm2sub_v2i32_i64: +; RV64: # %bb.0: +; RV64-NEXT: pm2sub.w a0, a0, a1 +; RV64-NEXT: ret + %r = call i64 @llvm.riscv.pm2sub.i64.v2i32(<2 x i32> %a, <2 x i32> %b) + ret i64 %r +} + +define i64 @test_pm2sub_x_v2i32_i64(<2 x i32> %a, <2 x i32> %b) { +; RV32-LABEL: test_pm2sub_x_v2i32_i64: +; RV32: # %bb.0: +; RV32-NEXT: wmul a4, a1, a2 +; RV32-NEXT: wmul a0, a0, a3 +; RV32-NEXT: subd a0, a0, a4 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pm2sub_x_v2i32_i64: +; RV64: # %bb.0: +; RV64-NEXT: pm2sub.wx a0, a0, a1 +; RV64-NEXT: ret + %r = call i64 @llvm.riscv.pm2sub.x.i64.v2i32(<2 x i32> %a, <2 x i32> %b) + ret i64 %r +} + +define i64 @test_pm2addsu_v2i32_i64(<2 x i32> %a, <2 x i32> %b) { +; RV32-LABEL: test_pm2addsu_v2i32_i64: +; RV32: # %bb.0: +; RV32-NEXT: mv a4, a1 +; RV32-NEXT: wmulsu a0, a0, a2 +; RV32-NEXT: wmaccsu a0, a4, a3 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pm2addsu_v2i32_i64: +; RV64: # %bb.0: +; RV64-NEXT: pm2addsu.w a0, a0, a1 +; RV64-NEXT: ret + %r = call i64 @llvm.riscv.pm2addsu.i64.v2i32(<2 x i32> %a, <2 x i32> %b) + ret i64 %r +} + +define i64 @test_pm4add_v4i16_i64(<4 x i16> %a, <4 x i16> %b) { +; RV32-LABEL: test_pm4add_v4i16_i64: +; RV32: # %bb.0: +; RV32-NEXT: mv a4, a1 +; RV32-NEXT: pm2wadd.h a0, a0, a2 +; RV32-NEXT: pm2wadda.h a0, a4, a3 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pm4add_v4i16_i64: +; RV64: # %bb.0: +; RV64-NEXT: pm4add.h a0, a0, a1 +; RV64-NEXT: ret + %r = call i64 @llvm.riscv.pm4add.i64.v4i16(<4 x i16> %a, <4 x i16> %b) + ret i64 %r +} + +define i64 @test_pm4addu_v4i16_i64(<4 x i16> %a, <4 x i16> %b) { +; RV32-LABEL: test_pm4addu_v4i16_i64: +; RV32: # %bb.0: +; RV32-NEXT: mv a4, a1 +; RV32-NEXT: pm2waddu.h a0, a0, a2 +; RV32-NEXT: pm2waddau.h a0, a4, a3 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pm4addu_v4i16_i64: +; RV64: # %bb.0: +; RV64-NEXT: pm4addu.h a0, a0, a1 +; RV64-NEXT: ret + %r = call i64 @llvm.riscv.pm4addu.i64.v4i16(<4 x i16> %a, <4 x i16> %b) + ret i64 %r +} + +define i64 @test_pm4addsu_v4i16_i64(<4 x i16> %a, <4 x i16> %b) { +; RV32-LABEL: test_pm4addsu_v4i16_i64: +; RV32: # %bb.0: +; RV32-NEXT: mv a4, a1 +; RV32-NEXT: pm2waddsu.h a0, a0, a2 +; RV32-NEXT: pm2waddasu.h a0, a4, a3 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pm4addsu_v4i16_i64: +; RV64: # %bb.0: +; RV64-NEXT: pm4addsu.h a0, a0, a1 +; RV64-NEXT: ret + %r = call i64 @llvm.riscv.pm4addsu.i64.v4i16(<4 x i16> %a, <4 x i16> %b) + ret i64 %r +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
