[llvm] [RISCV][P-ext] Add packed sign and zero extend intrinsics (PR #208685)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 10 03:18:56 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-ir
Author: SiHuaN (sihuan)
<details>
<summary>Changes</summary>
Add SelectionDAG support for RISC-V P packed sign and zero extend operations.
This adds:
- `riscv_pzext_inreg` target node for packed zero-extend-in-reg.
- DAG combine for packed `and` masks such as `(and vXi16, 0xff)` and `(and vXi32, 0xffff)`.
- `sext_inreg` and `riscv_pzext_inreg` patterns for `psext.*` / `pzext.*`.
- LLVM IR intrinsics:
- `llvm.riscv.psext.b`
- `llvm.riscv.psext.h`
- `llvm.riscv.pzext.b`
- `llvm.riscv.pzext.h`
For RV64 32-bit packed intrinsic results, the lowering widens to the legal
64-bit packed type and extracts the low subvector after lowering.
Unsupported intrinsic forms are rejected during lowering instead of being left
for instruction selection.
Tests cover RV32 and RV64 codegen for the plain IR combine paths, the new LLVM
IR intrinsics, and invalid intrinsic forms.
---
Full diff: https://github.com/llvm/llvm-project/pull/208685.diff
6 Files Affected:
- (modified) llvm/include/llvm/IR/IntrinsicsRISCV.td (+10)
- (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+86-4)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoP.td (+32-4)
- (modified) llvm/test/CodeGen/RISCV/rvp-simd-32.ll (+38)
- (modified) llvm/test/CodeGen/RISCV/rvp-simd-64.ll (+144)
- (added) llvm/test/CodeGen/RISCV/rvp-simd-intrinsic-invalid.ll (+39)
``````````diff
diff --git a/llvm/include/llvm/IR/IntrinsicsRISCV.td b/llvm/include/llvm/IR/IntrinsicsRISCV.td
index 28cde8111241c..eb4c19f150d99 100644
--- a/llvm/include/llvm/IR/IntrinsicsRISCV.td
+++ b/llvm/include/llvm/IR/IntrinsicsRISCV.td
@@ -2085,6 +2085,16 @@ class RVPBinaryIntrinsic
[IntrNoMem, IntrSpeculatable]>;
def int_riscv_pmerge : RVPTernaryIntrinsic;
+ // Packed Sign and Zero Extend.
+ class RVPExtIntrinsic
+ : DefaultAttrsIntrinsic<[llvm_anyvector_ty],
+ [LLVMMatchType<0>],
+ [IntrNoMem, IntrSpeculatable]>;
+ def int_riscv_psext_b : RVPExtIntrinsic;
+ def int_riscv_psext_h : RVPExtIntrinsic;
+ def int_riscv_pzext_b : RVPExtIntrinsic;
+ def int_riscv_pzext_h : RVPExtIntrinsic;
+
// 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 fda994a04b00f..0b11d50f5d7e4 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -680,11 +680,11 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
{MVT::v4i16, MVT::v2i32}, Legal);
setOperationAction(ISD::ANY_EXTEND_VECTOR_INREG, {MVT::v4i16, MVT::v2i32},
Custom);
- // LegalizeVectorOps uses result VT, LegalizeDAG uses ExtVT.
- setOperationAction(ISD::SIGN_EXTEND_INREG,
- {MVT::v2i16, MVT::v4i8, MVT::v2i32, MVT::v4i16},
- Legal);
}
+ // LegalizeVectorOps uses result VT, LegalizeDAG uses ExtVT.
+ setOperationAction(
+ ISD::SIGN_EXTEND_INREG,
+ {MVT::v2i8, MVT::v4i8, MVT::v2i16, MVT::v4i16, MVT::v2i32}, Legal);
}
if (Subtarget.hasStdExtZfbfmin()) {
@@ -11920,6 +11920,35 @@ SDValue RISCVTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
return DAG.getNode(Opc, DL, Op.getValueType(), Op.getOperand(1),
Op.getOperand(2));
}
+ case Intrinsic::riscv_psext_b:
+ case Intrinsic::riscv_psext_h: {
+ EVT VT = Op.getValueType();
+ if (!VT.isSimple() || !Subtarget.isPExtPackedType(VT.getSimpleVT()))
+ reportFatalUsageError("unsupported llvm.riscv.psext intrinsic");
+
+ MVT SimpleVT = VT.getSimpleVT();
+ unsigned SrcEltBits = IntNo == Intrinsic::riscv_psext_b ? 8 : 16;
+ if (SrcEltBits >= SimpleVT.getScalarSizeInBits())
+ reportFatalUsageError("unsupported llvm.riscv.psext intrinsic");
+
+ MVT ExtVT = MVT::getVectorVT(MVT::getIntegerVT(SrcEltBits),
+ SimpleVT.getVectorElementCount());
+ return DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, SimpleVT, Op.getOperand(1),
+ DAG.getValueType(ExtVT));
+ }
+ case Intrinsic::riscv_pzext_b:
+ case Intrinsic::riscv_pzext_h: {
+ EVT VT = Op.getValueType();
+ if (!VT.isSimple() || !Subtarget.isPExtPackedType(VT.getSimpleVT()))
+ reportFatalUsageError("unsupported llvm.riscv.pzext intrinsic");
+
+ MVT SimpleVT = VT.getSimpleVT();
+ unsigned SrcEltBits = IntNo == Intrinsic::riscv_pzext_b ? 8 : 16;
+ if (SimpleVT.getScalarSizeInBits() != SrcEltBits * 2)
+ reportFatalUsageError("unsupported llvm.riscv.pzext intrinsic");
+
+ return DAG.getNode(RISCVISD::PZEXT_INREG, DL, SimpleVT, Op.getOperand(1));
+ }
case Intrinsic::riscv_pabdsumu:
case Intrinsic::riscv_pabdsumau: {
// On RV32 an i32-result absolute difference sum over a 64-bit (GPRPair)
@@ -15936,6 +15965,34 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Res));
return;
}
+ case Intrinsic::riscv_psext_h:
+ reportFatalUsageError("unsupported llvm.riscv.psext intrinsic");
+ case Intrinsic::riscv_pzext_h: {
+ reportFatalUsageError("unsupported llvm.riscv.pzext intrinsic");
+ }
+ case Intrinsic::riscv_psext_b:
+ case Intrinsic::riscv_pzext_b: {
+ bool IsSExt = IntNo == Intrinsic::riscv_psext_b;
+ const char *UnsupportedMsg =
+ IsSExt ? "unsupported llvm.riscv.psext intrinsic"
+ : "unsupported llvm.riscv.pzext intrinsic";
+ EVT VT = N->getValueType(0);
+ if (!Subtarget.is64Bit() || VT != MVT::v2i16)
+ reportFatalUsageError(UnsupportedMsg);
+
+ SDValue Undef = DAG.getUNDEF(VT);
+ SDValue Src = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v4i16,
+ N->getOperand(1), Undef);
+ SDValue Res;
+ if (IsSExt)
+ Res = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::v4i16, Src,
+ DAG.getValueType(MVT::v4i8));
+ else
+ Res = DAG.getNode(RISCVISD::PZEXT_INREG, DL, MVT::v4i16, Src);
+ Results.push_back(DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, Res,
+ DAG.getVectorIdxConstant(0, DL)));
+ return;
+ }
case Intrinsic::riscv_paadd:
case Intrinsic::riscv_paaddu:
case Intrinsic::riscv_pasub:
@@ -17511,6 +17568,29 @@ static SDValue combineNarrowableShiftedLoad(SDNode *N, SelectionDAG &DAG) {
DAG.getShiftAmountConstant(ShiftAmt, VT, DL));
}
+static SDValue combinePZExtInReg(SDNode *N, SelectionDAG &DAG,
+ const RISCVSubtarget &Subtarget) {
+ EVT VT = N->getValueType(0);
+ if (!VT.isSimple())
+ return SDValue();
+
+ MVT SimpleVT = VT.getSimpleVT();
+ if (!Subtarget.isPExtPackedType(SimpleVT))
+ return SDValue();
+
+ APInt SplatVal;
+ if (!ISD::isConstantSplatVector(N->getOperand(1).getNode(), SplatVal))
+ return SDValue();
+
+ MVT EltVT = SimpleVT.getVectorElementType();
+ bool IsByteToHalf = EltVT == MVT::i16 && SplatVal == 0xff;
+ bool IsHalfToWord = EltVT == MVT::i32 && SplatVal == 0xffff;
+ if (!IsByteToHalf && !IsHalfToWord)
+ return SDValue();
+
+ return DAG.getNode(RISCVISD::PZEXT_INREG, SDLoc(N), VT, N->getOperand(0));
+}
+
// Combines two comparison operation and logic operation to one selection
// operation(min, max) and logic operation. Returns new constructed Node if
// conditions for optimization are satisfied.
@@ -17519,6 +17599,8 @@ static SDValue performANDCombine(SDNode *N,
const RISCVSubtarget &Subtarget) {
SelectionDAG &DAG = DCI.DAG;
SDValue N0 = N->getOperand(0);
+ if (SDValue V = combinePZExtInReg(N, DAG, Subtarget))
+ return V;
// Pre-promote (i32 (and (srl X, Y), 1)) on RV64 with Zbs without zero
// extending X. This is safe since we only need the LSB after the shift and
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index 7fa7c96ca99ca..6d19538131cdb 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -1894,6 +1894,12 @@ def SDT_RISCVMERGE : SDTypeProfile<1, 3, [SDTCisInt<0>,
SDTCisSameAs<0, 3>]>;
def riscv_merge : RVSDNode<"MERGE", SDT_RISCVMERGE>;
+// (and vXi16:$rs1, 0xff) / (and vXi32:$rs1, 0xffff) zero extends the low
+// subelement in each packed element.
+def SDT_RISCVPZExtInReg : SDTypeProfile<1, 1, [SDTCisVec<0>,
+ SDTCisSameAs<0, 1>]>;
+def riscv_pzext_inreg : RVSDNode<"PZEXT_INREG", SDT_RISCVPZExtInReg>;
+
// (rdlo, rdhi) PPAIRE_DB (rs1plo, rs1phi, rs2plo, rs2phi)
def SDT_RISCVPPairE_DB : SDTypeProfile<2, 4, [SDTCisVT<0, v4i8>,
SDTCisSameAs<0, 1>,
@@ -2483,6 +2489,21 @@ let append Predicates = [IsRV32] in {
def : PatGprPair<riscv_psabs, PSABS_DB, v8i8>;
def : PatGprPair<riscv_psabs, PSABS_DH, v4i16>;
+ // Packed sign and zero extend patterns
+ // Sign extend inreg patterns using psext. sext_invec is lowered to
+ // zext_invec+sext_inreg.
+ def : Pat<(v2i16 (sext_inreg GPR:$rs1, v2i8)), (PSEXT_H_B GPR:$rs1)>;
+ def : Pat<(v4i16 (sext_inreg GPRPair:$rs1, v4i8)), (PSEXT_DH_B GPRPair:$rs1)>;
+ def : Pat<(v2i32 (sext_inreg GPRPair:$rs1, v2i8)), (PSEXT_DW_B GPRPair:$rs1)>;
+ def : Pat<(v2i32 (sext_inreg GPRPair:$rs1, v2i16)),
+ (PSEXT_DW_H GPRPair:$rs1)>;
+ def : Pat<(riscv_pzext_inreg (v2i16 GPR:$rs1)),
+ (PPAIRE_B GPR:$rs1, (v4i8 X0))>;
+ def : Pat<(riscv_pzext_inreg (v4i16 GPRPair:$rs1)),
+ (PPAIRE_DB GPRPair:$rs1, (v8i8 X0_Pair))>;
+ def : Pat<(riscv_pzext_inreg (v2i32 GPRPair:$rs1)),
+ (PPAIRE_DH GPRPair:$rs1, (v4i16 X0_Pair))>;
+
// 16-bit bswap patterns
def : Pat<(v4i16 (bswap GPRPair:$rs)),
(PPAIROE_DB GPRPair:$rs, GPRPair:$rs)>;
@@ -2706,6 +2727,17 @@ let append Predicates = [IsRV64] in {
def : Pat<(v2i32 (vselect (v2i32 GPR:$mask), GPR:$true_v, GPR:$false_v)),
(MERGE GPR:$mask, GPR:$false_v, GPR:$true_v)>;
+ // Packed sign and zero extend patterns
+ // Sign extend inreg patterns using psext. sext_invec is lowered to
+ // zext_invec+sext_inreg.
+ def : Pat<(v4i16 (sext_inreg GPR:$rs1, v4i8)), (PSEXT_H_B GPR:$rs1)>;
+ def : Pat<(v2i32 (sext_inreg GPR:$rs1, v2i8)), (PSEXT_W_B GPR:$rs1)>;
+ def : Pat<(v2i32 (sext_inreg GPR:$rs1, v2i16)), (PSEXT_W_H GPR:$rs1)>;
+ def : Pat<(riscv_pzext_inreg (v4i16 GPR:$rs1)),
+ (PPAIRE_B GPR:$rs1, (v8i8 X0))>;
+ def : Pat<(riscv_pzext_inreg (v2i32 GPR:$rs1)),
+ (PPAIRE_H GPR:$rs1, (v4i16 X0))>;
+
// 32-bit bswap patterns
def : Pat<(v2i32 (bswap GPR:$rs)),
(PPAIROE_W (REV8_RV64 GPR:$rs), (REV8_RV64 GPR:$rs))>;
@@ -2770,9 +2802,5 @@ let append Predicates = [IsRV64] in {
(ZIP8P GPR:$rs1, GPR:$rs2)>;
def : Pat<(v4i16 (riscv_pzip (v4i16 GPR:$rs1), (v4i16 GPR:$rs2))),
(ZIP16P GPR:$rs1, GPR:$rs2)>;
- // Sign extend inreg patterns using psext. sext_invec is lowered to
- // zext_invec+sext_inreg.
- def : Pat<(v4i16 (sext_inreg GPR:$rs1, v4i8)), (PSEXT_H_B GPR:$rs1)>;
- def : Pat<(v2i32 (sext_inreg GPR:$rs1, v2i16)), (PSEXT_W_H GPR:$rs1)>;
} // append Predicates = [IsRV64]
} // Predicates = [HasStdExtP]
diff --git a/llvm/test/CodeGen/RISCV/rvp-simd-32.ll b/llvm/test/CodeGen/RISCV/rvp-simd-32.ll
index 48c7b3b14847e..ea74f1870fb1b 100644
--- a/llvm/test/CodeGen/RISCV/rvp-simd-32.ll
+++ b/llvm/test/CodeGen/RISCV/rvp-simd-32.ll
@@ -2632,6 +2632,44 @@ define <2 x i16> @test_pmerge_mvmn_i16x2(<2 x i16> %rs2, <2 x i16> %rs1, <2 x i1
ret <2 x i16> %res
}
+; Packed sign and zero extend
+define <2 x i16> @test_psext_b_v2i16(<2 x i16> %a) {
+; CHECK-LABEL: test_psext_b_v2i16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: psext.h.b a0, a0
+; CHECK-NEXT: ret
+ %shl = shl <2 x i16> %a, splat (i16 8)
+ %res = ashr <2 x i16> %shl, splat (i16 8)
+ ret <2 x i16> %res
+}
+
+define <2 x i16> @test_pzext_b_v2i16(<2 x i16> %a) {
+; CHECK-LABEL: test_pzext_b_v2i16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pzext.h.b a0, a0
+; CHECK-NEXT: ret
+ %res = and <2 x i16> %a, splat (i16 255)
+ ret <2 x i16> %res
+}
+
+define <2 x i16> @test_riscv_psext_b_v2i16(<2 x i16> %a) {
+; CHECK-LABEL: test_riscv_psext_b_v2i16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: psext.h.b a0, a0
+; CHECK-NEXT: ret
+ %res = call <2 x i16> @llvm.riscv.psext.b.v2i16(<2 x i16> %a)
+ ret <2 x i16> %res
+}
+
+define <2 x i16> @test_riscv_pzext_b_v2i16(<2 x i16> %a) {
+; CHECK-LABEL: test_riscv_pzext_b_v2i16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pzext.h.b a0, a0
+; CHECK-NEXT: ret
+ %res = call <2 x i16> @llvm.riscv.pzext.b.v2i16(<2 x i16> %a)
+ ret <2 x i16> %res
+}
+
; Packed absolute difference sum
define i32 @test_pabdsumu_u8x4_u32(<4 x i8> %a, <4 x i8> %b) {
; RV32-LABEL: test_pabdsumu_u8x4_u32:
diff --git a/llvm/test/CodeGen/RISCV/rvp-simd-64.ll b/llvm/test/CodeGen/RISCV/rvp-simd-64.ll
index 9cbd64717c1d5..c4acd4ce17f34 100644
--- a/llvm/test/CodeGen/RISCV/rvp-simd-64.ll
+++ b/llvm/test/CodeGen/RISCV/rvp-simd-64.ll
@@ -5755,6 +5755,150 @@ define <2 x i32> @test_pmerge_mvmn_i32x2(<2 x i32> %rs2, <2 x i32> %rs1, <2 x i3
ret <2 x i32> %res
}
+; Packed sign and zero extend
+define <4 x i16> @test_psext_b_v4i16(<4 x i16> %a) {
+; RV32-LABEL: test_psext_b_v4i16:
+; RV32: # %bb.0:
+; RV32-NEXT: psext.dh.b a0, a0
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_psext_b_v4i16:
+; RV64: # %bb.0:
+; RV64-NEXT: psext.h.b a0, a0
+; RV64-NEXT: ret
+ %shl = shl <4 x i16> %a, splat (i16 8)
+ %res = ashr <4 x i16> %shl, splat (i16 8)
+ ret <4 x i16> %res
+}
+
+define <2 x i32> @test_psext_b_v2i32(<2 x i32> %a) {
+; RV32-LABEL: test_psext_b_v2i32:
+; RV32: # %bb.0:
+; RV32-NEXT: psext.dw.b a0, a0
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_psext_b_v2i32:
+; RV64: # %bb.0:
+; RV64-NEXT: psext.w.b a0, a0
+; RV64-NEXT: ret
+ %shl = shl <2 x i32> %a, splat (i32 24)
+ %res = ashr <2 x i32> %shl, splat (i32 24)
+ ret <2 x i32> %res
+}
+
+define <2 x i32> @test_psext_h_v2i32(<2 x i32> %a) {
+; RV32-LABEL: test_psext_h_v2i32:
+; RV32: # %bb.0:
+; RV32-NEXT: psext.dw.h a0, a0
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_psext_h_v2i32:
+; RV64: # %bb.0:
+; RV64-NEXT: psext.w.h a0, a0
+; RV64-NEXT: ret
+ %shl = shl <2 x i32> %a, splat (i32 16)
+ %res = ashr <2 x i32> %shl, splat (i32 16)
+ ret <2 x i32> %res
+}
+
+define <4 x i16> @test_pzext_b_v4i16(<4 x i16> %a) {
+; RV32-LABEL: test_pzext_b_v4i16:
+; RV32: # %bb.0:
+; RV32-NEXT: pzext.dh.b a0, a0
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_pzext_b_v4i16:
+; RV64: # %bb.0:
+; RV64-NEXT: pzext.h.b a0, a0
+; RV64-NEXT: ret
+ %res = and <4 x i16> %a, splat (i16 255)
+ ret <4 x i16> %res
+}
+
+define <2 x i32> @test_pzext_h_v2i32(<2 x i32> %a) {
+; RV32-LABEL: test_pzext_h_v2i32:
+; RV32: # %bb.0:
+; RV32-NEXT: pzext.dw.h a0, a0
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_pzext_h_v2i32:
+; RV64: # %bb.0:
+; RV64-NEXT: pzext.w.h a0, a0
+; RV64-NEXT: ret
+ %res = and <2 x i32> %a, splat (i32 65535)
+ ret <2 x i32> %res
+}
+
+define <4 x i16> @test_riscv_psext_b_v4i16(<4 x i16> %a) {
+; RV32-LABEL: test_riscv_psext_b_v4i16:
+; RV32: # %bb.0:
+; RV32-NEXT: psext.dh.b a0, a0
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_riscv_psext_b_v4i16:
+; RV64: # %bb.0:
+; RV64-NEXT: psext.h.b a0, a0
+; RV64-NEXT: ret
+ %res = call <4 x i16> @llvm.riscv.psext.b.v4i16(<4 x i16> %a)
+ ret <4 x i16> %res
+}
+
+define <2 x i32> @test_riscv_psext_b_v2i32(<2 x i32> %a) {
+; RV32-LABEL: test_riscv_psext_b_v2i32:
+; RV32: # %bb.0:
+; RV32-NEXT: psext.dw.b a0, a0
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_riscv_psext_b_v2i32:
+; RV64: # %bb.0:
+; RV64-NEXT: psext.w.b a0, a0
+; RV64-NEXT: ret
+ %res = call <2 x i32> @llvm.riscv.psext.b.v2i32(<2 x i32> %a)
+ ret <2 x i32> %res
+}
+
+define <2 x i32> @test_riscv_psext_h_v2i32(<2 x i32> %a) {
+; RV32-LABEL: test_riscv_psext_h_v2i32:
+; RV32: # %bb.0:
+; RV32-NEXT: psext.dw.h a0, a0
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_riscv_psext_h_v2i32:
+; RV64: # %bb.0:
+; RV64-NEXT: psext.w.h a0, a0
+; RV64-NEXT: ret
+ %res = call <2 x i32> @llvm.riscv.psext.h.v2i32(<2 x i32> %a)
+ ret <2 x i32> %res
+}
+
+define <4 x i16> @test_riscv_pzext_b_v4i16(<4 x i16> %a) {
+; RV32-LABEL: test_riscv_pzext_b_v4i16:
+; RV32: # %bb.0:
+; RV32-NEXT: pzext.dh.b a0, a0
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_riscv_pzext_b_v4i16:
+; RV64: # %bb.0:
+; RV64-NEXT: pzext.h.b a0, a0
+; RV64-NEXT: ret
+ %res = call <4 x i16> @llvm.riscv.pzext.b.v4i16(<4 x i16> %a)
+ ret <4 x i16> %res
+}
+
+define <2 x i32> @test_riscv_pzext_h_v2i32(<2 x i32> %a) {
+; RV32-LABEL: test_riscv_pzext_h_v2i32:
+; RV32: # %bb.0:
+; RV32-NEXT: pzext.dw.h a0, a0
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_riscv_pzext_h_v2i32:
+; RV64: # %bb.0:
+; RV64-NEXT: pzext.w.h a0, a0
+; RV64-NEXT: ret
+ %res = call <2 x i32> @llvm.riscv.pzext.h.v2i32(<2 x i32> %a)
+ ret <2 x i32> %res
+}
+
; Packed absolute difference sum
define i32 @test_pabdsumu_u8x8_u32(<8 x i8> %a, <8 x i8> %b) {
; RV32-LABEL: test_pabdsumu_u8x8_u32:
diff --git a/llvm/test/CodeGen/RISCV/rvp-simd-intrinsic-invalid.ll b/llvm/test/CodeGen/RISCV/rvp-simd-intrinsic-invalid.ll
new file mode 100644
index 0000000000000..28b1d7c53a6e7
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rvp-simd-intrinsic-invalid.ll
@@ -0,0 +1,39 @@
+; RUN: sed -n '/^; BEGIN-PSEXT-LEGAL$/,/^; END-PSEXT-LEGAL$/p' %s \
+; RUN: | not llc -mtriple=riscv64 -mattr=+experimental-p,+m,+zbb \
+; RUN: -o /dev/null 2>&1 | FileCheck %s --check-prefix=PSEXT
+; RUN: sed -n '/^; BEGIN-PSEXT-WIDEN$/,/^; END-PSEXT-WIDEN$/p' %s \
+; RUN: | not llc -mtriple=riscv64 -mattr=+experimental-p,+m,+zbb \
+; RUN: -o /dev/null 2>&1 | FileCheck %s --check-prefix=PSEXT
+; RUN: sed -n '/^; BEGIN-PZEXT$/,/^; END-PZEXT$/p' %s \
+; RUN: | not llc -mtriple=riscv64 -mattr=+experimental-p,+m,+zbb \
+; RUN: -o /dev/null 2>&1 | FileCheck %s --check-prefix=PZEXT
+
+; PSEXT: LLVM ERROR: unsupported llvm.riscv.psext intrinsic
+; PZEXT: LLVM ERROR: unsupported llvm.riscv.pzext intrinsic
+
+; BEGIN-PSEXT-LEGAL
+define <4 x i16> @bad_psext_legal_type(<4 x i16> %a) {
+ %res = call <4 x i16> @llvm.riscv.psext.h.v4i16(<4 x i16> %a)
+ ret <4 x i16> %res
+}
+
+declare <4 x i16> @llvm.riscv.psext.h.v4i16(<4 x i16>)
+; END-PSEXT-LEGAL
+
+; BEGIN-PSEXT-WIDEN
+define <2 x i16> @bad_psext_widen_type(<2 x i16> %a) {
+ %res = call <2 x i16> @llvm.riscv.psext.h.v2i16(<2 x i16> %a)
+ ret <2 x i16> %res
+}
+
+declare <2 x i16> @llvm.riscv.psext.h.v2i16(<2 x i16>)
+; END-PSEXT-WIDEN
+
+; BEGIN-PZEXT
+define <2 x i32> @bad_pzext(<2 x i32> %a) {
+ %res = call <2 x i32> @llvm.riscv.pzext.b.v2i32(<2 x i32> %a)
+ ret <2 x i32> %res
+}
+
+declare <2 x i32> @llvm.riscv.pzext.b.v2i32(<2 x i32>)
+; END-PZEXT
``````````
</details>
https://github.com/llvm/llvm-project/pull/208685
More information about the llvm-commits
mailing list