diff --git a/src/coreclr/jit/hwintrinsicarm64.cpp b/src/coreclr/jit/hwintrinsicarm64.cpp index c82a568c3b33a9..8db572f6bbc54f 100644 --- a/src/coreclr/jit/hwintrinsicarm64.cpp +++ b/src/coreclr/jit/hwintrinsicarm64.cpp @@ -3377,6 +3377,34 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Sve2_VectorTableLookup: + { + assert(sig->numArgs == 2); + assert(retType != TYP_VOID); + + CORINFO_ARG_LIST_HANDLE arg1 = sig->args; + CORINFO_ARG_LIST_HANDLE arg2 = info.compCompHnd->getArgNext(arg1); + CORINFO_CLASS_HANDLE argClass = NO_CLASS_HANDLE; + var_types argType1 = JITtype2varType(strip(info.compCompHnd->getArgType(sig, arg1, &argClass))); + var_types argType2 = JITtype2varType(strip(info.compCompHnd->getArgType(sig, arg2, &argClass))); + + var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); + CorInfoType op1BaseJitType = getBaseJitTypeOfSIMDType(argClass); + + op2 = impPopStack().val; + op1 = impPopStack().val; + + if (op1->TypeIs(TYP_STRUCT)) + { + info.compNeedsConsecutiveRegisters = true; + unsigned fieldCount = info.compCompHnd->getClassNumInstanceFields(argClass); + op1 = gtConvertTableOpToFieldList(op1, fieldCount); + } + retNode = gtNewSimdHWIntrinsicNode(retType, op1, op2, intrinsic, simdBaseJitType, simdSize); + retNode->AsHWIntrinsic()->SetAuxiliaryJitType(op1BaseJitType); + break; + } + default: { return nullptr; diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index ca38c26ab7c845..f92d1479d935b7 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -1722,6 +1722,30 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) break; } + case NI_Sve2_VectorTableLookup: + { + assert(intrin.op1->OperIsFieldList()); + GenTreeFieldList* fieldList = intrin.op1->AsFieldList(); + GenTree* firstField = fieldList->Uses().GetHead()->GetNode(); + op1Reg = firstField->GetRegNum(); +#ifdef DEBUG + unsigned regCount = 0; + regNumber argReg = op1Reg; + for (GenTreeFieldList::Use& use : fieldList->Uses()) + { + regCount++; + + GenTree* argNode = use.GetNode(); + assert(argReg == argNode->GetRegNum()); + argReg = getNextSIMDRegWithWraparound(argReg); + } + assert(regCount == 2); +#endif + GetEmitter()->emitInsSve_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, opt, + INS_SCALABLE_OPTS_WITH_VECTOR_PAIR); + break; + } + case NI_Sve_StoreAndZipx2: case NI_Sve_StoreAndZipx3: case NI_Sve_StoreAndZipx4: diff --git a/src/coreclr/jit/hwintrinsiclistarm64sve.h b/src/coreclr/jit/hwintrinsiclistarm64sve.h index c40ec5a69e7e4f..815a0697a42688 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64sve.h +++ b/src/coreclr/jit/hwintrinsiclistarm64sve.h @@ -357,6 +357,8 @@ HARDWARE_INTRINSIC(Sve2, ShiftRightLogicalRoundedNarrowingEven, HARDWARE_INTRINSIC(Sve2, ShiftRightLogicalRoundedNarrowingOdd, -1, 3, {INS_sve_rshrnt, INS_sve_rshrnt, INS_sve_rshrnt, INS_sve_rshrnt, INS_sve_rshrnt, INS_sve_rshrnt, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(Sve2, ShiftRightLogicalRoundedNarrowingSaturateEven, -1, 2, {INS_invalid, INS_sve_uqrshrnb, INS_invalid, INS_sve_uqrshrnb, INS_invalid, INS_sve_uqrshrnb, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_Scalable|HW_Flag_HasImmediateOperand) HARDWARE_INTRINSIC(Sve2, ShiftRightLogicalRoundedNarrowingSaturateOdd, -1, 3, {INS_invalid, INS_sve_uqrshrnt, INS_invalid, INS_sve_uqrshrnt, INS_invalid, INS_sve_uqrshrnt, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sve2, VectorTableLookup, -1, 2, {INS_sve_tbl, INS_sve_tbl, INS_sve_tbl, INS_sve_tbl, INS_sve_tbl, INS_sve_tbl, INS_sve_tbl, INS_sve_tbl, INS_sve_tbl, INS_sve_tbl}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_NeedsConsecutiveRegisters|HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Sve2, VectorTableLookupExtension, -1, 3, {INS_sve_tbx, INS_sve_tbx, INS_sve_tbx, INS_sve_tbx, INS_sve_tbx, INS_sve_tbx, INS_sve_tbx, INS_sve_tbx, INS_sve_tbx, INS_sve_tbx}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(Sve2, Xor, -1, 3, {INS_sve_eor3, INS_sve_eor3, INS_sve_eor3, INS_sve_eor3, INS_sve_eor3, INS_sve_eor3, INS_sve_eor3, INS_sve_eor3, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(Sve2, XorRotateRight, -1, 3, {INS_sve_xar, INS_sve_xar, INS_sve_xar, INS_sve_xar, INS_sve_xar, INS_sve_xar, INS_sve_xar, INS_sve_xar, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_Scalable|HW_Flag_HasRMWSemantics|HW_Flag_HasImmediateOperand) #define LAST_NI_Sve2 NI_Sve2_XorRotateRight diff --git a/src/coreclr/jit/lsraarm64.cpp b/src/coreclr/jit/lsraarm64.cpp index 7cc1a231391c71..9fd26f61833764 100644 --- a/src/coreclr/jit/lsraarm64.cpp +++ b/src/coreclr/jit/lsraarm64.cpp @@ -2400,6 +2400,7 @@ GenTree* LinearScan::getConsecutiveRegistersOperand(const HWIntrinsic intrin, bo { case NI_AdvSimd_Arm64_VectorTableLookup: case NI_AdvSimd_VectorTableLookup: + case NI_Sve2_VectorTableLookup: consecutiveOp = intrin.op1; assert(consecutiveOp != nullptr); break; diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.PlatformNotSupported.cs index c963e74b7d088e..fcb02fef2bd6fc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.PlatformNotSupported.cs @@ -1493,6 +1493,132 @@ internal Arm64() { } public static Vector ShiftRightLogicalRoundedNarrowingSaturateOdd(Vector even, Vector value, [ConstantExpected] byte count) { throw new PlatformNotSupportedException(); } + // Bit vector table lookups + + /// + /// svuint8_t svtbl2[_u8](svuint8x2_t data, svuint8_t indices) + /// TBL Zd.B, { Zn1.B, Zn2.B }, Zm.B + /// + public static unsafe Vector VectorTableLookup((Vector data1, Vector data2) table, Vector indices) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svtbl2[_u16](svuint16x2_t data, svuint16_t indices) + /// TBL Zd.H, { Zn1.H, Zn2.H }, Zm.H + /// + public static unsafe Vector VectorTableLookup((Vector data1, Vector data2) table, Vector indices) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svtbl2[_u32](svuint32x2_t data, svuint32_t indices) + /// TBL Zd.S, { Zn1.S, Zn2.S }, Zm.S + /// + public static unsafe Vector VectorTableLookup((Vector data1, Vector data2) table, Vector indices) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svtbl2[_u64](svuint64x2_t data, svuint64_t indices) + /// TBL Zd.D, { Zn1.D, Zn2.D }, Zm.D + /// + public static unsafe Vector VectorTableLookup((Vector data1, Vector data2) table, Vector indices) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svtbl2[_f32](svfloat32x2_t data, svuint32_t indices) + /// TBL Zd.S, { Zn1.S, Zn2.S }, Zm.S + /// + public static unsafe Vector VectorTableLookup((Vector data1, Vector data2) table, Vector indices) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svtbl2[_f64](svfloat64x2_t data, svuint64_t indices) + /// TBL Zd.D, { Zn1.D, Zn2.D }, Zm.D + /// + public static unsafe Vector VectorTableLookup((Vector data1, Vector data2) table, Vector indices) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svtbl2[_s8](svint8x2_t data, svuint8_t indices) + /// TBL Zd.B, { Zn1.B, Zn2.B }, Zm.B + /// + public static unsafe Vector VectorTableLookup((Vector data1, Vector data2) table, Vector indices) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svtbl2[_s16](svint16x2_t data, svuint16_t indices) + /// TBL Zd.H, { Zn1.H, Zn2.H }, Zm.H + /// + public static unsafe Vector VectorTableLookup((Vector data1, Vector data2) table, Vector indices) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svtbl2[_s32](svint32x2_t data, svuint32_t indices) + /// TBL Zd.S, { Zn1.S, Zn2.S }, Zm.S + /// + public static unsafe Vector VectorTableLookup((Vector data1, Vector data2) table, Vector indices) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svtbl2[_s64](svint64x2_t data, svuint64_t indices) + /// TBL Zd.D, { Zn1.D, Zn2.D }, Zm.D + /// + public static unsafe Vector VectorTableLookup((Vector data1, Vector data2) table, Vector indices) { throw new PlatformNotSupportedException(); } + + + // Bit vector table lookup extensions + + /// + /// svuint8_t svtbx[_u8](svuint8_t fallback, svuint8_t data, svuint8_t indices) + /// TBX Zd.B, Zn.B, Zm.B + /// + public static unsafe Vector VectorTableLookupExtension(Vector defaultValues, Vector data, Vector indices) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svtbx[_u16](svuint16_t fallback, svuint16_t data, svuint16_t indices) + /// TBX Zd.H, Zn.H, Zm.H + /// + public static unsafe Vector VectorTableLookupExtension(Vector defaultValues, Vector data, Vector indices) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svtbx[_u32](svuint32_t fallback, svuint32_t data, svuint32_t indices) + /// TBX Zd.S, Zn.S, Zm.S + /// + public static unsafe Vector VectorTableLookupExtension(Vector defaultValues, Vector data, Vector indices) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svtbx[_u64](svuint64_t fallback, svuint64_t data, svuint64_t indices) + /// TBX Zd.D, Zn.D, Zm.D + /// + public static unsafe Vector VectorTableLookupExtension(Vector defaultValues, Vector data, Vector indices) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svtbx[_f32](svfloat32_t fallback, svfloat32_t data, svuint32_t indices) + /// TBX Zd.S, Zn.S, Zm.S + /// + public static unsafe Vector VectorTableLookupExtension(Vector defaultValues, Vector data, Vector indices) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svtbx[_f64](svfloat64_t fallback, svfloat64_t data, svuint64_t indices) + /// TBX Zd.D, Zn.D, Zm.D + /// + public static unsafe Vector VectorTableLookupExtension(Vector defaultValues, Vector data, Vector indices) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svtbx[_s8](svint8_t fallback, svint8_t data, svuint8_t indices) + /// TBX Zd.B, Zn.B, Zm.B + /// + public static unsafe Vector VectorTableLookupExtension(Vector defaultValues, Vector data, Vector indices) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svtbx[_s16](svint16_t fallback, svint16_t data, svuint16_t indices) + /// TBX Zd.H, Zn.H, Zm.H + /// + public static unsafe Vector VectorTableLookupExtension(Vector defaultValues, Vector data, Vector indices) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svtbx[_s32](svint32_t fallback, svint32_t data, svuint32_t indices) + /// TBX Zd.S, Zn.S, Zm.S + /// + public static unsafe Vector VectorTableLookupExtension(Vector defaultValues, Vector data, Vector indices) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svtbx[_s64](svint64_t fallback, svint64_t data, svuint64_t indices) + /// TBX Zd.D, Zn.D, Zm.D + /// + public static unsafe Vector VectorTableLookupExtension(Vector defaultValues, Vector data, Vector indices) { throw new PlatformNotSupportedException(); } + + // Bitwise exclusive OR of three vectors /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.cs index 98853bad0fc691..36efa55cc2ccba 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.cs @@ -1493,6 +1493,132 @@ internal Arm64() { } public static Vector ShiftRightLogicalRoundedNarrowingSaturateOdd(Vector even, Vector value, [ConstantExpected] byte count) => ShiftRightLogicalRoundedNarrowingSaturateOdd(even, value, count); + // Bit vector table lookups + + /// + /// svuint8_t svtbl2[_u8](svuint8x2_t data, svuint8_t indices) + /// TBL Zd.B, { Zn1.B, Zn2.B }, Zm.B + /// + public static unsafe Vector VectorTableLookup((Vector data1, Vector data2) table, Vector indices) => VectorTableLookup(table, indices); + + /// + /// svuint16_t svtbl2[_u16](svuint16x2_t data, svuint16_t indices) + /// TBL Zd.H, { Zn1.H, Zn2.H }, Zm.H + /// + public static unsafe Vector VectorTableLookup((Vector data1, Vector data2) table, Vector indices) => VectorTableLookup(table, indices); + + /// + /// svuint32_t svtbl2[_u32](svuint32x2_t data, svuint32_t indices) + /// TBL Zd.S, { Zn1.S, Zn2.S }, Zm.S + /// + public static unsafe Vector VectorTableLookup((Vector data1, Vector data2) table, Vector indices) => VectorTableLookup(table, indices); + + /// + /// svuint64_t svtbl2[_u64](svuint64x2_t data, svuint64_t indices) + /// TBL Zd.D, { Zn1.D, Zn2.D }, Zm.D + /// + public static unsafe Vector VectorTableLookup((Vector data1, Vector data2) table, Vector indices) => VectorTableLookup(table, indices); + + /// + /// svfloat32_t svtbl2[_f32](svfloat32x2_t data, svuint32_t indices) + /// TBL Zd.S, { Zn1.S, Zn2.S }, Zm.S + /// + public static unsafe Vector VectorTableLookup((Vector data1, Vector data2) table, Vector indices) => VectorTableLookup(table, indices); + + /// + /// svfloat64_t svtbl2[_f64](svfloat64x2_t data, svuint64_t indices) + /// TBL Zd.D, { Zn1.D, Zn2.D }, Zm.D + /// + public static unsafe Vector VectorTableLookup((Vector data1, Vector data2) table, Vector indices) => VectorTableLookup(table, indices); + + /// + /// svint8_t svtbl2[_s8](svint8x2_t data, svuint8_t indices) + /// TBL Zd.B, { Zn1.B, Zn2.B }, Zm.B + /// + public static unsafe Vector VectorTableLookup((Vector data1, Vector data2) table, Vector indices) => VectorTableLookup(table, indices); + + /// + /// svint16_t svtbl2[_s16](svint16x2_t data, svuint16_t indices) + /// TBL Zd.H, { Zn1.H, Zn2.H }, Zm.H + /// + public static unsafe Vector VectorTableLookup((Vector data1, Vector data2) table, Vector indices) => VectorTableLookup(table, indices); + + /// + /// svint32_t svtbl2[_s32](svint32x2_t data, svuint32_t indices) + /// TBL Zd.S, { Zn1.S, Zn2.S }, Zm.S + /// + public static unsafe Vector VectorTableLookup((Vector data1, Vector data2) table, Vector indices) => VectorTableLookup(table, indices); + + /// + /// svint64_t svtbl2[_s64](svint64x2_t data, svuint64_t indices) + /// TBL Zd.D, { Zn1.D, Zn2.D }, Zm.D + /// + public static unsafe Vector VectorTableLookup((Vector data1, Vector data2) table, Vector indices) => VectorTableLookup(table, indices); + + + // Bit vector table lookup extensions + + /// + /// svuint8_t svtbx[_u8](svuint8_t fallback, svuint8_t data, svuint8_t indices) + /// TBX Zd.B, Zn.B, Zm.B + /// + public static unsafe Vector VectorTableLookupExtension(Vector defaultValues, Vector data, Vector indices) => VectorTableLookupExtension(defaultValues, data, indices); + + /// + /// svuint16_t svtbx[_u16](svuint16_t fallback, svuint16_t data, svuint16_t indices) + /// TBX Zd.H, Zn.H, Zm.H + /// + public static unsafe Vector VectorTableLookupExtension(Vector defaultValues, Vector data, Vector indices) => VectorTableLookupExtension(defaultValues, data, indices); + + /// + /// svuint32_t svtbx[_u32](svuint32_t fallback, svuint32_t data, svuint32_t indices) + /// TBX Zd.S, Zn.S, Zm.S + /// + public static unsafe Vector VectorTableLookupExtension(Vector defaultValues, Vector data, Vector indices) => VectorTableLookupExtension(defaultValues, data, indices); + + /// + /// svuint64_t svtbx[_u64](svuint64_t fallback, svuint64_t data, svuint64_t indices) + /// TBX Zd.D, Zn.D, Zm.D + /// + public static unsafe Vector VectorTableLookupExtension(Vector defaultValues, Vector data, Vector indices) => VectorTableLookupExtension(defaultValues, data, indices); + + /// + /// svfloat32_t svtbx[_f32](svfloat32_t fallback, svfloat32_t data, svuint32_t indices) + /// TBX Zd.S, Zn.S, Zm.S + /// + public static unsafe Vector VectorTableLookupExtension(Vector defaultValues, Vector data, Vector indices) => VectorTableLookupExtension(defaultValues, data, indices); + + /// + /// svfloat64_t svtbx[_f64](svfloat64_t fallback, svfloat64_t data, svuint64_t indices) + /// TBX Zd.D, Zn.D, Zm.D + /// + public static unsafe Vector VectorTableLookupExtension(Vector defaultValues, Vector data, Vector indices) => VectorTableLookupExtension(defaultValues, data, indices); + + /// + /// svint8_t svtbx[_s8](svint8_t fallback, svint8_t data, svuint8_t indices) + /// TBX Zd.B, Zn.B, Zm.B + /// + public static unsafe Vector VectorTableLookupExtension(Vector defaultValues, Vector data, Vector indices) => VectorTableLookupExtension(defaultValues, data, indices); + + /// + /// svint16_t svtbx[_s16](svint16_t fallback, svint16_t data, svuint16_t indices) + /// TBX Zd.H, Zn.H, Zm.H + /// + public static unsafe Vector VectorTableLookupExtension(Vector defaultValues, Vector data, Vector indices) => VectorTableLookupExtension(defaultValues, data, indices); + + /// + /// svint32_t svtbx[_s32](svint32_t fallback, svint32_t data, svuint32_t indices) + /// TBX Zd.S, Zn.S, Zm.S + /// + public static unsafe Vector VectorTableLookupExtension(Vector defaultValues, Vector data, Vector indices) => VectorTableLookupExtension(defaultValues, data, indices); + + /// + /// svint64_t svtbx[_s64](svint64_t fallback, svint64_t data, svuint64_t indices) + /// TBX Zd.D, Zn.D, Zm.D + /// + public static unsafe Vector VectorTableLookupExtension(Vector defaultValues, Vector data, Vector indices) => VectorTableLookupExtension(defaultValues, data, indices); + + // Bitwise exclusive OR of three vectors /// 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 42be511d6f4213..beb666fc7712d1 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -6308,6 +6308,26 @@ internal Arm64() { } public static System.Numerics.Vector ShiftRightLogicalRoundedNarrowingSaturateOdd(System.Numerics.Vector even, System.Numerics.Vector value, [ConstantExpected] byte count) { throw null; } public static System.Numerics.Vector ShiftRightLogicalRoundedNarrowingSaturateOdd(System.Numerics.Vector even, System.Numerics.Vector value, [ConstantExpected] byte count) { throw null; } public static System.Numerics.Vector ShiftRightLogicalRoundedNarrowingSaturateOdd(System.Numerics.Vector even, System.Numerics.Vector value, [ConstantExpected] byte count) { throw null; } + public static System.Numerics.Vector VectorTableLookup((System.Numerics.Vector data1, System.Numerics.Vector data2) table, System.Numerics.Vector indices) { throw null; } + public static System.Numerics.Vector VectorTableLookup((System.Numerics.Vector data1, System.Numerics.Vector data2) table, System.Numerics.Vector indices) { throw null; } + public static System.Numerics.Vector VectorTableLookup((System.Numerics.Vector data1, System.Numerics.Vector data2) table, System.Numerics.Vector indices) { throw null; } + public static System.Numerics.Vector VectorTableLookup((System.Numerics.Vector data1, System.Numerics.Vector data2) table, System.Numerics.Vector indices) { throw null; } + public static System.Numerics.Vector VectorTableLookup((System.Numerics.Vector data1, System.Numerics.Vector data2) table, System.Numerics.Vector indices) { throw null; } + public static System.Numerics.Vector VectorTableLookup((System.Numerics.Vector data1, System.Numerics.Vector data2) table, System.Numerics.Vector indices) { throw null; } + public static System.Numerics.Vector VectorTableLookup((System.Numerics.Vector data1, System.Numerics.Vector data2) table, System.Numerics.Vector indices) { throw null; } + public static System.Numerics.Vector VectorTableLookup((System.Numerics.Vector data1, System.Numerics.Vector data2) table, System.Numerics.Vector indices) { throw null; } + public static System.Numerics.Vector VectorTableLookup((System.Numerics.Vector data1, System.Numerics.Vector data2) table, System.Numerics.Vector indices) { throw null; } + public static System.Numerics.Vector VectorTableLookup((System.Numerics.Vector data1, System.Numerics.Vector data2) table, System.Numerics.Vector indices) { throw null; } + public static System.Numerics.Vector VectorTableLookupExtension(System.Numerics.Vector defaultValues, System.Numerics.Vector data, System.Numerics.Vector indices) { throw null; } + public static System.Numerics.Vector VectorTableLookupExtension(System.Numerics.Vector defaultValues, System.Numerics.Vector data, System.Numerics.Vector indices) { throw null; } + public static System.Numerics.Vector VectorTableLookupExtension(System.Numerics.Vector defaultValues, System.Numerics.Vector data, System.Numerics.Vector indices) { throw null; } + public static System.Numerics.Vector VectorTableLookupExtension(System.Numerics.Vector defaultValues, System.Numerics.Vector data, System.Numerics.Vector indices) { throw null; } + public static System.Numerics.Vector VectorTableLookupExtension(System.Numerics.Vector defaultValues, System.Numerics.Vector data, System.Numerics.Vector indices) { throw null; } + public static System.Numerics.Vector VectorTableLookupExtension(System.Numerics.Vector defaultValues, System.Numerics.Vector data, System.Numerics.Vector indices) { throw null; } + public static System.Numerics.Vector VectorTableLookupExtension(System.Numerics.Vector defaultValues, System.Numerics.Vector data, System.Numerics.Vector indices) { throw null; } + public static System.Numerics.Vector VectorTableLookupExtension(System.Numerics.Vector defaultValues, System.Numerics.Vector data, System.Numerics.Vector indices) { throw null; } + public static System.Numerics.Vector VectorTableLookupExtension(System.Numerics.Vector defaultValues, System.Numerics.Vector data, System.Numerics.Vector indices) { throw null; } + public static System.Numerics.Vector VectorTableLookupExtension(System.Numerics.Vector defaultValues, System.Numerics.Vector data, System.Numerics.Vector indices) { throw null; } public static System.Numerics.Vector Xor(System.Numerics.Vector value1, System.Numerics.Vector value2, System.Numerics.Vector value3) { throw null; } public static System.Numerics.Vector Xor(System.Numerics.Vector value1, System.Numerics.Vector value2, System.Numerics.Vector value3) { throw null; } public static System.Numerics.Vector Xor(System.Numerics.Vector value1, System.Numerics.Vector value2, System.Numerics.Vector value3) { throw null; } diff --git a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs index 5373fce56a16bd..0d1d8faadb32a6 100644 --- a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs +++ b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs @@ -221,6 +221,16 @@ } }"; +const string SveValidateForEachRetElementCount_ValidationLogic = @" + for (var i = 0; i < RetElementCount; i++) + { + if ({ValidateEntry}) + { + succeeded = false; + break; + } + }"; + const string VecReduceUnOpTest_VectorValidationLogicForCndSel = @" { var hasFailed = (mask[0] != 0) ? ({ValidateReduceOpResult}): (falseVal[0] != result[0]); @@ -346,6 +356,8 @@ ("_SveStoreTemplate.template", "SveStoreTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), ("_SveStoreTemplate.template", "SveStoreNarrowTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogicForNarrowing }), ("_SveStoreTemplate.template", "SveStoreNonTemporalTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), + ("_SveTernaryOpValidateTestTemplate.template", "SveVecTernOpValidateTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SveValidateForEachRetElementCount_ValidationLogic }), + ("_SveBinaryOpTupleTestTemplate.template", "SveVecBinOpTupleTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SveValidateForEachRetElementCount_ValidationLogic }), }; (string templateFileName, Dictionary templateData)[] AdvSimdInputs = new[] @@ -5048,6 +5060,36 @@ ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve2_Xor_ushort", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "result[i] != Helpers.Xor(firstOp[i], secondOp[i], thirdOp[i])", ["GetIterResult"] = "Helpers.Xor(firstOp[i], secondOp[i], thirdOp[i])",}), ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve2_Xor_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "result[i] != Helpers.Xor(firstOp[i], secondOp[i], thirdOp[i])", ["GetIterResult"] = "Helpers.Xor(firstOp[i], secondOp[i], thirdOp[i])",}), ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve2_Xor_ulong", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "result[i] != Helpers.Xor(firstOp[i], secondOp[i], thirdOp[i])", ["GetIterResult"] = "Helpers.Xor(firstOp[i], secondOp[i], thirdOp[i])",}), + ("SveVecBinOpTupleTest.template", new Dictionary { ["TestName"] = "Sve2_VectorTableLookup_byte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "VectorTableLookup", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "(third[i] < (Byte) RetElementCount * 2) ? ((third[i] < (Byte) RetElementCount) ? (result[i] != first[third[i]]) : (result[i] != second[third[i]-(Byte) RetElementCount])) : (result[i] != 0)"}), + ("SveVecBinOpTupleTest.template", new Dictionary { ["TestName"] = "Sve2_VectorTableLookup_ushort", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "VectorTableLookup", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "(third[i] < (UInt16) RetElementCount * 2) ? ((third[i] < (UInt16) RetElementCount) ? (result[i] != first[third[i]]) : (result[i] != second[third[i]-(UInt16) RetElementCount])) : (result[i] != 0)"}), + ("SveVecBinOpTupleTest.template", new Dictionary { ["TestName"] = "Sve2_VectorTableLookup_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "VectorTableLookup", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "(third[i] < (UInt32) RetElementCount * 2) ? ((third[i] < (UInt32) RetElementCount) ? (result[i] != first[third[i]]) : (result[i] != second[third[i]-(UInt32) RetElementCount])) : (result[i] != 0)"}), + ("SveVecBinOpTupleTest.template", new Dictionary { ["TestName"] = "Sve2_VectorTableLookup_ulong", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "VectorTableLookup", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "(third[i] < (UInt64) RetElementCount * 2) ? ((third[i] < (UInt64) RetElementCount) ? (result[i] != first[third[i]]) : (result[i] != second[third[i]-(UInt64) RetElementCount])) : (result[i] != 0)"}), + ("SveVecBinOpTupleTest.template", new Dictionary { ["TestName"] = "Sve2_VectorTableLookup_float_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "VectorTableLookup", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "(third[i] < (UInt32) RetElementCount * 2) ? ((third[i] < (UInt32) RetElementCount) ? (result[i] != first[third[i]]) : (result[i] != second[third[i]-(UInt32) RetElementCount])) : (result[i] != 0)"}), + ("SveVecBinOpTupleTest.template", new Dictionary { ["TestName"] = "Sve2_VectorTableLookup_double_ulong", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "VectorTableLookup", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "(third[i] < (UInt64) RetElementCount * 2) ? ((third[i] < (UInt64) RetElementCount) ? (result[i] != first[third[i]]) : (result[i] != second[third[i]-(UInt64) RetElementCount])) : (result[i] != 0)"}), + ("SveVecBinOpTupleTest.template", new Dictionary { ["TestName"] = "Sve2_VectorTableLookup_sbyte_byte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "VectorTableLookup", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "(third[i] < (Byte) RetElementCount * 2) ? ((third[i] < (Byte) RetElementCount) ? (result[i] != first[third[i]]) : (result[i] != second[third[i]-(Byte) RetElementCount])) : (result[i] != 0)"}), + ("SveVecBinOpTupleTest.template", new Dictionary { ["TestName"] = "Sve2_VectorTableLookup_short_ushort", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "VectorTableLookup", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "(third[i] < (UInt16) RetElementCount * 2) ? ((third[i] < (UInt16) RetElementCount) ? (result[i] != first[third[i]]) : (result[i] != second[third[i]-(UInt16) RetElementCount])) : (result[i] != 0)"}), + ("SveVecBinOpTupleTest.template", new Dictionary { ["TestName"] = "Sve2_VectorTableLookup_int_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "VectorTableLookup", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "(third[i] < (UInt32) RetElementCount * 2) ? ((third[i] < (UInt32) RetElementCount) ? (result[i] != first[third[i]]) : (result[i] != second[third[i]-(UInt32) RetElementCount])) : (result[i] != 0)"}), + ("SveVecBinOpTupleTest.template", new Dictionary { ["TestName"] = "Sve2_VectorTableLookup_long_ulong", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "VectorTableLookup", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "(third[i] < (UInt64) RetElementCount * 2) ? ((third[i] < (UInt64) RetElementCount) ? (result[i] != first[third[i]]) : (result[i] != second[third[i]-(UInt64) RetElementCount])) : (result[i] != 0)"}), + + ("SveVecTernOpValidateTest.template", new Dictionary { ["TestName"] = "Sve2_VectorTableLookupExtension_byte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "VectorTableLookupExtension", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "(third[i] < (Byte) RetElementCount) ? (result[i] != second[third[i]]) : (result[i] != first[i])"}), + ("SveVecTernOpValidateTest.template", new Dictionary { ["TestName"] = "Sve2_VectorTableLookupExtension_ushort", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "VectorTableLookupExtension", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "(third[i] < (UInt16) RetElementCount) ? (result[i] != second[third[i]]) : (result[i] != first[i])"}), + ("SveVecTernOpValidateTest.template", new Dictionary { ["TestName"] = "Sve2_VectorTableLookupExtension_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "VectorTableLookupExtension", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "(third[i] < (UInt32) RetElementCount) ? (result[i] != second[third[i]]) : (result[i] != first[i])"}), + ("SveVecTernOpValidateTest.template", new Dictionary { ["TestName"] = "Sve2_VectorTableLookupExtension_ulong", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "VectorTableLookupExtension", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "(third[i] < (UInt64) RetElementCount) ? (result[i] != second[third[i]]) : (result[i] != first[i])"}), + ("SveVecTernOpValidateTest.template", new Dictionary { ["TestName"] = "Sve2_VectorTableLookupExtension_float_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "VectorTableLookupExtension", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "(third[i] < (UInt32) RetElementCount) ? (result[i] != second[third[i]]) : (result[i] != first[i])"}), + ("SveVecTernOpValidateTest.template", new Dictionary { ["TestName"] = "Sve2_VectorTableLookupExtension_double_ulong", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "VectorTableLookupExtension", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "(third[i] < (UInt64) RetElementCount) ? (result[i] != second[third[i]]) : (result[i] != first[i])"}), + ("SveVecTernOpValidateTest.template", new Dictionary { ["TestName"] = "Sve2_VectorTableLookupExtension_sbyte_byte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "VectorTableLookupExtension", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "(third[i] < (Byte) RetElementCount) ? (result[i] != second[third[i]]) : (result[i] != first[i])"}), + ("SveVecTernOpValidateTest.template", new Dictionary { ["TestName"] = "Sve2_VectorTableLookupExtension_short_ushort", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "VectorTableLookupExtension", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "(third[i] < (UInt16) RetElementCount) ? (result[i] != second[third[i]]) : (result[i] != first[i])"}), + ("SveVecTernOpValidateTest.template", new Dictionary { ["TestName"] = "Sve2_VectorTableLookupExtension_int_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "VectorTableLookupExtension", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "(third[i] < (UInt32) RetElementCount) ? (result[i] != second[third[i]]) : (result[i] != first[i])"}), + ("SveVecTernOpValidateTest.template", new Dictionary { ["TestName"] = "Sve2_VectorTableLookupExtension_long_ulong", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "VectorTableLookupExtension", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "(third[i] < (UInt64) RetElementCount) ? (result[i] != second[third[i]]) : (result[i] != first[i])"}), + + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve2_Xor_sbyte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "result[i] != Helpers.Xor(firstOp[i], secondOp[i], thirdOp[i])", ["GetIterResult"] = "Helpers.Xor(firstOp[i], secondOp[i], thirdOp[i])",}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve2_Xor_short", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "result[i] != Helpers.Xor(firstOp[i], secondOp[i], thirdOp[i])", ["GetIterResult"] = "Helpers.Xor(firstOp[i], secondOp[i], thirdOp[i])",}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve2_Xor_int", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "result[i] != Helpers.Xor(firstOp[i], secondOp[i], thirdOp[i])", ["GetIterResult"] = "Helpers.Xor(firstOp[i], secondOp[i], thirdOp[i])",}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve2_Xor_long", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt64()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "result[i] != Helpers.Xor(firstOp[i], secondOp[i], thirdOp[i])", ["GetIterResult"] = "Helpers.Xor(firstOp[i], secondOp[i], thirdOp[i])",}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve2_Xor_byte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "result[i] != Helpers.Xor(firstOp[i], secondOp[i], thirdOp[i])", ["GetIterResult"] = "Helpers.Xor(firstOp[i], secondOp[i], thirdOp[i])",}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve2_Xor_ushort", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "result[i] != Helpers.Xor(firstOp[i], secondOp[i], thirdOp[i])", ["GetIterResult"] = "Helpers.Xor(firstOp[i], secondOp[i], thirdOp[i])",}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve2_Xor_uint", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "result[i] != Helpers.Xor(firstOp[i], secondOp[i], thirdOp[i])", ["GetIterResult"] = "Helpers.Xor(firstOp[i], secondOp[i], thirdOp[i])",}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve2_Xor_ulong", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ConvertFunc"] = "", ["ValidateIterResult"] = "result[i] != Helpers.Xor(firstOp[i], secondOp[i], thirdOp[i])", ["GetIterResult"] = "Helpers.Xor(firstOp[i], secondOp[i], thirdOp[i])",}), ("SveVecImmBinOpTest.template", new Dictionary { ["TestName"] = "Sve2_XorRotateRight_sbyte", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "XorRotateRight", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueMask"] = "Helpers.getMaskSByte()", ["Imm"] = "8", ["InvalidImm"] = "9", ["ValidateIterResult"] = "result[i] != Helpers.XorRotateRight(firstOp[i], secondOp[i], Imm)", ["GetIterResult"] = "Helpers.XorRotateRight(firstOp[i], secondOp[i], Imm)",}), ("SveVecImmBinOpTest.template", new Dictionary { ["TestName"] = "Sve2_XorRotateRight_short", ["Isa"] = "Sve2", ["LoadIsa"] = "Sve2", ["Method"] = "XorRotateRight", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueMask"] = "Helpers.getMaskInt16()", ["Imm"] = "12", ["InvalidImm"] = "17", ["ValidateIterResult"] = "result[i] != Helpers.XorRotateRight(firstOp[i], secondOp[i], Imm)", ["GetIterResult"] = "Helpers.XorRotateRight(firstOp[i], secondOp[i], Imm)",}), diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveBinaryOpTupleTestTemplate.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveBinaryOpTupleTestTemplate.template new file mode 100644 index 00000000000000..4d07f9037da4a7 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveBinaryOpTupleTestTemplate.template @@ -0,0 +1,352 @@ +// 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 {TemplateName}BinaryOpTest__{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(); + } + + // 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 {TemplateName}BinaryOpTest__{TestName} + { + private struct DataTable + { + private byte[] inArray11; + private byte[] inArray12; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle11; + private GCHandle inHandle12; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray11, {Op1BaseType}[] inArray12, {Op2BaseType}[] inArray2, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray11 = inArray11.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfinArray12 = inArray12.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) < sizeOfinArray11 || (alignment * 2) < sizeOfinArray12 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray11 = new byte[alignment * 2]; + this.inArray12 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle11 = GCHandle.Alloc(this.inArray11, GCHandleType.Pinned); + this.inHandle12 = GCHandle.Alloc(this.inArray12, 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(inArray11Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray11[0]), (uint)sizeOfinArray11); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray12Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray12[0]), (uint)sizeOfinArray12); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray11Ptr => Align((byte*)(inHandle11.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray12Ptr => Align((byte*)(inHandle12.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle11.Free(); + inHandle12.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}> _fld11; + public {Op1VectorType}<{Op1BaseType}> _fld12; + public {Op2VectorType}<{Op2BaseType}> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op11ElementCount; i++) { _data11[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld11), ref Unsafe.As<{Op1BaseType}, byte>(ref _data11[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op12ElementCount; i++) { _data12[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld12), ref Unsafe.As<{Op1BaseType}, byte>(ref _data12[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({TemplateName}BinaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}((_fld11, _fld12), _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld11, _fld12, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op11ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int Op12ElementCount = 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 {Op1BaseType}[] _data11 = new {Op1BaseType}[Op11ElementCount]; + private static {Op1BaseType}[] _data12 = new {Op1BaseType}[Op12ElementCount]; + private static {Op2BaseType}[] _data2 = new {Op2BaseType}[Op2ElementCount]; + + private {Op1VectorType}<{Op1BaseType}> _fld11; + private {Op1VectorType}<{Op1BaseType}> _fld12; + private {Op2VectorType}<{Op2BaseType}> _fld2; + + private DataTable _dataTable; + + public {TemplateName}BinaryOpTest__{TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op11ElementCount; i++) { _data11[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld11), ref Unsafe.As<{Op1BaseType}, byte>(ref _data11[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op12ElementCount; i++) { _data12[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld12), ref Unsafe.As<{Op1BaseType}, byte>(ref _data12[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}>>()); + + _dataTable = new DataTable(_data11, _data12, _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.inArray11Ptr), + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray12Ptr)), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray11Ptr, _dataTable.inArray12Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + Vector<{Op1BaseType}> loadMask11 = Sve.CreateTrueMask{Op1BaseType}(SveMaskPattern.All); + Vector<{Op1BaseType}> loadMask12 = Sve.CreateTrueMask{Op1BaseType}(SveMaskPattern.All); + Vector<{Op2BaseType}> loadMask2 = Sve.CreateTrueMask{Op2BaseType}(SveMaskPattern.All); + + var result = {Isa}.{Method}( + ({LoadIsa}.Load{Op1VectorType}(loadMask11, ({Op1BaseType}*)(_dataTable.inArray11Ptr)), + {LoadIsa}.Load{Op1VectorType}(loadMask12, ({Op1BaseType}*)(_dataTable.inArray12Ptr))), + {LoadIsa}.Load{Op2VectorType}(loadMask2, ({Op2BaseType}*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray11Ptr, _dataTable.inArray12Ptr, _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}>, {Op1VectorType}<{Op1BaseType}>)), typeof({Op2VectorType}<{Op2BaseType}>) }) + .Invoke(null, new object[] { + (Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray11Ptr), + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray12Ptr)), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray11Ptr, _dataTable.inArray12Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op11 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray11Ptr); + var op12 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray12Ptr); + var op2 = Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr); + var result = {Isa}.{Method}((op11, op12), op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op11, op12, op2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}((_fld11, _fld12), _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld11, _fld12, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}((test._fld11, test._fld12), test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld11, test._fld12, 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}> op11, {Op1VectorType}<{Op1BaseType}> op12, {Op2VectorType}<{Op2BaseType}> op2, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray11 = new {Op1BaseType}[Op11ElementCount]; + {Op1BaseType}[] inArray12 = new {Op1BaseType}[Op12ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray11[0]), op11); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray12[0]), op12); + 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(inArray11, inArray12, inArray2, outArray, method); + } + + private void ValidateResult(void* op11, void* op12, void* op2, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray11 = new {Op1BaseType}[Op11ElementCount]; + {Op1BaseType}[] inArray12 = new {Op1BaseType}[Op12ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray11[0]), ref Unsafe.AsRef(op11), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray12[0]), ref Unsafe.AsRef(op12), (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(inArray11, inArray12, inArray2, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] first, {Op1BaseType}[] second, {Op2BaseType}[] third, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + {TemplateValidationLogic} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>(({Op1VectorType}<{Op1BaseType}>, {Op1VectorType}<{Op1BaseType}>), {Op2VectorType}<{Op2BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" first: ({string.Join(", ", first)})"); + TestLibrary.TestFramework.LogInformation($" second: ({string.Join(", ", second)})"); + TestLibrary.TestFramework.LogInformation($" third: ({string.Join(", ", third)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveTernaryOpValidateTestTemplate.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveTernaryOpValidateTestTemplate.template new file mode 100644 index 00000000000000..dad1b252c4fab0 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveTernaryOpValidateTestTemplate.template @@ -0,0 +1,355 @@ +// 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 {TemplateName}BinaryOpTest__{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(); + } + + // 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 {TemplateName}BinaryOpTest__{TestName} + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] inArray3; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle inHandle3; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray1, {Op2BaseType}[] inArray2, {Op3BaseType}[] inArray3, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<{Op2BaseType}>(); + int sizeOfinArray3 = inArray3.Length * Unsafe.SizeOf<{Op3BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 64 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfinArray3 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.inArray3 = 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.inHandle3 = GCHandle.Alloc(this.inArray3, 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); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray3Ptr), ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), (uint)sizeOfinArray3); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray3Ptr => Align((byte*)(inHandle3.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + inHandle3.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 {Op3VectorType}<{Op3BaseType}> _fld3; + + 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}>>()); + for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = {NextValueOp3}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op3VectorType}<{Op3BaseType}>, byte>(ref testStruct._fld3), ref Unsafe.As<{Op3BaseType}, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<{Op3VectorType}<{Op3BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario({TemplateName}BinaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld1, _fld2, _fld3); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fld3, 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 Op3ElementCount = Unsafe.SizeOf<{Op3VectorType}<{Op3BaseType}>>() / sizeof({Op3BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + private static {Op2BaseType}[] _data2 = new {Op2BaseType}[Op2ElementCount]; + private static {Op3BaseType}[] _data3 = new {Op3BaseType}[Op3ElementCount]; + + private {Op1VectorType}<{Op1BaseType}> _fld1; + private {Op2VectorType}<{Op2BaseType}> _fld2; + private {Op3VectorType}<{Op3BaseType}> _fld3; + + private DataTable _dataTable; + + public {TemplateName}BinaryOpTest__{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 < Op3ElementCount; i++) { _data3[i] = {NextValueOp3}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op3VectorType}<{Op3BaseType}>, byte>(ref _fld3), ref Unsafe.As<{Op3BaseType}, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<{Op3VectorType}<{Op3BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = {NextValueOp3}; } + _dataTable = new DataTable(_data1, _data2, _data3, 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), + Unsafe.Read<{Op3VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + Vector<{Op1BaseType}> loadMask1 = Sve.CreateTrueMask{Op1BaseType}(SveMaskPattern.All); + Vector<{Op2BaseType}> loadMask2 = Sve.CreateTrueMask{Op2BaseType}(SveMaskPattern.All); + Vector<{Op3BaseType}> loadMask3 = Sve.CreateTrueMask{Op3BaseType}(SveMaskPattern.All); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(loadMask1, ({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.Load{Op2VectorType}(loadMask2, ({Op2BaseType}*)(_dataTable.inArray2Ptr)), + {LoadIsa}.Load{Op3VectorType}(loadMask3, ({Op3BaseType}*)(_dataTable.inArray3Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _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({Op3VectorType}<{Op3BaseType}>) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + Unsafe.Read<{Op3VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _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 op3 = Unsafe.Read<{Op3VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr); + var result = {Isa}.{Method}(op1, op2, op3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1, _fld2, _fld3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1, test._fld2, test._fld3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fld3, _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, {Op3VectorType}<{Op3BaseType}> op3, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {Op3BaseType}[] inArray3 = new {Op3BaseType}[Op3ElementCount]; + {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.WriteUnaligned(ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), op3); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, inArray3, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* op3, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {Op3BaseType}[] inArray3 = new {Op3BaseType}[Op3ElementCount]; + {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<{Op3BaseType}, byte>(ref inArray3[0]), ref Unsafe.AsRef(op3), (uint)Unsafe.SizeOf<{Op3VectorType}<{Op3BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, inArray3, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] first, {Op2BaseType}[] second, {Op3BaseType}[] third, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + {TemplateValidationLogic} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op2VectorType}<{Op2BaseType}>, {Op3VectorType}<{Op3BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" first: ({string.Join(", ", first)})"); + TestLibrary.TestFramework.LogInformation($" second: ({string.Join(", ", second)})"); + TestLibrary.TestFramework.LogInformation($" third: ({string.Join(", ", third)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +}