diff --git a/src/coreclr/jit/codegenarmarch.cpp b/src/coreclr/jit/codegenarmarch.cpp index 71f775d70d8725..836de204d4534c 100644 --- a/src/coreclr/jit/codegenarmarch.cpp +++ b/src/coreclr/jit/codegenarmarch.cpp @@ -2130,34 +2130,40 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) int srcOffset = 0; GenTree* src = node->Data(); - assert(src->isContained()); - - if (src->OperIs(GT_LCL_VAR, GT_LCL_FLD)) + if (src->isContained()) { - srcLclNum = src->AsLclVarCommon()->GetLclNum(); - srcOffset = src->AsLclVarCommon()->GetLclOffs(); - } - else - { - assert(src->OperIs(GT_IND)); - GenTree* srcAddr = src->AsIndir()->Addr(); - - if (!srcAddr->isContained()) + if (src->OperIs(GT_LCL_VAR, GT_LCL_FLD)) { - srcAddrBaseReg = genConsumeReg(srcAddr); - } - else if (srcAddr->OperIsAddrMode()) - { - srcAddrBaseReg = genConsumeReg(srcAddr->AsAddrMode()->Base()); - srcOffset = srcAddr->AsAddrMode()->Offset(); + srcLclNum = src->AsLclVarCommon()->GetLclNum(); + srcOffset = src->AsLclVarCommon()->GetLclOffs(); } else { - assert(srcAddr->OperIsLocalAddr()); - srcLclNum = srcAddr->AsLclVarCommon()->GetLclNum(); - srcOffset = srcAddr->AsLclVarCommon()->GetLclOffs(); + assert(src->OperIs(GT_IND)); + GenTree* srcAddr = src->AsIndir()->Addr(); + + if (!srcAddr->isContained()) + { + srcAddrBaseReg = genConsumeReg(srcAddr); + } + else if (srcAddr->OperIsAddrMode()) + { + srcAddrBaseReg = genConsumeReg(srcAddr->AsAddrMode()->Base()); + srcOffset = srcAddr->AsAddrMode()->Offset(); + } + else + { + assert(srcAddr->OperIsLocalAddr()); + srcLclNum = srcAddr->AsLclVarCommon()->GetLclNum(); + srcOffset = srcAddr->AsLclVarCommon()->GetLclOffs(); + } } } + else + { + assert(src->OperIsHWIntrinsic()); + assert(src->TypeGet() == TYP_STRUCT); + } if (node->IsVolatile()) { @@ -2175,6 +2181,34 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) regNumber tempReg = node->ExtractTempReg(RBM_ALLINT); #ifdef TARGET_ARM64 + if (src->OperIsHWIntrinsic()) + { + const GenTreeHWIntrinsic* intrinsic = src->AsHWIntrinsic(); + + assert(src->IsMultiRegNode()); + const int srcCount = src->GetMultiRegCount(); + + for (int srcIndex = 0; srcIndex < srcCount; srcIndex++) + { + const regNumber srcReg = src->GetRegByIndex(srcIndex); + const var_types srcRegType = src->GetRegTypeByIndex(srcIndex); + const int srcRegSize = genTypeSize(srcRegType); + const emitAttr attr = emitTypeSize(srcRegType); + + if (dstLclNum != BAD_VAR_NUM) + { + GetEmitter()->emitIns_S_R(INS_str, attr, srcReg, dstLclNum, dstOffset); + } + else + { + GetEmitter()->emitIns_R_R_I(INS_str, attr, srcReg, dstAddrBaseReg, dstOffset); + } + + dstOffset += srcRegSize; + size -= srcRegSize; + } + } + if (size >= 2 * REGSIZE_BYTES) { regNumber tempReg2 = node->ExtractTempReg(RBM_ALLINT); diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 3596de621d664b..464f031a677f7b 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -715,14 +715,33 @@ int GenTree::GetRegisterDstCount(Compiler* compiler) const #endif } #endif - -#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS) - if (OperIs(GT_HWINTRINSIC)) + else if (OperIsHWIntrinsic()) { assert(TypeGet() == TYP_STRUCT); +#ifdef TARGET_ARM64 + const GenTreeHWIntrinsic* intrinsic = AsHWIntrinsic(); + const NamedIntrinsic intrinsicId = intrinsic->gtHWIntrinsicId; + assert(HWIntrinsicInfo::ReturnsStruct(intrinsicId)); + + switch (intrinsicId) + { + // TODO-ARM64-NYI: Support hardware intrinsics operating on multiple contiguous registers. + case NI_AdvSimd_Arm64_LoadPairScalarVector64: + case NI_AdvSimd_Arm64_LoadPairScalarVector64NonTemporal: + case NI_AdvSimd_Arm64_LoadPairVector64: + case NI_AdvSimd_Arm64_LoadPairVector64NonTemporal: + case NI_AdvSimd_Arm64_LoadPairVector128: + case NI_AdvSimd_Arm64_LoadPairVector128NonTemporal: + return 2; + + default: + unreached(); + } +#elif defined(TARGET_XARCH) return 2; - } #endif + } + if (OperIsScalarLocal()) { return AsLclVar()->GetFieldCount(compiler); diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index e2a5045e9069b4..f7c3da25fa5832 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -1840,7 +1840,7 @@ struct GenTree inline bool IsMultiRegNode() const; // Returns the number of registers defined by a multireg node. - unsigned GetMultiRegCount(); + unsigned GetMultiRegCount() const; // Returns the regIndex'th register defined by a possibly-multireg node. regNumber GetRegByIndex(int regIndex); @@ -6720,7 +6720,7 @@ struct GenTreeCopyOrReload : public GenTreeUnOp #endif } - unsigned GetRegCount() + unsigned GetRegCount() const { #if FEATURE_MULTIREG_RET // We need to return the highest index for which we have a valid register. @@ -7550,12 +7550,12 @@ inline bool GenTree::IsMultiRegNode() const return true; } #endif // FEATURE_MULTIREG_RET -#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS) - if (OperIs(GT_HWINTRINSIC)) + + if (OperIsHWIntrinsic()) { return (TypeGet() == TYP_STRUCT); } -#endif + if (IsMultiRegLclVar()) { return true; @@ -7571,7 +7571,7 @@ inline bool GenTree::IsMultiRegNode() const // Return Value: // Returns the number of registers defined by this node. // -inline unsigned GenTree::GetMultiRegCount() +inline unsigned GenTree::GetMultiRegCount() const { #if FEATURE_MULTIREG_RET if (IsMultiRegCall()) @@ -7598,13 +7598,33 @@ inline unsigned GenTree::GetMultiRegCount() return AsCopyOrReload()->GetRegCount(); } #endif // FEATURE_MULTIREG_RET -#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS) - if (OperIs(GT_HWINTRINSIC)) + + if (OperIsHWIntrinsic()) { assert(TypeGet() == TYP_STRUCT); +#ifdef TARGET_ARM64 + const GenTreeHWIntrinsic* intrinsic = AsHWIntrinsic(); + const NamedIntrinsic intrinsicId = intrinsic->gtHWIntrinsicId; + + switch (intrinsicId) + { + // TODO-ARM64-NYI: Support hardware intrinsics operating on multiple contiguous registers. + case NI_AdvSimd_Arm64_LoadPairScalarVector64: + case NI_AdvSimd_Arm64_LoadPairScalarVector64NonTemporal: + case NI_AdvSimd_Arm64_LoadPairVector64: + case NI_AdvSimd_Arm64_LoadPairVector64NonTemporal: + case NI_AdvSimd_Arm64_LoadPairVector128: + case NI_AdvSimd_Arm64_LoadPairVector128NonTemporal: + return 2; + + default: + unreached(); + } +#elif defined(TARGET_XARCH) return 2; - } #endif + } + if (OperIs(GT_LCL_VAR, GT_STORE_LCL_VAR)) { assert((gtFlags & GTF_VAR_MULTIREG) != 0); @@ -7667,13 +7687,14 @@ inline regNumber GenTree::GetRegByIndex(int regIndex) return AsCopyOrReload()->GetRegNumByIdx(regIndex); } #endif // FEATURE_MULTIREG_RET -#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS) +#ifdef FEATURE_HW_INTRINSICS if (OperIs(GT_HWINTRINSIC)) { assert(regIndex == 1); + // TODO-ARM64-NYI: Support hardware intrinsics operating on multiple contiguous registers. return AsHWIntrinsic()->GetOtherReg(); } -#endif +#endif // FEATURE_HW_INTRINSICS if (OperIs(GT_LCL_VAR, GT_STORE_LCL_VAR)) { return AsLclVar()->GetRegNumByIdx(regIndex); @@ -7724,15 +7745,26 @@ inline var_types GenTree::GetRegTypeByIndex(int regIndex) #endif // FEATURE_MULTIREG_RET -#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS) - if (OperIs(GT_HWINTRINSIC)) + if (OperIsHWIntrinsic()) { + assert(TypeGet() == TYP_STRUCT); +#ifdef TARGET_ARM64 + if (AsHWIntrinsic()->GetSimdSize() == 16) + { + return TYP_SIMD16; + } + else + { + assert(AsHWIntrinsic()->GetSimdSize() == 8); + return TYP_SIMD8; + } +#elif defined(TARGET_XARCH) // At this time, the only multi-reg HW intrinsics all return the type of their // arguments. If this changes, we will need a way to record or determine this. - assert(TypeGet() == TYP_STRUCT); return gtGetOp1()->TypeGet(); - } #endif + } + if (OperIs(GT_LCL_VAR, GT_STORE_LCL_VAR)) { if (TypeGet() == TYP_LONG) diff --git a/src/coreclr/jit/hwintrinsic.cpp b/src/coreclr/jit/hwintrinsic.cpp index f659dd40a669b6..6197a3fb394799 100644 --- a/src/coreclr/jit/hwintrinsic.cpp +++ b/src/coreclr/jit/hwintrinsic.cpp @@ -843,14 +843,23 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, { unsigned int sizeBytes; simdBaseJitType = getBaseJitTypeAndSizeOfSIMDType(sig->retTypeSigClass, &sizeBytes); - retType = getSIMDTypeForSize(sizeBytes); - assert(sizeBytes != 0); - // We want to return early here for cases where retType was TYP_STRUCT as per method signature and - // rather than deferring the decision after getting the simdBaseJitType of arg. - if (!isSupportedBaseType(intrinsic, simdBaseJitType)) + if (HWIntrinsicInfo::ReturnsStruct(intrinsic)) { - return nullptr; + assert(sizeBytes == 0); + } + else + { + assert(sizeBytes != 0); + + // We want to return early here for cases where retType was TYP_STRUCT as per method signature and + // rather than deferring the decision after getting the simdBaseJitType of arg. + if (!isSupportedBaseType(intrinsic, simdBaseJitType)) + { + return nullptr; + } + + retType = getSIMDTypeForSize(sizeBytes); } } @@ -1224,6 +1233,12 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, // retNode->gtFlags |= (GTF_GLOB_REF | GTF_EXCEPT); } + + if (HWIntrinsicInfo::ReturnsStruct(intrinsic)) + { + retNode->SetLayout(typGetObjLayout(sig->retTypeSigClass)); + } + return retNode; } diff --git a/src/coreclr/jit/hwintrinsic.h b/src/coreclr/jit/hwintrinsic.h index 0b35ca719b6e2f..3bb87319c9d512 100644 --- a/src/coreclr/jit/hwintrinsic.h +++ b/src/coreclr/jit/hwintrinsic.h @@ -113,50 +113,52 @@ enum HWIntrinsicFlag : unsigned int // but may be table-driven in the back-end HW_Flag_SpecialImport = 0x100, + // The intrinsic returns a struct. + HW_Flag_ReturnsStruct = 0x200, + // The below is for defining platform-specific flags #if defined(TARGET_XARCH) // Full range IMM intrinsic // - the immediate value is valid on the full range of imm8 (0-255) - HW_Flag_FullRangeIMM = 0x200, + HW_Flag_FullRangeIMM = 0x400, // Maybe IMM // the intrinsic has either imm or Vector overloads - HW_Flag_MaybeIMM = 0x400, + HW_Flag_MaybeIMM = 0x800, // Copy Upper bits // some SIMD scalar intrinsics need the semantics of copying upper bits from the source operand - HW_Flag_CopyUpperBits = 0x800, + HW_Flag_CopyUpperBits = 0x1000, // Maybe Memory Load/Store // - some intrinsics may have pointer overloads but without HW_Category_MemoryLoad/HW_Category_MemoryStore - HW_Flag_MaybeMemoryLoad = 0x1000, - HW_Flag_MaybeMemoryStore = 0x2000, + HW_Flag_MaybeMemoryLoad = 0x2000, + HW_Flag_MaybeMemoryStore = 0x4000, // No Read/Modify/Write Semantics // the intrinsic doesn't have read/modify/write semantics in two/three-operand form. - HW_Flag_NoRMWSemantics = 0x4000, + HW_Flag_NoRMWSemantics = 0x8000, // NoContainment // the intrinsic cannot be handled by containment, // all the intrinsic that have explicit memory load/store semantics should have this flag - HW_Flag_NoContainment = 0x8000, + HW_Flag_NoContainment = 0x10000 #elif defined(TARGET_ARM64) // The intrinsic has an immediate operand // - the value can be (and should be) encoded in a corresponding instruction when the operand value is constant - HW_Flag_HasImmediateOperand = 0x200, + HW_Flag_HasImmediateOperand = 0x400, // The intrinsic has read/modify/write semantics in multiple-operands form. - HW_Flag_HasRMWSemantics = 0x400, + HW_Flag_HasRMWSemantics = 0x800, // The intrinsic operates on the lower part of a SIMD register // - the upper part of the source registers are ignored // - the upper part of the destination register is zeroed - HW_Flag_SIMDScalar = 0x800, + HW_Flag_SIMDScalar = 0x1000, // The intrinsic supports some sort of containment analysis - HW_Flag_SupportsContainment = 0x1000 - + HW_Flag_SupportsContainment = 0x2000 #else #error Unsupported platform #endif @@ -701,6 +703,12 @@ struct HWIntrinsicInfo return (flags & HW_Flag_SpecialImport) != 0; } + static bool ReturnsStruct(NamedIntrinsic id) + { + const HWIntrinsicFlag flags = lookupFlags(id); + return (flags & HW_Flag_ReturnsStruct) != 0; + } + #ifdef TARGET_ARM64 static bool SIMDScalar(NamedIntrinsic id) { diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index 3352c9ba595710..e27d2066ea9a8b 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -655,6 +655,18 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) } break; + case NI_AdvSimd_Arm64_LoadPairVector128: + case NI_AdvSimd_Arm64_LoadPairVector128NonTemporal: + case NI_AdvSimd_Arm64_LoadPairVector64: + case NI_AdvSimd_Arm64_LoadPairVector64NonTemporal: + GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, node->GetOtherReg(), op1Reg); + break; + + case NI_AdvSimd_Arm64_LoadPairScalarVector64: + case NI_AdvSimd_Arm64_LoadPairScalarVector64NonTemporal: + GetEmitter()->emitIns_R_R_R(ins, emitTypeSize(intrin.baseType), targetReg, node->GetOtherReg(), op1Reg); + break; + case NI_AdvSimd_Store: GetEmitter()->emitIns_R_R(ins, emitSize, op2Reg, op1Reg, opt); break; diff --git a/src/coreclr/jit/hwintrinsiclistarm64.h b/src/coreclr/jit/hwintrinsiclistarm64.h index 71c3f56121a1e3..8eb383ea52c8fa 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64.h +++ b/src/coreclr/jit/hwintrinsiclistarm64.h @@ -419,6 +419,12 @@ HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplySubtractBySelectedScalar, HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplySubtractScalarBySelectedScalar, 8, 4, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmls, INS_fmls}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) HARDWARE_INTRINSIC(AdvSimd_Arm64, InsertSelectedScalar, -1, 4, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins}, HW_Category_SIMD, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_NoJmpTableIMM|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd_Arm64, LoadAndReplicateToVector128, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ld1r, INS_ld1r, INS_invalid, INS_ld1r}, HW_Category_MemoryLoad, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, LoadPairScalarVector64, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ldp, INS_ldp, INS_invalid, INS_invalid, INS_ldp, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_ReturnsStruct|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, LoadPairScalarVector64NonTemporal, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ldnp, INS_ldnp, INS_invalid, INS_invalid, INS_ldnp, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_ReturnsStruct|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, LoadPairVector64, 8, 1, {INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_ReturnsStruct|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, LoadPairVector64NonTemporal, 8, 1, {INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_ReturnsStruct|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, LoadPairVector128, 16, 1, {INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_ReturnsStruct|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, LoadPairVector128NonTemporal, 16, 1, {INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_ReturnsStruct|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd_Arm64, Max, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmax}, HW_Category_SIMD, HW_Flag_Commutative) HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxAcross, -1, 1, {INS_smaxv, INS_umaxv, INS_smaxv, INS_umaxv, INS_smaxv, INS_umaxv, INS_invalid, INS_invalid, INS_fmaxv, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxNumber, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnm}, HW_Category_SIMD, HW_Flag_Commutative) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index fc8544f9138ba6..d8372865bfa539 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -1287,8 +1287,20 @@ GenTree* Compiler::impAssignStructPtr(GenTree* destAddr, ilOffset = impCurStmtOffs; } - assert(src->OperIs(GT_LCL_VAR, GT_LCL_FLD, GT_FIELD, GT_IND, GT_OBJ, GT_CALL, GT_MKREFANY, GT_RET_EXPR, GT_COMMA) || - (src->TypeGet() != TYP_STRUCT && src->OperIsSimdOrHWintrinsic())); +#if defined(FEATURE_HW_INTRINSICS) && defined(DEBUG) + if (src->OperIs(GT_HWINTRINSIC)) + { + const GenTreeHWIntrinsic* intrinsic = src->AsHWIntrinsic(); + const bool returnsStruct = HWIntrinsicInfo::ReturnsStruct(intrinsic->gtHWIntrinsicId); + assert((src->TypeGet() == TYP_STRUCT) == returnsStruct); + } + else +#endif + { + assert(src->OperIs(GT_LCL_VAR, GT_LCL_FLD, GT_FIELD, GT_IND, GT_OBJ, GT_CALL, GT_MKREFANY, GT_RET_EXPR, + GT_COMMA) || + ((src->TypeGet() != TYP_STRUCT) && src->OperIsSIMD())); + } var_types asgType = src->TypeGet(); diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index 916cb93e187a93..3c906e932f6c6a 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -1781,12 +1781,6 @@ bool Compiler::StructPromotionHelper::CanPromoteStructType(CORINFO_CLASS_HANDLE return false; } - // Don't struct promote if we have an CUSTOMLAYOUT flag on an HFA type - if (StructHasCustomLayout(typeFlags) && compiler->IsHfa(typeHnd)) - { - return false; - } - #ifdef TARGET_ARM // On ARM, we have a requirement on the struct alignment; see below. unsigned structAlignment = roundUp(compHandle->getClassAlignmentRequirement(typeHnd), TARGET_POINTER_SIZE); diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index 6774a4ef1766b4..8c4d1d0c4b94b8 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -290,6 +290,16 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindHelper; } } + else if (src->OperIsHWIntrinsic()) + { + if (blkNode->OperIs(GT_STORE_OBJ)) + { + assert(!blkNode->AsObj()->GetLayout()->HasGCPtr()); + blkNode->SetOper(GT_STORE_BLK); + } + blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindUnroll; + ContainBlockStoreAddress(blkNode, size, dstAddr); + } else { assert(src->OperIs(GT_IND, GT_LCL_VAR, GT_LCL_FLD)); diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index e137b7f678a0d7..0f1248f48f45e5 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -152,13 +152,14 @@ void lsraAssignRegToTree(GenTree* tree, regNumber reg, unsigned regIdx) putArg->SetRegNumByIdx(reg, regIdx); } #endif // FEATURE_ARG_SPLIT -#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS) +#ifdef FEATURE_HW_INTRINSICS else if (tree->OperIs(GT_HWINTRINSIC)) { assert(regIdx == 1); + // TODO-ARM64-NYI: Support hardware intrinsics operating on multiple contiguous registers. tree->AsHWIntrinsic()->SetOtherReg(reg); } -#endif +#endif // FEATURE_HW_INTRINSICS else if (tree->OperIs(GT_LCL_VAR, GT_STORE_LCL_VAR)) { tree->AsLclVar()->SetRegNumByIdx(reg, regIdx); diff --git a/src/coreclr/jit/lsra.h b/src/coreclr/jit/lsra.h index eda5d014c658a7..bd718cba7e56ea 100644 --- a/src/coreclr/jit/lsra.h +++ b/src/coreclr/jit/lsra.h @@ -1878,7 +1878,7 @@ class LinearScan : public LinearScanInterface #endif // FEATURE_SIMD #ifdef FEATURE_HW_INTRINSICS - int BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree); + int BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCount); #endif // FEATURE_HW_INTRINSICS int BuildPutArgStk(GenTreePutArgStk* argNode); diff --git a/src/coreclr/jit/lsraarm64.cpp b/src/coreclr/jit/lsraarm64.cpp index a7a14fdfe54f96..2243801208a9bf 100644 --- a/src/coreclr/jit/lsraarm64.cpp +++ b/src/coreclr/jit/lsraarm64.cpp @@ -345,7 +345,7 @@ int LinearScan::BuildNode(GenTree* tree) #ifdef FEATURE_HW_INTRINSICS case GT_HWINTRINSIC: - srcCount = BuildHWIntrinsic(tree->AsHWIntrinsic()); + srcCount = BuildHWIntrinsic(tree->AsHWIntrinsic(), &dstCount); break; #endif // FEATURE_HW_INTRINSICS @@ -905,16 +905,28 @@ int LinearScan::BuildSIMD(GenTreeSIMD* simdTree) // // Arguments: // tree - The GT_HWINTRINSIC node of interest +// pDstCount - OUT parameter - the number of registers defined for the given node // // Return Value: // The number of sources consumed by this node. // -int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree) +int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCount) { + assert(pDstCount != nullptr); + const HWIntrinsic intrin(intrinsicTree); int srcCount = 0; - int dstCount = intrinsicTree->IsValue() ? 1 : 0; + int dstCount = 0; + + if (HWIntrinsicInfo::ReturnsStruct(intrin.id)) + { + dstCount = intrinsicTree->GetMultiRegCount(); + } + else if (intrinsicTree->IsValue()) + { + dstCount = 1; + } const bool hasImmediateOperand = HWIntrinsicInfo::HasImmediateOperand(intrin.id); @@ -1159,15 +1171,21 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree) buildInternalRegisterUses(); - if (dstCount == 1) + if ((dstCount == 1) || (dstCount == 2)) { BuildDef(intrinsicTree); + + if (dstCount == 2) + { + BuildDef(intrinsicTree, RBM_NONE, 1); + } } else { assert(dstCount == 0); } + *pDstCount = dstCount; return srcCount; } #endif diff --git a/src/coreclr/jit/lsraarmarch.cpp b/src/coreclr/jit/lsraarmarch.cpp index 8fb7ca7992f4bb..0a18e79eb2bb6d 100644 --- a/src/coreclr/jit/lsraarmarch.cpp +++ b/src/coreclr/jit/lsraarmarch.cpp @@ -701,8 +701,20 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode) { useCount += BuildAddrUses(dstAddr->AsAddrMode()->Base()); } - - if (srcAddrOrFill != nullptr) +#ifdef TARGET_ARM64 + if (src->IsMultiRegNode()) + { + assert(src->OperIsHWIntrinsic()); + const int srcCount = src->GetMultiRegCount(); + for (int i = 0; i < srcCount; ++i) + { + BuildUse(src, RBM_NONE, i); + } + useCount += srcCount; + } + else +#endif + if (srcAddrOrFill != nullptr) { if (!srcAddrOrFill->isContained()) { diff --git a/src/coreclr/jit/lsraxarch.cpp b/src/coreclr/jit/lsraxarch.cpp index 854e4521ec9001..7e54c75ff7807f 100644 --- a/src/coreclr/jit/lsraxarch.cpp +++ b/src/coreclr/jit/lsraxarch.cpp @@ -340,7 +340,7 @@ int LinearScan::BuildNode(GenTree* tree) #ifdef FEATURE_HW_INTRINSICS case GT_HWINTRINSIC: - srcCount = BuildHWIntrinsic(tree->AsHWIntrinsic()); + srcCount = BuildHWIntrinsic(tree->AsHWIntrinsic(), &dstCount); break; #endif // FEATURE_HW_INTRINSICS @@ -2063,12 +2063,15 @@ int LinearScan::BuildSIMD(GenTreeSIMD* simdTree) // // Arguments: // tree - The GT_HWINTRINSIC node of interest +// pDstCount - OUT parameter - the number of registers defined for the given node // // Return Value: // The number of sources consumed by this node. // -int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree) +int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCount) { + assert(pDstCount != nullptr); + NamedIntrinsic intrinsicId = intrinsicTree->gtHWIntrinsicId; var_types baseType = intrinsicTree->GetSimdBaseType(); HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsicId); @@ -2524,6 +2527,7 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree) assert(dstCount == 0); } + *pDstCount = dstCount; return srcCount; } #endif diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index e53c2d9e8ff757..55b4f57b034659 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -10799,6 +10799,17 @@ GenTree* Compiler::fgMorphBlockOperand(GenTree* tree, var_types asgType, unsigne assert(blockWidth == info.compCompHnd->getClassSize(call->gtRetClsHnd)); #endif } +#ifdef TARGET_ARM64 + else if (effectiveVal->OperIsHWIntrinsic()) + { + needsIndirection = false; +#ifdef DEBUG + GenTreeHWIntrinsic* intrinsic = effectiveVal->AsHWIntrinsic(); + assert(intrinsic->TypeGet() == TYP_STRUCT); + assert(HWIntrinsicInfo::ReturnsStruct(intrinsic->gtHWIntrinsicId)); +#endif + } +#endif // TARGET_ARM64 if (lclNode != nullptr) { @@ -11206,6 +11217,19 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree) requiresCopyBlock = true; } +#ifdef TARGET_ARM64 + if (src->OperIsHWIntrinsic()) + { + requiresCopyBlock = true; +#ifdef DEBUG + JITDUMP(" src is a hardware intrinsic"); + GenTreeHWIntrinsic* intrinsic = src->AsHWIntrinsic(); + assert(intrinsic->TypeGet() == TYP_STRUCT); + assert(HWIntrinsicInfo::ReturnsStruct(intrinsic->gtHWIntrinsicId)); +#endif + } +#endif // TARGET_ARM64 + // If we passed the above checks, then we will check these two if (!requiresCopyBlock) { diff --git a/src/libraries/System.Collections/src/System/Collections/BitArray.cs b/src/libraries/System.Collections/src/System/Collections/BitArray.cs index 1fddd453b92009..325adcc04f833e 100644 --- a/src/libraries/System.Collections/src/System/Collections/BitArray.cs +++ b/src/libraries/System.Collections/src/System/Collections/BitArray.cs @@ -1000,7 +1000,7 @@ public unsafe void CopyTo(Array array, int index) } } } - else if (AdvSimd.IsSupported) + else if (AdvSimd.Arm64.IsSupported) { Vector128 ones = Vector128.Create((byte)1); fixed (bool* destination = &boolArray[index]) @@ -1030,12 +1030,12 @@ public unsafe void CopyTo(Array array, int index) Vector128 shuffledLower = AdvSimd.Arm64.ZipLow(vector, vector); Vector128 extractedLower = AdvSimd.And(shuffledLower, s_bitMask128); Vector128 normalizedLower = AdvSimd.Min(extractedLower, ones); - AdvSimd.Store((byte*)destination + i, normalizedLower); Vector128 shuffledHigher = AdvSimd.Arm64.ZipHigh(vector, vector); Vector128 extractedHigher = AdvSimd.And(shuffledHigher, s_bitMask128); Vector128 normalizedHigher = AdvSimd.Min(extractedHigher, ones); - AdvSimd.Store((byte*)destination + i + Vector128.Count, normalizedHigher); + + AdvSimd.Arm64.StorePair((byte*)destination + i, normalizedLower, normalizedHigher); } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.PlatformNotSupported.cs index 2fcc2efcfc9cad..d53236e7116da8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.PlatformNotSupported.cs @@ -1567,6 +1567,236 @@ internal Arm64() { } /// public static unsafe Vector128 LoadAndReplicateToVector128(ulong* address) { throw new PlatformNotSupportedException(); } + /// + /// A64: LDP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64(byte* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64(double* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64(short* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64(int* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64(long* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64(sbyte* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64(float* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64(ushort* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64(uint* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64(ulong* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDP St1, St2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairScalarVector64(int* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDP St1, St2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairScalarVector64(float* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDP St1, St2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairScalarVector64(uint* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128(byte* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128(double* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128(short* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128(int* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128(long* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128(sbyte* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128(float* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128(ushort* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128(uint* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128(ulong* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64NonTemporal(byte* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64NonTemporal(double* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64NonTemporal(short* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64NonTemporal(int* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64NonTemporal(long* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64NonTemporal(sbyte* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64NonTemporal(float* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64NonTemporal(ushort* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64NonTemporal(uint* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64NonTemporal(ulong* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP St1, St2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairScalarVector64NonTemporal(int* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP St1, St2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairScalarVector64NonTemporal(float* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP St1, St2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairScalarVector64NonTemporal(uint* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128NonTemporal(byte* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128NonTemporal(double* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128NonTemporal(short* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128NonTemporal(int* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128NonTemporal(long* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128NonTemporal(sbyte* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128NonTemporal(float* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128NonTemporal(ushort* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128NonTemporal(uint* address) { throw new PlatformNotSupportedException(); } + + /// + /// A64: LDNP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128NonTemporal(ulong* address) { throw new PlatformNotSupportedException(); } + /// /// float64x2_t vmaxq_f64 (float64x2_t a, float64x2_t b) /// A64: FMAX Vd.2D, Vn.2D, Vm.2D diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.cs index a8db248ef75c22..11177c4fd59ee5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.cs @@ -1565,6 +1565,236 @@ internal Arm64() { } /// public static unsafe Vector128 LoadAndReplicateToVector128(ulong* address) => LoadAndReplicateToVector128(address); + /// + /// A64: LDP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64(byte* address) => LoadPairVector64(address); + + /// + /// A64: LDP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64(double* address) => LoadPairVector64(address); + + /// + /// A64: LDP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64(short* address) => LoadPairVector64(address); + + /// + /// A64: LDP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64(int* address) => LoadPairVector64(address); + + /// + /// A64: LDP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64(long* address) => LoadPairVector64(address); + + /// + /// A64: LDP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64(sbyte* address) => LoadPairVector64(address); + + /// + /// A64: LDP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64(float* address) => LoadPairVector64(address); + + /// + /// A64: LDP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64(ushort* address) => LoadPairVector64(address); + + /// + /// A64: LDP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64(uint* address) => LoadPairVector64(address); + + /// + /// A64: LDP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64(ulong* address) => LoadPairVector64(address); + + /// + /// A64: LDP St1, St2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairScalarVector64(int* address) => LoadPairScalarVector64(address); + + /// + /// A64: LDP St1, St2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairScalarVector64(float* address) => LoadPairScalarVector64(address); + + /// + /// A64: LDP St1, St2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairScalarVector64(uint* address) => LoadPairScalarVector64(address); + + /// + /// A64: LDP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128(byte* address) => LoadPairVector128(address); + + /// + /// A64: LDP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128(double* address) => LoadPairVector128(address); + + /// + /// A64: LDP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128(short* address) => LoadPairVector128(address); + + /// + /// A64: LDP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128(int* address) => LoadPairVector128(address); + + /// + /// A64: LDP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128(long* address) => LoadPairVector128(address); + + /// + /// A64: LDP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128(sbyte* address) => LoadPairVector128(address); + + /// + /// A64: LDP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128(float* address) => LoadPairVector128(address); + + /// + /// A64: LDP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128(ushort* address) => LoadPairVector128(address); + + /// + /// A64: LDP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128(uint* address) => LoadPairVector128(address); + + /// + /// A64: LDP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128(ulong* address) => LoadPairVector128(address); + + /// + /// A64: LDNP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64NonTemporal(byte* address) => LoadPairVector64NonTemporal(address); + + /// + /// A64: LDNP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64NonTemporal(double* address) => LoadPairVector64NonTemporal(address); + + /// + /// A64: LDNP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64NonTemporal(short* address) => LoadPairVector64NonTemporal(address); + + /// + /// A64: LDNP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64NonTemporal(int* address) => LoadPairVector64NonTemporal(address); + + /// + /// A64: LDNP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64NonTemporal(long* address) => LoadPairVector64NonTemporal(address); + + /// + /// A64: LDNP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64NonTemporal(sbyte* address) => LoadPairVector64NonTemporal(address); + + /// + /// A64: LDNP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64NonTemporal(float* address) => LoadPairVector64NonTemporal(address); + + /// + /// A64: LDNP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64NonTemporal(ushort* address) => LoadPairVector64NonTemporal(address); + + /// + /// A64: LDNP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64NonTemporal(uint* address) => LoadPairVector64NonTemporal(address); + + /// + /// A64: LDNP Dt1, Dt2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairVector64NonTemporal(ulong* address) => LoadPairVector64NonTemporal(address); + + /// + /// A64: LDNP St1, St2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairScalarVector64NonTemporal(int* address) => LoadPairScalarVector64NonTemporal(address); + + /// + /// A64: LDNP St1, St2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairScalarVector64NonTemporal(float* address) => LoadPairScalarVector64NonTemporal(address); + + /// + /// A64: LDNP St1, St2, [Xn] + /// + public static unsafe (Vector64 Value1, Vector64 Value2) LoadPairScalarVector64NonTemporal(uint* address) => LoadPairScalarVector64NonTemporal(address); + + /// + /// A64: LDNP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128NonTemporal(byte* address) => LoadPairVector128NonTemporal(address); + + /// + /// A64: LDNP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128NonTemporal(double* address) => LoadPairVector128NonTemporal(address); + + /// + /// A64: LDNP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128NonTemporal(short* address) => LoadPairVector128NonTemporal(address); + + /// + /// A64: LDNP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128NonTemporal(int* address) => LoadPairVector128NonTemporal(address); + + /// + /// A64: LDNP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128NonTemporal(long* address) => LoadPairVector128NonTemporal(address); + + /// + /// A64: LDNP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128NonTemporal(sbyte* address) => LoadPairVector128NonTemporal(address); + + /// + /// A64: LDNP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128NonTemporal(float* address) => LoadPairVector128NonTemporal(address); + + /// + /// A64: LDNP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128NonTemporal(ushort* address) => LoadPairVector128NonTemporal(address); + + /// + /// A64: LDNP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128NonTemporal(uint* address) => LoadPairVector128NonTemporal(address); + + /// + /// A64: LDNP Qt1, Qt2, [Xn] + /// + public static unsafe (Vector128 Value1, Vector128 Value2) LoadPairVector128NonTemporal(ulong* address) => LoadPairVector128NonTemporal(address); + /// /// float64x2_t vmaxq_f64 (float64x2_t a, float64x2_t b) /// A64: FMAX Vd.2D, Vn.2D, Vm.2D diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/ASCIIUtility.cs b/src/libraries/System.Private.CoreLib/src/System/Text/ASCIIUtility.cs index e490a2dd2d051c..31b0b1ad869b56 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/ASCIIUtility.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/ASCIIUtility.cs @@ -356,8 +356,7 @@ private static unsafe nuint GetIndexOfFirstNonAsciiByte_Intrinsified(byte* pBuff } else if (AdvSimd.Arm64.IsSupported) { - Vector128 firstVector = AdvSimd.LoadVector128(pBuffer); - Vector128 secondVector = AdvSimd.LoadVector128(pBuffer + SizeOfVector128); + (Vector128 firstVector, Vector128 secondVector) = AdvSimd.Arm64.LoadPairVector128(pBuffer); currentAdvSimdIndex = (uint)GetIndexOfFirstNonAsciiByteInLane_AdvSimd(firstVector, bitmask); secondAdvSimdIndex = (uint)GetIndexOfFirstNonAsciiByteInLane_AdvSimd(secondVector, bitmask); 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 6ad7fc3eb9842b..2db3cfba8bf540 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -2172,6 +2172,52 @@ internal Arm64() { } public unsafe static System.Runtime.Intrinsics.Vector128 LoadAndReplicateToVector128(double* address) { throw null; } public unsafe static System.Runtime.Intrinsics.Vector128 LoadAndReplicateToVector128(long* address) { throw null; } public unsafe static System.Runtime.Intrinsics.Vector128 LoadAndReplicateToVector128(ulong* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairScalarVector64(int* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairScalarVector64(float* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairScalarVector64(uint* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairScalarVector64NonTemporal(int* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairScalarVector64NonTemporal(float* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairScalarVector64NonTemporal(uint* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadPairVector128(byte* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadPairVector128(double* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadPairVector128(short* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadPairVector128(int* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadPairVector128(long* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadPairVector128(sbyte* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadPairVector128(float* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadPairVector128(ushort* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadPairVector128(uint* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadPairVector128(ulong* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadPairVector128NonTemporal(byte* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadPairVector128NonTemporal(double* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadPairVector128NonTemporal(short* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadPairVector128NonTemporal(int* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadPairVector128NonTemporal(long* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadPairVector128NonTemporal(sbyte* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadPairVector128NonTemporal(float* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadPairVector128NonTemporal(ushort* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadPairVector128NonTemporal(uint* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector128 Value1, System.Runtime.Intrinsics.Vector128 Value2) LoadPairVector128NonTemporal(ulong* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairVector64(byte* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairVector64(double* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairVector64(short* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairVector64(int* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairVector64(long* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairVector64(sbyte* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairVector64(float* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairVector64(ushort* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairVector64(uint* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairVector64(ulong* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairVector64NonTemporal(byte* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairVector64NonTemporal(double* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairVector64NonTemporal(short* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairVector64NonTemporal(int* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairVector64NonTemporal(long* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairVector64NonTemporal(sbyte* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairVector64NonTemporal(float* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairVector64NonTemporal(ushort* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairVector64NonTemporal(uint* address) { throw null; } + public unsafe static (System.Runtime.Intrinsics.Vector64 Value1, System.Runtime.Intrinsics.Vector64 Value2) LoadPairVector64NonTemporal(ulong* address) { throw null; } public static System.Runtime.Intrinsics.Vector128 Max(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 MaxAcross(System.Runtime.Intrinsics.Vector128 value) { throw null; } public static System.Runtime.Intrinsics.Vector64 MaxAcross(System.Runtime.Intrinsics.Vector128 value) { throw null; } diff --git a/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/OptimizedInboxTextEncoder.AdvSimd64.cs b/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/OptimizedInboxTextEncoder.AdvSimd64.cs index 9a2acba64d360b..f9647bcba2f7f8 100644 --- a/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/OptimizedInboxTextEncoder.AdvSimd64.cs +++ b/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/OptimizedInboxTextEncoder.AdvSimd64.cs @@ -166,9 +166,10 @@ private unsafe nuint GetIndexOfFirstCharToEncodeAdvSimd64(char* pData, nuint len // Read 16 chars at a time into 2x 128-bit vectors, then pack into a single 128-bit vector. // We turn 16 chars (256 bits) into 16 nibbles (64 bits) during this process. + (Vector128 lowerVector, Vector128 upperVector) = AdvSimd.Arm64.LoadPairVector128((/* unaligned */ short*)(pData + i)); Vector128 packed = AdvSimd.ExtractNarrowingSaturateUnsignedUpper( - AdvSimd.ExtractNarrowingSaturateUnsignedLower(AdvSimd.LoadVector128((/* unaligned */ short*)(pData + i))), - AdvSimd.LoadVector128((/* unaligned */ short*)(pData + 8 + i))); + AdvSimd.ExtractNarrowingSaturateUnsignedLower(lowerVector), + upperVector); var allowedCodePointsShuffled = AdvSimd.Arm64.VectorTableLookup(allowedCodePoints, AdvSimd.And(packed, vec0xF)); var vecPowersOfTwoShuffled = AdvSimd.Arm64.VectorTableLookup(vecPowersOfTwo, AdvSimd.ShiftRightArithmetic(packed.AsSByte(), 4).AsByte()); var result = AdvSimd.CompareTest(allowedCodePointsShuffled, vecPowersOfTwoShuffled); diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index 7d563842c16107..87cbb358036d1f 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -616,6 +616,21 @@ simd_class_to_llvm_type (EmitContext *ctx, MonoClass *klass) } } +static LLVMTypeRef +simd_valuetuple_to_llvm_type (EmitContext *ctx, MonoClass *klass) +{ + const char *klass_name = m_class_get_name (klass); + if (!strcmp (klass_name, "ValueTuple`2")) { + MonoType *etype = mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]; + if (etype->type != MONO_TYPE_GENERICINST) + g_assert_not_reached (); + MonoClass *eklass = etype->data.generic_class->cached_class; + LLVMTypeRef ltype = simd_class_to_llvm_type (ctx, eklass); + return LLVMArrayType (ltype, 2); + } + g_assert_not_reached (); +} + /* Return the 128 bit SIMD type corresponding to the mono type TYPE */ static inline G_GNUC_UNUSED LLVMTypeRef type_to_sse_type (int type) @@ -10452,6 +10467,49 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) values [ins->dreg] = result; break; } + case OP_ARM64_LDNP: + case OP_ARM64_LDNP_SCALAR: + case OP_ARM64_LDP: + case OP_ARM64_LDP_SCALAR: { + const char *oname = NULL; + gboolean nontemporal = FALSE; + gboolean scalar = FALSE; + switch (ins->opcode) { + case OP_ARM64_LDNP: oname = "arm64_ldnp"; nontemporal = TRUE; break; + case OP_ARM64_LDNP_SCALAR: oname = "arm64_ldnp_scalar"; nontemporal = TRUE; scalar = TRUE; break; + case OP_ARM64_LDP: oname = "arm64_ldp"; break; + case OP_ARM64_LDP_SCALAR: oname = "arm64_ldp_scalar"; scalar = TRUE; break; + } + if (!addresses [ins->dreg]) + addresses [ins->dreg] = build_named_alloca (ctx, m_class_get_byval_arg (ins->klass), oname); + LLVMTypeRef ret_t = simd_valuetuple_to_llvm_type (ctx, ins->klass); + LLVMTypeRef vec_t = LLVMGetElementType (ret_t); + LLVMValueRef ix = const_int32 (1); + LLVMTypeRef src_t = LLVMPointerType (scalar ? LLVMGetElementType (vec_t) : vec_t, 0); + LLVMValueRef src0 = convert (ctx, lhs, src_t); + LLVMValueRef src1 = LLVMBuildGEP (builder, src0, &ix, 1, oname); + LLVMValueRef vals [] = { src0, src1 }; + for (int i = 0; i < 2; ++i) { + vals [i] = LLVMBuildLoad (builder, vals [i], oname); + if (nontemporal) + set_nontemporal_flag (vals [i]); + } + unsigned int vec_sz = mono_llvm_get_prim_size_bits (vec_t); + if (scalar) { + g_assert (vec_sz == 64); + LLVMValueRef undef = LLVMGetUndef (vec_t); + for (int i = 0; i < 2; ++i) + vals [i] = LLVMBuildInsertElement (builder, undef, vals [i], const_int32 (0), oname); + } + LLVMValueRef val = LLVMGetUndef (ret_t); + for (int i = 0; i < 2; ++i) + val = LLVMBuildInsertValue (builder, val, vals [i], i, oname); + LLVMTypeRef retptr_t = LLVMPointerType (ret_t, 0); + LLVMValueRef dst = convert (ctx, addresses [ins->dreg], retptr_t); + LLVMBuildStore (builder, val, dst); + values [ins->dreg] = vec_sz == 64 ? val : NULL; + break; + } case OP_ARM64_ST1: { LLVMTypeRef t = LLVMTypeOf (rhs); LLVMValueRef address = convert (ctx, lhs, LLVMPointerType (t, 0)); diff --git a/src/mono/mono/mini/mini-ops.h b/src/mono/mono/mini/mini-ops.h index 25dd6d8fd6e9d6..eaa8a27160dad2 100644 --- a/src/mono/mono/mini/mini-ops.h +++ b/src/mono/mono/mini/mini-ops.h @@ -1604,6 +1604,15 @@ MINI_OP3(OP_ARM64_LD1_INSERT, "arm64_ld1_insert", XREG, IREG, XREG, IREG) MINI_OP(OP_ARM64_LD1, "arm64_ld1", XREG, IREG, NONE) MINI_OP(OP_ARM64_LD1R, "arm64_ld1r", XREG, IREG, NONE) +/* Loads two consecutive vector (or scalar) values into a pair of + * vector registers. Returns a ValueTuple in a vreg. klass must be set to the + * MonoClass representing the ValueTuple return type of the op. + */ +MINI_OP(OP_ARM64_LDNP, "arm64_ldnp", VREG, IREG, NONE) +MINI_OP(OP_ARM64_LDNP_SCALAR, "arm64_ldnp_scalar", VREG, IREG, NONE) +MINI_OP(OP_ARM64_LDP, "arm64_ldp", VREG, IREG, NONE) +MINI_OP(OP_ARM64_LDP_SCALAR, "arm64_ldp_scalar", VREG, IREG, NONE) + MINI_OP(OP_ARM64_ST1, "arm64_st1", NONE, IREG, XREG) MINI_OP(OP_ARM64_SXTL, "arm64_sxtl", XREG, XREG, NONE) MINI_OP(OP_ARM64_SXTL2, "arm64_sxtl2", XREG, XREG, NONE) diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index 9b4fce55bc0a0b..3a246d4b06b668 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -196,6 +196,9 @@ emit_simd_ins (MonoCompile *cfg, MonoClass *klass, int opcode, int sreg1, int sr } else if (spec [MONO_INST_DEST] == 'f') { ins->dreg = alloc_freg (cfg); ins->type = STACK_R8; + } else if (spec [MONO_INST_DEST] == 'v') { + ins->dreg = alloc_dreg (cfg, STACK_VTYPE); + ins->type = STACK_VTYPE; } ins->sreg1 = sreg1; ins->sreg2 = sreg2; @@ -1210,6 +1213,12 @@ static SimdIntrinsic advsimd_methods [] = { {SN_LoadAndInsertScalar, OP_ARM64_LD1_INSERT}, {SN_LoadAndReplicateToVector128, OP_ARM64_LD1R}, {SN_LoadAndReplicateToVector64, OP_ARM64_LD1R}, + {SN_LoadPairScalarVector64, OP_ARM64_LDP_SCALAR}, + {SN_LoadPairScalarVector64NonTemporal, OP_ARM64_LDNP_SCALAR}, + {SN_LoadPairVector128, OP_ARM64_LDP}, + {SN_LoadPairVector128NonTemporal, OP_ARM64_LDNP}, + {SN_LoadPairVector64, OP_ARM64_LDP}, + {SN_LoadPairVector64NonTemporal, OP_ARM64_LDNP}, {SN_LoadVector128, OP_ARM64_LD1}, {SN_LoadVector64, OP_ARM64_LD1}, {SN_Max, OP_XOP_OVR_X_X_X, INTRINS_AARCH64_ADV_SIMD_SMAX, OP_XOP_OVR_X_X_X, INTRINS_AARCH64_ADV_SIMD_UMAX, OP_XOP_OVR_X_X_X, INTRINS_AARCH64_ADV_SIMD_FMAX}, diff --git a/src/mono/mono/mini/simd-methods.h b/src/mono/mono/mini/simd-methods.h index 4abd0ebb7e6a42..c4d1f7f9db1f56 100644 --- a/src/mono/mono/mini/simd-methods.h +++ b/src/mono/mono/mini/simd-methods.h @@ -372,6 +372,12 @@ METHOD(InsertSelectedScalar) METHOD(LoadAndInsertScalar) METHOD(LoadAndReplicateToVector128) METHOD(LoadAndReplicateToVector64) +METHOD(LoadPairScalarVector64) +METHOD(LoadPairScalarVector64NonTemporal) +METHOD(LoadPairVector128) +METHOD(LoadPairVector128NonTemporal) +METHOD(LoadPairVector64) +METHOD(LoadPairVector64NonTemporal) METHOD(LoadVector64) METHOD(MaxAcross) METHOD(MaxNumber) diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part2_r.csproj b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part2_r.csproj index 9e5bb852c66c37..8124d4f14f7d33 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part2_r.csproj +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part2_r.csproj @@ -46,6 +46,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -62,52 +108,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part2_ro.csproj b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part2_ro.csproj index 0f2b16160a2194..66ee5660a0f9f1 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part2_ro.csproj +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part2_ro.csproj @@ -46,6 +46,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -62,52 +108,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part3_r.csproj b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part3_r.csproj index 437f1067d10762..0a5db075b14e71 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part3_r.csproj +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part3_r.csproj @@ -8,6 +8,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -62,52 +108,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part3_ro.csproj b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part3_ro.csproj index 13580d32dfa23c..b967739de0e524 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part3_ro.csproj +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part3_ro.csproj @@ -8,6 +8,52 @@ True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -62,52 +108,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part4_r.csproj b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part4_r.csproj index 143f9a5b8ecd05..10ec5b137683b9 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part4_r.csproj +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part4_r.csproj @@ -8,6 +8,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -62,52 +108,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part4_ro.csproj b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part4_ro.csproj index 88cd888f12816d..754009ca65ed40 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part4_ro.csproj +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part4_ro.csproj @@ -8,6 +8,52 @@ True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -62,52 +108,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part5_r.csproj b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part5_r.csproj index 39e343813daa39..9175e1f1047d1f 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part5_r.csproj +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part5_r.csproj @@ -8,6 +8,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -62,40 +108,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part5_ro.csproj b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part5_ro.csproj index 66171e3eb6c9e1..fe864173832a36 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part5_ro.csproj +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part5_ro.csproj @@ -8,6 +8,52 @@ True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -62,40 +108,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part6_r.csproj b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part6_r.csproj new file mode 100644 index 00000000000000..6d9e4362963e86 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part6_r.csproj @@ -0,0 +1,49 @@ + + + Exe + true + + + Embedded + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part6_ro.csproj b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part6_ro.csproj new file mode 100644 index 00000000000000..226486a7c7cdd6 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_Part6_ro.csproj @@ -0,0 +1,49 @@ + + + Exe + true + + + Embedded + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairScalarVector64.Int32.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairScalarVector64.Int32.cs new file mode 100644 index 00000000000000..f61ade4e143ca1 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairScalarVector64.Int32.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairScalarVector64_Int32() + { + var test = new LoadPairScalarVector64_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairScalarVector64_Int32 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairScalarVector64_Int32 testClass) + { + _fld = AdvSimd.Arm64.LoadPairScalarVector64((Int32*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(Int32); + private static readonly int Op1ElementCount = RetElementCount; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairScalarVector64_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairScalarVector64((Int32*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairScalarVector64), new Type[] { typeof(Int32*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Int32*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairScalarVector64((Int32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairScalarVector64_Int32(); + test._fld = AdvSimd.Arm64.LoadPairScalarVector64((Int32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairScalarVector64((Int32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (Helpers.LoadPairScalar(firstOp, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairScalarVector64)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairScalarVector64.Single.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairScalarVector64.Single.cs new file mode 100644 index 00000000000000..0f9362df1652b7 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairScalarVector64.Single.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairScalarVector64_Single() + { + var test = new LoadPairScalarVector64_Single(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairScalarVector64_Single + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Single[] inArray, Single[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairScalarVector64_Single testClass) + { + _fld = AdvSimd.Arm64.LoadPairScalarVector64((Single*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(Single); + private static readonly int Op1ElementCount = RetElementCount; + + private static Single[] _data = new Single[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairScalarVector64_Single() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSingle(); } + _dataTable = new DataTable(_data, new Single[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairScalarVector64((Single*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairScalarVector64), new Type[] { typeof(Single*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Single*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairScalarVector64((Single*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairScalarVector64_Single(); + test._fld = AdvSimd.Arm64.LoadPairScalarVector64((Single*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairScalarVector64((Single*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (BitConverter.SingleToInt32Bits(Helpers.LoadPairScalar(firstOp, i)) != BitConverter.SingleToInt32Bits(result[i])) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairScalarVector64)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairScalarVector64.UInt32.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairScalarVector64.UInt32.cs new file mode 100644 index 00000000000000..751a5b97646ea2 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairScalarVector64.UInt32.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairScalarVector64_UInt32() + { + var test = new LoadPairScalarVector64_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairScalarVector64_UInt32 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairScalarVector64_UInt32 testClass) + { + _fld = AdvSimd.Arm64.LoadPairScalarVector64((UInt32*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(UInt32); + private static readonly int Op1ElementCount = RetElementCount; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairScalarVector64_UInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairScalarVector64((UInt32*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairScalarVector64), new Type[] { typeof(UInt32*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(UInt32*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairScalarVector64((UInt32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairScalarVector64_UInt32(); + test._fld = AdvSimd.Arm64.LoadPairScalarVector64((UInt32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairScalarVector64((UInt32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (Helpers.LoadPairScalar(firstOp, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairScalarVector64)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairScalarVector64NonTemporal.Int32.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairScalarVector64NonTemporal.Int32.cs new file mode 100644 index 00000000000000..b44c071b7af205 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairScalarVector64NonTemporal.Int32.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairScalarVector64NonTemporal_Int32() + { + var test = new LoadPairScalarVector64NonTemporal_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairScalarVector64NonTemporal_Int32 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairScalarVector64NonTemporal_Int32 testClass) + { + _fld = AdvSimd.Arm64.LoadPairScalarVector64NonTemporal((Int32*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(Int32); + private static readonly int Op1ElementCount = RetElementCount; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairScalarVector64NonTemporal_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairScalarVector64NonTemporal((Int32*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairScalarVector64NonTemporal), new Type[] { typeof(Int32*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Int32*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairScalarVector64NonTemporal((Int32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairScalarVector64NonTemporal_Int32(); + test._fld = AdvSimd.Arm64.LoadPairScalarVector64NonTemporal((Int32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairScalarVector64NonTemporal((Int32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (Helpers.LoadPairScalar(firstOp, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairScalarVector64NonTemporal)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairScalarVector64NonTemporal.Single.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairScalarVector64NonTemporal.Single.cs new file mode 100644 index 00000000000000..c91dd43973d0a3 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairScalarVector64NonTemporal.Single.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairScalarVector64NonTemporal_Single() + { + var test = new LoadPairScalarVector64NonTemporal_Single(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairScalarVector64NonTemporal_Single + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Single[] inArray, Single[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairScalarVector64NonTemporal_Single testClass) + { + _fld = AdvSimd.Arm64.LoadPairScalarVector64NonTemporal((Single*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(Single); + private static readonly int Op1ElementCount = RetElementCount; + + private static Single[] _data = new Single[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairScalarVector64NonTemporal_Single() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSingle(); } + _dataTable = new DataTable(_data, new Single[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairScalarVector64NonTemporal((Single*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairScalarVector64NonTemporal), new Type[] { typeof(Single*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Single*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairScalarVector64NonTemporal((Single*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairScalarVector64NonTemporal_Single(); + test._fld = AdvSimd.Arm64.LoadPairScalarVector64NonTemporal((Single*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairScalarVector64NonTemporal((Single*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (BitConverter.SingleToInt32Bits(Helpers.LoadPairScalar(firstOp, i)) != BitConverter.SingleToInt32Bits(result[i])) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairScalarVector64NonTemporal)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairScalarVector64NonTemporal.UInt32.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairScalarVector64NonTemporal.UInt32.cs new file mode 100644 index 00000000000000..f99e7e30dc1399 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairScalarVector64NonTemporal.UInt32.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairScalarVector64NonTemporal_UInt32() + { + var test = new LoadPairScalarVector64NonTemporal_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairScalarVector64NonTemporal_UInt32 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairScalarVector64NonTemporal_UInt32 testClass) + { + _fld = AdvSimd.Arm64.LoadPairScalarVector64NonTemporal((UInt32*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(UInt32); + private static readonly int Op1ElementCount = RetElementCount; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairScalarVector64NonTemporal_UInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairScalarVector64NonTemporal((UInt32*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairScalarVector64NonTemporal), new Type[] { typeof(UInt32*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(UInt32*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairScalarVector64NonTemporal((UInt32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairScalarVector64NonTemporal_UInt32(); + test._fld = AdvSimd.Arm64.LoadPairScalarVector64NonTemporal((UInt32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairScalarVector64NonTemporal((UInt32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (Helpers.LoadPairScalar(firstOp, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairScalarVector64NonTemporal)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.Byte.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.Byte.cs new file mode 100644 index 00000000000000..d7a46dedb266ef --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.Byte.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector128_Byte() + { + var test = new LoadPairVector128_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector128_Byte + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector128,Vector128) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector128_Byte testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector128((Byte*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 32; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector128,Vector128)>() / sizeof(Byte); + private static readonly int Op1ElementCount = RetElementCount; + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static (Vector128,Vector128) _clsVar; + + private (Vector128,Vector128) _fld; + + private DataTable _dataTable; + + public LoadPairVector128_Byte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector128((Byte*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector128), new Type[] { typeof(Byte*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Byte*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector128,Vector128))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector128((Byte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector128_Byte(); + test._fld = AdvSimd.Arm64.LoadPairVector128((Byte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector128((Byte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector128)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.Double.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.Double.cs new file mode 100644 index 00000000000000..3198050fa7201f --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.Double.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector128_Double() + { + var test = new LoadPairVector128_Double(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector128_Double + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Double[] inArray, Double[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector128,Vector128) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector128_Double testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector128((Double*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 32; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector128,Vector128)>() / sizeof(Double); + private static readonly int Op1ElementCount = RetElementCount; + + private static Double[] _data = new Double[Op1ElementCount]; + + private static (Vector128,Vector128) _clsVar; + + private (Vector128,Vector128) _fld; + + private DataTable _dataTable; + + public LoadPairVector128_Double() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetDouble(); } + _dataTable = new DataTable(_data, new Double[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector128((Double*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector128), new Type[] { typeof(Double*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Double*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector128,Vector128))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector128((Double*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector128_Double(); + test._fld = AdvSimd.Arm64.LoadPairVector128((Double*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector128((Double*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Double[] inArray = new Double[Op1ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Double[] firstOp, Double[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector128)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.Int16.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.Int16.cs new file mode 100644 index 00000000000000..3480281b1f55c8 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.Int16.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector128_Int16() + { + var test = new LoadPairVector128_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector128_Int16 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector128,Vector128) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector128_Int16 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector128((Int16*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 32; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector128,Vector128)>() / sizeof(Int16); + private static readonly int Op1ElementCount = RetElementCount; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static (Vector128,Vector128) _clsVar; + + private (Vector128,Vector128) _fld; + + private DataTable _dataTable; + + public LoadPairVector128_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector128((Int16*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector128), new Type[] { typeof(Int16*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Int16*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector128,Vector128))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector128((Int16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector128_Int16(); + test._fld = AdvSimd.Arm64.LoadPairVector128((Int16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector128((Int16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector128)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.Int32.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.Int32.cs new file mode 100644 index 00000000000000..9e31f9f8d9b4aa --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.Int32.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector128_Int32() + { + var test = new LoadPairVector128_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector128_Int32 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector128,Vector128) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector128_Int32 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector128((Int32*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 32; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector128,Vector128)>() / sizeof(Int32); + private static readonly int Op1ElementCount = RetElementCount; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static (Vector128,Vector128) _clsVar; + + private (Vector128,Vector128) _fld; + + private DataTable _dataTable; + + public LoadPairVector128_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector128((Int32*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector128), new Type[] { typeof(Int32*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Int32*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector128,Vector128))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector128((Int32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector128_Int32(); + test._fld = AdvSimd.Arm64.LoadPairVector128((Int32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector128((Int32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector128)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.Int64.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.Int64.cs new file mode 100644 index 00000000000000..200c1b3ceb4ab8 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.Int64.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector128_Int64() + { + var test = new LoadPairVector128_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector128_Int64 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector128,Vector128) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector128_Int64 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector128((Int64*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 32; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector128,Vector128)>() / sizeof(Int64); + private static readonly int Op1ElementCount = RetElementCount; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static (Vector128,Vector128) _clsVar; + + private (Vector128,Vector128) _fld; + + private DataTable _dataTable; + + public LoadPairVector128_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector128((Int64*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector128), new Type[] { typeof(Int64*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Int64*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector128,Vector128))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector128((Int64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector128_Int64(); + test._fld = AdvSimd.Arm64.LoadPairVector128((Int64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector128((Int64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector128)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.SByte.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.SByte.cs new file mode 100644 index 00000000000000..4dc099e5025598 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.SByte.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector128_SByte() + { + var test = new LoadPairVector128_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector128_SByte + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector128,Vector128) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector128_SByte testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector128((SByte*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 32; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector128,Vector128)>() / sizeof(SByte); + private static readonly int Op1ElementCount = RetElementCount; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static (Vector128,Vector128) _clsVar; + + private (Vector128,Vector128) _fld; + + private DataTable _dataTable; + + public LoadPairVector128_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector128((SByte*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector128), new Type[] { typeof(SByte*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(SByte*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector128,Vector128))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector128((SByte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector128_SByte(); + test._fld = AdvSimd.Arm64.LoadPairVector128((SByte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector128((SByte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector128)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.Single.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.Single.cs new file mode 100644 index 00000000000000..171d9e146b344d --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.Single.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector128_Single() + { + var test = new LoadPairVector128_Single(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector128_Single + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Single[] inArray, Single[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector128,Vector128) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector128_Single testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector128((Single*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 32; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector128,Vector128)>() / sizeof(Single); + private static readonly int Op1ElementCount = RetElementCount; + + private static Single[] _data = new Single[Op1ElementCount]; + + private static (Vector128,Vector128) _clsVar; + + private (Vector128,Vector128) _fld; + + private DataTable _dataTable; + + public LoadPairVector128_Single() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSingle(); } + _dataTable = new DataTable(_data, new Single[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector128((Single*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector128), new Type[] { typeof(Single*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Single*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector128,Vector128))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector128((Single*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector128_Single(); + test._fld = AdvSimd.Arm64.LoadPairVector128((Single*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector128((Single*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector128)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.UInt16.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.UInt16.cs new file mode 100644 index 00000000000000..3746c0d6b31c96 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.UInt16.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector128_UInt16() + { + var test = new LoadPairVector128_UInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector128_UInt16 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector128,Vector128) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector128_UInt16 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector128((UInt16*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 32; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector128,Vector128)>() / sizeof(UInt16); + private static readonly int Op1ElementCount = RetElementCount; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static (Vector128,Vector128) _clsVar; + + private (Vector128,Vector128) _fld; + + private DataTable _dataTable; + + public LoadPairVector128_UInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector128((UInt16*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector128), new Type[] { typeof(UInt16*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(UInt16*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector128,Vector128))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector128((UInt16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector128_UInt16(); + test._fld = AdvSimd.Arm64.LoadPairVector128((UInt16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector128((UInt16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector128)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.UInt32.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.UInt32.cs new file mode 100644 index 00000000000000..a657cf7553c177 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.UInt32.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector128_UInt32() + { + var test = new LoadPairVector128_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector128_UInt32 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector128,Vector128) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector128_UInt32 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector128((UInt32*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 32; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector128,Vector128)>() / sizeof(UInt32); + private static readonly int Op1ElementCount = RetElementCount; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static (Vector128,Vector128) _clsVar; + + private (Vector128,Vector128) _fld; + + private DataTable _dataTable; + + public LoadPairVector128_UInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector128((UInt32*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector128), new Type[] { typeof(UInt32*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(UInt32*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector128,Vector128))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector128((UInt32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector128_UInt32(); + test._fld = AdvSimd.Arm64.LoadPairVector128((UInt32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector128((UInt32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector128)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.UInt64.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.UInt64.cs new file mode 100644 index 00000000000000..150c2f07c952bd --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128.UInt64.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector128_UInt64() + { + var test = new LoadPairVector128_UInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector128_UInt64 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray, UInt64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector128,Vector128) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector128_UInt64 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector128((UInt64*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 32; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector128,Vector128)>() / sizeof(UInt64); + private static readonly int Op1ElementCount = RetElementCount; + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static (Vector128,Vector128) _clsVar; + + private (Vector128,Vector128) _fld; + + private DataTable _dataTable; + + public LoadPairVector128_UInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector128((UInt64*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector128), new Type[] { typeof(UInt64*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(UInt64*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector128,Vector128))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector128((UInt64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector128_UInt64(); + test._fld = AdvSimd.Arm64.LoadPairVector128((UInt64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector128((UInt64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector128)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.Byte.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.Byte.cs new file mode 100644 index 00000000000000..14f60e3313a0ef --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.Byte.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector128NonTemporal_Byte() + { + var test = new LoadPairVector128NonTemporal_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector128NonTemporal_Byte + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector128,Vector128) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector128NonTemporal_Byte testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((Byte*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 32; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector128,Vector128)>() / sizeof(Byte); + private static readonly int Op1ElementCount = RetElementCount; + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static (Vector128,Vector128) _clsVar; + + private (Vector128,Vector128) _fld; + + private DataTable _dataTable; + + public LoadPairVector128NonTemporal_Byte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector128NonTemporal((Byte*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector128NonTemporal), new Type[] { typeof(Byte*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Byte*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector128,Vector128))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector128NonTemporal((Byte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector128NonTemporal_Byte(); + test._fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((Byte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((Byte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector128NonTemporal)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.Double.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.Double.cs new file mode 100644 index 00000000000000..23c3f4aa72e2c1 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.Double.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector128NonTemporal_Double() + { + var test = new LoadPairVector128NonTemporal_Double(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector128NonTemporal_Double + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Double[] inArray, Double[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector128,Vector128) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector128NonTemporal_Double testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((Double*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 32; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector128,Vector128)>() / sizeof(Double); + private static readonly int Op1ElementCount = RetElementCount; + + private static Double[] _data = new Double[Op1ElementCount]; + + private static (Vector128,Vector128) _clsVar; + + private (Vector128,Vector128) _fld; + + private DataTable _dataTable; + + public LoadPairVector128NonTemporal_Double() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetDouble(); } + _dataTable = new DataTable(_data, new Double[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector128NonTemporal((Double*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector128NonTemporal), new Type[] { typeof(Double*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Double*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector128,Vector128))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector128NonTemporal((Double*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector128NonTemporal_Double(); + test._fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((Double*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((Double*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Double[] inArray = new Double[Op1ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Double[] firstOp, Double[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector128NonTemporal)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.Int16.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.Int16.cs new file mode 100644 index 00000000000000..fb8835f21329ba --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.Int16.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector128NonTemporal_Int16() + { + var test = new LoadPairVector128NonTemporal_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector128NonTemporal_Int16 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector128,Vector128) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector128NonTemporal_Int16 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((Int16*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 32; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector128,Vector128)>() / sizeof(Int16); + private static readonly int Op1ElementCount = RetElementCount; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static (Vector128,Vector128) _clsVar; + + private (Vector128,Vector128) _fld; + + private DataTable _dataTable; + + public LoadPairVector128NonTemporal_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector128NonTemporal((Int16*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector128NonTemporal), new Type[] { typeof(Int16*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Int16*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector128,Vector128))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector128NonTemporal((Int16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector128NonTemporal_Int16(); + test._fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((Int16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((Int16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector128NonTemporal)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.Int32.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.Int32.cs new file mode 100644 index 00000000000000..0189c3d27927f7 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.Int32.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector128NonTemporal_Int32() + { + var test = new LoadPairVector128NonTemporal_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector128NonTemporal_Int32 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector128,Vector128) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector128NonTemporal_Int32 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((Int32*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 32; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector128,Vector128)>() / sizeof(Int32); + private static readonly int Op1ElementCount = RetElementCount; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static (Vector128,Vector128) _clsVar; + + private (Vector128,Vector128) _fld; + + private DataTable _dataTable; + + public LoadPairVector128NonTemporal_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector128NonTemporal((Int32*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector128NonTemporal), new Type[] { typeof(Int32*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Int32*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector128,Vector128))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector128NonTemporal((Int32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector128NonTemporal_Int32(); + test._fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((Int32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((Int32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector128NonTemporal)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.Int64.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.Int64.cs new file mode 100644 index 00000000000000..98a35c6203f8e3 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.Int64.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector128NonTemporal_Int64() + { + var test = new LoadPairVector128NonTemporal_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector128NonTemporal_Int64 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector128,Vector128) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector128NonTemporal_Int64 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((Int64*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 32; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector128,Vector128)>() / sizeof(Int64); + private static readonly int Op1ElementCount = RetElementCount; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static (Vector128,Vector128) _clsVar; + + private (Vector128,Vector128) _fld; + + private DataTable _dataTable; + + public LoadPairVector128NonTemporal_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector128NonTemporal((Int64*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector128NonTemporal), new Type[] { typeof(Int64*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Int64*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector128,Vector128))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector128NonTemporal((Int64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector128NonTemporal_Int64(); + test._fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((Int64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((Int64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector128NonTemporal)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.SByte.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.SByte.cs new file mode 100644 index 00000000000000..d12edccb4bb4a2 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.SByte.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector128NonTemporal_SByte() + { + var test = new LoadPairVector128NonTemporal_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector128NonTemporal_SByte + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector128,Vector128) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector128NonTemporal_SByte testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((SByte*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 32; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector128,Vector128)>() / sizeof(SByte); + private static readonly int Op1ElementCount = RetElementCount; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static (Vector128,Vector128) _clsVar; + + private (Vector128,Vector128) _fld; + + private DataTable _dataTable; + + public LoadPairVector128NonTemporal_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector128NonTemporal((SByte*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector128NonTemporal), new Type[] { typeof(SByte*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(SByte*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector128,Vector128))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector128NonTemporal((SByte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector128NonTemporal_SByte(); + test._fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((SByte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((SByte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector128NonTemporal)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.Single.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.Single.cs new file mode 100644 index 00000000000000..9ddfacf6f2e7b7 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.Single.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector128NonTemporal_Single() + { + var test = new LoadPairVector128NonTemporal_Single(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector128NonTemporal_Single + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Single[] inArray, Single[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector128,Vector128) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector128NonTemporal_Single testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((Single*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 32; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector128,Vector128)>() / sizeof(Single); + private static readonly int Op1ElementCount = RetElementCount; + + private static Single[] _data = new Single[Op1ElementCount]; + + private static (Vector128,Vector128) _clsVar; + + private (Vector128,Vector128) _fld; + + private DataTable _dataTable; + + public LoadPairVector128NonTemporal_Single() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSingle(); } + _dataTable = new DataTable(_data, new Single[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector128NonTemporal((Single*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector128NonTemporal), new Type[] { typeof(Single*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Single*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector128,Vector128))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector128NonTemporal((Single*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector128NonTemporal_Single(); + test._fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((Single*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((Single*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector128NonTemporal)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.UInt16.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.UInt16.cs new file mode 100644 index 00000000000000..9ae5fda62270df --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.UInt16.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector128NonTemporal_UInt16() + { + var test = new LoadPairVector128NonTemporal_UInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector128NonTemporal_UInt16 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector128,Vector128) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector128NonTemporal_UInt16 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((UInt16*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 32; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector128,Vector128)>() / sizeof(UInt16); + private static readonly int Op1ElementCount = RetElementCount; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static (Vector128,Vector128) _clsVar; + + private (Vector128,Vector128) _fld; + + private DataTable _dataTable; + + public LoadPairVector128NonTemporal_UInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector128NonTemporal((UInt16*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector128NonTemporal), new Type[] { typeof(UInt16*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(UInt16*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector128,Vector128))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector128NonTemporal((UInt16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector128NonTemporal_UInt16(); + test._fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((UInt16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((UInt16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector128NonTemporal)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.UInt32.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.UInt32.cs new file mode 100644 index 00000000000000..fd5787a0e4ef3d --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.UInt32.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector128NonTemporal_UInt32() + { + var test = new LoadPairVector128NonTemporal_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector128NonTemporal_UInt32 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector128,Vector128) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector128NonTemporal_UInt32 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((UInt32*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 32; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector128,Vector128)>() / sizeof(UInt32); + private static readonly int Op1ElementCount = RetElementCount; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static (Vector128,Vector128) _clsVar; + + private (Vector128,Vector128) _fld; + + private DataTable _dataTable; + + public LoadPairVector128NonTemporal_UInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector128NonTemporal((UInt32*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector128NonTemporal), new Type[] { typeof(UInt32*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(UInt32*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector128,Vector128))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector128NonTemporal((UInt32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector128NonTemporal_UInt32(); + test._fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((UInt32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((UInt32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector128NonTemporal)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.UInt64.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.UInt64.cs new file mode 100644 index 00000000000000..6ef1587e992651 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector128NonTemporal.UInt64.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector128NonTemporal_UInt64() + { + var test = new LoadPairVector128NonTemporal_UInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector128NonTemporal_UInt64 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray, UInt64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector128,Vector128) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector128NonTemporal_UInt64 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((UInt64*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 32; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector128,Vector128)>() / sizeof(UInt64); + private static readonly int Op1ElementCount = RetElementCount; + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static (Vector128,Vector128) _clsVar; + + private (Vector128,Vector128) _fld; + + private DataTable _dataTable; + + public LoadPairVector128NonTemporal_UInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector128NonTemporal((UInt64*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector128NonTemporal), new Type[] { typeof(UInt64*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(UInt64*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector128,Vector128))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector128NonTemporal((UInt64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector128NonTemporal_UInt64(); + test._fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((UInt64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector128NonTemporal((UInt64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector128NonTemporal)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.Byte.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.Byte.cs new file mode 100644 index 00000000000000..4b1d9901d1ffe7 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.Byte.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector64_Byte() + { + var test = new LoadPairVector64_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector64_Byte + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector64_Byte testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector64((Byte*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(Byte); + private static readonly int Op1ElementCount = RetElementCount; + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairVector64_Byte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector64((Byte*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector64), new Type[] { typeof(Byte*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Byte*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector64((Byte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector64_Byte(); + test._fld = AdvSimd.Arm64.LoadPairVector64((Byte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector64((Byte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector64)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.Double.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.Double.cs new file mode 100644 index 00000000000000..ea852b8af9eb13 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.Double.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector64_Double() + { + var test = new LoadPairVector64_Double(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector64_Double + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Double[] inArray, Double[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector64_Double testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector64((Double*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(Double); + private static readonly int Op1ElementCount = RetElementCount; + + private static Double[] _data = new Double[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairVector64_Double() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetDouble(); } + _dataTable = new DataTable(_data, new Double[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector64((Double*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector64), new Type[] { typeof(Double*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Double*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector64((Double*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector64_Double(); + test._fld = AdvSimd.Arm64.LoadPairVector64((Double*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector64((Double*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Double[] inArray = new Double[Op1ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Double[] firstOp, Double[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector64)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.Int16.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.Int16.cs new file mode 100644 index 00000000000000..dd68e9578706ba --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.Int16.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector64_Int16() + { + var test = new LoadPairVector64_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector64_Int16 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector64_Int16 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector64((Int16*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(Int16); + private static readonly int Op1ElementCount = RetElementCount; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairVector64_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector64((Int16*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector64), new Type[] { typeof(Int16*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Int16*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector64((Int16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector64_Int16(); + test._fld = AdvSimd.Arm64.LoadPairVector64((Int16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector64((Int16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector64)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.Int32.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.Int32.cs new file mode 100644 index 00000000000000..f376caad4ac896 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.Int32.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector64_Int32() + { + var test = new LoadPairVector64_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector64_Int32 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector64_Int32 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector64((Int32*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(Int32); + private static readonly int Op1ElementCount = RetElementCount; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairVector64_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector64((Int32*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector64), new Type[] { typeof(Int32*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Int32*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector64((Int32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector64_Int32(); + test._fld = AdvSimd.Arm64.LoadPairVector64((Int32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector64((Int32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector64)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.Int64.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.Int64.cs new file mode 100644 index 00000000000000..d5f639384460c7 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.Int64.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector64_Int64() + { + var test = new LoadPairVector64_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector64_Int64 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector64_Int64 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector64((Int64*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(Int64); + private static readonly int Op1ElementCount = RetElementCount; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairVector64_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector64((Int64*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector64), new Type[] { typeof(Int64*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Int64*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector64((Int64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector64_Int64(); + test._fld = AdvSimd.Arm64.LoadPairVector64((Int64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector64((Int64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector64)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.SByte.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.SByte.cs new file mode 100644 index 00000000000000..c8598a39e0b0fc --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.SByte.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector64_SByte() + { + var test = new LoadPairVector64_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector64_SByte + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector64_SByte testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector64((SByte*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(SByte); + private static readonly int Op1ElementCount = RetElementCount; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairVector64_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector64((SByte*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector64), new Type[] { typeof(SByte*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(SByte*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector64((SByte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector64_SByte(); + test._fld = AdvSimd.Arm64.LoadPairVector64((SByte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector64((SByte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector64)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.Single.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.Single.cs new file mode 100644 index 00000000000000..08a63a2204a8ab --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.Single.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector64_Single() + { + var test = new LoadPairVector64_Single(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector64_Single + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Single[] inArray, Single[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector64_Single testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector64((Single*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(Single); + private static readonly int Op1ElementCount = RetElementCount; + + private static Single[] _data = new Single[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairVector64_Single() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSingle(); } + _dataTable = new DataTable(_data, new Single[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector64((Single*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector64), new Type[] { typeof(Single*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Single*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector64((Single*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector64_Single(); + test._fld = AdvSimd.Arm64.LoadPairVector64((Single*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector64((Single*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector64)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.UInt16.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.UInt16.cs new file mode 100644 index 00000000000000..4ce7d85467bcb2 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.UInt16.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector64_UInt16() + { + var test = new LoadPairVector64_UInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector64_UInt16 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector64_UInt16 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector64((UInt16*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(UInt16); + private static readonly int Op1ElementCount = RetElementCount; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairVector64_UInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector64((UInt16*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector64), new Type[] { typeof(UInt16*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(UInt16*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector64((UInt16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector64_UInt16(); + test._fld = AdvSimd.Arm64.LoadPairVector64((UInt16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector64((UInt16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector64)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.UInt32.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.UInt32.cs new file mode 100644 index 00000000000000..e14a2d73afca58 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.UInt32.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector64_UInt32() + { + var test = new LoadPairVector64_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector64_UInt32 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector64_UInt32 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector64((UInt32*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(UInt32); + private static readonly int Op1ElementCount = RetElementCount; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairVector64_UInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector64((UInt32*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector64), new Type[] { typeof(UInt32*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(UInt32*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector64((UInt32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector64_UInt32(); + test._fld = AdvSimd.Arm64.LoadPairVector64((UInt32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector64((UInt32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector64)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.UInt64.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.UInt64.cs new file mode 100644 index 00000000000000..c1b625b014be34 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64.UInt64.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector64_UInt64() + { + var test = new LoadPairVector64_UInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector64_UInt64 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray, UInt64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector64_UInt64 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector64((UInt64*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(UInt64); + private static readonly int Op1ElementCount = RetElementCount; + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairVector64_UInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector64((UInt64*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector64), new Type[] { typeof(UInt64*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(UInt64*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector64((UInt64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector64_UInt64(); + test._fld = AdvSimd.Arm64.LoadPairVector64((UInt64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector64((UInt64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector64)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.Byte.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.Byte.cs new file mode 100644 index 00000000000000..b21feccc6be77e --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.Byte.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector64NonTemporal_Byte() + { + var test = new LoadPairVector64NonTemporal_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector64NonTemporal_Byte + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector64NonTemporal_Byte testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((Byte*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(Byte); + private static readonly int Op1ElementCount = RetElementCount; + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairVector64NonTemporal_Byte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector64NonTemporal((Byte*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector64NonTemporal), new Type[] { typeof(Byte*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Byte*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector64NonTemporal((Byte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector64NonTemporal_Byte(); + test._fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((Byte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((Byte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector64NonTemporal)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.Double.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.Double.cs new file mode 100644 index 00000000000000..869a1bc9193d16 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.Double.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector64NonTemporal_Double() + { + var test = new LoadPairVector64NonTemporal_Double(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector64NonTemporal_Double + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Double[] inArray, Double[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector64NonTemporal_Double testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((Double*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(Double); + private static readonly int Op1ElementCount = RetElementCount; + + private static Double[] _data = new Double[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairVector64NonTemporal_Double() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetDouble(); } + _dataTable = new DataTable(_data, new Double[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector64NonTemporal((Double*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector64NonTemporal), new Type[] { typeof(Double*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Double*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector64NonTemporal((Double*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector64NonTemporal_Double(); + test._fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((Double*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((Double*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Double[] inArray = new Double[Op1ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Double[] firstOp, Double[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector64NonTemporal)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.Int16.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.Int16.cs new file mode 100644 index 00000000000000..55f8607dee5a56 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.Int16.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector64NonTemporal_Int16() + { + var test = new LoadPairVector64NonTemporal_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector64NonTemporal_Int16 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector64NonTemporal_Int16 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((Int16*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(Int16); + private static readonly int Op1ElementCount = RetElementCount; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairVector64NonTemporal_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector64NonTemporal((Int16*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector64NonTemporal), new Type[] { typeof(Int16*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Int16*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector64NonTemporal((Int16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector64NonTemporal_Int16(); + test._fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((Int16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((Int16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector64NonTemporal)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.Int32.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.Int32.cs new file mode 100644 index 00000000000000..0be358d7893771 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.Int32.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector64NonTemporal_Int32() + { + var test = new LoadPairVector64NonTemporal_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector64NonTemporal_Int32 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector64NonTemporal_Int32 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((Int32*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(Int32); + private static readonly int Op1ElementCount = RetElementCount; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairVector64NonTemporal_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector64NonTemporal((Int32*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector64NonTemporal), new Type[] { typeof(Int32*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Int32*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector64NonTemporal((Int32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector64NonTemporal_Int32(); + test._fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((Int32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((Int32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector64NonTemporal)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.Int64.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.Int64.cs new file mode 100644 index 00000000000000..d3ebcb54524fd7 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.Int64.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector64NonTemporal_Int64() + { + var test = new LoadPairVector64NonTemporal_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector64NonTemporal_Int64 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector64NonTemporal_Int64 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((Int64*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(Int64); + private static readonly int Op1ElementCount = RetElementCount; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairVector64NonTemporal_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector64NonTemporal((Int64*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector64NonTemporal), new Type[] { typeof(Int64*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Int64*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector64NonTemporal((Int64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector64NonTemporal_Int64(); + test._fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((Int64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((Int64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector64NonTemporal)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.SByte.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.SByte.cs new file mode 100644 index 00000000000000..6217ad0578db05 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.SByte.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector64NonTemporal_SByte() + { + var test = new LoadPairVector64NonTemporal_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector64NonTemporal_SByte + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector64NonTemporal_SByte testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((SByte*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(SByte); + private static readonly int Op1ElementCount = RetElementCount; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairVector64NonTemporal_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector64NonTemporal((SByte*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector64NonTemporal), new Type[] { typeof(SByte*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(SByte*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector64NonTemporal((SByte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector64NonTemporal_SByte(); + test._fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((SByte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((SByte*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector64NonTemporal)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.Single.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.Single.cs new file mode 100644 index 00000000000000..aa606388ff3369 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.Single.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector64NonTemporal_Single() + { + var test = new LoadPairVector64NonTemporal_Single(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector64NonTemporal_Single + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Single[] inArray, Single[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector64NonTemporal_Single testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((Single*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(Single); + private static readonly int Op1ElementCount = RetElementCount; + + private static Single[] _data = new Single[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairVector64NonTemporal_Single() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSingle(); } + _dataTable = new DataTable(_data, new Single[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector64NonTemporal((Single*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector64NonTemporal), new Type[] { typeof(Single*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(Single*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector64NonTemporal((Single*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector64NonTemporal_Single(); + test._fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((Single*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((Single*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector64NonTemporal)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.UInt16.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.UInt16.cs new file mode 100644 index 00000000000000..f8c2a25077ed24 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.UInt16.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector64NonTemporal_UInt16() + { + var test = new LoadPairVector64NonTemporal_UInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector64NonTemporal_UInt16 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector64NonTemporal_UInt16 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((UInt16*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(UInt16); + private static readonly int Op1ElementCount = RetElementCount; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairVector64NonTemporal_UInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector64NonTemporal((UInt16*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector64NonTemporal), new Type[] { typeof(UInt16*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(UInt16*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector64NonTemporal((UInt16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector64NonTemporal_UInt16(); + test._fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((UInt16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((UInt16*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector64NonTemporal)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.UInt32.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.UInt32.cs new file mode 100644 index 00000000000000..b203fc8d2e1e55 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.UInt32.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector64NonTemporal_UInt32() + { + var test = new LoadPairVector64NonTemporal_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector64NonTemporal_UInt32 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector64NonTemporal_UInt32 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((UInt32*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(UInt32); + private static readonly int Op1ElementCount = RetElementCount; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairVector64NonTemporal_UInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector64NonTemporal((UInt32*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector64NonTemporal), new Type[] { typeof(UInt32*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(UInt32*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector64NonTemporal((UInt32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector64NonTemporal_UInt32(); + test._fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((UInt32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((UInt32*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector64NonTemporal)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.UInt64.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.UInt64.cs new file mode 100644 index 00000000000000..5e1b68e8f212dc --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/LoadPairVector64NonTemporal.UInt64.cs @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void LoadPairVector64NonTemporal_UInt64() + { + var test = new LoadPairVector64NonTemporal_UInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 LoadPairVector64NonTemporal_UInt64 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray, UInt64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public (Vector64,Vector64) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario(LoadPairVector64NonTemporal_UInt64 testClass) + { + _fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((UInt64*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = 16; + private static readonly int RetElementCount = Unsafe.SizeOf<(Vector64,Vector64)>() / sizeof(UInt64); + private static readonly int Op1ElementCount = RetElementCount; + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static (Vector64,Vector64) _clsVar; + + private (Vector64,Vector64) _fld; + + private DataTable _dataTable; + + public LoadPairVector64NonTemporal_UInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.LoadPairVector64NonTemporal((UInt64*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.LoadPairVector64NonTemporal), new Type[] { typeof(UInt64*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof(UInt64*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ((Vector64,Vector64))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = AdvSimd.Arm64.LoadPairVector64NonTemporal((UInt64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new LoadPairVector64NonTemporal_UInt64(); + test._fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((UInt64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = AdvSimd.Arm64.LoadPairVector64NonTemporal((UInt64*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if (firstOp[i] != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.LoadPairVector64NonTemporal)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64_Part2.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64_Part2.cs index 29788e0053f174..f34c72ddcca819 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64_Part2.cs +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64_Part2.cs @@ -49,6 +49,52 @@ static Program() ["LoadAndReplicateToVector128.Double"] = LoadAndReplicateToVector128_Double, ["LoadAndReplicateToVector128.Int64"] = LoadAndReplicateToVector128_Int64, ["LoadAndReplicateToVector128.UInt64"] = LoadAndReplicateToVector128_UInt64, + ["LoadPairScalarVector64.Int32"] = LoadPairScalarVector64_Int32, + ["LoadPairScalarVector64.Single"] = LoadPairScalarVector64_Single, + ["LoadPairScalarVector64.UInt32"] = LoadPairScalarVector64_UInt32, + ["LoadPairScalarVector64NonTemporal.Int32"] = LoadPairScalarVector64NonTemporal_Int32, + ["LoadPairScalarVector64NonTemporal.Single"] = LoadPairScalarVector64NonTemporal_Single, + ["LoadPairScalarVector64NonTemporal.UInt32"] = LoadPairScalarVector64NonTemporal_UInt32, + ["LoadPairVector64.Byte"] = LoadPairVector64_Byte, + ["LoadPairVector64.Double"] = LoadPairVector64_Double, + ["LoadPairVector64.Int16"] = LoadPairVector64_Int16, + ["LoadPairVector64.Int32"] = LoadPairVector64_Int32, + ["LoadPairVector64.Int64"] = LoadPairVector64_Int64, + ["LoadPairVector64.SByte"] = LoadPairVector64_SByte, + ["LoadPairVector64.Single"] = LoadPairVector64_Single, + ["LoadPairVector64.UInt16"] = LoadPairVector64_UInt16, + ["LoadPairVector64.UInt32"] = LoadPairVector64_UInt32, + ["LoadPairVector64.UInt64"] = LoadPairVector64_UInt64, + ["LoadPairVector64NonTemporal.Byte"] = LoadPairVector64NonTemporal_Byte, + ["LoadPairVector64NonTemporal.Double"] = LoadPairVector64NonTemporal_Double, + ["LoadPairVector64NonTemporal.Int16"] = LoadPairVector64NonTemporal_Int16, + ["LoadPairVector64NonTemporal.Int32"] = LoadPairVector64NonTemporal_Int32, + ["LoadPairVector64NonTemporal.Int64"] = LoadPairVector64NonTemporal_Int64, + ["LoadPairVector64NonTemporal.SByte"] = LoadPairVector64NonTemporal_SByte, + ["LoadPairVector64NonTemporal.Single"] = LoadPairVector64NonTemporal_Single, + ["LoadPairVector64NonTemporal.UInt16"] = LoadPairVector64NonTemporal_UInt16, + ["LoadPairVector64NonTemporal.UInt32"] = LoadPairVector64NonTemporal_UInt32, + ["LoadPairVector64NonTemporal.UInt64"] = LoadPairVector64NonTemporal_UInt64, + ["LoadPairVector128.Byte"] = LoadPairVector128_Byte, + ["LoadPairVector128.Double"] = LoadPairVector128_Double, + ["LoadPairVector128.Int16"] = LoadPairVector128_Int16, + ["LoadPairVector128.Int32"] = LoadPairVector128_Int32, + ["LoadPairVector128.Int64"] = LoadPairVector128_Int64, + ["LoadPairVector128.SByte"] = LoadPairVector128_SByte, + ["LoadPairVector128.Single"] = LoadPairVector128_Single, + ["LoadPairVector128.UInt16"] = LoadPairVector128_UInt16, + ["LoadPairVector128.UInt32"] = LoadPairVector128_UInt32, + ["LoadPairVector128.UInt64"] = LoadPairVector128_UInt64, + ["LoadPairVector128NonTemporal.Byte"] = LoadPairVector128NonTemporal_Byte, + ["LoadPairVector128NonTemporal.Double"] = LoadPairVector128NonTemporal_Double, + ["LoadPairVector128NonTemporal.Int16"] = LoadPairVector128NonTemporal_Int16, + ["LoadPairVector128NonTemporal.Int32"] = LoadPairVector128NonTemporal_Int32, + ["LoadPairVector128NonTemporal.Int64"] = LoadPairVector128NonTemporal_Int64, + ["LoadPairVector128NonTemporal.SByte"] = LoadPairVector128NonTemporal_SByte, + ["LoadPairVector128NonTemporal.Single"] = LoadPairVector128NonTemporal_Single, + ["LoadPairVector128NonTemporal.UInt16"] = LoadPairVector128NonTemporal_UInt16, + ["LoadPairVector128NonTemporal.UInt32"] = LoadPairVector128NonTemporal_UInt32, + ["LoadPairVector128NonTemporal.UInt64"] = LoadPairVector128NonTemporal_UInt64, ["Max.Vector128.Double"] = Max_Vector128_Double, ["MaxAcross.Vector64.Byte"] = MaxAcross_Vector64_Byte, ["MaxAcross.Vector64.Int16"] = MaxAcross_Vector64_Int16, @@ -65,52 +111,6 @@ static Program() ["MaxNumberAcross.Vector128.Single"] = MaxNumberAcross_Vector128_Single, ["MaxNumberPairwise.Vector64.Single"] = MaxNumberPairwise_Vector64_Single, ["MaxNumberPairwise.Vector128.Double"] = MaxNumberPairwise_Vector128_Double, - ["MaxNumberPairwise.Vector128.Single"] = MaxNumberPairwise_Vector128_Single, - ["MaxNumberPairwiseScalar.Vector64.Single"] = MaxNumberPairwiseScalar_Vector64_Single, - ["MaxNumberPairwiseScalar.Vector128.Double"] = MaxNumberPairwiseScalar_Vector128_Double, - ["MaxPairwise.Vector128.Byte"] = MaxPairwise_Vector128_Byte, - ["MaxPairwise.Vector128.Double"] = MaxPairwise_Vector128_Double, - ["MaxPairwise.Vector128.Int16"] = MaxPairwise_Vector128_Int16, - ["MaxPairwise.Vector128.Int32"] = MaxPairwise_Vector128_Int32, - ["MaxPairwise.Vector128.SByte"] = MaxPairwise_Vector128_SByte, - ["MaxPairwise.Vector128.Single"] = MaxPairwise_Vector128_Single, - ["MaxPairwise.Vector128.UInt16"] = MaxPairwise_Vector128_UInt16, - ["MaxPairwise.Vector128.UInt32"] = MaxPairwise_Vector128_UInt32, - ["MaxPairwiseScalar.Vector64.Single"] = MaxPairwiseScalar_Vector64_Single, - ["MaxPairwiseScalar.Vector128.Double"] = MaxPairwiseScalar_Vector128_Double, - ["MaxScalar.Vector64.Double"] = MaxScalar_Vector64_Double, - ["MaxScalar.Vector64.Single"] = MaxScalar_Vector64_Single, - ["Min.Vector128.Double"] = Min_Vector128_Double, - ["MinAcross.Vector64.Byte"] = MinAcross_Vector64_Byte, - ["MinAcross.Vector64.Int16"] = MinAcross_Vector64_Int16, - ["MinAcross.Vector64.SByte"] = MinAcross_Vector64_SByte, - ["MinAcross.Vector64.UInt16"] = MinAcross_Vector64_UInt16, - ["MinAcross.Vector128.Byte"] = MinAcross_Vector128_Byte, - ["MinAcross.Vector128.Int16"] = MinAcross_Vector128_Int16, - ["MinAcross.Vector128.Int32"] = MinAcross_Vector128_Int32, - ["MinAcross.Vector128.SByte"] = MinAcross_Vector128_SByte, - ["MinAcross.Vector128.Single"] = MinAcross_Vector128_Single, - ["MinAcross.Vector128.UInt16"] = MinAcross_Vector128_UInt16, - ["MinAcross.Vector128.UInt32"] = MinAcross_Vector128_UInt32, - ["MinNumber.Vector128.Double"] = MinNumber_Vector128_Double, - ["MinNumberAcross.Vector128.Single"] = MinNumberAcross_Vector128_Single, - ["MinNumberPairwise.Vector64.Single"] = MinNumberPairwise_Vector64_Single, - ["MinNumberPairwise.Vector128.Double"] = MinNumberPairwise_Vector128_Double, - ["MinNumberPairwise.Vector128.Single"] = MinNumberPairwise_Vector128_Single, - ["MinNumberPairwiseScalar.Vector64.Single"] = MinNumberPairwiseScalar_Vector64_Single, - ["MinNumberPairwiseScalar.Vector128.Double"] = MinNumberPairwiseScalar_Vector128_Double, - ["MinPairwise.Vector128.Byte"] = MinPairwise_Vector128_Byte, - ["MinPairwise.Vector128.Double"] = MinPairwise_Vector128_Double, - ["MinPairwise.Vector128.Int16"] = MinPairwise_Vector128_Int16, - ["MinPairwise.Vector128.Int32"] = MinPairwise_Vector128_Int32, - ["MinPairwise.Vector128.SByte"] = MinPairwise_Vector128_SByte, - ["MinPairwise.Vector128.Single"] = MinPairwise_Vector128_Single, - ["MinPairwise.Vector128.UInt16"] = MinPairwise_Vector128_UInt16, - ["MinPairwise.Vector128.UInt32"] = MinPairwise_Vector128_UInt32, - ["MinPairwiseScalar.Vector64.Single"] = MinPairwiseScalar_Vector64_Single, - ["MinPairwiseScalar.Vector128.Double"] = MinPairwiseScalar_Vector128_Double, - ["MinScalar.Vector64.Double"] = MinScalar_Vector64_Double, - ["MinScalar.Vector64.Single"] = MinScalar_Vector64_Single, }; } } diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64_Part3.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64_Part3.cs index c7c238a050d7bb..77c36bd700a5d9 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64_Part3.cs +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64_Part3.cs @@ -11,6 +11,52 @@ public static partial class Program static Program() { TestList = new Dictionary() { + ["MaxNumberPairwise.Vector128.Single"] = MaxNumberPairwise_Vector128_Single, + ["MaxNumberPairwiseScalar.Vector64.Single"] = MaxNumberPairwiseScalar_Vector64_Single, + ["MaxNumberPairwiseScalar.Vector128.Double"] = MaxNumberPairwiseScalar_Vector128_Double, + ["MaxPairwise.Vector128.Byte"] = MaxPairwise_Vector128_Byte, + ["MaxPairwise.Vector128.Double"] = MaxPairwise_Vector128_Double, + ["MaxPairwise.Vector128.Int16"] = MaxPairwise_Vector128_Int16, + ["MaxPairwise.Vector128.Int32"] = MaxPairwise_Vector128_Int32, + ["MaxPairwise.Vector128.SByte"] = MaxPairwise_Vector128_SByte, + ["MaxPairwise.Vector128.Single"] = MaxPairwise_Vector128_Single, + ["MaxPairwise.Vector128.UInt16"] = MaxPairwise_Vector128_UInt16, + ["MaxPairwise.Vector128.UInt32"] = MaxPairwise_Vector128_UInt32, + ["MaxPairwiseScalar.Vector64.Single"] = MaxPairwiseScalar_Vector64_Single, + ["MaxPairwiseScalar.Vector128.Double"] = MaxPairwiseScalar_Vector128_Double, + ["MaxScalar.Vector64.Double"] = MaxScalar_Vector64_Double, + ["MaxScalar.Vector64.Single"] = MaxScalar_Vector64_Single, + ["Min.Vector128.Double"] = Min_Vector128_Double, + ["MinAcross.Vector64.Byte"] = MinAcross_Vector64_Byte, + ["MinAcross.Vector64.Int16"] = MinAcross_Vector64_Int16, + ["MinAcross.Vector64.SByte"] = MinAcross_Vector64_SByte, + ["MinAcross.Vector64.UInt16"] = MinAcross_Vector64_UInt16, + ["MinAcross.Vector128.Byte"] = MinAcross_Vector128_Byte, + ["MinAcross.Vector128.Int16"] = MinAcross_Vector128_Int16, + ["MinAcross.Vector128.Int32"] = MinAcross_Vector128_Int32, + ["MinAcross.Vector128.SByte"] = MinAcross_Vector128_SByte, + ["MinAcross.Vector128.Single"] = MinAcross_Vector128_Single, + ["MinAcross.Vector128.UInt16"] = MinAcross_Vector128_UInt16, + ["MinAcross.Vector128.UInt32"] = MinAcross_Vector128_UInt32, + ["MinNumber.Vector128.Double"] = MinNumber_Vector128_Double, + ["MinNumberAcross.Vector128.Single"] = MinNumberAcross_Vector128_Single, + ["MinNumberPairwise.Vector64.Single"] = MinNumberPairwise_Vector64_Single, + ["MinNumberPairwise.Vector128.Double"] = MinNumberPairwise_Vector128_Double, + ["MinNumberPairwise.Vector128.Single"] = MinNumberPairwise_Vector128_Single, + ["MinNumberPairwiseScalar.Vector64.Single"] = MinNumberPairwiseScalar_Vector64_Single, + ["MinNumberPairwiseScalar.Vector128.Double"] = MinNumberPairwiseScalar_Vector128_Double, + ["MinPairwise.Vector128.Byte"] = MinPairwise_Vector128_Byte, + ["MinPairwise.Vector128.Double"] = MinPairwise_Vector128_Double, + ["MinPairwise.Vector128.Int16"] = MinPairwise_Vector128_Int16, + ["MinPairwise.Vector128.Int32"] = MinPairwise_Vector128_Int32, + ["MinPairwise.Vector128.SByte"] = MinPairwise_Vector128_SByte, + ["MinPairwise.Vector128.Single"] = MinPairwise_Vector128_Single, + ["MinPairwise.Vector128.UInt16"] = MinPairwise_Vector128_UInt16, + ["MinPairwise.Vector128.UInt32"] = MinPairwise_Vector128_UInt32, + ["MinPairwiseScalar.Vector64.Single"] = MinPairwiseScalar_Vector64_Single, + ["MinPairwiseScalar.Vector128.Double"] = MinPairwiseScalar_Vector128_Double, + ["MinScalar.Vector64.Double"] = MinScalar_Vector64_Double, + ["MinScalar.Vector64.Single"] = MinScalar_Vector64_Single, ["Multiply.Vector128.Double"] = Multiply_Vector128_Double, ["MultiplyByScalar.Vector128.Double"] = MultiplyByScalar_Vector128_Double, ["MultiplyBySelectedScalar.Vector128.Double.Vector128.Double.1"] = MultiplyBySelectedScalar_Vector128_Double_Vector128_Double_1, @@ -65,52 +111,6 @@ static Program() ["NegateScalar.Vector64.Int64"] = NegateScalar_Vector64_Int64, ["ReciprocalEstimate.Vector128.Double"] = ReciprocalEstimate_Vector128_Double, ["ReciprocalEstimateScalar.Vector64.Double"] = ReciprocalEstimateScalar_Vector64_Double, - ["ReciprocalEstimateScalar.Vector64.Single"] = ReciprocalEstimateScalar_Vector64_Single, - ["ReciprocalExponentScalar.Vector64.Double"] = ReciprocalExponentScalar_Vector64_Double, - ["ReciprocalExponentScalar.Vector64.Single"] = ReciprocalExponentScalar_Vector64_Single, - ["ReciprocalSquareRootEstimate.Vector128.Double"] = ReciprocalSquareRootEstimate_Vector128_Double, - ["ReciprocalSquareRootEstimateScalar.Vector64.Double"] = ReciprocalSquareRootEstimateScalar_Vector64_Double, - ["ReciprocalSquareRootEstimateScalar.Vector64.Single"] = ReciprocalSquareRootEstimateScalar_Vector64_Single, - ["ReciprocalSquareRootStep.Vector128.Double"] = ReciprocalSquareRootStep_Vector128_Double, - ["ReciprocalSquareRootStepScalar.Vector64.Double"] = ReciprocalSquareRootStepScalar_Vector64_Double, - ["ReciprocalSquareRootStepScalar.Vector64.Single"] = ReciprocalSquareRootStepScalar_Vector64_Single, - ["ReciprocalStep.Vector128.Double"] = ReciprocalStep_Vector128_Double, - ["ReciprocalStepScalar.Vector64.Double"] = ReciprocalStepScalar_Vector64_Double, - ["ReciprocalStepScalar.Vector64.Single"] = ReciprocalStepScalar_Vector64_Single, - ["ReverseElementBits.Vector128.Byte"] = ReverseElementBits_Vector128_Byte, - ["ReverseElementBits.Vector128.SByte"] = ReverseElementBits_Vector128_SByte, - ["ReverseElementBits.Vector64.Byte"] = ReverseElementBits_Vector64_Byte, - ["ReverseElementBits.Vector64.SByte"] = ReverseElementBits_Vector64_SByte, - ["RoundAwayFromZero.Vector128.Double"] = RoundAwayFromZero_Vector128_Double, - ["RoundToNearest.Vector128.Double"] = RoundToNearest_Vector128_Double, - ["RoundToNegativeInfinity.Vector128.Double"] = RoundToNegativeInfinity_Vector128_Double, - ["RoundToPositiveInfinity.Vector128.Double"] = RoundToPositiveInfinity_Vector128_Double, - ["RoundToZero.Vector128.Double"] = RoundToZero_Vector128_Double, - ["ShiftArithmeticRoundedSaturateScalar.Vector64.Int16"] = ShiftArithmeticRoundedSaturateScalar_Vector64_Int16, - ["ShiftArithmeticRoundedSaturateScalar.Vector64.Int32"] = ShiftArithmeticRoundedSaturateScalar_Vector64_Int32, - ["ShiftArithmeticRoundedSaturateScalar.Vector64.SByte"] = ShiftArithmeticRoundedSaturateScalar_Vector64_SByte, - ["ShiftArithmeticSaturateScalar.Vector64.Int16"] = ShiftArithmeticSaturateScalar_Vector64_Int16, - ["ShiftArithmeticSaturateScalar.Vector64.Int32"] = ShiftArithmeticSaturateScalar_Vector64_Int32, - ["ShiftArithmeticSaturateScalar.Vector64.SByte"] = ShiftArithmeticSaturateScalar_Vector64_SByte, - ["ShiftLeftLogicalSaturateScalar.Vector64.Byte.7"] = ShiftLeftLogicalSaturateScalar_Vector64_Byte_7, - ["ShiftLeftLogicalSaturateScalar.Vector64.Int16.15"] = ShiftLeftLogicalSaturateScalar_Vector64_Int16_15, - ["ShiftLeftLogicalSaturateScalar.Vector64.Int32.31"] = ShiftLeftLogicalSaturateScalar_Vector64_Int32_31, - ["ShiftLeftLogicalSaturateScalar.Vector64.SByte.1"] = ShiftLeftLogicalSaturateScalar_Vector64_SByte_1, - ["ShiftLeftLogicalSaturateScalar.Vector64.UInt16.1"] = ShiftLeftLogicalSaturateScalar_Vector64_UInt16_1, - ["ShiftLeftLogicalSaturateScalar.Vector64.UInt32.1"] = ShiftLeftLogicalSaturateScalar_Vector64_UInt32_1, - ["ShiftLeftLogicalSaturateUnsignedScalar.Vector64.Int16.5"] = ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int16_5, - ["ShiftLeftLogicalSaturateUnsignedScalar.Vector64.Int32.7"] = ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int32_7, - ["ShiftLeftLogicalSaturateUnsignedScalar.Vector64.SByte.3"] = ShiftLeftLogicalSaturateUnsignedScalar_Vector64_SByte_3, - ["ShiftLogicalRoundedSaturateScalar.Vector64.Byte"] = ShiftLogicalRoundedSaturateScalar_Vector64_Byte, - ["ShiftLogicalRoundedSaturateScalar.Vector64.Int16"] = ShiftLogicalRoundedSaturateScalar_Vector64_Int16, - ["ShiftLogicalRoundedSaturateScalar.Vector64.Int32"] = ShiftLogicalRoundedSaturateScalar_Vector64_Int32, - ["ShiftLogicalRoundedSaturateScalar.Vector64.SByte"] = ShiftLogicalRoundedSaturateScalar_Vector64_SByte, - ["ShiftLogicalRoundedSaturateScalar.Vector64.UInt16"] = ShiftLogicalRoundedSaturateScalar_Vector64_UInt16, - ["ShiftLogicalRoundedSaturateScalar.Vector64.UInt32"] = ShiftLogicalRoundedSaturateScalar_Vector64_UInt32, - ["ShiftLogicalSaturateScalar.Vector64.Byte"] = ShiftLogicalSaturateScalar_Vector64_Byte, - ["ShiftLogicalSaturateScalar.Vector64.Int16"] = ShiftLogicalSaturateScalar_Vector64_Int16, - ["ShiftLogicalSaturateScalar.Vector64.Int32"] = ShiftLogicalSaturateScalar_Vector64_Int32, - ["ShiftLogicalSaturateScalar.Vector64.SByte"] = ShiftLogicalSaturateScalar_Vector64_SByte, }; } } diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64_Part4.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64_Part4.cs index af2a7dcb3c8a06..7f93b00e0ba06f 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64_Part4.cs +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64_Part4.cs @@ -11,6 +11,52 @@ public static partial class Program static Program() { TestList = new Dictionary() { + ["ReciprocalEstimateScalar.Vector64.Single"] = ReciprocalEstimateScalar_Vector64_Single, + ["ReciprocalExponentScalar.Vector64.Double"] = ReciprocalExponentScalar_Vector64_Double, + ["ReciprocalExponentScalar.Vector64.Single"] = ReciprocalExponentScalar_Vector64_Single, + ["ReciprocalSquareRootEstimate.Vector128.Double"] = ReciprocalSquareRootEstimate_Vector128_Double, + ["ReciprocalSquareRootEstimateScalar.Vector64.Double"] = ReciprocalSquareRootEstimateScalar_Vector64_Double, + ["ReciprocalSquareRootEstimateScalar.Vector64.Single"] = ReciprocalSquareRootEstimateScalar_Vector64_Single, + ["ReciprocalSquareRootStep.Vector128.Double"] = ReciprocalSquareRootStep_Vector128_Double, + ["ReciprocalSquareRootStepScalar.Vector64.Double"] = ReciprocalSquareRootStepScalar_Vector64_Double, + ["ReciprocalSquareRootStepScalar.Vector64.Single"] = ReciprocalSquareRootStepScalar_Vector64_Single, + ["ReciprocalStep.Vector128.Double"] = ReciprocalStep_Vector128_Double, + ["ReciprocalStepScalar.Vector64.Double"] = ReciprocalStepScalar_Vector64_Double, + ["ReciprocalStepScalar.Vector64.Single"] = ReciprocalStepScalar_Vector64_Single, + ["ReverseElementBits.Vector128.Byte"] = ReverseElementBits_Vector128_Byte, + ["ReverseElementBits.Vector128.SByte"] = ReverseElementBits_Vector128_SByte, + ["ReverseElementBits.Vector64.Byte"] = ReverseElementBits_Vector64_Byte, + ["ReverseElementBits.Vector64.SByte"] = ReverseElementBits_Vector64_SByte, + ["RoundAwayFromZero.Vector128.Double"] = RoundAwayFromZero_Vector128_Double, + ["RoundToNearest.Vector128.Double"] = RoundToNearest_Vector128_Double, + ["RoundToNegativeInfinity.Vector128.Double"] = RoundToNegativeInfinity_Vector128_Double, + ["RoundToPositiveInfinity.Vector128.Double"] = RoundToPositiveInfinity_Vector128_Double, + ["RoundToZero.Vector128.Double"] = RoundToZero_Vector128_Double, + ["ShiftArithmeticRoundedSaturateScalar.Vector64.Int16"] = ShiftArithmeticRoundedSaturateScalar_Vector64_Int16, + ["ShiftArithmeticRoundedSaturateScalar.Vector64.Int32"] = ShiftArithmeticRoundedSaturateScalar_Vector64_Int32, + ["ShiftArithmeticRoundedSaturateScalar.Vector64.SByte"] = ShiftArithmeticRoundedSaturateScalar_Vector64_SByte, + ["ShiftArithmeticSaturateScalar.Vector64.Int16"] = ShiftArithmeticSaturateScalar_Vector64_Int16, + ["ShiftArithmeticSaturateScalar.Vector64.Int32"] = ShiftArithmeticSaturateScalar_Vector64_Int32, + ["ShiftArithmeticSaturateScalar.Vector64.SByte"] = ShiftArithmeticSaturateScalar_Vector64_SByte, + ["ShiftLeftLogicalSaturateScalar.Vector64.Byte.7"] = ShiftLeftLogicalSaturateScalar_Vector64_Byte_7, + ["ShiftLeftLogicalSaturateScalar.Vector64.Int16.15"] = ShiftLeftLogicalSaturateScalar_Vector64_Int16_15, + ["ShiftLeftLogicalSaturateScalar.Vector64.Int32.31"] = ShiftLeftLogicalSaturateScalar_Vector64_Int32_31, + ["ShiftLeftLogicalSaturateScalar.Vector64.SByte.1"] = ShiftLeftLogicalSaturateScalar_Vector64_SByte_1, + ["ShiftLeftLogicalSaturateScalar.Vector64.UInt16.1"] = ShiftLeftLogicalSaturateScalar_Vector64_UInt16_1, + ["ShiftLeftLogicalSaturateScalar.Vector64.UInt32.1"] = ShiftLeftLogicalSaturateScalar_Vector64_UInt32_1, + ["ShiftLeftLogicalSaturateUnsignedScalar.Vector64.Int16.5"] = ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int16_5, + ["ShiftLeftLogicalSaturateUnsignedScalar.Vector64.Int32.7"] = ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int32_7, + ["ShiftLeftLogicalSaturateUnsignedScalar.Vector64.SByte.3"] = ShiftLeftLogicalSaturateUnsignedScalar_Vector64_SByte_3, + ["ShiftLogicalRoundedSaturateScalar.Vector64.Byte"] = ShiftLogicalRoundedSaturateScalar_Vector64_Byte, + ["ShiftLogicalRoundedSaturateScalar.Vector64.Int16"] = ShiftLogicalRoundedSaturateScalar_Vector64_Int16, + ["ShiftLogicalRoundedSaturateScalar.Vector64.Int32"] = ShiftLogicalRoundedSaturateScalar_Vector64_Int32, + ["ShiftLogicalRoundedSaturateScalar.Vector64.SByte"] = ShiftLogicalRoundedSaturateScalar_Vector64_SByte, + ["ShiftLogicalRoundedSaturateScalar.Vector64.UInt16"] = ShiftLogicalRoundedSaturateScalar_Vector64_UInt16, + ["ShiftLogicalRoundedSaturateScalar.Vector64.UInt32"] = ShiftLogicalRoundedSaturateScalar_Vector64_UInt32, + ["ShiftLogicalSaturateScalar.Vector64.Byte"] = ShiftLogicalSaturateScalar_Vector64_Byte, + ["ShiftLogicalSaturateScalar.Vector64.Int16"] = ShiftLogicalSaturateScalar_Vector64_Int16, + ["ShiftLogicalSaturateScalar.Vector64.Int32"] = ShiftLogicalSaturateScalar_Vector64_Int32, + ["ShiftLogicalSaturateScalar.Vector64.SByte"] = ShiftLogicalSaturateScalar_Vector64_SByte, ["ShiftLogicalSaturateScalar.Vector64.UInt16"] = ShiftLogicalSaturateScalar_Vector64_UInt16, ["ShiftLogicalSaturateScalar.Vector64.UInt32"] = ShiftLogicalSaturateScalar_Vector64_UInt32, ["ShiftRightArithmeticNarrowingSaturateScalar.Vector64.Int16.16"] = ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int16_16, @@ -65,52 +111,6 @@ static Program() ["StorePairScalar.Vector64.UInt32"] = StorePairScalar_Vector64_UInt32, ["StorePairScalarNonTemporal.Vector64.Int32"] = StorePairScalarNonTemporal_Vector64_Int32, ["StorePairScalarNonTemporal.Vector64.Single"] = StorePairScalarNonTemporal_Vector64_Single, - ["StorePairScalarNonTemporal.Vector64.UInt32"] = StorePairScalarNonTemporal_Vector64_UInt32, - ["StorePairNonTemporal.Vector64.Byte"] = StorePairNonTemporal_Vector64_Byte, - ["StorePairNonTemporal.Vector64.Double"] = StorePairNonTemporal_Vector64_Double, - ["StorePairNonTemporal.Vector64.Int16"] = StorePairNonTemporal_Vector64_Int16, - ["StorePairNonTemporal.Vector64.Int32"] = StorePairNonTemporal_Vector64_Int32, - ["StorePairNonTemporal.Vector64.Int64"] = StorePairNonTemporal_Vector64_Int64, - ["StorePairNonTemporal.Vector64.SByte"] = StorePairNonTemporal_Vector64_SByte, - ["StorePairNonTemporal.Vector64.Single"] = StorePairNonTemporal_Vector64_Single, - ["StorePairNonTemporal.Vector64.UInt16"] = StorePairNonTemporal_Vector64_UInt16, - ["StorePairNonTemporal.Vector64.UInt32"] = StorePairNonTemporal_Vector64_UInt32, - ["StorePairNonTemporal.Vector64.UInt64"] = StorePairNonTemporal_Vector64_UInt64, - ["StorePairNonTemporal.Vector128.Byte"] = StorePairNonTemporal_Vector128_Byte, - ["StorePairNonTemporal.Vector128.Double"] = StorePairNonTemporal_Vector128_Double, - ["StorePairNonTemporal.Vector128.Int16"] = StorePairNonTemporal_Vector128_Int16, - ["StorePairNonTemporal.Vector128.Int32"] = StorePairNonTemporal_Vector128_Int32, - ["StorePairNonTemporal.Vector128.Int64"] = StorePairNonTemporal_Vector128_Int64, - ["StorePairNonTemporal.Vector128.SByte"] = StorePairNonTemporal_Vector128_SByte, - ["StorePairNonTemporal.Vector128.Single"] = StorePairNonTemporal_Vector128_Single, - ["StorePairNonTemporal.Vector128.UInt16"] = StorePairNonTemporal_Vector128_UInt16, - ["StorePairNonTemporal.Vector128.UInt32"] = StorePairNonTemporal_Vector128_UInt32, - ["StorePairNonTemporal.Vector128.UInt64"] = StorePairNonTemporal_Vector128_UInt64, - ["Subtract.Vector128.Double"] = Subtract_Vector128_Double, - ["SubtractSaturateScalar.Vector64.Byte"] = SubtractSaturateScalar_Vector64_Byte, - ["SubtractSaturateScalar.Vector64.Int16"] = SubtractSaturateScalar_Vector64_Int16, - ["SubtractSaturateScalar.Vector64.Int32"] = SubtractSaturateScalar_Vector64_Int32, - ["SubtractSaturateScalar.Vector64.SByte"] = SubtractSaturateScalar_Vector64_SByte, - ["SubtractSaturateScalar.Vector64.UInt16"] = SubtractSaturateScalar_Vector64_UInt16, - ["SubtractSaturateScalar.Vector64.UInt32"] = SubtractSaturateScalar_Vector64_UInt32, - ["TransposeEven.Vector64.Byte"] = TransposeEven_Vector64_Byte, - ["TransposeEven.Vector64.Int16"] = TransposeEven_Vector64_Int16, - ["TransposeEven.Vector64.Int32"] = TransposeEven_Vector64_Int32, - ["TransposeEven.Vector64.SByte"] = TransposeEven_Vector64_SByte, - ["TransposeEven.Vector64.Single"] = TransposeEven_Vector64_Single, - ["TransposeEven.Vector64.UInt16"] = TransposeEven_Vector64_UInt16, - ["TransposeEven.Vector64.UInt32"] = TransposeEven_Vector64_UInt32, - ["TransposeEven.Vector128.Byte"] = TransposeEven_Vector128_Byte, - ["TransposeEven.Vector128.Double"] = TransposeEven_Vector128_Double, - ["TransposeEven.Vector128.Int16"] = TransposeEven_Vector128_Int16, - ["TransposeEven.Vector128.Int32"] = TransposeEven_Vector128_Int32, - ["TransposeEven.Vector128.Int64"] = TransposeEven_Vector128_Int64, - ["TransposeEven.Vector128.SByte"] = TransposeEven_Vector128_SByte, - ["TransposeEven.Vector128.Single"] = TransposeEven_Vector128_Single, - ["TransposeEven.Vector128.UInt16"] = TransposeEven_Vector128_UInt16, - ["TransposeEven.Vector128.UInt32"] = TransposeEven_Vector128_UInt32, - ["TransposeEven.Vector128.UInt64"] = TransposeEven_Vector128_UInt64, - ["TransposeOdd.Vector64.Byte"] = TransposeOdd_Vector64_Byte, }; } } diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64_Part5.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64_Part5.cs index ce885756d0e364..13cb36890d5616 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64_Part5.cs +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64_Part5.cs @@ -11,6 +11,52 @@ public static partial class Program static Program() { TestList = new Dictionary() { + ["StorePairScalarNonTemporal.Vector64.UInt32"] = StorePairScalarNonTemporal_Vector64_UInt32, + ["StorePairNonTemporal.Vector64.Byte"] = StorePairNonTemporal_Vector64_Byte, + ["StorePairNonTemporal.Vector64.Double"] = StorePairNonTemporal_Vector64_Double, + ["StorePairNonTemporal.Vector64.Int16"] = StorePairNonTemporal_Vector64_Int16, + ["StorePairNonTemporal.Vector64.Int32"] = StorePairNonTemporal_Vector64_Int32, + ["StorePairNonTemporal.Vector64.Int64"] = StorePairNonTemporal_Vector64_Int64, + ["StorePairNonTemporal.Vector64.SByte"] = StorePairNonTemporal_Vector64_SByte, + ["StorePairNonTemporal.Vector64.Single"] = StorePairNonTemporal_Vector64_Single, + ["StorePairNonTemporal.Vector64.UInt16"] = StorePairNonTemporal_Vector64_UInt16, + ["StorePairNonTemporal.Vector64.UInt32"] = StorePairNonTemporal_Vector64_UInt32, + ["StorePairNonTemporal.Vector64.UInt64"] = StorePairNonTemporal_Vector64_UInt64, + ["StorePairNonTemporal.Vector128.Byte"] = StorePairNonTemporal_Vector128_Byte, + ["StorePairNonTemporal.Vector128.Double"] = StorePairNonTemporal_Vector128_Double, + ["StorePairNonTemporal.Vector128.Int16"] = StorePairNonTemporal_Vector128_Int16, + ["StorePairNonTemporal.Vector128.Int32"] = StorePairNonTemporal_Vector128_Int32, + ["StorePairNonTemporal.Vector128.Int64"] = StorePairNonTemporal_Vector128_Int64, + ["StorePairNonTemporal.Vector128.SByte"] = StorePairNonTemporal_Vector128_SByte, + ["StorePairNonTemporal.Vector128.Single"] = StorePairNonTemporal_Vector128_Single, + ["StorePairNonTemporal.Vector128.UInt16"] = StorePairNonTemporal_Vector128_UInt16, + ["StorePairNonTemporal.Vector128.UInt32"] = StorePairNonTemporal_Vector128_UInt32, + ["StorePairNonTemporal.Vector128.UInt64"] = StorePairNonTemporal_Vector128_UInt64, + ["Subtract.Vector128.Double"] = Subtract_Vector128_Double, + ["SubtractSaturateScalar.Vector64.Byte"] = SubtractSaturateScalar_Vector64_Byte, + ["SubtractSaturateScalar.Vector64.Int16"] = SubtractSaturateScalar_Vector64_Int16, + ["SubtractSaturateScalar.Vector64.Int32"] = SubtractSaturateScalar_Vector64_Int32, + ["SubtractSaturateScalar.Vector64.SByte"] = SubtractSaturateScalar_Vector64_SByte, + ["SubtractSaturateScalar.Vector64.UInt16"] = SubtractSaturateScalar_Vector64_UInt16, + ["SubtractSaturateScalar.Vector64.UInt32"] = SubtractSaturateScalar_Vector64_UInt32, + ["TransposeEven.Vector64.Byte"] = TransposeEven_Vector64_Byte, + ["TransposeEven.Vector64.Int16"] = TransposeEven_Vector64_Int16, + ["TransposeEven.Vector64.Int32"] = TransposeEven_Vector64_Int32, + ["TransposeEven.Vector64.SByte"] = TransposeEven_Vector64_SByte, + ["TransposeEven.Vector64.Single"] = TransposeEven_Vector64_Single, + ["TransposeEven.Vector64.UInt16"] = TransposeEven_Vector64_UInt16, + ["TransposeEven.Vector64.UInt32"] = TransposeEven_Vector64_UInt32, + ["TransposeEven.Vector128.Byte"] = TransposeEven_Vector128_Byte, + ["TransposeEven.Vector128.Double"] = TransposeEven_Vector128_Double, + ["TransposeEven.Vector128.Int16"] = TransposeEven_Vector128_Int16, + ["TransposeEven.Vector128.Int32"] = TransposeEven_Vector128_Int32, + ["TransposeEven.Vector128.Int64"] = TransposeEven_Vector128_Int64, + ["TransposeEven.Vector128.SByte"] = TransposeEven_Vector128_SByte, + ["TransposeEven.Vector128.Single"] = TransposeEven_Vector128_Single, + ["TransposeEven.Vector128.UInt16"] = TransposeEven_Vector128_UInt16, + ["TransposeEven.Vector128.UInt32"] = TransposeEven_Vector128_UInt32, + ["TransposeEven.Vector128.UInt64"] = TransposeEven_Vector128_UInt64, + ["TransposeOdd.Vector64.Byte"] = TransposeOdd_Vector64_Byte, ["TransposeOdd.Vector64.Int16"] = TransposeOdd_Vector64_Int16, ["TransposeOdd.Vector64.Int32"] = TransposeOdd_Vector64_Int32, ["TransposeOdd.Vector64.SByte"] = TransposeOdd_Vector64_SByte, @@ -65,40 +111,6 @@ static Program() ["UnzipOdd.Vector128.UInt16"] = UnzipOdd_Vector128_UInt16, ["UnzipOdd.Vector128.UInt32"] = UnzipOdd_Vector128_UInt32, ["UnzipOdd.Vector128.UInt64"] = UnzipOdd_Vector128_UInt64, - ["ZipHigh.Vector64.Byte"] = ZipHigh_Vector64_Byte, - ["ZipHigh.Vector64.Int16"] = ZipHigh_Vector64_Int16, - ["ZipHigh.Vector64.Int32"] = ZipHigh_Vector64_Int32, - ["ZipHigh.Vector64.SByte"] = ZipHigh_Vector64_SByte, - ["ZipHigh.Vector64.Single"] = ZipHigh_Vector64_Single, - ["ZipHigh.Vector64.UInt16"] = ZipHigh_Vector64_UInt16, - ["ZipHigh.Vector64.UInt32"] = ZipHigh_Vector64_UInt32, - ["ZipHigh.Vector128.Byte"] = ZipHigh_Vector128_Byte, - ["ZipHigh.Vector128.Double"] = ZipHigh_Vector128_Double, - ["ZipHigh.Vector128.Int16"] = ZipHigh_Vector128_Int16, - ["ZipHigh.Vector128.Int32"] = ZipHigh_Vector128_Int32, - ["ZipHigh.Vector128.Int64"] = ZipHigh_Vector128_Int64, - ["ZipHigh.Vector128.SByte"] = ZipHigh_Vector128_SByte, - ["ZipHigh.Vector128.Single"] = ZipHigh_Vector128_Single, - ["ZipHigh.Vector128.UInt16"] = ZipHigh_Vector128_UInt16, - ["ZipHigh.Vector128.UInt32"] = ZipHigh_Vector128_UInt32, - ["ZipHigh.Vector128.UInt64"] = ZipHigh_Vector128_UInt64, - ["ZipLow.Vector64.Byte"] = ZipLow_Vector64_Byte, - ["ZipLow.Vector64.Int16"] = ZipLow_Vector64_Int16, - ["ZipLow.Vector64.Int32"] = ZipLow_Vector64_Int32, - ["ZipLow.Vector64.SByte"] = ZipLow_Vector64_SByte, - ["ZipLow.Vector64.Single"] = ZipLow_Vector64_Single, - ["ZipLow.Vector64.UInt16"] = ZipLow_Vector64_UInt16, - ["ZipLow.Vector64.UInt32"] = ZipLow_Vector64_UInt32, - ["ZipLow.Vector128.Byte"] = ZipLow_Vector128_Byte, - ["ZipLow.Vector128.Double"] = ZipLow_Vector128_Double, - ["ZipLow.Vector128.Int16"] = ZipLow_Vector128_Int16, - ["ZipLow.Vector128.Int32"] = ZipLow_Vector128_Int32, - ["ZipLow.Vector128.Int64"] = ZipLow_Vector128_Int64, - ["ZipLow.Vector128.SByte"] = ZipLow_Vector128_SByte, - ["ZipLow.Vector128.Single"] = ZipLow_Vector128_Single, - ["ZipLow.Vector128.UInt16"] = ZipLow_Vector128_UInt16, - ["ZipLow.Vector128.UInt32"] = ZipLow_Vector128_UInt32, - ["ZipLow.Vector128.UInt64"] = ZipLow_Vector128_UInt64, }; } } diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64_Part6.cs b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64_Part6.cs new file mode 100644 index 00000000000000..7cf97e14beadc3 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64_Part6.cs @@ -0,0 +1,51 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + static Program() + { + TestList = new Dictionary() { + ["ZipHigh.Vector64.Byte"] = ZipHigh_Vector64_Byte, + ["ZipHigh.Vector64.Int16"] = ZipHigh_Vector64_Int16, + ["ZipHigh.Vector64.Int32"] = ZipHigh_Vector64_Int32, + ["ZipHigh.Vector64.SByte"] = ZipHigh_Vector64_SByte, + ["ZipHigh.Vector64.Single"] = ZipHigh_Vector64_Single, + ["ZipHigh.Vector64.UInt16"] = ZipHigh_Vector64_UInt16, + ["ZipHigh.Vector64.UInt32"] = ZipHigh_Vector64_UInt32, + ["ZipHigh.Vector128.Byte"] = ZipHigh_Vector128_Byte, + ["ZipHigh.Vector128.Double"] = ZipHigh_Vector128_Double, + ["ZipHigh.Vector128.Int16"] = ZipHigh_Vector128_Int16, + ["ZipHigh.Vector128.Int32"] = ZipHigh_Vector128_Int32, + ["ZipHigh.Vector128.Int64"] = ZipHigh_Vector128_Int64, + ["ZipHigh.Vector128.SByte"] = ZipHigh_Vector128_SByte, + ["ZipHigh.Vector128.Single"] = ZipHigh_Vector128_Single, + ["ZipHigh.Vector128.UInt16"] = ZipHigh_Vector128_UInt16, + ["ZipHigh.Vector128.UInt32"] = ZipHigh_Vector128_UInt32, + ["ZipHigh.Vector128.UInt64"] = ZipHigh_Vector128_UInt64, + ["ZipLow.Vector64.Byte"] = ZipLow_Vector64_Byte, + ["ZipLow.Vector64.Int16"] = ZipLow_Vector64_Int16, + ["ZipLow.Vector64.Int32"] = ZipLow_Vector64_Int32, + ["ZipLow.Vector64.SByte"] = ZipLow_Vector64_SByte, + ["ZipLow.Vector64.Single"] = ZipLow_Vector64_Single, + ["ZipLow.Vector64.UInt16"] = ZipLow_Vector64_UInt16, + ["ZipLow.Vector64.UInt32"] = ZipLow_Vector64_UInt32, + ["ZipLow.Vector128.Byte"] = ZipLow_Vector128_Byte, + ["ZipLow.Vector128.Double"] = ZipLow_Vector128_Double, + ["ZipLow.Vector128.Int16"] = ZipLow_Vector128_Int16, + ["ZipLow.Vector128.Int32"] = ZipLow_Vector128_Int32, + ["ZipLow.Vector128.Int64"] = ZipLow_Vector128_Int64, + ["ZipLow.Vector128.SByte"] = ZipLow_Vector128_SByte, + ["ZipLow.Vector128.Single"] = ZipLow_Vector128_Single, + ["ZipLow.Vector128.UInt16"] = ZipLow_Vector128_UInt16, + ["ZipLow.Vector128.UInt32"] = ZipLow_Vector128_UInt32, + ["ZipLow.Vector128.UInt64"] = ZipLow_Vector128_UInt64, + }; + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/GenerateTests.csx b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/GenerateTests.csx index ec6da1aa16e206..6cdf3969ae0ffd 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/GenerateTests.csx +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/GenerateTests.csx @@ -1977,6 +1977,52 @@ private static readonly (string templateFileName, Dictionary tem ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadAndReplicateToVector128_Double", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadAndReplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[i])"}), ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadAndReplicateToVector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadAndReplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "firstOp[0] != result[i]"}), ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadAndReplicateToVector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadAndReplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[0] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairScalarVector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairScalarVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.LoadPairScalar(firstOp, i) != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairScalarVector64_Single", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairScalarVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.LoadPairScalar(firstOp, i)) != BitConverter.SingleToInt32Bits(result[i])"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairScalarVector64_UInt32", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairScalarVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.LoadPairScalar(firstOp, i) != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairScalarVector64NonTemporal_Int32", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairScalarVector64NonTemporal", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.LoadPairScalar(firstOp, i) != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairScalarVector64NonTemporal_Single", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairScalarVector64NonTemporal", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.LoadPairScalar(firstOp, i)) != BitConverter.SingleToInt32Bits(result[i])"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairScalarVector64NonTemporal_UInt32", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairScalarVector64NonTemporal", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.LoadPairScalar(firstOp, i) != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector64_Double", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector64_Int64", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector64_Single", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector64_UInt32", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector64_UInt64", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector64NonTemporal_Byte", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector64NonTemporal", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector64NonTemporal_Double", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector64NonTemporal", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector64NonTemporal_Int16", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector64NonTemporal", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector64NonTemporal_Int32", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector64NonTemporal", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector64NonTemporal_Int64", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector64NonTemporal", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector64NonTemporal_SByte", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector64NonTemporal", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector64NonTemporal_Single", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector64NonTemporal", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector64NonTemporal_UInt16", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector64NonTemporal", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector64NonTemporal_UInt32", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector64NonTemporal", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector64NonTemporal_UInt64", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector64NonTemporal", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector128_Double", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector128_Single", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector128NonTemporal_Byte", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector128NonTemporal", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector128NonTemporal_Double", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector128NonTemporal", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector128NonTemporal_Int16", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector128NonTemporal", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector128NonTemporal_Int32", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector128NonTemporal", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector128NonTemporal_Int64", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector128NonTemporal", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector128NonTemporal_SByte", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector128NonTemporal", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector128NonTemporal_Single", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector128NonTemporal", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector128NonTemporal_UInt16", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector128NonTemporal", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector128NonTemporal_UInt32", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector128NonTemporal", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadPairVectorTest.template", new Dictionary { ["TestName"] = "LoadPairVector128NonTemporal_UInt64", ["Isa"] = "AdvSimd.Arm64", ["Method"] = "LoadPairVector128NonTemporal", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Max(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs index 74e3217313ae50..125c187bdd2d4e 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs @@ -5495,6 +5495,12 @@ public static double ConcatScalar(double[] op1, double[] op2, int i) public static double Insert(double[] op1, int op2, double op3, int i) => (op2 != i) ? op1[i] : op3; + public static int LoadPairScalar(int[] op1, int i) => (i == 0) ? op1[0] : (i == op1.Length / 2) ? op1[1] : (int)0; + + public static uint LoadPairScalar(uint[] op1, int i) => (i == 0) ? op1[0] : (i == op1.Length / 2) ? op1[1] : (uint)0; + + public static float LoadPairScalar(float[] op1, int i) => (i == 0) ? op1[0] : (i == op1.Length / 2) ? op1[1] : (float)0; + public static sbyte TableVectorExtension(int i, sbyte[] defaultValues, sbyte[] indices, params sbyte[][] table) { sbyte[] fullTable = table.SelectMany(x => x).ToArray(); diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.tt b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.tt index b133f53e1480e4..9205115e5b5cec 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.tt +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.tt @@ -1459,6 +1459,14 @@ namespace JIT.HardwareIntrinsics.Arm public static <#= typeName #> Insert(<#= typeName #>[] op1, int op2, <#= typeName #> op3, int i) => (op2 != i) ? op1[i] : op3; +<# + } + + foreach (string typeName in new string[] { "int", "uint", "float" }) + { +#> + public static <#= typeName #> LoadPairScalar(<#= typeName #>[] op1, int i) => (i == 0) ? op1[0] : (i == op1.Length / 2) ? op1[1] : (<#= typeName #>)0; + <# } diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/LoadPairVectorTest.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/LoadPairVectorTest.template new file mode 100644 index 00000000000000..245a16d34cc8a5 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/LoadPairVectorTest.template @@ -0,0 +1,263 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void {TestName}() + { + var test = new {TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + + // Validates loading to a static member works + test.RunClsVarScenario(); + + // Validates loading to the field of a local class works + test.RunClassLclFldScenario(); + + // Validates loading to the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates loading to 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 {TestName} + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + + if ((alignment != 16 && alignment != 32) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public ({RetVectorType}<{RetBaseType}>,{RetVectorType}<{RetBaseType}>) _fld; + + public static TestStruct Create() + { + return new TestStruct(); + } + + public void RunStructFldScenario({TestName} testClass) + { + _fld = {Isa}.{Method}(({Op1BaseType}*)(testClass._dataTable.inArrayPtr)); + + Unsafe.Write(testClass._dataTable.outArrayPtr, _fld); + testClass.ValidateResult(testClass._dataTable.inArrayPtr, testClass._dataTable.outArrayPtr); + } + } + + + private static readonly int LargestVectorSize = {LargestVectorSize}; + private static readonly int RetElementCount = Unsafe.SizeOf<({RetVectorType}<{RetBaseType}>,{RetVectorType}<{RetBaseType}>)>() / sizeof({RetBaseType}); + private static readonly int Op1ElementCount = RetElementCount; + + private static {Op1BaseType}[] _data = new {Op1BaseType}[Op1ElementCount]; + + private static ({RetVectorType}<{RetBaseType}>,{RetVectorType}<{RetBaseType}>) _clsVar; + + private ({RetVectorType}<{RetBaseType}>,{RetVectorType}<{RetBaseType}>) _fld; + + private DataTable _dataTable; + + public {TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = {NextValueOp1}; } + _dataTable = new DataTable(_data, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = {Isa}.{Method}(({Op1BaseType}*)(_dataTable.inArrayPtr)); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1BaseType}*) }) + .Invoke(null, new object[] { + Pointer.Box(_dataTable.inArrayPtr, typeof({Op1BaseType}*)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (({RetVectorType}<{RetBaseType}>,{RetVectorType}<{RetBaseType}>))result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + _clsVar = {Isa}.{Method}(({Op1BaseType}*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, _clsVar); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new {TestName}(); + test._fld = {Isa}.{Method}(({Op1BaseType}*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + test._fld = {Isa}.{Method}(({Op1BaseType}*)(_dataTable.inArrayPtr)); + + Unsafe.Write(_dataTable.outArrayPtr, test._fld); + ValidateResult(_dataTable.inArrayPtr, _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)); + + Succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)(Unsafe.SizeOf<{Op1BaseType}>() * Op1ElementCount)); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)(Unsafe.SizeOf<{RetBaseType}>() * RetElementCount)); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] firstOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < Op1ElementCount; i++) + { + if ({ValidateIterResult}) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +}