[RISCV][P-ext] Support Packed Saturating Absolute Value. (#207978)
This commit is contained in:
parent
76028e1199
commit
2df2a51c75
10 changed files with 232 additions and 8 deletions
|
|
@ -257,6 +257,14 @@ def pabdsumu_u8x8_u64 : RISCVBuiltin<"uint64_t(_Vector<8, unsigned char>, _Vecto
|
|||
def pabdsumau_u8x8_u32 : RISCVBuiltin<"unsigned int(unsigned int, _Vector<8, unsigned char>, _Vector<8, unsigned char>)">;
|
||||
def pabdsumau_u8x8_u64 : RISCVBuiltin<"uint64_t(uint64_t, _Vector<8, unsigned char>, _Vector<8, unsigned char>)">;
|
||||
|
||||
// Packed Saturating Absolute Value (32-bit)
|
||||
def psabs_i8x4 : RISCVBuiltin<"_Vector<4, signed char>(_Vector<4, signed char>)">;
|
||||
def psabs_i16x2 : RISCVBuiltin<"_Vector<2, short>(_Vector<2, short>)">;
|
||||
|
||||
// Packed Saturating Absolute Value (64-bit)
|
||||
def psabs_i8x8 : RISCVBuiltin<"_Vector<8, signed char>(_Vector<8, signed char>)">;
|
||||
def psabs_i16x4 : RISCVBuiltin<"_Vector<4, short>(_Vector<4, short>)">;
|
||||
|
||||
} // Features = "experimental-p"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
|||
|
|
@ -1258,7 +1258,12 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
|
|||
case RISCV::BI__builtin_riscv_pmerge_u16x4:
|
||||
case RISCV::BI__builtin_riscv_pmerge_i16x4:
|
||||
case RISCV::BI__builtin_riscv_pmerge_u32x2:
|
||||
case RISCV::BI__builtin_riscv_pmerge_i32x2: {
|
||||
case RISCV::BI__builtin_riscv_pmerge_i32x2:
|
||||
// Packed Saturating Absolute Value
|
||||
case RISCV::BI__builtin_riscv_psabs_i8x4:
|
||||
case RISCV::BI__builtin_riscv_psabs_i16x2:
|
||||
case RISCV::BI__builtin_riscv_psabs_i8x8:
|
||||
case RISCV::BI__builtin_riscv_psabs_i16x4: {
|
||||
switch (BuiltinID) {
|
||||
default:
|
||||
llvm_unreachable("unexpected builtin ID");
|
||||
|
|
@ -1344,6 +1349,12 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
|
|||
case RISCV::BI__builtin_riscv_pmerge_i32x2:
|
||||
ID = Intrinsic::riscv_pmerge;
|
||||
break;
|
||||
case RISCV::BI__builtin_riscv_psabs_i8x4:
|
||||
case RISCV::BI__builtin_riscv_psabs_i16x2:
|
||||
case RISCV::BI__builtin_riscv_psabs_i8x8:
|
||||
case RISCV::BI__builtin_riscv_psabs_i16x4:
|
||||
ID = Intrinsic::riscv_psabs;
|
||||
break;
|
||||
}
|
||||
|
||||
IntrinsicTypes = {ResultType};
|
||||
|
|
|
|||
|
|
@ -115,6 +115,11 @@ typedef uint32_t uint32x2_t __attribute__((__vector_size__(8)));
|
|||
return (ty)builtin(__rs1, __rs2, __rd); \
|
||||
}
|
||||
|
||||
#define __packed_psabs(name, ty, builtin) \
|
||||
static __inline__ ty __DEFAULT_FN_ATTRS __riscv_##name(ty __rs1) { \
|
||||
return builtin(__rs1); \
|
||||
}
|
||||
|
||||
/* Packed Reverse: reverse the order of the elements. Lowered to a single
|
||||
* rev8/rev16/ppairoe.* by the backend's packed reverse-shuffle handling. */
|
||||
#define __packed_reverse2(name, ty) \
|
||||
|
|
@ -562,6 +567,14 @@ __packed_abdsum(pabdsumu_u8x8_u64, uint64_t, uint8x8_t, __builtin_riscv_pabdsumu
|
|||
__packed_abdsum_acc(pabdsumau_u8x8_u32, uint32_t, uint8x8_t, __builtin_riscv_pabdsumau_u8x8_u32)
|
||||
__packed_abdsum_acc(pabdsumau_u8x8_u64, uint64_t, uint8x8_t, __builtin_riscv_pabdsumau_u8x8_u64)
|
||||
|
||||
/* Packed Saturating Absolute Value (32-bit) */
|
||||
__packed_psabs(psabs_i8x4, int8x4_t, __builtin_riscv_psabs_i8x4)
|
||||
__packed_psabs(psabs_i16x2, int16x2_t, __builtin_riscv_psabs_i16x2)
|
||||
|
||||
/* Packed Saturating Absolute Value (64-bit) */
|
||||
__packed_psabs(psabs_i8x8, int8x8_t, __builtin_riscv_psabs_i8x8)
|
||||
__packed_psabs(psabs_i16x4, int16x4_t, __builtin_riscv_psabs_i16x4)
|
||||
|
||||
// clang-format on
|
||||
|
||||
#undef __packed_splat2
|
||||
|
|
@ -583,6 +596,7 @@ __packed_abdsum_acc(pabdsumau_u8x8_u64, uint64_t, uint8x8_t, __builtin_riscv_pab
|
|||
#undef __packed_binary_builtin_cast
|
||||
#undef __packed_reduction
|
||||
#undef __packed_merge_builtin
|
||||
#undef __packed_psabs
|
||||
#undef __packed_reverse2
|
||||
#undef __packed_reverse4
|
||||
#undef __packed_reverse8
|
||||
|
|
|
|||
|
|
@ -6947,3 +6947,87 @@ uint32_t test_pabdsumau_u8x8_u32(uint32_t rd, uint8x8_t rs1, uint8x8_t rs2) {
|
|||
uint64_t test_pabdsumau_u8x8_u64(uint64_t rd, uint8x8_t rs1, uint8x8_t rs2) {
|
||||
return __riscv_pabdsumau_u8x8_u64(rd, rs1, rs2);
|
||||
}
|
||||
|
||||
/* Packed Saturating Absolute Value (32-bit) */
|
||||
|
||||
// RV32-LABEL: define dso_local i32 @test_psabs_i8x4(
|
||||
// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]]) #[[ATTR0]] {
|
||||
// RV32-NEXT: [[ENTRY:.*:]]
|
||||
// RV32-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8>
|
||||
// RV32-NEXT: [[TMP1:%.*]] = call <4 x i8> @llvm.riscv.psabs.v4i8(<4 x i8> [[TMP0]])
|
||||
// RV32-NEXT: [[TMP2:%.*]] = bitcast <4 x i8> [[TMP1]] to i32
|
||||
// RV32-NEXT: ret i32 [[TMP2]]
|
||||
//
|
||||
// RV64-LABEL: define dso_local i32 @test_psabs_i8x4(
|
||||
// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]]) #[[ATTR0]] {
|
||||
// RV64-NEXT: [[ENTRY:.*:]]
|
||||
// RV64-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8>
|
||||
// RV64-NEXT: [[TMP1:%.*]] = call <4 x i8> @llvm.riscv.psabs.v4i8(<4 x i8> [[TMP0]])
|
||||
// RV64-NEXT: [[TMP2:%.*]] = bitcast <4 x i8> [[TMP1]] to i32
|
||||
// RV64-NEXT: ret i32 [[TMP2]]
|
||||
//
|
||||
int8x4_t test_psabs_i8x4(int8x4_t rs1) {
|
||||
return __riscv_psabs_i8x4(rs1);
|
||||
}
|
||||
|
||||
// RV32-LABEL: define dso_local i32 @test_psabs_i16x2(
|
||||
// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]]) #[[ATTR0]] {
|
||||
// RV32-NEXT: [[ENTRY:.*:]]
|
||||
// RV32-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <2 x i16>
|
||||
// RV32-NEXT: [[TMP1:%.*]] = call <2 x i16> @llvm.riscv.psabs.v2i16(<2 x i16> [[TMP0]])
|
||||
// RV32-NEXT: [[TMP2:%.*]] = bitcast <2 x i16> [[TMP1]] to i32
|
||||
// RV32-NEXT: ret i32 [[TMP2]]
|
||||
//
|
||||
// RV64-LABEL: define dso_local i32 @test_psabs_i16x2(
|
||||
// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]]) #[[ATTR0]] {
|
||||
// RV64-NEXT: [[ENTRY:.*:]]
|
||||
// RV64-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <2 x i16>
|
||||
// RV64-NEXT: [[TMP1:%.*]] = call <2 x i16> @llvm.riscv.psabs.v2i16(<2 x i16> [[TMP0]])
|
||||
// RV64-NEXT: [[TMP2:%.*]] = bitcast <2 x i16> [[TMP1]] to i32
|
||||
// RV64-NEXT: ret i32 [[TMP2]]
|
||||
//
|
||||
int16x2_t test_psabs_i16x2(int16x2_t rs1) {
|
||||
return __riscv_psabs_i16x2(rs1);
|
||||
}
|
||||
|
||||
/* Packed Saturating Absolute Value (64-bit) */
|
||||
|
||||
// RV32-LABEL: define dso_local i64 @test_psabs_i8x8(
|
||||
// RV32-SAME: i64 noundef [[RS1_COERCE:%.*]]) #[[ATTR0]] {
|
||||
// RV32-NEXT: [[ENTRY:.*:]]
|
||||
// RV32-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8>
|
||||
// RV32-NEXT: [[TMP1:%.*]] = call <8 x i8> @llvm.riscv.psabs.v8i8(<8 x i8> [[TMP0]])
|
||||
// RV32-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to i64
|
||||
// RV32-NEXT: ret i64 [[TMP2]]
|
||||
//
|
||||
// RV64-LABEL: define dso_local i64 @test_psabs_i8x8(
|
||||
// RV64-SAME: i64 noundef [[RS1_COERCE:%.*]]) #[[ATTR0]] {
|
||||
// RV64-NEXT: [[ENTRY:.*:]]
|
||||
// RV64-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8>
|
||||
// RV64-NEXT: [[TMP1:%.*]] = call <8 x i8> @llvm.riscv.psabs.v8i8(<8 x i8> [[TMP0]])
|
||||
// RV64-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to i64
|
||||
// RV64-NEXT: ret i64 [[TMP2]]
|
||||
//
|
||||
int8x8_t test_psabs_i8x8(int8x8_t rs1) {
|
||||
return __riscv_psabs_i8x8(rs1);
|
||||
}
|
||||
|
||||
// RV32-LABEL: define dso_local i64 @test_psabs_i16x4(
|
||||
// RV32-SAME: i64 noundef [[RS1_COERCE:%.*]]) #[[ATTR0]] {
|
||||
// RV32-NEXT: [[ENTRY:.*:]]
|
||||
// RV32-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <4 x i16>
|
||||
// RV32-NEXT: [[TMP1:%.*]] = call <4 x i16> @llvm.riscv.psabs.v4i16(<4 x i16> [[TMP0]])
|
||||
// RV32-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[TMP1]] to i64
|
||||
// RV32-NEXT: ret i64 [[TMP2]]
|
||||
//
|
||||
// RV64-LABEL: define dso_local i64 @test_psabs_i16x4(
|
||||
// RV64-SAME: i64 noundef [[RS1_COERCE:%.*]]) #[[ATTR0]] {
|
||||
// RV64-NEXT: [[ENTRY:.*:]]
|
||||
// RV64-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <4 x i16>
|
||||
// RV64-NEXT: [[TMP1:%.*]] = call <4 x i16> @llvm.riscv.psabs.v4i16(<4 x i16> [[TMP0]])
|
||||
// RV64-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[TMP1]] to i64
|
||||
// RV64-NEXT: ret i64 [[TMP2]]
|
||||
//
|
||||
int16x4_t test_psabs_i16x4(int16x4_t rs1) {
|
||||
return __riscv_psabs_i16x4(rs1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2336,3 +2336,21 @@ uint32_t test_pabdsumau_u8x8_u32(uint32_t rd, uint8x8_t a, uint8x8_t b) {
|
|||
uint64_t test_pabdsumau_u8x8_u64(uint64_t rd, uint8x8_t a, uint8x8_t b) {
|
||||
return __riscv_pabdsumau_u8x8_u64(rd, a, b);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: test_psabs_i8x4:
|
||||
// CHECK: psabs.b
|
||||
int8x4_t test_psabs_i8x4(int8x4_t a) { return __riscv_psabs_i8x4(a); }
|
||||
|
||||
// CHECK-LABEL: test_psabs_i16x2:
|
||||
// CHECK: psabs.h
|
||||
int16x2_t test_psabs_i16x2(int16x2_t a) { return __riscv_psabs_i16x2(a); }
|
||||
|
||||
// CHECK-LABEL: test_psabs_i8x8:
|
||||
// RV32: psabs.db
|
||||
// RV64: psabs.b
|
||||
int8x8_t test_psabs_i8x8(int8x8_t a) { return __riscv_psabs_i8x8(a); }
|
||||
|
||||
// CHECK-LABEL: test_psabs_i16x4:
|
||||
// RV32: psabs.dh
|
||||
// RV64: psabs.h
|
||||
int16x4_t test_psabs_i16x4(int16x4_t a) { return __riscv_psabs_i16x4(a); }
|
||||
|
|
|
|||
|
|
@ -2095,6 +2095,13 @@ class RVPBinaryIntrinsic
|
|||
[LLVMMatchType<0>, llvm_anyvector_ty,
|
||||
LLVMMatchType<1>],
|
||||
[IntrNoMem, IntrSpeculatable]>;
|
||||
|
||||
// Packed Saturating Absolute Value
|
||||
class RVPUnaryIntrinsic
|
||||
: DefaultAttrsIntrinsic<[llvm_anyvector_ty],
|
||||
[LLVMMatchType<0>],
|
||||
[IntrNoMem, IntrSpeculatable]>;
|
||||
def int_riscv_psabs : RVPUnaryIntrinsic;
|
||||
} // TargetPrefix = "riscv"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
|||
|
|
@ -11856,7 +11856,8 @@ SDValue RISCVTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
|
|||
case Intrinsic::riscv_pasub:
|
||||
case Intrinsic::riscv_pasubu:
|
||||
case Intrinsic::riscv_pabd:
|
||||
case Intrinsic::riscv_pabdu: {
|
||||
case Intrinsic::riscv_pabdu:
|
||||
case Intrinsic::riscv_psabs: {
|
||||
unsigned Opc;
|
||||
switch (IntNo) {
|
||||
case Intrinsic::riscv_paadd:
|
||||
|
|
@ -11877,8 +11878,14 @@ SDValue RISCVTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
|
|||
case Intrinsic::riscv_pabdu:
|
||||
Opc = ISD::ABDU;
|
||||
break;
|
||||
case Intrinsic::riscv_psabs:
|
||||
Opc = RISCVISD::PSABS;
|
||||
break;
|
||||
}
|
||||
|
||||
if (IntNo == Intrinsic::riscv_psabs)
|
||||
return DAG.getNode(Opc, DL, Op.getValueType(), Op.getOperand(1));
|
||||
|
||||
return DAG.getNode(Opc, DL, Op.getValueType(), Op.getOperand(1),
|
||||
Op.getOperand(2));
|
||||
}
|
||||
|
|
@ -15882,7 +15889,8 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
|
|||
case Intrinsic::riscv_pssa:
|
||||
case Intrinsic::riscv_paas:
|
||||
case Intrinsic::riscv_pasa:
|
||||
case Intrinsic::riscv_pmerge: {
|
||||
case Intrinsic::riscv_pmerge:
|
||||
case Intrinsic::riscv_psabs: {
|
||||
EVT VT = N->getValueType(0);
|
||||
if (!Subtarget.is64Bit() || (VT != MVT::v4i8 && VT != MVT::v2i16))
|
||||
return;
|
||||
|
|
@ -15907,6 +15915,9 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
|
|||
case Intrinsic::riscv_pabdu:
|
||||
Opc = ISD::ABDU;
|
||||
break;
|
||||
case Intrinsic::riscv_psabs:
|
||||
Opc = RISCVISD::PSABS;
|
||||
break;
|
||||
default:
|
||||
// pas/psa/psas/pssa/paas/pasa and pmerge: re-emit at the widened type
|
||||
// rather than lowering to a generic node.
|
||||
|
|
@ -15918,20 +15929,25 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
|
|||
SDValue Undef = DAG.getUNDEF(VT);
|
||||
SDValue Op0 =
|
||||
DAG.getNode(ISD::CONCAT_VECTORS, DL, WideVT, N->getOperand(1), Undef);
|
||||
SDValue Op1 =
|
||||
DAG.getNode(ISD::CONCAT_VECTORS, DL, WideVT, N->getOperand(2), Undef);
|
||||
SDValue Res;
|
||||
if (Opc == ISD::INTRINSIC_WO_CHAIN) {
|
||||
if (IntNo == Intrinsic::riscv_psabs) {
|
||||
// Unary: v4i8/v2i16 is illegal on RV64, so perform the operation on
|
||||
// the widened (legal) type v8i8/v4i16, then extract the low half.
|
||||
Res = DAG.getNode(Opc, DL, WideVT, Op0);
|
||||
} else if (Opc == ISD::INTRINSIC_WO_CHAIN) {
|
||||
SmallVector<SDValue, 5> Ops;
|
||||
Ops.push_back(N->getOperand(0));
|
||||
Ops.push_back(Op0);
|
||||
Ops.push_back(Op1);
|
||||
Ops.push_back(DAG.getNode(ISD::CONCAT_VECTORS, DL, WideVT,
|
||||
N->getOperand(2), Undef));
|
||||
if (N->getNumOperands() > 3)
|
||||
Ops.push_back(DAG.getNode(ISD::CONCAT_VECTORS, DL, WideVT,
|
||||
N->getOperand(3), Undef));
|
||||
Res = DAG.getNode(Opc, DL, WideVT, Ops);
|
||||
} else {
|
||||
Res = DAG.getNode(Opc, DL, WideVT, Op0, Op1);
|
||||
Res = DAG.getNode(Opc, DL, WideVT, Op0,
|
||||
DAG.getNode(ISD::CONCAT_VECTORS, DL, WideVT,
|
||||
N->getOperand(2), Undef));
|
||||
}
|
||||
Results.push_back(DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, Res,
|
||||
DAG.getVectorIdxConstant(0, DL)));
|
||||
|
|
|
|||
|
|
@ -1754,6 +1754,11 @@ class PatGprPairGprPair<SDPatternOperator OpNode, RVInst Inst, ValueType vt>
|
|||
: Pat<(vt (OpNode (vt GPRPair:$rs1), (vt GPRPair:$rs2))),
|
||||
(Inst GPRPair:$rs1, GPRPair:$rs2)>;
|
||||
|
||||
// Unary GPRPair operation, one source register pair.
|
||||
class PatGprPair<SDPatternOperator OpNode, RVInst Inst, ValueType vt>
|
||||
: Pat<(vt (OpNode (vt GPRPair:$rs1))),
|
||||
(Inst GPRPair:$rs1)>;
|
||||
|
||||
// Reduction sum. PatRedSum is the single-GPR source (predsum.bs/hs/ws), result
|
||||
// XLenVT; PatRedSumPair is the RV32 paired source (predsum.dbs/dhs), result i32.
|
||||
// Target-illegal results (i32 accumulator on RV64, i64 on RV32) don't reach
|
||||
|
|
@ -1898,6 +1903,11 @@ def SDT_RISCVPPairE_DB : SDTypeProfile<2, 4, [SDTCisVT<0, v4i8>,
|
|||
SDTCisSameAs<0, 5>]>;
|
||||
def riscv_ppaire_db : RVSDNode<"PPAIRE_DB", SDT_RISCVPPairE_DB>;
|
||||
|
||||
// signed-saturating abs of each lane; an INT_MIN lane maps to INT_MAX.
|
||||
def SDT_RISCVPackedUnary : SDTypeProfile<1, 1, [SDTCisVec<0>,
|
||||
SDTCisSameAs<0, 1>]>;
|
||||
def riscv_psabs : RVSDNode<"PSABS", SDT_RISCVPackedUnary>;
|
||||
|
||||
// Add one to the immediate. Used by RISCVISD::SATI.
|
||||
def IncImm : SDNodeXForm<imm, [{
|
||||
return CurDAG->getTargetConstant(N->getZExtValue() + 1, SDLoc(N),
|
||||
|
|
@ -2118,6 +2128,10 @@ let Predicates = [HasStdExtP] in {
|
|||
def : PatGprGpr<smax, PMAX_H, XLenVecI16VT>;
|
||||
def : PatGprGpr<umax, PMAXU_H, XLenVecI16VT>;
|
||||
|
||||
// 8/16-bit saturating absolute value patterns
|
||||
def : PatGpr<riscv_psabs, PSABS_B, XLenVecI8VT>;
|
||||
def : PatGpr<riscv_psabs, PSABS_H, XLenVecI16VT>;
|
||||
|
||||
// 8/16-bit vselect patterns
|
||||
def : Pat<(XLenVecI8VT (vselect (XLenVecI8VT GPR:$mask), GPR:$true_v, GPR:$false_v)),
|
||||
(MERGE GPR:$mask, GPR:$false_v, GPR:$true_v)>;
|
||||
|
|
@ -2449,6 +2463,10 @@ let append Predicates = [IsRV32] in {
|
|||
def : PatGprPairGprPair<smax, PMAX_DW, v2i32>;
|
||||
def : PatGprPairGprPair<umax, PMAXU_DW, v2i32>;
|
||||
|
||||
// 8/16-bit saturating absolute value patterns
|
||||
def : PatGprPair<riscv_psabs, PSABS_DB, v8i8>;
|
||||
def : PatGprPair<riscv_psabs, PSABS_DH, v4i16>;
|
||||
|
||||
// 16-bit bswap patterns
|
||||
def : Pat<(v4i16 (bswap GPRPair:$rs)),
|
||||
(PPAIROE_DB GPRPair:$rs, GPRPair:$rs)>;
|
||||
|
|
|
|||
|
|
@ -2664,3 +2664,22 @@ define i32 @test_pabdsumau_u8x4_u32(i32 %rd, <4 x i8> %a, <4 x i8> %b) {
|
|||
%res = call i32 @llvm.riscv.pabdsumau.i32.v4i8(i32 %rd, <4 x i8> %a, <4 x i8> %b)
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Packed Saturating Absolute Value
|
||||
define <4 x i8> @test_psabs_v4i8(<4 x i8> %a) {
|
||||
; CHECK-LABEL: test_psabs_v4i8:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: psabs.b a0, a0
|
||||
; CHECK-NEXT: ret
|
||||
%res = call <4 x i8> @llvm.riscv.psabs.v4i8(<4 x i8> %a)
|
||||
ret <4 x i8> %res
|
||||
}
|
||||
|
||||
define <2 x i16> @test_psabs_v2i16(<2 x i16> %a) {
|
||||
; CHECK-LABEL: test_psabs_v2i16:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: psabs.h a0, a0
|
||||
; CHECK-NEXT: ret
|
||||
%res = call <2 x i16> @llvm.riscv.psabs.v2i16(<2 x i16> %a)
|
||||
ret <2 x i16> %res
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5817,3 +5817,32 @@ define i64 @test_pabdsumau_u8x8_u64(i64 %rd, <8 x i8> %a, <8 x i8> %b) {
|
|||
%res = call i64 @llvm.riscv.pabdsumau.i64.v8i8(i64 %rd, <8 x i8> %a, <8 x i8> %b)
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Packed Saturating Absolute Value
|
||||
define <8 x i8> @test_psabs_v8i8(<8 x i8> %a) {
|
||||
; RV32-LABEL: test_psabs_v8i8:
|
||||
; RV32: # %bb.0:
|
||||
; RV32-NEXT: psabs.db a0, a0
|
||||
; RV32-NEXT: ret
|
||||
;
|
||||
; RV64-LABEL: test_psabs_v8i8:
|
||||
; RV64: # %bb.0:
|
||||
; RV64-NEXT: psabs.b a0, a0
|
||||
; RV64-NEXT: ret
|
||||
%res = call <8 x i8> @llvm.riscv.psabs.v8i8(<8 x i8> %a)
|
||||
ret <8 x i8> %res
|
||||
}
|
||||
|
||||
define <4 x i16> @test_psabs_v4i16(<4 x i16> %a) {
|
||||
; RV32-LABEL: test_psabs_v4i16:
|
||||
; RV32: # %bb.0:
|
||||
; RV32-NEXT: psabs.dh a0, a0
|
||||
; RV32-NEXT: ret
|
||||
;
|
||||
; RV64-LABEL: test_psabs_v4i16:
|
||||
; RV64: # %bb.0:
|
||||
; RV64-NEXT: psabs.h a0, a0
|
||||
; RV64-NEXT: ret
|
||||
%res = call <4 x i16> @llvm.riscv.psabs.v4i16(<4 x i16> %a)
|
||||
ret <4 x i16> %res
|
||||
}
|
||||
Loading…
Reference in a new issue