https://github.com/Michael-Chen-NJU updated https://github.com/llvm/llvm-project/pull/217534
From 49159eb4c948e30d0d05f912f0c847bf398e80d4 Mon Sep 17 00:00:00 2001 From: Michael-Chen-NJU <[email protected]> Date: Thu, 20 Aug 2026 14:14:12 +0800 Subject: [PATCH 1/2] [Clang][RISCV] Add packed widening multiply intrinsics --- clang/lib/Headers/riscv_packed_simd.h | 23 +++ clang/test/CodeGen/RISCV/rvp-intrinsics.c | 156 ++++++++++++++++++ .../riscv_packed_simd.c | 50 ++++++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 52 ++++++ llvm/lib/Target/RISCV/RISCVInstrInfoP.td | 38 +++-- llvm/test/CodeGen/RISCV/rvp-simd-32.ll | 146 +++++++++++++--- llvm/test/CodeGen/RISCV/rvp-simd-64.ll | 28 +--- 7 files changed, 433 insertions(+), 60 deletions(-) diff --git a/clang/lib/Headers/riscv_packed_simd.h b/clang/lib/Headers/riscv_packed_simd.h index 2a9a8f88a0af4..4d46a64b3be2b 100644 --- a/clang/lib/Headers/riscv_packed_simd.h +++ b/clang/lib/Headers/riscv_packed_simd.h @@ -130,6 +130,18 @@ typedef uint32_t uint32x2_t __attribute__((__vector_size__(8))); static __inline__ rty __DEFAULT_FN_ATTRS __riscv_##name(ty __rs1) { \ return __builtin_convertvector(__rs1, rty); \ } +#define __packed_widen_mul(name, rty, ty) \ + static __inline__ rty __DEFAULT_FN_ATTRS __riscv_##name(ty __rs1, \ + ty __rs2) { \ + return __builtin_convertvector(__rs1, rty) * \ + __builtin_convertvector(__rs2, rty); \ + } +#define __packed_widen_mulsu(name, rty, ty1, ty2, uty) \ + static __inline__ rty __DEFAULT_FN_ATTRS __riscv_##name(ty1 __rs1, \ + ty2 __rs2) { \ + return __builtin_convertvector(__rs1, rty) * \ + (rty) __builtin_convertvector(__rs2, uty); \ + } #define __packed_widen_high2(name, rty, ty) \ static __inline__ rty __DEFAULT_FN_ATTRS __riscv_##name(ty __rs1) { \ return (rty)__builtin_shufflevector((ty){0}, __rs1, 0, 2, 1, 3); \ @@ -580,6 +592,15 @@ __packed_widen_high4(pwcvth_u16x4, uint16x4_t, uint8x4_t) __packed_widen_high2(pwcvth_i32x2, int32x2_t, int16x2_t) __packed_widen_high2(pwcvth_u32x2, uint32x2_t, uint16x2_t) +/* Packed Widening Multiply (32-bit) */ +__packed_widen_mul(pwmul_i16x4, int16x4_t, int8x4_t) +__packed_widen_mul(pwmul_i32x2, int32x2_t, int16x2_t) +__packed_widen_mul(pwmulu_u16x4, uint16x4_t, uint8x4_t) +__packed_widen_mul(pwmulu_u32x2, uint32x2_t, uint16x2_t) +__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 Narrowing Convert */ __packed_narrow_even4(pncvt_i8x4, int8x4_t, int16x4_t, int8x8_t) __packed_narrow_even4(pncvt_u8x4, uint8x4_t, uint16x4_t, uint8x8_t) @@ -925,6 +946,8 @@ __packed_reinterpret(u32x2_i32x2, int32x2_t, uint32x2_t) #undef __packed_merge_builtin #undef __packed_unary_builtin #undef __packed_widen_convert +#undef __packed_widen_mul +#undef __packed_widen_mulsu #undef __packed_widen_high2 #undef __packed_widen_high4 #undef __packed_narrow_even2 diff --git a/clang/test/CodeGen/RISCV/rvp-intrinsics.c b/clang/test/CodeGen/RISCV/rvp-intrinsics.c index 3a558d9750db2..87bc81ed7a645 100644 --- a/clang/test/CodeGen/RISCV/rvp-intrinsics.c +++ b/clang/test/CodeGen/RISCV/rvp-intrinsics.c @@ -8032,6 +8032,162 @@ uint32x2_t test_pwcvtu_u32x2(uint16x2_t rs1) { return __riscv_pwcvtu_u32x2(rs1); } +// RV32-LABEL: define dso_local i64 @test_pwmul_i16x4( +// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8> +// RV32-NEXT: [[CONV_I:%.*]] = sext <4 x i8> [[TMP0]] to <4 x i16> +// RV32-NEXT: [[CONV3_I:%.*]] = sext <4 x i8> [[TMP1]] to <4 x i16> +// RV32-NEXT: [[MUL_I:%.*]] = mul nsw <4 x i16> [[CONV_I]], [[CONV3_I]] +// RV32-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[MUL_I]] to i64 +// RV32-NEXT: ret i64 [[TMP2]] +// +// RV64-LABEL: define dso_local i64 @test_pwmul_i16x4( +// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8> +// RV64-NEXT: [[CONV_I:%.*]] = sext <4 x i8> [[TMP0]] to <4 x i16> +// RV64-NEXT: [[CONV3_I:%.*]] = sext <4 x i8> [[TMP1]] to <4 x i16> +// RV64-NEXT: [[MUL_I:%.*]] = mul nsw <4 x i16> [[CONV_I]], [[CONV3_I]] +// RV64-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[MUL_I]] to i64 +// RV64-NEXT: ret i64 [[TMP2]] +// +int16x4_t test_pwmul_i16x4(int8x4_t rs1, int8x4_t rs2) { + return __riscv_pwmul_i16x4(rs1, rs2); +} + +// RV32-LABEL: define dso_local i64 @test_pwmul_i32x2( +// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <2 x i16> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <2 x i16> +// RV32-NEXT: [[CONV_I:%.*]] = sext <2 x i16> [[TMP0]] to <2 x i32> +// RV32-NEXT: [[CONV3_I:%.*]] = sext <2 x i16> [[TMP1]] to <2 x i32> +// RV32-NEXT: [[MUL_I:%.*]] = mul nsw <2 x i32> [[CONV_I]], [[CONV3_I]] +// RV32-NEXT: [[TMP2:%.*]] = bitcast <2 x i32> [[MUL_I]] to i64 +// RV32-NEXT: ret i64 [[TMP2]] +// +// RV64-LABEL: define dso_local i64 @test_pwmul_i32x2( +// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <2 x i16> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <2 x i16> +// RV64-NEXT: [[CONV_I:%.*]] = sext <2 x i16> [[TMP0]] to <2 x i32> +// RV64-NEXT: [[CONV3_I:%.*]] = sext <2 x i16> [[TMP1]] to <2 x i32> +// RV64-NEXT: [[MUL_I:%.*]] = mul nsw <2 x i32> [[CONV_I]], [[CONV3_I]] +// RV64-NEXT: [[TMP2:%.*]] = bitcast <2 x i32> [[MUL_I]] to i64 +// RV64-NEXT: ret i64 [[TMP2]] +// +int32x2_t test_pwmul_i32x2(int16x2_t rs1, int16x2_t rs2) { + return __riscv_pwmul_i32x2(rs1, rs2); +} + +// RV32-LABEL: define dso_local i64 @test_pwmulu_u16x4( +// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8> +// RV32-NEXT: [[CONV_I:%.*]] = zext <4 x i8> [[TMP0]] to <4 x i16> +// RV32-NEXT: [[CONV3_I:%.*]] = zext <4 x i8> [[TMP1]] to <4 x i16> +// RV32-NEXT: [[MUL_I:%.*]] = mul nuw <4 x i16> [[CONV_I]], [[CONV3_I]] +// RV32-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[MUL_I]] to i64 +// RV32-NEXT: ret i64 [[TMP2]] +// +// RV64-LABEL: define dso_local i64 @test_pwmulu_u16x4( +// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8> +// RV64-NEXT: [[CONV_I:%.*]] = zext <4 x i8> [[TMP0]] to <4 x i16> +// RV64-NEXT: [[CONV3_I:%.*]] = zext <4 x i8> [[TMP1]] to <4 x i16> +// RV64-NEXT: [[MUL_I:%.*]] = mul nuw <4 x i16> [[CONV_I]], [[CONV3_I]] +// RV64-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[MUL_I]] to i64 +// RV64-NEXT: ret i64 [[TMP2]] +// +uint16x4_t test_pwmulu_u16x4(uint8x4_t rs1, uint8x4_t rs2) { + return __riscv_pwmulu_u16x4(rs1, rs2); +} + +// RV32-LABEL: define dso_local i64 @test_pwmulu_u32x2( +// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <2 x i16> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <2 x i16> +// RV32-NEXT: [[CONV_I:%.*]] = zext <2 x i16> [[TMP0]] to <2 x i32> +// RV32-NEXT: [[CONV3_I:%.*]] = zext <2 x i16> [[TMP1]] to <2 x i32> +// RV32-NEXT: [[MUL_I:%.*]] = mul nuw <2 x i32> [[CONV_I]], [[CONV3_I]] +// RV32-NEXT: [[TMP2:%.*]] = bitcast <2 x i32> [[MUL_I]] to i64 +// RV32-NEXT: ret i64 [[TMP2]] +// +// RV64-LABEL: define dso_local i64 @test_pwmulu_u32x2( +// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <2 x i16> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <2 x i16> +// RV64-NEXT: [[CONV_I:%.*]] = zext <2 x i16> [[TMP0]] to <2 x i32> +// RV64-NEXT: [[CONV3_I:%.*]] = zext <2 x i16> [[TMP1]] to <2 x i32> +// RV64-NEXT: [[MUL_I:%.*]] = mul nuw <2 x i32> [[CONV_I]], [[CONV3_I]] +// RV64-NEXT: [[TMP2:%.*]] = bitcast <2 x i32> [[MUL_I]] to i64 +// RV64-NEXT: ret i64 [[TMP2]] +// +uint32x2_t test_pwmulu_u32x2(uint16x2_t rs1, uint16x2_t rs2) { + return __riscv_pwmulu_u32x2(rs1, rs2); +} + +// RV32-LABEL: define dso_local i64 @test_pwmulsu_i16x4( +// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8> +// RV32-NEXT: [[CONV_I:%.*]] = sext <4 x i8> [[TMP0]] to <4 x i16> +// RV32-NEXT: [[CONV3_I:%.*]] = zext <4 x i8> [[TMP1]] to <4 x i16> +// RV32-NEXT: [[MUL_I:%.*]] = mul nsw <4 x i16> [[CONV_I]], [[CONV3_I]] +// RV32-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[MUL_I]] to i64 +// RV32-NEXT: ret i64 [[TMP2]] +// +// RV64-LABEL: define dso_local i64 @test_pwmulsu_i16x4( +// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8> +// RV64-NEXT: [[CONV_I:%.*]] = sext <4 x i8> [[TMP0]] to <4 x i16> +// RV64-NEXT: [[CONV3_I:%.*]] = zext <4 x i8> [[TMP1]] to <4 x i16> +// RV64-NEXT: [[MUL_I:%.*]] = mul nsw <4 x i16> [[CONV_I]], [[CONV3_I]] +// RV64-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[MUL_I]] to i64 +// RV64-NEXT: ret i64 [[TMP2]] +// +int16x4_t test_pwmulsu_i16x4(int8x4_t rs1, uint8x4_t rs2) { + return __riscv_pwmulsu_i16x4(rs1, rs2); +} + +// RV32-LABEL: define dso_local i64 @test_pwmulsu_i32x2( +// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <2 x i16> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <2 x i16> +// RV32-NEXT: [[CONV_I:%.*]] = sext <2 x i16> [[TMP0]] to <2 x i32> +// RV32-NEXT: [[CONV3_I:%.*]] = zext <2 x i16> [[TMP1]] to <2 x i32> +// RV32-NEXT: [[MUL_I:%.*]] = mul nsw <2 x i32> [[CONV_I]], [[CONV3_I]] +// RV32-NEXT: [[TMP2:%.*]] = bitcast <2 x i32> [[MUL_I]] to i64 +// RV32-NEXT: ret i64 [[TMP2]] +// +// RV64-LABEL: define dso_local i64 @test_pwmulsu_i32x2( +// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <2 x i16> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <2 x i16> +// RV64-NEXT: [[CONV_I:%.*]] = sext <2 x i16> [[TMP0]] to <2 x i32> +// RV64-NEXT: [[CONV3_I:%.*]] = zext <2 x i16> [[TMP1]] to <2 x i32> +// RV64-NEXT: [[MUL_I:%.*]] = mul nsw <2 x i32> [[CONV_I]], [[CONV3_I]] +// RV64-NEXT: [[TMP2:%.*]] = bitcast <2 x i32> [[MUL_I]] to i64 +// RV64-NEXT: ret i64 [[TMP2]] +// +int32x2_t test_pwmulsu_i32x2(int16x2_t rs1, uint16x2_t rs2) { + return __riscv_pwmulsu_i32x2(rs1, rs2); +} + // RV32-LABEL: define dso_local i64 @test_pwcvth_i16x4( // RV32-SAME: i32 noundef [[RS1_COERCE:%.*]]) #[[ATTR0]] { // RV32-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 10a2e508fa9ce..ae1e723e89b01 100644 --- a/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c +++ b/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c @@ -2293,6 +2293,56 @@ uint32x2_t test_pwcvth_u32x2(uint16x2_t rs1) { return __riscv_pwcvth_u32x2(rs1); } +// CHECK-LABEL: test_pwmul_i16x4: +// RV32: pwmul.b +// RV64: zip8p +// RV64: pmul.h.b01 +int16x4_t test_pwmul_i16x4(int8x4_t rs1, int8x4_t rs2) { + return __riscv_pwmul_i16x4(rs1, rs2); +} + +// CHECK-LABEL: test_pwmul_i32x2: +// RV32: pwmul.h +// RV64: zip16p +// RV64: pmul.w.h01 +int32x2_t test_pwmul_i32x2(int16x2_t rs1, int16x2_t rs2) { + return __riscv_pwmul_i32x2(rs1, rs2); +} + +// CHECK-LABEL: test_pwmulu_u16x4: +// RV32: pwmulu.b +// RV64: zip8p +// RV64: pmulu.h.b01 +uint16x4_t test_pwmulu_u16x4(uint8x4_t rs1, uint8x4_t rs2) { + return __riscv_pwmulu_u16x4(rs1, rs2); +} + +// CHECK-LABEL: test_pwmulu_u32x2: +// RV32: pwmulu.h +// RV64: zip16p +// RV64: pmulu.w.h01 +uint32x2_t test_pwmulu_u32x2(uint16x2_t rs1, uint16x2_t rs2) { + return __riscv_pwmulu_u32x2(rs1, rs2); +} + +// CHECK-LABEL: test_pwmulsu_i16x4: +// RV32: pwmulsu.b +// RV64: pwcvtu.wb +// RV64: pwcvtu.wb +// RV64: pmulsu.h.b00 +int16x4_t test_pwmulsu_i16x4(int8x4_t rs1, uint8x4_t rs2) { + return __riscv_pwmulsu_i16x4(rs1, rs2); +} + +// CHECK-LABEL: test_pwmulsu_i32x2: +// RV32: pwmulsu.h +// RV64: pwcvtu.wh +// RV64: pwcvtu.wh +// RV64: pmulsu.w.h00 +int32x2_t test_pwmulsu_i32x2(int16x2_t rs1, uint16x2_t rs2) { + return __riscv_pwmulsu_i32x2(rs1, rs2); +} + // CHECK-LABEL: test_pncvt_i8x4: // RV32: pncvt.b // RV64: pncvt.wb diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 1db51b19fde2d..ee6ec067b02dc 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -18857,6 +18857,55 @@ static SDValue combineVectorMulToSraBitcast(SDNode *N, SelectionDAG &DAG) { return DAG.getNode(ISD::BITCAST, DL, VT, Sra); } +static SDValue combinePExtWideningMul(SDNode *N, SelectionDAG &DAG, + const RISCVSubtarget &Subtarget) { + if (!Subtarget.hasStdExtP()) + return SDValue(); + + EVT VT = N->getValueType(0); + if (VT != MVT::v4i16 && VT != MVT::v2i32) + return SDValue(); + + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + bool N0IsSExt = N0.getOpcode() == ISD::SIGN_EXTEND; + bool N0IsZExt = N0.getOpcode() == ISD::ZERO_EXTEND; + bool N1IsSExt = N1.getOpcode() == ISD::SIGN_EXTEND; + bool N1IsZExt = N1.getOpcode() == ISD::ZERO_EXTEND; + + if (!(N0IsSExt || N0IsZExt) || !(N1IsSExt || N1IsZExt) || !N0.hasOneUse() || + !N1.hasOneUse()) + return SDValue(); + + SDValue A = N0.getOperand(0); + SDValue B = N1.getOperand(0); + EVT SrcVT = VT == MVT::v4i16 ? MVT::v4i8 : MVT::v2i16; + if (A.getValueType() != SrcVT || B.getValueType() != SrcVT) + return SDValue(); + + unsigned Opc; + if (N0IsSExt && N1IsSExt) { + Opc = RISCVISD::PWMUL; + } else if (N0IsZExt && N1IsZExt) { + Opc = RISCVISD::PWMULU; + } else { + Opc = RISCVISD::PWMULSU; + if (N0IsZExt && N1IsSExt) + std::swap(A, B); + } + + if (Subtarget.is64Bit()) { + MVT LegalSrcVT = VT == MVT::v4i16 ? MVT::v8i8 : MVT::v4i16; + SDLoc DL(N); + A = DAG.getNode(ISD::CONCAT_VECTORS, DL, LegalSrcVT, A, + DAG.getUNDEF(SrcVT)); + B = DAG.getNode(ISD::CONCAT_VECTORS, DL, LegalSrcVT, B, + DAG.getUNDEF(SrcVT)); + } + + return DAG.getNode(Opc, SDLoc(N), VT, A, B); +} + static SDValue performMULCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget) { @@ -18900,6 +18949,9 @@ static SDValue performMULCombine(SDNode *N, SelectionDAG &DAG, if (SDValue V = combineBinOpOfZExt(N, DAG)) return V; + if (SDValue V = combinePExtWideningMul(N, DAG, Subtarget)) + return V; + if (SDValue V = combineVectorMulToSraBitcast(N, DAG)) return V; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td index e499a6ba92265..db27cc619b6f1 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td @@ -1845,8 +1845,7 @@ def riscv_wmulsu : RVSDNode<"WMULSU", SDTIntBinHiLoOp>; def SDT_RISCVPackedWideningMul : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<1, 2>, - SDTCisOpSmallerThanOp<1, 0>, - SDTCisSameNumEltsAs<0, 1>]>; + SDTCisOpSmallerThanOp<1, 0>]>; def riscv_pwmul : RVSDNode<"PWMUL", SDT_RISCVPackedWideningMul, [SDNPCommutative]>; def riscv_pwmulu : RVSDNode<"PWMULU", SDT_RISCVPackedWideningMul, [SDNPCommutative]>; def riscv_pwmulsu : RVSDNode<"PWMULSU", SDT_RISCVPackedWideningMul>; @@ -2307,19 +2306,18 @@ let append Predicates = [IsRV32] in { (XLenVT (PPAIRE_B zexti8:$op1rs1, GPR:$op1rs2)))>; // Packed widening multiply patterns. - // The v2i32 patterns are not needed yet. def : Pat<(v4i16 (riscv_pwmul (v4i8 GPR:$rs1), (v4i8 GPR:$rs2))), - (PWMUL_B GPR:$rs1, GPR:$rs2)>; + (PWMUL_B GPR:$rs1, GPR:$rs2)>; def : Pat<(v2i32 (riscv_pwmul (v2i16 GPR:$rs1), (v2i16 GPR:$rs2))), - (PWMUL_H GPR:$rs1, GPR:$rs2)>; + (PWMUL_H GPR:$rs1, GPR:$rs2)>; def : Pat<(v4i16 (riscv_pwmulu (v4i8 GPR:$rs1), (v4i8 GPR:$rs2))), - (PWMULU_B GPR:$rs1, GPR:$rs2)>; - //def : Pat<(v2i32 (riscv_pwmulu (v2i16 GPR:$rs1), (v2i16 GPR:$rs2))), - // (PWMULU_H GPR:$rs1, GPR:$rs2)>; + (PWMULU_B GPR:$rs1, GPR:$rs2)>; + def : Pat<(v2i32 (riscv_pwmulu (v2i16 GPR:$rs1), (v2i16 GPR:$rs2))), + (PWMULU_H GPR:$rs1, GPR:$rs2)>; def : Pat<(v4i16 (riscv_pwmulsu (v4i8 GPR:$rs1), (v4i8 GPR:$rs2))), (PWMULSU_B GPR:$rs1, GPR:$rs2)>; - //def : Pat<(v2i32 (riscv_pwmulsu (v2i16 GPR:$rs1), (v2i16 GPR:$rs2))), - // (PWMULSU_H GPR:$rs1, GPR:$rs2)>; + def : Pat<(v2i32 (riscv_pwmulsu (v2i16 GPR:$rs1), (v2i16 GPR:$rs2))), + (PWMULSU_H GPR:$rs1, GPR:$rs2)>; // 8/16-bit bitreverse patterns // With Zbkb, brev8 reverses the bits within each byte directly; otherwise @@ -2808,6 +2806,26 @@ let append Predicates = [IsRV64] in { def : Pat<(v2i32 (mul GPR:$rs1, GPR:$rs2)), (PACK (MUL_W00 GPR:$rs1, GPR:$rs2), (MUL_W11 GPR:$rs1, GPR:$rs2))>; + // Packed widening multiply patterns. + def : Pat<(v4i16 (riscv_pwmul (v8i8 GPR:$rs1), (v8i8 GPR:$rs2))), + (PMUL_H_B01 (ZIP8P GPR:$rs1, GPR:$rs2), + (ZIP8P GPR:$rs1, GPR:$rs2))>; + def : Pat<(v2i32 (riscv_pwmul (v4i16 GPR:$rs1), (v4i16 GPR:$rs2))), + (PMUL_W_H01 (ZIP16P GPR:$rs1, GPR:$rs2), + (ZIP16P GPR:$rs1, GPR:$rs2))>; + def : Pat<(v4i16 (riscv_pwmulu (v8i8 GPR:$rs1), (v8i8 GPR:$rs2))), + (PMULU_H_B01 (ZIP8P GPR:$rs1, GPR:$rs2), + (ZIP8P GPR:$rs1, GPR:$rs2))>; + def : Pat<(v2i32 (riscv_pwmulu (v4i16 GPR:$rs1), (v4i16 GPR:$rs2))), + (PMULU_W_H01 (ZIP16P GPR:$rs1, GPR:$rs2), + (ZIP16P GPR:$rs1, GPR:$rs2))>; + def : Pat<(v4i16 (riscv_pwmulsu (v8i8 GPR:$rs1), (v8i8 GPR:$rs2))), + (PMULSU_H_B00 (ZIP8P GPR:$rs1, (v8i8 X0)), + (ZIP8P GPR:$rs2, (v8i8 X0)))>; + def : Pat<(v2i32 (riscv_pwmulsu (v4i16 GPR:$rs1), (v4i16 GPR:$rs2))), + (PMULSU_W_H00 (ZIP16P GPR:$rs1, (v4i16 X0)), + (ZIP16P GPR:$rs2, (v4i16 X0)))>; + // 8-bit multiply high patterns // FIXME custom lower def : Pat<(v8i8 (mulhs 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 5961c4f4ce940..0a5b14b7fd3ce 100644 --- a/llvm/test/CodeGen/RISCV/rvp-simd-32.ll +++ b/llvm/test/CodeGen/RISCV/rvp-simd-32.ll @@ -1356,6 +1356,116 @@ define <2 x i16> @test_pssha_s_i16x2_neg_imm_too_large(<2 x i16> %a) { ret <2 x i16> %res } +; Test packed widening multiply signed for v4i8 +define <4 x i16> @test_pwmul_b(<4 x i8> %a, <4 x i8> %b) { +; RV32-LABEL: test_pwmul_b: +; RV32: # %bb.0: +; RV32-NEXT: pwmul.b a0, a0, a1 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pwmul_b: +; RV64: # %bb.0: +; RV64-NEXT: zip8p a0, a0, a1 +; RV64-NEXT: pmul.h.b01 a0, a0, a0 +; RV64-NEXT: ret + %a_ext = sext <4 x i8> %a to <4 x i16> + %b_ext = sext <4 x i8> %b to <4 x i16> + %res = mul <4 x i16> %a_ext, %b_ext + ret <4 x i16> %res +} + +; Test packed widening multiply signed for v2i16 +define <2 x i32> @test_pwmul_h(<2 x i16> %a, <2 x i16> %b) { +; RV32-LABEL: test_pwmul_h: +; RV32: # %bb.0: +; RV32-NEXT: pwmul.h a0, a0, a1 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pwmul_h: +; RV64: # %bb.0: +; RV64-NEXT: zip16p a0, a0, a1 +; RV64-NEXT: pmul.w.h01 a0, a0, a0 +; RV64-NEXT: ret + %a_ext = sext <2 x i16> %a to <2 x i32> + %b_ext = sext <2 x i16> %b to <2 x i32> + %res = mul <2 x i32> %a_ext, %b_ext + ret <2 x i32> %res +} + +; Test packed widening multiply unsigned for v4i8 +define <4 x i16> @test_pwmulu_b(<4 x i8> %a, <4 x i8> %b) { +; RV32-LABEL: test_pwmulu_b: +; RV32: # %bb.0: +; RV32-NEXT: pwmulu.b a0, a0, a1 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pwmulu_b: +; RV64: # %bb.0: +; RV64-NEXT: zip8p a0, a0, a1 +; RV64-NEXT: pmulu.h.b01 a0, a0, a0 +; RV64-NEXT: ret + %a_ext = zext <4 x i8> %a to <4 x i16> + %b_ext = zext <4 x i8> %b to <4 x i16> + %res = mul <4 x i16> %a_ext, %b_ext + ret <4 x i16> %res +} + +; Test packed widening multiply unsigned for v2i16 +define <2 x i32> @test_pwmulu_h(<2 x i16> %a, <2 x i16> %b) { +; RV32-LABEL: test_pwmulu_h: +; RV32: # %bb.0: +; RV32-NEXT: pwmulu.h a0, a0, a1 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pwmulu_h: +; RV64: # %bb.0: +; RV64-NEXT: zip16p a0, a0, a1 +; RV64-NEXT: pmulu.w.h01 a0, a0, a0 +; RV64-NEXT: ret + %a_ext = zext <2 x i16> %a to <2 x i32> + %b_ext = zext <2 x i16> %b to <2 x i32> + %res = mul <2 x i32> %a_ext, %b_ext + ret <2 x i32> %res +} + +; Test packed widening multiply signed-unsigned for v4i8 +define <4 x i16> @test_pwmulsu_b(<4 x i8> %a, <4 x i8> %b) { +; RV32-LABEL: test_pwmulsu_b: +; RV32: # %bb.0: +; RV32-NEXT: pwmulsu.b a0, a0, a1 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pwmulsu_b: +; RV64: # %bb.0: +; RV64-NEXT: pwcvtu.wb a1, a1 +; RV64-NEXT: pwcvtu.wb a0, a0 +; RV64-NEXT: pmulsu.h.b00 a0, a0, a1 +; RV64-NEXT: ret + %a_ext = sext <4 x i8> %a to <4 x i16> + %b_ext = zext <4 x i8> %b to <4 x i16> + %res = mul <4 x i16> %a_ext, %b_ext + ret <4 x i16> %res +} + +; Test packed widening multiply signed-unsigned for v2i16 +define <2 x i32> @test_pwmulsu_h(<2 x i16> %a, <2 x i16> %b) { +; RV32-LABEL: test_pwmulsu_h: +; RV32: # %bb.0: +; RV32-NEXT: pwmulsu.h a0, a0, a1 +; RV32-NEXT: ret +; +; RV64-LABEL: test_pwmulsu_h: +; RV64: # %bb.0: +; RV64-NEXT: pwcvtu.wh a1, a1 +; RV64-NEXT: pwcvtu.wh a0, a0 +; RV64-NEXT: pmulsu.w.h00 a0, a0, a1 +; RV64-NEXT: ret + %a_ext = sext <2 x i16> %a to <2 x i32> + %b_ext = zext <2 x i16> %b to <2 x i32> + %res = mul <2 x i32> %a_ext, %b_ext + ret <2 x i32> %res +} + ; Test packed multiply high signed for v4i8 define <4 x i8> @test_pmulh_b(<4 x i8> %a, <4 x i8> %b) { ; RV32-LABEL: test_pmulh_b: @@ -1404,23 +1514,15 @@ define <4 x i8> @test_pmulhu_b(<4 x i8> %a, <4 x i8> %b) { define <4 x i8> @test_pmulhsu_b(<4 x i8> %a, <4 x i8> %b) { ; RV32-LABEL: test_pmulhsu_b: ; RV32: # %bb.0: -; RV32-NEXT: pwcvt.b a2, a0 -; RV32-NEXT: pwcvtu.b a0, a1 -; RV32-NEXT: pwmul.h a4, a3, a1 -; RV32-NEXT: pncvt.h a1, a4 -; RV32-NEXT: pwmul.h a2, a2, a0 -; RV32-NEXT: pncvt.h a0, a2 +; RV32-NEXT: pwmulsu.b a0, a0, a1 ; RV32-NEXT: pncvth.b a0, a0 ; RV32-NEXT: ret ; ; RV64-LABEL: test_pmulhsu_b: ; RV64: # %bb.0: -; RV64-NEXT: pwcvtu.wb a0, a0 -; RV64-NEXT: psext.h.b a0, a0 ; RV64-NEXT: pwcvtu.wb a1, a1 -; RV64-NEXT: pmul.w.h11 a2, a0, a1 -; RV64-NEXT: pmul.w.h00 a0, a0, a1 -; RV64-NEXT: ppaire.h a0, a0, a2 +; RV64-NEXT: pwcvtu.wb a0, a0 +; RV64-NEXT: pmulsu.h.b00 a0, a0, a1 ; RV64-NEXT: psrli.h a0, a0, 8 ; RV64-NEXT: pncvt.wb a0, a0 ; RV64-NEXT: ret @@ -1435,23 +1537,15 @@ define <4 x i8> @test_pmulhsu_b(<4 x i8> %a, <4 x i8> %b) { define <4 x i8> @test_pmulhsu_b_commuted(<4 x i8> %a, <4 x i8> %b) { ; RV32-LABEL: test_pmulhsu_b_commuted: ; RV32: # %bb.0: -; RV32-NEXT: pwcvtu.b a2, a0 -; RV32-NEXT: pwcvt.b a0, a1 -; RV32-NEXT: pwmul.h a4, a3, a1 -; RV32-NEXT: pncvt.h a1, a4 -; RV32-NEXT: pwmul.h a2, a2, a0 -; RV32-NEXT: pncvt.h a0, a2 +; RV32-NEXT: pwmulsu.b a0, a1, a0 ; RV32-NEXT: pncvth.b a0, a0 ; RV32-NEXT: ret ; ; RV64-LABEL: test_pmulhsu_b_commuted: ; RV64: # %bb.0: -; RV64-NEXT: pwcvtu.wb a1, a1 ; RV64-NEXT: pwcvtu.wb a0, a0 -; RV64-NEXT: psext.h.b a1, a1 -; RV64-NEXT: pmul.w.h11 a2, a0, a1 -; RV64-NEXT: pmul.w.h00 a0, a0, a1 -; RV64-NEXT: ppaire.h a0, a0, a2 +; RV64-NEXT: pwcvtu.wb a1, a1 +; RV64-NEXT: pmulsu.h.b00 a0, a1, a0 ; RV64-NEXT: psrli.h a0, a0, 8 ; RV64-NEXT: pncvt.wb a0, a0 ; RV64-NEXT: ret @@ -2314,10 +2408,10 @@ define <2 x i16> @test_select_v2i16(i1 %cond, <2 x i16> %a, <2 x i16> %b) { ; CHECK: # %bb.0: ; CHECK-NEXT: andi a3, a0, 1 ; CHECK-NEXT: mv a0, a1 -; CHECK-NEXT: bnez a3, .LBB164_2 +; CHECK-NEXT: bnez a3, [[SELECT_BB:.LBB[0-9]+_2]] ; CHECK-NEXT: # %bb.1: ; CHECK-NEXT: mv a0, a2 -; CHECK-NEXT: .LBB164_2: +; CHECK-NEXT: [[SELECT_BB]]: ; CHECK-NEXT: ret %res = select i1 %cond, <2 x i16> %a, <2 x i16> %b ret <2 x i16> %res @@ -2328,10 +2422,10 @@ define <4 x i8> @test_select_v4i8(i1 %cond, <4 x i8> %a, <4 x i8> %b) { ; CHECK: # %bb.0: ; CHECK-NEXT: andi a3, a0, 1 ; CHECK-NEXT: mv a0, a1 -; CHECK-NEXT: bnez a3, .LBB165_2 +; CHECK-NEXT: bnez a3, [[SELECT_BB:.LBB[0-9]+_2]] ; CHECK-NEXT: # %bb.1: ; CHECK-NEXT: mv a0, a2 -; CHECK-NEXT: .LBB165_2: +; CHECK-NEXT: [[SELECT_BB]]: ; CHECK-NEXT: ret %res = select i1 %cond, <4 x i8> %a, <4 x i8> %b ret <4 x i8> %res diff --git a/llvm/test/CodeGen/RISCV/rvp-simd-64.ll b/llvm/test/CodeGen/RISCV/rvp-simd-64.ll index 02ea76c17866e..47b74cc8115fe 100644 --- a/llvm/test/CodeGen/RISCV/rvp-simd-64.ll +++ b/llvm/test/CodeGen/RISCV/rvp-simd-64.ll @@ -2697,18 +2697,8 @@ define <2 x i32> @test_pmulhu_w(<2 x i32> %a, <2 x i32> %b) { define <8 x i8> @test_pmulhsu_b(<8 x i8> %a, <8 x i8> %b) { ; RV32-LABEL: test_pmulhsu_b: ; RV32: # %bb.0: -; RV32-NEXT: pwcvt.b a4, a0 -; RV32-NEXT: pwcvtu.b a6, a2 -; RV32-NEXT: pwcvt.b a0, a1 -; RV32-NEXT: pwmul.h t1, a5, a7 -; RV32-NEXT: pwcvtu.b a2, a3 -; RV32-NEXT: pncvt.h a5, t1 -; RV32-NEXT: pwmul.h a6, a4, a6 -; RV32-NEXT: pwmul.h t1, a1, a3 -; RV32-NEXT: pncvt.h a1, t1 -; RV32-NEXT: pwmul.h a2, a0, a2 -; RV32-NEXT: pncvt.h a4, a6 -; RV32-NEXT: pncvt.h a0, a2 +; RV32-NEXT: pwmulsu.b a4, a0, a2 +; RV32-NEXT: pwmulsu.b a0, a1, a3 ; RV32-NEXT: pncvth.b a1, a0 ; RV32-NEXT: pncvth.b a0, a4 ; RV32-NEXT: ret @@ -2756,18 +2746,8 @@ define <8 x i8> @test_pmulhsu_b(<8 x i8> %a, <8 x i8> %b) { define <8 x i8> @test_pmulhsu_b_commuted(<8 x i8> %a, <8 x i8> %b) { ; RV32-LABEL: test_pmulhsu_b_commuted: ; RV32: # %bb.0: -; RV32-NEXT: pwcvtu.b a4, a0 -; RV32-NEXT: pwcvt.b a6, a2 -; RV32-NEXT: pwcvtu.b a0, a1 -; RV32-NEXT: pwmul.h t1, a5, a7 -; RV32-NEXT: pwcvt.b a2, a3 -; RV32-NEXT: pncvt.h a5, t1 -; RV32-NEXT: pwmul.h a6, a4, a6 -; RV32-NEXT: pwmul.h t1, a1, a3 -; RV32-NEXT: pncvt.h a1, t1 -; RV32-NEXT: pwmul.h a2, a0, a2 -; RV32-NEXT: pncvt.h a4, a6 -; RV32-NEXT: pncvt.h a0, a2 +; RV32-NEXT: pwmulsu.b a4, a2, a0 +; RV32-NEXT: pwmulsu.b a0, a3, a1 ; RV32-NEXT: pncvth.b a1, a0 ; RV32-NEXT: pncvth.b a0, a4 ; RV32-NEXT: ret From 52b212a95bb02fc91555e8f3c2d60dd96a28488a Mon Sep 17 00:00:00 2001 From: Michael-Chen-NJU <[email protected]> Date: Fri, 21 Aug 2026 09:06:15 +0800 Subject: [PATCH 2/2] [RISCV] Model packed widening multiply RV64 pieces --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 37 ++++++++++----- llvm/lib/Target/RISCV/RISCVInstrInfoP.td | 50 +++++++++++++-------- 2 files changed, 56 insertions(+), 31 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index ee6ec067b02dc..e436df6817ca2 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -18883,27 +18883,40 @@ static SDValue combinePExtWideningMul(SDNode *N, SelectionDAG &DAG, if (A.getValueType() != SrcVT || B.getValueType() != SrcVT) return SDValue(); - unsigned Opc; + unsigned RV32Opc, RV64Opc; + bool IsSignedUnsigned = false; if (N0IsSExt && N1IsSExt) { - Opc = RISCVISD::PWMUL; + RV32Opc = RISCVISD::PWMUL; + RV64Opc = VT == MVT::v4i16 ? RISCVISD::PMUL_H_B01 : RISCVISD::PMUL_W_H01; } else if (N0IsZExt && N1IsZExt) { - Opc = RISCVISD::PWMULU; + RV32Opc = RISCVISD::PWMULU; + RV64Opc = VT == MVT::v4i16 ? RISCVISD::PMULU_H_B01 : RISCVISD::PMULU_W_H01; } else { - Opc = RISCVISD::PWMULSU; + IsSignedUnsigned = true; + RV32Opc = RISCVISD::PWMULSU; + RV64Opc = + VT == MVT::v4i16 ? RISCVISD::PMULSU_H_B00 : RISCVISD::PMULSU_W_H00; if (N0IsZExt && N1IsSExt) std::swap(A, B); } - if (Subtarget.is64Bit()) { - MVT LegalSrcVT = VT == MVT::v4i16 ? MVT::v8i8 : MVT::v4i16; - SDLoc DL(N); - A = DAG.getNode(ISD::CONCAT_VECTORS, DL, LegalSrcVT, A, - DAG.getUNDEF(SrcVT)); - B = DAG.getNode(ISD::CONCAT_VECTORS, DL, LegalSrcVT, B, - DAG.getUNDEF(SrcVT)); + SDLoc DL(N); + if (!Subtarget.is64Bit()) + return DAG.getNode(RV32Opc, DL, VT, A, B); + + MVT LegalSrcVT = VT == MVT::v4i16 ? MVT::v8i8 : MVT::v4i16; + A = DAG.getNode(ISD::CONCAT_VECTORS, DL, LegalSrcVT, A, DAG.getUNDEF(SrcVT)); + B = DAG.getNode(ISD::CONCAT_VECTORS, DL, LegalSrcVT, B, DAG.getUNDEF(SrcVT)); + + if (IsSignedUnsigned) { + SDValue Zero = DAG.getConstant(0, DL, LegalSrcVT); + A = DAG.getNode(RISCVISD::PZIP, DL, LegalSrcVT, A, Zero); + B = DAG.getNode(RISCVISD::PZIP, DL, LegalSrcVT, B, Zero); + return DAG.getNode(RV64Opc, DL, VT, A, B); } - return DAG.getNode(Opc, SDLoc(N), VT, A, B); + SDValue Zip = DAG.getNode(RISCVISD::PZIP, DL, LegalSrcVT, A, B); + return DAG.getNode(RV64Opc, DL, VT, Zip, Zip); } static SDValue performMULCombine(SDNode *N, SelectionDAG &DAG, diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td index db27cc619b6f1..24a3ca8cd7fc8 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td @@ -1845,11 +1845,29 @@ def riscv_wmulsu : RVSDNode<"WMULSU", SDTIntBinHiLoOp>; def SDT_RISCVPackedWideningMul : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<1, 2>, - SDTCisOpSmallerThanOp<1, 0>]>; + SDTCisOpSmallerThanOp<1, 0>, + SDTCisSameNumEltsAs<0, 1>]>; def riscv_pwmul : RVSDNode<"PWMUL", SDT_RISCVPackedWideningMul, [SDNPCommutative]>; def riscv_pwmulu : RVSDNode<"PWMULU", SDT_RISCVPackedWideningMul, [SDNPCommutative]>; def riscv_pwmulsu : RVSDNode<"PWMULSU", SDT_RISCVPackedWideningMul>; +def SDT_RISCVPackedWideningMulByHalves + : SDTypeProfile<1, 2, [SDTCisVec<0>, + SDTCisSameAs<1, 2>, + SDTCisOpSmallerThanOp<1, 0>]>; +def riscv_pmul_h_b01 + : RVSDNode<"PMUL_H_B01", SDT_RISCVPackedWideningMulByHalves>; +def riscv_pmul_w_h01 + : RVSDNode<"PMUL_W_H01", SDT_RISCVPackedWideningMulByHalves>; +def riscv_pmulu_h_b01 + : RVSDNode<"PMULU_H_B01", SDT_RISCVPackedWideningMulByHalves>; +def riscv_pmulu_w_h01 + : RVSDNode<"PMULU_W_H01", SDT_RISCVPackedWideningMulByHalves>; +def riscv_pmulsu_h_b00 + : RVSDNode<"PMULSU_H_B00", SDT_RISCVPackedWideningMulByHalves>; +def riscv_pmulsu_w_h00 + : RVSDNode<"PMULSU_W_H00", SDT_RISCVPackedWideningMulByHalves>; + def SDT_RISCVWideningShiftLeft : SDTypeProfile<2, 2, [SDTCisVT<0, i32>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, @@ -2807,24 +2825,18 @@ let append Predicates = [IsRV64] in { (PACK (MUL_W00 GPR:$rs1, GPR:$rs2), (MUL_W11 GPR:$rs1, GPR:$rs2))>; // Packed widening multiply patterns. - def : Pat<(v4i16 (riscv_pwmul (v8i8 GPR:$rs1), (v8i8 GPR:$rs2))), - (PMUL_H_B01 (ZIP8P GPR:$rs1, GPR:$rs2), - (ZIP8P GPR:$rs1, GPR:$rs2))>; - def : Pat<(v2i32 (riscv_pwmul (v4i16 GPR:$rs1), (v4i16 GPR:$rs2))), - (PMUL_W_H01 (ZIP16P GPR:$rs1, GPR:$rs2), - (ZIP16P GPR:$rs1, GPR:$rs2))>; - def : Pat<(v4i16 (riscv_pwmulu (v8i8 GPR:$rs1), (v8i8 GPR:$rs2))), - (PMULU_H_B01 (ZIP8P GPR:$rs1, GPR:$rs2), - (ZIP8P GPR:$rs1, GPR:$rs2))>; - def : Pat<(v2i32 (riscv_pwmulu (v4i16 GPR:$rs1), (v4i16 GPR:$rs2))), - (PMULU_W_H01 (ZIP16P GPR:$rs1, GPR:$rs2), - (ZIP16P GPR:$rs1, GPR:$rs2))>; - def : Pat<(v4i16 (riscv_pwmulsu (v8i8 GPR:$rs1), (v8i8 GPR:$rs2))), - (PMULSU_H_B00 (ZIP8P GPR:$rs1, (v8i8 X0)), - (ZIP8P GPR:$rs2, (v8i8 X0)))>; - def : Pat<(v2i32 (riscv_pwmulsu (v4i16 GPR:$rs1), (v4i16 GPR:$rs2))), - (PMULSU_W_H00 (ZIP16P GPR:$rs1, (v4i16 X0)), - (ZIP16P GPR:$rs2, (v4i16 X0)))>; + def : Pat<(v4i16 (riscv_pmul_h_b01 (v8i8 GPR:$rs1), (v8i8 GPR:$rs2))), + (PMUL_H_B01 GPR:$rs1, GPR:$rs2)>; + def : Pat<(v2i32 (riscv_pmul_w_h01 (v4i16 GPR:$rs1), (v4i16 GPR:$rs2))), + (PMUL_W_H01 GPR:$rs1, GPR:$rs2)>; + def : Pat<(v4i16 (riscv_pmulu_h_b01 (v8i8 GPR:$rs1), (v8i8 GPR:$rs2))), + (PMULU_H_B01 GPR:$rs1, GPR:$rs2)>; + def : Pat<(v2i32 (riscv_pmulu_w_h01 (v4i16 GPR:$rs1), (v4i16 GPR:$rs2))), + (PMULU_W_H01 GPR:$rs1, GPR:$rs2)>; + def : Pat<(v4i16 (riscv_pmulsu_h_b00 (v8i8 GPR:$rs1), (v8i8 GPR:$rs2))), + (PMULSU_H_B00 GPR:$rs1, GPR:$rs2)>; + def : Pat<(v2i32 (riscv_pmulsu_w_h00 (v4i16 GPR:$rs1), (v4i16 GPR:$rs2))), + (PMULSU_W_H00 GPR:$rs1, GPR:$rs2)>; // 8-bit multiply high patterns // FIXME custom lower _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
