diff --git a/src/coreclr/jit/emitarm64sve.cpp b/src/coreclr/jit/emitarm64sve.cpp index 99e86bb38c15c..3afae796d1ab4 100644 --- a/src/coreclr/jit/emitarm64sve.cpp +++ b/src/coreclr/jit/emitarm64sve.cpp @@ -2727,6 +2727,7 @@ void emitter::emitInsSve_R_R_I(instruction ins, if (sopt == INS_SCALABLE_OPTS_WITH_VECTOR_PAIR) { fmt = IF_SVE_BQ_2A; + unreached(); // Not supported yet. } else { diff --git a/src/coreclr/jit/hwintrinsic.cpp b/src/coreclr/jit/hwintrinsic.cpp index 474fc667226f6..0b963d23e39a5 100644 --- a/src/coreclr/jit/hwintrinsic.cpp +++ b/src/coreclr/jit/hwintrinsic.cpp @@ -1900,27 +1900,40 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, { assert(numArgs > 0); GenTree* op1 = retNode->AsHWIntrinsic()->Op(1); - if (intrinsic == NI_Sve_ConditionalSelect) + + switch (intrinsic) { - if (op1->IsVectorAllBitsSet() || op1->IsMaskAllBitsSet()) - { - return retNode->AsHWIntrinsic()->Op(2); - } - else if (op1->IsVectorZero()) + case NI_Sve_ConditionalSelect: { - return retNode->AsHWIntrinsic()->Op(3); + if (op1->IsVectorAllBitsSet() || op1->IsMaskAllBitsSet()) + { + return retNode->AsHWIntrinsic()->Op(2); + } + else if (op1->IsVectorZero()) + { + return retNode->AsHWIntrinsic()->Op(3); + } + break; } - } - else if (intrinsic == NI_Sve_GetActiveElementCount) - { - GenTree* op2 = retNode->AsHWIntrinsic()->Op(2); - // HWInstrinsic requires a mask for op2 - if (!varTypeIsMask(op2)) + case NI_Sve_GetActiveElementCount: + case NI_Sve_TestAnyTrue: + case NI_Sve_TestFirstTrue: + case NI_Sve_TestLastTrue: { - retNode->AsHWIntrinsic()->Op(2) = - gtNewSimdCvtVectorToMaskNode(TYP_MASK, op2, simdBaseJitType, simdSize); + GenTree* op2 = retNode->AsHWIntrinsic()->Op(2); + + // HWInstrinsic requires a mask for op2 + if (!varTypeIsMask(op2)) + { + retNode->AsHWIntrinsic()->Op(2) = + gtNewSimdCvtVectorToMaskNode(TYP_MASK, op2, simdBaseJitType, simdSize); + } + break; } + + default: + break; } if (!varTypeIsMask(op1)) diff --git a/src/coreclr/jit/hwintrinsicarm64.cpp b/src/coreclr/jit/hwintrinsicarm64.cpp index 63ba7e31df798..765f433e614ee 100644 --- a/src/coreclr/jit/hwintrinsicarm64.cpp +++ b/src/coreclr/jit/hwintrinsicarm64.cpp @@ -403,6 +403,7 @@ void HWIntrinsicInfo::lookupImmBounds( case NI_AdvSimd_Arm64_InsertSelectedScalar: case NI_Sve_FusedMultiplyAddBySelectedScalar: case NI_Sve_FusedMultiplySubtractBySelectedScalar: + case NI_Sve_ExtractVector: immUpperBound = Compiler::getSIMDVectorLength(simdSize, baseType) - 1; break; diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index a729a20fba917..f411205f21d4d 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -2111,6 +2111,36 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) break; } + case NI_Sve_TestAnyTrue: + case NI_Sve_TestFirstTrue: + case NI_Sve_TestLastTrue: + assert(targetReg == REG_NA); + GetEmitter()->emitIns_R_R(ins, EA_SCALABLE, op1Reg, op2Reg, INS_OPTS_SCALABLE_B); + break; + + case NI_Sve_ExtractVector: + { + assert(isRMW); + + if (targetReg != op1Reg) + { + assert(targetReg != op2Reg); + + GetEmitter()->emitIns_R_R(INS_sve_movprfx, EA_SCALABLE, targetReg, op1Reg); + } + + HWIntrinsicImmOpHelper helper(this, intrin.op3, node); + + for (helper.EmitBegin(); !helper.Done(); helper.EmitCaseEnd()) + { + const int elementIndex = helper.ImmValue(); + const int byteIndex = genTypeSize(intrin.baseType) * elementIndex; + + GetEmitter()->emitIns_R_R_I(ins, emitSize, targetReg, op2Reg, byteIndex, INS_OPTS_SCALABLE_B); + } + break; + } + case NI_Sve_InsertIntoShiftedVector: { assert(isRMW); diff --git a/src/coreclr/jit/hwintrinsiclistarm64sve.h b/src/coreclr/jit/hwintrinsiclistarm64sve.h index 9eb583e5ff4da..147c0a37fe85e 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64sve.h +++ b/src/coreclr/jit/hwintrinsiclistarm64sve.h @@ -68,6 +68,7 @@ HARDWARE_INTRINSIC(Sve, CreateWhileLessThanOrEqualMask8Bit, HARDWARE_INTRINSIC(Sve, Divide, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_sdiv, INS_sve_udiv, INS_sve_sdiv, INS_sve_udiv, INS_sve_fdiv, INS_sve_fdiv}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, DotProduct, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_sdot, INS_sve_udot, INS_sve_sdot, INS_sve_udot, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(Sve, DotProductBySelectedScalar, -1, 4, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_sdot, INS_sve_udot, INS_sve_sdot, INS_sve_udot, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_Scalable|HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_LowVectorOperation) +HARDWARE_INTRINSIC(Sve, ExtractVector, -1, 3, true, {INS_sve_ext, INS_sve_ext, INS_sve_ext, INS_sve_ext, INS_sve_ext, INS_sve_ext, INS_sve_ext, INS_sve_ext, INS_sve_ext, INS_sve_ext}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Sve, FusedMultiplyAdd, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_fmla, INS_sve_fmla}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation|HW_Flag_FmaIntrinsic|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Sve, FusedMultiplyAddBySelectedScalar, -1, 4, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_fmla, INS_sve_fmla}, HW_Category_SIMDByIndexedElement, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_FmaIntrinsic|HW_Flag_LowVectorOperation) HARDWARE_INTRINSIC(Sve, FusedMultiplyAddNegated, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_fnmla, INS_sve_fnmla}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation|HW_Flag_FmaIntrinsic|HW_Flag_SpecialCodeGen) @@ -204,6 +205,9 @@ HARDWARE_INTRINSIC(Sve, StoreNarrowing, HARDWARE_INTRINSIC(Sve, StoreNonTemporal, -1, 3, true, {INS_sve_stnt1b, INS_sve_stnt1b, INS_sve_stnt1h, INS_sve_stnt1h, INS_sve_stnt1w, INS_sve_stnt1w, INS_sve_stnt1d, INS_sve_stnt1d, INS_sve_stnt1w, INS_sve_stnt1d}, HW_Category_MemoryStore, HW_Flag_Scalable|HW_Flag_BaseTypeFromFirstArg|HW_Flag_ExplicitMaskedOperation|HW_Flag_SpecialCodeGen|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, Subtract, -1, 2, true, {INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_fsub, INS_sve_fsub}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_OptionalEmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) HARDWARE_INTRINSIC(Sve, SubtractSaturate, -1, 2, true, {INS_sve_sqsub, INS_sve_uqsub, INS_sve_sqsub, INS_sve_uqsub, INS_sve_sqsub, INS_sve_uqsub, INS_sve_sqsub, INS_sve_uqsub, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_OptionalEmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, TestAnyTrue, -1, 2, true, {INS_sve_ptest, INS_sve_ptest, INS_sve_ptest, INS_sve_ptest, INS_sve_ptest, INS_sve_ptest, INS_sve_ptest, INS_sve_ptest, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Sve, TestFirstTrue, -1, 2, true, {INS_sve_ptest, INS_sve_ptest, INS_sve_ptest, INS_sve_ptest, INS_sve_ptest, INS_sve_ptest, INS_sve_ptest, INS_sve_ptest, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Sve, TestLastTrue, -1, 2, true, {INS_sve_ptest, INS_sve_ptest, INS_sve_ptest, INS_sve_ptest, INS_sve_ptest, INS_sve_ptest, INS_sve_ptest, INS_sve_ptest, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation|HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Sve, TransposeEven, -1, 2, true, {INS_sve_trn1, INS_sve_trn1, INS_sve_trn1, INS_sve_trn1, INS_sve_trn1, INS_sve_trn1, INS_sve_trn1, INS_sve_trn1, INS_sve_trn1, INS_sve_trn1}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Sve, TransposeOdd, -1, 2, true, {INS_sve_trn2, INS_sve_trn2, INS_sve_trn2, INS_sve_trn2, INS_sve_trn2, INS_sve_trn2, INS_sve_trn2, INS_sve_trn2, INS_sve_trn2, INS_sve_trn2}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Sve, UnzipEven, -1, 2, true, {INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index 4b19477197f58..f958b392495e1 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -1266,6 +1266,27 @@ GenTree* Lowering::LowerHWIntrinsic(GenTreeHWIntrinsic* node) return LowerHWIntrinsicCmpOp(node, GT_NE); } + case NI_Sve_TestAnyTrue: + { + LowerNodeCC(node, GenCondition::NE); + node->gtType = TYP_VOID; + return node->gtNext; + } + + case NI_Sve_TestFirstTrue: + { + LowerNodeCC(node, GenCondition::SLT); + node->gtType = TYP_VOID; + return node->gtNext; + } + + case NI_Sve_TestLastTrue: + { + LowerNodeCC(node, GenCondition::ULT); + node->gtType = TYP_VOID; + return node->gtNext; + } + case NI_Vector128_WithLower: case NI_Vector128_WithUpper: { @@ -3192,6 +3213,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) case NI_Sve_PrefetchInt16: case NI_Sve_PrefetchInt32: case NI_Sve_PrefetchInt64: + case NI_Sve_ExtractVector: assert(hasImmediateOperand); assert(varTypeIsIntegral(intrin.op3)); if (intrin.op3->IsCnsIntOrI()) diff --git a/src/coreclr/jit/lsraarm64.cpp b/src/coreclr/jit/lsraarm64.cpp index 133bbd52b985d..27ea3e5659c56 100644 --- a/src/coreclr/jit/lsraarm64.cpp +++ b/src/coreclr/jit/lsraarm64.cpp @@ -1445,6 +1445,7 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCou case NI_Sve_PrefetchInt16: case NI_Sve_PrefetchInt32: case NI_Sve_PrefetchInt64: + case NI_Sve_ExtractVector: needBranchTargetReg = !intrin.op3->isContainedIntOrIImmed(); break; diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs index 844fb507b0a37..2c59e76fa5456 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs @@ -1402,6 +1402,68 @@ internal Arm64() { } /// public static unsafe Vector DotProductBySelectedScalar(Vector addend, Vector left, Vector right, [ConstantExpected] byte rightIndex) { throw new PlatformNotSupportedException(); } + + /// + /// svuint8_t svext[_u8](svuint8_t op1, svuint8_t op2, uint64_t imm3) + /// EXT Ztied1.B, Ztied1.B, Zop2.B, #imm3 + /// + public static unsafe Vector ExtractVector(Vector upper, Vector lower, [ConstantExpected] byte index) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svext[_f64](svfloat64_t op1, svfloat64_t op2, uint64_t imm3) + /// EXT Ztied1.B, Ztied1.B, Zop2.B, #imm3 * 8 + /// + public static unsafe Vector ExtractVector(Vector upper, Vector lower, [ConstantExpected] byte index) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svext[_s16](svint16_t op1, svint16_t op2, uint64_t imm3) + /// EXT Ztied1.B, Ztied1.B, Zop2.B, #imm3 * 2 + /// + public static unsafe Vector ExtractVector(Vector upper, Vector lower, [ConstantExpected] byte index) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svext[_s32](svint32_t op1, svint32_t op2, uint64_t imm3) + /// EXT Ztied1.B, Ztied1.B, Zop2.B, #imm3 * 4 + /// + public static unsafe Vector ExtractVector(Vector upper, Vector lower, [ConstantExpected] byte index) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svext[_s64](svint64_t op1, svint64_t op2, uint64_t imm3) + /// EXT Ztied1.B, Ztied1.B, Zop2.B, #imm3 * 8 + /// + public static unsafe Vector ExtractVector(Vector upper, Vector lower, [ConstantExpected] byte index) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svext[_s8](svint8_t op1, svint8_t op2, uint64_t imm3) + /// EXT Ztied1.B, Ztied1.B, Zop2.B, #imm3 + /// + public static unsafe Vector ExtractVector(Vector upper, Vector lower, [ConstantExpected] byte index) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svext[_f32](svfloat32_t op1, svfloat32_t op2, uint64_t imm3) + /// EXT Ztied1.B, Ztied1.B, Zop2.B, #imm3 * 4 + /// + public static unsafe Vector ExtractVector(Vector upper, Vector lower, [ConstantExpected] byte index) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svext[_u16](svuint16_t op1, svuint16_t op2, uint64_t imm3) + /// EXT Ztied1.B, Ztied1.B, Zop2.B, #imm3 * 2 + /// + public static unsafe Vector ExtractVector(Vector upper, Vector lower, [ConstantExpected] byte index) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svext[_u32](svuint32_t op1, svuint32_t op2, uint64_t imm3) + /// EXT Ztied1.B, Ztied1.B, Zop2.B, #imm3 * 4 + /// + public static unsafe Vector ExtractVector(Vector upper, Vector lower, [ConstantExpected] byte index) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svext[_u64](svuint64_t op1, svuint64_t op2, uint64_t imm3) + /// EXT Ztied1.B, Ztied1.B, Zop2.B, #imm3 * 8 + /// + public static unsafe Vector ExtractVector(Vector upper, Vector lower, [ConstantExpected] byte index) { throw new PlatformNotSupportedException(); } + + /// FusedMultiplyAdd : Multiply-add, addend first /// @@ -6113,6 +6175,150 @@ internal Arm64() { } /// public static unsafe Vector SignExtendWideningUpper(Vector value) { throw new PlatformNotSupportedException(); } + /// + /// bool svptest_any(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestAnyTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_any(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestAnyTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_any(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestAnyTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_any(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestAnyTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_any(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestAnyTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_any(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestAnyTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_any(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestAnyTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_any(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestAnyTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_first(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestFirstTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_first(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestFirstTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_first(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestFirstTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_first(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestFirstTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_first(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestFirstTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_first(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestFirstTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_first(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestFirstTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_first(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestFirstTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_last(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestLastTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_last(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestLastTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_last(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestLastTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_last(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestLastTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_last(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestLastTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_last(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestLastTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_last(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestLastTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + + /// + /// bool svptest_last(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestLastTrue(Vector mask, Vector srcMask) { throw new PlatformNotSupportedException(); } + /// Interleave even elements from two inputs diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs index a5cb2e3d09a36..278b3b600e7e3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs @@ -1458,6 +1458,68 @@ internal Arm64() { } /// public static unsafe Vector DotProductBySelectedScalar(Vector addend, Vector left, Vector right, [ConstantExpected] byte rightIndex) => DotProductBySelectedScalar(addend, left, right, rightIndex); + + /// + /// svuint8_t svext[_u8](svuint8_t op1, svuint8_t op2, uint64_t imm3) + /// EXT Ztied1.B, Ztied1.B, Zop2.B, #imm3 + /// + public static unsafe Vector ExtractVector(Vector upper, Vector lower, [ConstantExpected] byte index) => ExtractVector(upper, lower, index); + + /// + /// svfloat64_t svext[_f64](svfloat64_t op1, svfloat64_t op2, uint64_t imm3) + /// EXT Ztied1.B, Ztied1.B, Zop2.B, #imm3 * 8 + /// + public static unsafe Vector ExtractVector(Vector upper, Vector lower, [ConstantExpected] byte index) => ExtractVector(upper, lower, index); + + /// + /// svint16_t svext[_s16](svint16_t op1, svint16_t op2, uint64_t imm3) + /// EXT Ztied1.B, Ztied1.B, Zop2.B, #imm3 * 2 + /// + public static unsafe Vector ExtractVector(Vector upper, Vector lower, [ConstantExpected] byte index) => ExtractVector(upper, lower, index); + + /// + /// svint32_t svext[_s32](svint32_t op1, svint32_t op2, uint64_t imm3) + /// EXT Ztied1.B, Ztied1.B, Zop2.B, #imm3 * 4 + /// + public static unsafe Vector ExtractVector(Vector upper, Vector lower, [ConstantExpected] byte index) => ExtractVector(upper, lower, index); + + /// + /// svint64_t svext[_s64](svint64_t op1, svint64_t op2, uint64_t imm3) + /// EXT Ztied1.B, Ztied1.B, Zop2.B, #imm3 * 8 + /// + public static unsafe Vector ExtractVector(Vector upper, Vector lower, [ConstantExpected] byte index) => ExtractVector(upper, lower, index); + + /// + /// svint8_t svext[_s8](svint8_t op1, svint8_t op2, uint64_t imm3) + /// EXT Ztied1.B, Ztied1.B, Zop2.B, #imm3 + /// + public static unsafe Vector ExtractVector(Vector upper, Vector lower, [ConstantExpected] byte index) => ExtractVector(upper, lower, index); + + /// + /// svfloat32_t svext[_f32](svfloat32_t op1, svfloat32_t op2, uint64_t imm3) + /// EXT Ztied1.B, Ztied1.B, Zop2.B, #imm3 * 4 + /// + public static unsafe Vector ExtractVector(Vector upper, Vector lower, [ConstantExpected] byte index) => ExtractVector(upper, lower, index); + + /// + /// svuint16_t svext[_u16](svuint16_t op1, svuint16_t op2, uint64_t imm3) + /// EXT Ztied1.B, Ztied1.B, Zop2.B, #imm3 * 2 + /// + public static unsafe Vector ExtractVector(Vector upper, Vector lower, [ConstantExpected] byte index) => ExtractVector(upper, lower, index); + + /// + /// svuint32_t svext[_u32](svuint32_t op1, svuint32_t op2, uint64_t imm3) + /// EXT Ztied1.B, Ztied1.B, Zop2.B, #imm3 * 4 + /// + public static unsafe Vector ExtractVector(Vector upper, Vector lower, [ConstantExpected] byte index) => ExtractVector(upper, lower, index); + + /// + /// svuint64_t svext[_u64](svuint64_t op1, svuint64_t op2, uint64_t imm3) + /// EXT Ztied1.B, Ztied1.B, Zop2.B, #imm3 * 8 + /// + public static unsafe Vector ExtractVector(Vector upper, Vector lower, [ConstantExpected] byte index) => ExtractVector(upper, lower, index); + + /// FusedMultiplyAdd : Multiply-add, addend first /// @@ -6156,6 +6218,151 @@ internal Arm64() { } public static unsafe Vector SubtractSaturate(Vector left, Vector right) => SubtractSaturate(left, right); + /// + /// bool svptest_any(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestAnyTrue(Vector mask, Vector srcMask) => TestAnyTrue(mask, srcMask); + + /// + /// bool svptest_any(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestAnyTrue(Vector mask, Vector srcMask) => TestAnyTrue(mask, srcMask); + + /// + /// bool svptest_any(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestAnyTrue(Vector mask, Vector srcMask) => TestAnyTrue(mask, srcMask); + + /// + /// bool svptest_any(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestAnyTrue(Vector mask, Vector srcMask) => TestAnyTrue(mask, srcMask); + + /// + /// bool svptest_any(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestAnyTrue(Vector mask, Vector srcMask) => TestAnyTrue(mask, srcMask); + + /// + /// bool svptest_any(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestAnyTrue(Vector mask, Vector srcMask) => TestAnyTrue(mask, srcMask); + + /// + /// bool svptest_any(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestAnyTrue(Vector mask, Vector srcMask) => TestAnyTrue(mask, srcMask); + + /// + /// bool svptest_any(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestAnyTrue(Vector mask, Vector srcMask) => TestAnyTrue(mask, srcMask); + + /// + /// bool svptest_first(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestFirstTrue(Vector mask, Vector srcMask) => TestFirstTrue(mask, srcMask); + + /// + /// bool svptest_first(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestFirstTrue(Vector mask, Vector srcMask) => TestFirstTrue(mask, srcMask); + + /// + /// bool svptest_first(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestFirstTrue(Vector mask, Vector srcMask) => TestFirstTrue(mask, srcMask); + + /// + /// bool svptest_first(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestFirstTrue(Vector mask, Vector srcMask) => TestFirstTrue(mask, srcMask); + + /// + /// bool svptest_first(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestFirstTrue(Vector mask, Vector srcMask) => TestFirstTrue(mask, srcMask); + + /// + /// bool svptest_first(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestFirstTrue(Vector mask, Vector srcMask) => TestFirstTrue(mask, srcMask); + + /// + /// bool svptest_first(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestFirstTrue(Vector mask, Vector srcMask) => TestFirstTrue(mask, srcMask); + + /// + /// bool svptest_first(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestFirstTrue(Vector mask, Vector srcMask) => TestFirstTrue(mask, srcMask); + + /// + /// bool svptest_last(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestLastTrue(Vector mask, Vector srcMask) => TestLastTrue(mask, srcMask); + + /// + /// bool svptest_last(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestLastTrue(Vector mask, Vector srcMask) => TestLastTrue(mask, srcMask); + + /// + /// bool svptest_last(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestLastTrue(Vector mask, Vector srcMask) => TestLastTrue(mask, srcMask); + + /// + /// bool svptest_last(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestLastTrue(Vector mask, Vector srcMask) => TestLastTrue(mask, srcMask); + + /// + /// bool svptest_last(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestLastTrue(Vector mask, Vector srcMask) => TestLastTrue(mask, srcMask); + + /// + /// bool svptest_last(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestLastTrue(Vector mask, Vector srcMask) => TestLastTrue(mask, srcMask); + + /// + /// bool svptest_last(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestLastTrue(Vector mask, Vector srcMask) => TestLastTrue(mask, srcMask); + + /// + /// bool svptest_last(svbool_t pg, svbool_t op) + /// PTEST + /// + public static unsafe bool TestLastTrue(Vector mask, Vector srcMask) => TestLastTrue(mask, srcMask); + + /// Interleave even elements from two inputs /// diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index 8f9fad52775b2..b88247054132f 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -4391,6 +4391,17 @@ internal Arm64() { } public static System.Numerics.Vector DotProductBySelectedScalar(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right, [ConstantExpected] byte rightIndex) { throw null; } public static System.Numerics.Vector DotProductBySelectedScalar(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right, [ConstantExpected] byte rightIndex) { throw null; } + public static unsafe System.Numerics.Vector ExtractVector(System.Numerics.Vector upper, System.Numerics.Vector lower, [ConstantExpected] byte index) { throw null; } + public static unsafe System.Numerics.Vector ExtractVector(System.Numerics.Vector upper, System.Numerics.Vector lower, [ConstantExpected] byte index) { throw null; } + public static unsafe System.Numerics.Vector ExtractVector(System.Numerics.Vector upper, System.Numerics.Vector lower, [ConstantExpected] byte index) { throw null; } + public static unsafe System.Numerics.Vector ExtractVector(System.Numerics.Vector upper, System.Numerics.Vector lower, [ConstantExpected] byte index) { throw null; } + public static unsafe System.Numerics.Vector ExtractVector(System.Numerics.Vector upper, System.Numerics.Vector lower, [ConstantExpected] byte index) { throw null; } + public static unsafe System.Numerics.Vector ExtractVector(System.Numerics.Vector upper, System.Numerics.Vector lower, [ConstantExpected] byte index) { throw null; } + public static unsafe System.Numerics.Vector ExtractVector(System.Numerics.Vector upper, System.Numerics.Vector lower, [ConstantExpected] byte index) { throw null; } + public static unsafe System.Numerics.Vector ExtractVector(System.Numerics.Vector upper, System.Numerics.Vector lower, [ConstantExpected] byte index) { throw null; } + public static unsafe System.Numerics.Vector ExtractVector(System.Numerics.Vector upper, System.Numerics.Vector lower, [ConstantExpected] byte index) { throw null; } + public static unsafe System.Numerics.Vector ExtractVector(System.Numerics.Vector upper, System.Numerics.Vector lower, [ConstantExpected] byte index) { throw null; } + public static System.Numerics.Vector FusedMultiplyAdd(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector FusedMultiplyAdd(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector FusedMultiplyAddBySelectedScalar(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right, [ConstantExpected] byte rightIndex) { throw null; } @@ -5077,6 +5088,31 @@ internal Arm64() { } public static System.Numerics.Vector SubtractSaturate(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector SubtractSaturate(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static bool TestAnyTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestAnyTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestAnyTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestAnyTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestAnyTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestAnyTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestAnyTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestAnyTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestFirstTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestFirstTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestFirstTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestFirstTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestFirstTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestFirstTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestFirstTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestFirstTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestLastTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestLastTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestLastTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestLastTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestLastTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestLastTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestLastTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static bool TestLastTrue(System.Numerics.Vector mask, System.Numerics.Vector srcMask) { throw null; } + public static System.Numerics.Vector TransposeEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector TransposeEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector TransposeEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } diff --git a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs index 348e781453f1c..fed2344952043 100644 --- a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs +++ b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs @@ -3178,6 +3178,17 @@ ("SveCreateTrueMaskTest.template", new Dictionary { ["TestName"] = "Sve_CreateTrueMaskUInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateTrueMaskUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1Type"] = "SveMaskPattern"}), ("SveCreateTrueMaskTest.template", new Dictionary { ["TestName"] = "Sve_CreateTrueMaskUInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateTrueMaskUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1Type"] = "SveMaskPattern"}), + ("SveExtractVectorTest.template", new Dictionary { ["TestName"] = "SveExtractVector_Byte_1", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ExtractVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), + ("SveExtractVectorTest.template", new Dictionary { ["TestName"] = "SveExtractVector_Double_1", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ExtractVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i)) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("SveExtractVectorTest.template", new Dictionary { ["TestName"] = "SveExtractVector_Int16_1", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ExtractVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), + ("SveExtractVectorTest.template", new Dictionary { ["TestName"] = "SveExtractVector_Int32_1", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ExtractVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), + ("SveExtractVectorTest.template", new Dictionary { ["TestName"] = "SveExtractVector_Int64_1", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ExtractVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), + ("SveExtractVectorTest.template", new Dictionary { ["TestName"] = "SveExtractVector_SByte_1", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ExtractVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), + ("SveExtractVectorTest.template", new Dictionary { ["TestName"] = "SveExtractVector_Single_1", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ExtractVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i)) != BitConverter.SingleToInt32Bits(result[i])"}), + ("SveExtractVectorTest.template", new Dictionary { ["TestName"] = "SveExtractVector_UInt16_1", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ExtractVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), + ("SveExtractVectorTest.template", new Dictionary { ["TestName"] = "SveExtractVector_UInt32_1", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ExtractVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), + ("SveExtractVectorTest.template", new Dictionary { ["TestName"] = "SveExtractVector_UInt64_1", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ExtractVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), + // ("SveGatherVectorVectorBases.template", new Dictionary { ["TestName"] = "Sve_GatherVector_Bases_float_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "GatherVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["ExtendedElementType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueBase"] = "TestLibrary.Generator.GetSingle()"}), // ("SveGatherVectorVectorBases.template", new Dictionary { ["TestName"] = "Sve_GatherVector_Bases_int_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "GatherVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["ExtendedElementType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueBase"] = "TestLibrary.Generator.GetInt32()"}), // ("SveGatherVectorVectorBases.template", new Dictionary { ["TestName"] = "Sve_GatherVector_Bases_uint_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "GatherVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["ExtendedElementType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "Helpers.getMaskUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueBase"] = "TestLibrary.Generator.GetUInt32()"}), @@ -3949,6 +3960,33 @@ ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_RoundToZero_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "RoundToZero", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.RoundToZero(firstOp[i]) != result[i]", ["GetIterResult"] = "Helpers.RoundToZero(leftOp[i])"}), ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_RoundToZero_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "RoundToZero", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.RoundToZero(firstOp[i]) != result[i]", ["GetIterResult"] = "Helpers.RoundToZero(leftOp[i])"}), + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestAnyTrue_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestAnyTrue", ["MaskBaseType"] = "SByte", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskSByte())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskSByte())", ["ValidateEntry"] = "TestAnyTrue(op1, op2) != result"}), + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestAnyTrue_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestAnyTrue", ["MaskBaseType"] = "Int16", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskInt16())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskInt16())", ["ValidateEntry"] = "TestAnyTrue(op1, op2) != result"}), + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestAnyTrue_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestAnyTrue", ["MaskBaseType"] = "Int32", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskInt32())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskInt32())", ["ValidateEntry"] = "TestAnyTrue(op1, op2) != result"}), + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestAnyTrue_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestAnyTrue", ["MaskBaseType"] = "Int64", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskInt64())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskInt64())", ["ValidateEntry"] = "TestAnyTrue(op1, op2) != result"}), + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestAnyTrue_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestAnyTrue", ["MaskBaseType"] = "Byte", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskByte())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskByte())", ["ValidateEntry"] = "TestAnyTrue(op1, op2) != result"}), + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestAnyTrue_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestAnyTrue", ["MaskBaseType"] = "UInt16", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskUInt16())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskUInt16())", ["ValidateEntry"] = "TestAnyTrue(op1, op2) != result"}), + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestAnyTrue_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestAnyTrue", ["MaskBaseType"] = "UInt32", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskUInt32())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskUInt32())", ["ValidateEntry"] = "TestAnyTrue(op1, op2) != result"}), + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestAnyTrue_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestAnyTrue", ["MaskBaseType"] = "UInt64", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskUInt64())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskUInt64())", ["ValidateEntry"] = "TestAnyTrue(op1, op2) != result"}), + + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestFirstTrue_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestFirstTrue", ["MaskBaseType"] = "SByte", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskSByte())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskSByte())", ["ValidateEntry"] = "TestFirstTrue(op1, op2) != result"}), + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestFirstTrue_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestFirstTrue", ["MaskBaseType"] = "Int16", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskInt16())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskInt16())", ["ValidateEntry"] = "TestFirstTrue(op1, op2) != result"}), + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestFirstTrue_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestFirstTrue", ["MaskBaseType"] = "Int32", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskInt32())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskInt32())", ["ValidateEntry"] = "TestFirstTrue(op1, op2) != result"}), + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestFirstTrue_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestFirstTrue", ["MaskBaseType"] = "Int64", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskInt64())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskInt64())", ["ValidateEntry"] = "TestFirstTrue(op1, op2) != result"}), + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestFirstTrue_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestFirstTrue", ["MaskBaseType"] = "Byte", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskByte())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskByte())", ["ValidateEntry"] = "TestFirstTrue(op1, op2) != result"}), + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestFirstTrue_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestFirstTrue", ["MaskBaseType"] = "UInt16", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskUInt16())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskUInt16())", ["ValidateEntry"] = "TestFirstTrue(op1, op2) != result"}), + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestFirstTrue_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestFirstTrue", ["MaskBaseType"] = "UInt32", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskUInt32())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskUInt32())", ["ValidateEntry"] = "TestFirstTrue(op1, op2) != result"}), + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestFirstTrue_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestFirstTrue", ["MaskBaseType"] = "UInt64", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskUInt64())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskUInt64())", ["ValidateEntry"] = "TestFirstTrue(op1, op2) != result"}), + + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestLastTrue_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestLastTrue", ["MaskBaseType"] = "SByte", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskSByte())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskSByte())", ["ValidateEntry"] = "TestLastTrue(op1, op2) != result"}), + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestLastTrue_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestLastTrue", ["MaskBaseType"] = "Int16", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskInt16())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskInt16())", ["ValidateEntry"] = "TestLastTrue(op1, op2) != result"}), + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestLastTrue_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestLastTrue", ["MaskBaseType"] = "Int32", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskInt32())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskInt32())", ["ValidateEntry"] = "TestLastTrue(op1, op2) != result"}), + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestLastTrue_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestLastTrue", ["MaskBaseType"] = "Int64", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskInt64())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskInt64())", ["ValidateEntry"] = "TestLastTrue(op1, op2) != result"}), + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestLastTrue_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestLastTrue", ["MaskBaseType"] = "Byte", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskByte())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskByte())", ["ValidateEntry"] = "TestLastTrue(op1, op2) != result"}), + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestLastTrue_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestLastTrue", ["MaskBaseType"] = "UInt16", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskUInt16())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskUInt16())", ["ValidateEntry"] = "TestLastTrue(op1, op2) != result"}), + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestLastTrue_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestLastTrue", ["MaskBaseType"] = "UInt32", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskUInt32())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskUInt32())", ["ValidateEntry"] = "TestLastTrue(op1, op2) != result"}), + ("SveTestTest.template", new Dictionary { ["TestName"] = "SveTestLastTrue_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TestLastTrue", ["MaskBaseType"] = "UInt64", ["Op1Value"] = "Helpers.InitVector(_ => Helpers.getMaskUInt64())", ["Op2Value"] = "Helpers.InitVector(_ => Helpers.getMaskUInt64())", ["ValidateEntry"] = "TestLastTrue(op1, op2) != result"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveTransposeEven_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[i] != left[index * 2] || result[i + 1] != right[index * 2]"}), ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveTransposeEven_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[i] != left[index * 2] || result[i + 1] != right[index * 2]"}), ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveTransposeEven_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[i] != left[index * 2] || result[i + 1] != right[index * 2]"}), diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs index 7ae4e080edbbd..0230384448aa7 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs @@ -17,6 +17,17 @@ namespace JIT.HardwareIntrinsics.Arm { static class Helpers { + public static Vector InitVector(Func f) + { + var count = Vector.Count; + var arr = new T[count]; + for (var i = 0; i < count; i++) + { + arr[i] = f(i); + } + return new Vector(arr); + } + public static sbyte CountLeadingSignBits(sbyte op1) { return (sbyte)(CountLeadingZeroBits((sbyte)((ulong)op1 ^ ((ulong)op1 >> 1))) - 1); diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveExtractVectorTest.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveExtractVectorTest.template new file mode 100644 index 0000000000000..3e391755dc557 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveExtractVectorTest.template @@ -0,0 +1,379 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using Xunit; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + [Fact] + public static void {TestName}() + { + var test = new ExtractVectorTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + test.RunBasicScenario_Load_Wrapper(); + test.RunBasicScenario_Load_WrapperWithIndex(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ExtractVectorTest__{TestName} + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray1, {Op2BaseType}[] inArray2, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<{Op2BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 64 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + public {Op2VectorType}<{Op2BaseType}> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref testStruct._fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario(ExtractVectorTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld1, _fld2, ElementIndex); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int Op2ElementCount = Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>() / sizeof({Op2BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + private static readonly byte ElementIndex = {ElementIndex}; + + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + private static {Op2BaseType}[] _data2 = new {Op2BaseType}[Op2ElementCount]; + + private {Op1VectorType}<{Op1BaseType}> _fld1; + private {Op2VectorType}<{Op2BaseType}> _fld2; + + private DataTable _dataTable; + + public ExtractVectorTest__{TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref _fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + _dataTable = new DataTable(_data1, _data2, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + ElementIndex + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(Sve.CreateTrueMask{Op1BaseType}(SveMaskPattern.All), ({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.Load{Op2VectorType}(Sve.CreateTrueMask{Op2BaseType}(SveMaskPattern.All), ({Op2BaseType}*)(_dataTable.inArray2Ptr)), + ElementIndex + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + {RetVectorType}<{RetBaseType}> Wrapper() + { + return {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(Sve.CreateTrueMask{Op1BaseType}(SveMaskPattern.All), ({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.Load{Op2VectorType}(Sve.CreateTrueMask{Op2BaseType}(SveMaskPattern.All), ({Op2BaseType}*)(_dataTable.inArray2Ptr)), + {ElementIndex} + ); + } + + public void RunBasicScenario_Load_Wrapper() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load_Wrapper)); + + var result = Wrapper<{RetBaseType}>(); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + {RetVectorType}<{RetBaseType}> WrapperWithIndex(byte index) + { + return {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(Sve.CreateTrueMask{Op1BaseType}(SveMaskPattern.All), ({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.Load{Op2VectorType}(Sve.CreateTrueMask{Op2BaseType}(SveMaskPattern.All), ({Op2BaseType}*)(_dataTable.inArray2Ptr)), + index + ); + } + + public void RunBasicScenario_Load_WrapperWithIndex() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load_WrapperWithIndex)); + + var result = WrapperWithIndex<{RetBaseType}>(ElementIndex); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>), typeof({Op2VectorType}<{Op2BaseType}>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + ElementIndex + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr); + var result = {Isa}.{Method}(op1, op2, ElementIndex); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1, _fld2, ElementIndex); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1, test._fld2, ElementIndex); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op2VectorType}<{Op2BaseType}> op2, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] firstOp, {Op2BaseType}[] secondOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if ({ValidateIterResult}) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op2VectorType}<{Op2BaseType}>, {ElementIndex}): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveTestTest.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveTestTest.template new file mode 100644 index 0000000000000..61445c6847e71 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveTestTest.template @@ -0,0 +1,233 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Numerics; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using Xunit; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + [Fact] + public static void {TestName}() + { + var test = new TestTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class TestTest__{TestName} + { + private struct TestStruct + { + public Vector<{MaskBaseType}> _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + testStruct._fld1 = {Op1Value}; + + return testStruct; + } + + public void RunStructFldScenario(TestTest__{TestName} testClass) + { + Vector<{MaskBaseType}> op2 = {Op2Value}; + + var result = {Isa}.{Method}(_fld1, op2); + + testClass.ValidateResult(_fld1, op2, result); + } + } + + private Vector<{MaskBaseType}> _fld1; + + public TestTest__{TestName}() + { + if ({Isa}.IsSupported) + { + _fld1 = {Op1Value}; + } + else + { + _fld1 = default; + } + Succeeded = true; + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + Vector<{MaskBaseType}> op1 = {Op1Value}; + Vector<{MaskBaseType}> op2 = {Op2Value}; + + var result = {Isa}.{Method}(op1, op2); + + ValidateResult(op1, op2, result); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + Vector<{MaskBaseType}> op1 = {Op1Value}; + Vector<{MaskBaseType}> op2 = {Op2Value}; + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof(Vector<{MaskBaseType}>), typeof(Vector<{MaskBaseType}>) }) + .Invoke(null, new object[] { + op1, op2 + }); + + ValidateResult(op1, op2, (bool)result); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + Vector<{MaskBaseType}> op2 = {Op2Value}; + + var result = {Isa}.{Method}(_fld1, op2); + + ValidateResult(_fld1, op2, result); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + Vector<{MaskBaseType}> op2 = {Op2Value}; + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1, op2); + + ValidateResult(test._fld1, op2, result); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + /// Find any occurrence where both left and right and set + static bool TestAnyTrue(Vector<{MaskBaseType}> left, Vector<{MaskBaseType}> right) + { + for (var i = 0; i < Vector<{MaskBaseType}>.Count; i++) + { + if ((left[i] > 0) && (right[i] > 0)) return true; + } + return false; + } + + /// Find first true value in left, and return contents of right + static bool TestFirstTrue(Vector<{MaskBaseType}> left, Vector<{MaskBaseType}> right) + { + for (var i = 0; i < Vector<{MaskBaseType}>.Count; i++) + { + if (left[i] > 0) return (right[i] > 0); + } + return false; + } + + /// Find last true value in left, and return contents of right + static bool TestLastTrue(Vector<{MaskBaseType}> left, Vector<{MaskBaseType}> right) + { + for (var i = Vector<{MaskBaseType}>.Count - 1; i >= 0; i--) + { + if (left[i] > 0) return (right[i] > 0); + } + return false; + } + + private void ValidateResult(Vector<{MaskBaseType}> op1, Vector<{MaskBaseType}> op2, bool result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if ({ValidateEntry}) + { + succeeded = false; + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}(Vector<{MaskBaseType}>, Vector<{MaskBaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" mask: ({op1})"); + TestLibrary.TestFramework.LogInformation($" srcMask: ({op2})"); + TestLibrary.TestFramework.LogInformation($" result: ({result})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +}